15 #include "../fem/fem.hpp"
16 #include "../general/sort_pairs.hpp"
17 #include "../general/text.hpp"
30 #if defined(MFEM_USE_METIS) && defined(MFEM_USE_METIS_5)
45 int geom = GetElementBaseGeometry(i);
51 double Mesh::GetElementSize(
int i,
int type)
54 GetElementJacobian(i, J);
57 return pow(fabs(J.
Det()), 1./Dim);
69 double Mesh::GetElementSize(
int i,
const Vector &dir)
73 GetElementJacobian(i, J);
75 return sqrt((d_hat * d_hat) / (dir * dir));
78 double Mesh::GetElementVolume(
int i)
100 for (
int d = 0; d < spaceDim; d++)
102 min(d) = numeric_limits<double>::infinity();
103 max(d) = -numeric_limits<double>::infinity();
109 for (
int i = 0; i < NumOfVertices; i++)
111 coord = GetVertex(i);
112 for (
int d = 0; d < spaceDim; d++)
114 if (coord[d] < min(d)) { min(d) = coord[d]; }
115 if (coord[d] > max(d)) { max(d) = coord[d]; }
121 const bool use_boundary =
false;
122 int ne = use_boundary ? GetNBE() : GetNE();
130 for (
int i = 0; i < ne; i++)
134 GetBdrElementFace(i, &fn, &fo);
136 Tr = GetFaceElementTransformations(fn, 5);
143 T = GetElementTransformation(i);
147 for (
int j = 0; j < pointmat.
Width(); j++)
149 for (
int d = 0; d < pointmat.
Height(); d++)
151 if (pointmat(d,j) < min(d)) { min(d) = pointmat(d,j); }
152 if (pointmat(d,j) > max(d)) { max(d) = pointmat(d,j); }
159 void Mesh::GetCharacteristics(
double &h_min,
double &h_max,
160 double &kappa_min,
double &kappa_max,
168 sdim = SpaceDimension();
171 if (Vh) { Vh->
SetSize(NumOfElements); }
172 if (Vk) { Vk->
SetSize(NumOfElements); }
174 h_min = kappa_min = numeric_limits<double>::infinity();
175 h_max = kappa_max = -h_min;
176 for (i = 0; i < NumOfElements; i++)
178 GetElementJacobian(i, J);
179 h = pow(fabs(J.
Weight()), 1.0/
double(dim));
180 kappa = (dim == sdim) ?
182 if (Vh) { (*Vh)(i) = h; }
183 if (Vk) { (*Vk)(i) = kappa; }
185 if (h < h_min) { h_min = h; }
186 if (h > h_max) { h_max = h; }
187 if (kappa < kappa_min) { kappa_min =
kappa; }
188 if (kappa > kappa_max) { kappa_max =
kappa; }
194 double h_min, h_max, kappa_min, kappa_max;
196 out <<
"Mesh Characteristics:";
198 this->GetCharacteristics(h_min, h_max, kappa_min, kappa_max, Vh, Vk);
203 <<
"Number of vertices : " << GetNV() <<
'\n'
204 <<
"Number of elements : " << GetNE() <<
'\n'
205 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
206 <<
"h_min : " << h_min <<
'\n'
207 <<
"h_max : " << h_max <<
'\n';
212 <<
"Number of vertices : " << GetNV() <<
'\n'
213 <<
"Number of edges : " << GetNEdges() <<
'\n'
214 <<
"Number of elements : " << GetNE() <<
'\n'
215 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
216 <<
"Euler Number : " << EulerNumber2D() <<
'\n'
217 <<
"h_min : " << h_min <<
'\n'
218 <<
"h_max : " << h_max <<
'\n'
219 <<
"kappa_min : " << kappa_min <<
'\n'
220 <<
"kappa_max : " << kappa_max <<
'\n';
225 <<
"Number of vertices : " << GetNV() <<
'\n'
226 <<
"Number of edges : " << GetNEdges() <<
'\n'
227 <<
"Number of faces : " << GetNFaces() <<
'\n'
228 <<
"Number of elements : " << GetNE() <<
'\n'
229 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
230 <<
"Euler Number : " << EulerNumber() <<
'\n'
231 <<
"h_min : " << h_min <<
'\n'
232 <<
"h_max : " << h_max <<
'\n'
233 <<
"kappa_min : " << kappa_min <<
'\n'
234 <<
"kappa_max : " << kappa_max <<
'\n';
236 out <<
'\n' << std::flush;
243 case Element::POINT :
return &
PointFE;
244 case Element::SEGMENT :
return &
SegmentFE;
250 MFEM_ABORT(
"Unknown element type");
262 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
268 Nodes->FESpace()->GetElementVDofs(i, vdofs);
270 int n = vdofs.
Size()/spaceDim;
272 for (
int k = 0; k < spaceDim; k++)
274 for (
int j = 0; j < n; j++)
276 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
279 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
284 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
292 MFEM_ASSERT(nodes.
Size() == spaceDim*GetNV(),
"");
293 int nv = elements[i]->GetNVertices();
294 const int *v = elements[i]->GetVertices();
295 int n = vertices.
Size();
297 for (
int k = 0; k < spaceDim; k++)
299 for (
int j = 0; j < nv; j++)
301 pm(k, j) = nodes(k*n+v[j]);
304 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
308 MFEM_ASSERT(nodes.
Size() == Nodes->Size(),
"");
310 Nodes->FESpace()->GetElementVDofs(i, vdofs);
311 int n = vdofs.
Size()/spaceDim;
313 for (
int k = 0; k < spaceDim; k++)
315 for (
int j = 0; j < n; j++)
317 pm(k,j) = nodes(vdofs[n*k+j]);
320 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
327 GetElementTransformation(i, &Transformation);
329 return &Transformation;
334 GetBdrElementTransformation(i, &FaceTransformation);
335 return &FaceTransformation;
346 GetTransformationFEforElementType(GetBdrElementType(i)));
352 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
353 int n = vdofs.
Size()/spaceDim;
355 for (
int k = 0; k < spaceDim; k++)
357 for (
int j = 0; j < n; j++)
359 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
362 ElTr->
SetFE(Nodes->FESpace()->GetBE(i));
369 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
374 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
375 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
377 for (
int i = 0; i < spaceDim; i++)
379 for (
int j = 0; j < nv; j++)
381 pm(i, j) = vertices[v[j]](i);
384 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
388 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
392 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
393 int n = vdofs.
Size()/spaceDim;
395 for (
int i = 0; i < spaceDim; i++)
397 for (
int j = 0; j < n; j++)
399 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
406 FaceInfo &face_info = faces_info[FaceNo];
408 int face_geom = GetFaceGeometryType(FaceNo);
409 int face_type = GetFaceElementType(FaceNo);
411 GetLocalFaceTransformation(face_type,
412 GetElementType(face_info.
Elem1No),
413 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
416 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
420 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
422 Nodes->GetVectorValues(Transformation, eir, pm);
432 GetFaceTransformation(FaceNo, &FaceTransformation);
433 return &FaceTransformation;
440 GetFaceTransformation(EdgeNo, EdTr);
445 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
454 GetEdgeVertices(EdgeNo, v);
457 for (
int i = 0; i < spaceDim; i++)
459 for (
int j = 0; j < nv; j++)
461 pm(i, j) = vertices[v[j]](i);
464 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
468 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
472 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
473 int n = vdofs.
Size()/spaceDim;
475 for (
int i = 0; i < spaceDim; i++)
477 for (
int j = 0; j < n; j++)
479 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
482 EdTr->
SetFE(edge_el);
486 MFEM_ABORT(
"Not implemented.");
494 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
495 return &EdgeTransformation;
499 void Mesh::GetLocalPtToSegTransformation(
514 void Mesh::GetLocalSegToTriTransformation(
522 tv = tri_t::Edges[i/64];
523 so = seg_t::Orient[i%64];
526 for (
int j = 0; j < 2; j++)
528 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
529 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
534 void Mesh::GetLocalSegToQuadTransformation(
542 qv = quad_t::Edges[i/64];
543 so = seg_t::Orient[i%64];
546 for (
int j = 0; j < 2; j++)
548 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
549 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
554 void Mesh::GetLocalTriToTetTransformation(
561 const int *tv = tet_t::FaceVert[i/64];
564 const int *to = tri_t::Orient[i%64];
568 for (
int j = 0; j < 3; j++)
571 locpm(0, j) = vert.
x;
572 locpm(1, j) = vert.
y;
573 locpm(2, j) = vert.
z;
578 void Mesh::GetLocalQuadToHexTransformation(
585 const int *hv = hex_t::FaceVert[i/64];
587 const int *qo = quad_t::Orient[i%64];
590 for (
int j = 0; j < 4; j++)
593 locpm(0, j) = vert.
x;
594 locpm(1, j) = vert.
y;
595 locpm(2, j) = vert.
z;
600 void Mesh::GetLocalFaceTransformation(
606 GetLocalPtToSegTransformation(Transf, inf);
609 case Element::SEGMENT:
610 if (elem_type == Element::TRIANGLE)
612 GetLocalSegToTriTransformation(Transf, inf);
616 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
617 GetLocalSegToQuadTransformation(Transf, inf);
621 case Element::TRIANGLE:
622 MFEM_ASSERT(elem_type == Element::TETRAHEDRON,
"");
623 GetLocalTriToTetTransformation(Transf, inf);
626 case Element::QUADRILATERAL:
627 MFEM_ASSERT(elem_type == Element::HEXAHEDRON,
"");
628 GetLocalQuadToHexTransformation(Transf, inf);
636 FaceInfo &face_info = faces_info[FaceNo];
638 FaceElemTr.Elem1 = NULL;
639 FaceElemTr.Elem2 = NULL;
645 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
646 FaceElemTr.Elem1 = &Transformation;
652 FaceElemTr.Elem2No = face_info.
Elem2No;
653 if ((mask & 2) && FaceElemTr.Elem2No >= 0)
656 if (NURBSext && (mask & 1)) { MFEM_ABORT(
"NURBS mesh not supported!"); }
658 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
659 FaceElemTr.Elem2 = &Transformation2;
663 FaceElemTr.FaceGeom = GetFaceGeometryType(FaceNo);
664 FaceElemTr.Face = (mask & 16) ? GetFaceTransformation(FaceNo) : NULL;
667 int face_type = GetFaceElementType(FaceNo);
670 int elem_type = GetElementType(face_info.
Elem1No);
671 GetLocalFaceTransformation(face_type, elem_type,
672 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
674 if ((mask & 8) && FaceElemTr.Elem2No >= 0)
676 int elem_type = GetElementType(face_info.
Elem2No);
677 GetLocalFaceTransformation(face_type, elem_type,
678 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
681 if (Nonconforming() && IsSlaveFace(face_info))
683 ApplyLocalSlaveTransformation(FaceElemTr.Loc2.Transf, face_info);
685 if (face_type == Element::SEGMENT)
688 DenseMatrix &pm = FaceElemTr.Loc2.Transf.GetPointMat();
689 std::swap(pm(0,0), pm(0,1));
690 std::swap(pm(1,0), pm(1,1));
700 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
706 #ifdef MFEM_THREAD_SAFE
711 MFEM_ASSERT(fi.
NCFace >= 0,
"");
723 fn = be_to_face[BdrElemNo];
727 fn = be_to_edge[BdrElemNo];
731 fn = boundary[BdrElemNo]->GetVertices()[0];
734 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
738 tr = GetFaceElementTransformations(fn);
743 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
745 *Elem1 = faces_info[Face].
Elem1No;
746 *Elem2 = faces_info[Face].Elem2No;
749 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
751 *Inf1 = faces_info[Face].Elem1Inf;
752 *Inf2 = faces_info[Face].Elem2Inf;
755 int Mesh::GetFaceGeometryType(
int Face)
const
757 return (Dim == 1) ? Geometry::POINT : faces[Face]->GetGeometryType();
760 int Mesh::GetFaceElementType(
int Face)
const
762 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
770 NumOfElements = NumOfBdrElements = 0;
771 NumOfEdges = NumOfFaces = 0;
772 BaseGeom = BaseBdrGeom = -2;
779 last_operation = Mesh::NONE;
782 void Mesh::InitTables()
785 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
788 void Mesh::SetEmpty()
792 BaseGeom = BaseBdrGeom = -1;
800 void Mesh::DestroyTables()
815 void Mesh::DestroyPointers()
817 if (own_nodes) {
delete Nodes; }
823 for (
int i = 0; i < NumOfElements; i++)
825 FreeElement(elements[i]);
828 for (
int i = 0; i < NumOfBdrElements; i++)
830 FreeElement(boundary[i]);
833 for (
int i = 0; i < faces.Size(); i++)
835 FreeElement(faces[i]);
845 elements.DeleteAll();
846 vertices.DeleteAll();
847 boundary.DeleteAll();
849 faces_info.DeleteAll();
850 nc_faces_info.DeleteAll();
851 be_to_edge.DeleteAll();
852 be_to_face.DeleteAll();
859 CoarseFineTr.Clear();
861 #ifdef MFEM_USE_MEMALLOC
865 attributes.DeleteAll();
866 bdr_attributes.DeleteAll();
869 void Mesh::SetAttributes()
874 for (
int i = 0; i < attribs.
Size(); i++)
876 attribs[i] = GetBdrAttribute(i);
880 attribs.
Copy(bdr_attributes);
881 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
883 MFEM_WARNING(
"Non-positive attributes on the boundary!");
887 for (
int i = 0; i < attribs.
Size(); i++)
889 attribs[i] = GetAttribute(i);
893 attribs.
Copy(attributes);
894 if (attributes.Size() > 0 && attributes[0] <= 0)
896 MFEM_WARNING(
"Non-positive attributes in the domain!");
900 void Mesh::InitMesh(
int _Dim,
int _spaceDim,
int NVert,
int NElem,
int NBdrElem)
905 spaceDim = _spaceDim;
908 vertices.SetSize(NVert);
911 elements.SetSize(NElem);
913 NumOfBdrElements = 0;
914 boundary.SetSize(NBdrElem);
917 void Mesh::InitBaseGeom()
919 BaseGeom = BaseBdrGeom = -1;
920 for (
int i = 0; i < NumOfElements; i++)
922 int geom = elements[i]->GetGeometryType();
923 if (geom != BaseGeom && BaseGeom >= 0)
925 BaseGeom = -1;
break;
929 for (
int i = 0; i < NumOfBdrElements; i++)
931 int geom = boundary[i]->GetGeometryType();
932 if (geom != BaseBdrGeom && BaseBdrGeom >= 0)
934 BaseBdrGeom = -1;
break;
940 void Mesh::AddVertex(
const double *x)
942 double *y = vertices[NumOfVertices]();
944 for (
int i = 0; i < spaceDim; i++)
951 void Mesh::AddTri(
const int *vi,
int attr)
953 elements[NumOfElements++] =
new Triangle(vi, attr);
956 void Mesh::AddTriangle(
const int *vi,
int attr)
958 elements[NumOfElements++] =
new Triangle(vi, attr);
961 void Mesh::AddQuad(
const int *vi,
int attr)
966 void Mesh::AddTet(
const int *vi,
int attr)
968 #ifdef MFEM_USE_MEMALLOC
970 tet = TetMemory.Alloc();
973 elements[NumOfElements++] = tet;
975 elements[NumOfElements++] =
new Tetrahedron(vi, attr);
979 void Mesh::AddHex(
const int *vi,
int attr)
981 elements[NumOfElements++] =
new Hexahedron(vi, attr);
984 void Mesh::AddHexAsTets(
const int *vi,
int attr)
986 static const int hex_to_tet[6][4] =
988 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
989 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
993 for (
int i = 0; i < 6; i++)
995 for (
int j = 0; j < 4; j++)
997 ti[j] = vi[hex_to_tet[i][j]];
1003 void Mesh::AddBdrSegment(
const int *vi,
int attr)
1005 boundary[NumOfBdrElements++] =
new Segment(vi, attr);
1008 void Mesh::AddBdrTriangle(
const int *vi,
int attr)
1010 boundary[NumOfBdrElements++] =
new Triangle(vi, attr);
1013 void Mesh::AddBdrQuad(
const int *vi,
int attr)
1018 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1020 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1023 for (
int i = 0; i < 2; i++)
1025 for (
int j = 0; j < 3; j++)
1027 ti[j] = vi[quad_to_tri[i][j]];
1029 AddBdrTriangle(ti, attr);
1033 void Mesh::GenerateBoundaryElements()
1036 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1040 for (i = 0; i < boundary.Size(); i++)
1042 FreeElement(boundary[i]);
1052 NumOfBdrElements = 0;
1053 for (i = 0; i < faces_info.Size(); i++)
1055 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1058 boundary.SetSize(NumOfBdrElements);
1059 be2face.
SetSize(NumOfBdrElements);
1060 for (j = i = 0; i < faces_info.Size(); i++)
1062 if (faces_info[i].Elem2No < 0)
1064 boundary[j] = faces[i]->Duplicate(
this);
1071 void Mesh::FinalizeCheck()
1073 MFEM_VERIFY(vertices.Size() == NumOfVertices,
1074 "incorrect number of vertices: preallocated: " << vertices.Size()
1075 <<
", actually added: " << NumOfVertices);
1076 MFEM_VERIFY(elements.Size() == NumOfElements,
1077 "incorrect number of elements: preallocated: " << elements.Size()
1078 <<
", actually added: " << NumOfElements);
1079 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1080 "incorrect number of boundary elements: preallocated: "
1081 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1084 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1087 CheckElementOrientation(fix_orientation);
1091 MarkTriMeshForRefinement();
1096 el_to_edge =
new Table;
1097 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1099 CheckBdrElementOrientation();
1110 BaseGeom = Geometry::TRIANGLE;
1111 BaseBdrGeom = Geometry::SEGMENT;
1116 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1117 bool fix_orientation)
1120 if (fix_orientation)
1122 CheckElementOrientation(fix_orientation);
1127 el_to_edge =
new Table;
1128 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1130 CheckBdrElementOrientation();
1141 BaseGeom = Geometry::SQUARE;
1142 BaseBdrGeom = Geometry::SEGMENT;
1148 #ifdef MFEM_USE_GECKO
1154 Gecko::Functional *functional =
1155 new Gecko::FunctionalGeometric();
1156 unsigned int iterations = 1;
1157 unsigned int window = 2;
1158 unsigned int period = 1;
1159 unsigned int seed = 0;
1162 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1169 const Table &my_el_to_el = ElementToElementTable();
1170 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1172 const int *neighid = my_el_to_el.
GetRow(elemid);
1173 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
1175 graph.insert(elemid + 1, neighid[i] + 1);
1180 graph.order(functional, iterations, window, period, seed);
1183 Gecko::Node::Index NE = GetNE();
1184 for (Gecko::Node::Index gnodeid = 1; gnodeid <= NE; ++gnodeid)
1186 ordering[gnodeid - 1] = graph.rank(gnodeid);
1194 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
1198 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
1203 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
1207 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
1236 old_elem_node_vals.SetSize(GetNE());
1237 nodes_fes = Nodes->FESpace();
1240 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1242 nodes_fes->GetElementVDofs(old_elid, old_dofs);
1244 old_elem_node_vals[old_elid] =
new Vector(vals);
1250 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
1252 int new_elid = ordering[old_elid];
1253 new_elements[new_elid] = elements[old_elid];
1258 if (reorder_vertices)
1263 vertex_ordering = -1;
1265 int new_vertex_ind = 0;
1266 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1268 int *elem_vert = elements[new_elid]->GetVertices();
1269 int nv = elements[new_elid]->GetNVertices();
1270 for (
int vi = 0; vi < nv; ++vi)
1272 int old_vertex_ind = elem_vert[vi];
1273 if (vertex_ordering[old_vertex_ind] == -1)
1275 vertex_ordering[old_vertex_ind] = new_vertex_ind;
1276 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
1286 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1288 int *elem_vert = elements[new_elid]->GetVertices();
1289 int nv = elements[new_elid]->GetNVertices();
1290 for (
int vi = 0; vi < nv; ++vi)
1292 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
1297 for (
int belid = 0; belid < GetNBE(); ++belid)
1299 int *be_vert = boundary[belid]->GetVertices();
1300 int nv = boundary[belid]->GetNVertices();
1301 for (
int vi = 0; vi < nv; ++vi)
1303 be_vert[vi] = vertex_ordering[be_vert[vi]];
1314 el_to_edge =
new Table;
1315 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1320 GetElementToFaceTable();
1328 nodes_fes->Update();
1330 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1332 int new_elid = ordering[old_elid];
1333 nodes_fes->GetElementVDofs(new_elid, new_dofs);
1334 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
1335 delete old_elem_node_vals[old_elid];
1341 void Mesh::MarkForRefinement()
1347 MarkTriMeshForRefinement();
1351 DSTable v_to_v(NumOfVertices);
1352 GetVertexToVertexTable(v_to_v);
1353 MarkTetMeshForRefinement(v_to_v);
1358 void Mesh::MarkTriMeshForRefinement()
1363 for (
int i = 0; i < NumOfElements; i++)
1365 if (elements[i]->GetType() == Element::TRIANGLE)
1367 GetPointMatrix(i, pmat);
1368 elements[i]->MarkEdge(pmat);
1379 for (
int i = 0; i < NumOfVertices; i++)
1384 length_idx[j].one = GetLength(i, it.Column());
1385 length_idx[j].two = j;
1392 for (
int i = 0; i < NumOfEdges; i++)
1394 order[length_idx[i].two] = i;
1398 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
1403 GetEdgeOrdering(v_to_v, order);
1405 for (
int i = 0; i < NumOfElements; i++)
1407 if (elements[i]->GetType() == Element::TETRAHEDRON)
1409 elements[i]->MarkEdge(v_to_v, order);
1412 for (
int i = 0; i < NumOfBdrElements; i++)
1414 if (boundary[i]->GetType() == Element::TRIANGLE)
1416 boundary[i]->MarkEdge(v_to_v, order);
1423 if (*old_v_to_v && *old_elem_vert)
1431 if (*old_v_to_v == NULL)
1434 if (num_edge_dofs > 0)
1436 *old_v_to_v =
new DSTable(NumOfVertices);
1437 GetVertexToVertexTable(*(*old_v_to_v));
1440 if (*old_elem_vert == NULL)
1443 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1444 if (num_elem_dofs > 1)
1446 *old_elem_vert =
new Table;
1447 (*old_elem_vert)->
MakeI(GetNE());
1448 for (
int i = 0; i < GetNE(); i++)
1450 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
1452 (*old_elem_vert)->MakeJ();
1453 for (
int i = 0; i < GetNE(); i++)
1455 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
1456 elements[i]->GetNVertices());
1458 (*old_elem_vert)->ShiftUpI();
1472 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1488 if (num_edge_dofs > 0)
1490 DSTable new_v_to_v(NumOfVertices);
1491 GetVertexToVertexTable(new_v_to_v);
1493 for (
int i = 0; i < NumOfVertices; i++)
1497 int old_i = (*old_v_to_v)(i, it.Column());
1498 int new_i = it.Index();
1505 old_dofs.
SetSize(num_edge_dofs);
1506 new_dofs.
SetSize(num_edge_dofs);
1507 for (
int j = 0; j < num_edge_dofs; j++)
1509 old_dofs[j] = offset + old_i * num_edge_dofs + j;
1510 new_dofs[j] = offset + new_i * num_edge_dofs + j;
1514 for (
int j = 0; j < old_dofs.
Size(); j++)
1516 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1520 offset += NumOfEdges * num_edge_dofs;
1523 mfem::out <<
"Mesh::DoNodeReorder : redges = " << redges << endl;
1528 if (num_face_dofs > 0)
1531 Table old_face_vertex;
1532 old_face_vertex.
MakeI(NumOfFaces);
1533 for (
int i = 0; i < NumOfFaces; i++)
1537 old_face_vertex.
MakeJ();
1538 for (
int i = 0; i < NumOfFaces; i++)
1540 faces[i]->GetNVertices());
1544 STable3D *faces_tbl = GetElementToFaceTable(1);
1548 for (
int i = 0; i < NumOfFaces; i++)
1550 int *old_v = old_face_vertex.
GetRow(i), *new_v;
1551 int new_i, new_or, *dof_ord;
1552 switch (old_face_vertex.
RowSize(i))
1555 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
1556 new_v = faces[new_i]->GetVertices();
1557 new_or = GetTriOrientation(old_v, new_v);
1562 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
1563 new_v = faces[new_i]->GetVertices();
1564 new_or = GetQuadOrientation(old_v, new_v);
1569 old_dofs.
SetSize(num_face_dofs);
1570 new_dofs.
SetSize(num_face_dofs);
1571 for (
int j = 0; j < num_face_dofs; j++)
1573 old_dofs[j] = offset + i * num_face_dofs + j;
1574 new_dofs[j] = offset + new_i * num_face_dofs + dof_ord[j];
1580 for (
int j = 0; j < old_dofs.
Size(); j++)
1582 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1586 offset += NumOfFaces * num_face_dofs;
1592 if (num_elem_dofs > 1)
1604 for (
int i = 0; i < GetNE(); i++)
1606 int *old_v = old_elem_vert->
GetRow(i);
1607 int *new_v = elements[i]->GetVertices();
1608 int new_or, *dof_ord;
1609 int geom = elements[i]->GetGeometryType();
1612 case Geometry::SEGMENT:
1613 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
1615 case Geometry::TRIANGLE:
1616 new_or = GetTriOrientation(old_v, new_v);
1618 case Geometry::SQUARE:
1619 new_or = GetQuadOrientation(old_v, new_v);
1623 mfem::err <<
"Mesh::DoNodeReorder : " << Geometry::Name[
geom]
1624 <<
" elements (" << fec->
Name()
1625 <<
" FE collection) are not supported yet!" << endl;
1630 if (dof_ord == NULL)
1632 mfem::err <<
"Mesh::DoNodeReorder : FE collection '" << fec->
Name()
1633 <<
"' does not define reordering for " << Geometry::Name[
geom]
1634 <<
" elements!" << endl;
1637 old_dofs.
SetSize(num_elem_dofs);
1638 new_dofs.
SetSize(num_elem_dofs);
1639 for (
int j = 0; j < num_elem_dofs; j++)
1642 old_dofs[j] = offset + dof_ord[j];
1643 new_dofs[j] = offset + j;
1647 for (
int j = 0; j < old_dofs.
Size(); j++)
1649 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1652 offset += num_elem_dofs;
1659 if (num_face_dofs == 0)
1663 GetElementToFaceTable();
1666 CheckBdrElementOrientation();
1671 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1676 CheckBdrElementOrientation();
1679 Nodes->FESpace()->RebuildElementToDofTable();
1682 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
1685 CheckElementOrientation(fix_orientation);
1687 if (NumOfBdrElements == 0)
1689 GetElementToFaceTable();
1691 GenerateBoundaryElements();
1696 DSTable v_to_v(NumOfVertices);
1697 GetVertexToVertexTable(v_to_v);
1698 MarkTetMeshForRefinement(v_to_v);
1701 GetElementToFaceTable();
1704 CheckBdrElementOrientation();
1706 if (generate_edges == 1)
1708 el_to_edge =
new Table;
1709 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1720 BaseGeom = Geometry::TETRAHEDRON;
1721 BaseBdrGeom = Geometry::TRIANGLE;
1726 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
1729 CheckElementOrientation(fix_orientation);
1731 GetElementToFaceTable();
1734 if (NumOfBdrElements == 0)
1736 GenerateBoundaryElements();
1739 CheckBdrElementOrientation();
1743 el_to_edge =
new Table;
1744 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1753 BaseGeom = Geometry::CUBE;
1754 BaseBdrGeom = Geometry::SQUARE;
1759 void Mesh::FinalizeTopology()
1771 bool generate_edges =
true;
1773 if (spaceDim == 0) { spaceDim = Dim; }
1774 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
1781 if (NumOfBdrElements == 0 && Dim > 2)
1784 GetElementToFaceTable();
1786 GenerateBoundaryElements();
1796 GetElementToFaceTable();
1805 if (Dim > 1 && generate_edges)
1808 if (!el_to_edge) { el_to_edge =
new Table; }
1809 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1813 if (NumOfBdrElements == 0)
1815 GenerateBoundaryElements();
1827 ncmesh->OnMeshUpdated(
this);
1830 GenerateNCFaceInfo();
1837 void Mesh::Finalize(
bool refine,
bool fix_orientation)
1839 if (NURBSext || ncmesh)
1841 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
1842 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
1851 const bool check_orientation =
true;
1852 const bool curved = (Nodes != NULL);
1853 const bool may_change_topology =
1854 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
1855 ( check_orientation && fix_orientation &&
1856 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
1859 Table *old_elem_vert = NULL;
1861 if (curved && may_change_topology)
1863 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
1866 if (check_orientation)
1869 CheckElementOrientation(fix_orientation);
1873 MarkForRefinement();
1876 if (may_change_topology)
1880 DoNodeReorder(old_v_to_v, old_elem_vert);
1881 delete old_elem_vert;
1894 CheckBdrElementOrientation();
1898 int generate_edges,
double sx,
double sy,
double sz)
1902 int NVert, NElem, NBdrElem;
1904 NVert = (nx+1) * (ny+1) * (nz+1);
1905 NElem = nx * ny * nz;
1906 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
1907 if (type == Element::TETRAHEDRON)
1913 InitMesh(3, 3, NVert, NElem, NBdrElem);
1919 for (z = 0; z <= nz; z++)
1921 coord[2] = ((double) z / nz) * sz;
1922 for (y = 0; y <= ny; y++)
1924 coord[1] = ((double) y / ny) * sy;
1925 for (x = 0; x <= nx; x++)
1927 coord[0] = ((double) x / nx) * sx;
1933 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
1936 for (z = 0; z < nz; z++)
1938 for (y = 0; y < ny; y++)
1940 for (x = 0; x < nx; x++)
1942 ind[0] = VTX(x , y , z );
1943 ind[1] = VTX(x+1, y , z );
1944 ind[2] = VTX(x+1, y+1, z );
1945 ind[3] = VTX(x , y+1, z );
1946 ind[4] = VTX(x , y , z+1);
1947 ind[5] = VTX(x+1, y , z+1);
1948 ind[6] = VTX(x+1, y+1, z+1);
1949 ind[7] = VTX(x , y+1, z+1);
1950 if (type == Element::TETRAHEDRON)
1952 AddHexAsTets(ind, 1);
1964 for (y = 0; y < ny; y++)
1965 for (x = 0; x < nx; x++)
1967 ind[0] = VTX(x , y , 0);
1968 ind[1] = VTX(x , y+1, 0);
1969 ind[2] = VTX(x+1, y+1, 0);
1970 ind[3] = VTX(x+1, y , 0);
1971 if (type == Element::TETRAHEDRON)
1973 AddBdrQuadAsTriangles(ind, 1);
1981 for (y = 0; y < ny; y++)
1982 for (x = 0; x < nx; x++)
1984 ind[0] = VTX(x , y , nz);
1985 ind[1] = VTX(x+1, y , nz);
1986 ind[2] = VTX(x+1, y+1, nz);
1987 ind[3] = VTX(x , y+1, nz);
1988 if (type == Element::TETRAHEDRON)
1990 AddBdrQuadAsTriangles(ind, 6);
1998 for (z = 0; z < nz; z++)
1999 for (y = 0; y < ny; y++)
2001 ind[0] = VTX(0 , y , z );
2002 ind[1] = VTX(0 , y , z+1);
2003 ind[2] = VTX(0 , y+1, z+1);
2004 ind[3] = VTX(0 , y+1, z );
2005 if (type == Element::TETRAHEDRON)
2007 AddBdrQuadAsTriangles(ind, 5);
2015 for (z = 0; z < nz; z++)
2016 for (y = 0; y < ny; y++)
2018 ind[0] = VTX(nx, y , z );
2019 ind[1] = VTX(nx, y+1, z );
2020 ind[2] = VTX(nx, y+1, z+1);
2021 ind[3] = VTX(nx, y , z+1);
2022 if (type == Element::TETRAHEDRON)
2024 AddBdrQuadAsTriangles(ind, 3);
2032 for (x = 0; x < nx; x++)
2033 for (z = 0; z < nz; z++)
2035 ind[0] = VTX(x , 0, z );
2036 ind[1] = VTX(x+1, 0, z );
2037 ind[2] = VTX(x+1, 0, z+1);
2038 ind[3] = VTX(x , 0, z+1);
2039 if (type == Element::TETRAHEDRON)
2041 AddBdrQuadAsTriangles(ind, 2);
2049 for (x = 0; x < nx; x++)
2050 for (z = 0; z < nz; z++)
2052 ind[0] = VTX(x , ny, z );
2053 ind[1] = VTX(x , ny, z+1);
2054 ind[2] = VTX(x+1, ny, z+1);
2055 ind[3] = VTX(x+1, ny, z );
2056 if (type == Element::TETRAHEDRON)
2058 AddBdrQuadAsTriangles(ind, 4);
2067 ofstream test_stream(
"debug.mesh");
2069 test_stream.close();
2073 bool fix_orientation =
true;
2075 if (type == Element::TETRAHEDRON)
2077 FinalizeTetMesh(generate_edges, refine, fix_orientation);
2081 FinalizeHexMesh(generate_edges, refine, fix_orientation);
2086 double sx,
double sy)
2095 if (type == Element::QUADRILATERAL)
2098 NumOfVertices = (nx+1) * (ny+1);
2099 NumOfElements = nx * ny;
2100 NumOfBdrElements = 2 * nx + 2 * ny;
2101 BaseGeom = Geometry::SQUARE;
2102 BaseBdrGeom = Geometry::SEGMENT;
2104 vertices.SetSize(NumOfVertices);
2105 elements.SetSize(NumOfElements);
2106 boundary.SetSize(NumOfBdrElements);
2113 for (j = 0; j < ny+1; j++)
2115 cy = ((double) j / ny) * sy;
2116 for (i = 0; i < nx+1; i++)
2118 cx = ((double) i / nx) * sx;
2119 vertices[k](0) = cx;
2120 vertices[k](1) = cy;
2127 for (j = 0; j < ny; j++)
2129 for (i = 0; i < nx; i++)
2131 ind[0] = i + j*(nx+1);
2132 ind[1] = i + 1 +j*(nx+1);
2133 ind[2] = i + 1 + (j+1)*(nx+1);
2134 ind[3] = i + (j+1)*(nx+1);
2142 for (i = 0; i < nx; i++)
2144 boundary[i] =
new Segment(i, i+1, 1);
2145 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2148 for (j = 0; j < ny; j++)
2150 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2151 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2155 else if (type == Element::TRIANGLE)
2158 NumOfVertices = (nx+1) * (ny+1);
2159 NumOfElements = 2 * nx * ny;
2160 NumOfBdrElements = 2 * nx + 2 * ny;
2161 BaseGeom = Geometry::TRIANGLE;
2162 BaseBdrGeom = Geometry::SEGMENT;
2164 vertices.SetSize(NumOfVertices);
2165 elements.SetSize(NumOfElements);
2166 boundary.SetSize(NumOfBdrElements);
2173 for (j = 0; j < ny+1; j++)
2175 cy = ((double) j / ny) * sy;
2176 for (i = 0; i < nx+1; i++)
2178 cx = ((double) i / nx) * sx;
2179 vertices[k](0) = cx;
2180 vertices[k](1) = cy;
2187 for (j = 0; j < ny; j++)
2189 for (i = 0; i < nx; i++)
2191 ind[0] = i + j*(nx+1);
2192 ind[1] = i + 1 + (j+1)*(nx+1);
2193 ind[2] = i + (j+1)*(nx+1);
2196 ind[1] = i + 1 + j*(nx+1);
2197 ind[2] = i + 1 + (j+1)*(nx+1);
2205 for (i = 0; i < nx; i++)
2207 boundary[i] =
new Segment(i, i+1, 1);
2208 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2211 for (j = 0; j < ny; j++)
2213 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2214 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2217 MarkTriMeshForRefinement();
2221 MFEM_ABORT(
"Unsupported element type.");
2224 CheckElementOrientation();
2226 if (generate_edges == 1)
2228 el_to_edge =
new Table;
2229 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2231 CheckBdrElementOrientation();
2240 attributes.Append(1);
2241 bdr_attributes.Append(1); bdr_attributes.Append(2);
2242 bdr_attributes.Append(3); bdr_attributes.Append(4);
2245 void Mesh::Make1D(
int n,
double sx)
2254 BaseGeom = Geometry::SEGMENT;
2255 BaseBdrGeom = Geometry::POINT;
2259 NumOfVertices = n + 1;
2261 NumOfBdrElements = 2;
2262 vertices.SetSize(NumOfVertices);
2263 elements.SetSize(NumOfElements);
2264 boundary.SetSize(NumOfBdrElements);
2267 for (j = 0; j < n+1; j++)
2269 vertices[j](0) = ((
double) j / n) * sx;
2273 for (j = 0; j < n; j++)
2275 elements[j] =
new Segment(j, j+1, 1);
2280 boundary[0] =
new Point(ind, 1);
2282 boundary[1] =
new Point(ind, 2);
2289 attributes.Append(1);
2290 bdr_attributes.Append(1); bdr_attributes.Append(2);
2293 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
2311 last_operation = Mesh::NONE;
2314 elements.SetSize(NumOfElements);
2315 for (
int i = 0; i < NumOfElements; i++)
2317 elements[i] = mesh.
elements[i]->Duplicate(
this);
2321 MFEM_ASSERT(mesh.
vertices.Size() == NumOfVertices,
"internal MFEM error!");
2325 boundary.SetSize(NumOfBdrElements);
2326 for (
int i = 0; i < NumOfBdrElements; i++)
2328 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
2347 faces.SetSize(mesh.
faces.Size());
2348 for (
int i = 0; i < faces.Size(); i++)
2351 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
2370 "copying NURBS meshes is not implemented");
2378 if (mesh.
Nodes && copy_nodes)
2383 FiniteElementCollection::New(fec->
Name());
2388 Nodes->MakeOwner(fec_copy);
2389 *Nodes = *mesh.
Nodes;
2399 Mesh::Mesh(
const char *filename,
int generate_edges,
int refine,
2400 bool fix_orientation)
2409 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
2413 Load(imesh, generate_edges, refine, fix_orientation);
2417 Mesh::Mesh(std::istream &input,
int generate_edges,
int refine,
2418 bool fix_orientation)
2421 Load(input, generate_edges, refine, fix_orientation);
2424 void Mesh::ChangeVertexDataOwnership(
double *vertex_data,
int len_vertex_data,
2429 MFEM_VERIFY(len_vertex_data >= NumOfVertices * 3,
2430 "Not enough vertices in external array : "
2431 "len_vertex_data = "<< len_vertex_data <<
", "
2432 "NumOfVertices * 3 = " << NumOfVertices * 3);
2434 if (vertex_data == (
double *)(vertices.GetData()))
2436 MFEM_ASSERT(!vertices.OwnsData(),
"invalid ownership");
2441 memcpy(vertex_data, vertices.GetData(),
2442 NumOfVertices * 3 *
sizeof(double));
2445 vertices.MakeRef(reinterpret_cast<Vertex*>(vertex_data), NumOfVertices);
2448 Mesh::Mesh(
double *_vertices,
int num_vertices,
2450 int *element_attributes,
int num_elements,
2452 int *boundary_attributes,
int num_boundary_elements,
2453 int dimension,
int space_dimension)
2455 if (space_dimension == -1)
2457 space_dimension = dimension;
2460 InitMesh(dimension, space_dimension, 0, num_elements,
2461 num_boundary_elements);
2463 int element_index_stride = Geometry::NumVerts[element_type];
2464 int boundary_index_stride = num_boundary_elements > 0 ?
2465 Geometry::NumVerts[boundary_type] : 0;
2468 vertices.MakeRef(reinterpret_cast<Vertex*>(_vertices), num_vertices);
2469 NumOfVertices = num_vertices;
2471 for (
int i = 0; i < num_elements; i++)
2473 elements[i] = NewElement(element_type);
2474 elements[i]->SetVertices(element_indices + i * element_index_stride);
2475 elements[i]->SetAttribute(element_attributes[i]);
2477 NumOfElements = num_elements;
2479 for (
int i = 0; i < num_boundary_elements; i++)
2481 boundary[i] = NewElement(boundary_type);
2482 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
2483 boundary[i]->SetAttribute(boundary_attributes[i]);
2485 NumOfBdrElements = num_boundary_elements;
2494 case Geometry::POINT:
return (
new Point);
2495 case Geometry::SEGMENT:
return (
new Segment);
2496 case Geometry::TRIANGLE:
return (
new Triangle);
2498 case Geometry::CUBE:
return (
new Hexahedron);
2499 case Geometry::TETRAHEDRON:
2500 #ifdef MFEM_USE_MEMALLOC
2501 return TetMemory.Alloc();
2510 Element *Mesh::ReadElementWithoutAttr(std::istream &input)
2516 el = NewElement(geom);
2519 for (
int i = 0; i < nv; i++)
2527 void Mesh::PrintElementWithoutAttr(
const Element *el, std::ostream &
out)
2532 for (
int j = 0; j < nv; j++)
2545 el = ReadElementWithoutAttr(input);
2554 PrintElementWithoutAttr(el, out);
2557 void Mesh::SetMeshGen()
2560 for (
int i = 0; i < NumOfElements; i++)
2562 switch (elements[i]->GetType())
2564 case Element::SEGMENT:
2565 case Element::TRIANGLE:
2566 case Element::TETRAHEDRON:
2567 meshgen |= 1;
break;
2569 case Element::QUADRILATERAL:
2570 case Element::HEXAHEDRON:
2576 void Mesh::Loader(std::istream &input,
int generate_edges,
2577 std::string parse_tag)
2579 int curved = 0, read_gf = 1;
2583 MFEM_ABORT(
"Input stream is not open");
2590 getline(input, mesh_type);
2594 bool mfem_v10 = (mesh_type ==
"MFEM mesh v1.0");
2595 bool mfem_v11 = (mesh_type ==
"MFEM mesh v1.1");
2596 bool mfem_v12 = (mesh_type ==
"MFEM mesh v1.2");
2597 if (mfem_v10 || mfem_v11 || mfem_v12)
2603 if ( mfem_v12 && parse_tag.empty() )
2605 parse_tag =
"mfem_mesh_end";
2607 ReadMFEMMesh(input, mfem_v11, curved);
2609 else if (mesh_type ==
"linemesh")
2611 ReadLineMesh(input);
2613 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
2615 if (mesh_type ==
"curved_areamesh2")
2619 ReadNetgen2DMesh(input, curved);
2621 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
2623 ReadNetgen3DMesh(input);
2625 else if (mesh_type ==
"TrueGrid")
2627 ReadTrueGridMesh(input);
2629 else if (mesh_type ==
"# vtk DataFile Version 3.0" ||
2630 mesh_type ==
"# vtk DataFile Version 2.0")
2632 ReadVTKMesh(input, curved, read_gf);
2634 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
2636 ReadNURBSMesh(input, curved, read_gf);
2638 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
2640 ReadInlineMesh(input, generate_edges);
2643 else if (mesh_type ==
"$MeshFormat")
2645 ReadGmshMesh(input);
2648 ((mesh_type.size() > 2 &&
2649 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
2650 (mesh_type.size() > 3 &&
2651 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
2656 #ifdef MFEM_USE_NETCDF
2657 ReadCubit(mesh_input->
filename, curved, read_gf);
2659 MFEM_ABORT(
"NetCDF support requires configuration with"
2660 " MFEM_USE_NETCDF=YES");
2666 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
2667 " Use mfem::named_ifgzstream for input.");
2673 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
2698 if (curved && read_gf)
2702 spaceDim = Nodes->VectorDim();
2703 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2705 for (
int i = 0; i < spaceDim; i++)
2708 Nodes->GetNodalValues(vert_val, i+1);
2709 for (
int j = 0; j < NumOfVertices; j++)
2711 vertices[j](i) = vert_val(j);
2724 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
2725 getline(input, line);
2731 if (line ==
"mfem_mesh_end") {
break; }
2733 while (line != parse_tag);
2739 Mesh::Mesh(
Mesh *mesh_array[],
int num_pieces)
2741 int i, j, ie, ib, iv, *v, nv;
2750 BaseGeom = mesh_array[0]->
BaseGeom;
2753 if (mesh_array[0]->NURBSext)
2758 NumOfVertices = NURBSext->GetNV();
2759 NumOfElements = NURBSext->GetNE();
2761 NURBSext->GetElementTopo(elements);
2774 NumOfBdrElements = 0;
2775 for (i = 0; i < num_pieces; i++)
2777 NumOfBdrElements += mesh_array[i]->
GetNBE();
2779 boundary.SetSize(NumOfBdrElements);
2780 vertices.SetSize(NumOfVertices);
2782 for (i = 0; i < num_pieces; i++)
2788 for (j = 0; j < m->
GetNE(); j++)
2790 elements[lelem_elem[j]]->SetAttribute(m->
GetAttribute(j));
2793 for (j = 0; j < m->
GetNBE(); j++)
2798 for (
int k = 0; k < nv; k++)
2800 v[k] = lvert_vert[v[k]];
2802 boundary[ib++] = el;
2805 for (j = 0; j < m->
GetNV(); j++)
2815 NumOfBdrElements = 0;
2817 for (i = 0; i < num_pieces; i++)
2820 NumOfElements += m->
GetNE();
2821 NumOfBdrElements += m->
GetNBE();
2822 NumOfVertices += m->
GetNV();
2824 elements.SetSize(NumOfElements);
2825 boundary.SetSize(NumOfBdrElements);
2826 vertices.SetSize(NumOfVertices);
2828 for (i = 0; i < num_pieces; i++)
2832 for (j = 0; j < m->
GetNE(); j++)
2837 for (
int k = 0; k < nv; k++)
2841 elements[ie++] = el;
2844 for (j = 0; j < m->
GetNBE(); j++)
2849 for (
int k = 0; k < nv; k++)
2853 boundary[ib++] = el;
2856 for (j = 0; j < m->
GetNV(); j++)
2865 for (i = 0; i < num_pieces; i++)
2873 GetElementToFaceTable();
2884 el_to_edge =
new Table;
2885 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2904 for (i = 0; i < num_pieces; i++)
2906 gf_array[i] = mesh_array[i]->
GetNodes();
2913 CheckElementOrientation(
false);
2914 CheckBdrElementOrientation(
false);
2918 Mesh::Mesh(
Mesh *orig_mesh,
int ref_factor,
int ref_type)
2921 MFEM_VERIFY(ref_factor > 1,
"the refinement factor must be > 1");
2922 MFEM_VERIFY(ref_type == BasisType::ClosedUniform ||
2923 ref_type == BasisType::GaussLobatto,
"invalid refinement type");
2924 MFEM_VERIFY(Dim == 2 || Dim == 3,
2925 "only implemented for Hexahedron and Quadrilateral elements in "
2933 int r_bndr_factor = ref_factor * (Dim == 2 ? 1 : ref_factor);
2934 int r_elem_factor = ref_factor * r_bndr_factor;
2937 int r_num_elem = orig_mesh->
GetNE() * r_elem_factor;
2938 int r_num_bndr = orig_mesh->
GetNBE() * r_bndr_factor;
2940 InitMesh(Dim, orig_mesh->
SpaceDimension(), r_num_vert, r_num_elem,
2944 NumOfVertices = r_num_vert;
2949 for (
int el = 0; el < orig_mesh->
GetNE(); el++)
2953 int nvert = Geometry::NumVerts[
geom];
2956 max_nv = std::max(max_nv, nvert);
2962 const int *c2h_map = rfec.
GetDofMap(geom);
2963 for (
int i = 0; i < phys_pts.
Width(); i++)
2965 vertices[rdofs[i]].SetCoords(spaceDim, phys_pts.
GetColumn(i));
2969 Element *elem = NewElement(geom);
2972 for (
int k = 0; k < nvert; k++)
2975 v[k] = rdofs[c2h_map[cid]];
2981 for (
int el = 0; el < orig_mesh->
GetNBE(); el++)
2985 int nvert = Geometry::NumVerts[
geom];
2990 const int *c2h_map = rfec.
GetDofMap(geom);
2993 Element *elem = NewElement(geom);
2996 for (
int k = 0; k < nvert; k++)
2999 v[k] = rdofs[c2h_map[cid]];
3001 AddBdrElement(elem);
3007 last_operation = Mesh::REFINE;
3010 MFEM_VERIFY(BaseGeom != -1,
"meshes with mixed elements are not supported");
3011 CoarseFineTr.point_matrices.SetSize(Dim, max_nv, r_elem_factor);
3012 CoarseFineTr.embeddings.SetSize(GetNE());
3013 if (orig_mesh->
GetNE() > 0)
3017 int nvert = Geometry::NumVerts[
geom];
3019 const int *c2h_map = rfec.
GetDofMap(geom);
3024 for (
int k = 0; k < nvert; k++)
3032 for (
int el = 0; el < GetNE(); el++)
3034 Embedding &emb = CoarseFineTr.embeddings[el];
3035 emb.
parent = el / r_elem_factor;
3036 emb.
matrix = el % r_elem_factor;
3039 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
3040 MFEM_ASSERT(CheckBdrElementOrientation(
false) == 0,
"");
3045 if (NURBSext == NULL)
3047 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
3050 if (kv.
Size() != NURBSext->GetNKV())
3052 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
3055 NURBSext->ConvertToPatches(*Nodes);
3057 NURBSext->KnotInsert(kv);
3062 void Mesh::NURBSUniformRefinement()
3065 NURBSext->ConvertToPatches(*Nodes);
3067 NURBSext->UniformRefinement();
3069 last_operation = Mesh::REFINE;
3075 void Mesh::DegreeElevate(
int t)
3077 if (NURBSext == NULL)
3079 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
3082 NURBSext->ConvertToPatches(*Nodes);
3084 NURBSext->DegreeElevate(t);
3097 void Mesh::UpdateNURBS()
3099 NURBSext->SetKnotsFromPatches();
3101 Dim = NURBSext->Dimension();
3104 if (NumOfElements != NURBSext->GetNE())
3106 for (
int i = 0; i < elements.Size(); i++)
3108 FreeElement(elements[i]);
3110 NumOfElements = NURBSext->GetNE();
3111 NURBSext->GetElementTopo(elements);
3114 if (NumOfBdrElements != NURBSext->GetNBE())
3116 for (
int i = 0; i < boundary.Size(); i++)
3118 FreeElement(boundary[i]);
3120 NumOfBdrElements = NURBSext->GetNBE();
3121 NURBSext->GetBdrElementTopo(boundary);
3124 Nodes->FESpace()->Update();
3126 NURBSext->SetCoordsFromPatches(*Nodes);
3128 if (NumOfVertices != NURBSext->GetNV())
3130 NumOfVertices = NURBSext->GetNV();
3131 vertices.SetSize(NumOfVertices);
3132 int vd = Nodes->VectorDim();
3133 for (
int i = 0; i < vd; i++)
3136 Nodes->GetNodalValues(vert_val, i+1);
3137 for (
int j = 0; j < NumOfVertices; j++)
3139 vertices[j](i) = vert_val(j);
3146 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3155 GetElementToFaceTable();
3160 void Mesh::LoadPatchTopo(std::istream &input,
Array<int> &edge_to_knot)
3178 input >> NumOfElements;
3179 elements.SetSize(NumOfElements);
3180 for (j = 0; j < NumOfElements; j++)
3182 elements[j] = ReadElement(input);
3188 input >> NumOfBdrElements;
3189 boundary.SetSize(NumOfBdrElements);
3190 for (j = 0; j < NumOfBdrElements; j++)
3192 boundary[j] = ReadElement(input);
3198 input >> NumOfEdges;
3199 edge_vertex =
new Table(NumOfEdges, 2);
3200 edge_to_knot.
SetSize(NumOfEdges);
3201 for (j = 0; j < NumOfEdges; j++)
3203 int *v = edge_vertex->GetRow(j);
3204 input >> edge_to_knot[j] >> v[0] >> v[1];
3207 edge_to_knot[j] = -1 - edge_to_knot[j];
3214 input >> NumOfVertices;
3215 vertices.SetSize(0);
3224 GetElementToFaceTable();
3226 if (NumOfBdrElements == 0)
3228 GenerateBoundaryElements();
3230 CheckBdrElementOrientation();
3240 el_to_edge =
new Table;
3241 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3245 if (NumOfBdrElements == 0)
3247 GenerateBoundaryElements();
3249 CheckBdrElementOrientation();
3265 for (
int d = 0; d < v.
Size(); d++)
3273 for (d = 0; d < p.
Size(); d++)
3277 for ( ; d < v.
Size(); d++)
3286 if (Nodes == NULL || Nodes->FESpace() != nodes.
FESpace())
3301 SetNodalGridFunction(nodes,
true);
3307 NewNodes(*nodes, make_owner);
3312 return ((Nodes) ? Nodes->FESpace() : NULL);
3315 void Mesh::SetCurvature(
int order,
bool discont,
int space_dim,
int ordering)
3317 space_dim = (space_dim == -1) ? spaceDim : space_dim;
3330 SetNodalFESpace(nfes);
3331 Nodes->MakeOwner(nfec);
3334 int Mesh::GetNumFaces()
const
3338 case 1:
return GetNV();
3339 case 2:
return GetNEdges();
3340 case 3:
return GetNFaces();
3345 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3346 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
3349 int Mesh::CheckElementOrientation(
bool fix_it)
3351 int i, j, k, wo = 0, fo = 0, *vi = 0;
3354 if (Dim == 2 && spaceDim == 2)
3358 for (i = 0; i < NumOfElements; i++)
3362 vi = elements[i]->GetVertices();
3363 for (j = 0; j < 3; j++)
3365 v[j] = vertices[vi[j]]();
3367 for (j = 0; j < 2; j++)
3368 for (k = 0; k < 2; k++)
3370 J(j, k) = v[j+1][k] - v[0][k];
3376 GetElementJacobian(i, J);
3382 switch (GetElementType(i))
3384 case Element::TRIANGLE:
3387 case Element::QUADRILATERAL:
3402 for (i = 0; i < NumOfElements; i++)
3404 vi = elements[i]->GetVertices();
3405 switch (GetElementType(i))
3407 case Element::TETRAHEDRON:
3410 for (j = 0; j < 4; j++)
3412 v[j] = vertices[vi[j]]();
3414 for (j = 0; j < 3; j++)
3415 for (k = 0; k < 3; k++)
3417 J(j, k) = v[j+1][k] - v[0][k];
3423 GetElementJacobian(i, J);
3436 case Element::HEXAHEDRON:
3438 GetElementJacobian(i, J);
3451 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3453 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / "
3454 << NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
3460 int Mesh::GetTriOrientation(
const int *base,
const int *test)
3468 if (test[0] == base[0])
3469 if (test[1] == base[1])
3477 else if (test[0] == base[1])
3478 if (test[1] == base[0])
3487 if (test[1] == base[0])
3497 const int *aor = tri_t::Orient[orient];
3498 for (
int j = 0; j < 3; j++)
3499 if (test[aor[j]] != base[j])
3508 int Mesh::GetQuadOrientation(
const int *base,
const int *test)
3512 for (i = 0; i < 4; i++)
3513 if (test[i] == base[0])
3520 if (test[(i+1)%4] == base[1])
3528 const int *aor = quad_t::Orient[orient];
3529 for (
int j = 0; j < 4; j++)
3530 if (test[aor[j]] != base[j])
3532 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
3534 for (
int k = 0; k < 4; k++)
3539 for (
int k = 0; k < 4; k++)
3548 if (test[(i+1)%4] == base[1])
3556 int Mesh::CheckBdrElementOrientation(
bool fix_it)
3562 for (i = 0; i < NumOfBdrElements; i++)
3564 if (faces_info[be_to_edge[i]].Elem2No < 0)
3566 int *bv = boundary[i]->GetVertices();
3567 int *fv = faces[be_to_edge[i]]->GetVertices();
3572 mfem::Swap<int>(bv[0], bv[1]);
3585 for (i = 0; i < NumOfBdrElements; i++)
3587 if (faces_info[be_to_face[i]].Elem2No < 0)
3590 bv = boundary[i]->GetVertices();
3591 el = faces_info[be_to_face[i]].Elem1No;
3592 ev = elements[el]->GetVertices();
3593 switch (GetElementType(el))
3595 case Element::TETRAHEDRON:
3597 int *fv = faces[be_to_face[i]]->GetVertices();
3600 orientation = GetTriOrientation(fv, bv);
3601 if (orientation % 2)
3607 mfem::Swap<int>(bv[0], bv[1]);
3610 int *be = bel_to_edge->GetRow(i);
3611 mfem::Swap<int>(be[1], be[2]);
3619 case Element::HEXAHEDRON:
3621 int lf = faces_info[be_to_face[i]].Elem1Inf/64;
3622 for (
int j = 0; j < 4; j++)
3624 v[j] = ev[hex_t::FaceVert[lf][j]];
3626 if (GetQuadOrientation(v, bv) % 2)
3630 mfem::Swap<int>(bv[0], bv[2]);
3633 int *be = bel_to_edge->GetRow(i);
3634 mfem::Swap<int>(be[0], be[1]);
3635 mfem::Swap<int>(be[2], be[3]);
3650 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / "
3651 << NumOfBdrElements <<
" (" << fixed_or_not[fix_it ? 0 : 1]
3662 el_to_edge->GetRow(i, edges);
3666 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
3667 "is not generated.");
3670 const int *v = elements[i]->GetVertices();
3671 const int ne = elements[i]->GetNEdges();
3673 for (
int j = 0; j < ne; j++)
3675 const int *e = elements[i]->GetEdgeVertices(j);
3676 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3686 edges[0] = be_to_edge[i];
3687 const int *v = boundary[i]->GetVertices();
3688 cor[0] = (v[0] < v[1]) ? (1) : (-1);
3694 bel_to_edge->GetRow(i, edges);
3701 const int *v = boundary[i]->GetVertices();
3702 const int ne = boundary[i]->GetNEdges();
3704 for (
int j = 0; j < ne; j++)
3706 const int *e = boundary[i]->GetEdgeVertices(j);
3707 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3719 const int *v = faces[i]->GetVertices();
3720 o[0] = (v[0] < v[1]) ? (1) : (-1);
3730 face_edge->GetRow(i, edges);
3732 const int *v = faces[i]->GetVertices();
3733 const int ne = faces[i]->GetNEdges();
3735 for (
int j = 0; j < ne; j++)
3737 const int *e = faces[i]->GetEdgeVertices(j);
3738 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3747 if (!edge_vertex) { GetEdgeVertexTable(); }
3748 edge_vertex->GetRow(i, vert);
3764 if (faces.Size() != NumOfFaces)
3766 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
3770 DSTable v_to_v(NumOfVertices);
3771 GetVertexToVertexTable(v_to_v);
3773 face_edge =
new Table;
3774 GetElementArrayEdgeTable(faces, v_to_v, *face_edge);
3786 DSTable v_to_v(NumOfVertices);
3787 GetVertexToVertexTable(v_to_v);
3790 edge_vertex =
new Table(nedges, 2);
3791 for (
int i = 0; i < NumOfVertices; i++)
3796 edge_vertex->Push(j, i);
3797 edge_vertex->Push(j, it.Column());
3800 edge_vertex->Finalize();
3811 vert_elem->
MakeI(NumOfVertices);
3813 for (i = 0; i < NumOfElements; i++)
3815 nv = elements[i]->GetNVertices();
3816 v = elements[i]->GetVertices();
3817 for (j = 0; j < nv; j++)
3825 for (i = 0; i < NumOfElements; i++)
3827 nv = elements[i]->GetNVertices();
3828 v = elements[i]->GetVertices();
3829 for (j = 0; j < nv; j++)
3840 Table *Mesh::GetFaceToElementTable()
const
3844 face_elem->
MakeI(faces_info.Size());
3846 for (
int i = 0; i < faces_info.Size(); i++)
3848 if (faces_info[i].Elem2No >= 0)
3860 for (
int i = 0; i < faces_info.Size(); i++)
3863 if (faces_info[i].Elem2No >= 0)
3881 el_to_face->
GetRow(i, fcs);
3885 mfem_error(
"Mesh::GetElementFaces(...) : el_to_face not generated.");
3890 for (j = 0; j < n; j++)
3891 if (faces_info[fcs[j]].Elem1No == i)
3893 cor[j] = faces_info[fcs[j]].Elem1Inf % 64;
3896 else if (faces_info[fcs[j]].Elem2No == i)
3898 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3902 mfem_error(
"Mesh::GetElementFaces(...) : 2");
3907 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3912 void Mesh::GetBdrElementFace(
int i,
int *f,
int *o)
const
3917 bv = boundary[i]->GetVertices();
3918 fv = faces[be_to_face[i]]->GetVertices();
3922 switch (GetBdrElementType(i))
3924 case Element::TRIANGLE:
3925 *o = GetTriOrientation(fv, bv);
3927 case Element::QUADRILATERAL:
3928 *o = GetQuadOrientation(fv, bv);
3931 mfem_error(
"Mesh::GetBdrElementFace(...) 2");
3935 int Mesh::GetFaceBaseGeometry(
int i)
const
3938 switch (GetElementType(0))
3940 case Element::SEGMENT:
3941 return Geometry::POINT;
3943 case Element::TRIANGLE:
3944 case Element::QUADRILATERAL:
3945 return Geometry::SEGMENT;
3947 case Element::TETRAHEDRON:
3948 return Geometry::TRIANGLE;
3949 case Element::HEXAHEDRON:
3950 return Geometry::SQUARE;
3952 mfem_error(
"Mesh::GetFaceBaseGeometry(...) #1");
3957 int Mesh::GetBdrElementEdgeIndex(
int i)
const
3961 case 1:
return boundary[i]->GetVertices()[0];
3962 case 2:
return be_to_edge[i];
3963 case 3:
return be_to_face[i];
3964 default:
mfem_error(
"Mesh::GetBdrElementEdgeIndex: invalid dimension!");
3969 void Mesh::GetBdrElementAdjacentElement(
int bdr_el,
int &el,
int &info)
const
3971 int fid = GetBdrElementEdgeIndex(bdr_el);
3972 const FaceInfo &fi = faces_info[fid];
3973 MFEM_ASSERT(fi.
Elem1Inf%64 == 0,
"internal error");
3974 const int *fv = (Dim > 1) ? faces[fid]->GetVertices() : NULL;
3975 const int *bv = boundary[bdr_el]->GetVertices();
3977 switch (GetBdrElementBaseGeometry(bdr_el))
3979 case Geometry::POINT: ori = 0;
break;
3980 case Geometry::SEGMENT: ori = (fv[0] == bv[0]) ? 0 : 1;
break;
3981 case Geometry::TRIANGLE: ori = GetTriOrientation(fv, bv);
break;
3982 case Geometry::SQUARE: ori = GetQuadOrientation(fv, bv);
break;
3983 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
3989 int Mesh::GetElementType(
int i)
const
3991 return elements[i]->GetType();
3994 int Mesh::GetBdrElementType(
int i)
const
3996 return boundary[i]->GetType();
4004 v = elements[i]->GetVertices();
4005 nv = elements[i]->GetNVertices();
4007 pointmat.
SetSize(spaceDim, nv);
4008 for (k = 0; k < spaceDim; k++)
4009 for (j = 0; j < nv; j++)
4011 pointmat(k, j) = vertices[v[j]](k);
4020 v = boundary[i]->GetVertices();
4021 nv = boundary[i]->GetNVertices();
4023 pointmat.
SetSize(spaceDim, nv);
4024 for (k = 0; k < spaceDim; k++)
4025 for (j = 0; j < nv; j++)
4027 pointmat(k, j) = vertices[v[j]](k);
4031 double Mesh::GetLength(
int i,
int j)
const
4033 const double *vi = vertices[i]();
4034 const double *vj = vertices[j]();
4037 for (
int k = 0; k < spaceDim; k++)
4039 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
4042 return sqrt(length);
4050 for (
int i = 0; i < elem_array.
Size(); i++)
4055 for (
int i = 0; i < elem_array.
Size(); i++)
4057 const int *v = elem_array[i]->GetVertices();
4058 const int ne = elem_array[i]->GetNEdges();
4059 for (
int j = 0; j < ne; j++)
4061 const int *e = elem_array[i]->GetEdgeVertices(j);
4068 void Mesh::GetVertexToVertexTable(
DSTable &v_to_v)
const
4072 for (
int i = 0; i < edge_vertex->Size(); i++)
4074 const int *v = edge_vertex->GetRow(i);
4075 v_to_v.
Push(v[0], v[1]);
4080 for (
int i = 0; i < NumOfElements; i++)
4082 const int *v = elements[i]->GetVertices();
4083 const int ne = elements[i]->GetNEdges();
4084 for (
int j = 0; j < ne; j++)
4086 const int *e = elements[i]->GetEdgeVertices(j);
4087 v_to_v.
Push(v[e[0]], v[e[1]]);
4095 int i, NumberOfEdges;
4097 DSTable v_to_v(NumOfVertices);
4098 GetVertexToVertexTable(v_to_v);
4103 GetElementArrayEdgeTable(elements, v_to_v, e_to_f);
4108 be_to_f.
SetSize(NumOfBdrElements);
4109 for (i = 0; i < NumOfBdrElements; i++)
4111 const int *v = boundary[i]->GetVertices();
4112 be_to_f[i] = v_to_v(v[0], v[1]);
4117 if (bel_to_edge == NULL)
4119 bel_to_edge =
new Table;
4121 GetElementArrayEdgeTable(boundary, v_to_v, *bel_to_edge);
4125 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
4129 return NumberOfEdges;
4132 const Table & Mesh::ElementToElementTable()
4140 MFEM_ASSERT(faces_info.Size() >= GetNumFaces(),
"faces were not generated!");
4143 conn.
Reserve(2*faces_info.Size());
4145 for (
int i = 0; i < faces_info.Size(); i++)
4147 const FaceInfo &fi = faces_info[i];
4155 int nbr_elem_idx = NumOfElements - 1 - fi.
Elem2No;
4163 el_to_el =
new Table(NumOfElements, conn);
4168 const Table & Mesh::ElementToFaceTable()
const
4170 if (el_to_face == NULL)
4177 const Table & Mesh::ElementToEdgeTable()
const
4179 if (el_to_edge == NULL)
4186 void Mesh::AddPointFaceElement(
int lf,
int gf,
int el)
4188 if (faces_info[gf].Elem1No == -1)
4191 faces_info[gf].Elem1No = el;
4192 faces_info[gf].Elem1Inf = 64 * lf;
4193 faces_info[gf].Elem2No = -1;
4194 faces_info[gf].Elem2Inf = -1;
4198 faces_info[gf].Elem2No = el;
4199 faces_info[gf].Elem2Inf = 64 * lf + 1;
4203 void Mesh::AddSegmentFaceElement(
int lf,
int gf,
int el,
int v0,
int v1)
4205 if (faces[gf] == NULL)
4207 faces[gf] =
new Segment(v0, v1);
4208 faces_info[gf].Elem1No = el;
4209 faces_info[gf].Elem1Inf = 64 * lf;
4210 faces_info[gf].Elem2No = -1;
4211 faces_info[gf].Elem2Inf = -1;
4215 int *v = faces[gf]->GetVertices();
4216 faces_info[gf].Elem2No = el;
4217 if ( v[1] == v0 && v[0] == v1 )
4219 faces_info[gf].Elem2Inf = 64 * lf + 1;
4221 else if ( v[0] == v0 && v[1] == v1 )
4223 faces_info[gf].Elem2Inf = 64 * lf;
4227 MFEM_ASSERT((v[1] == v0 && v[0] == v1)||
4228 (v[0] == v0 && v[1] == v1),
"");
4233 void Mesh::AddTriangleFaceElement(
int lf,
int gf,
int el,
4234 int v0,
int v1,
int v2)
4236 if (faces[gf] == NULL)
4238 faces[gf] =
new Triangle(v0, v1, v2);
4239 faces_info[gf].Elem1No = el;
4240 faces_info[gf].Elem1Inf = 64 * lf;
4241 faces_info[gf].Elem2No = -1;
4242 faces_info[gf].Elem2Inf = -1;
4246 int orientation, vv[3] = { v0, v1, v2 };
4247 orientation = GetTriOrientation(faces[gf]->GetVertices(), vv);
4248 MFEM_ASSERT(orientation % 2 != 0,
"");
4249 faces_info[gf].Elem2No = el;
4250 faces_info[gf].Elem2Inf = 64 * lf + orientation;
4254 void Mesh::AddQuadFaceElement(
int lf,
int gf,
int el,
4255 int v0,
int v1,
int v2,
int v3)
4257 if (faces_info[gf].Elem1No < 0)
4260 faces_info[gf].Elem1No = el;
4261 faces_info[gf].Elem1Inf = 64 * lf;
4262 faces_info[gf].Elem2No = -1;
4263 faces_info[gf].Elem2Inf = -1;
4267 int vv[4] = { v0, v1, v2, v3 };
4268 int oo = GetQuadOrientation(faces[gf]->GetVertices(), vv);
4269 MFEM_ASSERT(oo % 2 != 0,
"");
4270 faces_info[gf].Elem2No = el;
4271 faces_info[gf].Elem2Inf = 64 * lf + oo;
4275 void Mesh::GenerateFaces()
4277 int i, nfaces = GetNumFaces();
4279 for (i = 0; i < faces.Size(); i++)
4281 FreeElement(faces[i]);
4285 faces.SetSize(nfaces);
4286 faces_info.SetSize(nfaces);
4287 for (i = 0; i < nfaces; i++)
4290 faces_info[i].Elem1No = -1;
4291 faces_info[i].NCFace = -1;
4293 for (i = 0; i < NumOfElements; i++)
4295 const int *v = elements[i]->GetVertices();
4299 AddPointFaceElement(0, v[0], i);
4300 AddPointFaceElement(1, v[1], i);
4304 ef = el_to_edge->GetRow(i);
4305 const int ne = elements[i]->GetNEdges();
4306 for (
int j = 0; j < ne; j++)
4308 const int *e = elements[i]->GetEdgeVertices(j);
4309 AddSegmentFaceElement(j, ef[j], i, v[e[0]], v[e[1]]);
4314 ef = el_to_face->GetRow(i);
4315 switch (GetElementType(i))
4317 case Element::TETRAHEDRON:
4319 for (
int j = 0; j < 4; j++)
4321 const int *fv = tet_t::FaceVert[j];
4322 AddTriangleFaceElement(j, ef[j], i,
4323 v[fv[0]], v[fv[1]], v[fv[2]]);
4327 case Element::HEXAHEDRON:
4329 for (
int j = 0; j < 6; j++)
4331 const int *fv = hex_t::FaceVert[j];
4332 AddQuadFaceElement(j, ef[j], i,
4333 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4338 MFEM_ABORT(
"Unexpected type of Element.");
4344 void Mesh::GenerateNCFaceInfo()
4346 MFEM_VERIFY(ncmesh,
"missing NCMesh.");
4348 for (
int i = 0; i < faces_info.Size(); i++)
4350 faces_info[i].NCFace = -1;
4354 (Dim == 2) ? ncmesh->GetEdgeList() : ncmesh->GetFaceList();
4356 nc_faces_info.SetSize(0);
4357 nc_faces_info.Reserve(list.
masters.size() + list.
slaves.size());
4359 int nfaces = GetNumFaces();
4362 for (
unsigned i = 0; i < list.
masters.size(); i++)
4365 if (master.
index >= nfaces) {
continue; }
4367 faces_info[master.
index].NCFace = nc_faces_info.Size();
4373 for (
unsigned i = 0; i < list.
slaves.size(); i++)
4376 if (slave.
index >= nfaces || slave.
master >= nfaces) {
continue; }
4382 slave_fi.
NCFace = nc_faces_info.Size();
4394 for (
int i = 0; i < NumOfElements; i++)
4396 const int *v = elements[i]->GetVertices();
4397 switch (GetElementType(i))
4399 case Element::TETRAHEDRON:
4401 for (
int j = 0; j < 4; j++)
4403 const int *fv = tet_t::FaceVert[j];
4404 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
4408 case Element::HEXAHEDRON:
4412 for (
int j = 0; j < 6; j++)
4414 const int *fv = hex_t::FaceVert[j];
4415 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4420 MFEM_ABORT(
"Unexpected type of Element.");
4431 if (el_to_face != NULL)
4435 el_to_face =
new Table(NumOfElements, 6);
4436 faces_tbl =
new STable3D(NumOfVertices);
4437 for (i = 0; i < NumOfElements; i++)
4439 v = elements[i]->GetVertices();
4440 switch (GetElementType(i))
4442 case Element::TETRAHEDRON:
4444 for (
int j = 0; j < 4; j++)
4446 const int *fv = tet_t::FaceVert[j];
4448 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
4452 case Element::HEXAHEDRON:
4456 for (
int j = 0; j < 6; j++)
4458 const int *fv = hex_t::FaceVert[j];
4460 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
4465 MFEM_ABORT(
"Unexpected type of Element.");
4468 el_to_face->Finalize();
4470 be_to_face.SetSize(NumOfBdrElements);
4471 for (i = 0; i < NumOfBdrElements; i++)
4473 v = boundary[i]->GetVertices();
4474 switch (GetBdrElementType(i))
4476 case Element::TRIANGLE:
4478 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2]);
4481 case Element::QUADRILATERAL:
4483 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
4487 MFEM_ABORT(
"Unexpected type of boundary Element.");
4499 void Mesh::ReorientTetMesh()
4503 if (Dim != 3 || !(meshgen & 1))
4509 Table *old_elem_vert = NULL;
4513 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
4516 for (
int i = 0; i < NumOfElements; i++)
4518 if (GetElementType(i) == Element::TETRAHEDRON)
4520 v = elements[i]->GetVertices();
4522 Rotate3(v[0], v[1], v[2]);
4525 Rotate3(v[1], v[2], v[3]);
4529 ShiftL2R(v[0], v[1], v[3]);
4534 for (
int i = 0; i < NumOfBdrElements; i++)
4536 if (GetBdrElementType(i) == Element::TRIANGLE)
4538 v = boundary[i]->GetVertices();
4540 Rotate3(v[0], v[1], v[2]);
4546 GetElementToFaceTable();
4550 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
4555 DoNodeReorder(old_v_to_v, old_elem_vert);
4556 delete old_elem_vert;
4561 #if defined(MFEM_USE_METIS) && !defined(MFEM_USE_METIS_5)
4566 int*,
int*,
int*,
int*,
int*,
idxtype*);
4568 int*,
int*,
int*,
int*,
int*,
idxtype*);
4570 int*,
int*,
int*,
int*,
int*,
idxtype*);
4574 int *Mesh::CartesianPartitioning(
int nxyz[])
4577 double pmin[3] = { numeric_limits<double>::infinity(),
4578 numeric_limits<double>::infinity(),
4579 numeric_limits<double>::infinity()
4581 double pmax[3] = { -numeric_limits<double>::infinity(),
4582 -numeric_limits<double>::infinity(),
4583 -numeric_limits<double>::infinity()
4586 for (
int vi = 0; vi < NumOfVertices; vi++)
4588 const double *p = vertices[vi]();
4589 for (
int i = 0; i < spaceDim; i++)
4591 if (p[i] < pmin[i]) { pmin[i] = p[i]; }
4592 if (p[i] > pmax[i]) { pmax[i] = p[i]; }
4596 partitioning =
new int[NumOfElements];
4600 Vector pt(ppt, spaceDim);
4601 for (
int el = 0; el < NumOfElements; el++)
4603 GetElementTransformation(el)->Transform(
4606 for (
int i = spaceDim-1; i >= 0; i--)
4608 int idx = (int)floor(nxyz[i]*((pt(i) - pmin[i])/(pmax[i] - pmin[i])));
4609 if (idx < 0) { idx = 0; }
4610 if (idx >= nxyz[i]) { idx = nxyz[i]-1; }
4611 part = part * nxyz[i] + idx;
4613 partitioning[el] = part;
4616 return partitioning;
4619 int *Mesh::GeneratePartitioning(
int nparts,
int part_method)
4621 #ifdef MFEM_USE_METIS
4622 int i, *partitioning;
4624 ElementToElementTable();
4626 partitioning =
new int[NumOfElements];
4630 for (i = 0; i < NumOfElements; i++)
4632 partitioning[i] = 0;
4638 #ifndef MFEM_USE_METIS_5
4650 I = el_to_el->GetI();
4651 J = el_to_el->GetJ();
4652 #ifndef MFEM_USE_METIS_5
4655 METIS_SetDefaultOptions(options);
4656 options[METIS_OPTION_CONTIG] = 1;
4660 if (part_method >= 0 && part_method <= 2)
4662 for (i = 0; i < n; i++)
4668 std::sort(J+I[i], J+I[i+1], std::greater<int>());
4674 if (part_method == 0 || part_method == 3)
4676 #ifndef MFEM_USE_METIS_5
4704 " error in METIS_PartGraphRecursive!");
4710 if (part_method == 1 || part_method == 4)
4712 #ifndef MFEM_USE_METIS_5
4740 " error in METIS_PartGraphKway!");
4746 if (part_method == 2 || part_method == 5)
4748 #ifndef MFEM_USE_METIS_5
4761 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_VOL;
4777 " error in METIS_PartGraphKway!");
4782 mfem::out <<
"Mesh::GeneratePartitioning(...): edgecut = "
4796 for (i = 0; i < nparts; i++)
4802 for (i = 0; i < NumOfElements; i++)
4804 psize[partitioning[i]].one++;
4807 int empty_parts = 0;
4808 for (i = 0; i < nparts; i++)
4809 if (psize[i].one == 0)
4818 mfem::err <<
"Mesh::GeneratePartitioning returned " << empty_parts
4819 <<
" empty parts!" << endl;
4821 SortPairs<int,int>(psize, nparts);
4823 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4828 for (
int j = 0; j < NumOfElements; j++)
4829 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4830 if (psize[i].one == 0 || partitioning[j] != psize[i].two)
4836 partitioning[j] = psize[nparts-1-i].two;
4842 return partitioning;
4846 mfem_error(
"Mesh::GeneratePartitioning(...): "
4847 "MFEM was compiled without Metis.");
4861 int num_elem, *i_elem_elem, *j_elem_elem;
4863 num_elem = elem_elem.
Size();
4864 i_elem_elem = elem_elem.
GetI();
4865 j_elem_elem = elem_elem.
GetJ();
4870 int stack_p, stack_top_p, elem;
4874 for (i = 0; i < num_elem; i++)
4876 if (partitioning[i] > num_part)
4878 num_part = partitioning[i];
4885 for (i = 0; i < num_part; i++)
4892 for (elem = 0; elem < num_elem; elem++)
4894 if (component[elem] >= 0)
4899 component[elem] = num_comp[partitioning[elem]]++;
4901 elem_stack[stack_top_p++] = elem;
4903 for ( ; stack_p < stack_top_p; stack_p++)
4905 i = elem_stack[stack_p];
4906 for (j = i_elem_elem[i]; j < i_elem_elem[i+1]; j++)
4909 if (partitioning[k] == partitioning[i])
4911 if (component[k] < 0)
4913 component[k] = component[i];
4914 elem_stack[stack_top_p++] = k;
4916 else if (component[k] != component[i])
4926 void Mesh::CheckPartitioning(
int *partitioning)
4928 int i, n_empty, n_mcomp;
4930 const Array<int> _partitioning(partitioning, GetNE());
4932 ElementToElementTable();
4936 n_empty = n_mcomp = 0;
4937 for (i = 0; i < num_comp.
Size(); i++)
4938 if (num_comp[i] == 0)
4942 else if (num_comp[i] > 1)
4949 mfem::out <<
"Mesh::CheckPartitioning(...) :\n"
4950 <<
"The following subdomains are empty :\n";
4951 for (i = 0; i < num_comp.
Size(); i++)
4952 if (num_comp[i] == 0)
4960 mfem::out <<
"Mesh::CheckPartitioning(...) :\n"
4961 <<
"The following subdomains are NOT connected :\n";
4962 for (i = 0; i < num_comp.
Size(); i++)
4963 if (num_comp[i] > 1)
4969 if (n_empty == 0 && n_mcomp == 0)
4970 mfem::out <<
"Mesh::CheckPartitioning(...) : "
4971 "All subdomains are connected." << endl;
4985 const double *a = A.
Data();
4986 const double *b = B.
Data();
4995 c(0) = a[0]*a[3]-a[1]*a[2];
4996 c(1) = a[0]*b[3]-a[1]*b[2]+b[0]*a[3]-b[1]*a[2];
4997 c(2) = b[0]*b[3]-b[1]*b[2];
5018 c(0) = (a[0] * (a[4] * a[8] - a[5] * a[7]) +
5019 a[1] * (a[5] * a[6] - a[3] * a[8]) +
5020 a[2] * (a[3] * a[7] - a[4] * a[6]));
5022 c(1) = (b[0] * (a[4] * a[8] - a[5] * a[7]) +
5023 b[1] * (a[5] * a[6] - a[3] * a[8]) +
5024 b[2] * (a[3] * a[7] - a[4] * a[6]) +
5026 a[0] * (b[4] * a[8] - b[5] * a[7]) +
5027 a[1] * (b[5] * a[6] - b[3] * a[8]) +
5028 a[2] * (b[3] * a[7] - b[4] * a[6]) +
5030 a[0] * (a[4] * b[8] - a[5] * b[7]) +
5031 a[1] * (a[5] * b[6] - a[3] * b[8]) +
5032 a[2] * (a[3] * b[7] - a[4] * b[6]));
5034 c(2) = (a[0] * (b[4] * b[8] - b[5] * b[7]) +
5035 a[1] * (b[5] * b[6] - b[3] * b[8]) +
5036 a[2] * (b[3] * b[7] - b[4] * b[6]) +
5038 b[0] * (a[4] * b[8] - a[5] * b[7]) +
5039 b[1] * (a[5] * b[6] - a[3] * b[8]) +
5040 b[2] * (a[3] * b[7] - a[4] * b[6]) +
5042 b[0] * (b[4] * a[8] - b[5] * a[7]) +
5043 b[1] * (b[5] * a[6] - b[3] * a[8]) +
5044 b[2] * (b[3] * a[7] - b[4] * a[6]));
5046 c(3) = (b[0] * (b[4] * b[8] - b[5] * b[7]) +
5047 b[1] * (b[5] * b[6] - b[3] * b[8]) +
5048 b[2] * (b[3] * b[7] - b[4] * b[6]));
5094 double a = z(2), b = z(1), c = z(0);
5095 double D = b*b-4*a*c;
5102 x(0) = x(1) = -0.5 * b / a;
5107 x(0) = -(x(1) = fabs(0.5 * sqrt(D) / a));
5115 t = -0.5 * (b + sqrt(D));
5119 t = -0.5 * (b - sqrt(D));
5125 Swap<double>(x(0), x(1));
5133 double a = z(2)/z(3), b = z(1)/z(3), c = z(0)/z(3);
5136 double Q = (a * a - 3 * b) / 9;
5137 double R = (2 * a * a * a - 9 * a * b + 27 * c) / 54;
5138 double Q3 = Q * Q * Q;
5145 x(0) = x(1) = x(2) = - a / 3;
5149 double sqrtQ = sqrt(Q);
5153 x(0) = -2 * sqrtQ - a / 3;
5154 x(1) = x(2) = sqrtQ - a / 3;
5158 x(0) = x(1) = - sqrtQ - a / 3;
5159 x(2) = 2 * sqrtQ - a / 3;
5166 double theta = acos(R / sqrt(Q3));
5167 double A = -2 * sqrt(Q);
5169 x0 = A * cos(theta / 3) - a / 3;
5170 x1 = A * cos((theta + 2.0 * M_PI) / 3) - a / 3;
5171 x2 = A * cos((theta - 2.0 * M_PI) / 3) - a / 3;
5176 Swap<double>(x0, x1);
5180 Swap<double>(x1, x2);
5183 Swap<double>(x0, x1);
5196 A = -pow(sqrt(R2 - Q3) + R, 1.0/3.0);
5200 A = pow(sqrt(R2 - Q3) - R, 1.0/3.0);
5202 x(0) = A + Q / A - a / 3;
5211 const double factor,
const int Dim)
5213 const double c0 = c(0);
5214 c(0) = c0 * (1.0 - pow(factor, -Dim));
5216 for (
int j = 0; j < nr; j++)
5228 c(0) = c0 * (1.0 - pow(factor, Dim));
5230 for (
int j = 0; j < nr; j++)
5244 void Mesh::CheckDisplacements(
const Vector &displacements,
double &tmax)
5246 int nvs = vertices.Size();
5247 DenseMatrix P, V, DS, PDS(spaceDim), VDS(spaceDim);
5248 Vector c(spaceDim+1), x(spaceDim);
5249 const double factor = 2.0;
5256 for (
int i = 0; i < NumOfElements; i++)
5263 for (
int j = 0; j < spaceDim; j++)
5264 for (
int k = 0; k < nv; k++)
5266 P(j, k) = vertices[v[k]](j);
5267 V(j, k) = displacements(v[k]+j*nvs);
5271 GetTransformationFEforElementType(el->
GetType());
5275 case Element::TRIANGLE:
5276 case Element::TETRAHEDRON:
5294 case Element::QUADRILATERAL:
5297 for (
int j = 0; j < nv; j++)
5321 void Mesh::MoveVertices(
const Vector &displacements)
5323 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5324 for (
int j = 0; j < spaceDim; j++)
5326 vertices[i](j) += displacements(j*nv+i);
5330 void Mesh::GetVertices(
Vector &vert_coord)
const
5332 int nv = vertices.Size();
5333 vert_coord.
SetSize(nv*spaceDim);
5334 for (
int i = 0; i < nv; i++)
5335 for (
int j = 0; j < spaceDim; j++)
5337 vert_coord(j*nv+i) = vertices[i](j);
5341 void Mesh::SetVertices(
const Vector &vert_coord)
5343 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5344 for (
int j = 0; j < spaceDim; j++)
5346 vertices[i](j) = vert_coord(j*nv+i);
5350 void Mesh::GetNode(
int i,
double *coord)
5355 for (
int j = 0; j < spaceDim; j++)
5357 coord[j] = (*Nodes)(fes->
DofToVDof(i, j));
5362 for (
int j = 0; j < spaceDim; j++)
5364 coord[j] = vertices[i](j);
5369 void Mesh::SetNode(
int i,
const double *coord)
5374 for (
int j = 0; j < spaceDim; j++)
5376 (*Nodes)(fes->
DofToVDof(i, j)) = coord[j];
5381 for (
int j = 0; j < spaceDim; j++)
5383 vertices[i](j) = coord[j];
5389 void Mesh::MoveNodes(
const Vector &displacements)
5393 (*Nodes) += displacements;
5397 MoveVertices(displacements);
5401 void Mesh::GetNodes(
Vector &node_coord)
const
5405 node_coord = (*Nodes);
5409 GetVertices(node_coord);
5413 void Mesh::SetNodes(
const Vector &node_coord)
5417 (*Nodes) = node_coord;
5421 SetVertices(node_coord);
5427 if (own_nodes) {
delete Nodes; }
5430 own_nodes = (int)make_owner;
5441 mfem::Swap<GridFunction*>(Nodes, nodes);
5442 mfem::Swap<int>(own_nodes, own_nodes_);
5449 void Mesh::AverageVertices(
int * indexes,
int n,
int result)
5453 for (k = 0; k < spaceDim; k++)
5455 vertices[result](k) = vertices[indexes[0]](k);
5458 for (j = 1; j < n; j++)
5459 for (k = 0; k < spaceDim; k++)
5461 vertices[result](k) += vertices[indexes[j]](k);
5464 for (k = 0; k < spaceDim; k++)
5466 vertices[result](k) *= (1.0 / n);
5470 void Mesh::UpdateNodes()
5474 Nodes->FESpace()->Update();
5479 void Mesh::QuadUniformRefinement()
5481 int i, j, *v, vv[2], attr;
5484 if (el_to_edge == NULL)
5486 el_to_edge =
new Table;
5487 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5490 int oedge = NumOfVertices;
5491 int oelem = oedge + NumOfEdges;
5493 vertices.SetSize(oelem + NumOfElements);
5495 for (i = 0; i < NumOfElements; i++)
5497 v = elements[i]->GetVertices();
5499 AverageVertices(v, 4, oelem+i);
5501 e = el_to_edge->GetRow(i);
5503 vv[0] = v[0], vv[1] = v[1]; AverageVertices(vv, 2, oedge+e[0]);
5504 vv[0] = v[1], vv[1] = v[2]; AverageVertices(vv, 2, oedge+e[1]);
5505 vv[0] = v[2], vv[1] = v[3]; AverageVertices(vv, 2, oedge+e[2]);
5506 vv[0] = v[3], vv[1] = v[0]; AverageVertices(vv, 2, oedge+e[3]);
5509 elements.SetSize(4 * NumOfElements);
5510 for (i = 0; i < NumOfElements; i++)
5512 attr = elements[i]->GetAttribute();
5513 v = elements[i]->GetVertices();
5514 e = el_to_edge->GetRow(i);
5515 j = NumOfElements + 3 * i;
5517 elements[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5519 elements[j+1] =
new Quadrilateral(oelem+i, oedge+e[1], v[2],
5521 elements[j+2] =
new Quadrilateral(oedge+e[3], oelem+i, oedge+e[2],
5529 boundary.SetSize(2 * NumOfBdrElements);
5530 for (i = 0; i < NumOfBdrElements; i++)
5532 attr = boundary[i]->GetAttribute();
5533 v = boundary[i]->GetVertices();
5534 j = NumOfBdrElements + i;
5536 boundary[j] =
new Segment(oedge+be_to_edge[i], v[1], attr);
5538 v[1] = oedge+be_to_edge[i];
5541 static double quad_children[2*4*4] =
5543 0.0,0.0, 0.5,0.0, 0.5,0.5, 0.0,0.5,
5544 0.5,0.0, 1.0,0.0, 1.0,0.5, 0.5,0.5,
5545 0.5,0.5, 1.0,0.5, 1.0,1.0, 0.5,1.0,
5546 0.0,0.5, 0.5,0.5, 0.5,1.0, 0.0,1.0
5549 CoarseFineTr.point_matrices.UseExternalData(quad_children, 2, 4, 4);
5550 CoarseFineTr.embeddings.SetSize(elements.Size());
5552 for (i = 0; i < elements.Size(); i++)
5554 Embedding &emb = CoarseFineTr.embeddings[i];
5555 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 3;
5556 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 3 + 1;
5559 NumOfVertices = oelem + NumOfElements;
5560 NumOfElements = 4 * NumOfElements;
5561 NumOfBdrElements = 2 * NumOfBdrElements;
5564 if (el_to_edge != NULL)
5566 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5570 last_operation = Mesh::REFINE;
5576 CheckElementOrientation(
false);
5577 CheckBdrElementOrientation(
false);
5581 void Mesh::HexUniformRefinement()
5588 if (el_to_edge == NULL)
5590 el_to_edge =
new Table;
5591 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5593 if (el_to_face == NULL)
5595 GetElementToFaceTable();
5598 int oedge = NumOfVertices;
5599 int oface = oedge + NumOfEdges;
5600 int oelem = oface + NumOfFaces;
5602 vertices.SetSize(oelem + NumOfElements);
5603 for (i = 0; i < NumOfElements; i++)
5605 MFEM_ASSERT(elements[i]->GetType() == Element::HEXAHEDRON,
5606 "Element is not a hex!");
5607 v = elements[i]->GetVertices();
5609 AverageVertices(v, 8, oelem+i);
5611 f = el_to_face->GetRow(i);
5613 for (
int j = 0; j < 6; j++)
5615 for (
int k = 0; k < 4; k++)
5617 vv[k] = v[hex_t::FaceVert[j][k]];
5619 AverageVertices(vv, 4, oface+f[j]);
5622 e = el_to_edge->GetRow(i);
5624 for (
int j = 0; j < 12; j++)
5626 for (
int k = 0; k < 2; k++)
5628 vv[k] = v[hex_t::Edges[j][k]];
5630 AverageVertices(vv, 2, oedge+e[j]);
5635 elements.SetSize(8 * NumOfElements);
5636 for (i = 0; i < NumOfElements; i++)
5638 attr = elements[i]->GetAttribute();
5639 v = elements[i]->GetVertices();
5640 e = el_to_edge->GetRow(i);
5641 f = el_to_face->GetRow(i);
5642 j = NumOfElements + 7 * i;
5644 elements[j+0] =
new Hexahedron(oedge+e[0], v[1], oedge+e[1], oface+f[0],
5645 oface+f[1], oedge+e[9], oface+f[2],
5647 elements[j+1] =
new Hexahedron(oface+f[0], oedge+e[1], v[2], oedge+e[2],
5648 oelem+i, oface+f[2], oedge+e[10],
5650 elements[j+2] =
new Hexahedron(oedge+e[3], oface+f[0], oedge+e[2], v[3],
5651 oface+f[4], oelem+i, oface+f[3],
5653 elements[j+3] =
new Hexahedron(oedge+e[8], oface+f[1], oelem+i,
5654 oface+f[4], v[4], oedge+e[4], oface+f[5],
5656 elements[j+4] =
new Hexahedron(oface+f[1], oedge+e[9], oface+f[2],
5657 oelem+i, oedge+e[4], v[5], oedge+e[5],
5659 elements[j+5] =
new Hexahedron(oelem+i, oface+f[2], oedge+e[10],
5660 oface+f[3], oface+f[5], oedge+e[5], v[6],
5662 elements[j+6] =
new Hexahedron(oface+f[4], oelem+i, oface+f[3],
5663 oedge+e[11], oedge+e[7], oface+f[5],
5664 oedge+e[6], v[7], attr);
5675 boundary.SetSize(4 * NumOfBdrElements);
5676 for (i = 0; i < NumOfBdrElements; i++)
5678 MFEM_ASSERT(boundary[i]->GetType() == Element::QUADRILATERAL,
5679 "boundary Element is not a quad!");
5680 attr = boundary[i]->GetAttribute();
5681 v = boundary[i]->GetVertices();
5682 e = bel_to_edge->GetRow(i);
5683 f = & be_to_face[i];
5684 j = NumOfBdrElements + 3 * i;
5686 boundary[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5688 boundary[j+1] =
new Quadrilateral(oface+f[0], oedge+e[1], v[2],
5690 boundary[j+2] =
new Quadrilateral(oedge+e[3], oface+f[0], oedge+e[2],
5698 static const double A = 0.0, B = 0.5, C = 1.0;
5699 static double hex_children[3*8*8] =
5701 A,A,A, B,A,A, B,B,A, A,B,A, A,A,B, B,A,B, B,B,B, A,B,B,
5702 B,A,A, C,A,A, C,B,A, B,B,A, B,A,B, C,A,B, C,B,B, B,B,B,
5703 B,B,A, C,B,A, C,C,A, B,C,A, B,B,B, C,B,B, C,C,B, B,C,B,
5704 A,B,A, B,B,A, B,C,A, A,C,A, A,B,B, B,B,B, B,C,B, A,C,B,
5705 A,A,B, B,A,B, B,B,B, A,B,B, A,A,C, B,A,C, B,B,C, A,B,C,
5706 B,A,B, C,A,B, C,B,B, B,B,B, B,A,C, C,A,C, C,B,C, B,B,C,
5707 B,B,B, C,B,B, C,C,B, B,C,B, B,B,C, C,B,C, C,C,C, B,C,C,
5708 A,B,B, B,B,B, B,C,B, A,C,B, A,B,C, B,B,C, B,C,C, A,C,C
5711 CoarseFineTr.point_matrices.UseExternalData(hex_children, 3, 8, 8);
5712 CoarseFineTr.embeddings.SetSize(elements.Size());
5714 for (i = 0; i < elements.Size(); i++)
5716 Embedding &emb = CoarseFineTr.embeddings[i];
5717 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 7;
5718 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 7 + 1;
5721 NumOfVertices = oelem + NumOfElements;
5722 NumOfElements = 8 * NumOfElements;
5723 NumOfBdrElements = 4 * NumOfBdrElements;
5725 if (el_to_face != NULL)
5727 GetElementToFaceTable();
5732 CheckBdrElementOrientation(
false);
5735 if (el_to_edge != NULL)
5737 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5740 last_operation = Mesh::REFINE;
5746 void Mesh::LocalRefinement(
const Array<int> &marked_el,
int type)
5748 int i, j, ind, nedges;
5753 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
5756 InitRefinementTransforms();
5760 int cne = NumOfElements, cnv = NumOfVertices;
5761 NumOfVertices += marked_el.
Size();
5762 NumOfElements += marked_el.
Size();
5763 vertices.SetSize(NumOfVertices);
5764 elements.SetSize(NumOfElements);
5765 CoarseFineTr.embeddings.SetSize(NumOfElements);
5767 for (j = 0; j < marked_el.
Size(); j++)
5772 int new_v = cnv + j, new_e = cne + j;
5773 AverageVertices(vert, 2, new_v);
5774 elements[new_e] =
new Segment(new_v, vert[1], attr);
5777 CoarseFineTr.embeddings[i] =
Embedding(i, 1);
5778 CoarseFineTr.embeddings[new_e] =
Embedding(i, 2);
5781 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
5782 CoarseFineTr.point_matrices.UseExternalData(seg_children, 1, 2, 3);
5790 DSTable v_to_v(NumOfVertices);
5791 GetVertexToVertexTable(v_to_v);
5795 int *edge1 =
new int[nedges];
5796 int *edge2 =
new int[nedges];
5797 int *middle =
new int[nedges];
5799 for (i = 0; i < nedges; i++)
5801 edge1[i] = edge2[i] = middle[i] = -1;
5804 for (i = 0; i < NumOfElements; i++)
5806 elements[i]->GetVertices(v);
5807 for (j = 1; j < v.
Size(); j++)
5809 ind = v_to_v(v[j-1], v[j]);
5810 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5812 ind = v_to_v(v[0], v[v.
Size()-1]);
5813 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5817 for (i = 0; i < marked_el.
Size(); i++)
5819 RedRefinement(marked_el[i], v_to_v, edge1, edge2, middle);
5823 int need_refinement;
5826 need_refinement = 0;
5827 for (i = 0; i < nedges; i++)
5829 if (middle[i] != -1 && edge1[i] != -1)
5831 need_refinement = 1;
5832 GreenRefinement(edge1[i], v_to_v, edge1, edge2, middle);
5836 while (need_refinement == 1);
5839 int v1[2], v2[2], bisect, temp;
5840 temp = NumOfBdrElements;
5841 for (i = 0; i < temp; i++)
5843 boundary[i]->GetVertices(v);
5844 bisect = v_to_v(v[0], v[1]);
5845 if (middle[bisect] != -1)
5847 if (boundary[i]->GetType() == Element::SEGMENT)
5849 v1[0] = v[0]; v1[1] = middle[bisect];
5850 v2[0] = middle[bisect]; v2[1] = v[1];
5852 boundary[i]->SetVertices(v1);
5853 boundary.
Append(
new Segment(v2, boundary[i]->GetAttribute()));
5856 mfem_error(
"Only bisection of segment is implemented"
5860 NumOfBdrElements = boundary.Size();
5867 if (el_to_edge != NULL)
5869 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5877 DSTable v_to_v(NumOfVertices);
5878 GetVertexToVertexTable(v_to_v);
5882 int *middle =
new int[nedges];
5884 for (i = 0; i < nedges; i++)
5894 for (i = 0; i < marked_el.
Size(); i++)
5896 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5900 for (i = 0; i < marked_el.
Size(); i++)
5902 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5904 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5905 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5909 for (i = 0; i < marked_el.
Size(); i++)
5911 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5913 ii = NumOfElements - 1;
5914 Bisection(ii, v_to_v, NULL, NULL, middle);
5915 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5916 Bisection(ii, v_to_v, NULL, NULL, middle);
5918 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5919 Bisection(NumOfElements-1, v_to_v, NULL, NULL, middle);
5920 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5926 int need_refinement;
5931 need_refinement = 0;
5934 for (i = 0; i < NumOfElements; i++)
5939 if (elements[i]->NeedRefinement(v_to_v, middle))
5941 need_refinement = 1;
5942 Bisection(i, v_to_v, NULL, NULL, middle);
5946 while (need_refinement == 1);
5953 need_refinement = 0;
5954 for (i = 0; i < NumOfBdrElements; i++)
5955 if (boundary[i]->NeedRefinement(v_to_v, middle))
5957 need_refinement = 1;
5958 Bisection(i, v_to_v, middle);
5961 while (need_refinement == 1);
5964 int refinement_edges[2], type, flag;
5965 for (i = 0; i < NumOfElements; i++)
5970 if (type == Tetrahedron::TYPE_PF)
5977 NumOfBdrElements = boundary.Size();
5982 if (el_to_edge != NULL)
5984 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5986 if (el_to_face != NULL)
5988 GetElementToFaceTable();
5994 last_operation = Mesh::REFINE;
6000 CheckElementOrientation(
false);
6007 MFEM_VERIFY(!NURBSext,
"Nonconforming refinement of NURBS meshes is "
6008 "not supported. Project the NURBS to Nodes first.");
6013 ncmesh =
new NCMesh(
this);
6016 if (!refinements.
Size())
6018 last_operation = Mesh::NONE;
6023 ncmesh->MarkCoarseLevel();
6024 ncmesh->Refine(refinements);
6028 ncmesh->LimitNCLevel(nc_limit);
6033 ncmesh->OnMeshUpdated(mesh2);
6037 Swap(*mesh2,
false);
6040 GenerateNCFaceInfo();
6042 last_operation = Mesh::REFINE;
6047 Nodes->FESpace()->Update();
6054 MFEM_VERIFY(ncmesh,
"only supported for non-conforming meshes.");
6055 MFEM_VERIFY(!NURBSext,
"Derefinement of NURBS meshes is not supported. "
6056 "Project the NURBS to Nodes first.");
6058 ncmesh->Derefine(derefinements);
6061 ncmesh->OnMeshUpdated(mesh2);
6063 Swap(*mesh2,
false);
6066 GenerateNCFaceInfo();
6068 last_operation = Mesh::DEREFINE;
6073 Nodes->FESpace()->Update();
6079 double threshold,
int nc_limit,
int op)
6081 const Table &dt = ncmesh->GetDerefinementTable();
6086 ncmesh->CheckDerefinementNCLevel(dt, level_ok, nc_limit);
6090 for (
int i = 0; i < dt.
Size(); i++)
6092 if (nc_limit > 0 && !level_ok[i]) {
continue; }
6094 const int* fine = dt.
GetRow(i);
6098 for (
int j = 0; j < size; j++)
6100 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
6102 double err_fine = elem_error[fine[j]];
6105 case 0: error = std::min(error, err_fine);
break;
6106 case 1: error += err_fine;
break;
6107 case 2: error = std::max(error, err_fine);
break;
6111 if (error < threshold) { derefs.
Append(i); }
6116 DerefineMesh(derefs);
6124 int nc_limit,
int op)
6128 if (Nonconforming())
6130 return NonconformingDerefinement(elem_error, threshold, nc_limit, op);
6134 MFEM_ABORT(
"Derefinement is currently supported for non-conforming "
6140 bool Mesh::DerefineByError(
const Vector &elem_error,
double threshold,
6141 int nc_limit,
int op)
6144 for (
int i = 0; i < tmp.Size(); i++)
6146 tmp[i] = elem_error(i);
6148 return DerefineByError(tmp, threshold, nc_limit, op);
6152 void Mesh::InitFromNCMesh(
const NCMesh &ncmesh)
6161 case Geometry::TRIANGLE:
6162 case Geometry::SQUARE:
6163 BaseBdrGeom = Geometry::SEGMENT;
6165 case Geometry::CUBE:
6166 BaseBdrGeom = Geometry::SQUARE;
6176 NumOfVertices = vertices.Size();
6177 NumOfElements = elements.Size();
6178 NumOfBdrElements = boundary.Size();
6182 NumOfEdges = NumOfFaces = 0;
6186 el_to_edge =
new Table;
6187 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6191 GetElementToFaceTable();
6195 CheckBdrElementOrientation(
false);
6206 InitFromNCMesh(ncmesh);
6256 const int nv = Geometry::NumVerts[
geom];
6258 for (
int i = 0; i < elem_array.
Size(); i++)
6260 if (elem_array[i]->GetGeometryType() ==
geom)
6265 elem_vtx.
SetSize(nv*num_elems);
6269 for (
int i = 0; i < elem_array.
Size(); i++)
6275 elem_vtx.
Append(loc_vtx);
6280 void Mesh::UniformRefinement()
6284 NURBSUniformRefinement();
6286 else if (meshgen == 1 || ncmesh)
6289 for (
int i = 0; i < elem_to_refine.
Size(); i++)
6291 elem_to_refine[i] = i;
6298 LocalRefinement(elem_to_refine);
6302 GeneralRefinement(elem_to_refine, 1);
6307 QuadUniformRefinement();
6311 HexUniformRefinement();
6320 int nonconforming,
int nc_limit)
6322 if (Dim == 1 || (Dim == 3 && meshgen & 1))
6326 else if (nonconforming < 0)
6329 int geom = GetElementBaseGeometry();
6330 if (geom == Geometry::CUBE || geom == Geometry::SQUARE)
6340 if (nonconforming || ncmesh != NULL)
6343 NonconformingRefinement(refinements, nc_limit);
6348 for (
int i = 0; i < refinements.
Size(); i++)
6350 el_to_refine[i] = refinements[i].index;
6354 int type, rt = (refinements.
Size() ? refinements[0].ref_type : 7);
6355 if (rt == 1 || rt == 2 || rt == 4)
6359 else if (rt == 3 || rt == 5 || rt == 6)
6369 LocalRefinement(el_to_refine, type);
6373 void Mesh::GeneralRefinement(
const Array<int> &el_to_refine,
int nonconforming,
6377 for (
int i = 0; i < el_to_refine.
Size(); i++)
6379 refinements[i] =
Refinement(el_to_refine[i]);
6381 GeneralRefinement(refinements, nonconforming, nc_limit);
6384 void Mesh::EnsureNCMesh(
bool triangles_nonconforming)
6386 MFEM_VERIFY(!NURBSext,
"Cannot convert a NURBS mesh to an NC mesh. "
6387 "Project the NURBS to Nodes first.");
6391 if ((meshgen & 2) ||
6392 (triangles_nonconforming && BaseGeom == Geometry::TRIANGLE))
6394 ncmesh =
new NCMesh(
this);
6395 ncmesh->OnMeshUpdated(
this);
6396 GenerateNCFaceInfo();
6401 void Mesh::RandomRefinement(
double prob,
bool aniso,
int nonconforming,
6405 for (
int i = 0; i < GetNE(); i++)
6407 if ((
double) rand() / RAND_MAX < prob)
6412 type = (Dim == 3) ? (rand() % 7 + 1) : (rand() % 3 + 1);
6417 GeneralRefinement(refs, nonconforming, nc_limit);
6420 void Mesh::RefineAtVertex(
const Vertex& vert,
double eps,
int nonconforming)
6424 for (
int i = 0; i < GetNE(); i++)
6426 GetElementVertices(i, v);
6427 bool refine =
false;
6428 for (
int j = 0; j < v.
Size(); j++)
6431 for (
int l = 0; l < spaceDim; l++)
6433 double d = vert(l) - vertices[v[j]](l);
6436 if (dist <= eps*eps) { refine =
true;
break; }
6443 GeneralRefinement(refs, nonconforming);
6447 int nonconforming,
int nc_limit)
6449 MFEM_VERIFY(elem_error.
Size() == GetNE(),
"");
6451 for (
int i = 0; i < GetNE(); i++)
6453 if (elem_error[i] > threshold)
6458 if (ReduceInt(refs.Size()))
6460 GeneralRefinement(refs, nonconforming, nc_limit);
6466 bool Mesh::RefineByError(
const Vector &elem_error,
double threshold,
6467 int nonconforming,
int nc_limit)
6471 return RefineByError(tmp, threshold, nonconforming, nc_limit);
6475 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
6476 int *edge1,
int *edge2,
int *middle)
6479 int v[2][4], v_new, bisect, t;
6484 if (t == Element::TRIANGLE)
6491 bisect = v_to_v(vert[0], vert[1]);
6492 MFEM_ASSERT(bisect >= 0,
"");
6494 if (middle[bisect] == -1)
6496 v_new = NumOfVertices++;
6497 for (
int d = 0; d < spaceDim; d++)
6499 V(d) = 0.5 * (vertices[vert[0]](d) + vertices[vert[1]](d));
6505 if (edge1[bisect] == i)
6507 edge1[bisect] = edge2[bisect];
6510 middle[bisect] = v_new;
6514 v_new = middle[bisect];
6522 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6523 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6528 elements.Append(tri_new);
6537 int coarse = FindCoarseElement(i);
6538 CoarseFineTr.embeddings[i].parent = coarse;
6539 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6544 bisect = v_to_v(v[1][0], v[1][1]);
6545 MFEM_ASSERT(bisect >= 0,
"");
6547 if (edge1[bisect] == i)
6549 edge1[bisect] = NumOfElements;
6551 else if (edge2[bisect] == i)
6553 edge2[bisect] = NumOfElements;
6558 else if (t == Element::TETRAHEDRON)
6560 int j, type, new_type, old_redges[2], new_redges[2][2], flag;
6564 "TETRAHEDRON element is not marked for refinement.");
6569 bisect = v_to_v(vert[0], vert[1]);
6573 mfem::err <<
"Error in Bisection(...) of tetrahedron!" << endl
6574 <<
" redge[0] = " << old_redges[0]
6575 <<
" redge[1] = " << old_redges[1]
6576 <<
" type = " << type
6577 <<
" flag = " << flag << endl;
6581 if (middle[bisect] == -1)
6583 v_new = NumOfVertices++;
6584 for (j = 0; j < 3; j++)
6586 V(j) = 0.5 * (vertices[vert[0]](j) + vertices[vert[1]](j));
6590 middle[bisect] = v_new;
6594 v_new = middle[bisect];
6603 new_redges[0][0] = 2;
6604 new_redges[0][1] = 1;
6605 new_redges[1][0] = 2;
6606 new_redges[1][1] = 1;
6607 int tr1 = -1, tr2 = -1;
6608 switch (old_redges[0])
6611 v[0][0] = vert[0]; v[0][1] = vert[2]; v[0][2] = vert[3];
6612 if (type == Tetrahedron::TYPE_PF) { new_redges[0][1] = 4; }
6616 v[0][0] = vert[3]; v[0][1] = vert[0]; v[0][2] = vert[2];
6620 v[0][0] = vert[2]; v[0][1] = vert[3]; v[0][2] = vert[0];
6623 switch (old_redges[1])
6626 v[1][0] = vert[2]; v[1][1] = vert[1]; v[1][2] = vert[3];
6627 if (type == Tetrahedron::TYPE_PF) { new_redges[1][0] = 3; }
6631 v[1][0] = vert[1]; v[1][1] = vert[3]; v[1][2] = vert[2];
6635 v[1][0] = vert[3]; v[1][1] = vert[2]; v[1][2] = vert[1];
6642 #ifdef MFEM_USE_MEMALLOC
6650 elements.Append(tet2);
6656 int coarse = FindCoarseElement(i);
6657 CoarseFineTr.embeddings[i].parent = coarse;
6658 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6663 case Tetrahedron::TYPE_PU:
6664 new_type = Tetrahedron::TYPE_PF;
break;
6665 case Tetrahedron::TYPE_PF:
6666 new_type = Tetrahedron::TYPE_A;
break;
6668 new_type = Tetrahedron::TYPE_PU;
6678 MFEM_ABORT(
"Bisection for now works only for triangles & tetrahedra.");
6682 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
int *middle)
6685 int v[2][3], v_new, bisect, t;
6686 Element *bdr_el = boundary[i];
6689 if (t == Element::TRIANGLE)
6696 bisect = v_to_v(vert[0], vert[1]);
6697 MFEM_ASSERT(bisect >= 0,
"");
6698 v_new = middle[bisect];
6699 MFEM_ASSERT(v_new != -1,
"");
6703 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6704 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6714 MFEM_ABORT(
"Bisection of boundary elements works only for triangles!");
6718 void Mesh::UniformRefinement(
int i,
const DSTable &v_to_v,
6719 int *edge1,
int *edge2,
int *middle)
6722 int j, v1[3], v2[3], v3[3], v4[3], v_new[3], bisect[3];
6725 if (elements[i]->GetType() == Element::TRIANGLE)
6731 bisect[0] = v_to_v(v[0],v[1]);
6732 bisect[1] = v_to_v(v[1],v[2]);
6733 bisect[2] = v_to_v(v[0],v[2]);
6734 MFEM_ASSERT(bisect[0] >= 0 && bisect[1] >= 0 && bisect[2] >= 0,
"");
6736 for (j = 0; j < 3; j++)
6738 if (middle[bisect[j]] == -1)
6740 v_new[j] = NumOfVertices++;
6741 for (
int d = 0; d < spaceDim; d++)
6743 V(d) = (vertices[v[j]](d) + vertices[v[(j+1)%3]](d))/2.;
6749 if (edge1[bisect[j]] == i)
6751 edge1[bisect[j]] = edge2[bisect[j]];
6754 middle[bisect[j]] = v_new[j];
6758 v_new[j] = middle[bisect[j]];
6761 edge1[bisect[j]] = -1;
6767 v1[0] = v[0]; v1[1] = v_new[0]; v1[2] = v_new[2];
6768 v2[0] = v_new[0]; v2[1] = v[1]; v2[2] = v_new[1];
6769 v3[0] = v_new[2]; v3[1] = v_new[1]; v3[2] = v[2];
6770 v4[0] = v_new[1]; v4[1] = v_new[2]; v4[2] = v_new[0];
6776 elements.Append(tri1);
6777 elements.Append(tri2);
6778 elements.Append(tri3);
6785 tri2->ResetTransform(code);
6786 tri3->ResetTransform(code);
6790 tri2->PushTransform(1);
6791 tri3->PushTransform(2);
6794 int coarse = FindCoarseElement(i);
6795 CoarseFineTr.embeddings[i] =
Embedding(coarse);
6796 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6797 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6798 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6804 MFEM_ABORT(
"Uniform refinement for now works only for triangles.");
6808 void Mesh::InitRefinementTransforms()
6811 CoarseFineTr.point_matrices.SetSize(0, 0, 0);
6812 CoarseFineTr.embeddings.SetSize(NumOfElements);
6813 for (
int i = 0; i < NumOfElements; i++)
6815 elements[i]->ResetTransform(0);
6816 CoarseFineTr.embeddings[i] =
Embedding(i);
6820 int Mesh::FindCoarseElement(
int i)
6823 while ((coarse = CoarseFineTr.embeddings[i].parent) != i)
6832 MFEM_VERIFY(GetLastOperation() == Mesh::REFINE,
"");
6836 return ncmesh->GetRefinementTransforms();
6839 if (!CoarseFineTr.point_matrices.SizeK())
6841 if (BaseGeom == Geometry::TRIANGLE ||
6842 BaseGeom == Geometry::TETRAHEDRON)
6844 std::map<unsigned, int> mat_no;
6848 for (
int i = 0; i < elements.Size(); i++)
6851 unsigned code = elements[i]->GetTransform();
6854 int &matrix = mat_no[code];
6855 if (!matrix) { matrix = mat_no.size(); }
6858 CoarseFineTr.embeddings[i].matrix = index;
6862 pmats.
SetSize(Dim, Dim+1, mat_no.size());
6865 std::map<unsigned, int>::iterator it;
6866 for (it = mat_no.begin(); it != mat_no.end(); ++it)
6868 if (BaseGeom == Geometry::TRIANGLE)
6870 Triangle::GetPointMatrix(it->first, pmats(it->second-1));
6874 Tetrahedron::GetPointMatrix(it->first, pmats(it->second-1));
6880 MFEM_ABORT(
"Don't know how to construct CoarseFineTr.");
6885 return CoarseFineTr;
6888 void Mesh::PrintXG(std::ostream &
out)
const
6890 MFEM_ASSERT(Dim==spaceDim,
"2D Manifold meshes not supported");
6899 out <<
"areamesh2\n\n";
6903 out <<
"curved_areamesh2\n\n";
6907 out << NumOfBdrElements <<
'\n';
6908 for (i = 0; i < NumOfBdrElements; i++)
6910 boundary[i]->GetVertices(v);
6912 out << boundary[i]->GetAttribute();
6913 for (j = 0; j < v.
Size(); j++)
6915 out <<
' ' << v[j] + 1;
6921 out << NumOfElements <<
'\n';
6922 for (i = 0; i < NumOfElements; i++)
6924 elements[i]->GetVertices(v);
6926 out << elements[i]->GetAttribute() <<
' ' << v.
Size();
6927 for (j = 0; j < v.
Size(); j++)
6929 out <<
' ' << v[j] + 1;
6937 out << NumOfVertices <<
'\n';
6938 for (i = 0; i < NumOfVertices; i++)
6940 out << vertices[i](0);
6941 for (j = 1; j < Dim; j++)
6943 out <<
' ' << vertices[i](j);
6950 out << NumOfVertices <<
'\n';
6958 mfem_error(
"Mesh::PrintXG(...) : Curved mesh in 3D");
6966 out <<
"NETGEN_Neutral_Format\n";
6968 out << NumOfVertices <<
'\n';
6969 for (i = 0; i < NumOfVertices; i++)
6971 for (j = 0; j < Dim; j++)
6973 out <<
' ' << vertices[i](j);
6979 out << NumOfElements <<
'\n';
6980 for (i = 0; i < NumOfElements; i++)
6982 nv = elements[i]->GetNVertices();
6983 ind = elements[i]->GetVertices();
6984 out << elements[i]->GetAttribute();
6985 for (j = 0; j < nv; j++)
6987 out <<
' ' << ind[j]+1;
6993 out << NumOfBdrElements <<
'\n';
6994 for (i = 0; i < NumOfBdrElements; i++)
6996 nv = boundary[i]->GetNVertices();
6997 ind = boundary[i]->GetVertices();
6998 out << boundary[i]->GetAttribute();
6999 for (j = 0; j < nv; j++)
7001 out <<
' ' << ind[j]+1;
7006 else if (meshgen == 2)
7012 <<
"1 " << NumOfVertices <<
" " << NumOfElements
7013 <<
" 0 0 0 0 0 0 0\n"
7014 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
7015 <<
"0 0 " << NumOfBdrElements <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
7016 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
7017 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
7019 for (i = 0; i < NumOfVertices; i++)
7020 out << i+1 <<
" 0.0 " << vertices[i](0) <<
' ' << vertices[i](1)
7021 <<
' ' << vertices[i](2) <<
" 0.0\n";
7023 for (i = 0; i < NumOfElements; i++)
7025 nv = elements[i]->GetNVertices();
7026 ind = elements[i]->GetVertices();
7027 out << i+1 <<
' ' << elements[i]->GetAttribute();
7028 for (j = 0; j < nv; j++)
7030 out <<
' ' << ind[j]+1;
7035 for (i = 0; i < NumOfBdrElements; i++)
7037 nv = boundary[i]->GetNVertices();
7038 ind = boundary[i]->GetVertices();
7039 out << boundary[i]->GetAttribute();
7040 for (j = 0; j < nv; j++)
7042 out <<
' ' << ind[j]+1;
7044 out <<
" 1.0 1.0 1.0 1.0\n";
7052 void Mesh::Printer(std::ostream &
out, std::string section_delimiter)
const
7059 NURBSext->Print(out);
7070 out << (ncmesh ?
"MFEM mesh v1.1\n" :
7071 section_delimiter.empty() ?
"MFEM mesh v1.0\n" :
7072 "MFEM mesh v1.2\n");
7076 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7081 "# TETRAHEDRON = 4\n"
7085 out <<
"\ndimension\n" << Dim
7086 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7087 for (i = 0; i < NumOfElements; i++)
7089 PrintElement(elements[i], out);
7092 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
7093 for (i = 0; i < NumOfBdrElements; i++)
7095 PrintElement(boundary[i], out);
7100 out <<
"\nvertex_parents\n";
7101 ncmesh->PrintVertexParents(out);
7103 out <<
"\ncoarse_elements\n";
7104 ncmesh->PrintCoarseElements(out);
7107 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7110 out << spaceDim <<
'\n';
7111 for (i = 0; i < NumOfVertices; i++)
7113 out << vertices[i](0);
7114 for (j = 1; j < spaceDim; j++)
7116 out <<
' ' << vertices[i](j);
7128 if (!ncmesh && !section_delimiter.empty())
7130 out << section_delimiter << endl;
7139 out <<
"MFEM NURBS mesh v1.0\n";
7143 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7149 out <<
"\ndimension\n" << Dim
7150 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7151 for (i = 0; i < NumOfElements; i++)
7153 PrintElement(elements[i], out);
7156 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
7157 for (i = 0; i < NumOfBdrElements; i++)
7159 PrintElement(boundary[i], out);
7162 out <<
"\nedges\n" << NumOfEdges <<
'\n';
7163 for (i = 0; i < NumOfEdges; i++)
7165 edge_vertex->GetRow(i, vert);
7171 out << ki <<
' ' << vert[0] <<
' ' << vert[1] <<
'\n';
7173 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7176 void Mesh::PrintVTK(std::ostream &
out)
7179 "# vtk DataFile Version 3.0\n"
7180 "Generated by MFEM\n"
7182 "DATASET UNSTRUCTURED_GRID\n";
7186 out <<
"POINTS " << NumOfVertices <<
" double\n";
7187 for (
int i = 0; i < NumOfVertices; i++)
7189 out << vertices[i](0);
7191 for (j = 1; j < spaceDim; j++)
7193 out <<
' ' << vertices[i](j);
7205 out <<
"POINTS " << Nodes->FESpace()->GetNDofs() <<
" double\n";
7206 for (
int i = 0; i < Nodes->FESpace()->GetNDofs(); i++)
7210 Nodes->FESpace()->DofsToVDofs(vdofs);
7211 out << (*Nodes)(vdofs[0]);
7213 for (j = 1; j < spaceDim; j++)
7215 out <<
' ' << (*Nodes)(vdofs[j]);
7229 for (
int i = 0; i < NumOfElements; i++)
7231 size += elements[i]->GetNVertices() + 1;
7233 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
7234 for (
int i = 0; i < NumOfElements; i++)
7236 const int *v = elements[i]->GetVertices();
7237 const int nv = elements[i]->GetNVertices();
7239 for (
int j = 0; j < nv; j++)
7251 for (
int i = 0; i < NumOfElements; i++)
7253 Nodes->FESpace()->GetElementDofs(i, dofs);
7254 size += dofs.
Size() + 1;
7256 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
7257 const char *fec_name = Nodes->FESpace()->FEColl()->Name();
7258 if (!strcmp(fec_name,
"Linear") ||
7259 !strcmp(fec_name,
"H1_2D_P1") ||
7260 !strcmp(fec_name,
"H1_3D_P1"))
7264 else if (!strcmp(fec_name,
"Quadratic") ||
7265 !strcmp(fec_name,
"H1_2D_P2") ||
7266 !strcmp(fec_name,
"H1_3D_P2"))
7272 mfem::err <<
"Mesh::PrintVTK : can not save '"
7273 << fec_name <<
"' elements!" << endl;
7276 for (
int i = 0; i < NumOfElements; i++)