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";