15 #include "../fem/fem.hpp"
16 #include "../general/sort_pairs.hpp"
17 #include "../general/binaryio.hpp"
18 #include "../general/text.hpp"
19 #include "../general/device.hpp"
20 #include "../general/tic_toc.hpp"
21 #include "../general/gecko.hpp"
22 #include "../fem/quadinterpolator.hpp"
37 #if defined(MFEM_USE_METIS) && defined(MFEM_USE_METIS_5)
42 #if defined(MFEM_USE_METIS) && !defined(MFEM_USE_METIS_5)
47 int*,
int*,
int*,
int*,
int*,
idxtype*);
49 int*,
int*,
int*,
int*,
int*,
idxtype*);
51 int*,
int*,
int*,
int*,
int*,
idxtype*);
68 void Mesh::GetElementCenter(
int i,
Vector ¢er)
71 int geom = GetElementBaseGeometry(i);
98 double Mesh::GetElementSize(
int i,
int type)
100 return GetElementSize(GetElementTransformation(i), type);
103 double Mesh::GetElementSize(
int i,
const Vector &dir)
107 GetElementJacobian(i, J);
109 return sqrt((d_hat * d_hat) / (dir * dir));
112 double Mesh::GetElementVolume(
int i)
134 for (
int d = 0; d < spaceDim; d++)
143 for (
int i = 0; i < NumOfVertices; i++)
145 coord = GetVertex(i);
146 for (
int d = 0; d < spaceDim; d++)
148 if (coord[d] < min(d)) { min(d) = coord[d]; }
149 if (coord[d] > max(d)) { max(d) = coord[d]; }
155 const bool use_boundary =
false;
156 int ne = use_boundary ? GetNBE() : GetNE();
164 for (
int i = 0; i < ne; i++)
168 GetBdrElementFace(i, &fn, &fo);
170 Tr = GetFaceElementTransformations(fn, 5);
177 T = GetElementTransformation(i);
181 for (
int j = 0; j < pointmat.
Width(); j++)
183 for (
int d = 0; d < pointmat.
Height(); d++)
185 if (pointmat(d,j) < min(d)) { min(d) = pointmat(d,j); }
186 if (pointmat(d,j) > max(d)) { max(d) = pointmat(d,j); }
193 void Mesh::GetCharacteristics(
double &h_min,
double &h_max,
194 double &kappa_min,
double &kappa_max,
202 sdim = SpaceDimension();
204 if (Vh) { Vh->
SetSize(NumOfElements); }
205 if (Vk) { Vk->
SetSize(NumOfElements); }
208 h_max = kappa_max = -h_min;
209 if (dim == 0) {
if (Vh) { *Vh = 1.0; }
if (Vk) {*Vk = 1.0; }
return; }
211 for (i = 0; i < NumOfElements; i++)
213 GetElementJacobian(i, J);
214 h =
pow(fabs(J.
Weight()), 1.0/
double(dim));
215 kappa = (dim == sdim) ?
217 if (Vh) { (*Vh)(i) = h; }
218 if (Vk) { (*Vk)(i) = kappa; }
220 if (h < h_min) { h_min = h; }
221 if (h > h_max) { h_max = h; }
222 if (kappa < kappa_min) { kappa_min =
kappa; }
223 if (kappa > kappa_max) { kappa_max =
kappa; }
228 void Mesh::PrintElementsByGeometry(
int dim,
232 for (
int g = Geometry::DimStart[dim], first = 1;
233 g < Geometry::DimStart[dim+1]; g++)
235 if (!num_elems_by_geom[g]) {
continue; }
236 if (!first) { os <<
" + "; }
238 os << num_elems_by_geom[g] <<
' ' << Geometry::Name[g] <<
"(s)";
242 void Mesh::PrintCharacteristics(
Vector *Vh,
Vector *Vk, std::ostream &os)
244 double h_min, h_max, kappa_min, kappa_max;
246 os <<
"Mesh Characteristics:";
248 this->GetCharacteristics(h_min, h_max, kappa_min, kappa_max, Vh, Vk);
250 Array<int> num_elems_by_geom(Geometry::NumGeom);
251 num_elems_by_geom = 0;
252 for (
int i = 0; i < GetNE(); i++)
254 num_elems_by_geom[GetElementBaseGeometry(i)]++;
258 <<
"Dimension : " << Dimension() <<
'\n'
259 <<
"Space dimension : " << SpaceDimension();
263 <<
"Number of vertices : " << GetNV() <<
'\n'
264 <<
"Number of elements : " << GetNE() <<
'\n'
265 <<
"Number of bdr elem : " << GetNBE() <<
'\n';
270 <<
"Number of vertices : " << GetNV() <<
'\n'
271 <<
"Number of elements : " << GetNE() <<
'\n'
272 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
273 <<
"h_min : " << h_min <<
'\n'
274 <<
"h_max : " << h_max <<
'\n';
279 <<
"Number of vertices : " << GetNV() <<
'\n'
280 <<
"Number of edges : " << GetNEdges() <<
'\n'
281 <<
"Number of elements : " << GetNE() <<
" -- ";
282 PrintElementsByGeometry(2, num_elems_by_geom, os);
284 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
285 <<
"Euler Number : " << EulerNumber2D() <<
'\n'
286 <<
"h_min : " << h_min <<
'\n'
287 <<
"h_max : " << h_max <<
'\n'
288 <<
"kappa_min : " << kappa_min <<
'\n'
289 <<
"kappa_max : " << kappa_max <<
'\n';
293 Array<int> num_bdr_elems_by_geom(Geometry::NumGeom);
294 num_bdr_elems_by_geom = 0;
295 for (
int i = 0; i < GetNBE(); i++)
297 num_bdr_elems_by_geom[GetBdrElementBaseGeometry(i)]++;
299 Array<int> num_faces_by_geom(Geometry::NumGeom);
300 num_faces_by_geom = 0;
301 for (
int i = 0; i < GetNFaces(); i++)
303 num_faces_by_geom[GetFaceBaseGeometry(i)]++;
307 <<
"Number of vertices : " << GetNV() <<
'\n'
308 <<
"Number of edges : " << GetNEdges() <<
'\n'
309 <<
"Number of faces : " << GetNFaces() <<
" -- ";
310 PrintElementsByGeometry(Dim-1, num_faces_by_geom, os);
312 <<
"Number of elements : " << GetNE() <<
" -- ";
313 PrintElementsByGeometry(Dim, num_elems_by_geom, os);
315 <<
"Number of bdr elem : " << GetNBE() <<
" -- ";
316 PrintElementsByGeometry(Dim-1, num_bdr_elems_by_geom, os);
318 <<
"Euler Number : " << EulerNumber() <<
'\n'
319 <<
"h_min : " << h_min <<
'\n'
320 <<
"h_max : " << h_max <<
'\n'
321 <<
"kappa_min : " << kappa_min <<
'\n'
322 <<
"kappa_max : " << kappa_max <<
'\n';
324 os <<
'\n' << std::flush;
331 case Element::POINT :
return &
PointFE;
332 case Element::SEGMENT :
return &
SegmentFE;
337 case Element::WEDGE :
return &
WedgeFE;
338 case Element::PYRAMID :
return &
PyramidFE;
340 MFEM_ABORT(
"Unknown element type \"" << ElemType <<
"\"");
343 MFEM_ABORT(
"Unknown element type");
352 ElTr->
ElementType = ElementTransformation::ELEMENT;
358 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
364 Nodes->FESpace()->GetElementVDofs(i, vdofs);
367 int n = vdofs.
Size()/spaceDim;
369 for (
int k = 0; k < spaceDim; k++)
371 for (
int j = 0; j < n; j++)
373 pm(k,j) = nodes(vdofs[n*k+j]);
376 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
380 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
385 ElTr->
ElementType = ElementTransformation::ELEMENT;
392 MFEM_ASSERT(nodes.
Size() == spaceDim*GetNV(),
"");
393 int nv = elements[i]->GetNVertices();
394 const int *v = elements[i]->GetVertices();
395 int n = vertices.Size();
397 for (
int k = 0; k < spaceDim; k++)
399 for (
int j = 0; j < nv; j++)
401 pm(k, j) = nodes(k*n+v[j]);
404 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
408 MFEM_ASSERT(nodes.
Size() == Nodes->Size(),
"");
410 Nodes->FESpace()->GetElementVDofs(i, vdofs);
411 int n = vdofs.
Size()/spaceDim;
413 for (
int k = 0; k < spaceDim; k++)
415 for (
int j = 0; j < n; j++)
417 pm(k,j) = nodes(vdofs[n*k+j]);
420 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
426 GetElementTransformation(i, &Transformation);
428 return &Transformation;
433 GetBdrElementTransformation(i, &BdrTransformation);
434 return &BdrTransformation;
441 ElTr->
ElementType = ElementTransformation::BDR_ELEMENT;
447 GetBdrPointMatrix(i, pm);
448 ElTr->
SetFE(GetTransformationFEforElementType(GetBdrElementType(i)));
458 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
459 int n = vdofs.
Size()/spaceDim;
461 for (
int k = 0; k < spaceDim; k++)
463 for (
int j = 0; j < n; j++)
465 pm(k,j) = nodes(vdofs[n*k+j]);
472 int elem_id, face_info;
473 GetBdrElementAdjacentElement(i, elem_id, face_info);
475 GetLocalFaceTransformation(GetBdrElementType(i),
476 GetElementType(elem_id),
477 FaceElemTr.Loc1.Transf, face_info);
482 Nodes->FESpace()->GetTraceElement(elem_id, face_geom);
483 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
484 "Mesh requires nodal Finite Element.");
486 FaceElemTr.Loc1.Transf.ElementNo = elem_id;
487 FaceElemTr.Loc1.Transf.mesh =
this;
488 FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
489 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
490 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
492 ElTr->
SetFE(face_el);
499 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
507 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
508 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
510 for (
int i = 0; i < spaceDim; i++)
512 for (
int j = 0; j < nv; j++)
514 pm(i, j) = vertices[v[j]](i);
517 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
521 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
527 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
528 int n = vdofs.
Size()/spaceDim;
530 for (
int i = 0; i < spaceDim; i++)
532 for (
int j = 0; j < n; j++)
534 pm(i, j) = nodes(vdofs[n*i+j]);
541 FaceInfo &face_info = faces_info[FaceNo];
546 GetLocalFaceTransformation(face_type,
547 GetElementType(face_info.
Elem1No),
548 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
551 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
553 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
554 "Mesh requires nodal Finite Element.");
557 FaceElemTr.Loc1.Transf.ElementNo = face_info.
Elem1No;
558 FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
559 FaceElemTr.Loc1.Transf.mesh =
this;
560 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
561 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
570 GetFaceTransformation(FaceNo, &FaceTransformation);
571 return &FaceTransformation;
578 GetFaceTransformation(EdgeNo, EdTr);
583 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
595 GetEdgeVertices(EdgeNo, v);
598 for (
int i = 0; i < spaceDim; i++)
600 for (
int j = 0; j < nv; j++)
602 pm(i, j) = vertices[v[j]](i);
605 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
609 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
615 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
616 int n = vdofs.
Size()/spaceDim;
618 for (
int i = 0; i < spaceDim; i++)
620 for (
int j = 0; j < n; j++)
622 pm(i, j) = nodes(vdofs[n*i+j]);
625 EdTr->
SetFE(edge_el);
629 MFEM_ABORT(
"Not implemented.");
636 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
637 return &EdgeTransformation;
641 void Mesh::GetLocalPtToSegTransformation(
656 void Mesh::GetLocalSegToTriTransformation(
665 tv = tri_t::Edges[i/64];
666 so = seg_t::Orient[i%64];
669 for (
int j = 0; j < 2; j++)
671 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
672 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
676 void Mesh::GetLocalSegToQuadTransformation(
685 qv = quad_t::Edges[i/64];
686 so = seg_t::Orient[i%64];
689 for (
int j = 0; j < 2; j++)
691 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
692 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
696 void Mesh::GetLocalTriToTetTransformation(
704 const int *tv = tet_t::FaceVert[i/64];
707 const int *to = tri_t::Orient[i%64];
711 for (
int j = 0; j < 3; j++)
714 locpm(0, j) = vert.
x;
715 locpm(1, j) = vert.
y;
716 locpm(2, j) = vert.
z;
720 void Mesh::GetLocalTriToWdgTransformation(
728 MFEM_VERIFY(i < 128,
"Local face index " << i/64
729 <<
" is not a triangular face of a wedge.");
730 const int *pv = pri_t::FaceVert[i/64];
733 const int *to = tri_t::Orient[i%64];
737 for (
int j = 0; j < 3; j++)
740 locpm(0, j) = vert.
x;
741 locpm(1, j) = vert.
y;
742 locpm(2, j) = vert.
z;
746 void Mesh::GetLocalTriToPyrTransformation(
753 MFEM_VERIFY(i >= 64,
"Local face index " << i/64
754 <<
" is not a triangular face of a pyramid.");
755 const int *pv = pyr_t::FaceVert[i/64];
758 const int *to = tri_t::Orient[i%64];
762 for (
int j = 0; j < 3; j++)
765 locpm(0, j) = vert.
x;
766 locpm(1, j) = vert.
y;
767 locpm(2, j) = vert.
z;
771 void Mesh::GetLocalQuadToHexTransformation(
779 const int *hv = hex_t::FaceVert[i/64];
781 const int *qo = quad_t::Orient[i%64];
784 for (
int j = 0; j < 4; j++)
787 locpm(0, j) = vert.
x;
788 locpm(1, j) = vert.
y;
789 locpm(2, j) = vert.
z;
793 void Mesh::GetLocalQuadToWdgTransformation(
801 MFEM_VERIFY(i >= 128,
"Local face index " << i/64
802 <<
" is not a quadrilateral face of a wedge.");
803 const int *pv = pri_t::FaceVert[i/64];
805 const int *qo = quad_t::Orient[i%64];
808 for (
int j = 0; j < 4; j++)
811 locpm(0, j) = vert.
x;
812 locpm(1, j) = vert.
y;
813 locpm(2, j) = vert.
z;
817 void Mesh::GetLocalQuadToPyrTransformation(
824 MFEM_VERIFY(i < 64,
"Local face index " << i/64
825 <<
" is not a quadrilateral face of a pyramid.");
826 const int *pv = pyr_t::FaceVert[i/64];
828 const int *qo = quad_t::Orient[i%64];
831 for (
int j = 0; j < 4; j++)
834 locpm(0, j) = vert.
x;
835 locpm(1, j) = vert.
y;
836 locpm(2, j) = vert.
z;
844 for (
int i = 0; i < geom_factors.Size(); i++)
856 geom_factors.Append(gf);
864 for (
int i = 0; i < face_geom_factors.Size(); i++)
877 face_geom_factors.Append(gf);
881 void Mesh::DeleteGeometricFactors()
883 for (
int i = 0; i < geom_factors.Size(); i++)
885 delete geom_factors[i];
887 geom_factors.SetSize(0);
888 for (
int i = 0; i < face_geom_factors.Size(); i++)
890 delete face_geom_factors[i];
892 face_geom_factors.SetSize(0);
895 void Mesh::GetLocalFaceTransformation(
901 GetLocalPtToSegTransformation(Transf, info);
904 case Element::SEGMENT:
905 if (elem_type == Element::TRIANGLE)
907 GetLocalSegToTriTransformation(Transf, info);
911 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
912 GetLocalSegToQuadTransformation(Transf, info);
916 case Element::TRIANGLE:
917 if (elem_type == Element::TETRAHEDRON)
919 GetLocalTriToTetTransformation(Transf, info);
921 else if (elem_type == Element::WEDGE)
923 GetLocalTriToWdgTransformation(Transf, info);
925 else if (elem_type == Element::PYRAMID)
927 GetLocalTriToPyrTransformation(Transf, info);
931 MFEM_ABORT(
"Mesh::GetLocalFaceTransformation not defined for "
932 "face type " << face_type
933 <<
" and element type " << elem_type <<
"\n");
937 case Element::QUADRILATERAL:
938 if (elem_type == Element::HEXAHEDRON)
940 GetLocalQuadToHexTransformation(Transf, info);
942 else if (elem_type == Element::WEDGE)
944 GetLocalQuadToWdgTransformation(Transf, info);
946 else if (elem_type == Element::PYRAMID)
948 GetLocalQuadToPyrTransformation(Transf, info);
952 MFEM_ABORT(
"Mesh::GetLocalFaceTransformation not defined for "
953 "face type " << face_type
954 <<
" and element type " << elem_type <<
"\n");
963 FaceInfo &face_info = faces_info[FaceNo];
966 FaceElemTr.SetConfigurationMask(cmask);
967 FaceElemTr.Elem1 = NULL;
968 FaceElemTr.Elem2 = NULL;
972 if (mask & FaceElementTransformations::HAVE_ELEM1)
974 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
975 FaceElemTr.Elem1 = &Transformation;
982 FaceElemTr.Elem2No = face_info.
Elem2No;
983 if ((mask & FaceElementTransformations::HAVE_ELEM2) &&
984 FaceElemTr.Elem2No >= 0)
987 if (NURBSext && (mask & FaceElementTransformations::HAVE_ELEM1))
988 { MFEM_ABORT(
"NURBS mesh not supported!"); }
990 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
991 FaceElemTr.Elem2 = &Transformation2;
996 if (mask & FaceElementTransformations::HAVE_FACE)
998 GetFaceTransformation(FaceNo, &FaceElemTr);
1003 FaceElemTr.SetGeometryType(GetFaceGeometryType(FaceNo));
1007 int face_type = GetFaceElementType(FaceNo);
1008 if (mask & FaceElementTransformations::HAVE_LOC1)
1010 int elem_type = GetElementType(face_info.
Elem1No);
1011 GetLocalFaceTransformation(face_type, elem_type,
1012 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
1015 if ((mask & FaceElementTransformations::HAVE_LOC2) &&
1016 FaceElemTr.Elem2No >= 0)
1018 int elem_type = GetElementType(face_info.
Elem2No);
1019 GetLocalFaceTransformation(face_type, elem_type,
1020 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
1023 if (Nonconforming() && IsSlaveFace(face_info))
1025 ApplyLocalSlaveTransformation(FaceElemTr, face_info,
false);
1030 FaceElemTr.SetConfigurationMask(cmask);
1036 double dist = FaceElemTr.CheckConsistency();
1039 mfem::out <<
"\nInternal error: face id = " << FaceNo
1040 <<
", dist = " << dist <<
'\n';
1041 FaceElemTr.CheckConsistency(1);
1042 MFEM_ABORT(
"internal error");
1052 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
1058 #ifdef MFEM_THREAD_SAFE
1063 MFEM_ASSERT(fi.
NCFace >= 0,
"");
1064 MFEM_ASSERT(nc_faces_info[fi.
NCFace].Slave,
"internal error");
1075 std::swap(composition(0,0), composition(0,1));
1076 std::swap(composition(1,0), composition(1,1));
1097 int fn = GetBdrFace(BdrElemNo);
1100 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
1104 tr = GetFaceElementTransformations(fn, 21);
1105 tr->
Attribute = boundary[BdrElemNo]->GetAttribute();
1107 tr->
ElementType = ElementTransformation::BDR_FACE;
1112 int Mesh::GetBdrFace(
int BdrElemNo)
const
1117 fn = be_to_face[BdrElemNo];
1121 fn = be_to_edge[BdrElemNo];
1125 fn = boundary[BdrElemNo]->GetVertices()[0];
1136 GetFaceElements(f, &e1, &e2);
1137 GetFaceInfos(f, &inf1, &inf2, &ncface);
1147 if (f < GetNumFaces())
1153 face.
tag = FaceInfoTag::LocalConforming;
1154 face.
topology = FaceTopology::Conforming;
1163 face.
tag = FaceInfoTag::LocalSlaveNonconforming;
1164 face.
topology = FaceTopology::Nonconforming;
1169 MFEM_ASSERT(inf2%64==0,
"unexpected slave face orientation.");
1180 face.
tag = FaceInfoTag::Boundary;
1181 face.
topology = FaceTopology::Boundary;
1190 face.
tag = FaceInfoTag::SharedConforming;
1191 face.
topology = FaceTopology::Conforming;
1203 face.
tag = FaceInfoTag::MasterNonconforming;
1204 face.
topology = FaceTopology::Nonconforming;
1213 face.
tag = FaceInfoTag::SharedSlaveNonconforming;
1214 face.
topology = FaceTopology::Nonconforming;
1229 face.
tag = FaceInfoTag::GhostMaster;
1239 face.
tag = FaceInfoTag::GhostSlave;
1240 face.
topology = FaceTopology::Nonconforming;
1257 case FaceInfoTag::LocalConforming:
1258 res.
Elem1No = element[0].index;
1259 res.Elem2No = element[1].index;
1260 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1261 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1262 res.NCFace = ncface;
1264 case FaceInfoTag::LocalSlaveNonconforming:
1265 res.Elem1No = element[0].index;
1266 res.Elem2No = element[1].index;
1267 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1268 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1269 res.NCFace = ncface;
1271 case FaceInfoTag::Boundary:
1272 res.Elem1No = element[0].index;
1273 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1275 case FaceInfoTag::SharedConforming:
1276 res.Elem1No = element[0].index;
1277 res.Elem2No = -1 - element[1].index;
1278 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1279 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1281 case FaceInfoTag::MasterNonconforming:
1282 res.Elem1No = element[0].index;
1283 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1285 case FaceInfoTag::SharedSlaveNonconforming:
1286 res.Elem1No = element[0].index;
1287 res.Elem2No = -1 - element[1].index;
1288 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1289 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1291 case FaceInfoTag::GhostMaster:
1293 case FaceInfoTag::GhostSlave:
1294 res.Elem1No = element[0].index;
1295 res.Elem2No = -1 - element[1].index;
1296 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1297 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1305 os <<
"face topology=";
1308 case Mesh::FaceTopology::Boundary:
1311 case Mesh::FaceTopology::Conforming:
1314 case Mesh::FaceTopology::Nonconforming:
1315 os <<
"Non-conforming";
1317 case Mesh::FaceTopology::NA:
1321 os <<
"element[0].location=";
1324 case Mesh::ElementLocation::Local:
1327 case Mesh::ElementLocation::FaceNbr:
1330 case Mesh::ElementLocation::NA:
1335 os <<
"element[1].location=";
1338 case Mesh::ElementLocation::Local:
1341 case Mesh::ElementLocation::FaceNbr:
1344 case Mesh::ElementLocation::NA:
1349 os <<
"element[0].conformity=";
1352 case Mesh::ElementConformity::Coincident:
1355 case Mesh::ElementConformity::Superset:
1358 case Mesh::ElementConformity::Subset:
1361 case Mesh::ElementConformity::NA:
1366 os <<
"element[1].conformity=";
1369 case Mesh::ElementConformity::Coincident:
1372 case Mesh::ElementConformity::Superset:
1375 case Mesh::ElementConformity::Subset:
1378 case Mesh::ElementConformity::NA:
1383 os <<
"element[0].index=" << info.
element[0].
index << std::endl
1384 <<
"element[1].index=" << info.
element[1].
index << std::endl
1389 <<
"ncface=" << info.
ncface << std::endl;
1393 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
const
1395 *Elem1 = faces_info[Face].Elem1No;
1396 *Elem2 = faces_info[Face].Elem2No;
1399 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
const
1401 *Inf1 = faces_info[Face].Elem1Inf;
1402 *Inf2 = faces_info[Face].Elem2Inf;
1405 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2,
int *NCFace)
const
1407 *Inf1 = faces_info[Face].Elem1Inf;
1408 *Inf2 = faces_info[Face].Elem2Inf;
1409 *NCFace = faces_info[Face].NCFace;
1416 case 1:
return Geometry::POINT;
1417 case 2:
return Geometry::SEGMENT;
1419 if (Face < NumOfFaces)
1421 return faces[Face]->GetGeometryType();
1424 const int nc_face_id = faces_info[Face].NCFace;
1425 MFEM_ASSERT(nc_face_id >= 0,
"parent ghost faces are not supported");
1426 return faces[nc_faces_info[nc_face_id].MasterFace]->GetGeometryType();
1428 return Geometry::INVALID;
1433 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
1441 NumOfElements = NumOfBdrElements = 0;
1442 NumOfEdges = NumOfFaces = 0;
1443 nbInteriorFaces = -1;
1444 nbBoundaryFaces = -1;
1445 meshgen = mesh_geoms = 0;
1451 last_operation = Mesh::NONE;
1454 void Mesh::InitTables()
1457 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
1460 void Mesh::SetEmpty()
1466 void Mesh::DestroyTables()
1471 DeleteGeometricFactors();
1482 void Mesh::DestroyPointers()
1484 if (own_nodes) {
delete Nodes; }
1490 for (
int i = 0; i < NumOfElements; i++)
1492 FreeElement(elements[i]);
1495 for (
int i = 0; i < NumOfBdrElements; i++)
1497 FreeElement(boundary[i]);
1500 for (
int i = 0; i < faces.Size(); i++)
1502 FreeElement(faces[i]);
1508 void Mesh::Destroy()
1512 elements.DeleteAll();
1513 vertices.DeleteAll();
1514 boundary.DeleteAll();
1516 faces_info.DeleteAll();
1517 nc_faces_info.DeleteAll();
1518 be_to_edge.DeleteAll();
1519 be_to_face.DeleteAll();
1527 CoarseFineTr.Clear();
1529 #ifdef MFEM_USE_MEMALLOC
1533 attributes.DeleteAll();
1534 bdr_attributes.DeleteAll();
1537 void Mesh::ResetLazyData()
1539 delete el_to_el; el_to_el = NULL;
1540 delete face_edge; face_edge = NULL;
1541 delete edge_vertex; edge_vertex = NULL;
1542 DeleteGeometricFactors();
1543 nbInteriorFaces = -1;
1544 nbBoundaryFaces = -1;
1547 void Mesh::SetAttributes()
1552 for (
int i = 0; i < attribs.
Size(); i++)
1554 attribs[i] = GetBdrAttribute(i);
1558 attribs.
Copy(bdr_attributes);
1559 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
1561 MFEM_WARNING(
"Non-positive attributes on the boundary!");
1565 for (
int i = 0; i < attribs.
Size(); i++)
1567 attribs[i] = GetAttribute(i);
1571 attribs.
Copy(attributes);
1572 if (attributes.Size() > 0 && attributes[0] <= 0)
1574 MFEM_WARNING(
"Non-positive attributes in the domain!");
1578 void Mesh::InitMesh(
int Dim_,
int spaceDim_,
int NVert,
int NElem,
int NBdrElem)
1583 spaceDim = spaceDim_;
1586 vertices.SetSize(NVert);
1589 elements.SetSize(NElem);
1591 NumOfBdrElements = 0;
1592 boundary.SetSize(NBdrElem);
1595 template<
typename T>
1596 static void CheckEnlarge(
Array<T> &array,
int size)
1598 if (size >= array.
Size()) { array.
SetSize(size + 1); }
1601 int Mesh::AddVertex(
double x,
double y,
double z)
1603 CheckEnlarge(vertices, NumOfVertices);
1604 double *v = vertices[NumOfVertices]();
1608 return NumOfVertices++;
1611 int Mesh::AddVertex(
const double *coords)
1613 CheckEnlarge(vertices, NumOfVertices);
1614 vertices[NumOfVertices].SetCoords(spaceDim, coords);
1615 return NumOfVertices++;
1618 void Mesh::AddVertexParents(
int i,
int p1,
int p2)
1624 if (i < vertices.Size())
1626 double *vi = vertices[i](), *vp1 = vertices[p1](), *vp2 = vertices[p2]();
1627 for (
int j = 0; j < 3; j++)
1629 vi[j] = (vp1[j] + vp2[j]) * 0.5;
1634 int Mesh::AddSegment(
int v1,
int v2,
int attr)
1636 CheckEnlarge(elements, NumOfElements);
1637 elements[NumOfElements] =
new Segment(v1, v2, attr);
1638 return NumOfElements++;
1641 int Mesh::AddSegment(
const int *vi,
int attr)
1643 CheckEnlarge(elements, NumOfElements);
1644 elements[NumOfElements] =
new Segment(vi, attr);
1645 return NumOfElements++;
1648 int Mesh::AddTriangle(
int v1,
int v2,
int v3,
int attr)
1650 CheckEnlarge(elements, NumOfElements);
1651 elements[NumOfElements] =
new Triangle(v1, v2, v3, attr);
1652 return NumOfElements++;
1655 int Mesh::AddTriangle(
const int *vi,
int attr)
1657 CheckEnlarge(elements, NumOfElements);
1658 elements[NumOfElements] =
new Triangle(vi, attr);
1659 return NumOfElements++;
1662 int Mesh::AddQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1664 CheckEnlarge(elements, NumOfElements);
1665 elements[NumOfElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1666 return NumOfElements++;
1669 int Mesh::AddQuad(
const int *vi,
int attr)
1671 CheckEnlarge(elements, NumOfElements);
1673 return NumOfElements++;
1676 int Mesh::AddTet(
int v1,
int v2,
int v3,
int v4,
int attr)
1678 int vi[4] = {v1, v2, v3, v4};
1679 return AddTet(vi, attr);
1682 int Mesh::AddTet(
const int *vi,
int attr)
1684 CheckEnlarge(elements, NumOfElements);
1685 #ifdef MFEM_USE_MEMALLOC
1687 tet = TetMemory.Alloc();
1690 elements[NumOfElements] = tet;
1692 elements[NumOfElements] =
new Tetrahedron(vi, attr);
1694 return NumOfElements++;
1697 int Mesh::AddWedge(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int attr)
1699 CheckEnlarge(elements, NumOfElements);
1700 elements[NumOfElements] =
new Wedge(v1, v2, v3, v4, v5, v6, attr);
1701 return NumOfElements++;
1704 int Mesh::AddWedge(
const int *vi,
int attr)
1706 CheckEnlarge(elements, NumOfElements);
1707 elements[NumOfElements] =
new Wedge(vi, attr);
1708 return NumOfElements++;
1711 int Mesh::AddPyramid(
int v1,
int v2,
int v3,
int v4,
int v5,
int attr)
1713 CheckEnlarge(elements, NumOfElements);
1714 elements[NumOfElements] =
new Pyramid(v1, v2, v3, v4, v5, attr);
1715 return NumOfElements++;
1718 int Mesh::AddPyramid(
const int *vi,
int attr)
1720 CheckEnlarge(elements, NumOfElements);
1721 elements[NumOfElements] =
new Pyramid(vi, attr);
1722 return NumOfElements++;
1725 int Mesh::AddHex(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int v7,
int v8,
1728 CheckEnlarge(elements, NumOfElements);
1729 elements[NumOfElements] =
1730 new Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8, attr);
1731 return NumOfElements++;
1734 int Mesh::AddHex(
const int *vi,
int attr)
1736 CheckEnlarge(elements, NumOfElements);
1737 elements[NumOfElements] =
new Hexahedron(vi, attr);
1738 return NumOfElements++;
1741 void Mesh::AddHexAsTets(
const int *vi,
int attr)
1743 static const int hex_to_tet[6][4] =
1745 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
1746 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
1750 for (
int i = 0; i < 6; i++)
1752 for (
int j = 0; j < 4; j++)
1754 ti[j] = vi[hex_to_tet[i][j]];
1760 void Mesh::AddHexAsWedges(
const int *vi,
int attr)
1762 static const int hex_to_wdg[2][6] =
1764 { 0, 1, 2, 4, 5, 6 }, { 0, 2, 3, 4, 6, 7 }
1768 for (
int i = 0; i < 2; i++)
1770 for (
int j = 0; j < 6; j++)
1772 ti[j] = vi[hex_to_wdg[i][j]];
1778 void Mesh::AddHexAsPyramids(
const int *vi,
int attr)
1780 static const int hex_to_pyr[6][5] =
1782 { 0, 1, 2, 3, 8 }, { 0, 4, 5, 1, 8 }, { 1, 5, 6, 2, 8 },
1783 { 2, 6, 7, 3, 8 }, { 3, 7, 4, 0, 8 }, { 7, 6, 5, 4, 8 }
1787 for (
int i = 0; i < 6; i++)
1789 for (
int j = 0; j < 5; j++)
1791 ti[j] = vi[hex_to_pyr[i][j]];
1793 AddPyramid(ti, attr);
1799 CheckEnlarge(elements, NumOfElements);
1800 elements[NumOfElements] = elem;
1801 return NumOfElements++;
1806 CheckEnlarge(boundary, NumOfBdrElements);
1807 boundary[NumOfBdrElements] = elem;
1808 return NumOfBdrElements++;
1811 int Mesh::AddBdrSegment(
int v1,
int v2,
int attr)
1813 CheckEnlarge(boundary, NumOfBdrElements);
1814 boundary[NumOfBdrElements] =
new Segment(v1, v2, attr);
1815 return NumOfBdrElements++;
1818 int Mesh::AddBdrSegment(
const int *vi,
int attr)
1820 CheckEnlarge(boundary, NumOfBdrElements);
1821 boundary[NumOfBdrElements] =
new Segment(vi, attr);
1822 return NumOfBdrElements++;
1825 int Mesh::AddBdrTriangle(
int v1,
int v2,
int v3,
int attr)
1827 CheckEnlarge(boundary, NumOfBdrElements);
1828 boundary[NumOfBdrElements] =
new Triangle(v1, v2, v3, attr);
1829 return NumOfBdrElements++;
1832 int Mesh::AddBdrTriangle(
const int *vi,
int attr)
1834 CheckEnlarge(boundary, NumOfBdrElements);
1835 boundary[NumOfBdrElements] =
new Triangle(vi, attr);
1836 return NumOfBdrElements++;
1839 int Mesh::AddBdrQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1841 CheckEnlarge(boundary, NumOfBdrElements);
1842 boundary[NumOfBdrElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1843 return NumOfBdrElements++;
1846 int Mesh::AddBdrQuad(
const int *vi,
int attr)
1848 CheckEnlarge(boundary, NumOfBdrElements);
1850 return NumOfBdrElements++;
1853 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1855 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1858 for (
int i = 0; i < 2; i++)
1860 for (
int j = 0; j < 3; j++)
1862 ti[j] = vi[quad_to_tri[i][j]];
1864 AddBdrTriangle(ti, attr);
1868 int Mesh::AddBdrPoint(
int v,
int attr)
1870 CheckEnlarge(boundary, NumOfBdrElements);
1871 boundary[NumOfBdrElements] =
new Point(&v, attr);
1872 return NumOfBdrElements++;
1875 void Mesh::GenerateBoundaryElements()
1878 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1882 for (i = 0; i < boundary.Size(); i++)
1884 FreeElement(boundary[i]);
1894 NumOfBdrElements = 0;
1895 for (i = 0; i < faces_info.Size(); i++)
1897 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1900 boundary.SetSize(NumOfBdrElements);
1901 be2face.
SetSize(NumOfBdrElements);
1902 for (j = i = 0; i < faces_info.Size(); i++)
1904 if (faces_info[i].Elem2No < 0)
1906 boundary[j] = faces[i]->Duplicate(
this);
1913 void Mesh::FinalizeCheck()
1915 MFEM_VERIFY(vertices.Size() == NumOfVertices ||
1916 vertices.Size() == 0,
1917 "incorrect number of vertices: preallocated: " << vertices.Size()
1918 <<
", actually added: " << NumOfVertices);
1919 MFEM_VERIFY(elements.Size() == NumOfElements,
1920 "incorrect number of elements: preallocated: " << elements.Size()
1921 <<
", actually added: " << NumOfElements);
1922 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1923 "incorrect number of boundary elements: preallocated: "
1924 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1927 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1930 CheckElementOrientation(fix_orientation);
1934 MarkTriMeshForRefinement();
1939 el_to_edge =
new Table;
1940 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1942 CheckBdrElementOrientation();
1956 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1957 bool fix_orientation)
1960 if (fix_orientation)
1962 CheckElementOrientation(fix_orientation);
1967 el_to_edge =
new Table;
1968 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1970 CheckBdrElementOrientation();
1990 GeckoProgress(
double limit) : limit(limit) { sw.Start(); }
1991 virtual bool quit()
const {
return limit > 0 && sw.UserTime() > limit; }
1994 class GeckoVerboseProgress :
public GeckoProgress
2000 GeckoVerboseProgress(
double limit) : GeckoProgress(limit) {}
2002 virtual void beginorder(
const Graph* graph,
Float cost)
const
2003 {
mfem::out <<
"Begin Gecko ordering, cost = " << cost << std::endl; }
2004 virtual void endorder(
const Graph* graph,
Float cost)
const
2005 {
mfem::out <<
"End ordering, cost = " << cost << std::endl; }
2007 virtual void beginiter(
const Graph* graph,
2010 mfem::out <<
"Iteration " << iter <<
"/" << maxiter <<
", window "
2011 << window << std::flush;
2013 virtual void enditer(
const Graph* graph,
Float mincost,
Float cost)
const
2014 {
mfem::out <<
", cost = " << cost << endl; }
2019 int iterations,
int window,
2020 int period,
int seed,
bool verbose,
2026 GeckoProgress progress(time_limit);
2027 GeckoVerboseProgress vprogress(time_limit);
2030 for (
int elemid = 0; elemid < GetNE(); ++elemid)
2037 const Table &my_el_to_el = ElementToElementTable();
2038 for (
int elemid = 0; elemid < GetNE(); ++elemid)
2040 const int *neighid = my_el_to_el.
GetRow(elemid);
2041 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
2043 graph.
insert_arc(elemid + 1, neighid[i] + 1);
2048 graph.
order(&functional, iterations, window, period, seed,
2049 verbose ? &vprogress : &progress);
2055 ordering[gnodeid - 1] = graph.
rank(gnodeid);
2058 return graph.
cost();
2069 HilbertCmp(
int coord,
bool dir,
const Array<double> &points,
double mid)
2070 : coord(coord), dir(dir), points(points), mid(mid) {}
2072 bool operator()(
int i)
const
2074 return (points[3*i + coord] < mid) != dir;
2078 static void HilbertSort2D(
int coord1,
2081 const Array<double> &points,
int *beg,
int *end,
2082 double xmin,
double ymin,
double xmax,
double ymax)
2084 if (end - beg <= 1) {
return; }
2086 double xmid = (xmin + xmax)*0.5;
2087 double ymid = (ymin + ymax)*0.5;
2089 int coord2 = (coord1 + 1) % 2;
2092 int *p0 = beg, *p4 = end;
2093 int *p2 = std::partition(p0, p4, HilbertCmp(coord1, dir1, points, xmid));
2094 int *p1 = std::partition(p0, p2, HilbertCmp(coord2, dir2, points, ymid));
2095 int *p3 = std::partition(p2, p4, HilbertCmp(coord2, !dir2, points, ymid));
2099 HilbertSort2D(coord2, dir2, dir1, points, p0, p1,
2100 ymin, xmin, ymid, xmid);
2102 if (p1 != p0 || p2 != p4)
2104 HilbertSort2D(coord1, dir1, dir2, points, p1, p2,
2105 xmin, ymid, xmid, ymax);
2107 if (p2 != p0 || p3 != p4)
2109 HilbertSort2D(coord1, dir1, dir2, points, p2, p3,
2110 xmid, ymid, xmax, ymax);
2114 HilbertSort2D(coord2, !dir2, !dir1, points, p3, p4,
2115 ymid, xmax, ymin, xmid);
2119 static void HilbertSort3D(
int coord1,
bool dir1,
bool dir2,
bool dir3,
2120 const Array<double> &points,
int *beg,
int *end,
2121 double xmin,
double ymin,
double zmin,
2122 double xmax,
double ymax,
double zmax)
2124 if (end - beg <= 1) {
return; }
2126 double xmid = (xmin + xmax)*0.5;
2127 double ymid = (ymin + ymax)*0.5;
2128 double zmid = (zmin + zmax)*0.5;
2130 int coord2 = (coord1 + 1) % 3;
2131 int coord3 = (coord1 + 2) % 3;
2134 int *p0 = beg, *p8 = end;
2135 int *p4 = std::partition(p0, p8, HilbertCmp(coord1, dir1, points, xmid));
2136 int *p2 = std::partition(p0, p4, HilbertCmp(coord2, dir2, points, ymid));
2137 int *p6 = std::partition(p4, p8, HilbertCmp(coord2, !dir2, points, ymid));
2138 int *p1 = std::partition(p0, p2, HilbertCmp(coord3, dir3, points, zmid));
2139 int *p3 = std::partition(p2, p4, HilbertCmp(coord3, !dir3, points, zmid));
2140 int *p5 = std::partition(p4, p6, HilbertCmp(coord3, dir3, points, zmid));
2141 int *p7 = std::partition(p6, p8, HilbertCmp(coord3, !dir3, points, zmid));
2145 HilbertSort3D(coord3, dir3, dir1, dir2, points, p0, p1,
2146 zmin, xmin, ymin, zmid, xmid, ymid);
2148 if (p1 != p0 || p2 != p8)
2150 HilbertSort3D(coord2, dir2, dir3, dir1, points, p1, p2,
2151 ymin, zmid, xmin, ymid, zmax, xmid);
2153 if (p2 != p0 || p3 != p8)
2155 HilbertSort3D(coord2, dir2, dir3, dir1, points, p2, p3,
2156 ymid, zmid, xmin, ymax, zmax, xmid);
2158 if (p3 != p0 || p4 != p8)
2160 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p3, p4,
2161 xmin, ymax, zmid, xmid, ymid, zmin);
2163 if (p4 != p0 || p5 != p8)
2165 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p4, p5,
2166 xmid, ymax, zmid, xmax, ymid, zmin);
2168 if (p5 != p0 || p6 != p8)
2170 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p5, p6,
2171 ymax, zmid, xmax, ymid, zmax, xmid);
2173 if (p6 != p0 || p7 != p8)
2175 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p6, p7,
2176 ymid, zmid, xmax, ymin, zmax, xmid);
2180 HilbertSort3D(coord3, !dir3, !dir1, dir2, points, p7, p8,
2181 zmid, xmax, ymin, zmin, xmid, ymid);
2187 MFEM_VERIFY(spaceDim <= 3,
"");
2190 GetBoundingBox(min, max);
2195 if (spaceDim < 3) { points = 0.0; }
2198 for (
int i = 0; i < GetNE(); i++)
2200 GetElementCenter(i, center);
2201 for (
int j = 0; j < spaceDim; j++)
2203 points[3*i + j] = center(j);
2210 indices.
Sort([&](
int a,
int b)
2211 {
return points[3*
a] < points[3*
b]; });
2213 else if (spaceDim == 2)
2216 HilbertSort2D(0,
false,
false,
2217 points, indices.
begin(), indices.
end(),
2218 min(0), min(1), max(0), max(1));
2223 HilbertSort3D(0,
false,
false,
false,
2224 points, indices.
begin(), indices.
end(),
2225 min(0), min(1), min(2), max(0), max(1), max(2));
2230 for (
int i = 0; i < GetNE(); i++)
2232 ordering[indices[i]] = i;
2237 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
2241 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
2246 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
2250 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
2280 old_elem_node_vals.SetSize(GetNE());
2281 nodes_fes = Nodes->FESpace();
2284 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2286 nodes_fes->GetElementVDofs(old_elid, old_dofs);
2288 old_elem_node_vals[old_elid] =
new Vector(vals);
2294 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
2296 int new_elid = ordering[old_elid];
2297 new_elements[new_elid] = elements[old_elid];
2302 if (reorder_vertices)
2307 vertex_ordering = -1;
2309 int new_vertex_ind = 0;
2310 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
2312 int *elem_vert = elements[new_elid]->GetVertices();
2313 int nv = elements[new_elid]->GetNVertices();
2314 for (
int vi = 0; vi < nv; ++vi)
2316 int old_vertex_ind = elem_vert[vi];
2317 if (vertex_ordering[old_vertex_ind] == -1)
2319 vertex_ordering[old_vertex_ind] = new_vertex_ind;
2320 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
2330 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
2332 int *elem_vert = elements[new_elid]->GetVertices();
2333 int nv = elements[new_elid]->GetNVertices();
2334 for (
int vi = 0; vi < nv; ++vi)
2336 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
2341 for (
int belid = 0; belid < GetNBE(); ++belid)
2343 int *be_vert = boundary[belid]->GetVertices();
2344 int nv = boundary[belid]->GetNVertices();
2345 for (
int vi = 0; vi < nv; ++vi)
2347 be_vert[vi] = vertex_ordering[be_vert[vi]];
2358 el_to_edge =
new Table;
2359 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2364 GetElementToFaceTable();
2374 last_operation = Mesh::NONE;
2375 nodes_fes->Update(
false);
2378 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2380 int new_elid = ordering[old_elid];
2381 nodes_fes->GetElementVDofs(new_elid, new_dofs);
2382 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
2383 delete old_elem_node_vals[old_elid];
2389 void Mesh::MarkForRefinement()
2395 MarkTriMeshForRefinement();
2399 DSTable v_to_v(NumOfVertices);
2400 GetVertexToVertexTable(v_to_v);
2401 MarkTetMeshForRefinement(v_to_v);
2406 void Mesh::MarkTriMeshForRefinement()
2411 for (
int i = 0; i < NumOfElements; i++)
2413 if (elements[i]->GetType() == Element::TRIANGLE)
2415 GetPointMatrix(i, pmat);
2416 static_cast<Triangle*
>(elements[i])->MarkEdge(pmat);
2427 for (
int i = 0; i < NumOfVertices; i++)
2432 length_idx[j].one = GetLength(i, it.Column());
2433 length_idx[j].two = j;
2440 for (
int i = 0; i < NumOfEdges; i++)
2442 order[length_idx[i].two] = i;
2446 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
2451 GetEdgeOrdering(v_to_v, order);
2453 for (
int i = 0; i < NumOfElements; i++)
2455 if (elements[i]->GetType() == Element::TETRAHEDRON)
2457 elements[i]->MarkEdge(v_to_v, order);
2460 for (
int i = 0; i < NumOfBdrElements; i++)
2462 if (boundary[i]->GetType() == Element::TRIANGLE)
2464 boundary[i]->MarkEdge(v_to_v, order);
2471 if (*old_v_to_v && *old_elem_vert)
2478 if (*old_v_to_v == NULL)
2480 bool need_v_to_v =
false;
2482 for (
int i = 0; i < GetNEdges(); i++)
2488 if (dofs.
Size() > 0)
2496 *old_v_to_v =
new DSTable(NumOfVertices);
2497 GetVertexToVertexTable(*(*old_v_to_v));
2500 if (*old_elem_vert == NULL)
2502 bool need_elem_vert =
false;
2504 for (
int i = 0; i < GetNE(); i++)
2510 if (dofs.
Size() > 1)
2512 need_elem_vert =
true;
2518 *old_elem_vert =
new Table;
2519 (*old_elem_vert)->
MakeI(GetNE());
2520 for (
int i = 0; i < GetNE(); i++)
2522 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
2524 (*old_elem_vert)->MakeJ();
2525 for (
int i = 0; i < GetNE(); i++)
2527 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
2528 elements[i]->GetNVertices());
2530 (*old_elem_vert)->ShiftUpI();
2543 const int num_edge_dofs = old_dofs.
Size();
2546 const Vector onodes = *Nodes;
2550 int offset = NumOfVertices * old_dofs.
Size();
2554 if (num_edge_dofs > 0)
2556 DSTable new_v_to_v(NumOfVertices);
2557 GetVertexToVertexTable(new_v_to_v);
2559 for (
int i = 0; i < NumOfVertices; i++)
2563 const int old_i = (*old_v_to_v)(i, it.Column());
2564 const int new_i = it.Index();
2565 if (new_i == old_i) {
continue; }
2567 old_dofs.
SetSize(num_edge_dofs);
2568 new_dofs.
SetSize(num_edge_dofs);
2569 for (
int j = 0; j < num_edge_dofs; j++)
2571 old_dofs[j] = offset + old_i * num_edge_dofs + j;
2572 new_dofs[j] = offset + new_i * num_edge_dofs + j;
2576 for (
int j = 0; j < old_dofs.
Size(); j++)
2578 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2582 offset += NumOfEdges * num_edge_dofs;
2590 Table old_face_vertex;
2591 old_face_vertex.
MakeI(NumOfFaces);
2592 for (
int i = 0; i < NumOfFaces; i++)
2596 old_face_vertex.
MakeJ();
2597 for (
int i = 0; i < NumOfFaces; i++)
2599 faces[i]->GetNVertices());
2603 STable3D *faces_tbl = GetElementToFaceTable(1);
2609 for (
int i = 0; i < NumOfFaces; i++)
2611 const int *old_v = old_face_vertex.
GetRow(i);
2613 switch (old_face_vertex.
RowSize(i))
2616 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2620 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2624 new_fdofs[new_i+1] = old_dofs.
Size();
2629 for (
int i = 0; i < NumOfFaces; i++)
2631 const int *old_v = old_face_vertex.
GetRow(i), *new_v;
2634 switch (old_face_vertex.
RowSize(i))
2637 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2638 new_v = faces[new_i]->GetVertices();
2639 new_or = GetTriOrientation(old_v, new_v);
2644 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2645 new_v = faces[new_i]->GetVertices();
2646 new_or = GetQuadOrientation(old_v, new_v);
2653 for (
int j = 0; j < old_dofs.
Size(); j++)
2656 const int old_j = dof_ord[j];
2657 new_dofs[old_j] = offset + new_fdofs[new_i] + j;
2661 for (
int j = 0; j < old_dofs.
Size(); j++)
2663 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2685 for (
int i = 0; i < GetNE(); i++)
2687 const int *old_v = old_elem_vert->
GetRow(i);
2688 const int *new_v = elements[i]->GetVertices();
2694 case Geometry::SEGMENT:
2695 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
2697 case Geometry::TRIANGLE:
2698 new_or = GetTriOrientation(old_v, new_v);
2700 case Geometry::SQUARE:
2701 new_or = GetQuadOrientation(old_v, new_v);
2703 case Geometry::TETRAHEDRON:
2704 new_or = GetTetOrientation(old_v, new_v);
2708 MFEM_ABORT(Geometry::Name[geom] <<
" elements (" << fec->
Name()
2709 <<
" FE collection) are not supported yet!");
2713 MFEM_VERIFY(dof_ord != NULL,
2714 "FE collection '" << fec->
Name()
2715 <<
"' does not define reordering for "
2716 << Geometry::Name[geom] <<
" elements!");
2719 for (
int j = 0; j < new_dofs.
Size(); j++)
2722 const int old_j = dof_ord[j];
2723 new_dofs[old_j] = offset + j;
2725 offset += new_dofs.
Size();
2728 for (
int j = 0; j < old_dofs.
Size(); j++)
2730 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2742 GetElementToFaceTable();
2745 CheckBdrElementOrientation();
2750 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2755 CheckBdrElementOrientation();
2760 last_operation = Mesh::NONE;
2765 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
2768 CheckElementOrientation(fix_orientation);
2770 if (NumOfBdrElements == 0)
2772 GetElementToFaceTable();
2774 GenerateBoundaryElements();
2779 DSTable v_to_v(NumOfVertices);
2780 GetVertexToVertexTable(v_to_v);
2781 MarkTetMeshForRefinement(v_to_v);
2784 GetElementToFaceTable();
2787 CheckBdrElementOrientation();
2789 if (generate_edges == 1)
2791 el_to_edge =
new Table;
2792 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2806 void Mesh::FinalizeWedgeMesh(
int generate_edges,
int refine,
2807 bool fix_orientation)
2810 CheckElementOrientation(fix_orientation);
2812 if (NumOfBdrElements == 0)
2814 GetElementToFaceTable();
2816 GenerateBoundaryElements();
2819 GetElementToFaceTable();
2822 CheckBdrElementOrientation();
2824 if (generate_edges == 1)
2826 el_to_edge =
new Table;
2827 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2841 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
2844 CheckElementOrientation(fix_orientation);
2846 GetElementToFaceTable();
2849 if (NumOfBdrElements == 0)
2851 GenerateBoundaryElements();
2854 CheckBdrElementOrientation();
2858 el_to_edge =
new Table;
2859 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2871 void Mesh::FinalizeMesh(
int refine,
bool fix_orientation)
2875 Finalize(refine, fix_orientation);
2878 void Mesh::FinalizeTopology(
bool generate_bdr)
2890 bool generate_edges =
true;
2892 if (spaceDim == 0) { spaceDim = Dim; }
2893 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2897 if (tmp_vertex_parents.Size())
2899 MFEM_VERIFY(ncmesh == NULL,
"");
2900 ncmesh =
new NCMesh(
this);
2904 InitFromNCMesh(*ncmesh);
2905 ncmesh->OnMeshUpdated(
this);
2906 GenerateNCFaceInfo();
2910 tmp_vertex_parents.DeleteAll();
2920 GetElementToFaceTable();
2922 if (NumOfBdrElements == 0 && generate_bdr)
2924 GenerateBoundaryElements();
2925 GetElementToFaceTable();
2934 if (Dim > 1 && generate_edges)
2937 if (!el_to_edge) { el_to_edge =
new Table; }
2938 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2942 if (NumOfBdrElements == 0 && generate_bdr)
2944 GenerateBoundaryElements();
2961 ncmesh->OnMeshUpdated(
this);
2964 GenerateNCFaceInfo();
2971 void Mesh::Finalize(
bool refine,
bool fix_orientation)
2973 if (NURBSext || ncmesh)
2975 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
2976 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
2985 const bool check_orientation =
true;
2986 const bool curved = (Nodes != NULL);
2987 const bool may_change_topology =
2988 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
2989 ( check_orientation && fix_orientation &&
2990 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
2993 Table *old_elem_vert = NULL;
2995 if (curved && may_change_topology)
2997 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
3000 if (check_orientation)
3003 CheckElementOrientation(fix_orientation);
3007 MarkForRefinement();
3010 if (may_change_topology)
3014 DoNodeReorder(old_v_to_v, old_elem_vert);
3015 delete old_elem_vert;
3028 CheckBdrElementOrientation();
3033 if (Dim >= 2 && Dim == spaceDim)
3035 const int num_faces = GetNumFaces();
3036 for (
int i = 0; i < num_faces; i++)
3038 MFEM_VERIFY(faces_info[i].Elem2No < 0 ||
3039 faces_info[i].Elem2Inf%2 != 0,
"Invalid mesh topology."
3040 " Interior face with incompatible orientations.");
3047 double sx,
double sy,
double sz,
bool sfc_ordering)
3051 int NVert, NElem, NBdrElem;
3053 NVert = (nx+1) * (ny+1) * (nz+1);
3054 NElem = nx * ny * nz;
3055 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
3056 if (type == Element::TETRAHEDRON)
3061 else if (type == Element::WEDGE)
3064 NBdrElem += 2*nx*ny;
3066 else if (type == Element::PYRAMID)
3069 NVert += nx * ny * nz;
3072 InitMesh(3, 3, NVert, NElem, NBdrElem);
3078 for (z = 0; z <= nz; z++)
3080 coord[2] = ((double) z / nz) * sz;
3081 for (y = 0; y <= ny; y++)
3083 coord[1] = ((double) y / ny) * sy;
3084 for (x = 0; x <= nx; x++)
3086 coord[0] = ((double) x / nx) * sx;
3091 if (type == Element::PYRAMID)
3093 for (z = 0; z < nz; z++)
3095 coord[2] = (((double) z + 0.5) / nz) * sz;
3096 for (y = 0; y < ny; y++)
3098 coord[1] = (((double) y + 0.5 ) / ny) * sy;
3099 for (x = 0; x < nx; x++)
3101 coord[0] = (((double) x + 0.5 ) / nx) * sx;
3108 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
3109 #define VTXP(XC, YC, ZC) ((nx+1)*(ny+1)*(nz+1)+(XC)+((YC)+(ZC)*ny)*nx)
3112 if (sfc_ordering && type == Element::HEXAHEDRON)
3115 NCMesh::GridSfcOrdering3D(nx, ny, nz, sfc);
3116 MFEM_VERIFY(sfc.
Size() == 3*nx*ny*nz,
"");
3118 for (
int k = 0; k < nx*ny*nz; k++)
3125 ind[0] = VTX(x , y , z );
3126 ind[1] = VTX(x+1, y , z );
3127 ind[2] = VTX(x+1, y+1, z );
3128 ind[3] = VTX(x , y+1, z );
3129 ind[4] = VTX(x , y , z+1);
3130 ind[5] = VTX(x+1, y , z+1);
3131 ind[6] = VTX(x+1, y+1, z+1);
3132 ind[7] = VTX(x , y+1, z+1);
3140 for (z = 0; z < nz; z++)
3142 for (y = 0; y < ny; y++)
3144 for (x = 0; x < nx; x++)
3147 ind[0] = VTX(x , y , z );
3148 ind[1] = VTX(x+1, y , z );
3149 ind[2] = VTX(x+1, y+1, z );
3150 ind[3] = VTX(x , y+1, z );
3151 ind[4] = VTX(x , y , z+1);
3152 ind[5] = VTX(x+1, y , z+1);
3153 ind[6] = VTX(x+1, y+1, z+1);
3154 ind[7] = VTX( x, y+1, z+1);
3156 if (type == Element::TETRAHEDRON)
3158 AddHexAsTets(ind, 1);
3160 else if (type == Element::WEDGE)
3162 AddHexAsWedges(ind, 1);
3164 else if (type == Element::PYRAMID)
3166 ind[8] = VTXP(x, y, z);
3167 AddHexAsPyramids(ind, 1);
3180 for (y = 0; y < ny; y++)
3182 for (x = 0; x < nx; x++)
3185 ind[0] = VTX(x , y , 0);
3186 ind[1] = VTX(x , y+1, 0);
3187 ind[2] = VTX(x+1, y+1, 0);
3188 ind[3] = VTX(x+1, y , 0);
3190 if (type == Element::TETRAHEDRON)
3192 AddBdrQuadAsTriangles(ind, 1);
3194 else if (type == Element::WEDGE)
3196 AddBdrQuadAsTriangles(ind, 1);
3205 for (y = 0; y < ny; y++)
3207 for (x = 0; x < nx; x++)
3210 ind[0] = VTX(x , y , nz);
3211 ind[1] = VTX(x+1, y , nz);
3212 ind[2] = VTX(x+1, y+1, nz);
3213 ind[3] = VTX(x , y+1, nz);
3215 if (type == Element::TETRAHEDRON)
3217 AddBdrQuadAsTriangles(ind, 6);
3219 else if (type == Element::WEDGE)
3221 AddBdrQuadAsTriangles(ind, 6);
3230 for (z = 0; z < nz; z++)
3232 for (y = 0; y < ny; y++)
3235 ind[0] = VTX(0 , y , z );
3236 ind[1] = VTX(0 , y , z+1);
3237 ind[2] = VTX(0 , y+1, z+1);
3238 ind[3] = VTX(0 , y+1, z );
3240 if (type == Element::TETRAHEDRON)
3242 AddBdrQuadAsTriangles(ind, 5);
3251 for (z = 0; z < nz; z++)
3253 for (y = 0; y < ny; y++)
3256 ind[0] = VTX(nx, y , z );
3257 ind[1] = VTX(nx, y+1, z );
3258 ind[2] = VTX(nx, y+1, z+1);
3259 ind[3] = VTX(nx, y , z+1);
3261 if (type == Element::TETRAHEDRON)
3263 AddBdrQuadAsTriangles(ind, 3);
3272 for (x = 0; x < nx; x++)
3274 for (z = 0; z < nz; z++)
3277 ind[0] = VTX(x , 0, z );
3278 ind[1] = VTX(x+1, 0, z );
3279 ind[2] = VTX(x+1, 0, z+1);
3280 ind[3] = VTX(x , 0, z+1);
3282 if (type == Element::TETRAHEDRON)
3284 AddBdrQuadAsTriangles(ind, 2);
3293 for (x = 0; x < nx; x++)
3295 for (z = 0; z < nz; z++)
3298 ind[0] = VTX(x , ny, z );
3299 ind[1] = VTX(x , ny, z+1);
3300 ind[2] = VTX(x+1, ny, z+1);
3301 ind[3] = VTX(x+1, ny, z );
3303 if (type == Element::TETRAHEDRON)
3305 AddBdrQuadAsTriangles(ind, 4);
3317 ofstream test_stream(
"debug.mesh");
3319 test_stream.close();
3328 double sx,
double sy,
3329 bool generate_edges,
bool sfc_ordering)
3338 if (type == Element::QUADRILATERAL)
3340 NumOfVertices = (nx+1) * (ny+1);
3341 NumOfElements = nx * ny;
3342 NumOfBdrElements = 2 * nx + 2 * ny;
3344 vertices.SetSize(NumOfVertices);
3345 elements.SetSize(NumOfElements);
3346 boundary.SetSize(NumOfBdrElements);
3353 for (j = 0; j < ny+1; j++)
3355 cy = ((double) j / ny) * sy;
3356 for (i = 0; i < nx+1; i++)
3358 cx = ((double) i / nx) * sx;
3359 vertices[k](0) = cx;
3360 vertices[k](1) = cy;
3369 NCMesh::GridSfcOrdering2D(nx, ny, sfc);
3370 MFEM_VERIFY(sfc.
Size() == 2*nx*ny,
"");
3372 for (k = 0; k < nx*ny; k++)
3376 ind[0] = i + j*(nx+1);
3377 ind[1] = i + 1 +j*(nx+1);
3378 ind[2] = i + 1 + (j+1)*(nx+1);
3379 ind[3] = i + (j+1)*(nx+1);
3386 for (j = 0; j < ny; j++)
3388 for (i = 0; i < nx; i++)
3390 ind[0] = i + j*(nx+1);
3391 ind[1] = i + 1 +j*(nx+1);
3392 ind[2] = i + 1 + (j+1)*(nx+1);
3393 ind[3] = i + (j+1)*(nx+1);
3402 for (i = 0; i < nx; i++)
3404 boundary[i] =
new Segment(i, i+1, 1);
3405 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3408 for (j = 0; j < ny; j++)
3410 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3411 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3415 else if (type == Element::TRIANGLE)
3417 NumOfVertices = (nx+1) * (ny+1);
3418 NumOfElements = 2 * nx * ny;
3419 NumOfBdrElements = 2 * nx + 2 * ny;
3421 vertices.SetSize(NumOfVertices);
3422 elements.SetSize(NumOfElements);
3423 boundary.SetSize(NumOfBdrElements);
3430 for (j = 0; j < ny+1; j++)
3432 cy = ((double) j / ny) * sy;
3433 for (i = 0; i < nx+1; i++)
3435 cx = ((double) i / nx) * sx;
3436 vertices[k](0) = cx;
3437 vertices[k](1) = cy;
3444 for (j = 0; j < ny; j++)
3446 for (i = 0; i < nx; i++)
3448 ind[0] = i + j*(nx+1);
3449 ind[1] = i + 1 + (j+1)*(nx+1);
3450 ind[2] = i + (j+1)*(nx+1);
3453 ind[1] = i + 1 + j*(nx+1);
3454 ind[2] = i + 1 + (j+1)*(nx+1);
3462 for (i = 0; i < nx; i++)
3464 boundary[i] =
new Segment(i, i+1, 1);
3465 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3468 for (j = 0; j < ny; j++)
3470 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3471 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3478 MFEM_ABORT(
"Unsupported element type.");
3482 CheckElementOrientation();
3484 if (generate_edges == 1)
3486 el_to_edge =
new Table;
3487 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3489 CheckBdrElementOrientation();
3498 attributes.Append(1);
3499 bdr_attributes.Append(1); bdr_attributes.Append(2);
3500 bdr_attributes.Append(3); bdr_attributes.Append(4);
3505 void Mesh::Make1D(
int n,
double sx)
3514 NumOfVertices = n + 1;
3516 NumOfBdrElements = 2;
3517 vertices.SetSize(NumOfVertices);
3518 elements.SetSize(NumOfElements);
3519 boundary.SetSize(NumOfBdrElements);
3522 for (j = 0; j < n+1; j++)
3524 vertices[j](0) = ((
double) j / n) * sx;
3528 for (j = 0; j < n; j++)
3530 elements[j] =
new Segment(j, j+1, 1);
3535 boundary[0] =
new Point(ind, 1);
3537 boundary[1] =
new Point(ind, 2);
3545 attributes.Append(1);
3546 bdr_attributes.Append(1); bdr_attributes.Append(2);
3549 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
3567 last_operation = Mesh::NONE;
3570 elements.SetSize(NumOfElements);
3571 for (
int i = 0; i < NumOfElements; i++)
3573 elements[i] = mesh.
elements[i]->Duplicate(
this);
3580 boundary.SetSize(NumOfBdrElements);
3581 for (
int i = 0; i < NumOfBdrElements; i++)
3583 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
3602 faces.SetSize(mesh.
faces.Size());
3603 for (
int i = 0; i < faces.Size(); i++)
3606 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
3640 if (dynamic_cast<const ParMesh*>(&mesh))
3652 if (mesh.
Nodes && copy_nodes)
3657 FiniteElementCollection::New(fec->
Name());
3661 Nodes->MakeOwner(fec_copy);
3662 *Nodes = *mesh.
Nodes;
3684 bool fix_orientation)
3688 if (!imesh) { MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n'); }
3689 else { mesh.
Load(imesh, generate_edges, refine, fix_orientation); }
3703 double sx,
double sy,
bool sfc_ordering)
3706 mesh.
Make2D(nx, ny, type, sx, sy, generate_edges, sfc_ordering);
3713 double sx,
double sy,
double sz,
bool sfc_ordering)
3716 mesh.
Make3D(nx, ny, nz, type, sx, sy, sz, sfc_ordering);
3725 ref_factors = ref_factor;
3739 bool fix_orientation)
3748 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
3752 Load(imesh, generate_edges, refine, fix_orientation);
3757 bool fix_orientation)
3760 Load(input, generate_edges, refine, fix_orientation);
3769 "Not enough vertices in external array : "
3770 "len_vertex_data = "<< len_vertex_data <<
", "
3773 if (vertex_data == (
double *)(
vertices.GetData()))
3775 MFEM_ASSERT(!
vertices.OwnsData(),
"invalid ownership");
3780 memcpy(vertex_data,
vertices.GetData(),
3789 int *element_attributes,
int num_elements,
3791 int *boundary_attributes,
int num_boundary_elements,
3792 int dimension,
int space_dimension)
3794 if (space_dimension == -1)
3796 space_dimension = dimension;
3799 InitMesh(dimension, space_dimension, 0, num_elements,
3800 num_boundary_elements);
3803 int boundary_index_stride = num_boundary_elements > 0 ?
3807 vertices.MakeRef(reinterpret_cast<Vertex*>(vertices_), num_vertices);
3810 for (
int i = 0; i < num_elements; i++)
3813 elements[i]->SetVertices(element_indices + i * element_index_stride);
3814 elements[i]->SetAttribute(element_attributes[i]);
3818 for (
int i = 0; i < num_boundary_elements; i++)
3821 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
3822 boundary[i]->SetAttribute(boundary_attributes[i]);
3838 #ifdef MFEM_USE_MEMALLOC
3847 MFEM_ABORT(
"invalid Geometry::Type, geom = " << geom);
3860 MFEM_VERIFY(el,
"Unsupported element type: " << geom);
3863 for (
int i = 0; i < nv; i++)
3876 for (
int j = 0; j < nv; j++)
3948 MFEM_ABORT(
"invalid element type: " << type);
3955 std::string parse_tag)
3957 int curved = 0, read_gf = 1;
3958 bool finalize_topo =
true;
3962 MFEM_ABORT(
"Input stream is not open");
3969 getline(input, mesh_type);
3973 int mfem_version = 0;
3974 if (mesh_type ==
"MFEM mesh v1.0") { mfem_version = 10; }
3975 else if (mesh_type ==
"MFEM mesh v1.2") { mfem_version = 12; }
3979 int mfem_nc_version = 0;
3980 if (mesh_type ==
"MFEM NC mesh v1.0") { mfem_nc_version = 10; }
3981 else if (mesh_type ==
"MFEM mesh v1.1") { mfem_nc_version = 1 ; }
3989 if (mfem_version == 12 && parse_tag.empty())
3991 parse_tag =
"mfem_mesh_end";
3995 else if (mfem_nc_version)
3997 MFEM_ASSERT(
ncmesh == NULL,
"internal error");
4004 MFEM_VERIFY(mfem_nc_version >= 10,
4005 "Legacy nonconforming format (MFEM mesh v1.1) cannot be "
4006 "used to load a parallel nonconforming mesh, sorry.");
4009 input, mfem_nc_version, curved, is_nc);
4014 ncmesh =
new NCMesh(input, mfem_nc_version, curved, is_nc);
4027 else if (mesh_type ==
"linemesh")
4031 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
4033 if (mesh_type ==
"curved_areamesh2")
4039 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
4043 else if (mesh_type ==
"TrueGrid")
4047 else if (mesh_type.rfind(
"# vtk DataFile Version") == 0)
4049 int major_vtk_version = mesh_type[mesh_type.length()-3] -
'0';
4051 MFEM_VERIFY(major_vtk_version >= 2 && major_vtk_version <= 4,
4052 "Unsupported VTK format");
4053 ReadVTKMesh(input, curved, read_gf, finalize_topo);
4055 else if (mesh_type.rfind(
"<VTKFile ") == 0 || mesh_type.rfind(
"<?xml") == 0)
4059 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
4063 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
4068 else if (mesh_type ==
"$MeshFormat")
4073 ((mesh_type.size() > 2 &&
4074 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
4075 (mesh_type.size() > 3 &&
4076 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
4081 #ifdef MFEM_USE_NETCDF
4084 MFEM_ABORT(
"NetCDF support requires configuration with"
4085 " MFEM_USE_NETCDF=YES");
4091 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
4092 " Use mfem::named_ifgzstream for input.");
4098 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
4124 bool generate_bdr =
false;
4129 if (curved && read_gf)
4143 if (mfem_version == 12)
4149 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
4150 getline(input, line);
4156 if (line ==
"mfem_mesh_end") {
break; }
4158 while (line != parse_tag);
4160 else if (mfem_nc_version >= 10)
4165 MFEM_VERIFY(ident ==
"mfem_mesh_end",
4166 "invalid mesh: end of file tag not found");
4174 int i, j, ie, ib, iv, *v, nv;
4205 for (i = 0; i < num_pieces; i++)
4212 for (i = 0; i < num_pieces; i++)
4218 for (j = 0; j < m->
GetNE(); j++)
4223 for (j = 0; j < m->
GetNBE(); j++)
4228 for (
int k = 0; k < nv; k++)
4230 v[k] = lvert_vert[v[k]];
4235 for (j = 0; j < m->
GetNV(); j++)
4247 for (i = 0; i < num_pieces; i++)
4258 for (i = 0; i < num_pieces; i++)
4262 for (j = 0; j < m->
GetNE(); j++)
4267 for (
int k = 0; k < nv; k++)
4274 for (j = 0; j < m->
GetNBE(); j++)
4279 for (
int k = 0; k < nv; k++)
4286 for (j = 0; j < m->
GetNV(); j++)
4300 for (i = 0; i < num_pieces; i++)
4302 gf_array[i] = mesh_array[i]->
GetNodes();
4317 ref_factors = ref_factor;
4328 int orig_ne = orig_mesh.
GetNE();
4329 MFEM_VERIFY(ref_factors.
Size() == orig_ne && orig_ne > 0,
4330 "Number of refinement factors must equal number of elements")
4331 MFEM_VERIFY(ref_factors.
Min() >= 1,
"Refinement factor must be >= 1");
4334 "Invalid refinement type. Must use closed basis type.");
4336 int min_ref = ref_factors.
Min();
4337 int max_ref = ref_factors.
Max();
4339 bool var_order = (min_ref != max_ref);
4352 for (
int i = 0; i < orig_ne; i++)
4370 for (
int el = 0; el < orig_ne; el++)
4382 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[el]);
4383 for (
int i = 0; i < phys_pts.
Width(); i++)
4392 for (
int k = 0; k < nvert; k++)
4395 v[k] = rdofs[c2h_map[cid]];
4408 for (
int el = 0; el < orig_mesh.
GetNBE(); el++)
4419 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[i]);
4425 for (
int k = 0; k < nvert; k++)
4428 v[k] = rdofs[c2h_map[cid]];
4450 for (
int iel = 0; iel < orig_ne; iel++)
4459 const int *node_map = NULL;
4462 if (h1_fec != NULL) { node_map = h1_fec->
GetDofMap(geom); }
4463 const int *vertex_map = vertex_fec.
GetDofMap(geom);
4464 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[iel]);
4465 for (
int jel = 0; jel < RG.
RefGeoms.
Size()/nvert; jel++)
4468 for (
int iv_lex=0; iv_lex<nvert; ++iv_lex)
4471 int iv = vertex_map[iv_lex];
4473 int pt_idx = c2h_map[RG.
RefGeoms[iv+nvert*jel]];
4475 int node_idx = node_map ? node_map[iv_lex] : iv_lex;
4478 (*Nodes)[dofs[node_idx + d*nvert]] = phys_pts(d,pt_idx);
4489 using GeomRef = std::pair<Geometry::Type, int>;
4490 std::map<GeomRef, int> point_matrices_offsets;
4492 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4496 GeomRef id(geom, ref_factors[el_coarse]);
4497 if (point_matrices_offsets.find(
id) == point_matrices_offsets.end())
4503 point_matrices_offsets[id] = n_point_matrices[geom];
4504 n_point_matrices[geom] += nref_el;
4511 int nmatrices = n_point_matrices[geom];
4518 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4521 int ref = ref_factors[el_coarse];
4522 int offset = point_matrices_offsets[GeomRef(geom, ref)];
4528 for (
int k = 0; k < nvert; k++)
4560 "Mesh::MakeSimplicial requires a properly oriented input mesh");
4562 "Mesh::MakeSimplicial does not support non-conforming meshes.")
4569 Mesh copy(orig_mesh);
4574 int nv = orig_mesh.
GetNV();
4575 int ne = orig_mesh.
GetNE();
4576 int nbe = orig_mesh.
GetNBE();
4589 int new_ne = 0, new_nbe = 0;
4590 for (
int i=0; i<ne; ++i)
4594 for (
int i=0; i<nbe; ++i)
4603 for (
int i=0; i<nv; ++i)
4613 if (vglobal == NULL)
4616 for (
int i=0; i<nv; ++i) { vglobal_id[i] = i; }
4617 vglobal = vglobal_id.
GetData();
4620 constexpr
int nv_tri = 3, nv_quad = 4, nv_tet = 4, nv_prism = 6, nv_hex = 8;
4621 constexpr
int quad_ntris = 2, prism_ntets = 3;
4622 static const int quad_trimap[2][nv_tri*quad_ntris] =
4634 static const int prism_rot[nv_prism*nv_prism] =
4643 static const int prism_f[nv_quad] = {1, 2, 5, 4};
4644 static const int prism_tetmaps[2][nv_prism*prism_ntets] =
4658 static const int hex_rot[nv_hex*nv_hex] =
4660 0, 1, 2, 3, 4, 5, 6, 7,
4661 1, 0, 4, 5, 2, 3, 7, 6,
4662 2, 1, 5, 6, 3, 0, 4, 7,
4663 3, 0, 1, 2, 7, 4, 5, 6,
4664 4, 0, 3, 7, 5, 1, 2, 6,
4665 5, 1, 0, 4, 6, 2, 3, 7,
4666 6, 2, 1, 5, 7, 3, 0, 4,
4667 7, 3, 2, 6, 4, 0, 1, 5
4669 static const int hex_f0[nv_quad] = {1, 2, 6, 5};
4670 static const int hex_f1[nv_quad] = {2, 3, 7, 6};
4671 static const int hex_f2[nv_quad] = {4, 5, 6, 7};
4672 static const int num_rot[8] = {0, 1, 2, 0, 0, 2, 1, 0};
4673 static const int hex_tetmap0[nv_tet*5] =
4680 static const int hex_tetmap1[nv_tet*6] =
4687 static const int hex_tetmap2[nv_tet*6] =
4694 static const int hex_tetmap3[nv_tet*6] =
4701 static const int *hex_tetmaps[4] =
4703 hex_tetmap0, hex_tetmap1, hex_tetmap2, hex_tetmap3
4706 auto find_min = [](
const int*
a,
int n) {
return std::min_element(a,a+n)-
a; };
4708 for (
int i=0; i<ne; ++i)
4710 const int *v = orig_mesh.
elements[i]->GetVertices();
4714 if (num_subdivisions[orig_geom] == 1)
4726 for (
int itri=0; itri<quad_ntris; ++itri)
4731 for (
int iv=0; iv<nv_tri; ++iv)
4733 v2[iv] = v[quad_trimap[0][itri + iv*quad_ntris]];
4741 for (
int iv=0; iv<nv_prism; ++iv) { vg[iv] = vglobal[v[iv]]; }
4744 int irot = find_min(vg, nv_prism);
4745 for (
int iv=0; iv<nv_prism; ++iv)
4747 int jv = prism_rot[iv + irot*nv_prism];
4752 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[prism_f[iv]]]; }
4753 int j = find_min(q, nv_quad);
4754 const int *tetmap = (j == 0 || j == 2) ? prism_tetmaps[0] : prism_tetmaps[1];
4755 for (
int itet=0; itet<prism_ntets; ++itet)
4760 for (
int iv=0; iv<nv_tet; ++iv)
4762 v2[iv] = vg[tetmap[itet + iv*prism_ntets]];
4770 for (
int iv=0; iv<nv_hex; ++iv) { vg[iv] = vglobal[v[iv]]; }
4774 int irot = find_min(vg, nv_hex);
4775 for (
int iv=0; iv<nv_hex; ++iv)
4777 int jv = hex_rot[iv + irot*nv_hex];
4787 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f0[iv]]]; }
4788 j = find_min(q, nv_quad);
4789 if (j == 0 || j == 2) { bitmask += 4; }
4791 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f1[iv]]]; }
4792 j = find_min(q, nv_quad);
4793 if (j == 1 || j == 3) { bitmask += 2; }
4795 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f2[iv]]]; }
4796 j = find_min(q, nv_quad);
4797 if (j == 0 || j == 2) { bitmask += 1; }
4800 int nrot = num_rot[bitmask];
4801 for (
int k=0; k<nrot; ++k)
4815 int ndiags = ((bitmask&4) >> 2) + ((bitmask&2) >> 1) + (bitmask&1);
4816 int ntets = (ndiags == 0) ? 5 : 6;
4817 const int *tetmap = hex_tetmaps[ndiags];
4818 for (
int itet=0; itet<ntets; ++itet)
4823 for (
int iv=0; iv<nv_tet; ++iv)
4825 v2[iv] = vg[tetmap[itet + iv*ntets]];
4834 for (
int i=0; i<nbe; ++i)
4836 const int *v = orig_mesh.
boundary[i]->GetVertices();
4839 if (num_subdivisions[orig_geom] == 1)
4849 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
4851 int iv_min = find_min(vg, nv_quad);
4852 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
4853 for (
int itri=0; itri<quad_ntris; ++itri)
4858 for (
int iv=0; iv<nv_tri; ++iv)
4860 v2[iv] = v[quad_trimap[isplit][itri + iv*quad_ntris]];
4867 MFEM_ABORT(
"Unreachable");
4881 Mesh periodic_mesh(orig_mesh,
true);
4887 for (
int i = 0; i < periodic_mesh.
GetNE(); i++)
4892 for (
int j = 0; j < nv; j++)
4898 for (
int i = 0; i < periodic_mesh.
GetNBE(); i++)
4903 for (
int j = 0; j < nv; j++)
4910 return periodic_mesh;
4914 const std::vector<Vector> &translations,
double tol)
const
4918 Vector coord(sdim), at(sdim), dx(sdim);
4919 Vector xMax(sdim), xMin(sdim), xDiff(sdim);
4920 xMax = xMin = xDiff = 0.0;
4924 for (
int be = 0; be <
GetNBE(); be++)
4929 for (
int i = 0; i < dofs.
Size(); i++)
4931 bdr_v.insert(dofs[i]);
4934 for (
int j = 0; j < sdim; j++)
4936 xMax[j] = max(xMax[j], coord[j]);
4937 xMin[j] = min(xMin[j], coord[j]);
4941 add(xMax, -1.0, xMin, xDiff);
4942 double dia = xDiff.
Norml2();
4950 map<int, int> replica2primary;
4952 map<int, set<int>> primary2replicas;
4956 for (
int v : bdr_v) { primary2replicas[v]; }
4960 auto make_replica = [&replica2primary, &primary2replicas](
int r,
int p)
4962 if (r ==
p) {
return; }
4963 primary2replicas[
p].insert(r);
4964 replica2primary[r] =
p;
4965 for (
int s : primary2replicas[r])
4967 primary2replicas[
p].insert(
s);
4968 replica2primary[
s] =
p;
4970 primary2replicas.erase(r);
4973 for (
unsigned int i = 0; i < translations.size(); i++)
4975 for (
int vi : bdr_v)
4978 add(coord, translations[i], at);
4980 for (
int vj : bdr_v)
4983 add(at, -1.0, coord, dx);
4984 if (dx.
Norml2() > dia*tol) {
continue; }
4989 bool pi = primary2replicas.find(vi) != primary2replicas.end();
4990 bool pj = primary2replicas.find(vj) != primary2replicas.end();
4996 make_replica(vj, vi);
5001 int owner_of_vj = replica2primary[vj];
5003 make_replica(vi, owner_of_vj);
5009 int owner_of_vi = replica2primary[vi];
5010 make_replica(vj, owner_of_vi);
5017 int owner_of_vi = replica2primary[vi];
5018 int owner_of_vj = replica2primary[vj];
5019 make_replica(owner_of_vj, owner_of_vi);
5026 std::vector<int> v2v(
GetNV());
5027 for (
size_t i = 0; i < v2v.size(); i++)
5031 for (
auto &&r2p : replica2primary)
5033 v2v[r2p.first] = r2p.second;
5042 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
5047 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
5064 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
5069 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
5099 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
5123 for (
int i = 0; i <
elements.Size(); i++)
5133 for (
int i = 0; i <
boundary.Size(); i++)
5150 for (
int i = 0; i < vd; i++)
5204 boundary.SetSize(NumOfBdrElements);
5215 edge_to_knot.
SetSize(NumOfEdges);
5219 input >> edge_to_knot[j] >> v[0] >> v[1];
5222 edge_to_knot[j] = -1 - edge_to_knot[j];
5240 for (
int d = 0; d < v.
Size(); d++)
5248 for (d = 0; d < p.
Size(); d++)
5252 for ( ; d < v.
Size(); d++)
5284 if (dynamic_cast<const H1_FECollection*>(fec)
5285 || dynamic_cast<const L2_FECollection*>(fec))
5314 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
5333 MFEM_ASSERT(nodes != NULL,
"");
5349 case 1:
return GetNV();
5385 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
5386 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
5391 int i, j, k, wo = 0, fo = 0;
5400 int *vi =
elements[i]->GetVertices();
5403 for (j = 0; j < 3; j++)
5407 for (j = 0; j < 2; j++)
5408 for (k = 0; k < 2; k++)
5410 J(j, k) = v[j+1][k] - v[0][k];
5431 MFEM_ABORT(
"Invalid 2D element type \""
5448 int *vi =
elements[i]->GetVertices();
5454 for (j = 0; j < 4; j++)
5458 for (j = 0; j < 3; j++)
5459 for (k = 0; k < 3; k++)
5461 J(j, k) = v[j+1][k] - v[0][k];
5520 MFEM_ABORT(
"Invalid 3D element type \""
5526 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
5529 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / "
5530 <<
NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
5545 if (test[0] == base[0])
5546 if (test[1] == base[1])
5554 else if (test[0] == base[1])
5555 if (test[1] == base[0])
5564 if (test[1] == base[0])
5575 for (
int j = 0; j < 3; j++)
5576 if (test[aor[j]] != base[j])
5589 for (i = 0; i < 4; i++)
5590 if (test[i] == base[0])
5597 if (test[(i+1)%4] == base[1])
5606 for (
int j = 0; j < 4; j++)
5607 if (test[aor[j]] != base[j])
5609 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
5611 for (
int k = 0; k < 4; k++)
5616 for (
int k = 0; k < 4; k++)
5625 if (test[(i+1)%4] == base[1])
5641 if (test[0] == base[0])
5642 if (test[1] == base[1])
5643 if (test[2] == base[2])
5651 else if (test[2] == base[1])
5652 if (test[3] == base[2])
5661 if (test[1] == base[2])
5669 else if (test[1] == base[0])
5670 if (test[2] == base[1])
5671 if (test[0] == base[2])
5679 else if (test[3] == base[1])
5680 if (test[2] == base[2])
5689 if (test[3] == base[2])
5697 else if (test[2] == base[0])
5698 if (test[3] == base[1])
5699 if (test[0] == base[2])
5707 else if (test[0] == base[1])
5708 if (test[1] == base[2])
5717 if (test[3] == base[2])
5726 if (test[0] == base[1])
5727 if (test[2] == base[2])
5735 else if (test[1] == base[1])
5736 if (test[0] == base[2])
5745 if (test[1] == base[2])
5756 for (
int j = 0; j < 4; j++)
5757 if (test[aor[j]] != base[j])
5782 int *bv =
boundary[i]->GetVertices();
5788 mfem::Swap<int>(bv[0], bv[1]);
5802 if (
faces_info[fi].Elem2No >= 0) {
continue; }
5805 int *bv =
boundary[i]->GetVertices();
5807 MFEM_ASSERT(fi <
faces.Size(),
"internal error");
5808 const int *fv =
faces[fi]->GetVertices();
5825 MFEM_ABORT(
"Invalid 2D boundary element type \""
5826 << bdr_type <<
"\"");
5831 if (orientation % 2 == 0) {
continue; }
5833 if (!fix_it) {
continue; }
5841 mfem::Swap<int>(bv[0], bv[1]);
5845 mfem::Swap<int>(be[1], be[2]);
5851 mfem::Swap<int>(bv[0], bv[2]);
5855 mfem::Swap<int>(be[0], be[1]);
5856 mfem::Swap<int>(be[2], be[3]);
5869 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / "
5879 MFEM_ASSERT(0 <= dim && dim <=
Dim,
"invalid dim: " << dim);
5890 MFEM_ASSERT(0 <= dim && dim <=
Dim,
"invalid dim: " << dim);
5909 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
5910 "is not generated.");
5913 const int *v =
elements[i]->GetVertices();
5914 const int ne =
elements[i]->GetNEdges();
5916 for (
int j = 0; j < ne; j++)
5918 const int *e =
elements[i]->GetEdgeVertices(j);
5919 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5930 const int *v =
boundary[i]->GetVertices();
5931 cor[0] = (v[0] < v[1]) ? (1) : (-1);
5944 const int *v =
boundary[i]->GetVertices();
5945 const int ne =
boundary[i]->GetNEdges();
5947 for (
int j = 0; j < ne; j++)
5949 const int *e =
boundary[i]->GetEdgeVertices(j);
5950 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5962 const int *v =
faces[i]->GetVertices();
5963 o[0] = (v[0] < v[1]) ? (1) : (-1);
5975 const int *v =
faces[i]->GetVertices();
5976 const int ne =
faces[i]->GetNEdges();
5978 for (
int j = 0; j < ne; j++)
5980 const int *e =
faces[i]->GetEdgeVertices(j);
5981 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
6009 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
6060 for (j = 0; j < nv; j++)
6072 for (j = 0; j < nv; j++)
6119 MFEM_VERIFY(
el_to_face != NULL,
"el_to_face not generated");
6123 int n = el_faces.
Size();
6126 for (
int j = 0; j < n; j++)
6130 ori[j] =
faces_info[el_faces[j]].Elem1Inf % 64;
6134 MFEM_ASSERT(
faces_info[el_faces[j]].Elem2No == i,
"internal error");
6135 ori[j] =
faces_info[el_faces[j]].Elem2Inf % 64;
6159 MFEM_ABORT(
"invalid geometry");
6167 case 1:
return boundary[i]->GetVertices()[0];
6170 default: MFEM_ABORT(
"invalid dimension!");
6180 MFEM_ASSERT(fi.
Elem1Inf % 64 == 0,
"internal error");
6183 const int *bv =
boundary[bdr_el]->GetVertices();
6191 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
6218 for (j = 0; j < nv; j++)
6220 pointmat(k, j) =
vertices[v[j]](k);
6235 for (j = 0; j < nv; j++)
6237 pointmat(k, j) =
vertices[v[j]](k);
6249 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
6252 return sqrt(length);
6260 for (
int i = 0; i < elem_array.
Size(); i++)
6265 for (
int i = 0; i < elem_array.
Size(); i++)
6267 const int *v = elem_array[i]->GetVertices();
6268 const int ne = elem_array[i]->GetNEdges();
6269 for (
int j = 0; j < ne; j++)
6271 const int *e = elem_array[i]->GetEdgeVertices(j);
6285 v_to_v.
Push(v[0], v[1]);
6292 const int *v =
elements[i]->GetVertices();
6293 const int ne =
elements[i]->GetNEdges();
6294 for (
int j = 0; j < ne; j++)
6296 const int *e =
elements[i]->GetEdgeVertices(j);
6297 v_to_v.
Push(v[e[0]], v[e[1]]);
6305 int i, NumberOfEdges;
6321 const int *v =
boundary[i]->GetVertices();
6322 be_to_f[i] = v_to_v(v[0], v[1]);
6335 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
6339 return NumberOfEdges;
6430 if (
faces[gf] == NULL)
6440 MFEM_VERIFY(
faces_info[gf].Elem2No < 0,
"Invalid mesh topology. "
6441 "Interior edge found between 2D elements "
6443 <<
" and " << el <<
".");
6444 int *v =
faces[gf]->GetVertices();
6446 if ( v[1] == v0 && v[0] == v1 )
6450 else if ( v[0] == v0 && v[1] == v1 )
6460 MFEM_ABORT(
"internal error");
6466 int v0,
int v1,
int v2)
6468 if (
faces[gf] == NULL)