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*);
75 void Mesh::GetElementCenter(
int i,
Vector ¢er)
78 int geom = GetElementBaseGeometry(i);
93 return pow(fabs(J.
Weight()), 1./Dim);
105 double Mesh::GetElementSize(
int i,
int type)
107 return GetElementSize(GetElementTransformation(i), type);
110 double Mesh::GetElementSize(
int i,
const Vector &dir)
114 GetElementJacobian(i, J);
116 return sqrt((d_hat * d_hat) / (dir * dir));
119 double Mesh::GetElementVolume(
int i)
141 for (
int d = 0; d < spaceDim; d++)
150 for (
int i = 0; i < NumOfVertices; i++)
152 coord = GetVertex(i);
153 for (
int d = 0; d < spaceDim; d++)
155 if (coord[d] < min(d)) { min(d) = coord[d]; }
156 if (coord[d] > max(d)) { max(d) = coord[d]; }
162 const bool use_boundary =
false;
163 int ne = use_boundary ? GetNBE() : GetNE();
171 for (
int i = 0; i < ne; i++)
175 GetBdrElementFace(i, &fn, &fo);
177 Tr = GetFaceElementTransformations(fn, 5);
184 T = GetElementTransformation(i);
186 T->Transform(RefG->
RefPts, pointmat);
188 for (
int j = 0; j < pointmat.
Width(); j++)
190 for (
int d = 0; d < pointmat.
Height(); d++)
192 if (pointmat(d,j) < min(d)) { min(d) = pointmat(d,j); }
193 if (pointmat(d,j) > max(d)) { max(d) = pointmat(d,j); }
200 void Mesh::GetCharacteristics(
double &h_min,
double &h_max,
201 double &kappa_min,
double &kappa_max,
209 sdim = SpaceDimension();
211 if (Vh) { Vh->
SetSize(NumOfElements); }
212 if (Vk) { Vk->
SetSize(NumOfElements); }
215 h_max = kappa_max = -h_min;
216 if (
dim == 0) {
if (Vh) { *Vh = 1.0; }
if (Vk) {*Vk = 1.0; }
return; }
218 for (i = 0; i < NumOfElements; i++)
220 GetElementJacobian(i, J);
221 h = pow(fabs(J.
Weight()), 1.0/
double(
dim));
224 if (Vh) { (*Vh)(i) = h; }
225 if (Vk) { (*Vk)(i) =
kappa; }
227 if (h < h_min) { h_min = h; }
228 if (h > h_max) { h_max = h; }
235 void Mesh::PrintElementsByGeometry(
int dim,
239 for (
int g = Geometry::DimStart[
dim], first = 1;
240 g < Geometry::DimStart[
dim+1]; g++)
242 if (!num_elems_by_geom[g]) {
continue; }
243 if (!first) { os <<
" + "; }
245 os << num_elems_by_geom[g] <<
' ' << Geometry::Name[g] <<
"(s)";
249 void Mesh::PrintCharacteristics(
Vector *Vh,
Vector *Vk, std::ostream &os)
251 double h_min, h_max, kappa_min, kappa_max;
253 os <<
"Mesh Characteristics:";
255 this->GetCharacteristics(h_min, h_max, kappa_min, kappa_max, Vh, Vk);
257 Array<int> num_elems_by_geom(Geometry::NumGeom);
258 num_elems_by_geom = 0;
259 for (
int i = 0; i < GetNE(); i++)
261 num_elems_by_geom[GetElementBaseGeometry(i)]++;
265 <<
"Dimension : " << Dimension() <<
'\n' 266 <<
"Space dimension : " << SpaceDimension();
270 <<
"Number of vertices : " << GetNV() <<
'\n' 271 <<
"Number of elements : " << GetNE() <<
'\n' 272 <<
"Number of bdr elem : " << GetNBE() <<
'\n';
277 <<
"Number of vertices : " << GetNV() <<
'\n' 278 <<
"Number of elements : " << GetNE() <<
'\n' 279 <<
"Number of bdr elem : " << GetNBE() <<
'\n' 280 <<
"h_min : " << h_min <<
'\n' 281 <<
"h_max : " << h_max <<
'\n';
286 <<
"Number of vertices : " << GetNV() <<
'\n' 287 <<
"Number of edges : " << GetNEdges() <<
'\n' 288 <<
"Number of elements : " << GetNE() <<
" -- ";
289 PrintElementsByGeometry(2, num_elems_by_geom, os);
291 <<
"Number of bdr elem : " << GetNBE() <<
'\n' 292 <<
"Euler Number : " << EulerNumber2D() <<
'\n' 293 <<
"h_min : " << h_min <<
'\n' 294 <<
"h_max : " << h_max <<
'\n' 295 <<
"kappa_min : " << kappa_min <<
'\n' 296 <<
"kappa_max : " << kappa_max <<
'\n';
300 Array<int> num_bdr_elems_by_geom(Geometry::NumGeom);
301 num_bdr_elems_by_geom = 0;
302 for (
int i = 0; i < GetNBE(); i++)
304 num_bdr_elems_by_geom[GetBdrElementBaseGeometry(i)]++;
306 Array<int> num_faces_by_geom(Geometry::NumGeom);
307 num_faces_by_geom = 0;
308 for (
int i = 0; i < GetNFaces(); i++)
310 num_faces_by_geom[GetFaceGeometry(i)]++;
314 <<
"Number of vertices : " << GetNV() <<
'\n' 315 <<
"Number of edges : " << GetNEdges() <<
'\n' 316 <<
"Number of faces : " << GetNFaces() <<
" -- ";
317 PrintElementsByGeometry(Dim-1, num_faces_by_geom, os);
319 <<
"Number of elements : " << GetNE() <<
" -- ";
320 PrintElementsByGeometry(Dim, num_elems_by_geom, os);
322 <<
"Number of bdr elem : " << GetNBE() <<
" -- ";
323 PrintElementsByGeometry(Dim-1, num_bdr_elems_by_geom, os);
325 <<
"Euler Number : " << EulerNumber() <<
'\n' 326 <<
"h_min : " << h_min <<
'\n' 327 <<
"h_max : " << h_max <<
'\n' 328 <<
"kappa_min : " << kappa_min <<
'\n' 329 <<
"kappa_max : " << kappa_max <<
'\n';
331 os <<
'\n' << std::flush;
338 case Element::POINT :
return &
PointFE;
339 case Element::SEGMENT :
return &
SegmentFE;
344 case Element::WEDGE :
return &
WedgeFE;
345 case Element::PYRAMID :
return &
PyramidFE;
347 MFEM_ABORT(
"Unknown element type \"" << ElemType <<
"\"");
350 MFEM_ABORT(
"Unknown element type");
359 ElTr->
ElementType = ElementTransformation::ELEMENT;
365 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
371 Nodes->FESpace()->GetElementVDofs(i, vdofs);
374 int n = vdofs.
Size()/spaceDim;
376 for (
int k = 0; k < spaceDim; k++)
378 for (
int j = 0; j < n; j++)
380 pm(k,j) = nodes(vdofs[n*k+j]);
383 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
387 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
392 ElTr->
ElementType = ElementTransformation::ELEMENT;
399 MFEM_ASSERT(nodes.
Size() == spaceDim*GetNV(),
"");
400 int nv = elements[i]->GetNVertices();
401 const int *v = elements[i]->GetVertices();
402 int n = vertices.Size();
404 for (
int k = 0; k < spaceDim; k++)
406 for (
int j = 0; j < nv; j++)
408 pm(k, j) = nodes(k*n+v[j]);
411 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
415 MFEM_ASSERT(nodes.
Size() == Nodes->Size(),
"");
417 Nodes->FESpace()->GetElementVDofs(i, vdofs);
418 int n = vdofs.
Size()/spaceDim;
420 for (
int k = 0; k < spaceDim; k++)
422 for (
int j = 0; j < n; j++)
424 pm(k,j) = nodes(vdofs[n*k+j]);
427 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
433 GetElementTransformation(i, &Transformation);
435 return &Transformation;
440 GetBdrElementTransformation(i, &BdrTransformation);
441 return &BdrTransformation;
448 ElTr->
ElementType = ElementTransformation::BDR_ELEMENT;
454 GetBdrPointMatrix(i, pm);
455 ElTr->
SetFE(GetTransformationFEforElementType(GetBdrElementType(i)));
465 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
466 int n = vdofs.
Size()/spaceDim;
468 for (
int k = 0; k < spaceDim; k++)
470 for (
int j = 0; j < n; j++)
472 pm(k,j) = nodes(vdofs[n*k+j]);
479 int elem_id, face_info;
480 GetBdrElementAdjacentElement2(i, elem_id, face_info);
482 GetLocalFaceTransformation(GetBdrElementType(i),
483 GetElementType(elem_id),
484 FaceElemTr.Loc1.Transf, face_info);
489 Nodes->FESpace()->GetTraceElement(elem_id, face_geom);
490 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
491 "Mesh requires nodal Finite Element.");
493 FaceElemTr.Loc1.Transf.ElementNo = elem_id;
494 FaceElemTr.Loc1.Transf.mesh =
this;
495 FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
496 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
497 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
499 ElTr->
SetFE(face_el);
506 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
514 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
515 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
517 for (
int i = 0; i < spaceDim; i++)
519 for (
int j = 0; j < nv; j++)
521 pm(i, j) = vertices[v[j]](i);
524 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
528 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
534 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
535 int n = vdofs.
Size()/spaceDim;
537 for (
int i = 0; i < spaceDim; i++)
539 for (
int j = 0; j < n; j++)
541 pm(i, j) = nodes(vdofs[n*i+j]);
548 FaceInfo &face_info = faces_info[FaceNo];
553 GetLocalFaceTransformation(face_type,
554 GetElementType(face_info.
Elem1No),
555 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
558 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
560 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
561 "Mesh requires nodal Finite Element.");
564 FaceElemTr.Loc1.Transf.ElementNo = face_info.
Elem1No;
565 FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
566 FaceElemTr.Loc1.Transf.mesh =
this;
567 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
568 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
577 GetFaceTransformation(FaceNo, &FaceTransformation);
578 return &FaceTransformation;
585 GetFaceTransformation(EdgeNo, EdTr);
590 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
602 GetEdgeVertices(EdgeNo, v);
605 for (
int i = 0; i < spaceDim; i++)
607 for (
int j = 0; j < nv; j++)
609 pm(i, j) = vertices[v[j]](i);
612 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
616 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
622 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
623 int n = vdofs.
Size()/spaceDim;
625 for (
int i = 0; i < spaceDim; i++)
627 for (
int j = 0; j < n; j++)
629 pm(i, j) = nodes(vdofs[n*i+j]);
632 EdTr->
SetFE(edge_el);
636 MFEM_ABORT(
"Not implemented.");
643 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
644 return &EdgeTransformation;
648 void Mesh::GetLocalPtToSegTransformation(
663 void Mesh::GetLocalSegToTriTransformation(
672 tv = tri_t::Edges[i/64];
673 so = seg_t::Orient[i%64];
676 for (
int j = 0; j < 2; j++)
678 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
679 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
683 void Mesh::GetLocalSegToQuadTransformation(
692 qv = quad_t::Edges[i/64];
693 so = seg_t::Orient[i%64];
696 for (
int j = 0; j < 2; j++)
698 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
699 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
703 void Mesh::GetLocalTriToTetTransformation(
711 const int *tv = tet_t::FaceVert[i/64];
714 const int *to = tri_t::Orient[i%64];
718 for (
int j = 0; j < 3; j++)
721 locpm(0, j) = vert.
x;
722 locpm(1, j) = vert.
y;
723 locpm(2, j) = vert.
z;
727 void Mesh::GetLocalTriToWdgTransformation(
735 MFEM_VERIFY(i < 128,
"Local face index " << i/64
736 <<
" is not a triangular face of a wedge.");
737 const int *pv = pri_t::FaceVert[i/64];
740 const int *to = tri_t::Orient[i%64];
744 for (
int j = 0; j < 3; j++)
747 locpm(0, j) = vert.
x;
748 locpm(1, j) = vert.
y;
749 locpm(2, j) = vert.
z;
753 void Mesh::GetLocalTriToPyrTransformation(
760 MFEM_VERIFY(i >= 64,
"Local face index " << i/64
761 <<
" is not a triangular face of a pyramid.");
762 const int *pv = pyr_t::FaceVert[i/64];
765 const int *to = tri_t::Orient[i%64];
769 for (
int j = 0; j < 3; j++)
772 locpm(0, j) = vert.
x;
773 locpm(1, j) = vert.
y;
774 locpm(2, j) = vert.
z;
778 void Mesh::GetLocalQuadToHexTransformation(
786 const int *hv = hex_t::FaceVert[i/64];
788 const int *qo = quad_t::Orient[i%64];
791 for (
int j = 0; j < 4; j++)
794 locpm(0, j) = vert.
x;
795 locpm(1, j) = vert.
y;
796 locpm(2, j) = vert.
z;
800 void Mesh::GetLocalQuadToWdgTransformation(
808 MFEM_VERIFY(i >= 128,
"Local face index " << i/64
809 <<
" is not a quadrilateral face of a wedge.");
810 const int *pv = pri_t::FaceVert[i/64];
812 const int *qo = quad_t::Orient[i%64];
815 for (
int j = 0; j < 4; j++)
818 locpm(0, j) = vert.
x;
819 locpm(1, j) = vert.
y;
820 locpm(2, j) = vert.
z;
824 void Mesh::GetLocalQuadToPyrTransformation(
831 MFEM_VERIFY(i < 64,
"Local face index " << i/64
832 <<
" is not a quadrilateral face of a pyramid.");
833 const int *pv = pyr_t::FaceVert[i/64];
835 const int *qo = quad_t::Orient[i%64];
838 for (
int j = 0; j < 4; j++)
841 locpm(0, j) = vert.
x;
842 locpm(1, j) = vert.
y;
843 locpm(2, j) = vert.
z;
851 for (
int i = 0; i < geom_factors.Size(); i++)
863 geom_factors.Append(gf);
871 for (
int i = 0; i < face_geom_factors.Size(); i++)
885 face_geom_factors.Append(gf);
889 void Mesh::DeleteGeometricFactors()
891 for (
int i = 0; i < geom_factors.Size(); i++)
893 delete geom_factors[i];
895 geom_factors.SetSize(0);
896 for (
int i = 0; i < face_geom_factors.Size(); i++)
898 delete face_geom_factors[i];
900 face_geom_factors.SetSize(0);
903 void Mesh::GetLocalFaceTransformation(
909 GetLocalPtToSegTransformation(Transf, info);
912 case Element::SEGMENT:
913 if (elem_type == Element::TRIANGLE)
915 GetLocalSegToTriTransformation(Transf, info);
919 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
920 GetLocalSegToQuadTransformation(Transf, info);
924 case Element::TRIANGLE:
925 if (elem_type == Element::TETRAHEDRON)
927 GetLocalTriToTetTransformation(Transf, info);
929 else if (elem_type == Element::WEDGE)
931 GetLocalTriToWdgTransformation(Transf, info);
933 else if (elem_type == Element::PYRAMID)
935 GetLocalTriToPyrTransformation(Transf, info);
939 MFEM_ABORT(
"Mesh::GetLocalFaceTransformation not defined for " 940 "face type " << face_type
941 <<
" and element type " << elem_type <<
"\n");
945 case Element::QUADRILATERAL:
946 if (elem_type == Element::HEXAHEDRON)
948 GetLocalQuadToHexTransformation(Transf, info);
950 else if (elem_type == Element::WEDGE)
952 GetLocalQuadToWdgTransformation(Transf, info);
954 else if (elem_type == Element::PYRAMID)
956 GetLocalQuadToPyrTransformation(Transf, info);
960 MFEM_ABORT(
"Mesh::GetLocalFaceTransformation not defined for " 961 "face type " << face_type
962 <<
" and element type " << elem_type <<
"\n");
971 FaceInfo &face_info = faces_info[FaceNo];
974 FaceElemTr.SetConfigurationMask(cmask);
975 FaceElemTr.Elem1 = NULL;
976 FaceElemTr.Elem2 = NULL;
980 if (mask & FaceElementTransformations::HAVE_ELEM1)
982 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
983 FaceElemTr.Elem1 = &Transformation;
990 FaceElemTr.Elem2No = face_info.
Elem2No;
991 if ((mask & FaceElementTransformations::HAVE_ELEM2) &&
992 FaceElemTr.Elem2No >= 0)
995 if (NURBSext && (mask & FaceElementTransformations::HAVE_ELEM1))
996 { MFEM_ABORT(
"NURBS mesh not supported!"); }
998 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
999 FaceElemTr.Elem2 = &Transformation2;
1004 if (mask & FaceElementTransformations::HAVE_FACE)
1006 GetFaceTransformation(FaceNo, &FaceElemTr);
1011 FaceElemTr.SetGeometryType(GetFaceGeometry(FaceNo));
1015 int face_type = GetFaceElementType(FaceNo);
1016 if (mask & FaceElementTransformations::HAVE_LOC1)
1018 int elem_type = GetElementType(face_info.
Elem1No);
1019 GetLocalFaceTransformation(face_type, elem_type,
1020 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
1023 if ((mask & FaceElementTransformations::HAVE_LOC2) &&
1024 FaceElemTr.Elem2No >= 0)
1026 int elem_type = GetElementType(face_info.
Elem2No);
1027 GetLocalFaceTransformation(face_type, elem_type,
1028 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
1031 if (Nonconforming() && IsSlaveFace(face_info))
1033 ApplyLocalSlaveTransformation(FaceElemTr, face_info,
false);
1038 FaceElemTr.SetConfigurationMask(cmask);
1044 double dist = FaceElemTr.CheckConsistency();
1047 mfem::out <<
"\nInternal error: face id = " << FaceNo
1048 <<
", dist = " << dist <<
'\n';
1049 FaceElemTr.CheckConsistency(1);
1050 MFEM_ABORT(
"internal error");
1060 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
1066 #ifdef MFEM_THREAD_SAFE 1071 MFEM_ASSERT(fi.
NCFace >= 0,
"");
1072 MFEM_ASSERT(nc_faces_info[fi.
NCFace].Slave,
"internal error");
1083 std::swap(composition(0,0), composition(0,1));
1084 std::swap(composition(1,0), composition(1,1));
1105 int fn = GetBdrFace(BdrElemNo);
1108 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
1112 tr = GetFaceElementTransformations(fn, 21);
1113 tr->
Attribute = boundary[BdrElemNo]->GetAttribute();
1115 tr->
ElementType = ElementTransformation::BDR_FACE;
1120 int Mesh::GetBdrFace(
int BdrElemNo)
const 1125 fn = be_to_face[BdrElemNo];
1129 fn = be_to_edge[BdrElemNo];
1133 fn = boundary[BdrElemNo]->GetVertices()[0];
1144 GetFaceElements(
f, &e1, &e2);
1145 GetFaceInfos(
f, &inf1, &inf2, &ncface);
1155 if (
f < GetNumFaces())
1161 face.
tag = FaceInfoTag::LocalConforming;
1162 face.
topology = FaceTopology::Conforming;
1171 face.
tag = FaceInfoTag::LocalSlaveNonconforming;
1172 face.
topology = FaceTopology::Nonconforming;
1177 MFEM_ASSERT(inf2%64==0,
"unexpected slave face orientation.");
1188 face.
tag = FaceInfoTag::Boundary;
1189 face.
topology = FaceTopology::Boundary;
1198 face.
tag = FaceInfoTag::SharedConforming;
1199 face.
topology = FaceTopology::Conforming;
1211 face.
tag = FaceInfoTag::MasterNonconforming;
1212 face.
topology = FaceTopology::Nonconforming;
1221 face.
tag = FaceInfoTag::SharedSlaveNonconforming;
1222 face.
topology = FaceTopology::Nonconforming;
1237 face.
tag = FaceInfoTag::GhostMaster;
1247 face.
tag = FaceInfoTag::GhostSlave;
1248 face.
topology = FaceTopology::Nonconforming;
1265 case FaceInfoTag::LocalConforming:
1266 res.
Elem1No = element[0].index;
1267 res.Elem2No = element[1].index;
1268 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1269 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1270 res.NCFace = ncface;
1272 case FaceInfoTag::LocalSlaveNonconforming:
1273 res.Elem1No = element[0].index;
1274 res.Elem2No = element[1].index;
1275 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1276 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1277 res.NCFace = ncface;
1279 case FaceInfoTag::Boundary:
1280 res.Elem1No = element[0].index;
1281 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1283 case FaceInfoTag::SharedConforming:
1284 res.Elem1No = element[0].index;
1285 res.Elem2No = -1 - element[1].index;
1286 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1287 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1289 case FaceInfoTag::MasterNonconforming:
1290 res.Elem1No = element[0].index;
1291 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1293 case FaceInfoTag::SharedSlaveNonconforming:
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;
1299 case FaceInfoTag::GhostMaster:
1301 case FaceInfoTag::GhostSlave:
1302 res.Elem1No = element[0].index;
1303 res.Elem2No = -1 - element[1].index;
1304 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1305 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1313 os <<
"face topology=";
1316 case Mesh::FaceTopology::Boundary:
1319 case Mesh::FaceTopology::Conforming:
1322 case Mesh::FaceTopology::Nonconforming:
1323 os <<
"Non-conforming";
1325 case Mesh::FaceTopology::NA:
1330 os <<
"element[0].location=";
1333 case Mesh::ElementLocation::Local:
1336 case Mesh::ElementLocation::FaceNbr:
1339 case Mesh::ElementLocation::NA:
1344 os <<
"element[1].location=";
1347 case Mesh::ElementLocation::Local:
1350 case Mesh::ElementLocation::FaceNbr:
1353 case Mesh::ElementLocation::NA:
1358 os <<
"element[0].conformity=";
1361 case Mesh::ElementConformity::Coincident:
1364 case Mesh::ElementConformity::Superset:
1367 case Mesh::ElementConformity::Subset:
1370 case Mesh::ElementConformity::NA:
1375 os <<
"element[1].conformity=";
1378 case Mesh::ElementConformity::Coincident:
1381 case Mesh::ElementConformity::Superset:
1384 case Mesh::ElementConformity::Subset:
1387 case Mesh::ElementConformity::NA:
1392 os <<
"element[0].index=" << info.
element[0].
index <<
'\n' 1393 <<
"element[1].index=" << info.
element[1].
index <<
'\n' 1398 <<
"ncface=" << info.
ncface << std::endl;
1402 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
const 1404 *Elem1 = faces_info[Face].Elem1No;
1405 *Elem2 = faces_info[Face].Elem2No;
1408 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
const 1410 *Inf1 = faces_info[Face].Elem1Inf;
1411 *Inf2 = faces_info[Face].Elem2Inf;
1414 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2,
int *NCFace)
const 1416 *Inf1 = faces_info[Face].Elem1Inf;
1417 *Inf2 = faces_info[Face].Elem2Inf;
1418 *NCFace = faces_info[Face].NCFace;
1425 case 1:
return Geometry::POINT;
1426 case 2:
return Geometry::SEGMENT;
1428 if (Face < NumOfFaces)
1430 return faces[Face]->GetGeometryType();
1433 const int nc_face_id = faces_info[Face].NCFace;
1434 MFEM_ASSERT(nc_face_id >= 0,
"parent ghost faces are not supported");
1435 return faces[nc_faces_info[nc_face_id].MasterFace]->GetGeometryType();
1437 return Geometry::INVALID;
1442 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
1447 Array<int> face_to_be(Dim == 2 ? NumOfEdges : NumOfFaces);
1449 for (
int i = 0; i < NumOfBdrElements; i++)
1451 face_to_be[GetBdrElementEdgeIndex(i)] = i;
1461 NumOfElements = NumOfBdrElements = 0;
1462 NumOfEdges = NumOfFaces = 0;
1463 nbInteriorFaces = -1;
1464 nbBoundaryFaces = -1;
1465 meshgen = mesh_geoms = 0;
1471 last_operation = Mesh::NONE;
1474 void Mesh::InitTables()
1477 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
1478 face_to_elem = NULL;
1481 void Mesh::SetEmpty()
1487 void Mesh::DestroyTables()
1492 DeleteGeometricFactors();
1502 delete face_to_elem;
1503 face_to_elem = NULL;
1506 void Mesh::DestroyPointers()
1508 if (own_nodes) {
delete Nodes; }
1514 for (
int i = 0; i < NumOfElements; i++)
1516 FreeElement(elements[i]);
1519 for (
int i = 0; i < NumOfBdrElements; i++)
1521 FreeElement(boundary[i]);
1524 for (
int i = 0; i < faces.Size(); i++)
1526 FreeElement(faces[i]);
1532 void Mesh::Destroy()
1536 elements.DeleteAll();
1537 vertices.DeleteAll();
1538 boundary.DeleteAll();
1540 faces_info.DeleteAll();
1541 nc_faces_info.DeleteAll();
1542 be_to_edge.DeleteAll();
1543 be_to_face.DeleteAll();
1551 CoarseFineTr.Clear();
1553 #ifdef MFEM_USE_MEMALLOC 1557 attributes.DeleteAll();
1558 bdr_attributes.DeleteAll();
1561 void Mesh::ResetLazyData()
1563 delete el_to_el; el_to_el = NULL;
1564 delete face_edge; face_edge = NULL;
1565 delete face_to_elem; face_to_elem = NULL;
1566 delete edge_vertex; edge_vertex = NULL;
1567 DeleteGeometricFactors();
1568 nbInteriorFaces = -1;
1569 nbBoundaryFaces = -1;
1572 void Mesh::SetAttributes()
1577 for (
int i = 0; i < attribs.
Size(); i++)
1579 attribs[i] = GetBdrAttribute(i);
1583 attribs.
Copy(bdr_attributes);
1584 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
1586 MFEM_WARNING(
"Non-positive attributes on the boundary!");
1590 for (
int i = 0; i < attribs.
Size(); i++)
1592 attribs[i] = GetAttribute(i);
1596 attribs.
Copy(attributes);
1597 if (attributes.Size() > 0 && attributes[0] <= 0)
1599 MFEM_WARNING(
"Non-positive attributes in the domain!");
1603 void Mesh::InitMesh(
int Dim_,
int spaceDim_,
int NVert,
int NElem,
int NBdrElem)
1608 spaceDim = spaceDim_;
1611 vertices.SetSize(NVert);
1614 elements.SetSize(NElem);
1616 NumOfBdrElements = 0;
1617 boundary.SetSize(NBdrElem);
1620 template<
typename T>
1621 static void CheckEnlarge(
Array<T> &array,
int size)
1623 if (size >= array.
Size()) { array.
SetSize(size + 1); }
1626 int Mesh::AddVertex(
double x,
double y,
double z)
1628 CheckEnlarge(vertices, NumOfVertices);
1629 double *v = vertices[NumOfVertices]();
1633 return NumOfVertices++;
1636 int Mesh::AddVertex(
const double *coords)
1638 CheckEnlarge(vertices, NumOfVertices);
1639 vertices[NumOfVertices].SetCoords(spaceDim, coords);
1640 return NumOfVertices++;
1645 MFEM_ASSERT(coords.
Size() >= spaceDim,
1646 "invalid 'coords' size: " << coords.
Size());
1647 return AddVertex(coords.
GetData());
1650 void Mesh::AddVertexParents(
int i,
int p1,
int p2)
1656 if (i < vertices.Size())
1658 double *vi = vertices[i](), *vp1 = vertices[p1](), *vp2 = vertices[p2]();
1659 for (
int j = 0; j < 3; j++)
1661 vi[j] = (vp1[j] + vp2[j]) * 0.5;
1666 int Mesh::AddSegment(
int v1,
int v2,
int attr)
1668 CheckEnlarge(elements, NumOfElements);
1669 elements[NumOfElements] =
new Segment(v1, v2, attr);
1670 return NumOfElements++;
1673 int Mesh::AddSegment(
const int *vi,
int attr)
1675 CheckEnlarge(elements, NumOfElements);
1676 elements[NumOfElements] =
new Segment(vi, attr);
1677 return NumOfElements++;
1680 int Mesh::AddTriangle(
int v1,
int v2,
int v3,
int attr)
1682 CheckEnlarge(elements, NumOfElements);
1683 elements[NumOfElements] =
new Triangle(v1, v2, v3, attr);
1684 return NumOfElements++;
1687 int Mesh::AddTriangle(
const int *vi,
int attr)
1689 CheckEnlarge(elements, NumOfElements);
1690 elements[NumOfElements] =
new Triangle(vi, attr);
1691 return NumOfElements++;
1694 int Mesh::AddQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1696 CheckEnlarge(elements, NumOfElements);
1697 elements[NumOfElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1698 return NumOfElements++;
1701 int Mesh::AddQuad(
const int *vi,
int attr)
1703 CheckEnlarge(elements, NumOfElements);
1705 return NumOfElements++;
1708 int Mesh::AddTet(
int v1,
int v2,
int v3,
int v4,
int attr)
1710 int vi[4] = {v1, v2, v3, v4};
1711 return AddTet(vi, attr);
1714 int Mesh::AddTet(
const int *vi,
int attr)
1716 CheckEnlarge(elements, NumOfElements);
1717 #ifdef MFEM_USE_MEMALLOC 1719 tet = TetMemory.Alloc();
1722 elements[NumOfElements] = tet;
1724 elements[NumOfElements] =
new Tetrahedron(vi, attr);
1726 return NumOfElements++;
1729 int Mesh::AddWedge(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int attr)
1731 CheckEnlarge(elements, NumOfElements);
1732 elements[NumOfElements] =
new Wedge(v1, v2, v3, v4, v5, v6, attr);
1733 return NumOfElements++;
1736 int Mesh::AddWedge(
const int *vi,
int attr)
1738 CheckEnlarge(elements, NumOfElements);
1739 elements[NumOfElements] =
new Wedge(vi, attr);
1740 return NumOfElements++;
1743 int Mesh::AddPyramid(
int v1,
int v2,
int v3,
int v4,
int v5,
int attr)
1745 CheckEnlarge(elements, NumOfElements);
1746 elements[NumOfElements] =
new Pyramid(v1, v2, v3, v4, v5, attr);
1747 return NumOfElements++;
1750 int Mesh::AddPyramid(
const int *vi,
int attr)
1752 CheckEnlarge(elements, NumOfElements);
1753 elements[NumOfElements] =
new Pyramid(vi, attr);
1754 return NumOfElements++;
1757 int Mesh::AddHex(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int v7,
int v8,
1760 CheckEnlarge(elements, NumOfElements);
1761 elements[NumOfElements] =
1762 new Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8, attr);
1763 return NumOfElements++;
1766 int Mesh::AddHex(
const int *vi,
int attr)
1768 CheckEnlarge(elements, NumOfElements);
1769 elements[NumOfElements] =
new Hexahedron(vi, attr);
1770 return NumOfElements++;
1773 void Mesh::AddHexAsTets(
const int *vi,
int attr)
1775 static const int hex_to_tet[6][4] =
1777 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
1778 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
1782 for (
int i = 0; i < 6; i++)
1784 for (
int j = 0; j < 4; j++)
1786 ti[j] = vi[hex_to_tet[i][j]];
1792 void Mesh::AddHexAsWedges(
const int *vi,
int attr)
1794 static const int hex_to_wdg[2][6] =
1796 { 0, 1, 2, 4, 5, 6 }, { 0, 2, 3, 4, 6, 7 }
1800 for (
int i = 0; i < 2; i++)
1802 for (
int j = 0; j < 6; j++)
1804 ti[j] = vi[hex_to_wdg[i][j]];
1810 void Mesh::AddHexAsPyramids(
const int *vi,
int attr)
1812 static const int hex_to_pyr[6][5] =
1814 { 0, 1, 2, 3, 8 }, { 0, 4, 5, 1, 8 }, { 1, 5, 6, 2, 8 },
1815 { 2, 6, 7, 3, 8 }, { 3, 7, 4, 0, 8 }, { 7, 6, 5, 4, 8 }
1819 for (
int i = 0; i < 6; i++)
1821 for (
int j = 0; j < 5; j++)
1823 ti[j] = vi[hex_to_pyr[i][j]];
1825 AddPyramid(ti, attr);
1831 CheckEnlarge(elements, NumOfElements);
1832 elements[NumOfElements] = elem;
1833 return NumOfElements++;
1838 CheckEnlarge(boundary, NumOfBdrElements);
1839 boundary[NumOfBdrElements] = elem;
1840 return NumOfBdrElements++;
1843 int Mesh::AddBdrSegment(
int v1,
int v2,
int attr)
1845 CheckEnlarge(boundary, NumOfBdrElements);
1846 boundary[NumOfBdrElements] =
new Segment(v1, v2, attr);
1847 return NumOfBdrElements++;
1850 int Mesh::AddBdrSegment(
const int *vi,
int attr)
1852 CheckEnlarge(boundary, NumOfBdrElements);
1853 boundary[NumOfBdrElements] =
new Segment(vi, attr);
1854 return NumOfBdrElements++;
1857 int Mesh::AddBdrTriangle(
int v1,
int v2,
int v3,
int attr)
1859 CheckEnlarge(boundary, NumOfBdrElements);
1860 boundary[NumOfBdrElements] =
new Triangle(v1, v2, v3, attr);
1861 return NumOfBdrElements++;
1864 int Mesh::AddBdrTriangle(
const int *vi,
int attr)
1866 CheckEnlarge(boundary, NumOfBdrElements);
1867 boundary[NumOfBdrElements] =
new Triangle(vi, attr);
1868 return NumOfBdrElements++;
1871 int Mesh::AddBdrQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1873 CheckEnlarge(boundary, NumOfBdrElements);
1874 boundary[NumOfBdrElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1875 return NumOfBdrElements++;
1878 int Mesh::AddBdrQuad(
const int *vi,
int attr)
1880 CheckEnlarge(boundary, NumOfBdrElements);
1882 return NumOfBdrElements++;
1885 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1887 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1890 for (
int i = 0; i < 2; i++)
1892 for (
int j = 0; j < 3; j++)
1894 ti[j] = vi[quad_to_tri[i][j]];
1896 AddBdrTriangle(ti, attr);
1900 int Mesh::AddBdrPoint(
int v,
int attr)
1902 CheckEnlarge(boundary, NumOfBdrElements);
1903 boundary[NumOfBdrElements] =
new Point(&v, attr);
1904 return NumOfBdrElements++;
1907 void Mesh::GenerateBoundaryElements()
1910 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1914 for (i = 0; i < boundary.Size(); i++)
1916 FreeElement(boundary[i]);
1926 NumOfBdrElements = 0;
1927 for (i = 0; i < faces_info.Size(); i++)
1929 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1932 boundary.SetSize(NumOfBdrElements);
1933 be2face.
SetSize(NumOfBdrElements);
1934 for (j = i = 0; i < faces_info.Size(); i++)
1936 if (faces_info[i].Elem2No < 0)
1938 boundary[j] = faces[i]->Duplicate(
this);
1945 void Mesh::FinalizeCheck()
1947 MFEM_VERIFY(vertices.Size() == NumOfVertices ||
1948 vertices.Size() == 0,
1949 "incorrect number of vertices: preallocated: " << vertices.Size()
1950 <<
", actually added: " << NumOfVertices);
1951 MFEM_VERIFY(elements.Size() == NumOfElements,
1952 "incorrect number of elements: preallocated: " << elements.Size()
1953 <<
", actually added: " << NumOfElements);
1954 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1955 "incorrect number of boundary elements: preallocated: " 1956 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1959 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1962 CheckElementOrientation(fix_orientation);
1966 MarkTriMeshForRefinement();
1971 el_to_edge =
new Table;
1972 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1974 CheckBdrElementOrientation();
1988 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1989 bool fix_orientation)
1992 if (fix_orientation)
1994 CheckElementOrientation(fix_orientation);
1999 el_to_edge =
new Table;
2000 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2002 CheckBdrElementOrientation();
2022 GeckoProgress(
double limit) : limit(limit) { sw.
Start(); }
2023 virtual bool quit()
const {
return limit > 0 && sw.
UserTime() > limit; }
2026 class GeckoVerboseProgress :
public GeckoProgress
2032 GeckoVerboseProgress(
double limit) : GeckoProgress(limit) {}
2034 virtual void beginorder(
const Graph* graph,
Float cost)
const 2035 {
mfem::out <<
"Begin Gecko ordering, cost = " << cost << std::endl; }
2036 virtual void endorder(
const Graph* graph,
Float cost)
const 2037 {
mfem::out <<
"End ordering, cost = " << cost << std::endl; }
2039 virtual void beginiter(
const Graph* graph,
2042 mfem::out <<
"Iteration " << iter <<
"/" << maxiter <<
", window " 2043 << window << std::flush;
2045 virtual void enditer(
const Graph* graph,
Float mincost,
Float cost)
const 2046 {
mfem::out <<
", cost = " << cost << endl; }
2051 int iterations,
int window,
2052 int period,
int seed,
bool verbose,
2058 GeckoProgress progress(time_limit);
2059 GeckoVerboseProgress vprogress(time_limit);
2062 for (
int elemid = 0; elemid < GetNE(); ++elemid)
2069 const Table &my_el_to_el = ElementToElementTable();
2070 for (
int elemid = 0; elemid < GetNE(); ++elemid)
2072 const int *neighid = my_el_to_el.
GetRow(elemid);
2073 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
2075 graph.
insert_arc(elemid + 1, neighid[i] + 1);
2080 graph.
order(&functional, iterations, window, period, seed,
2081 verbose ? &vprogress : &progress);
2087 ordering[gnodeid - 1] = graph.
rank(gnodeid);
2090 return graph.
cost();
2101 HilbertCmp(
int coord,
bool dir,
const Array<double> &points,
double mid)
2102 : coord(coord), dir(dir), points(points), mid(mid) {}
2104 bool operator()(
int i)
const 2106 return (points[3*i + coord] < mid) != dir;
2110 static void HilbertSort2D(
int coord1,
2113 const Array<double> &points,
int *beg,
int *end,
2114 double xmin,
double ymin,
double xmax,
double ymax)
2116 if (end - beg <= 1) {
return; }
2118 double xmid = (xmin + xmax)*0.5;
2119 double ymid = (ymin + ymax)*0.5;
2121 int coord2 = (coord1 + 1) % 2;
2124 int *p0 = beg, *p4 = end;
2125 int *p2 = std::partition(p0, p4, HilbertCmp(coord1, dir1, points, xmid));
2126 int *p1 = std::partition(p0, p2, HilbertCmp(coord2, dir2, points, ymid));
2127 int *p3 = std::partition(p2, p4, HilbertCmp(coord2, !dir2, points, ymid));
2131 HilbertSort2D(coord2, dir2, dir1, points, p0, p1,
2132 ymin, xmin, ymid, xmid);
2134 if (p1 != p0 || p2 != p4)
2136 HilbertSort2D(coord1, dir1, dir2, points, p1, p2,
2137 xmin, ymid, xmid, ymax);
2139 if (p2 != p0 || p3 != p4)
2141 HilbertSort2D(coord1, dir1, dir2, points, p2, p3,
2142 xmid, ymid, xmax, ymax);
2146 HilbertSort2D(coord2, !dir2, !dir1, points, p3, p4,
2147 ymid, xmax, ymin, xmid);
2151 static void HilbertSort3D(
int coord1,
bool dir1,
bool dir2,
bool dir3,
2152 const Array<double> &points,
int *beg,
int *end,
2153 double xmin,
double ymin,
double zmin,
2154 double xmax,
double ymax,
double zmax)
2156 if (end - beg <= 1) {
return; }
2158 double xmid = (xmin + xmax)*0.5;
2159 double ymid = (ymin + ymax)*0.5;
2160 double zmid = (zmin + zmax)*0.5;
2162 int coord2 = (coord1 + 1) % 3;
2163 int coord3 = (coord1 + 2) % 3;
2166 int *p0 = beg, *p8 = end;
2167 int *p4 = std::partition(p0, p8, HilbertCmp(coord1, dir1, points, xmid));
2168 int *p2 = std::partition(p0, p4, HilbertCmp(coord2, dir2, points, ymid));
2169 int *p6 = std::partition(p4, p8, HilbertCmp(coord2, !dir2, points, ymid));
2170 int *p1 = std::partition(p0, p2, HilbertCmp(coord3, dir3, points, zmid));
2171 int *p3 = std::partition(p2, p4, HilbertCmp(coord3, !dir3, points, zmid));
2172 int *p5 = std::partition(p4, p6, HilbertCmp(coord3, dir3, points, zmid));
2173 int *p7 = std::partition(p6, p8, HilbertCmp(coord3, !dir3, points, zmid));
2177 HilbertSort3D(coord3, dir3, dir1, dir2, points, p0, p1,
2178 zmin, xmin, ymin, zmid, xmid, ymid);
2180 if (p1 != p0 || p2 != p8)
2182 HilbertSort3D(coord2, dir2, dir3, dir1, points, p1, p2,
2183 ymin, zmid, xmin, ymid, zmax, xmid);
2185 if (p2 != p0 || p3 != p8)
2187 HilbertSort3D(coord2, dir2, dir3, dir1, points, p2, p3,
2188 ymid, zmid, xmin, ymax, zmax, xmid);
2190 if (p3 != p0 || p4 != p8)
2192 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p3, p4,
2193 xmin, ymax, zmid, xmid, ymid, zmin);
2195 if (p4 != p0 || p5 != p8)
2197 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p4, p5,
2198 xmid, ymax, zmid, xmax, ymid, zmin);
2200 if (p5 != p0 || p6 != p8)
2202 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p5, p6,
2203 ymax, zmid, xmax, ymid, zmax, xmid);
2205 if (p6 != p0 || p7 != p8)
2207 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p6, p7,
2208 ymid, zmid, xmax, ymin, zmax, xmid);
2212 HilbertSort3D(coord3, !dir3, !dir1, dir2, points, p7, p8,
2213 zmid, xmax, ymin, zmin, xmid, ymid);
2219 MFEM_VERIFY(spaceDim <= 3,
"");
2222 GetBoundingBox(min, max);
2227 if (spaceDim < 3) { points = 0.0; }
2230 for (
int i = 0; i < GetNE(); i++)
2232 GetElementCenter(i, center);
2233 for (
int j = 0; j < spaceDim; j++)
2235 points[3*i + j] = center(j);
2242 indices.
Sort([&](
int a,
int b)
2243 {
return points[3*
a] < points[3*
b]; });
2245 else if (spaceDim == 2)
2248 HilbertSort2D(0,
false,
false,
2249 points, indices.
begin(), indices.
end(),
2250 min(0), min(1), max(0), max(1));
2255 HilbertSort3D(0,
false,
false,
false,
2256 points, indices.
begin(), indices.
end(),
2257 min(0), min(1), min(2), max(0), max(1), max(2));
2262 for (
int i = 0; i < GetNE(); i++)
2264 ordering[indices[i]] = i;
2269 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
2273 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
2278 MFEM_WARNING(
"element reordering of non-conforming meshes is not" 2282 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
2312 old_elem_node_vals.SetSize(GetNE());
2313 nodes_fes = Nodes->FESpace();
2316 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2318 nodes_fes->GetElementVDofs(old_elid, old_dofs);
2320 old_elem_node_vals[old_elid] =
new Vector(vals);
2326 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
2328 int new_elid = ordering[old_elid];
2329 new_elements[new_elid] = elements[old_elid];
2334 if (reorder_vertices)
2339 vertex_ordering = -1;
2341 int new_vertex_ind = 0;
2342 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
2344 int *elem_vert = elements[new_elid]->GetVertices();
2345 int nv = elements[new_elid]->GetNVertices();
2346 for (
int vi = 0; vi < nv; ++vi)
2348 int old_vertex_ind = elem_vert[vi];
2349 if (vertex_ordering[old_vertex_ind] == -1)
2351 vertex_ordering[old_vertex_ind] = new_vertex_ind;
2352 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
2362 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
2364 int *elem_vert = elements[new_elid]->GetVertices();
2365 int nv = elements[new_elid]->GetNVertices();
2366 for (
int vi = 0; vi < nv; ++vi)
2368 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
2373 for (
int belid = 0; belid < GetNBE(); ++belid)
2375 int *be_vert = boundary[belid]->GetVertices();
2376 int nv = boundary[belid]->GetNVertices();
2377 for (
int vi = 0; vi < nv; ++vi)
2379 be_vert[vi] = vertex_ordering[be_vert[vi]];
2390 el_to_edge =
new Table;
2391 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2396 GetElementToFaceTable();
2406 last_operation = Mesh::NONE;
2407 nodes_fes->Update(
false);
2410 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2412 int new_elid = ordering[old_elid];
2413 nodes_fes->GetElementVDofs(new_elid, new_dofs);
2414 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
2415 delete old_elem_node_vals[old_elid];
2421 void Mesh::MarkForRefinement()
2427 MarkTriMeshForRefinement();
2431 DSTable v_to_v(NumOfVertices);
2432 GetVertexToVertexTable(v_to_v);
2433 MarkTetMeshForRefinement(v_to_v);
2438 void Mesh::MarkTriMeshForRefinement()
2443 for (
int i = 0; i < NumOfElements; i++)
2445 if (elements[i]->GetType() == Element::TRIANGLE)
2447 GetPointMatrix(i, pmat);
2448 static_cast<Triangle*
>(elements[i])->MarkEdge(pmat);
2459 for (
int i = 0; i < NumOfVertices; i++)
2464 length_idx[j].one = GetLength(i, it.Column());
2465 length_idx[j].two = j;
2472 for (
int i = 0; i < NumOfEdges; i++)
2474 order[length_idx[i].two] = i;
2478 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
2483 GetEdgeOrdering(v_to_v, order);
2485 for (
int i = 0; i < NumOfElements; i++)
2487 if (elements[i]->GetType() == Element::TETRAHEDRON)
2489 elements[i]->MarkEdge(v_to_v, order);
2492 for (
int i = 0; i < NumOfBdrElements; i++)
2494 if (boundary[i]->GetType() == Element::TRIANGLE)
2496 boundary[i]->MarkEdge(v_to_v, order);
2503 if (*old_v_to_v && *old_elem_vert)
2510 if (*old_v_to_v == NULL)
2512 bool need_v_to_v =
false;
2514 for (
int i = 0; i < GetNEdges(); i++)
2520 if (dofs.
Size() > 0)
2528 *old_v_to_v =
new DSTable(NumOfVertices);
2529 GetVertexToVertexTable(*(*old_v_to_v));
2532 if (*old_elem_vert == NULL)
2534 bool need_elem_vert =
false;
2536 for (
int i = 0; i < GetNE(); i++)
2542 if (dofs.
Size() > 1)
2544 need_elem_vert =
true;
2550 *old_elem_vert =
new Table;
2551 (*old_elem_vert)->
MakeI(GetNE());
2552 for (
int i = 0; i < GetNE(); i++)
2554 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
2556 (*old_elem_vert)->MakeJ();
2557 for (
int i = 0; i < GetNE(); i++)
2559 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
2560 elements[i]->GetNVertices());
2562 (*old_elem_vert)->ShiftUpI();
2575 const int num_edge_dofs = old_dofs.
Size();
2578 const Vector onodes = *Nodes;
2582 int offset = NumOfVertices * old_dofs.
Size();
2586 if (num_edge_dofs > 0)
2588 DSTable new_v_to_v(NumOfVertices);
2589 GetVertexToVertexTable(new_v_to_v);
2591 for (
int i = 0; i < NumOfVertices; i++)
2595 const int old_i = (*old_v_to_v)(i, it.Column());
2596 const int new_i = it.Index();
2597 if (new_i == old_i) {
continue; }
2599 old_dofs.
SetSize(num_edge_dofs);
2600 new_dofs.
SetSize(num_edge_dofs);
2601 for (
int j = 0; j < num_edge_dofs; j++)
2603 old_dofs[j] = offset + old_i * num_edge_dofs + j;
2604 new_dofs[j] = offset + new_i * num_edge_dofs + j;
2608 for (
int j = 0; j < old_dofs.
Size(); j++)
2610 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2614 offset += NumOfEdges * num_edge_dofs;
2622 Table old_face_vertex;
2623 old_face_vertex.
MakeI(NumOfFaces);
2624 for (
int i = 0; i < NumOfFaces; i++)
2628 old_face_vertex.
MakeJ();
2629 for (
int i = 0; i < NumOfFaces; i++)
2631 faces[i]->GetNVertices());
2635 STable3D *faces_tbl = GetElementToFaceTable(1);
2641 for (
int i = 0; i < NumOfFaces; i++)
2643 const int *old_v = old_face_vertex.
GetRow(i);
2645 switch (old_face_vertex.
RowSize(i))
2648 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2652 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2656 new_fdofs[new_i+1] = old_dofs.
Size();
2661 for (
int i = 0; i < NumOfFaces; i++)
2663 const int *old_v = old_face_vertex.
GetRow(i), *new_v;
2666 switch (old_face_vertex.
RowSize(i))
2669 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2670 new_v = faces[new_i]->GetVertices();
2671 new_or = GetTriOrientation(old_v, new_v);
2676 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2677 new_v = faces[new_i]->GetVertices();
2678 new_or = GetQuadOrientation(old_v, new_v);
2685 for (
int j = 0; j < old_dofs.
Size(); j++)
2688 const int old_j = dof_ord[j];
2689 new_dofs[old_j] = offset + new_fdofs[new_i] + j;
2693 for (
int j = 0; j < old_dofs.
Size(); j++)
2695 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2717 for (
int i = 0; i < GetNE(); i++)
2719 const int *old_v = old_elem_vert->
GetRow(i);
2720 const int *new_v = elements[i]->GetVertices();
2726 case Geometry::SEGMENT:
2727 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
2729 case Geometry::TRIANGLE:
2730 new_or = GetTriOrientation(old_v, new_v);
2732 case Geometry::SQUARE:
2733 new_or = GetQuadOrientation(old_v, new_v);
2735 case Geometry::TETRAHEDRON:
2736 new_or = GetTetOrientation(old_v, new_v);
2740 MFEM_ABORT(Geometry::Name[geom] <<
" elements (" << fec->
Name()
2741 <<
" FE collection) are not supported yet!");
2745 MFEM_VERIFY(dof_ord != NULL,
2746 "FE collection '" << fec->
Name()
2747 <<
"' does not define reordering for " 2748 << Geometry::Name[geom] <<
" elements!");
2751 for (
int j = 0; j < new_dofs.
Size(); j++)
2754 const int old_j = dof_ord[j];
2755 new_dofs[old_j] = offset + j;
2757 offset += new_dofs.
Size();
2760 for (
int j = 0; j < old_dofs.
Size(); j++)
2762 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2774 GetElementToFaceTable();
2777 CheckBdrElementOrientation();
2782 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2787 CheckBdrElementOrientation();
2792 last_operation = Mesh::NONE;
2797 void Mesh::SetPatchAttribute(
int i,
int attr)
2799 MFEM_ASSERT(NURBSext,
"SetPatchAttribute is only for NURBS meshes");
2800 NURBSext->SetPatchAttribute(i, attr);
2801 const Array<int>& elems = NURBSext->GetPatchElements(i);
2802 for (
auto e : elems)
2804 SetAttribute(e, attr);
2808 int Mesh::GetPatchAttribute(
int i)
const 2810 MFEM_ASSERT(NURBSext,
"GetPatchAttribute is only for NURBS meshes");
2811 return NURBSext->GetPatchAttribute(i);
2814 void Mesh::SetPatchBdrAttribute(
int i,
int attr)
2816 MFEM_ASSERT(NURBSext,
"SetPatchBdrAttribute is only for NURBS meshes");
2817 NURBSext->SetPatchBdrAttribute(i, attr);
2819 const Array<int>& bdryelems = NURBSext->GetPatchBdrElements(i);
2820 for (
auto be : bdryelems)
2822 SetBdrAttribute(be, attr);
2826 int Mesh::GetPatchBdrAttribute(
int i)
const 2828 MFEM_ASSERT(NURBSext,
"GetBdrPatchBdrAttribute is only for NURBS meshes");
2829 return NURBSext->GetPatchBdrAttribute(i);
2832 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
2835 CheckElementOrientation(fix_orientation);
2837 if (NumOfBdrElements == 0)
2839 GetElementToFaceTable();
2841 GenerateBoundaryElements();
2846 DSTable v_to_v(NumOfVertices);
2847 GetVertexToVertexTable(v_to_v);
2848 MarkTetMeshForRefinement(v_to_v);
2851 GetElementToFaceTable();
2854 CheckBdrElementOrientation();
2856 if (generate_edges == 1)
2858 el_to_edge =
new Table;
2859 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2873 void Mesh::FinalizeWedgeMesh(
int generate_edges,
int refine,
2874 bool fix_orientation)
2877 CheckElementOrientation(fix_orientation);
2879 if (NumOfBdrElements == 0)
2881 GetElementToFaceTable();
2883 GenerateBoundaryElements();
2886 GetElementToFaceTable();
2889 CheckBdrElementOrientation();
2891 if (generate_edges == 1)
2893 el_to_edge =
new Table;
2894 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2908 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
2911 CheckElementOrientation(fix_orientation);
2913 GetElementToFaceTable();
2916 if (NumOfBdrElements == 0)
2918 GenerateBoundaryElements();
2921 CheckBdrElementOrientation();
2925 el_to_edge =
new Table;
2926 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2938 void Mesh::FinalizeMesh(
int refine,
bool fix_orientation)
2942 Finalize(refine, fix_orientation);
2945 void Mesh::FinalizeTopology(
bool generate_bdr)
2957 bool generate_edges =
true;
2959 if (spaceDim == 0) { spaceDim = Dim; }
2960 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2964 if (tmp_vertex_parents.Size())
2966 MFEM_VERIFY(ncmesh == NULL,
"");
2967 ncmesh =
new NCMesh(
this);
2971 InitFromNCMesh(*ncmesh);
2972 ncmesh->OnMeshUpdated(
this);
2973 GenerateNCFaceInfo();
2977 tmp_vertex_parents.DeleteAll();
2987 GetElementToFaceTable();
2989 if (NumOfBdrElements == 0 && generate_bdr)
2991 GenerateBoundaryElements();
2992 GetElementToFaceTable();
3001 if (Dim > 1 && generate_edges)
3004 if (!el_to_edge) { el_to_edge =
new Table; }
3005 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3009 if (NumOfBdrElements == 0 && generate_bdr)
3011 GenerateBoundaryElements();
3023 if (NumOfBdrElements == 0 && generate_bdr)
3025 GenerateBoundaryElements();
3032 ncmesh->OnMeshUpdated(
this);
3035 GenerateNCFaceInfo();
3042 void Mesh::Finalize(
bool refine,
bool fix_orientation)
3044 if (NURBSext || ncmesh)
3046 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
3047 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
3056 const bool check_orientation =
true;
3057 const bool curved = (Nodes != NULL);
3058 const bool may_change_topology =
3059 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
3060 ( check_orientation && fix_orientation &&
3061 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
3064 Table *old_elem_vert = NULL;
3066 if (curved && may_change_topology)
3068 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
3071 if (check_orientation)
3074 CheckElementOrientation(fix_orientation);
3078 MarkForRefinement();
3081 if (may_change_topology)
3085 DoNodeReorder(old_v_to_v, old_elem_vert);
3086 delete old_elem_vert;
3099 CheckBdrElementOrientation();
3104 if (Dim >= 2 && Dim == spaceDim)
3106 const int num_faces = GetNumFaces();
3107 for (
int i = 0; i < num_faces; i++)
3109 MFEM_VERIFY(faces_info[i].Elem2No < 0 ||
3110 faces_info[i].Elem2Inf%2 != 0,
"Invalid mesh topology." 3111 " Interior face with incompatible orientations.");
3118 double sx,
double sy,
double sz,
bool sfc_ordering)
3122 int NVert, NElem, NBdrElem;
3124 NVert = (nx+1) * (ny+1) * (nz+1);
3125 NElem = nx * ny * nz;
3126 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
3127 if (type == Element::TETRAHEDRON)
3132 else if (type == Element::WEDGE)
3135 NBdrElem += 2*nx*ny;
3137 else if (type == Element::PYRAMID)
3140 NVert += nx * ny * nz;
3143 InitMesh(3, 3, NVert, NElem, NBdrElem);
3149 for (z = 0; z <= nz; z++)
3151 coord[2] = ((double) z / nz) * sz;
3152 for (y = 0; y <= ny; y++)
3154 coord[1] = ((double) y / ny) * sy;
3155 for (x = 0; x <= nx; x++)
3157 coord[0] = ((double) x / nx) * sx;
3162 if (type == Element::PYRAMID)
3164 for (z = 0; z < nz; z++)
3166 coord[2] = (((double) z + 0.5) / nz) * sz;
3167 for (y = 0; y < ny; y++)
3169 coord[1] = (((double) y + 0.5 ) / ny) * sy;
3170 for (x = 0; x < nx; x++)
3172 coord[0] = (((double) x + 0.5 ) / nx) * sx;
3179 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1)) 3180 #define VTXP(XC, YC, ZC) ((nx+1)*(ny+1)*(nz+1)+(XC)+((YC)+(ZC)*ny)*nx) 3183 if (sfc_ordering && type == Element::HEXAHEDRON)
3186 NCMesh::GridSfcOrdering3D(nx, ny, nz, sfc);
3187 MFEM_VERIFY(sfc.
Size() == 3*nx*ny*nz,
"");
3189 for (
int k = 0; k < nx*ny*nz; k++)
3196 ind[0] = VTX(x , y , z );
3197 ind[1] = VTX(x+1, y , z );
3198 ind[2] = VTX(x+1, y+1, z );
3199 ind[3] = VTX(x , y+1, z );
3200 ind[4] = VTX(x , y , z+1);
3201 ind[5] = VTX(x+1, y , z+1);
3202 ind[6] = VTX(x+1, y+1, z+1);
3203 ind[7] = VTX(x , y+1, z+1);
3211 for (z = 0; z < nz; z++)
3213 for (y = 0; y < ny; y++)
3215 for (x = 0; x < nx; x++)
3218 ind[0] = VTX(x , y , z );
3219 ind[1] = VTX(x+1, y , z );
3220 ind[2] = VTX(x+1, y+1, z );
3221 ind[3] = VTX(x , y+1, z );
3222 ind[4] = VTX(x , y , z+1);
3223 ind[5] = VTX(x+1, y , z+1);
3224 ind[6] = VTX(x+1, y+1, z+1);
3225 ind[7] = VTX( x, y+1, z+1);
3227 if (type == Element::TETRAHEDRON)
3229 AddHexAsTets(ind, 1);
3231 else if (type == Element::WEDGE)
3233 AddHexAsWedges(ind, 1);
3235 else if (type == Element::PYRAMID)
3237 ind[8] = VTXP(x, y, z);
3238 AddHexAsPyramids(ind, 1);
3251 for (y = 0; y < ny; y++)
3253 for (x = 0; x < nx; x++)
3256 ind[0] = VTX(x , y , 0);
3257 ind[1] = VTX(x , y+1, 0);
3258 ind[2] = VTX(x+1, y+1, 0);
3259 ind[3] = VTX(x+1, y , 0);
3261 if (type == Element::TETRAHEDRON)
3263 AddBdrQuadAsTriangles(ind, 1);
3265 else if (type == Element::WEDGE)
3267 AddBdrQuadAsTriangles(ind, 1);
3276 for (y = 0; y < ny; y++)
3278 for (x = 0; x < nx; x++)
3281 ind[0] = VTX(x , y , nz);
3282 ind[1] = VTX(x+1, y , nz);
3283 ind[2] = VTX(x+1, y+1, nz);
3284 ind[3] = VTX(x , y+1, nz);
3286 if (type == Element::TETRAHEDRON)
3288 AddBdrQuadAsTriangles(ind, 6);
3290 else if (type == Element::WEDGE)
3292 AddBdrQuadAsTriangles(ind, 6);
3301 for (z = 0; z < nz; z++)
3303 for (y = 0; y < ny; y++)
3306 ind[0] = VTX(0 , y , z );
3307 ind[1] = VTX(0 , y , z+1);
3308 ind[2] = VTX(0 , y+1, z+1);
3309 ind[3] = VTX(0 , y+1, z );
3311 if (type == Element::TETRAHEDRON)
3313 AddBdrQuadAsTriangles(ind, 5);
3322 for (z = 0; z < nz; z++)
3324 for (y = 0; y < ny; y++)
3327 ind[0] = VTX(nx, y , z );
3328 ind[1] = VTX(nx, y+1, z );
3329 ind[2] = VTX(nx, y+1, z+1);
3330 ind[3] = VTX(nx, y , z+1);
3332 if (type == Element::TETRAHEDRON)
3334 AddBdrQuadAsTriangles(ind, 3);
3343 for (x = 0; x < nx; x++)
3345 for (z = 0; z < nz; z++)
3348 ind[0] = VTX(x , 0, z );
3349 ind[1] = VTX(x+1, 0, z );
3350 ind[2] = VTX(x+1, 0, z+1);
3351 ind[3] = VTX(x , 0, z+1);
3353 if (type == Element::TETRAHEDRON)
3355 AddBdrQuadAsTriangles(ind, 2);
3364 for (x = 0; x < nx; x++)
3366 for (z = 0; z < nz; z++)
3369 ind[0] = VTX(x , ny, z );
3370 ind[1] = VTX(x , ny, z+1);
3371 ind[2] = VTX(x+1, ny, z+1);
3372 ind[3] = VTX(x+1, ny, z );
3374 if (type == Element::TETRAHEDRON)
3376 AddBdrQuadAsTriangles(ind, 4);
3388 ofstream test_stream(
"debug.mesh");
3390 test_stream.close();
3399 double sx,
double sy,
3400 bool generate_edges,
bool sfc_ordering)
3409 if (type == Element::QUADRILATERAL)
3411 NumOfVertices = (nx+1) * (ny+1);
3412 NumOfElements = nx * ny;
3413 NumOfBdrElements = 2 * nx + 2 * ny;
3415 vertices.SetSize(NumOfVertices);
3416 elements.SetSize(NumOfElements);
3417 boundary.SetSize(NumOfBdrElements);
3424 for (j = 0; j < ny+1; j++)
3426 cy = ((double) j / ny) * sy;
3427 for (i = 0; i < nx+1; i++)
3429 cx = ((double) i / nx) * sx;
3430 vertices[k](0) = cx;
3431 vertices[k](1) = cy;
3440 NCMesh::GridSfcOrdering2D(nx, ny, sfc);
3441 MFEM_VERIFY(sfc.
Size() == 2*nx*ny,
"");
3443 for (k = 0; k < nx*ny; k++)
3447 ind[0] = i + j*(nx+1);
3448 ind[1] = i + 1 +j*(nx+1);
3449 ind[2] = i + 1 + (j+1)*(nx+1);
3450 ind[3] = i + (j+1)*(nx+1);
3457 for (j = 0; j < ny; j++)
3459 for (i = 0; i < nx; i++)
3461 ind[0] = i + j*(nx+1);
3462 ind[1] = i + 1 +j*(nx+1);
3463 ind[2] = i + 1 + (j+1)*(nx+1);
3464 ind[3] = i + (j+1)*(nx+1);
3473 for (i = 0; i < nx; i++)
3475 boundary[i] =
new Segment(i, i+1, 1);
3476 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3479 for (j = 0; j < ny; j++)
3481 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3482 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3486 else if (type == Element::TRIANGLE)
3488 NumOfVertices = (nx+1) * (ny+1);
3489 NumOfElements = 2 * nx * ny;
3490 NumOfBdrElements = 2 * nx + 2 * ny;
3492 vertices.SetSize(NumOfVertices);
3493 elements.SetSize(NumOfElements);
3494 boundary.SetSize(NumOfBdrElements);
3501 for (j = 0; j < ny+1; j++)
3503 cy = ((double) j / ny) * sy;
3504 for (i = 0; i < nx+1; i++)
3506 cx = ((double) i / nx) * sx;
3507 vertices[k](0) = cx;
3508 vertices[k](1) = cy;
3515 for (j = 0; j < ny; j++)
3517 for (i = 0; i < nx; i++)
3519 ind[0] = i + j*(nx+1);
3520 ind[1] = i + 1 + (j+1)*(nx+1);
3521 ind[2] = i + (j+1)*(nx+1);
3524 ind[1] = i + 1 + j*(nx+1);
3525 ind[2] = i + 1 + (j+1)*(nx+1);
3533 for (i = 0; i < nx; i++)
3535 boundary[i] =
new Segment(i, i+1, 1);
3536 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3539 for (j = 0; j < ny; j++)
3541 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3542 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3549 MFEM_ABORT(
"Unsupported element type.");
3553 CheckElementOrientation();
3555 if (generate_edges == 1)
3557 el_to_edge =
new Table;
3558 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3560 CheckBdrElementOrientation();
3569 attributes.Append(1);
3570 bdr_attributes.Append(1); bdr_attributes.Append(2);
3571 bdr_attributes.Append(3); bdr_attributes.Append(4);
3576 void Mesh::Make1D(
int n,
double sx)
3585 NumOfVertices = n + 1;
3587 NumOfBdrElements = 2;
3588 vertices.SetSize(NumOfVertices);
3589 elements.SetSize(NumOfElements);
3590 boundary.SetSize(NumOfBdrElements);
3593 for (j = 0; j < n+1; j++)
3595 vertices[j](0) = ((
double) j / n) * sx;
3599 for (j = 0; j < n; j++)
3601 elements[j] =
new Segment(j, j+1, 1);
3606 boundary[0] =
new Point(ind, 1);
3608 boundary[1] =
new Point(ind, 2);
3616 attributes.Append(1);
3617 bdr_attributes.Append(1); bdr_attributes.Append(2);
3620 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
3638 last_operation = Mesh::NONE;
3641 elements.SetSize(NumOfElements);
3642 for (
int i = 0; i < NumOfElements; i++)
3644 elements[i] = mesh.
elements[i]->Duplicate(
this);
3651 boundary.SetSize(NumOfBdrElements);
3652 for (
int i = 0; i < NumOfBdrElements; i++)
3654 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
3673 faces.SetSize(mesh.
faces.Size());
3674 for (
int i = 0; i < faces.Size(); i++)
3677 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
3687 face_to_elem = NULL;
3712 if (dynamic_cast<const ParMesh*>(&mesh))
3724 if (mesh.
Nodes && copy_nodes)
3729 FiniteElementCollection::New(fec->
Name());
3733 Nodes->MakeOwner(fec_copy);
3734 *Nodes = *mesh.
Nodes;
3756 int refine,
bool fix_orientation)
3760 if (!imesh) { MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n'); }
3761 else { mesh.
Load(imesh, generate_edges, refine, fix_orientation); }
3775 double sx,
double sy,
bool sfc_ordering)
3778 mesh.
Make2D(nx, ny, type, sx, sy, generate_edges, sfc_ordering);
3785 double sx,
double sy,
double sz,
bool sfc_ordering)
3788 mesh.
Make3D(nx, ny, nz, type, sx, sy, sz, sfc_ordering);
3797 ref_factors = ref_factor;
3810 Mesh::Mesh(
const std::string &filename,
int generate_edges,
int refine,
3811 bool fix_orientation)
3820 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
3824 Load(imesh, generate_edges, refine, fix_orientation);
3829 bool fix_orientation)
3832 Load(input, generate_edges, refine, fix_orientation);
3841 "Not enough vertices in external array : " 3842 "len_vertex_data = "<< len_vertex_data <<
", " 3845 if (vertex_data == (
double *)(
vertices.GetData()))
3847 MFEM_ASSERT(!
vertices.OwnsData(),
"invalid ownership");
3852 memcpy(vertex_data,
vertices.GetData(),
3861 int *element_attributes,
int num_elements,
3863 int *boundary_attributes,
int num_boundary_elements,
3866 if (space_dimension == -1)
3872 num_boundary_elements);
3875 int boundary_index_stride = num_boundary_elements > 0 ?
3879 vertices.MakeRef(reinterpret_cast<Vertex*>(vertices_), num_vertices);
3882 for (
int i = 0; i < num_elements; i++)
3885 elements[i]->SetVertices(element_indices + i * element_index_stride);
3886 elements[i]->SetAttribute(element_attributes[i]);
3890 for (
int i = 0; i < num_boundary_elements; i++)
3893 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
3894 boundary[i]->SetAttribute(boundary_attributes[i]);
3910 #ifdef MFEM_USE_MEMALLOC 3919 MFEM_ABORT(
"invalid Geometry::Type, geom = " << geom);
3932 MFEM_VERIFY(el,
"Unsupported element type: " << geom);
3935 for (
int i = 0; i < nv; i++)
3948 for (
int j = 0; j < nv; j++)
4020 MFEM_ABORT(
"invalid element type: " << type);
4027 std::string parse_tag)
4029 int curved = 0, read_gf = 1;
4030 bool finalize_topo =
true;
4034 MFEM_ABORT(
"Input stream is not open");
4041 getline(input, mesh_type);
4045 int mfem_version = 0;
4046 if (mesh_type ==
"MFEM mesh v1.0") { mfem_version = 10; }
4047 else if (mesh_type ==
"MFEM mesh v1.2") { mfem_version = 12; }
4051 int mfem_nc_version = 0;
4052 if (mesh_type ==
"MFEM NC mesh v1.0") { mfem_nc_version = 10; }
4053 else if (mesh_type ==
"MFEM mesh v1.1") { mfem_nc_version = 1 ; }
4061 if (mfem_version == 12 && parse_tag.empty())
4063 parse_tag =
"mfem_mesh_end";
4067 else if (mfem_nc_version)
4069 MFEM_ASSERT(
ncmesh == NULL,
"internal error");
4076 MFEM_VERIFY(mfem_nc_version >= 10,
4077 "Legacy nonconforming format (MFEM mesh v1.1) cannot be " 4078 "used to load a parallel nonconforming mesh, sorry.");
4081 input, mfem_nc_version, curved, is_nc);
4086 ncmesh =
new NCMesh(input, mfem_nc_version, curved, is_nc);
4099 else if (mesh_type ==
"linemesh")
4103 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
4105 if (mesh_type ==
"curved_areamesh2")
4111 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
4115 else if (mesh_type ==
"TrueGrid")
4119 else if (mesh_type.rfind(
"# vtk DataFile Version") == 0)
4121 int major_vtk_version = mesh_type[mesh_type.length()-3] -
'0';
4123 MFEM_VERIFY(major_vtk_version >= 2 && major_vtk_version <= 4,
4124 "Unsupported VTK format");
4125 ReadVTKMesh(input, curved, read_gf, finalize_topo);
4127 else if (mesh_type.rfind(
"<VTKFile ") == 0 || mesh_type.rfind(
"<?xml") == 0)
4131 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
4135 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
4140 else if (mesh_type ==
"$MeshFormat")
4145 ((mesh_type.size() > 2 &&
4146 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
4147 (mesh_type.size() > 3 &&
4148 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
4153 #ifdef MFEM_USE_NETCDF 4156 MFEM_ABORT(
"NetCDF support requires configuration with" 4157 " MFEM_USE_NETCDF=YES");
4163 MFEM_ABORT(
"Can not determine Cubit mesh filename!" 4164 " Use mfem::named_ifgzstream for input.");
4170 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
4196 bool generate_bdr =
false;
4201 if (curved && read_gf)
4215 if (mfem_version == 12)
4221 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
4222 getline(input, line);
4228 if (line ==
"mfem_mesh_end") {
break; }
4230 while (line != parse_tag);
4232 else if (mfem_nc_version >= 10)
4237 MFEM_VERIFY(ident ==
"mfem_mesh_end",
4238 "invalid mesh: end of file tag not found");
4246 int i, j, ie, ib, iv, *v, nv;
4277 for (i = 0; i < num_pieces; i++)
4284 for (i = 0; i < num_pieces; i++)
4290 for (j = 0; j < m->
GetNE(); j++)
4295 for (j = 0; j < m->
GetNBE(); j++)
4300 for (
int k = 0; k < nv; k++)
4302 v[k] = lvert_vert[v[k]];
4307 for (j = 0; j < m->
GetNV(); j++)
4319 for (i = 0; i < num_pieces; i++)
4330 for (i = 0; i < num_pieces; i++)
4334 for (j = 0; j < m->
GetNE(); j++)
4339 for (
int k = 0; k < nv; k++)
4346 for (j = 0; j < m->
GetNBE(); j++)
4351 for (
int k = 0; k < nv; k++)
4358 for (j = 0; j < m->
GetNV(); j++)
4372 for (i = 0; i < num_pieces; i++)
4374 gf_array[i] = mesh_array[i]->
GetNodes();
4389 ref_factors = ref_factor;
4400 int orig_ne = orig_mesh.
GetNE();
4401 MFEM_VERIFY(ref_factors.
Size() == orig_ne && orig_ne > 0,
4402 "Number of refinement factors must equal number of elements")
4403 MFEM_VERIFY(ref_factors.
Min() >= 1,
"Refinement factor must be >= 1");
4406 "Invalid refinement type. Must use closed basis type.");
4408 int min_ref = ref_factors.
Min();
4409 int max_ref = ref_factors.
Max();
4411 bool var_order = (min_ref != max_ref);
4424 for (
int i = 0; i < orig_ne; i++)
4442 for (
int el = 0; el < orig_ne; el++)
4454 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[el]);
4455 for (
int i = 0; i < phys_pts.
Width(); i++)
4464 for (
int k = 0; k < nvert; k++)
4467 v[k] = rdofs[c2h_map[cid]];
4480 for (
int el = 0; el < orig_mesh.
GetNBE(); el++)
4491 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[i]);
4497 for (
int k = 0; k < nvert; k++)
4500 v[k] = rdofs[c2h_map[cid]];
4522 for (
int iel = 0; iel < orig_ne; iel++)
4531 const int *node_map = NULL;
4534 if (h1_fec != NULL) { node_map = h1_fec->
GetDofMap(geom); }
4535 const int *vertex_map = vertex_fec.
GetDofMap(geom);
4536 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[iel]);
4537 for (
int jel = 0; jel < RG.
RefGeoms.
Size()/nvert; jel++)
4540 for (
int iv_lex=0; iv_lex<nvert; ++iv_lex)
4543 int iv = vertex_map[iv_lex];
4545 int pt_idx = c2h_map[RG.
RefGeoms[iv+nvert*jel]];
4547 int node_idx = node_map ? node_map[iv_lex] : iv_lex;
4550 (*Nodes)[dofs[node_idx + d*nvert]] = phys_pts(d,pt_idx);
4561 using GeomRef = std::pair<Geometry::Type, int>;
4562 std::map<GeomRef, int> point_matrices_offsets;
4564 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4568 GeomRef id(geom, ref_factors[el_coarse]);
4569 if (point_matrices_offsets.find(
id) == point_matrices_offsets.end())
4575 point_matrices_offsets[id] = n_point_matrices[geom];
4576 n_point_matrices[geom] += nref_el;
4583 int nmatrices = n_point_matrices[geom];
4590 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4593 int ref = ref_factors[el_coarse];
4594 int offset = point_matrices_offsets[GeomRef(geom, ref)];
4600 for (
int k = 0; k < nvert; k++)
4632 "Mesh::MakeSimplicial requires a properly oriented input mesh");
4634 "Mesh::MakeSimplicial does not support non-conforming meshes.")
4641 Mesh copy(orig_mesh);
4646 int nv = orig_mesh.
GetNV();
4647 int ne = orig_mesh.
GetNE();
4648 int nbe = orig_mesh.
GetNBE();
4661 int new_ne = 0, new_nbe = 0;
4662 for (
int i=0; i<ne; ++i)
4666 for (
int i=0; i<nbe; ++i)
4675 for (
int i=0; i<nv; ++i)
4685 if (vglobal == NULL)
4688 for (
int i=0; i<nv; ++i) { vglobal_id[i] = i; }
4689 vglobal = vglobal_id.
GetData();
4692 constexpr
int nv_tri = 3, nv_quad = 4, nv_tet = 4, nv_prism = 6, nv_hex = 8;
4693 constexpr
int quad_ntris = 2, prism_ntets = 3;
4694 static const int quad_trimap[2][nv_tri*quad_ntris] =
4706 static const int prism_rot[nv_prism*nv_prism] =
4715 static const int prism_f[nv_quad] = {1, 2, 5, 4};
4716 static const int prism_tetmaps[2][nv_prism*prism_ntets] =
4730 static const int hex_rot[nv_hex*nv_hex] =
4732 0, 1, 2, 3, 4, 5, 6, 7,
4733 1, 0, 4, 5, 2, 3, 7, 6,
4734 2, 1, 5, 6, 3, 0, 4, 7,
4735 3, 0, 1, 2, 7, 4, 5, 6,
4736 4, 0, 3, 7, 5, 1, 2, 6,
4737 5, 1, 0, 4, 6, 2, 3, 7,
4738 6, 2, 1, 5, 7, 3, 0, 4,
4739 7, 3, 2, 6, 4, 0, 1, 5
4741 static const int hex_f0[nv_quad] = {1, 2, 6, 5};
4742 static const int hex_f1[nv_quad] = {2, 3, 7, 6};
4743 static const int hex_f2[nv_quad] = {4, 5, 6, 7};
4744 static const int num_rot[8] = {0, 1, 2, 0, 0, 2, 1, 0};
4745 static const int hex_tetmap0[nv_tet*5] =
4752 static const int hex_tetmap1[nv_tet*6] =
4759 static const int hex_tetmap2[nv_tet*6] =
4766 static const int hex_tetmap3[nv_tet*6] =
4773 static const int *hex_tetmaps[4] =
4775 hex_tetmap0, hex_tetmap1, hex_tetmap2, hex_tetmap3
4778 auto find_min = [](
const int*
a,
int n) {
return std::min_element(
a,
a+n)-
a; };
4780 for (
int i=0; i<ne; ++i)
4782 const int *v = orig_mesh.
elements[i]->GetVertices();
4786 if (num_subdivisions[orig_geom] == 1)
4798 for (
int itri=0; itri<quad_ntris; ++itri)
4803 for (
int iv=0; iv<nv_tri; ++iv)
4805 v2[iv] = v[quad_trimap[0][itri + iv*quad_ntris]];
4813 for (
int iv=0; iv<nv_prism; ++iv) { vg[iv] = vglobal[v[iv]]; }
4816 int irot = find_min(vg, nv_prism);
4817 for (
int iv=0; iv<nv_prism; ++iv)
4819 int jv = prism_rot[iv + irot*nv_prism];
4824 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[prism_f[iv]]]; }
4825 int j = find_min(q, nv_quad);
4826 const int *tetmap = (j == 0 || j == 2) ? prism_tetmaps[0] : prism_tetmaps[1];
4827 for (
int itet=0; itet<prism_ntets; ++itet)
4832 for (
int iv=0; iv<nv_tet; ++iv)
4834 v2[iv] = vg[tetmap[itet + iv*prism_ntets]];
4842 for (
int iv=0; iv<nv_hex; ++iv) { vg[iv] = vglobal[v[iv]]; }
4846 int irot = find_min(vg, nv_hex);
4847 for (
int iv=0; iv<nv_hex; ++iv)
4849 int jv = hex_rot[iv + irot*nv_hex];
4859 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f0[iv]]]; }
4860 j = find_min(q, nv_quad);
4861 if (j == 0 || j == 2) { bitmask += 4; }
4863 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f1[iv]]]; }
4864 j = find_min(q, nv_quad);
4865 if (j == 1 || j == 3) { bitmask += 2; }
4867 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f2[iv]]]; }
4868 j = find_min(q, nv_quad);
4869 if (j == 0 || j == 2) { bitmask += 1; }
4872 int nrot = num_rot[bitmask];
4873 for (
int k=0; k<nrot; ++k)
4887 int ndiags = ((bitmask&4) >> 2) + ((bitmask&2) >> 1) + (bitmask&1);
4888 int ntets = (ndiags == 0) ? 5 : 6;
4889 const int *tetmap = hex_tetmaps[ndiags];
4890 for (
int itet=0; itet<ntets; ++itet)
4895 for (
int iv=0; iv<nv_tet; ++iv)
4897 v2[iv] = vg[tetmap[itet + iv*ntets]];
4906 for (
int i=0; i<nbe; ++i)
4908 const int *v = orig_mesh.
boundary[i]->GetVertices();
4911 if (num_subdivisions[orig_geom] == 1)
4921 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
4923 int iv_min = find_min(vg, nv_quad);
4924 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
4925 for (
int itri=0; itri<quad_ntris; ++itri)
4930 for (
int iv=0; iv<nv_tri; ++iv)
4932 v2[iv] = v[quad_trimap[isplit][itri + iv*quad_ntris]];
4939 MFEM_ABORT(
"Unreachable");
4953 Mesh periodic_mesh(orig_mesh,
true);
4959 for (
int i = 0; i < periodic_mesh.
GetNE(); i++)
4964 for (
int j = 0; j < nv; j++)
4970 for (
int i = 0; i < periodic_mesh.
GetNBE(); i++)
4975 for (
int j = 0; j < nv; j++)
4982 return periodic_mesh;
4986 const std::vector<Vector> &translations,
double tol)
const 4990 Vector coord(sdim), at(sdim), dx(sdim);
4991 Vector xMax(sdim), xMin(sdim), xDiff(sdim);
4992 xMax = xMin = xDiff = 0.0;
4996 for (
int be = 0; be <
GetNBE(); be++)
5001 for (
int i = 0; i < dofs.
Size(); i++)
5003 bdr_v.insert(dofs[i]);
5006 for (
int j = 0; j < sdim; j++)
5008 xMax[j] = max(xMax[j], coord[j]);
5009 xMin[j] = min(xMin[j], coord[j]);
5013 add(xMax, -1.0, xMin, xDiff);
5014 double dia = xDiff.
Norml2();
5022 map<int, int> replica2primary;
5024 map<int, set<int>> primary2replicas;
5028 for (
int v : bdr_v) { primary2replicas[v]; }
5032 auto make_replica = [&replica2primary, &primary2replicas](
int r,
int p)
5034 if (r ==
p) {
return; }
5035 primary2replicas[
p].insert(r);
5036 replica2primary[r] =
p;
5037 for (
int s : primary2replicas[r])
5039 primary2replicas[
p].insert(
s);
5040 replica2primary[
s] =
p;
5042 primary2replicas.erase(r);
5045 for (
unsigned int i = 0; i < translations.size(); i++)
5047 for (
int vi : bdr_v)
5050 add(coord, translations[i], at);
5052 for (
int vj : bdr_v)
5055 add(at, -1.0, coord, dx);
5056 if (dx.
Norml2() > dia*tol) {
continue; }
5061 bool pi = primary2replicas.find(vi) != primary2replicas.end();
5062 bool pj = primary2replicas.find(vj) != primary2replicas.end();
5068 make_replica(vj, vi);
5073 int owner_of_vj = replica2primary[vj];
5075 make_replica(vi, owner_of_vj);
5081 int owner_of_vi = replica2primary[vi];
5082 make_replica(vj, owner_of_vi);
5089 int owner_of_vi = replica2primary[vi];
5090 int owner_of_vj = replica2primary[vj];
5091 make_replica(owner_of_vj, owner_of_vi);
5098 std::vector<int> v2v(
GetNV());
5099 for (
size_t i = 0; i < v2v.size(); i++)
5103 for (
auto &&r2p : replica2primary)
5105 v2v[r2p.first] = r2p.second;
5112 MFEM_VERIFY(
NURBSext,
"Mesh::RefineNURBSFromFile: Not a NURBS mesh!");
5113 mfem::out<<
"Refining NURBS from refinement file: "<<ref_file<<endl;
5116 ifstream input(ref_file);
5123 mfem::out<<
"Knot vectors in ref_file: "<<nkv<<endl;
5125 MFEM_ABORT(
"Refine file does not have the correct number of knot vectors");
5130 for (
int kv = 0; kv < nkv; kv++)
5132 knotVec[kv] =
new Vector();
5133 knotVec[kv]->
Load(input);
5141 for (
int kv = 0; kv < nkv; kv++)
5151 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
5156 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
5173 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
5178 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
5208 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
5232 for (
int i = 0; i <
elements.Size(); i++)
5242 for (
int i = 0; i <
boundary.Size(); i++)
5259 for (
int i = 0; i < vd; i++)
5326 input >> edge_to_knot[j] >> v[0] >> v[1];
5329 edge_to_knot[j] = -1 - edge_to_knot[j];
5349 if (edge_to_knot.
Size() == 0)
5353 constexpr
int notset = -9999999;
5354 edge_to_knot = notset;
5366 edge0[0] = 0; edge1[0] = 2;
5367 edge0[1] = 1; edge1[1] = 3;
5375 edge0[0] = 0; edge1[0] = 2;
5376 edge0[1] = 0; edge1[1] = 4;
5377 edge0[2] = 0; edge1[2] = 6;
5379 edge0[3] = 1; edge1[3] = 3;
5380 edge0[4] = 1; edge1[4] = 5;
5381 edge0[5] = 1; edge1[5] = 7;
5383 edge0[6] = 8; edge1[6] = 9;
5384 edge0[7] = 8; edge1[7] = 10;
5385 edge0[8] = 8; edge1[8] = 11;
5393 int e0, e1, v0, v1, df;
5399 const int *v =
elements[
p]->GetVertices();
5400 for (j = 0; j < edges.
Size(); j++)
5403 const int *e =
elements[
p]->GetEdgeVertices(j);
5416 for (j = 0; j < edge1.
Size(); j++)
5418 e0 = edges[edge0[j]];
5419 e1 = edges[edge1[j]];
5420 v0 = edge_to_knot[e0];
5421 v1 = edge_to_knot[e1];
5422 df = flip*oedge[edge0[j]]*oedge[edge1[j]];
5425 if ((v0 == notset) && (v1 == notset))
5427 edge_to_knot[e0] = knot;
5428 edge_to_knot[e1] = knot;
5434 else if ((v0 != notset) && (v1 == notset))
5436 edge_to_knot[e1] = (df >= 0 ? -v0-1 : v0);
5438 else if ((v0 == notset) && (v1 != notset))
5440 edge_to_knot[e0] = (df >= 0 ? -v1-1 : v1);
5460 for (j = 0; j < edge1.
Size(); j++)
5462 e0 = edges[edge0[j]];
5463 e1 = edges[edge1[j]];
5464 v0 = edge_to_knot[e0];
5465 v1 = edge_to_knot[e1];
5466 v0 = ( v0 >= 0 ? v0 : -v0-1);
5467 v1 = ( v1 >= 0 ? v1 : -v1-1);
5473 edge_to_knot[e1] = (oedge[edge1[j]] >= 0 ? v0 : -v0-1);
5477 edge_to_knot[e0] = (oedge[edge0[j]] >= 0 ? v1 : -v1-1);
5485 while (corrections > 0 && passes <
GetNE() + 1);
5488 if (corrections > 0 )
5490 mfem::err<<
"Edge_to_knot mapping potentially incorrect"<<endl;
5492 mfem::err<<
" corrections = "<<corrections<<endl;
5502 k = edge_to_knot[j];
5503 cnt[(k >= 0 ? k : -k-1)]++;
5507 for (j = 0; j < cnt.
Size(); j++)
5509 cnt[j] = (cnt[j] > 0 ? k++ : -1);
5514 k = edge_to_knot[j];
5515 edge_to_knot[j] = (k >= 0 ? cnt[k]:-cnt[-k-1]-1);
5519 mfem::out<<
"Generated edge to knot mapping:"<<endl;
5523 k = edge_to_knot[j];
5532 mfem::out<<(k >= 0 ? k:-k-1)<<
" "<< v[0] <<
" "<<v[1]<<endl;
5536 if (corrections > 0 ) {
mfem_error(
"Mesh::LoadPatchTopo");}
5542 if (
p.Size() >= v.
Size())
5544 for (
int d = 0; d < v.
Size(); d++)
5552 for (d = 0; d <
p.Size(); d++)
5556 for ( ; d < v.
Size(); d++)
5588 if (dynamic_cast<const H1_FECollection*>(fec)
5589 || dynamic_cast<const L2_FECollection*>(fec))
5598 #ifndef MFEM_USE_MPI 5599 const bool warn =
true;
5602 const bool warn = !pmesh || pmesh->
GetMyRank() == 0;
5606 MFEM_WARNING(
"converting NURBS mesh to order " << order <<
5607 " H1-continuous mesh!\n " 5608 "If this is the desired behavior, you can silence" 5609 " this warning by converting\n " 5610 "the NURBS mesh to high-order mesh in advance by" 5611 " calling the method\n " 5612 "Mesh::SetCurvature().");
5637 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
5656 MFEM_ASSERT(nodes != NULL,
"");
5672 case 1:
return GetNV();
5708 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG)) 5709 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
5714 int i, j, k, wo = 0, fo = 0;
5723 int *vi =
elements[i]->GetVertices();
5726 for (j = 0; j < 3; j++)
5730 for (j = 0; j < 2; j++)
5731 for (k = 0; k < 2; k++)
5733 J(j, k) = v[j+1][k] - v[0][k];
5754 MFEM_ABORT(
"Invalid 2D element type \"" 5771 int *vi =
elements[i]->GetVertices();
5777 for (j = 0; j < 4; j++)
5781 for (j = 0; j < 3; j++)
5782 for (k = 0; k < 3; k++)
5784 J(j, k) = v[j+1][k] - v[0][k];
5843 MFEM_ABORT(
"Invalid 3D element type \"" 5849 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG)) 5852 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / " 5853 <<
NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
5857 MFEM_CONTRACT_VAR(fo);
5870 if (test[0] == base[0])
5871 if (test[1] == base[1])
5879 else if (test[0] == base[1])
5880 if (test[1] == base[0])
5889 if (test[1] == base[0])
5900 for (
int j = 0; j < 3; j++)
5901 if (test[aor[j]] != base[j])
5903 mfem::err <<
"Mesh::GetTriOrientation(...)" << endl;
5905 for (
int k = 0; k < 3; k++)
5910 for (
int k = 0; k < 3; k++)
5931 const int oo[6][6] =
5941 int ori_a_c = oo[ori_a_b][ori_b_c];
5947 const int inv_ori[6] = {0, 1, 4, 3, 2, 5};
5948 return inv_ori[ori];
5955 for (i = 0; i < 4; i++)
5956 if (test[i] == base[0])
5963 if (test[(i+1)%4] == base[1])
5972 for (
int j = 0; j < 4; j++)
5973 if (test[aor[j]] != base[j])
5975 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
5977 for (
int k = 0; k < 4; k++)
5982 for (
int k = 0; k < 4; k++)
5991 if (test[(i+1)%4] == base[1])
6008 const int oo[8][8] =
6010 {0, 1, 2, 3, 4, 5, 6, 7},
6011 {1, 0, 3, 2, 5, 4, 7, 6},
6012 {2, 7, 4, 1, 6, 3, 0, 5},
6013 {3, 6, 5, 0, 7, 2, 1, 4},
6014 {4, 5, 6, 7, 0, 1, 2, 3},
6015 {5, 4, 7, 6, 1, 0, 3, 2},
6016 {6, 3, 0, 5, 2, 7, 4, 1},
6017 {7, 2, 1, 4, 3, 6, 5, 0}
6020 int ori_a_c = oo[ori_a_b][ori_b_c];
6026 const int inv_ori[8] = {0, 1, 6, 3, 4, 5, 2, 7};
6027 return inv_ori[ori];
6038 if (test[0] == base[0])
6039 if (test[1] == base[1])
6040 if (test[2] == base[2])
6048 else if (test[2] == base[1])
6049 if (test[3] == base[2])
6058 if (test[1] == base[2])
6066 else if (test[1] == base[0])
6067 if (test[2] == base[1])
6068 if (test[0] == base[2])
6076 else if (test[3] == base[1])
6077 if (test[2] == base[2])
6086 if (test[3] == base[2])
6094 else if (test[2] == base[0])
6095 if (test[3] == base[1])
6096 if (test[0] == base[2])
6104 else if (test[0] == base[1])
6105 if (test[1] == base[2])
6114 if (test[3] == base[2])
6123 if (test[0] == base[1])
6124 if (test[2] == base[2])
6132 else if (test[1] == base[1])
6133 if (test[0] == base[2])
6142 if (test[1] == base[2])
6153 for (
int j = 0; j < 4; j++)
6154 if (test[aor[j]] != base[j])
6179 int *bv =
boundary[i]->GetVertices();
6185 mfem::Swap<int>(bv[0], bv[1]);
6199 if (
faces_info[fi].Elem2No >= 0) {
continue; }
6202 int *bv =
boundary[i]->GetVertices();
6204 MFEM_ASSERT(fi <
faces.Size(),
"internal error");
6205 const int *fv =
faces[fi]->GetVertices();
6222 MFEM_ABORT(
"Invalid 2D boundary element type \"" 6223 << bdr_type <<
"\"");
6228 if (orientation % 2 == 0) {
continue; }
6230 if (!fix_it) {
continue; }
6238 mfem::Swap<int>(bv[0], bv[1]);
6242 mfem::Swap<int>(be[1], be[2]);
6248 mfem::Swap<int>(bv[0], bv[2]);
6252 mfem::Swap<int>(be[0], be[1]);
6253 mfem::Swap<int>(be[2], be[3]);
6266 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / " 6276 MFEM_ASSERT(0 <=
dim &&
dim <=
Dim,
"invalid dim: " <<
dim);
6287 MFEM_ASSERT(0 <=
dim &&
dim <=
Dim,
"invalid dim: " <<
dim);
6306 mfem_error(
"Mesh::GetElementEdges(...) element to edge table " 6307 "is not generated.");
6310 const int *v =
elements[i]->GetVertices();
6311 const int ne =
elements[i]->GetNEdges();
6313 for (
int j = 0; j < ne; j++)
6315 const int *e =
elements[i]->GetEdgeVertices(j);
6316 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
6327 const int *v =
boundary[i]->GetVertices();
6328 cor[0] = (v[0] < v[1]) ? (1) : (-1);
6341 const int *v =
boundary[i]->GetVertices();
6342 const int ne =
boundary[i]->GetNEdges();
6344 for (
int j = 0; j < ne; j++)
6346 const int *e =
boundary[i]->GetEdgeVertices(j);
6347 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
6359 const int *v =
faces[i]->GetVertices();
6360 o[0] = (v[0] < v[1]) ? (1) : (-1);
6372 const int *v =
faces[i]->GetVertices();
6373 const int ne =
faces[i]->GetNEdges();
6375 for (
int j = 0; j < ne; j++)
6377 const int *e =
faces[i]->GetEdgeVertices(j);
6378 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
6406 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
6457 for (j = 0; j < nv; j++)
6469 for (j = 0; j < nv; j++)
6516 MFEM_VERIFY(
el_to_face != NULL,
"el_to_face not generated");
6520 int n = el_faces.
Size();
6523 for (
int j = 0; j < n; j++)
6527 ori[j] =
faces_info[el_faces[j]].Elem1Inf % 64;
6531 MFEM_ASSERT(
faces_info[el_faces[j]].Elem2No == i,
"internal error");
6532 ori[j] =
faces_info[el_faces[j]].Elem2Inf % 64;
6549 for (
auto f : elem_faces)
6584 MFEM_ABORT(
"invalid geometry");
6592 case 1:
return boundary[i]->GetVertices()[0];