15 #include "../fem/fem.hpp"
16 #include "../general/sort_pairs.hpp"
17 #include "../general/text.hpp"
38 int geom = GetElementBaseGeometry(i);
44 double Mesh::GetElementSize(
int i,
int type)
47 GetElementJacobian(i, J);
50 return pow(fabs(J.
Det()), 1./Dim);
62 double Mesh::GetElementSize(
int i,
const Vector &dir)
66 GetElementJacobian(i, J);
68 return sqrt((d_hat * d_hat) / (dir * dir));
71 double Mesh::GetElementVolume(
int i)
93 for (
int d = 0; d < Dim; d++)
95 min[d] = numeric_limits<double>::infinity();
96 max[d] = -numeric_limits<double>::infinity();
102 for (
int i = 0; i < NumOfVertices; i++)
104 coord = GetVertex(i);
105 for (
int d = 0; d < Dim; d++)
107 if (coord[d] < min[d]) { min[d] = coord[d]; }
108 if (coord[d] > max[d]) { max[d] = coord[d]; }
114 int ne = (Dim == 3) ? GetNBE() : GetNE();
122 for (
int i = 0; i < ne; i++)
126 GetBdrElementFace(i, &fn, &fo);
128 Tr = GetFaceElementTransformations(fn, 5);
135 T = GetElementTransformation(i);
139 for (
int j = 0; j < pointmat.
Width(); j++)
141 for (
int d = 0; d < Dim; d++)
143 if (pointmat(d,j) < min[d]) { min[d] = pointmat(d,j); }
144 if (pointmat(d,j) > max[d]) { max[d] = pointmat(d,j); }
151 void Mesh::PrintCharacteristics(
Vector *Vh,
Vector *Vk, std::ostream &out)
155 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
157 out <<
"Mesh Characteristics:";
160 sdim = SpaceDimension();
163 if (Vh) { Vh->
SetSize(NumOfElements); }
164 if (Vk) { Vk->
SetSize(NumOfElements); }
166 h_min = kappa_min = numeric_limits<double>::infinity();
167 h_max = kappa_max = -h_min;
168 for (i = 0; i < NumOfElements; i++)
170 GetElementJacobian(i, J);
171 h = pow(fabs(J.
Weight()), 1.0/
double(dim));
172 kappa = (dim == sdim) ?
174 if (Vh) { (*Vh)(i) = h; }
175 if (Vk) { (*Vk)(i) = kappa; }
177 if (h < h_min) { h_min = h; }
178 if (h > h_max) { h_max = h; }
179 if (kappa < kappa_min) { kappa_min =
kappa; }
180 if (kappa > kappa_max) { kappa_max =
kappa; }
186 <<
"Number of vertices : " << GetNV() <<
'\n'
187 <<
"Number of elements : " << GetNE() <<
'\n'
188 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
189 <<
"h_min : " << h_min <<
'\n'
190 <<
"h_max : " << h_max <<
'\n';
195 <<
"Number of vertices : " << GetNV() <<
'\n'
196 <<
"Number of edges : " << GetNEdges() <<
'\n'
197 <<
"Number of elements : " << GetNE() <<
'\n'
198 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
199 <<
"Euler Number : " << EulerNumber2D() <<
'\n'
200 <<
"h_min : " << h_min <<
'\n'
201 <<
"h_max : " << h_max <<
'\n'
202 <<
"kappa_min : " << kappa_min <<
'\n'
203 <<
"kappa_max : " << kappa_max <<
'\n';
208 <<
"Number of vertices : " << GetNV() <<
'\n'
209 <<
"Number of edges : " << GetNEdges() <<
'\n'
210 <<
"Number of faces : " << GetNFaces() <<
'\n'
211 <<
"Number of elements : " << GetNE() <<
'\n'
212 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
213 <<
"Euler Number : " << EulerNumber() <<
'\n'
214 <<
"h_min : " << h_min <<
'\n'
215 <<
"h_max : " << h_max <<
'\n'
216 <<
"kappa_min : " << kappa_min <<
'\n'
217 <<
"kappa_max : " << kappa_max <<
'\n';
219 out <<
'\n' << std::flush;
226 case Element::POINT :
return &
PointFE;
227 case Element::SEGMENT :
return &
SegmentFE;
233 MFEM_ABORT(
"Unknown element type");
245 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
251 Nodes->FESpace()->GetElementVDofs(i, vdofs);
253 int n = vdofs.
Size()/spaceDim;
255 for (
int k = 0; k < spaceDim; k++)
257 for (
int j = 0; j < n; j++)
259 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
262 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
266 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
274 int nv = elements[i]->GetNVertices();
275 const int *v = elements[i]->GetVertices();
276 int n = vertices.
Size();
278 for (
int k = 0; k < spaceDim; k++)
280 for (
int j = 0; j < nv; j++)
282 pm(k, j) = nodes(k*n+v[j]);
285 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
290 Nodes->FESpace()->GetElementVDofs(i, vdofs);
291 int n = vdofs.
Size()/spaceDim;
293 for (
int k = 0; k < spaceDim; k++)
295 for (
int j = 0; j < n; j++)
297 pm(k,j) = nodes(vdofs[n*k+j]);
300 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
306 GetElementTransformation(i, &Transformation);
308 return &Transformation;
313 GetBdrElementTransformation(i, &FaceTransformation);
314 return &FaceTransformation;
325 GetTransformationFEforElementType(GetBdrElementType(i)));
331 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
332 int n = vdofs.
Size()/spaceDim;
334 for (
int k = 0; k < spaceDim; k++)
336 for (
int j = 0; j < n; j++)
338 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
341 ElTr->
SetFE(Nodes->FESpace()->GetBE(i));
347 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
352 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
353 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
355 for (
int i = 0; i < spaceDim; i++)
357 for (
int j = 0; j < nv; j++)
359 pm(i, j) = vertices[v[j]](i);
362 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
366 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
370 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
371 int n = vdofs.
Size()/spaceDim;
373 for (
int i = 0; i < spaceDim; i++)
375 for (
int j = 0; j < n; j++)
377 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
384 FaceInfo &face_info = faces_info[FaceNo];
386 int face_geom = GetFaceGeometryType(FaceNo);
387 int face_type = GetFaceElementType(FaceNo);
389 GetLocalFaceTransformation(face_type,
390 GetElementType(face_info.
Elem1No),
391 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
394 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
398 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
400 Nodes->GetVectorValues(Transformation, eir, pm);
409 GetFaceTransformation(FaceNo, &FaceTransformation);
410 return &FaceTransformation;
417 GetFaceTransformation(EdgeNo, EdTr);
422 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
431 GetEdgeVertices(EdgeNo, v);
434 for (
int i = 0; i < spaceDim; i++)
436 for (
int j = 0; j < nv; j++)
438 pm(i, j) = vertices[v[j]](i);
441 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
445 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
449 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
450 int n = vdofs.
Size()/spaceDim;
452 for (
int i = 0; i < spaceDim; i++)
454 for (
int j = 0; j < n; j++)
456 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
459 EdTr->
SetFE(edge_el);
463 MFEM_ABORT(
"Not implemented.");
470 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
471 return &EdgeTransformation;
475 void Mesh::GetLocalPtToSegTransformation(
489 void Mesh::GetLocalSegToTriTransformation(
497 tv = tri_t::Edges[i/64];
498 so = seg_t::Orient[i%64];
501 for (
int j = 0; j < 2; j++)
503 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
504 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
508 void Mesh::GetLocalSegToQuadTransformation(
516 qv = quad_t::Edges[i/64];
517 so = seg_t::Orient[i%64];
520 for (
int j = 0; j < 2; j++)
522 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
523 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
527 void Mesh::GetLocalTriToTetTransformation(
534 const int *tv = tet_t::FaceVert[i/64];
537 const int *to = tri_t::Orient[i%64];
541 for (
int j = 0; j < 3; j++)
544 locpm(0, j) = vert.
x;
545 locpm(1, j) = vert.
y;
546 locpm(2, j) = vert.
z;
550 void Mesh::GetLocalQuadToHexTransformation(
557 const int *hv = hex_t::FaceVert[i/64];
559 const int *qo = quad_t::Orient[i%64];
562 for (
int j = 0; j < 4; j++)
565 locpm(0, j) = vert.
x;
566 locpm(1, j) = vert.
y;
567 locpm(2, j) = vert.
z;
571 void Mesh::GetLocalFaceTransformation(
577 GetLocalPtToSegTransformation(Transf, inf);
580 case Element::SEGMENT:
581 if (elem_type == Element::TRIANGLE)
583 GetLocalSegToTriTransformation(Transf, inf);
587 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
588 GetLocalSegToQuadTransformation(Transf, inf);
592 case Element::TRIANGLE:
593 MFEM_ASSERT(elem_type == Element::TETRAHEDRON,
"");
594 GetLocalTriToTetTransformation(Transf, inf);
597 case Element::QUADRILATERAL:
598 MFEM_ASSERT(elem_type == Element::HEXAHEDRON,
"");
599 GetLocalQuadToHexTransformation(Transf, inf);
607 FaceInfo &face_info = faces_info[FaceNo];
609 FaceElemTr.Elem1 = NULL;
610 FaceElemTr.Elem2 = NULL;
616 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
617 FaceElemTr.Elem1 = &Transformation;
623 FaceElemTr.Elem2No = face_info.
Elem2No;
624 if ((mask & 2) && FaceElemTr.Elem2No >= 0)
627 if (NURBSext && (mask & 1)) { MFEM_ABORT(
"NURBS mesh not supported!"); }
629 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
630 FaceElemTr.Elem2 = &Transformation2;
634 FaceElemTr.FaceGeom = GetFaceGeometryType(FaceNo);
635 FaceElemTr.Face = (mask & 16) ? GetFaceTransformation(FaceNo) : NULL;
638 int face_type = GetFaceElementType(FaceNo);
641 int elem_type = GetElementType(face_info.
Elem1No);
642 GetLocalFaceTransformation(face_type, elem_type,
643 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
645 if ((mask & 8) && FaceElemTr.Elem2No >= 0)
647 int elem_type = GetElementType(face_info.
Elem2No);
648 GetLocalFaceTransformation(face_type, elem_type,
649 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
652 if (Nonconforming() && IsSlaveFace(face_info))
654 ApplyLocalSlaveTransformation(FaceElemTr.Loc2.Transf, face_info);
656 if (face_type == Element::SEGMENT)
659 DenseMatrix &pm = FaceElemTr.Loc2.Transf.GetPointMat();
660 std::swap(pm(0,0), pm(0,1));
661 std::swap(pm(1,0), pm(1,1));
671 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
677 #ifdef MFEM_THREAD_SAFE
682 MFEM_ASSERT(fi.
NCFace >= 0,
"");
693 fn = be_to_face[BdrElemNo];
697 fn = be_to_edge[BdrElemNo];
701 fn = boundary[BdrElemNo]->GetVertices()[0];
704 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
708 tr = GetFaceElementTransformations(fn);
713 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
715 *Elem1 = faces_info[Face].
Elem1No;
716 *Elem2 = faces_info[Face].Elem2No;
719 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
721 *Inf1 = faces_info[Face].Elem1Inf;
722 *Inf2 = faces_info[Face].Elem2Inf;
725 int Mesh::GetFaceGeometryType(
int Face)
const
727 return (Dim == 1) ? Geometry::POINT : faces[Face]->GetGeometryType();
730 int Mesh::GetFaceElementType(
int Face)
const
732 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
740 NumOfElements = NumOfBdrElements = 0;
741 NumOfEdges = NumOfFaces = 0;
742 BaseGeom = BaseBdrGeom = -2;
749 last_operation = Mesh::NONE;
752 void Mesh::InitTables()
755 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
758 void Mesh::SetEmpty()
762 BaseGeom = BaseBdrGeom = -1;
770 void Mesh::DestroyTables()
785 void Mesh::DestroyPointers()
787 if (own_nodes) {
delete Nodes; }
793 for (
int i = 0; i < NumOfElements; i++)
795 FreeElement(elements[i]);
798 for (
int i = 0; i < NumOfBdrElements; i++)
800 FreeElement(boundary[i]);
803 for (
int i = 0; i < faces.Size(); i++)
805 FreeElement(faces[i]);
815 elements.DeleteAll();
816 vertices.DeleteAll();
817 boundary.DeleteAll();
819 faces_info.DeleteAll();
820 nc_faces_info.DeleteAll();
821 be_to_edge.DeleteAll();
822 be_to_face.DeleteAll();
829 CoarseFineTr.Clear();
831 #ifdef MFEM_USE_MEMALLOC
835 attributes.DeleteAll();
836 bdr_attributes.DeleteAll();
839 void Mesh::SetAttributes()
844 for (
int i = 0; i < attribs.
Size(); i++)
846 attribs[i] = GetBdrAttribute(i);
850 attribs.
Copy(bdr_attributes);
851 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
853 MFEM_WARNING(
"Non-positive attributes on the boundary!");
857 for (
int i = 0; i < attribs.
Size(); i++)
859 attribs[i] = GetAttribute(i);
863 attribs.
Copy(attributes);
864 if (attributes.Size() > 0 && attributes[0] <= 0)
866 MFEM_WARNING(
"Non-positive attributes in the domain!");
870 void Mesh::InitMesh(
int _Dim,
int _spaceDim,
int NVert,
int NElem,
int NBdrElem)
875 spaceDim = _spaceDim;
878 vertices.SetSize(NVert);
881 elements.SetSize(NElem);
883 NumOfBdrElements = 0;
884 boundary.SetSize(NBdrElem);
887 void Mesh::InitBaseGeom()
889 BaseGeom = BaseBdrGeom = -1;
890 for (
int i = 0; i < NumOfElements; i++)
892 int geom = elements[i]->GetGeometryType();
893 if (geom != BaseGeom && BaseGeom >= 0)
895 BaseGeom = -1;
break;
899 for (
int i = 0; i < NumOfBdrElements; i++)
901 int geom = boundary[i]->GetGeometryType();
902 if (geom != BaseBdrGeom && BaseBdrGeom >= 0)
904 BaseBdrGeom = -1;
break;
910 void Mesh::AddVertex(
const double *x)
912 double *y = vertices[NumOfVertices]();
914 for (
int i = 0; i < spaceDim; i++)
921 void Mesh::AddTri(
const int *vi,
int attr)
923 elements[NumOfElements++] =
new Triangle(vi, attr);
926 void Mesh::AddTriangle(
const int *vi,
int attr)
928 elements[NumOfElements++] =
new Triangle(vi, attr);
931 void Mesh::AddQuad(
const int *vi,
int attr)
936 void Mesh::AddTet(
const int *vi,
int attr)
938 #ifdef MFEM_USE_MEMALLOC
940 tet = TetMemory.Alloc();
943 elements[NumOfElements++] = tet;
945 elements[NumOfElements++] =
new Tetrahedron(vi, attr);
949 void Mesh::AddHex(
const int *vi,
int attr)
951 elements[NumOfElements++] =
new Hexahedron(vi, attr);
954 void Mesh::AddHexAsTets(
const int *vi,
int attr)
956 static const int hex_to_tet[6][4] =
958 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
959 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
963 for (
int i = 0; i < 6; i++)
965 for (
int j = 0; j < 4; j++)
967 ti[j] = vi[hex_to_tet[i][j]];
973 void Mesh::AddBdrSegment(
const int *vi,
int attr)
975 boundary[NumOfBdrElements++] =
new Segment(vi, attr);
978 void Mesh::AddBdrTriangle(
const int *vi,
int attr)
980 boundary[NumOfBdrElements++] =
new Triangle(vi, attr);
983 void Mesh::AddBdrQuad(
const int *vi,
int attr)
988 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
990 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
993 for (
int i = 0; i < 2; i++)
995 for (
int j = 0; j < 3; j++)
997 ti[j] = vi[quad_to_tri[i][j]];
999 AddBdrTriangle(ti, attr);
1003 void Mesh::GenerateBoundaryElements()
1006 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1010 for (i = 0; i < boundary.Size(); i++)
1012 FreeElement(boundary[i]);
1022 NumOfBdrElements = 0;
1023 for (i = 0; i < faces_info.Size(); i++)
1025 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1028 boundary.SetSize(NumOfBdrElements);
1029 be2face.
SetSize(NumOfBdrElements);
1030 for (j = i = 0; i < faces_info.Size(); i++)
1032 if (faces_info[i].Elem2No < 0)
1034 boundary[j] = faces[i]->Duplicate(
this);
1041 void Mesh::FinalizeCheck()
1043 MFEM_VERIFY(vertices.Size() == NumOfVertices,
1044 "incorrect number of vertices: preallocated: " << vertices.Size()
1045 <<
", actually added: " << NumOfVertices);
1046 MFEM_VERIFY(elements.Size() == NumOfElements,
1047 "incorrect number of elements: preallocated: " << elements.Size()
1048 <<
", actually added: " << NumOfElements);
1049 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1050 "incorrect number of boundary elements: preallocated: "
1051 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1054 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1057 CheckElementOrientation(fix_orientation);
1061 MarkTriMeshForRefinement();
1066 el_to_edge =
new Table;
1067 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1069 CheckBdrElementOrientation();
1080 BaseGeom = Geometry::TRIANGLE;
1081 BaseBdrGeom = Geometry::SEGMENT;
1086 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1087 bool fix_orientation)
1090 if (fix_orientation)
1092 CheckElementOrientation(fix_orientation);
1097 el_to_edge =
new Table;
1098 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1100 CheckBdrElementOrientation();
1111 BaseGeom = Geometry::SQUARE;
1112 BaseBdrGeom = Geometry::SEGMENT;
1118 #ifdef MFEM_USE_GECKO
1124 Gecko::Functional *functional =
1125 new Gecko::FunctionalGeometric();
1126 unsigned int iterations = 1;
1127 unsigned int window = 2;
1128 unsigned int period = 1;
1129 unsigned int seed = 0;
1132 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1139 const Table &my_el_to_el = ElementToElementTable();
1140 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1142 const int *neighid = my_el_to_el.
GetRow(elemid);
1143 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
1145 graph.insert(elemid + 1, neighid[i] + 1);
1150 graph.order(functional, iterations, window, period, seed);
1153 Gecko::Node::Index NE = GetNE();
1154 for (Gecko::Node::Index gnodeid = 1; gnodeid <= NE; ++gnodeid)
1156 ordering[gnodeid - 1] = graph.rank(gnodeid);
1164 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
1168 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
1173 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
1177 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
1206 old_elem_node_vals.SetSize(GetNE());
1207 nodes_fes = Nodes->FESpace();
1210 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1212 nodes_fes->GetElementVDofs(old_elid, old_dofs);
1214 old_elem_node_vals[old_elid] =
new Vector(vals);
1220 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
1222 int new_elid = ordering[old_elid];
1223 new_elements[new_elid] = elements[old_elid];
1228 if (reorder_vertices)
1233 vertex_ordering = -1;
1235 int new_vertex_ind = 0;
1236 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1238 int *elem_vert = elements[new_elid]->GetVertices();
1239 int nv = elements[new_elid]->GetNVertices();
1240 for (
int vi = 0; vi < nv; ++vi)
1242 int old_vertex_ind = elem_vert[vi];
1243 if (vertex_ordering[old_vertex_ind] == -1)
1245 vertex_ordering[old_vertex_ind] = new_vertex_ind;
1246 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
1256 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1258 int *elem_vert = elements[new_elid]->GetVertices();
1259 int nv = elements[new_elid]->GetNVertices();
1260 for (
int vi = 0; vi < nv; ++vi)
1262 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
1267 for (
int belid = 0; belid < GetNBE(); ++belid)
1269 int *be_vert = boundary[belid]->GetVertices();
1270 int nv = boundary[belid]->GetNVertices();
1271 for (
int vi = 0; vi < nv; ++vi)
1273 be_vert[vi] = vertex_ordering[be_vert[vi]];
1284 el_to_edge =
new Table;
1285 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1290 GetElementToFaceTable();
1298 nodes_fes->Update();
1300 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1302 int new_elid = ordering[old_elid];
1303 nodes_fes->GetElementVDofs(new_elid, new_dofs);
1304 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
1305 delete old_elem_node_vals[old_elid];
1311 void Mesh::MarkForRefinement()
1317 MarkTriMeshForRefinement();
1321 DSTable v_to_v(NumOfVertices);
1322 GetVertexToVertexTable(v_to_v);
1323 MarkTetMeshForRefinement(v_to_v);
1328 void Mesh::MarkTriMeshForRefinement()
1333 for (
int i = 0; i < NumOfElements; i++)
1335 if (elements[i]->GetType() == Element::TRIANGLE)
1337 GetPointMatrix(i, pmat);
1338 elements[i]->MarkEdge(pmat);
1349 for (
int i = 0; i < NumOfVertices; i++)
1354 length_idx[j].one = GetLength(i, it.Column());
1355 length_idx[j].two = j;
1362 for (
int i = 0; i < NumOfEdges; i++)
1364 order[length_idx[i].two] = i;
1368 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
1373 GetEdgeOrdering(v_to_v, order);
1375 for (
int i = 0; i < NumOfElements; i++)
1377 if (elements[i]->GetType() == Element::TETRAHEDRON)
1379 elements[i]->MarkEdge(v_to_v, order);
1382 for (
int i = 0; i < NumOfBdrElements; i++)
1384 if (boundary[i]->GetType() == Element::TRIANGLE)
1386 boundary[i]->MarkEdge(v_to_v, order);
1393 if (*old_v_to_v && *old_elem_vert)
1401 if (*old_v_to_v == NULL)
1404 if (num_edge_dofs > 0)
1406 *old_v_to_v =
new DSTable(NumOfVertices);
1407 GetVertexToVertexTable(*(*old_v_to_v));
1410 if (*old_elem_vert == NULL)
1413 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1414 if (num_elem_dofs > 1)
1416 *old_elem_vert =
new Table;
1417 (*old_elem_vert)->
MakeI(GetNE());
1418 for (
int i = 0; i < GetNE(); i++)
1420 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
1422 (*old_elem_vert)->MakeJ();
1423 for (
int i = 0; i < GetNE(); i++)
1425 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
1426 elements[i]->GetNVertices());
1428 (*old_elem_vert)->ShiftUpI();
1442 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1458 if (num_edge_dofs > 0)
1460 DSTable new_v_to_v(NumOfVertices);
1461 GetVertexToVertexTable(new_v_to_v);
1463 for (
int i = 0; i < NumOfVertices; i++)
1467 int old_i = (*old_v_to_v)(i, it.Column());
1468 int new_i = it.Index();
1475 old_dofs.
SetSize(num_edge_dofs);
1476 new_dofs.
SetSize(num_edge_dofs);
1477 for (
int j = 0; j < num_edge_dofs; j++)
1479 old_dofs[j] = offset + old_i * num_edge_dofs + j;
1480 new_dofs[j] = offset + new_i * num_edge_dofs + j;
1484 for (
int j = 0; j < old_dofs.
Size(); j++)
1486 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1490 offset += NumOfEdges * num_edge_dofs;
1493 cout <<
"Mesh::DoNodeReorder : redges = " << redges << endl;
1498 if (num_face_dofs > 0)
1501 Table old_face_vertex;
1502 old_face_vertex.
MakeI(NumOfFaces);
1503 for (
int i = 0; i < NumOfFaces; i++)
1507 old_face_vertex.
MakeJ();
1508 for (
int i = 0; i < NumOfFaces; i++)
1510 faces[i]->GetNVertices());
1514 STable3D *faces_tbl = GetElementToFaceTable(1);
1518 for (
int i = 0; i < NumOfFaces; i++)
1520 int *old_v = old_face_vertex.
GetRow(i), *new_v;
1521 int new_i, new_or, *dof_ord;
1522 switch (old_face_vertex.
RowSize(i))
1525 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
1526 new_v = faces[new_i]->GetVertices();
1527 new_or = GetTriOrientation(old_v, new_v);
1532 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
1533 new_v = faces[new_i]->GetVertices();
1534 new_or = GetQuadOrientation(old_v, new_v);
1539 old_dofs.
SetSize(num_face_dofs);
1540 new_dofs.
SetSize(num_face_dofs);
1541 for (
int j = 0; j < num_face_dofs; j++)
1543 old_dofs[j] = offset + i * num_face_dofs + j;
1544 new_dofs[j] = offset + new_i * num_face_dofs + dof_ord[j];
1550 for (
int j = 0; j < old_dofs.
Size(); j++)
1552 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1556 offset += NumOfFaces * num_face_dofs;
1562 if (num_elem_dofs > 1)
1574 for (
int i = 0; i < GetNE(); i++)
1576 int *old_v = old_elem_vert->
GetRow(i);
1577 int *new_v = elements[i]->GetVertices();
1578 int new_or, *dof_ord;
1579 int geom = elements[i]->GetGeometryType();
1582 case Geometry::SEGMENT:
1583 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
1585 case Geometry::TRIANGLE:
1586 new_or = GetTriOrientation(old_v, new_v);
1588 case Geometry::SQUARE:
1589 new_or = GetQuadOrientation(old_v, new_v);
1593 cerr <<
"Mesh::DoNodeReorder : " << Geometry::Name[
geom]
1594 <<
" elements (" << fec->
Name()
1595 <<
" FE collection) are not supported yet!" << endl;
1600 if (dof_ord == NULL)
1602 cerr <<
"Mesh::DoNodeReorder : FE collection '" << fec->
Name()
1603 <<
"' does not define reordering for " << Geometry::Name[
geom]
1604 <<
" elements!" << endl;
1607 old_dofs.
SetSize(num_elem_dofs);
1608 new_dofs.
SetSize(num_elem_dofs);
1609 for (
int j = 0; j < num_elem_dofs; j++)
1612 old_dofs[j] = offset + dof_ord[j];
1613 new_dofs[j] = offset + j;
1617 for (
int j = 0; j < old_dofs.
Size(); j++)
1619 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1622 offset += num_elem_dofs;
1629 if (num_face_dofs == 0)
1633 GetElementToFaceTable();
1636 CheckBdrElementOrientation();
1641 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1646 CheckBdrElementOrientation();
1649 Nodes->FESpace()->RebuildElementToDofTable();
1652 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
1655 CheckElementOrientation(fix_orientation);
1657 if (NumOfBdrElements == 0)
1659 GetElementToFaceTable();
1661 GenerateBoundaryElements();
1666 DSTable v_to_v(NumOfVertices);
1667 GetVertexToVertexTable(v_to_v);
1668 MarkTetMeshForRefinement(v_to_v);
1671 GetElementToFaceTable();
1674 CheckBdrElementOrientation();
1676 if (generate_edges == 1)
1678 el_to_edge =
new Table;
1679 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1690 BaseGeom = Geometry::TETRAHEDRON;
1691 BaseBdrGeom = Geometry::TRIANGLE;
1696 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
1699 CheckElementOrientation(fix_orientation);
1701 GetElementToFaceTable();
1704 if (NumOfBdrElements == 0)
1706 GenerateBoundaryElements();
1709 CheckBdrElementOrientation();
1713 el_to_edge =
new Table;
1714 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1723 BaseGeom = Geometry::CUBE;
1724 BaseBdrGeom = Geometry::SQUARE;
1729 void Mesh::FinalizeTopology()
1741 bool generate_edges =
true;
1743 if (spaceDim == 0) { spaceDim = Dim; }
1744 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
1751 if (NumOfBdrElements == 0 && Dim > 2)
1754 GetElementToFaceTable();
1756 GenerateBoundaryElements();
1766 GetElementToFaceTable();
1775 if (Dim > 1 && generate_edges)
1778 if (!el_to_edge) { el_to_edge =
new Table; }
1779 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1783 if (NumOfBdrElements == 0)
1785 GenerateBoundaryElements();
1797 ncmesh->OnMeshUpdated(
this);
1800 GenerateNCFaceInfo();
1807 void Mesh::Finalize(
bool refine,
bool fix_orientation)
1809 if (NURBSext || ncmesh)
1811 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
1812 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
1821 const bool check_orientation =
true;
1822 const bool curved = (Nodes != NULL);
1823 const bool may_change_topology =
1824 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
1825 ( check_orientation && fix_orientation &&
1826 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
1829 Table *old_elem_vert = NULL;
1831 if (curved && may_change_topology)
1833 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
1836 if (check_orientation)
1839 CheckElementOrientation(fix_orientation);
1843 MarkForRefinement();
1846 if (may_change_topology)
1850 DoNodeReorder(old_v_to_v, old_elem_vert);
1851 delete old_elem_vert;
1864 CheckBdrElementOrientation();
1868 int generate_edges,
double sx,
double sy,
double sz)
1872 int NVert, NElem, NBdrElem;
1874 NVert = (nx+1) * (ny+1) * (nz+1);
1875 NElem = nx * ny * nz;
1876 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
1877 if (type == Element::TETRAHEDRON)
1883 InitMesh(3, 3, NVert, NElem, NBdrElem);
1889 for (z = 0; z <= nz; z++)
1891 coord[2] = ((double) z / nz) * sz;
1892 for (y = 0; y <= ny; y++)
1894 coord[1] = ((double) y / ny) * sy;
1895 for (x = 0; x <= nx; x++)
1897 coord[0] = ((double) x / nx) * sx;
1903 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
1906 for (z = 0; z < nz; z++)
1908 for (y = 0; y < ny; y++)
1910 for (x = 0; x < nx; x++)
1912 ind[0] = VTX(x , y , z );
1913 ind[1] = VTX(x+1, y , z );
1914 ind[2] = VTX(x+1, y+1, z );
1915 ind[3] = VTX(x , y+1, z );
1916 ind[4] = VTX(x , y , z+1);
1917 ind[5] = VTX(x+1, y , z+1);
1918 ind[6] = VTX(x+1, y+1, z+1);
1919 ind[7] = VTX(x , y+1, z+1);
1920 if (type == Element::TETRAHEDRON)
1922 AddHexAsTets(ind, 1);
1934 for (y = 0; y < ny; y++)
1935 for (x = 0; x < nx; x++)
1937 ind[0] = VTX(x , y , 0);
1938 ind[1] = VTX(x , y+1, 0);
1939 ind[2] = VTX(x+1, y+1, 0);
1940 ind[3] = VTX(x+1, y , 0);
1941 if (type == Element::TETRAHEDRON)
1943 AddBdrQuadAsTriangles(ind, 1);
1951 for (y = 0; y < ny; y++)
1952 for (x = 0; x < nx; x++)
1954 ind[0] = VTX(x , y , nz);
1955 ind[1] = VTX(x+1, y , nz);
1956 ind[2] = VTX(x+1, y+1, nz);
1957 ind[3] = VTX(x , y+1, nz);
1958 if (type == Element::TETRAHEDRON)
1960 AddBdrQuadAsTriangles(ind, 6);
1968 for (z = 0; z < nz; z++)
1969 for (y = 0; y < ny; y++)
1971 ind[0] = VTX(0 , y , z );
1972 ind[1] = VTX(0 , y , z+1);
1973 ind[2] = VTX(0 , y+1, z+1);
1974 ind[3] = VTX(0 , y+1, z );
1975 if (type == Element::TETRAHEDRON)
1977 AddBdrQuadAsTriangles(ind, 5);
1985 for (z = 0; z < nz; z++)
1986 for (y = 0; y < ny; y++)
1988 ind[0] = VTX(nx, y , z );
1989 ind[1] = VTX(nx, y+1, z );
1990 ind[2] = VTX(nx, y+1, z+1);
1991 ind[3] = VTX(nx, y , z+1);
1992 if (type == Element::TETRAHEDRON)
1994 AddBdrQuadAsTriangles(ind, 3);
2002 for (x = 0; x < nx; x++)
2003 for (z = 0; z < nz; z++)
2005 ind[0] = VTX(x , 0, z );
2006 ind[1] = VTX(x+1, 0, z );
2007 ind[2] = VTX(x+1, 0, z+1);
2008 ind[3] = VTX(x , 0, z+1);
2009 if (type == Element::TETRAHEDRON)
2011 AddBdrQuadAsTriangles(ind, 2);
2019 for (x = 0; x < nx; x++)
2020 for (z = 0; z < nz; z++)
2022 ind[0] = VTX(x , ny, z );
2023 ind[1] = VTX(x , ny, z+1);
2024 ind[2] = VTX(x+1, ny, z+1);
2025 ind[3] = VTX(x+1, ny, z );
2026 if (type == Element::TETRAHEDRON)
2028 AddBdrQuadAsTriangles(ind, 4);
2037 ofstream test_stream(
"debug.mesh");
2039 test_stream.close();
2043 bool fix_orientation =
true;
2045 if (type == Element::TETRAHEDRON)
2047 FinalizeTetMesh(generate_edges, refine, fix_orientation);
2051 FinalizeHexMesh(generate_edges, refine, fix_orientation);
2056 double sx,
double sy)
2065 if (type == Element::QUADRILATERAL)
2068 NumOfVertices = (nx+1) * (ny+1);
2069 NumOfElements = nx * ny;
2070 NumOfBdrElements = 2 * nx + 2 * ny;
2071 BaseGeom = Geometry::SQUARE;
2072 BaseBdrGeom = Geometry::SEGMENT;
2074 vertices.SetSize(NumOfVertices);
2075 elements.SetSize(NumOfElements);
2076 boundary.SetSize(NumOfBdrElements);
2083 for (j = 0; j < ny+1; j++)
2085 cy = ((double) j / ny) * sy;
2086 for (i = 0; i < nx+1; i++)
2088 cx = ((double) i / nx) * sx;
2089 vertices[k](0) = cx;
2090 vertices[k](1) = cy;
2097 for (j = 0; j < ny; j++)
2099 for (i = 0; i < nx; i++)
2101 ind[0] = i + j*(nx+1);
2102 ind[1] = i + 1 +j*(nx+1);
2103 ind[2] = i + 1 + (j+1)*(nx+1);
2104 ind[3] = i + (j+1)*(nx+1);
2112 for (i = 0; i < nx; i++)
2114 boundary[i] =
new Segment(i, i+1, 1);
2115 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2118 for (j = 0; j < ny; j++)
2120 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2121 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2125 else if (type == Element::TRIANGLE)
2128 NumOfVertices = (nx+1) * (ny+1);
2129 NumOfElements = 2 * nx * ny;
2130 NumOfBdrElements = 2 * nx + 2 * ny;
2131 BaseGeom = Geometry::TRIANGLE;
2132 BaseBdrGeom = Geometry::SEGMENT;
2134 vertices.SetSize(NumOfVertices);
2135 elements.SetSize(NumOfElements);
2136 boundary.SetSize(NumOfBdrElements);
2143 for (j = 0; j < ny+1; j++)
2145 cy = ((double) j / ny) * sy;
2146 for (i = 0; i < nx+1; i++)
2148 cx = ((double) i / nx) * sx;
2149 vertices[k](0) = cx;
2150 vertices[k](1) = cy;
2157 for (j = 0; j < ny; j++)
2159 for (i = 0; i < nx; i++)
2161 ind[0] = i + j*(nx+1);
2162 ind[1] = i + 1 + (j+1)*(nx+1);
2163 ind[2] = i + (j+1)*(nx+1);
2166 ind[1] = i + 1 + j*(nx+1);
2167 ind[2] = i + 1 + (j+1)*(nx+1);
2175 for (i = 0; i < nx; i++)
2177 boundary[i] =
new Segment(i, i+1, 1);
2178 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2181 for (j = 0; j < ny; j++)
2183 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2184 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2187 MarkTriMeshForRefinement();
2191 MFEM_ABORT(
"Unsupported element type.");
2194 CheckElementOrientation();
2196 if (generate_edges == 1)
2198 el_to_edge =
new Table;
2199 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2201 CheckBdrElementOrientation();
2210 attributes.Append(1);
2211 bdr_attributes.Append(1); bdr_attributes.Append(2);
2212 bdr_attributes.Append(3); bdr_attributes.Append(4);
2215 void Mesh::Make1D(
int n,
double sx)
2224 BaseGeom = Geometry::SEGMENT;
2225 BaseBdrGeom = Geometry::POINT;
2229 NumOfVertices = n + 1;
2231 NumOfBdrElements = 2;
2232 vertices.SetSize(NumOfVertices);
2233 elements.SetSize(NumOfElements);
2234 boundary.SetSize(NumOfBdrElements);
2237 for (j = 0; j < n+1; j++)
2239 vertices[j](0) = ((
double) j / n) * sx;
2243 for (j = 0; j < n; j++)
2245 elements[j] =
new Segment(j, j+1, 1);
2250 boundary[0] =
new Point(ind, 1);
2252 boundary[1] =
new Point(ind, 2);
2259 attributes.Append(1);
2260 bdr_attributes.Append(1); bdr_attributes.Append(2);
2263 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
2280 elements.SetSize(NumOfElements);
2281 for (
int i = 0; i < NumOfElements; i++)
2283 elements[i] = mesh.
elements[i]->Duplicate(
this);
2287 MFEM_ASSERT(mesh.
vertices.Size() == NumOfVertices,
"internal MFEM error!");
2291 boundary.SetSize(NumOfBdrElements);
2292 for (
int i = 0; i < NumOfBdrElements; i++)
2294 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
2313 faces.SetSize(mesh.
faces.Size());
2314 for (
int i = 0; i < faces.Size(); i++)
2317 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
2336 "copying NURBS meshes is not implemented");
2340 MFEM_VERIFY(mesh.
ncmesh == NULL,
2341 "copying non-conforming meshes is not implemented");
2346 if (mesh.
Nodes && copy_nodes)
2351 FiniteElementCollection::New(fec->
Name());
2356 Nodes->MakeOwner(fec_copy);
2357 *Nodes = *mesh.
Nodes;
2367 Mesh::Mesh(
const char *filename,
int generate_edges,
int refine,
2368 bool fix_orientation)
2377 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
2381 Load(imesh, generate_edges, refine, fix_orientation);
2385 Mesh::Mesh(std::istream &input,
int generate_edges,
int refine,
2386 bool fix_orientation)
2389 Load(input, generate_edges, refine, fix_orientation);
2392 void Mesh::ChangeVertexDataOwnership(
double *vertex_data,
int len_vertex_data,
2397 MFEM_VERIFY(len_vertex_data >= NumOfVertices * 3,
2398 "Not enough vertices in external array : "
2399 "len_vertex_data = "<< len_vertex_data <<
", "
2400 "NumOfVertices * 3 = " << NumOfVertices * 3);
2402 if (vertex_data == (
double *)(vertices.GetData()))
2404 MFEM_ASSERT(!vertices.OwnsData(),
"invalid ownership");
2409 memcpy(vertex_data, vertices.GetData(),
2410 NumOfVertices * 3 *
sizeof(double));
2413 vertices.MakeRef(reinterpret_cast<Vertex*>(vertex_data), NumOfVertices);
2416 Mesh::Mesh(
double *_vertices,
int num_vertices,
2418 int *element_attributes,
int num_elements,
2420 int *boundary_attributes,
int num_boundary_elements,
2421 int dimension,
int space_dimension)
2423 if (space_dimension == -1)
2425 space_dimension = dimension;
2428 InitMesh(dimension, space_dimension, 0, num_elements,
2429 num_boundary_elements);
2431 int element_index_stride = Geometry::NumVerts[element_type];
2432 int boundary_index_stride = Geometry::NumVerts[boundary_type];
2435 vertices.MakeRef(reinterpret_cast<Vertex*>(_vertices), num_vertices);
2436 NumOfVertices = num_vertices;
2438 for (
int i = 0; i < num_elements; i++)
2440 elements[i] = NewElement(element_type);
2441 elements[i]->SetVertices(element_indices + i * element_index_stride);
2442 elements[i]->SetAttribute(element_attributes[i]);
2444 NumOfElements = num_elements;
2446 for (
int i = 0; i < num_boundary_elements; i++)
2448 boundary[i] = NewElement(boundary_type);
2449 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
2450 boundary[i]->SetAttribute(boundary_attributes[i]);
2452 NumOfBdrElements = num_boundary_elements;
2461 case Geometry::POINT:
return (
new Point);
2462 case Geometry::SEGMENT:
return (
new Segment);
2463 case Geometry::TRIANGLE:
return (
new Triangle);
2465 case Geometry::CUBE:
return (
new Hexahedron);
2466 case Geometry::TETRAHEDRON:
2467 #ifdef MFEM_USE_MEMALLOC
2468 return TetMemory.Alloc();
2477 Element *Mesh::ReadElementWithoutAttr(std::istream &input)
2483 el = NewElement(geom);
2486 for (
int i = 0; i < nv; i++)
2494 void Mesh::PrintElementWithoutAttr(
const Element *el, std::ostream &out)
2499 for (
int j = 0; j < nv; j++)
2512 el = ReadElementWithoutAttr(input);
2518 void Mesh::PrintElement(
const Element *el, std::ostream &out)
2521 PrintElementWithoutAttr(el, out);
2524 void Mesh::SetMeshGen()
2527 for (
int i = 0; i < NumOfElements; i++)
2529 switch (elements[i]->GetType())
2531 case Element::SEGMENT:
2532 case Element::TRIANGLE:
2533 case Element::TETRAHEDRON:
2534 meshgen |= 1;
break;
2536 case Element::QUADRILATERAL:
2537 case Element::HEXAHEDRON:
2543 void Mesh::Loader(std::istream &input,
int generate_edges,
2544 std::string parse_tag)
2546 int curved = 0, read_gf = 1;
2550 MFEM_ABORT(
"Input stream is not open");
2557 getline(input, mesh_type);
2561 bool mfem_v10 = (mesh_type ==
"MFEM mesh v1.0");
2562 bool mfem_v11 = (mesh_type ==
"MFEM mesh v1.1");
2563 bool mfem_v12 = (mesh_type ==
"MFEM mesh v1.2");
2564 if (mfem_v10 || mfem_v11 || mfem_v12)
2570 if ( mfem_v12 && parse_tag.empty() )
2572 parse_tag =
"mfem_mesh_end";
2574 ReadMFEMMesh(input, mfem_v11, curved);
2576 else if (mesh_type ==
"linemesh")
2578 ReadLineMesh(input);
2580 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
2582 if (mesh_type ==
"curved_areamesh2")
2586 ReadNetgen2DMesh(input, curved);
2588 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
2590 ReadNetgen3DMesh(input);
2592 else if (mesh_type ==
"TrueGrid")
2594 ReadTrueGridMesh(input);
2596 else if (mesh_type ==
"# vtk DataFile Version 3.0" ||
2597 mesh_type ==
"# vtk DataFile Version 2.0")
2599 ReadVTKMesh(input, curved, read_gf);
2601 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
2603 ReadNURBSMesh(input, curved, read_gf);
2605 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
2607 ReadInlineMesh(input, generate_edges);
2610 else if (mesh_type ==
"$MeshFormat")
2612 ReadGmshMesh(input);
2614 else if (mesh_type.size() > 2 &&
2615 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F')
2620 #ifdef MFEM_USE_NETCDF
2621 ReadCubit(mesh_input->
filename, curved, read_gf);
2623 MFEM_ABORT(
"NetCDF support requires configuration with"
2624 " MFEM_USE_NETCDF=YES");
2630 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
2631 " Use mfem::named_ifgzstream for input.");
2637 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
2662 if (curved && read_gf)
2666 spaceDim = Nodes->VectorDim();
2667 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2669 for (
int i = 0; i < spaceDim; i++)
2672 Nodes->GetNodalValues(vert_val, i+1);
2673 for (
int j = 0; j < NumOfVertices; j++)
2675 vertices[j](i) = vert_val(j);
2688 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
2689 getline(input, line);
2695 if (line ==
"mfem_mesh_end") {
break; }
2697 while (line != parse_tag);
2703 Mesh::Mesh(
Mesh *mesh_array[],
int num_pieces)
2705 int i, j, ie, ib, iv, *v, nv;
2714 BaseGeom = mesh_array[0]->
BaseGeom;
2717 if (mesh_array[0]->NURBSext)
2722 NumOfVertices = NURBSext->GetNV();
2723 NumOfElements = NURBSext->GetNE();
2725 NURBSext->GetElementTopo(elements);
2738 NumOfBdrElements = 0;
2739 for (i = 0; i < num_pieces; i++)
2741 NumOfBdrElements += mesh_array[i]->
GetNBE();
2743 boundary.SetSize(NumOfBdrElements);
2744 vertices.SetSize(NumOfVertices);
2746 for (i = 0; i < num_pieces; i++)
2752 for (j = 0; j < m->
GetNE(); j++)
2754 elements[lelem_elem[j]]->SetAttribute(m->
GetAttribute(j));
2757 for (j = 0; j < m->
GetNBE(); j++)
2762 for (
int k = 0; k < nv; k++)
2764 v[k] = lvert_vert[v[k]];
2766 boundary[ib++] = el;
2769 for (j = 0; j < m->
GetNV(); j++)
2771 vertices[lvert_vert[j]].SetCoords(m->
GetVertex(j));
2778 NumOfBdrElements = 0;
2780 for (i = 0; i < num_pieces; i++)
2783 NumOfElements += m->
GetNE();
2784 NumOfBdrElements += m->
GetNBE();
2785 NumOfVertices += m->
GetNV();
2787 elements.SetSize(NumOfElements);
2788 boundary.SetSize(NumOfBdrElements);
2789 vertices.SetSize(NumOfVertices);
2791 for (i = 0; i < num_pieces; i++)
2795 for (j = 0; j < m->
GetNE(); j++)
2800 for (
int k = 0; k < nv; k++)
2804 elements[ie++] = el;
2807 for (j = 0; j < m->
GetNBE(); j++)
2812 for (
int k = 0; k < nv; k++)
2816 boundary[ib++] = el;
2819 for (j = 0; j < m->
GetNV(); j++)
2821 vertices[iv++].SetCoords(m->
GetVertex(j));
2828 for (i = 0; i < num_pieces; i++)
2836 GetElementToFaceTable();
2847 el_to_edge =
new Table;
2848 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2867 for (i = 0; i < num_pieces; i++)
2869 gf_array[i] = mesh_array[i]->
GetNodes();
2876 CheckElementOrientation(
false);
2877 CheckBdrElementOrientation(
false);
2881 Mesh::Mesh(
Mesh *orig_mesh,
int ref_factor,
int ref_type)
2884 MFEM_VERIFY(ref_factor > 1,
"the refinement factor must be > 1");
2885 MFEM_VERIFY(ref_type == BasisType::ClosedUniform ||
2886 ref_type == BasisType::GaussLobatto,
"invalid refinement type");
2887 MFEM_VERIFY(Dim == 2 || Dim == 3,
2888 "only implemented for Hexahedron and Quadrilateral elements in "
2896 int r_bndr_factor = ref_factor * (Dim == 2 ? 1 : ref_factor);
2897 int r_elem_factor = ref_factor * r_bndr_factor;
2900 int r_num_elem = orig_mesh->
GetNE() * r_elem_factor;
2901 int r_num_bndr = orig_mesh->
GetNBE() * r_bndr_factor;
2903 InitMesh(Dim, orig_mesh->
SpaceDimension(), r_num_vert, r_num_elem,
2907 NumOfVertices = r_num_vert;
2912 for (
int el = 0; el < orig_mesh->
GetNE(); el++)
2916 int nvert = Geometry::NumVerts[
geom];
2919 max_nv = std::max(max_nv, nvert);
2925 const int *c2h_map = rfec.
GetDofMap(geom);
2926 for (
int i = 0; i < phys_pts.
Width(); i++)
2928 vertices[rdofs[i]].SetCoords(phys_pts.
GetColumn(i));
2932 Element *elem = NewElement(geom);
2935 for (
int k = 0; k < nvert; k++)
2938 v[k] = rdofs[c2h_map[cid]];
2944 for (
int el = 0; el < orig_mesh->
GetNBE(); el++)
2948 int nvert = Geometry::NumVerts[
geom];
2953 const int *c2h_map = rfec.
GetDofMap(geom);
2956 Element *elem = NewElement(geom);
2959 for (
int k = 0; k < nvert; k++)
2962 v[k] = rdofs[c2h_map[cid]];
2964 AddBdrElement(elem);
2970 last_operation = Mesh::REFINE;
2973 MFEM_VERIFY(BaseGeom != -1,
"meshes with mixed elements are not supported");
2974 CoarseFineTr.point_matrices.SetSize(Dim, max_nv, r_elem_factor);
2975 CoarseFineTr.embeddings.SetSize(GetNE());
2976 if (orig_mesh->
GetNE() > 0)
2980 int nvert = Geometry::NumVerts[
geom];
2982 const int *c2h_map = rfec.
GetDofMap(geom);
2987 for (
int k = 0; k < nvert; k++)
2995 for (
int el = 0; el < GetNE(); el++)
2997 Embedding &emb = CoarseFineTr.embeddings[el];
2998 emb.
parent = el / r_elem_factor;
2999 emb.
matrix = el % r_elem_factor;
3002 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
3003 MFEM_ASSERT(CheckBdrElementOrientation(
false) == 0,
"");
3008 if (NURBSext == NULL)
3010 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
3013 if (kv.
Size() != NURBSext->GetNKV())
3015 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
3018 NURBSext->ConvertToPatches(*Nodes);
3020 NURBSext->KnotInsert(kv);
3025 void Mesh::NURBSUniformRefinement()
3028 NURBSext->ConvertToPatches(*Nodes);
3030 NURBSext->UniformRefinement();
3032 last_operation = Mesh::REFINE;
3038 void Mesh::DegreeElevate(
int t)
3040 if (NURBSext == NULL)
3042 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
3045 NURBSext->ConvertToPatches(*Nodes);
3047 NURBSext->DegreeElevate(t);
3060 void Mesh::UpdateNURBS()
3062 NURBSext->SetKnotsFromPatches();
3064 Dim = NURBSext->Dimension();
3067 if (NumOfElements != NURBSext->GetNE())
3069 for (
int i = 0; i < elements.Size(); i++)
3071 FreeElement(elements[i]);
3073 NumOfElements = NURBSext->GetNE();
3074 NURBSext->GetElementTopo(elements);
3077 if (NumOfBdrElements != NURBSext->GetNBE())
3079 for (
int i = 0; i < boundary.Size(); i++)
3081 FreeElement(boundary[i]);
3083 NumOfBdrElements = NURBSext->GetNBE();
3084 NURBSext->GetBdrElementTopo(boundary);
3087 Nodes->FESpace()->Update();
3089 NURBSext->SetCoordsFromPatches(*Nodes);
3091 if (NumOfVertices != NURBSext->GetNV())
3093 NumOfVertices = NURBSext->GetNV();
3094 vertices.SetSize(NumOfVertices);
3095 int vd = Nodes->VectorDim();
3096 for (
int i = 0; i < vd; i++)
3099 Nodes->GetNodalValues(vert_val, i+1);
3100 for (
int j = 0; j < NumOfVertices; j++)
3102 vertices[j](i) = vert_val(j);
3109 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3118 GetElementToFaceTable();
3123 void Mesh::LoadPatchTopo(std::istream &input,
Array<int> &edge_to_knot)
3141 input >> NumOfElements;
3142 elements.SetSize(NumOfElements);
3143 for (j = 0; j < NumOfElements; j++)
3145 elements[j] = ReadElement(input);
3151 input >> NumOfBdrElements;
3152 boundary.SetSize(NumOfBdrElements);
3153 for (j = 0; j < NumOfBdrElements; j++)
3155 boundary[j] = ReadElement(input);
3161 input >> NumOfEdges;
3162 edge_vertex =
new Table(NumOfEdges, 2);
3163 edge_to_knot.
SetSize(NumOfEdges);
3164 for (j = 0; j < NumOfEdges; j++)
3166 int *v = edge_vertex->GetRow(j);
3167 input >> edge_to_knot[j] >> v[0] >> v[1];
3170 edge_to_knot[j] = -1 - edge_to_knot[j];
3177 input >> NumOfVertices;
3178 vertices.SetSize(0);
3187 GetElementToFaceTable();
3189 if (NumOfBdrElements == 0)
3191 GenerateBoundaryElements();
3193 CheckBdrElementOrientation();
3203 el_to_edge =
new Table;
3204 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3208 if (NumOfBdrElements == 0)
3210 GenerateBoundaryElements();
3212 CheckBdrElementOrientation();
3228 for (
int d = 0; d < v.
Size(); d++)
3236 for (d = 0; d < p.
Size(); d++)
3240 for ( ; d < v.
Size(); d++)
3249 if (Nodes == NULL || Nodes->FESpace() != nodes.
FESpace())
3264 SetNodalGridFunction(nodes,
true);
3270 NewNodes(*nodes, make_owner);
3275 return ((Nodes) ? Nodes->FESpace() : NULL);
3278 void Mesh::SetCurvature(
int order,
bool discont,
int space_dim,
int ordering)
3280 space_dim = (space_dim == -1) ? spaceDim : space_dim;
3293 SetNodalFESpace(nfes);
3294 Nodes->MakeOwner(nfec);
3297 int Mesh::GetNumFaces()
const
3301 case 1:
return GetNV();
3302 case 2:
return GetNEdges();
3303 case 3:
return GetNFaces();
3308 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3309 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
3312 int Mesh::CheckElementOrientation(
bool fix_it)
3314 int i, j, k, wo = 0, fo = 0, *vi = 0;
3317 if (Dim == 2 && spaceDim == 2)
3321 for (i = 0; i < NumOfElements; i++)
3325 vi = elements[i]->GetVertices();
3326 for (j = 0; j < 3; j++)
3328 v[j] = vertices[vi[j]]();
3330 for (j = 0; j < 2; j++)
3331 for (k = 0; k < 2; k++)
3333 J(j, k) = v[j+1][k] - v[0][k];
3339 GetElementJacobian(i, J);
3345 switch (GetElementType(i))
3347 case Element::TRIANGLE:
3350 case Element::QUADRILATERAL:
3365 for (i = 0; i < NumOfElements; i++)
3367 vi = elements[i]->GetVertices();
3368 switch (GetElementType(i))
3370 case Element::TETRAHEDRON:
3373 for (j = 0; j < 4; j++)
3375 v[j] = vertices[vi[j]]();
3377 for (j = 0; j < 3; j++)
3378 for (k = 0; k < 3; k++)
3380 J(j, k) = v[j+1][k] - v[0][k];
3386 GetElementJacobian(i, J);
3399 case Element::HEXAHEDRON:
3401 GetElementJacobian(i, J);
3414 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3416 cout <<
"Elements with wrong orientation: " << wo <<
" / "
3417 << NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
3423 int Mesh::GetTriOrientation(
const int *base,
const int *test)
3431 if (test[0] == base[0])
3432 if (test[1] == base[1])
3440 else if (test[0] == base[1])
3441 if (test[1] == base[0])
3450 if (test[1] == base[0])
3460 const int *aor = tri_t::Orient[orient];
3461 for (
int j = 0; j < 3; j++)
3462 if (test[aor[j]] != base[j])
3471 int Mesh::GetQuadOrientation(
const int *base,
const int *test)
3475 for (i = 0; i < 4; i++)
3476 if (test[i] == base[0])
3483 if (test[(i+1)%4] == base[1])
3491 const int *aor = quad_t::Orient[orient];
3492 for (
int j = 0; j < 4; j++)
3493 if (test[aor[j]] != base[j])
3495 cerr <<
"Mesh::GetQuadOrientation(...)" << endl;
3496 cerr <<
" base = [";
3497 for (
int k = 0; k < 4; k++)
3499 cerr <<
" " << base[k];
3501 cerr <<
" ]\n test = [";
3502 for (
int k = 0; k < 4; k++)
3504 cerr <<
" " << test[k];
3506 cerr <<
" ]" << endl;
3511 if (test[(i+1)%4] == base[1])
3519 int Mesh::CheckBdrElementOrientation(
bool fix_it)
3525 for (i = 0; i < NumOfBdrElements; i++)
3527 if (faces_info[be_to_edge[i]].Elem2No < 0)
3529 int *bv = boundary[i]->GetVertices();
3530 int *fv = faces[be_to_edge[i]]->GetVertices();
3535 mfem::Swap<int>(bv[0], bv[1]);
3548 for (i = 0; i < NumOfBdrElements; i++)
3550 if (faces_info[be_to_face[i]].Elem2No < 0)
3553 bv = boundary[i]->GetVertices();
3554 el = faces_info[be_to_face[i]].Elem1No;
3555 ev = elements[el]->GetVertices();
3556 switch (GetElementType(el))
3558 case Element::TETRAHEDRON:
3560 int *fv = faces[be_to_face[i]]->GetVertices();
3563 orientation = GetTriOrientation(fv, bv);
3564 if (orientation % 2)
3570 mfem::Swap<int>(bv[0], bv[1]);
3573 int *be = bel_to_edge->GetRow(i);
3574 mfem::Swap<int>(be[1], be[2]);
3582 case Element::HEXAHEDRON:
3584 int lf = faces_info[be_to_face[i]].Elem1Inf/64;
3585 for (
int j = 0; j < 4; j++)
3587 v[j] = ev[hex_t::FaceVert[lf][j]];
3589 if (GetQuadOrientation(v, bv) % 2)
3593 mfem::Swap<int>(bv[0], bv[2]);
3596 int *be = bel_to_edge->GetRow(i);
3597 mfem::Swap<int>(be[0], be[1]);
3598 mfem::Swap<int>(be[2], be[3]);
3613 cout <<
"Boundary elements with wrong orientation: " << wo <<
" / "
3614 << NumOfBdrElements <<
" (" << fixed_or_not[fix_it ? 0 : 1]
3625 el_to_edge->GetRow(i, edges);
3629 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
3630 "is not generated.");
3633 const int *v = elements[i]->GetVertices();
3634 const int ne = elements[i]->GetNEdges();
3636 for (
int j = 0; j < ne; j++)
3638 const int *e = elements[i]->GetEdgeVertices(j);
3639 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3649 edges[0] = be_to_edge[i];
3650 const int *v = boundary[i]->GetVertices();
3651 cor[0] = (v[0] < v[1]) ? (1) : (-1);
3657 bel_to_edge->GetRow(i, edges);
3664 const int *v = boundary[i]->GetVertices();
3665 const int ne = boundary[i]->GetNEdges();
3667 for (
int j = 0; j < ne; j++)
3669 const int *e = boundary[i]->GetEdgeVertices(j);
3670 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3682 const int *v = faces[i]->GetVertices();
3683 o[0] = (v[0] < v[1]) ? (1) : (-1);
3693 face_edge->GetRow(i, edges);
3695 const int *v = faces[i]->GetVertices();
3696 const int ne = faces[i]->GetNEdges();
3698 for (
int j = 0; j < ne; j++)
3700 const int *e = faces[i]->GetEdgeVertices(j);
3701 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3710 if (!edge_vertex) { GetEdgeVertexTable(); }
3711 edge_vertex->GetRow(i, vert);
3727 if (faces.Size() != NumOfFaces)
3729 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
3733 DSTable v_to_v(NumOfVertices);
3734 GetVertexToVertexTable(v_to_v);
3736 face_edge =
new Table;
3737 GetElementArrayEdgeTable(faces, v_to_v, *face_edge);
3749 DSTable v_to_v(NumOfVertices);
3750 GetVertexToVertexTable(v_to_v);
3753 edge_vertex =
new Table(nedges, 2);
3754 for (
int i = 0; i < NumOfVertices; i++)
3759 edge_vertex->Push(j, i);
3760 edge_vertex->Push(j, it.Column());
3763 edge_vertex->Finalize();
3774 vert_elem->
MakeI(NumOfVertices);
3776 for (i = 0; i < NumOfElements; i++)
3778 nv = elements[i]->GetNVertices();
3779 v = elements[i]->GetVertices();
3780 for (j = 0; j < nv; j++)
3788 for (i = 0; i < NumOfElements; i++)
3790 nv = elements[i]->GetNVertices();
3791 v = elements[i]->GetVertices();
3792 for (j = 0; j < nv; j++)
3803 Table *Mesh::GetFaceToElementTable()
const
3807 face_elem->
MakeI(faces_info.Size());
3809 for (
int i = 0; i < faces_info.Size(); i++)
3811 if (faces_info[i].Elem2No >= 0)
3823 for (
int i = 0; i < faces_info.Size(); i++)
3826 if (faces_info[i].Elem2No >= 0)
3844 el_to_face->
GetRow(i, fcs);
3848 mfem_error(
"Mesh::GetElementFaces(...) : el_to_face not generated.");
3853 for (j = 0; j < n; j++)
3854 if (faces_info[fcs[j]].Elem1No == i)
3856 cor[j] = faces_info[fcs[j]].Elem1Inf % 64;
3859 else if (faces_info[fcs[j]].Elem2No == i)
3861 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3865 mfem_error(
"Mesh::GetElementFaces(...) : 2");
3870 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3875 void Mesh::GetBdrElementFace(
int i,
int *f,
int *o)
const
3880 bv = boundary[i]->GetVertices();
3881 fv = faces[be_to_face[i]]->GetVertices();
3885 switch (GetBdrElementType(i))
3887 case Element::TRIANGLE:
3888 *o = GetTriOrientation(fv, bv);
3890 case Element::QUADRILATERAL:
3891 *o = GetQuadOrientation(fv, bv);
3894 mfem_error(
"Mesh::GetBdrElementFace(...) 2");
3898 int Mesh::GetFaceBaseGeometry(
int i)
const
3901 switch (GetElementType(0))
3903 case Element::SEGMENT:
3904 return Geometry::POINT;
3906 case Element::TRIANGLE:
3907 case Element::QUADRILATERAL:
3908 return Geometry::SEGMENT;
3910 case Element::TETRAHEDRON:
3911 return Geometry::TRIANGLE;
3912 case Element::HEXAHEDRON:
3913 return Geometry::SQUARE;
3915 mfem_error(
"Mesh::GetFaceBaseGeometry(...) #1");
3920 int Mesh::GetBdrElementEdgeIndex(
int i)
const
3924 case 1:
return boundary[i]->GetVertices()[0];
3925 case 2:
return be_to_edge[i];
3926 case 3:
return be_to_face[i];
3927 default:
mfem_error(
"Mesh::GetBdrElementEdgeIndex: invalid dimension!");
3932 void Mesh::GetBdrElementAdjacentElement(
int bdr_el,
int &el,
int &info)
const
3934 int fid = GetBdrElementEdgeIndex(bdr_el);
3935 const FaceInfo &fi = faces_info[fid];
3936 MFEM_ASSERT(fi.
Elem1Inf%64 == 0,
"internal error");
3937 const int *fv = (Dim > 1) ? faces[fid]->GetVertices() : NULL;
3938 const int *bv = boundary[bdr_el]->GetVertices();
3940 switch (GetBdrElementBaseGeometry(bdr_el))
3942 case Geometry::POINT: ori = 0;
break;
3943 case Geometry::SEGMENT: ori = (fv[0] == bv[0]) ? 0 : 1;
break;
3944 case Geometry::TRIANGLE: ori = GetTriOrientation(fv, bv);
break;
3945 case Geometry::SQUARE: ori = GetQuadOrientation(fv, bv);
break;
3946 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
3952 int Mesh::GetElementType(
int i)
const
3954 return elements[i]->GetType();
3957 int Mesh::GetBdrElementType(
int i)
const
3959 return boundary[i]->GetType();
3967 v = elements[i]->GetVertices();
3968 nv = elements[i]->GetNVertices();
3970 pointmat.
SetSize(spaceDim, nv);
3971 for (k = 0; k < spaceDim; k++)
3972 for (j = 0; j < nv; j++)
3974 pointmat(k, j) = vertices[v[j]](k);
3983 v = boundary[i]->GetVertices();
3984 nv = boundary[i]->GetNVertices();
3986 pointmat.
SetSize(spaceDim, nv);
3987 for (k = 0; k < spaceDim; k++)
3988 for (j = 0; j < nv; j++)
3990 pointmat(k, j) = vertices[v[j]](k);
3994 double Mesh::GetLength(
int i,
int j)
const
3996 const double *vi = vertices[i]();
3997 const double *vj = vertices[j]();
4000 for (
int k = 0; k < spaceDim; k++)
4002 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
4005 return sqrt(length);
4013 for (
int i = 0; i < elem_array.
Size(); i++)
4018 for (
int i = 0; i < elem_array.
Size(); i++)
4020 const int *v = elem_array[i]->GetVertices();
4021 const int ne = elem_array[i]->GetNEdges();
4022 for (
int j = 0; j < ne; j++)
4024 const int *e = elem_array[i]->GetEdgeVertices(j);
4031 void Mesh::GetVertexToVertexTable(
DSTable &v_to_v)
const
4035 for (
int i = 0; i < edge_vertex->Size(); i++)
4037 const int *v = edge_vertex->GetRow(i);
4038 v_to_v.
Push(v[0], v[1]);
4043 for (
int i = 0; i < NumOfElements; i++)
4045 const int *v = elements[i]->GetVertices();
4046 const int ne = elements[i]->GetNEdges();
4047 for (
int j = 0; j < ne; j++)
4049 const int *e = elements[i]->GetEdgeVertices(j);
4050 v_to_v.
Push(v[e[0]], v[e[1]]);
4058 int i, NumberOfEdges;
4060 DSTable v_to_v(NumOfVertices);
4061 GetVertexToVertexTable(v_to_v);
4066 GetElementArrayEdgeTable(elements, v_to_v, e_to_f);
4071 be_to_f.
SetSize(NumOfBdrElements);
4072 for (i = 0; i < NumOfBdrElements; i++)
4074 const int *v = boundary[i]->GetVertices();
4075 be_to_f[i] = v_to_v(v[0], v[1]);
4080 if (bel_to_edge == NULL)
4082 bel_to_edge =
new Table;
4084 GetElementArrayEdgeTable(boundary, v_to_v, *bel_to_edge);
4088 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
4092 return NumberOfEdges;
4095 const Table & Mesh::ElementToElementTable()
4102 int num_faces = GetNumFaces();
4103 MFEM_ASSERT(faces_info.Size() == num_faces,
"faces were not generated!");
4108 for (
int i = 0; i < faces_info.Size(); i++)
4110 const FaceInfo &fi = faces_info[i];
4118 int nbr_elem_idx = NumOfElements - 1 - fi.
Elem2No;
4126 el_to_el =
new Table(NumOfElements, conn);
4131 const Table & Mesh::ElementToFaceTable()
const
4133 if (el_to_face == NULL)
4140 const Table & Mesh::ElementToEdgeTable()
const
4142 if (el_to_edge == NULL)
4149 void Mesh::AddPointFaceElement(
int lf,
int gf,
int el)
4151 if (faces_info[gf].Elem1No == -1)
4154 faces_info[gf].Elem1No = el;
4155 faces_info[gf].Elem1Inf = 64 * lf;
4156 faces_info[gf].Elem2No = -1;
4157 faces_info[gf].Elem2Inf = -1;
4161 faces_info[gf].Elem2No = el;
4162 faces_info[gf].Elem2Inf = 64 * lf + 1;
4166 void Mesh::AddSegmentFaceElement(
int lf,
int gf,
int el,
int v0,
int v1)
4168 if (faces[gf] == NULL)
4170 faces[gf] =
new Segment(v0, v1);
4171 faces_info[gf].Elem1No = el;
4172 faces_info[gf].Elem1Inf = 64 * lf;
4173 faces_info[gf].Elem2No = -1;
4174 faces_info[gf].Elem2Inf = -1;
4178 int *v = faces[gf]->GetVertices();
4179 faces_info[gf].Elem2No = el;
4180 if ( v[1] == v0 && v[0] == v1 )
4182 faces_info[gf].Elem2Inf = 64 * lf + 1;
4184 else if ( v[0] == v0 && v[1] == v1 )
4186 faces_info[gf].Elem2Inf = 64 * lf;
4190 MFEM_ASSERT((v[1] == v0 && v[0] == v1)||
4191 (v[0] == v0 && v[1] == v1),
"");
4196 void Mesh::AddTriangleFaceElement(
int lf,
int gf,
int el,
4197 int v0,
int v1,
int v2)
4199 if (faces[gf] == NULL)
4201 faces[gf] =
new Triangle(v0, v1, v2);
4202 faces_info[gf].Elem1No = el;
4203 faces_info[gf].Elem1Inf = 64 * lf;
4204 faces_info[gf].Elem2No = -1;
4205 faces_info[gf].Elem2Inf = -1;
4209 int orientation, vv[3] = { v0, v1, v2 };
4210 orientation = GetTriOrientation(faces[gf]->GetVertices(), vv);
4211 MFEM_ASSERT(orientation % 2 != 0,
"");
4212 faces_info[gf].Elem2No = el;
4213 faces_info[gf].Elem2Inf = 64 * lf + orientation;
4217 void Mesh::AddQuadFaceElement(
int lf,
int gf,
int el,
4218 int v0,
int v1,
int v2,
int v3)
4220 if (faces_info[gf].Elem1No < 0)
4223 faces_info[gf].Elem1No = el;
4224 faces_info[gf].Elem1Inf = 64 * lf;
4225 faces_info[gf].Elem2No = -1;
4226 faces_info[gf].Elem2Inf = -1;
4230 int vv[4] = { v0, v1, v2, v3 };
4231 int oo = GetQuadOrientation(faces[gf]->GetVertices(), vv);
4232 MFEM_ASSERT(oo % 2 != 0,
"");
4233 faces_info[gf].Elem2No = el;
4234 faces_info[gf].Elem2Inf = 64 * lf + oo;
4238 void Mesh::GenerateFaces()
4240 int i, nfaces = GetNumFaces();
4242 for (i = 0; i < faces.Size(); i++)
4244 FreeElement(faces[i]);
4248 faces.SetSize(nfaces);
4249 faces_info.SetSize(nfaces);
4250 for (i = 0; i < nfaces; i++)
4253 faces_info[i].Elem1No = -1;
4254 faces_info[i].NCFace = -1;
4256 for (i = 0; i < NumOfElements; i++)
4258 const int *v = elements[i]->GetVertices();
4262 AddPointFaceElement(0, v[0], i);
4263 AddPointFaceElement(1, v[1], i);
4267 ef = el_to_edge->GetRow(i);
4268 const int ne = elements[i]->GetNEdges();
4269 for (
int j = 0; j < ne; j++)
4271 const int *e = elements[i]->GetEdgeVertices(j);
4272 AddSegmentFaceElement(j, ef[j], i, v[e[0]], v[e[1]]);
4277 ef = el_to_face->GetRow(i);
4278 switch (GetElementType(i))
4280 case Element::TETRAHEDRON:
4282 for (
int j = 0; j < 4; j++)
4284 const int *fv = tet_t::FaceVert[j];
4285 AddTriangleFaceElement(j, ef[j], i,
4286 v[fv[0]], v[fv[1]], v[fv[2]]);
4290 case Element::HEXAHEDRON:
4292 for (
int j = 0; j < 6; j++)
4294 const int *fv = hex_t::FaceVert[j];
4295 AddQuadFaceElement(j, ef[j], i,
4296 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4301 MFEM_ABORT(
"Unexpected type of Element.");
4307 void Mesh::GenerateNCFaceInfo()
4309 MFEM_VERIFY(ncmesh,
"missing NCMesh.");
4311 for (
int i = 0; i < faces_info.Size(); i++)
4313 faces_info[i].NCFace = -1;
4317 (Dim == 2) ? ncmesh->GetEdgeList() : ncmesh->GetFaceList();
4319 nc_faces_info.SetSize(0);
4320 nc_faces_info.Reserve(list.
masters.size() + list.
slaves.size());
4322 int nfaces = GetNumFaces();
4325 for (
unsigned i = 0; i < list.
masters.size(); i++)
4328 if (master.
index >= nfaces) {
continue; }
4330 faces_info[master.
index].NCFace = nc_faces_info.Size();
4336 for (
unsigned i = 0; i < list.
slaves.size(); i++)
4339 if (slave.
index >= nfaces || slave.
master >= nfaces) {
continue; }
4345 slave_fi.
NCFace = nc_faces_info.Size();
4357 for (
int i = 0; i < NumOfElements; i++)
4359 const int *v = elements[i]->GetVertices();
4360 switch (GetElementType(i))
4362 case Element::TETRAHEDRON:
4364 for (
int j = 0; j < 4; j++)
4366 const int *fv = tet_t::FaceVert[j];
4367 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
4371 case Element::HEXAHEDRON:
4375 for (
int j = 0; j < 6; j++)
4377 const int *fv = hex_t::FaceVert[j];
4378 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4383 MFEM_ABORT(
"Unexpected type of Element.");
4394 if (el_to_face != NULL)
4398 el_to_face =
new Table(NumOfElements, 6);
4399 faces_tbl =
new STable3D(NumOfVertices);
4400 for (i = 0; i < NumOfElements; i++)
4402 v = elements[i]->GetVertices();
4403 switch (GetElementType(i))
4405 case Element::TETRAHEDRON:
4407 for (
int j = 0; j < 4; j++)
4409 const int *fv = tet_t::FaceVert[j];
4411 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
4415 case Element::HEXAHEDRON:
4419 for (
int j = 0; j < 6; j++)
4421 const int *fv = hex_t::FaceVert[j];
4423 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
4428 MFEM_ABORT(
"Unexpected type of Element.");
4431 el_to_face->Finalize();
4433 be_to_face.SetSize(NumOfBdrElements);
4434 for (i = 0; i < NumOfBdrElements; i++)
4436 v = boundary[i]->GetVertices();
4437 switch (GetBdrElementType(i))
4439 case Element::TRIANGLE:
4441 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2]);
4444 case Element::QUADRILATERAL:
4446 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
4450 MFEM_ABORT(
"Unexpected type of boundary Element.");
4462 void Mesh::ReorientTetMesh()
4466 if (Dim != 3 || !(meshgen & 1))
4472 Table *old_elem_vert = NULL;
4476 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
4479 for (
int i = 0; i < NumOfElements; i++)
4481 if (GetElementType(i) == Element::TETRAHEDRON)
4483 v = elements[i]->GetVertices();
4485 Rotate3(v[0], v[1], v[2]);
4488 Rotate3(v[1], v[2], v[3]);
4492 ShiftL2R(v[0], v[1], v[3]);
4497 for (
int i = 0; i < NumOfBdrElements; i++)
4499 if (GetBdrElementType(i) == Element::TRIANGLE)
4501 v = boundary[i]->GetVertices();
4503 Rotate3(v[0], v[1], v[2]);
4509 GetElementToFaceTable();
4513 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
4518 DoNodeReorder(old_v_to_v, old_elem_vert);
4519 delete old_elem_vert;
4525 #ifndef MFEM_USE_METIS_5
4530 int*,
int*,
int*,
int*,
int*,
idxtype*);
4532 int*,
int*,
int*,
int*,
int*,
idxtype*);
4534 int*,
int*,
int*,
int*,
int*,
idxtype*);
4541 int *Mesh::CartesianPartitioning(
int nxyz[])
4544 double pmin[3] = { numeric_limits<double>::infinity(),
4545 numeric_limits<double>::infinity(),
4546 numeric_limits<double>::infinity()
4548 double pmax[3] = { -numeric_limits<double>::infinity(),
4549 -numeric_limits<double>::infinity(),
4550 -numeric_limits<double>::infinity()
4553 for (
int vi = 0; vi < NumOfVertices; vi++)
4555 const double *p = vertices[vi]();
4556 for (
int i = 0; i < spaceDim; i++)
4558 if (p[i] < pmin[i]) { pmin[i] = p[i]; }
4559 if (p[i] > pmax[i]) { pmax[i] = p[i]; }
4563 partitioning =
new int[NumOfElements];
4567 Vector pt(ppt, spaceDim);
4568 for (
int el = 0; el < NumOfElements; el++)
4570 GetElementTransformation(el)->Transform(
4573 for (
int i = spaceDim-1; i >= 0; i--)
4575 int idx = (int)floor(nxyz[i]*((pt(i) - pmin[i])/(pmax[i] - pmin[i])));
4576 if (idx < 0) { idx = 0; }
4577 if (idx >= nxyz[i]) { idx = nxyz[i]-1; }
4578 part = part * nxyz[i] + idx;
4580 partitioning[el] = part;
4583 return partitioning;
4586 int *Mesh::GeneratePartitioning(
int nparts,
int part_method)
4589 int i, *partitioning;
4591 ElementToElementTable();
4593 partitioning =
new int[NumOfElements];
4597 for (i = 0; i < NumOfElements; i++)
4599 partitioning[i] = 0;
4605 #ifndef MFEM_USE_METIS_5
4617 I = el_to_el->GetI();
4618 J = el_to_el->GetJ();
4619 #ifndef MFEM_USE_METIS_5
4622 METIS_SetDefaultOptions(options);
4623 options[METIS_OPTION_CONTIG] = 1;
4627 if (part_method >= 0 && part_method <= 2)
4629 for (i = 0; i < n; i++)
4635 std::sort(J+I[i], J+I[i+1], std::greater<int>());
4641 if (part_method == 0 || part_method == 3)
4643 #ifndef MFEM_USE_METIS_5
4671 " error in METIS_PartGraphRecursive!");
4677 if (part_method == 1 || part_method == 4)
4679 #ifndef MFEM_USE_METIS_5
4707 " error in METIS_PartGraphKway!");
4713 if (part_method == 2 || part_method == 5)
4715 #ifndef MFEM_USE_METIS_5
4728 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_VOL;
4744 " error in METIS_PartGraphKway!");
4749 cout <<
"Mesh::GeneratePartitioning(...): edgecut = "
4763 for (i = 0; i < nparts; i++)
4769 for (i = 0; i < NumOfElements; i++)
4771 psize[partitioning[i]].one++;
4774 int empty_parts = 0;
4775 for (i = 0; i < nparts; i++)
4776 if (psize[i].one == 0)
4785 cerr <<
"Mesh::GeneratePartitioning returned " << empty_parts
4786 <<
" empty parts!" << endl;
4788 SortPairs<int,int>(psize, nparts);
4790 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4795 for (
int j = 0; j < NumOfElements; j++)
4796 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4797 if (psize[i].one == 0 || partitioning[j] != psize[i].two)
4803 partitioning[j] = psize[nparts-1-i].two;
4809 return partitioning;
4813 mfem_error(
"Mesh::GeneratePartitioning(...): "
4814 "MFEM was compiled without Metis.");
4828 int num_elem, *i_elem_elem, *j_elem_elem;
4830 num_elem = elem_elem.
Size();
4831 i_elem_elem = elem_elem.
GetI();
4832 j_elem_elem = elem_elem.
GetJ();
4837 int stack_p, stack_top_p, elem;
4841 for (i = 0; i < num_elem; i++)
4843 if (partitioning[i] > num_part)
4845 num_part = partitioning[i];
4852 for (i = 0; i < num_part; i++)
4859 for (elem = 0; elem < num_elem; elem++)
4861 if (component[elem] >= 0)
4866 component[elem] = num_comp[partitioning[elem]]++;
4868 elem_stack[stack_top_p++] = elem;
4870 for ( ; stack_p < stack_top_p; stack_p++)
4872 i = elem_stack[stack_p];
4873 for (j = i_elem_elem[i]; j < i_elem_elem[i+1]; j++)
4876 if (partitioning[k] == partitioning[i])
4878 if (component[k] < 0)
4880 component[k] = component[i];
4881 elem_stack[stack_top_p++] = k;
4883 else if (component[k] != component[i])
4893 void Mesh::CheckPartitioning(
int *partitioning)
4895 int i, n_empty, n_mcomp;
4897 const Array<int> _partitioning(partitioning, GetNE());
4899 ElementToElementTable();
4903 n_empty = n_mcomp = 0;
4904 for (i = 0; i < num_comp.
Size(); i++)
4905 if (num_comp[i] == 0)
4909 else if (num_comp[i] > 1)
4916 cout <<
"Mesh::CheckPartitioning(...) :\n"
4917 <<
"The following subdomains are empty :\n";
4918 for (i = 0; i < num_comp.
Size(); i++)
4919 if (num_comp[i] == 0)
4927 cout <<
"Mesh::CheckPartitioning(...) :\n"
4928 <<
"The following subdomains are NOT connected :\n";
4929 for (i = 0; i < num_comp.
Size(); i++)
4930 if (num_comp[i] > 1)
4936 if (n_empty == 0 && n_mcomp == 0)
4937 cout <<
"Mesh::CheckPartitioning(...) : "
4938 "All subdomains are connected." << endl;
4952 const double *a = A.
Data();
4953 const double *b = B.
Data();
4962 c(0) = a[0]*a[3]-a[1]*a[2];
4963 c(1) = a[0]*b[3]-a[1]*b[2]+b[0]*a[3]-b[1]*a[2];
4964 c(2) = b[0]*b[3]-b[1]*b[2];
4985 c(0) = (a[0] * (a[4] * a[8] - a[5] * a[7]) +
4986 a[1] * (a[5] * a[6] - a[3] * a[8]) +
4987 a[2] * (a[3] * a[7] - a[4] * a[6]));
4989 c(1) = (b[0] * (a[4] * a[8] - a[5] * a[7]) +
4990 b[1] * (a[5] * a[6] - a[3] * a[8]) +
4991 b[2] * (a[3] * a[7] - a[4] * a[6]) +
4993 a[0] * (b[4] * a[8] - b[5] * a[7]) +
4994 a[1] * (b[5] * a[6] - b[3] * a[8]) +
4995 a[2] * (b[3] * a[7] - b[4] * a[6]) +
4997 a[0] * (a[4] * b[8] - a[5] * b[7]) +
4998 a[1] * (a[5] * b[6] - a[3] * b[8]) +
4999 a[2] * (a[3] * b[7] - a[4] * b[6]));
5001 c(2) = (a[0] * (b[4] * b[8] - b[5] * b[7]) +
5002 a[1] * (b[5] * b[6] - b[3] * b[8]) +
5003 a[2] * (b[3] * b[7] - b[4] * b[6]) +
5005 b[0] * (a[4] * b[8] - a[5] * b[7]) +
5006 b[1] * (a[5] * b[6] - a[3] * b[8]) +
5007 b[2] * (a[3] * b[7] - a[4] * b[6]) +
5009 b[0] * (b[4] * a[8] - b[5] * a[7]) +
5010 b[1] * (b[5] * a[6] - b[3] * a[8]) +
5011 b[2] * (b[3] * a[7] - b[4] * a[6]));
5013 c(3) = (b[0] * (b[4] * b[8] - b[5] * b[7]) +
5014 b[1] * (b[5] * b[6] - b[3] * b[8]) +
5015 b[2] * (b[3] * b[7] - b[4] * b[6]));
5061 double a = z(2), b = z(1), c = z(0);
5062 double D = b*b-4*a*c;
5069 x(0) = x(1) = -0.5 * b / a;
5074 x(0) = -(x(1) = fabs(0.5 * sqrt(D) / a));
5082 t = -0.5 * (b + sqrt(D));
5086 t = -0.5 * (b - sqrt(D));
5092 Swap<double>(x(0), x(1));
5100 double a = z(2)/z(3), b = z(1)/z(3), c = z(0)/z(3);
5103 double Q = (a * a - 3 * b) / 9;
5104 double R = (2 * a * a * a - 9 * a * b + 27 * c) / 54;
5105 double Q3 = Q * Q * Q;
5112 x(0) = x(1) = x(2) = - a / 3;
5116 double sqrtQ = sqrt(Q);
5120 x(0) = -2 * sqrtQ - a / 3;
5121 x(1) = x(2) = sqrtQ - a / 3;
5125 x(0) = x(1) = - sqrtQ - a / 3;
5126 x(2) = 2 * sqrtQ - a / 3;
5133 double theta = acos(R / sqrt(Q3));
5134 double A = -2 * sqrt(Q);
5136 x0 = A * cos(theta / 3) - a / 3;
5137 x1 = A * cos((theta + 2.0 * M_PI) / 3) - a / 3;
5138 x2 = A * cos((theta - 2.0 * M_PI) / 3) - a / 3;
5143 Swap<double>(x0, x1);
5147 Swap<double>(x1, x2);
5150 Swap<double>(x0, x1);
5163 A = -pow(sqrt(R2 - Q3) + R, 1.0/3.0);
5167 A = pow(sqrt(R2 - Q3) - R, 1.0/3.0);
5169 x(0) = A + Q / A - a / 3;
5178 const double factor,
const int Dim)
5180 const double c0 = c(0);
5181 c(0) = c0 * (1.0 - pow(factor, -Dim));
5183 for (
int j = 0; j < nr; j++)
5195 c(0) = c0 * (1.0 - pow(factor, Dim));
5197 for (
int j = 0; j < nr; j++)
5211 void Mesh::CheckDisplacements(
const Vector &displacements,
double &tmax)
5213 int nvs = vertices.Size();
5214 DenseMatrix P, V, DS, PDS(spaceDim), VDS(spaceDim);
5215 Vector c(spaceDim+1), x(spaceDim);
5216 const double factor = 2.0;
5223 for (
int i = 0; i < NumOfElements; i++)
5230 for (
int j = 0; j < spaceDim; j++)
5231 for (
int k = 0; k < nv; k++)
5233 P(j, k) = vertices[v[k]](j);
5234 V(j, k) = displacements(v[k]+j*nvs);
5238 GetTransformationFEforElementType(el->
GetType());
5242 case Element::TRIANGLE:
5243 case Element::TETRAHEDRON:
5261 case Element::QUADRILATERAL:
5264 for (
int j = 0; j < nv; j++)
5288 void Mesh::MoveVertices(
const Vector &displacements)
5290 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5291 for (
int j = 0; j < spaceDim; j++)
5293 vertices[i](j) += displacements(j*nv+i);
5297 void Mesh::GetVertices(
Vector &vert_coord)
const
5299 int nv = vertices.Size();
5300 vert_coord.
SetSize(nv*spaceDim);
5301 for (
int i = 0; i < nv; i++)
5302 for (
int j = 0; j < spaceDim; j++)
5304 vert_coord(j*nv+i) = vertices[i](j);
5308 void Mesh::SetVertices(
const Vector &vert_coord)
5310 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5311 for (
int j = 0; j < spaceDim; j++)
5313 vertices[i](j) = vert_coord(j*nv+i);
5317 void Mesh::GetNode(
int i,
double *coord)
5322 for (
int j = 0; j < spaceDim; j++)
5324 coord[j] = (*Nodes)(fes->
DofToVDof(i, j));
5329 for (
int j = 0; j < spaceDim; j++)
5331 coord[j] = vertices[i](j);
5336 void Mesh::SetNode(
int i,
const double *coord)
5341 for (
int j = 0; j < spaceDim; j++)
5343 (*Nodes)(fes->
DofToVDof(i, j)) = coord[j];
5348 for (
int j = 0; j < spaceDim; j++)
5350 vertices[i](j) = coord[j];
5356 void Mesh::MoveNodes(
const Vector &displacements)
5360 (*Nodes) += displacements;
5364 MoveVertices(displacements);
5368 void Mesh::GetNodes(
Vector &node_coord)
const
5372 node_coord = (*Nodes);
5376 GetVertices(node_coord);
5380 void Mesh::SetNodes(
const Vector &node_coord)
5384 (*Nodes) = node_coord;
5388 SetVertices(node_coord);
5394 if (own_nodes) {
delete Nodes; }
5397 own_nodes = (int)make_owner;
5408 mfem::Swap<GridFunction*>(Nodes, nodes);
5409 mfem::Swap<int>(own_nodes, own_nodes_);
5416 void Mesh::AverageVertices(
int * indexes,
int n,
int result)
5420 for (k = 0; k < spaceDim; k++)
5422 vertices[result](k) = vertices[indexes[0]](k);
5425 for (j = 1; j < n; j++)
5426 for (k = 0; k < spaceDim; k++)
5428 vertices[result](k) += vertices[indexes[j]](k);
5431 for (k = 0; k < spaceDim; k++)
5433 vertices[result](k) *= (1.0 / n);
5437 void Mesh::UpdateNodes()
5441 Nodes->FESpace()->Update();
5446 void Mesh::QuadUniformRefinement()
5448 int i, j, *v, vv[2], attr;
5451 if (el_to_edge == NULL)
5453 el_to_edge =
new Table;
5454 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5457 int oedge = NumOfVertices;
5458 int oelem = oedge + NumOfEdges;
5460 vertices.SetSize(oelem + NumOfElements);
5462 for (i = 0; i < NumOfElements; i++)
5464 v = elements[i]->GetVertices();
5466 AverageVertices(v, 4, oelem+i);
5468 e = el_to_edge->GetRow(i);
5470 vv[0] = v[0], vv[1] = v[1]; AverageVertices(vv, 2, oedge+e[0]);
5471 vv[0] = v[1], vv[1] = v[2]; AverageVertices(vv, 2, oedge+e[1]);
5472 vv[0] = v[2], vv[1] = v[3]; AverageVertices(vv, 2, oedge+e[2]);
5473 vv[0] = v[3], vv[1] = v[0]; AverageVertices(vv, 2, oedge+e[3]);
5476 elements.SetSize(4 * NumOfElements);
5477 for (i = 0; i < NumOfElements; i++)
5479 attr = elements[i]->GetAttribute();
5480 v = elements[i]->GetVertices();
5481 e = el_to_edge->GetRow(i);
5482 j = NumOfElements + 3 * i;
5484 elements[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5486 elements[j+1] =
new Quadrilateral(oelem+i, oedge+e[1], v[2],
5488 elements[j+2] =
new Quadrilateral(oedge+e[3], oelem+i, oedge+e[2],
5496 boundary.SetSize(2 * NumOfBdrElements);
5497 for (i = 0; i < NumOfBdrElements; i++)
5499 attr = boundary[i]->GetAttribute();
5500 v = boundary[i]->GetVertices();
5501 j = NumOfBdrElements + i;
5503 boundary[j] =
new Segment(oedge+be_to_edge[i], v[1], attr);
5505 v[1] = oedge+be_to_edge[i];
5508 static double quad_children[2*4*4] =
5510 0.0,0.0, 0.5,0.0, 0.5,0.5, 0.0,0.5,
5511 0.5,0.0, 1.0,0.0, 1.0,0.5, 0.5,0.5,
5512 0.5,0.5, 1.0,0.5, 1.0,1.0, 0.5,1.0,
5513 0.0,0.5, 0.5,0.5, 0.5,1.0, 0.0,1.0
5516 CoarseFineTr.point_matrices.UseExternalData(quad_children, 2, 4, 4);
5517 CoarseFineTr.embeddings.SetSize(elements.Size());
5519 for (i = 0; i < elements.Size(); i++)
5521 Embedding &emb = CoarseFineTr.embeddings[i];
5522 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 3;
5523 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 3 + 1;
5526 NumOfVertices = oelem + NumOfElements;
5527 NumOfElements = 4 * NumOfElements;
5528 NumOfBdrElements = 2 * NumOfBdrElements;
5531 if (el_to_edge != NULL)
5533 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5537 last_operation = Mesh::REFINE;
5543 CheckElementOrientation(
false);
5544 CheckBdrElementOrientation(
false);
5548 void Mesh::HexUniformRefinement()
5555 if (el_to_edge == NULL)
5557 el_to_edge =
new Table;
5558 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5560 if (el_to_face == NULL)
5562 GetElementToFaceTable();
5565 int oedge = NumOfVertices;
5566 int oface = oedge + NumOfEdges;
5567 int oelem = oface + NumOfFaces;
5569 vertices.SetSize(oelem + NumOfElements);
5570 for (i = 0; i < NumOfElements; i++)
5572 MFEM_ASSERT(elements[i]->GetType() == Element::HEXAHEDRON,
5573 "Element is not a hex!");
5574 v = elements[i]->GetVertices();
5576 AverageVertices(v, 8, oelem+i);
5578 f = el_to_face->GetRow(i);
5580 for (
int j = 0; j < 6; j++)
5582 for (
int k = 0; k < 4; k++)
5584 vv[k] = v[hex_t::FaceVert[j][k]];
5586 AverageVertices(vv, 4, oface+f[j]);
5589 e = el_to_edge->GetRow(i);
5591 for (
int j = 0; j < 12; j++)
5593 for (
int k = 0; k < 2; k++)
5595 vv[k] = v[hex_t::Edges[j][k]];
5597 AverageVertices(vv, 2, oedge+e[j]);
5602 elements.SetSize(8 * NumOfElements);
5603 for (i = 0; i < NumOfElements; i++)
5605 attr = elements[i]->GetAttribute();
5606 v = elements[i]->GetVertices();
5607 e = el_to_edge->GetRow(i);
5608 f = el_to_face->GetRow(i);
5609 j = NumOfElements + 7 * i;
5611 elements[j+0] =
new Hexahedron(oedge+e[0], v[1], oedge+e[1], oface+f[0],
5612 oface+f[1], oedge+e[9], oface+f[2],
5614 elements[j+1] =
new Hexahedron(oface+f[0], oedge+e[1], v[2], oedge+e[2],
5615 oelem+i, oface+f[2], oedge+e[10],
5617 elements[j+2] =
new Hexahedron(oedge+e[3], oface+f[0], oedge+e[2], v[3],
5618 oface+f[4], oelem+i, oface+f[3],
5620 elements[j+3] =
new Hexahedron(oedge+e[8], oface+f[1], oelem+i,
5621 oface+f[4], v[4], oedge+e[4], oface+f[5],
5623 elements[j+4] =
new Hexahedron(oface+f[1], oedge+e[9], oface+f[2],
5624 oelem+i, oedge+e[4], v[5], oedge+e[5],
5626 elements[j+5] =
new Hexahedron(oelem+i, oface+f[2], oedge+e[10],
5627 oface+f[3], oface+f[5], oedge+e[5], v[6],
5629 elements[j+6] =
new Hexahedron(oface+f[4], oelem+i, oface+f[3],
5630 oedge+e[11], oedge+e[7], oface+f[5],
5631 oedge+e[6], v[7], attr);
5642 boundary.SetSize(4 * NumOfBdrElements);
5643 for (i = 0; i < NumOfBdrElements; i++)
5645 MFEM_ASSERT(boundary[i]->GetType() == Element::QUADRILATERAL,
5646 "boundary Element is not a quad!");
5647 attr = boundary[i]->GetAttribute();
5648 v = boundary[i]->GetVertices();
5649 e = bel_to_edge->GetRow(i);
5650 f = & be_to_face[i];
5651 j = NumOfBdrElements + 3 * i;
5653 boundary[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5655 boundary[j+1] =
new Quadrilateral(oface+f[0], oedge+e[1], v[2],
5657 boundary[j+2] =
new Quadrilateral(oedge+e[3], oface+f[0], oedge+e[2],
5665 static const double A = 0.0, B = 0.5, C = 1.0;
5666 static double hex_children[3*8*8] =
5668 A,A,A, B,A,A, B,B,A, A,B,A, A,A,B, B,A,B, B,B,B, A,B,B,
5669 B,A,A, C,A,A, C,B,A, B,B,A, B,A,B, C,A,B, C,B,B, B,B,B,
5670 B,B,A, C,B,A, C,C,A, B,C,A, B,B,B, C,B,B, C,C,B, B,C,B,
5671 A,B,A, B,B,A, B,C,A, A,C,A, A,B,B, B,B,B, B,C,B, A,C,B,
5672 A,A,B, B,A,B, B,B,B, A,B,B, A,A,C, B,A,C, B,B,C, A,B,C,
5673 B,A,B, C,A,B, C,B,B, B,B,B, B,A,C, C,A,C, C,B,C, B,B,C,
5674 B,B,B, C,B,B, C,C,B, B,C,B, B,B,C, C,B,C, C,C,C, B,C,C,
5675 A,B,B, B,B,B, B,C,B, A,C,B, A,B,C, B,B,C, B,C,C, A,C,C
5678 CoarseFineTr.point_matrices.UseExternalData(hex_children, 3, 8, 8);
5679 CoarseFineTr.embeddings.SetSize(elements.Size());
5681 for (i = 0; i < elements.Size(); i++)
5683 Embedding &emb = CoarseFineTr.embeddings[i];
5684 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 7;
5685 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 7 + 1;
5688 NumOfVertices = oelem + NumOfElements;
5689 NumOfElements = 8 * NumOfElements;
5690 NumOfBdrElements = 4 * NumOfBdrElements;
5692 if (el_to_face != NULL)
5694 GetElementToFaceTable();
5699 CheckBdrElementOrientation(
false);
5702 if (el_to_edge != NULL)
5704 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5707 last_operation = Mesh::REFINE;
5713 void Mesh::LocalRefinement(
const Array<int> &marked_el,
int type)
5715 int i, j, ind, nedges;
5720 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
5723 InitRefinementTransforms();
5727 int cne = NumOfElements, cnv = NumOfVertices;
5728 NumOfVertices += marked_el.
Size();
5729 NumOfElements += marked_el.
Size();
5730 vertices.SetSize(NumOfVertices);
5731 elements.SetSize(NumOfElements);
5732 CoarseFineTr.embeddings.SetSize(NumOfElements);
5734 for (j = 0; j < marked_el.
Size(); j++)
5739 int new_v = cnv + j, new_e = cne + j;
5740 AverageVertices(vert, 2, new_v);
5741 elements[new_e] =
new Segment(new_v, vert[1], attr);
5744 CoarseFineTr.embeddings[i] =
Embedding(i, 1);
5745 CoarseFineTr.embeddings[new_e] =
Embedding(i, 2);
5748 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
5749 CoarseFineTr.point_matrices.UseExternalData(seg_children, 1, 2, 3);
5757 DSTable v_to_v(NumOfVertices);
5758 GetVertexToVertexTable(v_to_v);
5762 int *edge1 =
new int[nedges];
5763 int *edge2 =
new int[nedges];
5764 int *middle =
new int[nedges];
5766 for (i = 0; i < nedges; i++)
5768 edge1[i] = edge2[i] = middle[i] = -1;
5771 for (i = 0; i < NumOfElements; i++)
5773 elements[i]->GetVertices(v);
5774 for (j = 1; j < v.
Size(); j++)
5776 ind = v_to_v(v[j-1], v[j]);
5777 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5779 ind = v_to_v(v[0], v[v.
Size()-1]);
5780 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5784 for (i = 0; i < marked_el.
Size(); i++)
5786 RedRefinement(marked_el[i], v_to_v, edge1, edge2, middle);
5790 int need_refinement;
5793 need_refinement = 0;
5794 for (i = 0; i < nedges; i++)
5796 if (middle[i] != -1 && edge1[i] != -1)
5798 need_refinement = 1;
5799 GreenRefinement(edge1[i], v_to_v, edge1, edge2, middle);
5803 while (need_refinement == 1);
5806 int v1[2], v2[2], bisect, temp;
5807 temp = NumOfBdrElements;
5808 for (i = 0; i < temp; i++)
5810 boundary[i]->GetVertices(v);
5811 bisect = v_to_v(v[0], v[1]);
5812 if (middle[bisect] != -1)
5814 if (boundary[i]->GetType() == Element::SEGMENT)
5816 v1[0] = v[0]; v1[1] = middle[bisect];
5817 v2[0] = middle[bisect]; v2[1] = v[1];
5819 boundary[i]->SetVertices(v1);
5820 boundary.
Append(
new Segment(v2, boundary[i]->GetAttribute()));
5823 mfem_error(
"Only bisection of segment is implemented"
5827 NumOfBdrElements = boundary.Size();
5834 if (el_to_edge != NULL)
5836 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5844 DSTable v_to_v(NumOfVertices);
5845 GetVertexToVertexTable(v_to_v);
5849 int *middle =
new int[nedges];
5851 for (i = 0; i < nedges; i++)
5861 for (i = 0; i < marked_el.
Size(); i++)
5863 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5867 for (i = 0; i < marked_el.
Size(); i++)
5869 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5871 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5872 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5876 for (i = 0; i < marked_el.
Size(); i++)
5878 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5880 ii = NumOfElements - 1;
5881 Bisection(ii, v_to_v, NULL, NULL, middle);
5882 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5883 Bisection(ii, v_to_v, NULL, NULL, middle);
5885 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5886 Bisection(NumOfElements-1, v_to_v, NULL, NULL, middle);
5887 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5893 int need_refinement;
5898 need_refinement = 0;
5901 for (i = 0; i < NumOfElements; i++)
5905 if (elements[i]->NeedRefinement(v_to_v, middle))
5907 need_refinement = 1;
5908 Bisection(i, v_to_v, NULL, NULL, middle);
5912 while (need_refinement == 1);
5919 need_refinement = 0;
5920 for (i = 0; i < NumOfBdrElements; i++)
5921 if (boundary[i]->NeedRefinement(v_to_v, middle))
5923 need_refinement = 1;
5924 Bisection(i, v_to_v, middle);
5927 while (need_refinement == 1);
5930 int refinement_edges[2], type, flag;
5931 for (i = 0; i < NumOfElements; i++)
5936 if (type == Tetrahedron::TYPE_PF)
5943 NumOfBdrElements = boundary.Size();
5948 if (el_to_edge != NULL)
5950 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5952 if (el_to_face != NULL)
5954 GetElementToFaceTable();
5960 last_operation = Mesh::REFINE;
5966 CheckElementOrientation(
false);
5973 MFEM_VERIFY(!NURBSext,
"Nonconforming refinement of NURBS meshes is "
5974 "not supported. Project the NURBS to Nodes first.");
5979 ncmesh =
new NCMesh(
this);
5982 if (!refinements.
Size())
5984 last_operation = Mesh::NONE;
5989 ncmesh->MarkCoarseLevel();
5990 ncmesh->Refine(refinements);
5994 ncmesh->LimitNCLevel(nc_limit);
5999 ncmesh->OnMeshUpdated(mesh2);
6003 Swap(*mesh2,
false);
6006 GenerateNCFaceInfo();
6008 last_operation = Mesh::REFINE;
6013 Nodes->FESpace()->Update();
6020 MFEM_VERIFY(ncmesh,
"only supported for non-conforming meshes.");
6021 MFEM_VERIFY(!NURBSext,
"Derefinement of NURBS meshes is not supported. "
6022 "Project the NURBS to Nodes first.");
6024 ncmesh->Derefine(derefinements);
6027 ncmesh->OnMeshUpdated(mesh2);
6029 Swap(*mesh2,
false);
6032 GenerateNCFaceInfo();
6034 last_operation = Mesh::DEREFINE;
6039 Nodes->FESpace()->Update();
6045 double threshold,
int nc_limit,
int op)
6047 const Table &dt = ncmesh->GetDerefinementTable();
6052 ncmesh->CheckDerefinementNCLevel(dt, level_ok, nc_limit);
6056 for (
int i = 0; i < dt.
Size(); i++)
6058 if (nc_limit > 0 && !level_ok[i]) {
continue; }
6060 const int* fine = dt.
GetRow(i);
6064 for (
int j = 0; j < size; j++)
6066 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
6068 double err_fine = elem_error[fine[j]];
6071 case 0: error = std::min(error, err_fine);
break;
6072 case 1: error += err_fine;
break;
6073 case 2: error = std::max(error, err_fine);
break;
6077 if (error < threshold) { derefs.
Append(i); }
6082 DerefineMesh(derefs);
6090 int nc_limit,
int op)
6094 if (Nonconforming())
6096 return NonconformingDerefinement(elem_error, threshold, nc_limit, op);
6100 MFEM_ABORT(
"Derefinement is currently supported for non-conforming "
6106 bool Mesh::DerefineByError(
const Vector &elem_error,
double threshold,
6107 int nc_limit,
int op)
6110 for (
int i = 0; i < tmp.Size(); i++)
6112 tmp[i] = elem_error(i);
6114 return DerefineByError(tmp, threshold, nc_limit, op);
6118 void Mesh::InitFromNCMesh(
const NCMesh &ncmesh)
6127 case Geometry::TRIANGLE:
6128 case Geometry::SQUARE:
6129 BaseBdrGeom = Geometry::SEGMENT;
6131 case Geometry::CUBE:
6132 BaseBdrGeom = Geometry::SQUARE;
6142 NumOfVertices = vertices.Size();
6143 NumOfElements = elements.Size();
6144 NumOfBdrElements = boundary.Size();
6148 NumOfEdges = NumOfFaces = 0;
6152 el_to_edge =
new Table;
6153 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6157 GetElementToFaceTable();
6161 CheckBdrElementOrientation(
false);
6172 InitFromNCMesh(ncmesh);
6222 const int nv = Geometry::NumVerts[
geom];
6224 for (
int i = 0; i < elem_array.
Size(); i++)
6226 if (elem_array[i]->GetGeometryType() ==
geom)
6231 elem_vtx.
SetSize(nv*num_elems);
6235 for (
int i = 0; i < elem_array.
Size(); i++)
6241 elem_vtx.
Append(loc_vtx);
6246 void Mesh::UniformRefinement()
6250 NURBSUniformRefinement();
6252 else if (meshgen == 1 || ncmesh)
6255 for (
int i = 0; i < elem_to_refine.
Size(); i++)
6257 elem_to_refine[i] = i;
6264 LocalRefinement(elem_to_refine);
6268 GeneralRefinement(elem_to_refine, 1);
6273 QuadUniformRefinement();
6277 HexUniformRefinement();
6286 int nonconforming,
int nc_limit)
6288 if (Dim == 1 || (Dim == 3 && meshgen & 1))
6292 else if (nonconforming < 0)
6295 int geom = GetElementBaseGeometry();
6296 if (geom == Geometry::CUBE || geom == Geometry::SQUARE)
6306 if (nonconforming || ncmesh != NULL)
6309 NonconformingRefinement(refinements, nc_limit);
6314 for (
int i = 0; i < refinements.
Size(); i++)
6316 el_to_refine[i] = refinements[i].index;
6320 int type, rt = (refinements.
Size() ? refinements[0].ref_type : 7);
6321 if (rt == 1 || rt == 2 || rt == 4)
6325 else if (rt == 3 || rt == 5 || rt == 6)
6335 LocalRefinement(el_to_refine, type);
6339 void Mesh::GeneralRefinement(
const Array<int> &el_to_refine,
int nonconforming,
6343 for (
int i = 0; i < el_to_refine.
Size(); i++)
6345 refinements[i] =
Refinement(el_to_refine[i]);
6347 GeneralRefinement(refinements, nonconforming, nc_limit);
6350 void Mesh::EnsureNCMesh(
bool triangles_nonconforming)
6352 MFEM_VERIFY(!NURBSext,
"Cannot convert a NURBS mesh to an NC mesh. "
6353 "Project the NURBS to Nodes first.");
6357 if ((meshgen & 2) ||
6358 (triangles_nonconforming && BaseGeom == Geometry::TRIANGLE))
6360 ncmesh =
new NCMesh(
this);
6361 ncmesh->OnMeshUpdated(
this);
6362 GenerateNCFaceInfo();
6367 void Mesh::RandomRefinement(
double prob,
bool aniso,
int nonconforming,
6371 for (
int i = 0; i < GetNE(); i++)
6373 if ((
double) rand() / RAND_MAX < prob)
6378 type = (Dim == 3) ? (rand() % 7 + 1) : (rand() % 3 + 1);
6383 GeneralRefinement(refs, nonconforming, nc_limit);
6386 void Mesh::RefineAtVertex(
const Vertex& vert,
double eps,
int nonconforming)
6390 for (
int i = 0; i < GetNE(); i++)
6392 GetElementVertices(i, v);
6393 bool refine =
false;
6394 for (
int j = 0; j < v.
Size(); j++)
6397 for (
int l = 0; l < spaceDim; l++)
6399 double d = vert(l) - vertices[v[j]](l);
6402 if (dist <= eps*eps) { refine =
true;
break; }
6409 GeneralRefinement(refs, nonconforming);
6413 int nonconforming,
int nc_limit)
6415 MFEM_VERIFY(elem_error.
Size() == GetNE(),
"");
6417 for (
int i = 0; i < GetNE(); i++)
6419 if (elem_error[i] > threshold)
6424 if (ReduceInt(refs.Size()))
6426 GeneralRefinement(refs, nonconforming, nc_limit);
6432 bool Mesh::RefineByError(
const Vector &elem_error,
double threshold,
6433 int nonconforming,
int nc_limit)
6437 return RefineByError(tmp, threshold, nonconforming, nc_limit);
6441 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
6442 int *edge1,
int *edge2,
int *middle)
6445 int v[2][4], v_new, bisect, t;
6450 if (t == Element::TRIANGLE)
6457 bisect = v_to_v(vert[0], vert[1]);
6458 MFEM_ASSERT(bisect >= 0,
"");
6460 if (middle[bisect] == -1)
6462 v_new = NumOfVertices++;
6463 for (
int d = 0; d < spaceDim; d++)
6465 V(d) = 0.5 * (vertices[vert[0]](d) + vertices[vert[1]](d));
6471 if (edge1[bisect] == i)
6473 edge1[bisect] = edge2[bisect];
6476 middle[bisect] = v_new;
6480 v_new = middle[bisect];
6488 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6489 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6494 elements.Append(tri_new);
6503 int coarse = FindCoarseElement(i);
6504 CoarseFineTr.embeddings[i].parent = coarse;
6505 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6510 bisect = v_to_v(v[1][0], v[1][1]);
6511 MFEM_ASSERT(bisect >= 0,
"");
6513 if (edge1[bisect] == i)
6515 edge1[bisect] = NumOfElements;
6517 else if (edge2[bisect] == i)
6519 edge2[bisect] = NumOfElements;
6524 else if (t == Element::TETRAHEDRON)
6526 int j, type, new_type, old_redges[2], new_redges[2][2], flag;
6530 "TETRAHEDRON element is not marked for refinement.");
6535 bisect = v_to_v(vert[0], vert[1]);
6539 cerr <<
"Error in Bisection(...) of tetrahedron!" << endl
6540 <<
" redge[0] = " << old_redges[0]
6541 <<
" redge[1] = " << old_redges[1]
6542 <<
" type = " << type
6543 <<
" flag = " << flag << endl;
6547 if (middle[bisect] == -1)
6549 v_new = NumOfVertices++;
6550 for (j = 0; j < 3; j++)
6552 V(j) = 0.5 * (vertices[vert[0]](j) + vertices[vert[1]](j));
6556 middle[bisect] = v_new;
6560 v_new = middle[bisect];
6569 new_redges[0][0] = 2;
6570 new_redges[0][1] = 1;
6571 new_redges[1][0] = 2;
6572 new_redges[1][1] = 1;
6573 int tr1 = -1, tr2 = -1;
6574 switch (old_redges[0])
6577 v[0][0] = vert[0]; v[0][1] = vert[2]; v[0][2] = vert[3];
6578 if (type == Tetrahedron::TYPE_PF) { new_redges[0][1] = 4; }
6582 v[0][0] = vert[3]; v[0][1] = vert[0]; v[0][2] = vert[2];
6586 v[0][0] = vert[2]; v[0][1] = vert[3]; v[0][2] = vert[0];
6589 switch (old_redges[1])
6592 v[1][0] = vert[2]; v[1][1] = vert[1]; v[1][2] = vert[3];
6593 if (type == Tetrahedron::TYPE_PF) { new_redges[1][0] = 3; }
6597 v[1][0] = vert[1]; v[1][1] = vert[3]; v[1][2] = vert[2];
6601 v[1][0] = vert[3]; v[1][1] = vert[2]; v[1][2] = vert[1];
6608 #ifdef MFEM_USE_MEMALLOC
6616 elements.Append(tet2);
6622 int coarse = FindCoarseElement(i);
6623 CoarseFineTr.embeddings[i].parent = coarse;
6624 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6629 case Tetrahedron::TYPE_PU:
6630 new_type = Tetrahedron::TYPE_PF;
break;
6631 case Tetrahedron::TYPE_PF:
6632 new_type = Tetrahedron::TYPE_A;
break;
6634 new_type = Tetrahedron::TYPE_PU;
6644 MFEM_ABORT(
"Bisection for now works only for triangles & tetrahedra.");
6648 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
int *middle)
6651 int v[2][3], v_new, bisect, t;
6652 Element *bdr_el = boundary[i];
6655 if (t == Element::TRIANGLE)
6662 bisect = v_to_v(vert[0], vert[1]);
6663 MFEM_ASSERT(bisect >= 0,
"");
6664 v_new = middle[bisect];
6665 MFEM_ASSERT(v_new != -1,
"");
6669 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6670 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6680 MFEM_ABORT(
"Bisection of boundary elements works only for triangles!");
6684 void Mesh::UniformRefinement(
int i,
const DSTable &v_to_v,
6685 int *edge1,
int *edge2,
int *middle)
6688 int j, v1[3], v2[3], v3[3], v4[3], v_new[3], bisect[3];
6691 if (elements[i]->GetType() == Element::TRIANGLE)
6697 bisect[0] = v_to_v(v[0],v[1]);
6698 bisect[1] = v_to_v(v[1],v[2]);
6699 bisect[2] = v_to_v(v[0],v[2]);
6700 MFEM_ASSERT(bisect[0] >= 0 && bisect[1] >= 0 && bisect[2] >= 0,
"");
6702 for (j = 0; j < 3; j++)
6704 if (middle[bisect[j]] == -1)
6706 v_new[j] = NumOfVertices++;
6707 for (
int d = 0; d < spaceDim; d++)
6709 V(d) = (vertices[v[j]](d) + vertices[v[(j+1)%3]](d))/2.;
6715 if (edge1[bisect[j]] == i)
6717 edge1[bisect[j]] = edge2[bisect[j]];
6720 middle[bisect[j]] = v_new[j];
6724 v_new[j] = middle[bisect[j]];
6727 edge1[bisect[j]] = -1;
6733 v1[0] = v[0]; v1[1] = v_new[0]; v1[2] = v_new[2];
6734 v2[0] = v_new[0]; v2[1] = v[1]; v2[2] = v_new[1];
6735 v3[0] = v_new[2]; v3[1] = v_new[1]; v3[2] = v[2];
6736 v4[0] = v_new[1]; v4[1] = v_new[2]; v4[2] = v_new[0];
6742 elements.Append(tri1);
6743 elements.Append(tri2);
6744 elements.Append(tri3);
6751 tri2->ResetTransform(code);
6752 tri3->ResetTransform(code);
6756 tri2->PushTransform(1);
6757 tri3->PushTransform(2);
6760 int coarse = FindCoarseElement(i);
6761 CoarseFineTr.embeddings[i] =
Embedding(coarse);
6762 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6763 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6764 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6770 MFEM_ABORT(
"Uniform refinement for now works only for triangles.");
6774 void Mesh::InitRefinementTransforms()
6777 CoarseFineTr.point_matrices.SetSize(0, 0, 0);
6778 CoarseFineTr.embeddings.SetSize(NumOfElements);
6779 for (
int i = 0; i < NumOfElements; i++)
6781 elements[i]->ResetTransform(0);
6782 CoarseFineTr.embeddings[i] =
Embedding(i);
6786 int Mesh::FindCoarseElement(
int i)
6789 while ((coarse = CoarseFineTr.embeddings[i].parent) != i)
6798 MFEM_VERIFY(GetLastOperation() == Mesh::REFINE,
"");
6802 return ncmesh->GetRefinementTransforms();
6805 if (!CoarseFineTr.point_matrices.SizeK())
6807 if (BaseGeom == Geometry::TRIANGLE ||
6808 BaseGeom == Geometry::TETRAHEDRON)
6810 std::map<unsigned, int> mat_no;
6814 for (
int i = 0; i < elements.Size(); i++)
6817 unsigned code = elements[i]->GetTransform();
6820 int &matrix = mat_no[code];
6821 if (!matrix) { matrix = mat_no.size(); }
6824 CoarseFineTr.embeddings[i].matrix = index;
6828 pmats.
SetSize(Dim, Dim+1, mat_no.size());
6831 std::map<unsigned, int>::iterator it;
6832 for (it = mat_no.begin(); it != mat_no.end(); ++it)
6834 if (BaseGeom == Geometry::TRIANGLE)
6836 Triangle::GetPointMatrix(it->first, pmats(it->second-1));
6840 Tetrahedron::GetPointMatrix(it->first, pmats(it->second-1));
6846 MFEM_ABORT(
"Don't know how to construct CoarseFineTr.");
6851 return CoarseFineTr;
6854 void Mesh::PrintXG(std::ostream &out)
const
6856 MFEM_ASSERT(Dim==spaceDim,
"2D Manifold meshes not supported");
6865 out <<
"areamesh2\n\n";
6869 out <<
"curved_areamesh2\n\n";
6873 out << NumOfBdrElements <<
'\n';
6874 for (i = 0; i < NumOfBdrElements; i++)
6876 boundary[i]->GetVertices(v);
6878 out << boundary[i]->GetAttribute();
6879 for (j = 0; j < v.
Size(); j++)
6881 out <<
' ' << v[j] + 1;
6887 out << NumOfElements <<
'\n';
6888 for (i = 0; i < NumOfElements; i++)
6890 elements[i]->GetVertices(v);
6892 out << elements[i]->GetAttribute() <<
' ' << v.
Size();
6893 for (j = 0; j < v.
Size(); j++)
6895 out <<
' ' << v[j] + 1;
6903 out << NumOfVertices <<
'\n';
6904 for (i = 0; i < NumOfVertices; i++)
6906 out << vertices[i](0);
6907 for (j = 1; j < Dim; j++)
6909 out <<
' ' << vertices[i](j);
6916 out << NumOfVertices <<
'\n';
6924 mfem_error(
"Mesh::PrintXG(...) : Curved mesh in 3D");
6932 out <<
"NETGEN_Neutral_Format\n";
6934 out << NumOfVertices <<
'\n';
6935 for (i = 0; i < NumOfVertices; i++)
6937 for (j = 0; j < Dim; j++)
6939 out <<
' ' << vertices[i](j);
6945 out << NumOfElements <<
'\n';
6946 for (i = 0; i < NumOfElements; i++)
6948 nv = elements[i]->GetNVertices();
6949 ind = elements[i]->GetVertices();
6950 out << elements[i]->GetAttribute();
6951 for (j = 0; j < nv; j++)
6953 out <<
' ' << ind[j]+1;
6959 out << NumOfBdrElements <<
'\n';
6960 for (i = 0; i < NumOfBdrElements; i++)
6962 nv = boundary[i]->GetNVertices();
6963 ind = boundary[i]->GetVertices();
6964 out << boundary[i]->GetAttribute();
6965 for (j = 0; j < nv; j++)
6967 out <<
' ' << ind[j]+1;
6972 else if (meshgen == 2)
6978 <<
"1 " << NumOfVertices <<
" " << NumOfElements
6979 <<
" 0 0 0 0 0 0 0\n"
6980 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
6981 <<
"0 0 " << NumOfBdrElements <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
6982 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
6983 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
6985 for (i = 0; i < NumOfVertices; i++)
6986 out << i+1 <<
" 0.0 " << vertices[i](0) <<
' ' << vertices[i](1)
6987 <<
' ' << vertices[i](2) <<
" 0.0\n";
6989 for (i = 0; i < NumOfElements; i++)
6991 nv = elements[i]->GetNVertices();
6992 ind = elements[i]->GetVertices();
6993 out << i+1 <<
' ' << elements[i]->GetAttribute();
6994 for (j = 0; j < nv; j++)
6996 out <<
' ' << ind[j]+1;
7001 for (i = 0; i < NumOfBdrElements; i++)
7003 nv = boundary[i]->GetNVertices();
7004 ind = boundary[i]->GetVertices();
7005 out << boundary[i]->GetAttribute();
7006 for (j = 0; j < nv; j++)
7008 out <<
' ' << ind[j]+1;
7010 out <<
" 1.0 1.0 1.0 1.0\n";
7018 void Mesh::Printer(std::ostream &out, std::string section_delimiter)
const
7025 NURBSext->Print(out);
7036 out << (ncmesh ?
"MFEM mesh v1.1\n" :
7037 section_delimiter.empty() ?
"MFEM mesh v1.0\n" :
7038 "MFEM mesh v1.2\n");
7042 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7047 "# TETRAHEDRON = 4\n"
7051 out <<
"\ndimension\n" << Dim
7052 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7053 for (i = 0; i < NumOfElements; i++)
7055 PrintElement(elements[i], out);
7058 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
7059 for (i = 0; i < NumOfBdrElements; i++)
7061 PrintElement(boundary[i], out);
7066 out <<
"\nvertex_parents\n";
7067 ncmesh->PrintVertexParents(out);
7069 out <<
"\ncoarse_elements\n";
7070 ncmesh->PrintCoarseElements(out);
7073 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7076 out << spaceDim <<
'\n';
7077 for (i = 0; i < NumOfVertices; i++)
7079 out << vertices[i](0);
7080 for (j = 1; j < spaceDim; j++)
7082 out <<
' ' << vertices[i](j);
7094 if (!ncmesh && !section_delimiter.empty())
7096 out << section_delimiter << endl;
7100 void Mesh::PrintTopo(std::ostream &out,
const Array<int> &e_to_k)
const
7105 out <<
"MFEM NURBS mesh v1.0\n";
7109 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7115 out <<
"\ndimension\n" << Dim
7116 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7117 for (i = 0; i < NumOfElements; i++)
7119 PrintElement(elements[i], out);
7122 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
7123 for (i = 0; i < NumOfBdrElements; i++)
7125 PrintElement(boundary[i], out);
7128 out <<
"\nedges\n" << NumOfEdges <<
'\n';
7129 for (i = 0; i < NumOfEdges; i++)
7131 edge_vertex->GetRow(i, vert);
7137 out << ki <<
' ' << vert[0] <<
' ' << vert[1] <<
'\n';
7139 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7142 void Mesh::PrintVTK(std::ostream &out)
7145 "# vtk DataFile Version 3.0\n"
7146 "Generated by MFEM\n"
7148 "DATASET UNSTRUCTURED_GRID\n";
7152 out <<
"POINTS " << NumOfVertices <<
" double\n";
7153 for (
int i = 0; i < NumOfVertices; i++)
7155 out << vertices[i](0);
7157 for (j = 1; j < spaceDim; j++)
7159 out <<
' ' << vertices[i](j);
7171 out <<
"POINTS " << Nodes->FESpace()->GetNDofs() <<
" double\n";
7172 for (
int i = 0; i < Nodes->FESpace()->GetNDofs(); i++)
7176 Nodes->FESpace()->DofsToVDofs(vdofs);
7177 out << (*Nodes)(vdofs[0]);
7179 for (j = 1; j < spaceDim; j++)
7181 out <<
' ' << (*Nodes)(vdofs[j]);
7195 for (
int i = 0; i < NumOfElements; i++)
7197 size += elements[i]->GetNVertices() + 1;
7199 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
7200 for (
int i = 0; i < NumOfElements; i++)
7202 const int *v = elements[i]->GetVertices();
7203 const int nv = elements[i]->GetNVertices();
7205 for (
int j = 0; j < nv; j++)
7217 for (
int i = 0; i < NumOfElements; i++)
7219 Nodes->FESpace()->GetElementDofs(i, dofs);
7220 size += dofs.
Size() + 1;
7222 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
7223 const char *fec_name = Nodes->FESpace()->FEColl()->Name();
7224 if (!strcmp(fec_name,
"Linear") ||
7225 !strcmp(fec_name,
"H1_2D_P1") ||
7226 !strcmp(fec_name,
"H1_3D_P1"))
7230 else if (!strcmp(fec_name,
"Quadratic") ||
7231 !strcmp(fec_name,
"H1_2D_P2") ||
7232 !strcmp(fec_name,
"H1_3D_P2"))
7238 cerr <<
"Mesh::PrintVTK : can not save '"
7239 << fec_name <<
"' elements!" << endl;
7242 for (
int i = 0; i < NumOfElements; i++)
7244 Nodes->FESpace()->GetElementDofs(i, dofs);
7248 for (
int j = 0; j < dofs.
Size(); j++)
7250 out <<
' ' << dofs[j];
7253 else if (order == 2)
7255 const int *vtk_mfem;
7256 switch (elements[i]->GetGeometryType())
7258 case Geometry::TRIANGLE:
7259 case Geometry::SQUARE:
7260 vtk_mfem = vtk_quadratic_hex;
break;
7261 case Geometry::TETRAHEDRON:
7262 vtk_mfem = vtk_quadratic_tet;
break;
7263 case Geometry::CUBE:
7265 vtk_mfem = vtk_quadratic_hex;
break;
7267 for (
int j = 0; j < dofs.
Size(); j++)
7269 out <<
' ' << dofs[vtk_mfem[j]];
7276 out <<
"CELL_TYPES " << NumOfElements <<
'\n';
7277 for (
int i = 0; i < NumOfElements; i++)
7279 int vtk_cell_type = 5;
7282 switch (elements[i]->GetGeometryType())
7284 case Geometry::TRIANGLE: vtk_cell_type = 5;
break;
7285 case Geometry::SQUARE: vtk_cell_type = 9;
break;
7286 case Geometry::TETRAHEDRON: vtk_cell_type = 10;
break;
7287 case Geometry::CUBE: vtk_cell_type = 12;
break;
7290 else if (order == 2)
7292 switch (elements[i]->GetGeometryType())
7294 case Geometry::TRIANGLE: vtk_cell_type = 22;
break;
7295 case Geometry::SQUARE: vtk_cell_type = 28;
break;
7296 case Geometry::TETRAHEDRON: vtk_cell_type = 24;
break;
7297 case Geometry::CUBE: vtk_cell_type = 29;
break;
7301 out << vtk_cell_type <<
'\n';
7305 out <<
"CELL_DATA " << NumOfElements <<
'\n'
7306 <<
"SCALARS material int\n"
7307 <<
"LOOKUP_TABLE default\n";
7308 for (
int i = 0; i < NumOfElements; i++)
7310 out << elements[i]->GetAttribute() <<
'\n';
7315 void Mesh::PrintVTK(std::ostream &out,
int ref,
int field_data)
7322 "# vtk DataFile Version 3.0\n"
7323 "Generated by MFEM\n"
7325 "DATASET UNSTRUCTURED_GRID\n";
7330 out <<
"FIELD FieldData 1\n"
7331 <<
"MaterialIds " << 1 <<
" " << attributes.
Size() <<
" int\n";
7332 for (
int i = 0; i < attributes.Size(); i++)
7334 out <<
' ' << attributes[i];
7341 for (
int i = 0; i < GetNE(); i++)
7343 int geom = GetElementBaseGeometry(i);
7350 out <<
"POINTS " << np <<
" double\n";
7352 for (
int i = 0; i < GetNE(); i++)
7355 GetElementBaseGeometry(i), ref, 1);
7357 GetElementTransformation(i)->Transform(RefG->
RefPts, pmat);
7359 for (
int j = 0; j < pmat.
Width(); j++)
7361 out << pmat(0, j) <<
' ';
7364 out << pmat(1, j) <<
' ';
7376 out << 0.0 <<
' ' << 0.0;
7383 out <<
"CELLS " << nc <<
' ' << size <<
'\n';
7385 for (
int i = 0; i < GetNE(); i++)
7387 int geom = GetElementBaseGeometry(i);
7392 for (
int j = 0; j < RG.
Size(); )
7395 for (
int k = 0; k < nv; k++, j++)
7397 out <<
' ' << np + RG[j];
7403 out <<
"CELL_TYPES " << nc <<
'\n';
7404 for (
int i = 0; i < GetNE(); i++)
7406 int geom = GetElementBaseGeometry(i);
7410 int vtk_cell_type = 5;
7414 case Geometry::SEGMENT: vtk_cell_type = 3;
break;
7415 case Geometry::TRIANGLE: vtk_cell_type = 5;
break;
7416 case Geometry::SQUARE: vtk_cell_type = 9;
break;
7417 case Geometry::TETRAHEDRON: vtk_cell_type = 10;
break;
7418 case Geometry::CUBE: vtk_cell_type = 12;
break;
7421 for (
int j = 0; j < RG.
Size(); j += nv)
7423 out << vtk_cell_type <<
'\n';
7427 out <<
"CELL_DATA " << nc <<
'\n'
7428 <<
"SCALARS material int\n"
7429 <<
"LOOKUP_TABLE default\n";
7430 for (
int i = 0; i < GetNE(); i++)
7432 int geom = GetElementBaseGeometry(i);
7435 int attr = GetAttribute(i);
7438 out << attr <<
'\n';
7443 srand((
unsigned)time(0));
7444 double a = double(rand()) / (double(RAND_MAX) + 1.);
7445 int el0 = (int)floor(a * GetNE());
7446 GetElementColoring(coloring, el0);
7447 out <<
"SCALARS element_coloring int\n"
7448 <<
"LOOKUP_TABLE default\n";
7449 for (
int i = 0; i < GetNE(); i++)
7451 int geom = GetElementBaseGeometry(i);
7456 out << coloring[i] + 1 <<
'\n';
7460 out <<
"POINT_DATA " << np <<
'\n' << flush;
7465 int delete_el_to_el = (el_to_el) ? (0) : (1);
7466 const Table &el_el = ElementToElementTable();
7467 int num_el = GetNE(), stack_p, stack_top_p, max_num_col;
7470 const int *i_el_el = el_el.
GetI();
7471 const int *j_el_el = el_el.
GetJ();
7476 stack_p = stack_top_p = 0;
7477 for (
int el = el0; stack_top_p < num_el; el=(el+1)%num_el)
7479 if (colors[el] != -2)
7485 el_stack[stack_top_p++] = el;
7487 for ( ; stack_p < stack_top_p; stack_p++)
7489 int i = el_stack[stack_p];
7490 int num_nb = i_el_el[i+1] - i_el_el[i];
7491 if (max_num_col < num_nb + 1)
7493 max_num_col = num_nb + 1;
7495 for (
int j = i_el_el[i]; j < i_el_el[i+1]; j++)
7498 if (colors[k] == -2)
7501 el_stack[stack_top_p++] = k;
7509 for (stack_p = 0; stack_p < stack_top_p; stack_p++)
7511 int i = el_stack[stack_p], col;
7513 for (
int j = i_el_el[i]; j < i_el_el[i+1]; j++)
7515 col = colors[j_el_el[j]];
7518 col_marker[col] = 1;
7522 for (col = 0; col < max_num_col; col++)
7523 if (col_marker[col] == 0)
7531 if (delete_el_to_el)
7538 void Mesh::PrintWithPartitioning(
int *partitioning, std::ostream &out,
7539 int elem_attr)
const
7541 if (Dim != 3 && Dim != 2) {
return; }
7543 int i, j, k, l, nv, nbe, *v;
7545 out <<
"MFEM mesh v1.0\n";
7549 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7554 "# TETRAHEDRON = 4\n"
7558 out <<
"\ndimension\n" << Dim
7559 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7560 for (i = 0; i < NumOfElements; i++)
7562 out << int((elem_attr) ? partitioning[i]+1 : elements[i]->GetAttribute())
7563 <<
' ' << elements[i]->GetGeometryType();
7564 nv = elements[i]->GetNVertices();
7565 v = elements[i]->GetVertices();
7566 for (j = 0; j < nv; j++)
7573 for (i = 0; i < faces_info.Size(); i++)
7575 if ((l = faces_info[i].Elem2No) >= 0)
7577 k = partitioning[faces_info[i].Elem1No];
7578 l = partitioning[l];
7589 out <<
"\nboundary\n" << nbe <<
'\n';
7590 for (i = 0; i < faces_info.Size(); i++)
7592 if ((l = faces_info[i].Elem2No) >= 0)
7594 k = partitioning[faces_info[i].Elem1No];
7595 l = partitioning[l];
7598 nv = faces[i]->GetNVertices();
7599 v = faces[i]->GetVertices();
7600 out << k+1 <<
' ' << faces[i]->GetGeometryType();
7601 for (j = 0; j < nv; j++)
7606 out << l+1 <<
' ' << faces[i]->GetGeometryType();
7607 for (j = nv-1; j >= 0; j--)
7616 k = partitioning[faces_info[i].Elem1No];
7617 nv = faces[i]->GetNVertices();
7618 v = faces[i]->GetVertices();
7619 out << k+1 <<
' ' << faces[i]->GetGeometryType();
7620 for (j = 0; j < nv; j++)
7627 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7630 out << spaceDim <<
'\n';
7631 for (i = 0; i < NumOfVertices; i++)
7633 out << vertices[i](0);
7634 for (j = 1; j < spaceDim; j++)
7636 out <<
' ' << vertices[i](j);
7649 void Mesh::PrintElementsWithPartitioning(
int *partitioning,
7653 MFEM_ASSERT(Dim == spaceDim,
"2D Manifolds not supported\n");
7654 if (Dim != 3 && Dim != 2) {
return; }
7661 int *vcount =
new int[NumOfVertices];
7662 for (i = 0; i < NumOfVertices; i++)
7666 for (i = 0; i < NumOfElements; i++)
7668 nv = elements[i]->GetNVertices();
7669 ind = elements[i]->GetVertices();
7670 for (j = 0; j < nv; j++)
7676 int *voff =
new int[NumOfVertices+1];
7678 for (i = 1; i <= NumOfVertices; i++)
7680 voff[i] = vcount[i-1] + voff[i-1];
7683 int **vown =
new int*[NumOfVertices];
7684 for (i = 0; i < NumOfVertices; i++)
7686 vown[i] =
new int[vcount[i]];
7696 Transpose(ElementToEdgeTable(), edge_el);
7699 for (i = 0; i < NumOfElements; i++)
7701 nv = elements[i]->GetNVertices();
7702 ind = elements[i]->GetVertices();
7703 for (j = 0; j < nv; j++)
7706 vown[ind[j]][vcount[ind[j]]] = i;
7710 for (i = 0; i < NumOfVertices; i++)
7712 vcount[i] = voff[i+1] - voff[i];
7716 for (i = 0; i < edge_el.
Size(); i++)
7718 const int *el = edge_el.
GetRow(i);
7721 k = partitioning[el[0]];
7722 l = partitioning[el[1]];
7723 if (interior_faces || k != l)
7735 out <<
"areamesh2\n\n" << nbe <<
'\n';
7737 for (i = 0; i < edge_el.
Size(); i++)
7739 const int *el = edge_el.
GetRow(i);
7742 k = partitioning[el[0]];
7743 l = partitioning[el[1]];
7744 if (interior_faces || k != l)
7747 GetEdgeVertices(i,ev);
7749 for (j = 0; j < 2; j++)
7750 for (s = 0; s < vcount[ev[j]]; s++)
7751 if (vown[ev[j]][s] == el[0])
7753 out <<
' ' << voff[ev[j]]+s+1;
7757 for (j = 1; j >= 0; j--)
7758 for (s = 0; s < vcount[ev[j]]; s++)
7759 if (vown[ev[j]][s] == el[1])
7761 out <<
' ' << voff[ev[j]]+s+1;
7768 k = partitioning[el[0]];
7770 GetEdgeVertices(i,ev);
7772 for (j = 0; j < 2; j++)
7773 for (s = 0; s < vcount[ev[j]]; s++)
7774 if (vown[ev[j]][s] == el[0])
7776 out <<
' ' << voff[ev[j]]+s+1;
7783 out << NumOfElements <<
'\n';
7784 for (i = 0; i < NumOfElements; i++)
7786 nv = elements[i]->GetNVertices();
7787 ind = elements[i]->GetVertices();
7788 out << partitioning[i]+1 <<
' ';
7790 for (j = 0; j < nv; j++)
7792 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7793 vown[ind[j]][vcount[ind[j]]] = i;
7798 for (i = 0; i < NumOfVertices; i++)
7800 vcount[i] = voff[i+1] - voff[i];
7804 out << voff[NumOfVertices] <<
'\n';
7805 for (i = 0; i < NumOfVertices; i++)
7806 for (k = 0; k < vcount[i]; k++)
7808 for (j = 0; j < Dim; j++)
7810 out << vertices[i](j) <<
' ';
7821 out <<
"NETGEN_Neutral_Format\n";
7823 out << voff[NumOfVertices] <<
'\n';
7824 for (i = 0; i < NumOfVertices; i++)
7825 for (k = 0; k < vcount[i]; k++)
7827 for (j = 0; j < Dim; j++)
7829 out <<
' ' << vertices[i](j);
7835 out << NumOfElements <<
'\n';
7836 for (i = 0; i < NumOfElements; i++)
7838 nv = elements[i]->GetNVertices();
7839 ind = elements[i]->GetVertices();
7840 out << partitioning[i]+1;
7841 for (j = 0; j < nv; j++)
7843 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7844 vown[ind[j]][vcount[ind[j]]] = i;
7849 for (i = 0; i < NumOfVertices; i++)
7851 vcount[i] = voff[i+1] - voff[i];
7857 for (i = 0; i < NumOfFaces; i++)
7858 if ((l = faces_info[i].Elem2No) >= 0)
7860 k = partitioning[faces_info[i].Elem1No];
7861 l = partitioning[l];
7862 if (interior_faces || k != l)
7873 for (i = 0; i < NumOfFaces; i++)
7874 if ((l = faces_info[i].Elem2No) >= 0)
7876 k = partitioning[faces_info[i].Elem1No];
7877 l = partitioning[l];
7878 if (interior_faces || k != l)
7880 nv = faces[i]->GetNVertices();
7881 ind = faces[i]->GetVertices();
7883 for (j = 0; j < nv; j++)
7884 for (s = 0; s < vcount[ind[j]]; s++)
7885 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7887 out <<
' ' << voff[ind[j]]+s+1;
7891 for (j = nv-1; j >= 0; j--)
7892 for (s = 0; s < vcount[ind[j]]; s++)
7893 if (vown[ind[j]][s] == faces_info[i].Elem2No)
7895 out <<
' ' << voff[ind[j]]+s+1;
7902 k = partitioning[faces_info[i].Elem1No];
7903 nv = faces[i]->GetNVertices();
7904 ind = faces[i]->GetVertices();
7906 for (j = 0; j < nv; j++)
7907 for (s = 0; s < vcount[ind[j]]; s++)
7908 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7910 out <<
' ' << voff[ind[j]]+s+1;
7915 for (i = 0; i < NumOfVertices; i++)
7920 else if (meshgen == 2)
7925 for (i = 0; i < NumOfFaces; i++)
7926 if ((l = faces_info[i].Elem2No) >= 0)
7928 k = partitioning[faces_info[i].Elem1No];
7929 l = partitioning[l];
7930 if (interior_faces || k != l)
7942 <<
"1 " << voff[NumOfVertices] <<
" " << NumOfElements
7943 <<
" 0 0 0 0 0 0 0\n"
7944 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
7945 <<
"0 0 " << nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
7946 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
7947 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
7949 for (i = 0; i < NumOfVertices; i++)
7950 for (k = 0; k < vcount[i]; k++)
7951 out << voff[i]+k <<
" 0.0 " << vertices[i](0) <<
' '
7952 << vertices[i](1) <<
' ' << vertices[i](2) <<
" 0.0\n";
7954 for (i = 0; i < NumOfElements; i++)
7956 nv = elements[i]->GetNVertices();
7957 ind = elements[i]->GetVertices();
7958 out << i+1 <<
' ' << partitioning[i]+1;
7959 for (j = 0; j < nv; j++)
7961 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7962 vown[ind[j]][vcount[ind[j]]] = i;
7967 for (i = 0; i < NumOfVertices; i++)
7969 vcount[i] = voff[i+1] - voff[i];
7973 for (i = 0; i < NumOfFaces; i++)
7974 if ((l = faces_info[i].Elem2No) >= 0)
7976 k = partitioning[faces_info[i].Elem1No];
7977 l = partitioning[l];
7978 if (interior_faces || k != l)
7980 nv = faces[i]->GetNVertices();
7981 ind = faces[i]->GetVertices();
7983 for (j = 0; j < nv; j++)
7984 for (s = 0; s < vcount[ind[j]]; s++)
7985 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7987 out <<
' ' << voff[ind[j]]+s+1;
7989 out <<
" 1.0 1.0 1.0 1.0\n";
7991 for (j = nv-1; j >= 0; j--)
7992 for (s = 0; s < vcount[ind[j]]; s++)
7993 if (vown[ind[j]][s] == faces_info[i].Elem2No)
7995 out <<
' ' << voff[ind[j]]+s+1;
7997 out <<
" 1.0 1.0 1.0 1.0\n";
8002 k = partitioning[faces_info[i].Elem1No];
8003 nv = faces[i]->GetNVertices();
8004 ind = faces[i]->GetVertices();
8006 for (j = 0; j < nv; j++)
8007 for (s = 0; s < vcount[ind[j]]; s++)
8008 if (vown[ind[j]][s] == faces_info[i].Elem1No)
8010 out <<
' ' << voff[ind[j]]+s+1;
8012 out <<
" 1.0 1.0 1.0 1.0\n";
8023 void Mesh::PrintSurfaces(
const Table & Aface_face, std::ostream &out)
const
8030 " NURBS mesh is not supported!");
8034 out <<
"MFEM mesh v1.0\n";
8038 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
8043 "# TETRAHEDRON = 4\n"
8047 out <<
"\ndimension\n" << Dim
8048 <<
"\n\nelements\n" << NumOfElements <<
'\n';
8049 for (i = 0; i < NumOfElements; i++)
8051 PrintElement(elements[i], out);
8055 const int *
const i_AF_f = Aface_face.
GetI();
8056 const int *
const j_AF_f = Aface_face.
GetJ();
8058 for (
int iAF=0; iAF < Aface_face.
Size(); ++iAF)
8059 for (
const int * iface = j_AF_f + i_AF_f[iAF]; iface < j_AF_f + i_AF_f[iAF+1];
8062 out << iAF+1 <<
' ';
8063 PrintElementWithoutAttr(faces[*iface],out);
8066 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
8069 out << spaceDim <<
'\n';
8070 for (i = 0; i < NumOfVertices; i++)
8072 out << vertices[i](0);
8073 for (j = 1; j < spaceDim; j++)
8075 out <<
' ' << vertices[i](j);
8088 void Mesh::ScaleSubdomains(
double sf)
8093 int na = attributes.
Size();
8094 double *cg =
new double[na*spaceDim];
8095 int *nbea =
new int[na];
8097 int *vn =
new int[NumOfVertices];
8098 for (i = 0; i < NumOfVertices; i++)
8102 for (i = 0; i < na; i++)
8104 for (j = 0; j < spaceDim; j++)
8106 cg[i*spaceDim+j] = 0.0;
8111 for (i = 0; i < NumOfElements; i++)
8113 GetElementVertices(i, vert);
8114 for (k = 0; k < vert.
Size(); k++)
8120 for (i = 0; i < NumOfElements; i++)
8122 int bea = GetAttribute(i)-1;
8123 GetPointMatrix(i, pointmat);
8124 GetElementVertices(i, vert);
8126 for (k = 0; k < vert.
Size(); k++)
8127 if (vn[vert[k]] == 1)
8130 for (j = 0; j < spaceDim; j++)
8132 cg[bea*spaceDim+j] += pointmat(j,k);
8138 for (i = 0; i < NumOfElements; i++)
8140 int bea = GetAttribute(i)-1;
8141 GetElementVertices (i, vert);
8143 for (k = 0; k < vert.
Size(); k++)
8146 for (j = 0; j < spaceDim; j++)
8147 vertices[vert[k]](j) = sf*vertices[vert[k]](j) +
8148 (1-sf)*cg[bea*spaceDim+j]/nbea[bea];
8158 void Mesh::ScaleElements(
double sf)
8163 int na = NumOfElements;
8164 double *cg =
new double[na*spaceDim];
8165 int *nbea =
new int[na];
8167 int *vn =
new int[NumOfVertices];
8168 for (i = 0; i < NumOfVertices; i++)
8172 for (i = 0; i < na; i++)
8174 for (j = 0; j < spaceDim; j++)
8176 cg[i*spaceDim+j] = 0.0;
8181 for (i = 0; i < NumOfElements; i++)
8183 GetElementVertices(i, vert);
8184 for (k = 0; k < vert.
Size(); k++)
8190 for (i = 0; i < NumOfElements; i++)
8193 GetPointMatrix(i, pointmat);
8194 GetElementVertices(i, vert);
8196 for (k = 0; k < vert.
Size(); k++)
8197 if (vn[vert[k]] == 1)
8200 for (j = 0; j < spaceDim; j++)
8202 cg[bea*spaceDim+j] += pointmat(j,k);
8208 for (i = 0; i < NumOfElements; i++)
8211 GetElementVertices(i, vert);
8213 for (k = 0; k < vert.
Size(); k++)
8216 for (j = 0; j < spaceDim; j++)
8217 vertices[vert[k]](j) = sf*vertices[vert[k]](j) +
8218 (1-sf)*cg[bea*spaceDim+j]/nbea[bea];
8233 Vector vold(spaceDim), vnew(NULL, spaceDim);
8234 for (
int i = 0; i < vertices.Size(); i++)
8236 for (
int j = 0; j < spaceDim; j++)
8238 vold(j) = vertices[i](j);
8248 xnew.ProjectCoefficient(f_pert);
8255 MFEM_VERIFY(spaceDim == deformation.
GetVDim(),
8256 "incompatible vector dimensions");
8263 for (
int i = 0; i < NumOfVertices; i++)
8264 for (
int d = 0; d < spaceDim; d++)
8266 vertices[i](d) = xnew(d + spaceDim*i);
8277 void Mesh::RemoveUnusedVertices()
8279 if (NURBSext || ncmesh) {
return; }
8283 for (
int i = 0; i < GetNE(); i++)
8288 for (
int j = 0; j < nv; j++)
8293 for (
int i = 0; i < GetNBE(); i++)
8295 Element *el = GetBdrElement(i);
8298 for (
int j = 0; j < nv; j++)
8304 for (
int i = 0; i < v2v.
Size(); i++)
8308 vertices[num_vert] = vertices[i];
8309 v2v[i] = num_vert++;
8313 if (num_vert == v2v.
Size()) {
return; }
8320 for (
int i = 0; i < GetNE(); i++)
8322 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8327 for (
int i = 0; i < GetNE(); i++)
8329 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8330 Nodes->GetSubVector(vdofs, &nodes_by_element(s));
8334 vertices.SetSize(num_vert);
8335 NumOfVertices = num_vert;
8336 for (
int i = 0; i < GetNE(); i++)
8341 for (
int j = 0; j < nv; j++)
8346 for (
int i = 0; i < GetNBE(); i++)
8348 Element *el = GetBdrElement(i);
8351 for (
int j = 0; j < nv; j++)
8360 el_to_edge =
new Table;
8361 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
8366 GetElementToFaceTable();
8372 Nodes->FESpace()->Update();
8375 for (
int i = 0; i < GetNE(); i++)
8377 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8378 Nodes->SetSubVector(vdofs, &nodes_by_element(s));
8384 void Mesh::RemoveInternalBoundaries()
8386 if (NURBSext || ncmesh) {
return; }
8388 int num_bdr_elem = 0;
8389 int new_bel_to_edge_nnz = 0;
8390 for (
int i = 0; i < GetNBE(); i++)
8392 if (FaceIsInterior(GetBdrElementEdgeIndex(i)))
8394 FreeElement(boundary[i]);
8401 new_bel_to_edge_nnz += bel_to_edge->RowSize(i);
8406 if (num_bdr_elem == GetNBE()) {
return; }
8410 Table *new_bel_to_edge = NULL;
8414 new_be_to_edge.
Reserve(num_bdr_elem);
8418 new_be_to_face.
Reserve(num_bdr_elem);
8419 new_bel_to_edge =
new Table;
8420 new_bel_to_edge->
SetDims(num_bdr_elem, new_bel_to_edge_nnz);
8422 for (
int i = 0; i < GetNBE(); i++)
8424 if (!FaceIsInterior(GetBdrElementEdgeIndex(i)))
8426 new_boundary.
Append(boundary[i]);
8429 new_be_to_edge.
Append(be_to_edge[i]);
8433 int row = new_be_to_face.
Size();
8434 new_be_to_face.
Append(be_to_face[i]);
8435 int *e = bel_to_edge->GetRow(i);
8436 int ne = bel_to_edge->RowSize(i);
8437 int *new_e = new_bel_to_edge->
GetRow(row);
8438 for (
int j = 0; j < ne; j++)
8442 new_bel_to_edge->
GetI()[row+1] = new_bel_to_edge->
GetI()[row] + ne;
8447 NumOfBdrElements = new_boundary.
Size();
8458 bel_to_edge = new_bel_to_edge;
8462 for (
int i = 0; i < attribs.
Size(); i++)
8464 attribs[i] = GetBdrAttribute(i);
8468 bdr_attributes.DeleteAll();
8469 attribs.
Copy(bdr_attributes);
8474 #ifdef MFEM_USE_MEMALLOC
8477 if (E->
GetType() == Element::TETRAHEDRON)
8498 NodeExtrudeCoefficient::NodeExtrudeCoefficient(
const int dim,
const int _n,
8512 V(1) = s * ((ip.
y + layer) / n);
8517 V(2) = s * ((ip.
z + layer) / n);
8526 cerr <<
"Extrude1D : Not a 1D mesh!" << endl;
8530 int nvy = (closed) ? (ny) : (ny + 1);
8531 int nvt = mesh->
GetNV() * nvy;
8540 mesh2d =
new Mesh(2, nvt, mesh->
GetNE()*ny,
8545 for (
int i = 0; i < mesh->
GetNV(); i++)
8548 for (
int j = 0; j < nvy; j++)
8550 vc[1] = sy * (double(j) / ny);
8556 for (
int i = 0; i < mesh->
GetNE(); i++)
8561 for (
int j = 0; j < ny; j++)
8564 qv[0] = vert[0] * nvy + j;
8565 qv[1] = vert[1] * nvy + j;
8566 qv[2] = vert[1] * nvy + (j + 1) % nvy;
8567 qv[3] = vert[0] * nvy + (j + 1) % nvy;
8573 for (
int i = 0; i < mesh->
GetNBE(); i++)
8578 for (
int j = 0; j < ny; j++)
8581 sv[0] = vert[0] * nvy + j;
8582 sv[1] = vert[0] * nvy + (j + 1) % nvy;
8586 Swap<int>(sv[0], sv[1]);
8598 for (
int i = 0; i < mesh->
GetNE(); i++)
8604 sv[0] = vert[0] * nvy;
8605 sv[1] = vert[1] * nvy;
8609 sv[0] = vert[1] * nvy + ny;
8610 sv[1] = vert[0] * nvy + ny;
8626 string cname = name;
8627 if (cname ==
"Linear")
8631 else if (cname ==
"Quadratic")
8635 else if (cname ==
"Cubic")
8639 else if (!strncmp(name,
"H1_", 3))
8643 else if (!strncmp(name,
"L2_T", 4))
8647 else if (!strncmp(name,
"L2_", 3))
8654 cerr <<
"Extrude1D : The mesh uses unknown FE collection : "
8666 for (
int i = 0; i < mesh->
GetNE(); i++)
8669 for (
int j = ny-1; j >= 0; j--)
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
int Size() const
For backward compatibility define Size to be synonym of Width()
std::ostream & operator<<(std::ostream &out, const Mesh &mesh)
Ordering::Type GetOrdering() const
Return the ordering method.
int Size() const
Logical size of the array.
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
void Get(double *p, const int dim) const
int GetNDofs() const
Returns number of degrees of freedom.
Class for an integration rule - an Array of IntegrationPoint.
void UpdateOrder(int Order)
Change the order of the collection.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Class for grid function - Vector with associated FE space.
int DofToVDof(int dof, int vd, int ndofs=-1) const
virtual Element * Duplicate(Mesh *m) const =0
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void METIS_PartGraphRecursive(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
void AddColumnsInRow(int r, int ncol)
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
virtual void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
Array< Element * > boundary
void JacToPerfJac(int GeomType, const DenseMatrix &J, DenseMatrix &PJ) const
void SetSize(int s)
Resize the vector to size s.
int GetNBE() const
Returns number of boundary elements.
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
void MakeOwner(FiniteElementCollection *_fec)
Make the GridFunction the owner of 'fec' and 'fes'.
double Det() const
Calculates the determinant of the matrix (for 2x2 or 3x3 matrices)
int GetElementGeometry() const
Return the type of elements in the mesh.
Lists all edges/faces in the nonconforming mesh.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void SetDims(int rows, int nnz)
void Copy(Array ©) const
Create a copy of the current array.
RefinedGeometry * Refine(int Geom, int Times, int ETimes=1)
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
int Push(int r, int c, int f)
Piecewise-(bi)linear continuous finite elements.
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
Mesh * Extrude1D(Mesh *mesh, const int ny, const double sy, const bool closed)
Extrude a 1D mesh.
void Save(std::ostream &out, int fmt=0) const
Save the Array to the stream out using the format fmt. The format fmt can be:
void SetSize(int i, int j, int k)
int GetNE() const
Returns number of elements.
void GetElementLocalToGlobal(Array< int > &lelem_elem)
virtual void SetVertices(const int *ind)
Set the vertices according to the given input.
Data type quadrilateral element.
void AddBdrSegment(const int *vi, int attr=1)
const IntegrationPoint & GetCenter(int GeomType)
void GetVertexLocalToGlobal(Array< int > &lvert_vert)
NURBSExtension * GetNURBSext()
int Size_of_connections() const
const IntegrationRule * GetVertices(int GeomType)
void skip_comment_lines(std::istream &is, const char comment_char)
int GetGeometryType() const
void DeleteAll()
Delete whole array.
void AddConnections(int r, const int *c, int nc)
int master
master number (in Mesh numbering)
Array< NCFaceInfo > nc_faces_info
void AddVertex(const double *)
Piecewise-(bi)cubic continuous finite elements.
PointFiniteElement PointFE
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
Data type hexahedron element.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
void DetOfLinComb(const DenseMatrix &A, const DenseMatrix &B, Vector &c)
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int local
local number within 'element'
int Append(const T &el)
Append element to array, resize if necessary.
virtual void ResetTransform(int tr)
Set current coarse-fine transformation number.
void CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
std::vector< Master > masters
TriLinear3DFiniteElement HexahedronFE
void AddConnection(int r, int c)
int MeshGenerator()
Get the mesh generator/type.
Type
Constants for the classes derived from Element.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
virtual void GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
const int * GetDofMap(int GeomType) const
Get the Cartesian to local H1 dof map.
NURBSExtension * StealNURBSext()
const IntegrationRule & GetNodes() const
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
GeometryRefiner GlobGeometryRefiner
void SetLayer(const int l)
int GetAttribute() const
Return element's attribute.
Data type triangle element.
const Element * GetElement(int i) const
virtual void SetVertices(const int *ind)
Set the vertices according to the given input.
void Sort()
Sorts the array. This requires operator< to be defined for T.
int GetVDim()
Returns dimension of the vector.
void SetNodalFESpace(FiniteElementSpace *nfes)
virtual void ResetTransform(int tr)
Set current coarse-fine transformation number.
int Size() const
Returns the number of TYPE I elements.
int GetVDim() const
Returns vector dimension.
A class for non-conforming AMR on higher-order hexahedral, quadrilateral or triangular meshes...
FiniteElementSpace * FESpace()
void GetColumn(int c, Vector &col) const
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
virtual unsigned GetTransform() const
Return current coarse-fine transformation.
void FindPartitioningComponents(Table &elem_elem, const Array< int > &partitioning, Array< int > &component, Array< int > &num_comp)
Data type tetrahedron element.
int GetGeomType() const
Returns the Geometry::Type of the reference element.
int SpaceDimension() const
virtual unsigned GetTransform() const
Return current coarse-fine transformation.
double * Data() const
Returns the matrix data array.
void Swap(Array< T > &, Array< T > &)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
virtual void PushTransform(int tr)
Add 'tr' to the current chain of coarse-fine transformations.
int SpaceDimension() const
std::vector< Slave > slaves
int GetDof() const
Returns the number of degrees of freedom in the finite element.
void METIS_PartGraphKway(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
void AddAColumnInRow(int r)
void mfem_error(const char *msg)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
int FindRoots(const Vector &z, Vector &x)
void AddQuad(const int *vi, int attr=1)
int Push4(int r, int c, int f, int t)
Helper struct for defining a connectivity table, see Table::MakeFromList.
Linear3DFiniteElement TetrahedronFE
Array< Element * > elements
Linear2DFiniteElement TriangleFE
void METIS_PartGraphVKway(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
int GetElementBaseGeometry(int i=0) const
virtual int * DofOrderForOrientation(int GeomType, int Or) const =0
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
virtual void GetBdrElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom for i'th boundary element.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual const char * Name() const
Class for integration point with weight.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
void FinalizeQuadMesh(int generate_edges=0, int refine=0, bool fix_orientation=true)
Finalize the construction of a quadrilateral Mesh.
void FindTMax(Vector &c, Vector &x, double &tmax, const double factor, const int Dim)
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i'th element.
void GetMeshComponents(Array< mfem::Vertex > &vertices, Array< mfem::Element * > &elements, Array< mfem::Element * > &boundary) const
Return the basic Mesh arrays for the current finest level.
double CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
Array< FaceInfo > faces_info
virtual int GetNVertices() const =0
int parent
element index in the coarse mesh
void SetAttribute(const int attr)
Set element's attribute.
void ProjectCoefficient(Coefficient &coeff)
Piecewise-(bi)quadratic continuous finite elements.
NCMesh * ncmesh
Optional non-conforming mesh extension.
void filter_dos(std::string &line)
const FiniteElementCollection * FEColl() const
void GetNodes(Vector &node_coord) const
int NumberOfEntries() const
virtual void PushTransform(int tr)
Add 'tr' to the current chain of coarse-fine transformations.
Arbitrary order H1-conforming (continuous) finite elements.
void XYZ_VectorFunction(const Vector &p, Vector &v)
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
virtual int GetRefinementFlag()
virtual int DofForGeometry(int GeomType) const =0
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
BiLinear2DFiniteElement QuadrilateralFE
Rank 3 tensor (array of matrices)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Abstract data type element.
int GetAttribute(int i) const
Return the attribute of element i.
Data type line segment element.
Linear1DFiniteElement SegmentFE
int GetBdrElementBaseGeometry(int i=0) const
Array< int > attributes
A list of all unique element attributes used by the Mesh.
const Element * GetBdrElement(int i) const
virtual int GetType() const =0
Returns element's type.
DenseMatrix point_matrix
position within the master edge/face
Defines the position of a fine element within a coarse element.
int matrix
index into CoarseFineTransformations::point_matrices
Arbitrary order "L2-conforming" discontinuous finite elements.
virtual void Print(std::ostream &out=std::cout) const
Class used to extrude the nodes of a mesh.
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const