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);
86 return pow(fabs(J.
Weight()), 1./Dim);
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 GetBdrElementAdjacentElement2(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++)
878 face_geom_factors.Append(gf);
882 void Mesh::DeleteGeometricFactors()
884 for (
int i = 0; i < geom_factors.Size(); i++)
886 delete geom_factors[i];
888 geom_factors.SetSize(0);
889 for (
int i = 0; i < face_geom_factors.Size(); i++)
891 delete face_geom_factors[i];
893 face_geom_factors.SetSize(0);
896 void Mesh::GetLocalFaceTransformation(
902 GetLocalPtToSegTransformation(Transf, info);
905 case Element::SEGMENT:
906 if (elem_type == Element::TRIANGLE)
908 GetLocalSegToTriTransformation(Transf, info);
912 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
913 GetLocalSegToQuadTransformation(Transf, info);
917 case Element::TRIANGLE:
918 if (elem_type == Element::TETRAHEDRON)
920 GetLocalTriToTetTransformation(Transf, info);
922 else if (elem_type == Element::WEDGE)
924 GetLocalTriToWdgTransformation(Transf, info);
926 else if (elem_type == Element::PYRAMID)
928 GetLocalTriToPyrTransformation(Transf, info);
932 MFEM_ABORT(
"Mesh::GetLocalFaceTransformation not defined for "
933 "face type " << face_type
934 <<
" and element type " << elem_type <<
"\n");
938 case Element::QUADRILATERAL:
939 if (elem_type == Element::HEXAHEDRON)
941 GetLocalQuadToHexTransformation(Transf, info);
943 else if (elem_type == Element::WEDGE)
945 GetLocalQuadToWdgTransformation(Transf, info);
947 else if (elem_type == Element::PYRAMID)
949 GetLocalQuadToPyrTransformation(Transf, info);
953 MFEM_ABORT(
"Mesh::GetLocalFaceTransformation not defined for "
954 "face type " << face_type
955 <<
" and element type " << elem_type <<
"\n");
964 FaceInfo &face_info = faces_info[FaceNo];
967 FaceElemTr.SetConfigurationMask(cmask);
968 FaceElemTr.Elem1 = NULL;
969 FaceElemTr.Elem2 = NULL;
973 if (mask & FaceElementTransformations::HAVE_ELEM1)
975 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
976 FaceElemTr.Elem1 = &Transformation;
983 FaceElemTr.Elem2No = face_info.
Elem2No;
984 if ((mask & FaceElementTransformations::HAVE_ELEM2) &&
985 FaceElemTr.Elem2No >= 0)
988 if (NURBSext && (mask & FaceElementTransformations::HAVE_ELEM1))
989 { MFEM_ABORT(
"NURBS mesh not supported!"); }
991 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
992 FaceElemTr.Elem2 = &Transformation2;
997 if (mask & FaceElementTransformations::HAVE_FACE)
999 GetFaceTransformation(FaceNo, &FaceElemTr);
1004 FaceElemTr.SetGeometryType(GetFaceGeometryType(FaceNo));
1008 int face_type = GetFaceElementType(FaceNo);
1009 if (mask & FaceElementTransformations::HAVE_LOC1)
1011 int elem_type = GetElementType(face_info.
Elem1No);
1012 GetLocalFaceTransformation(face_type, elem_type,
1013 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
1016 if ((mask & FaceElementTransformations::HAVE_LOC2) &&
1017 FaceElemTr.Elem2No >= 0)
1019 int elem_type = GetElementType(face_info.
Elem2No);
1020 GetLocalFaceTransformation(face_type, elem_type,
1021 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
1024 if (Nonconforming() && IsSlaveFace(face_info))
1026 ApplyLocalSlaveTransformation(FaceElemTr, face_info,
false);
1031 FaceElemTr.SetConfigurationMask(cmask);
1037 double dist = FaceElemTr.CheckConsistency();
1040 mfem::out <<
"\nInternal error: face id = " << FaceNo
1041 <<
", dist = " << dist <<
'\n';
1042 FaceElemTr.CheckConsistency(1);
1043 MFEM_ABORT(
"internal error");
1053 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
1059 #ifdef MFEM_THREAD_SAFE
1064 MFEM_ASSERT(fi.
NCFace >= 0,
"");
1065 MFEM_ASSERT(nc_faces_info[fi.
NCFace].Slave,
"internal error");
1076 std::swap(composition(0,0), composition(0,1));
1077 std::swap(composition(1,0), composition(1,1));
1098 int fn = GetBdrFace(BdrElemNo);
1101 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
1105 tr = GetFaceElementTransformations(fn, 21);
1106 tr->
Attribute = boundary[BdrElemNo]->GetAttribute();
1108 tr->
ElementType = ElementTransformation::BDR_FACE;
1113 int Mesh::GetBdrFace(
int BdrElemNo)
const
1118 fn = be_to_face[BdrElemNo];
1122 fn = be_to_edge[BdrElemNo];
1126 fn = boundary[BdrElemNo]->GetVertices()[0];
1137 GetFaceElements(f, &e1, &e2);
1138 GetFaceInfos(f, &inf1, &inf2, &ncface);
1148 if (f < GetNumFaces())
1154 face.
tag = FaceInfoTag::LocalConforming;
1155 face.
topology = FaceTopology::Conforming;
1164 face.
tag = FaceInfoTag::LocalSlaveNonconforming;
1165 face.
topology = FaceTopology::Nonconforming;
1170 MFEM_ASSERT(inf2%64==0,
"unexpected slave face orientation.");
1181 face.
tag = FaceInfoTag::Boundary;
1182 face.
topology = FaceTopology::Boundary;
1191 face.
tag = FaceInfoTag::SharedConforming;
1192 face.
topology = FaceTopology::Conforming;
1204 face.
tag = FaceInfoTag::MasterNonconforming;
1205 face.
topology = FaceTopology::Nonconforming;
1214 face.
tag = FaceInfoTag::SharedSlaveNonconforming;
1215 face.
topology = FaceTopology::Nonconforming;
1230 face.
tag = FaceInfoTag::GhostMaster;
1240 face.
tag = FaceInfoTag::GhostSlave;
1241 face.
topology = FaceTopology::Nonconforming;
1258 case FaceInfoTag::LocalConforming:
1259 res.
Elem1No = element[0].index;
1260 res.Elem2No = element[1].index;
1261 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1262 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1263 res.NCFace = ncface;
1265 case FaceInfoTag::LocalSlaveNonconforming:
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::Boundary:
1273 res.Elem1No = element[0].index;
1274 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1276 case FaceInfoTag::SharedConforming:
1277 res.Elem1No = element[0].index;
1278 res.Elem2No = -1 - element[1].index;
1279 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1280 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1282 case FaceInfoTag::MasterNonconforming:
1283 res.Elem1No = element[0].index;
1284 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1286 case FaceInfoTag::SharedSlaveNonconforming:
1287 res.Elem1No = element[0].index;
1288 res.Elem2No = -1 - element[1].index;
1289 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1290 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1292 case FaceInfoTag::GhostMaster:
1294 case FaceInfoTag::GhostSlave:
1295 res.Elem1No = element[0].index;
1296 res.Elem2No = -1 - element[1].index;
1297 res.Elem1Inf = element[0].orientation + element[0].local_face_id*64;
1298 res.Elem2Inf = element[1].orientation + element[1].local_face_id*64;
1306 os <<
"face topology=";
1309 case Mesh::FaceTopology::Boundary:
1312 case Mesh::FaceTopology::Conforming:
1315 case Mesh::FaceTopology::Nonconforming:
1316 os <<
"Non-conforming";
1318 case Mesh::FaceTopology::NA:
1322 os <<
"element[0].location=";
1325 case Mesh::ElementLocation::Local:
1328 case Mesh::ElementLocation::FaceNbr:
1331 case Mesh::ElementLocation::NA:
1336 os <<
"element[1].location=";
1339 case Mesh::ElementLocation::Local:
1342 case Mesh::ElementLocation::FaceNbr:
1345 case Mesh::ElementLocation::NA:
1350 os <<
"element[0].conformity=";
1353 case Mesh::ElementConformity::Coincident:
1356 case Mesh::ElementConformity::Superset:
1359 case Mesh::ElementConformity::Subset:
1362 case Mesh::ElementConformity::NA:
1367 os <<
"element[1].conformity=";
1370 case Mesh::ElementConformity::Coincident:
1373 case Mesh::ElementConformity::Superset:
1376 case Mesh::ElementConformity::Subset:
1379 case Mesh::ElementConformity::NA:
1384 os <<
"element[0].index=" << info.
element[0].
index << std::endl
1385 <<
"element[1].index=" << info.
element[1].
index << std::endl
1390 <<
"ncface=" << info.
ncface << std::endl;
1394 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
const
1396 *Elem1 = faces_info[Face].Elem1No;
1397 *Elem2 = faces_info[Face].Elem2No;
1400 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
const
1402 *Inf1 = faces_info[Face].Elem1Inf;
1403 *Inf2 = faces_info[Face].Elem2Inf;
1406 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2,
int *NCFace)
const
1408 *Inf1 = faces_info[Face].Elem1Inf;
1409 *Inf2 = faces_info[Face].Elem2Inf;
1410 *NCFace = faces_info[Face].NCFace;
1417 case 1:
return Geometry::POINT;
1418 case 2:
return Geometry::SEGMENT;
1420 if (Face < NumOfFaces)
1422 return faces[Face]->GetGeometryType();
1425 const int nc_face_id = faces_info[Face].NCFace;
1426 MFEM_ASSERT(nc_face_id >= 0,
"parent ghost faces are not supported");
1427 return faces[nc_faces_info[nc_face_id].MasterFace]->GetGeometryType();
1429 return Geometry::INVALID;
1434 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
1441 for (
int i = 0; i < NumOfBdrElements; i++)
1443 face_to_be[GetBdrElementEdgeIndex(i)] = i;
1453 NumOfElements = NumOfBdrElements = 0;
1454 NumOfEdges = NumOfFaces = 0;
1455 nbInteriorFaces = -1;
1456 nbBoundaryFaces = -1;
1457 meshgen = mesh_geoms = 0;
1463 last_operation = Mesh::NONE;
1466 void Mesh::InitTables()
1469 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
1472 void Mesh::SetEmpty()
1478 void Mesh::DestroyTables()
1483 DeleteGeometricFactors();
1494 void Mesh::DestroyPointers()
1496 if (own_nodes) {
delete Nodes; }
1502 for (
int i = 0; i < NumOfElements; i++)
1504 FreeElement(elements[i]);
1507 for (
int i = 0; i < NumOfBdrElements; i++)
1509 FreeElement(boundary[i]);
1512 for (
int i = 0; i < faces.Size(); i++)
1514 FreeElement(faces[i]);
1520 void Mesh::Destroy()
1524 elements.DeleteAll();
1525 vertices.DeleteAll();
1526 boundary.DeleteAll();
1528 faces_info.DeleteAll();
1529 nc_faces_info.DeleteAll();
1530 be_to_edge.DeleteAll();
1531 be_to_face.DeleteAll();
1539 CoarseFineTr.Clear();
1541 #ifdef MFEM_USE_MEMALLOC
1545 attributes.DeleteAll();
1546 bdr_attributes.DeleteAll();
1549 void Mesh::ResetLazyData()
1551 delete el_to_el; el_to_el = NULL;
1552 delete face_edge; face_edge = NULL;
1553 delete edge_vertex; edge_vertex = NULL;
1554 DeleteGeometricFactors();
1555 nbInteriorFaces = -1;
1556 nbBoundaryFaces = -1;
1559 void Mesh::SetAttributes()
1564 for (
int i = 0; i < attribs.
Size(); i++)
1566 attribs[i] = GetBdrAttribute(i);
1570 attribs.
Copy(bdr_attributes);
1571 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
1573 MFEM_WARNING(
"Non-positive attributes on the boundary!");
1577 for (
int i = 0; i < attribs.
Size(); i++)
1579 attribs[i] = GetAttribute(i);
1583 attribs.
Copy(attributes);
1584 if (attributes.Size() > 0 && attributes[0] <= 0)
1586 MFEM_WARNING(
"Non-positive attributes in the domain!");
1590 void Mesh::InitMesh(
int Dim_,
int spaceDim_,
int NVert,
int NElem,
int NBdrElem)
1595 spaceDim = spaceDim_;
1598 vertices.SetSize(NVert);
1601 elements.SetSize(NElem);
1603 NumOfBdrElements = 0;
1604 boundary.SetSize(NBdrElem);
1607 template<
typename T>
1608 static void CheckEnlarge(
Array<T> &array,
int size)
1610 if (size >= array.
Size()) { array.
SetSize(size + 1); }
1613 int Mesh::AddVertex(
double x,
double y,
double z)
1615 CheckEnlarge(vertices, NumOfVertices);
1616 double *v = vertices[NumOfVertices]();
1620 return NumOfVertices++;
1623 int Mesh::AddVertex(
const double *coords)
1625 CheckEnlarge(vertices, NumOfVertices);
1626 vertices[NumOfVertices].SetCoords(spaceDim, coords);
1627 return NumOfVertices++;
1630 void Mesh::AddVertexParents(
int i,
int p1,
int p2)
1636 if (i < vertices.Size())
1638 double *vi = vertices[i](), *vp1 = vertices[p1](), *vp2 = vertices[p2]();
1639 for (
int j = 0; j < 3; j++)
1641 vi[j] = (vp1[j] + vp2[j]) * 0.5;
1646 int Mesh::AddSegment(
int v1,
int v2,
int attr)
1648 CheckEnlarge(elements, NumOfElements);
1649 elements[NumOfElements] =
new Segment(v1, v2, attr);
1650 return NumOfElements++;
1653 int Mesh::AddSegment(
const int *vi,
int attr)
1655 CheckEnlarge(elements, NumOfElements);
1656 elements[NumOfElements] =
new Segment(vi, attr);
1657 return NumOfElements++;
1660 int Mesh::AddTriangle(
int v1,
int v2,
int v3,
int attr)
1662 CheckEnlarge(elements, NumOfElements);
1663 elements[NumOfElements] =
new Triangle(v1, v2, v3, attr);
1664 return NumOfElements++;
1667 int Mesh::AddTriangle(
const int *vi,
int attr)
1669 CheckEnlarge(elements, NumOfElements);
1670 elements[NumOfElements] =
new Triangle(vi, attr);
1671 return NumOfElements++;
1674 int Mesh::AddQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1676 CheckEnlarge(elements, NumOfElements);
1677 elements[NumOfElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1678 return NumOfElements++;
1681 int Mesh::AddQuad(
const int *vi,
int attr)
1683 CheckEnlarge(elements, NumOfElements);
1685 return NumOfElements++;
1688 int Mesh::AddTet(
int v1,
int v2,
int v3,
int v4,
int attr)
1690 int vi[4] = {v1, v2, v3, v4};
1691 return AddTet(vi, attr);
1694 int Mesh::AddTet(
const int *vi,
int attr)
1696 CheckEnlarge(elements, NumOfElements);
1697 #ifdef MFEM_USE_MEMALLOC
1699 tet = TetMemory.Alloc();
1702 elements[NumOfElements] = tet;
1704 elements[NumOfElements] =
new Tetrahedron(vi, attr);
1706 return NumOfElements++;
1709 int Mesh::AddWedge(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int attr)
1711 CheckEnlarge(elements, NumOfElements);
1712 elements[NumOfElements] =
new Wedge(v1, v2, v3, v4, v5, v6, attr);
1713 return NumOfElements++;
1716 int Mesh::AddWedge(
const int *vi,
int attr)
1718 CheckEnlarge(elements, NumOfElements);
1719 elements[NumOfElements] =
new Wedge(vi, attr);
1720 return NumOfElements++;
1723 int Mesh::AddPyramid(
int v1,
int v2,
int v3,
int v4,
int v5,
int attr)
1725 CheckEnlarge(elements, NumOfElements);
1726 elements[NumOfElements] =
new Pyramid(v1, v2, v3, v4, v5, attr);
1727 return NumOfElements++;
1730 int Mesh::AddPyramid(
const int *vi,
int attr)
1732 CheckEnlarge(elements, NumOfElements);
1733 elements[NumOfElements] =
new Pyramid(vi, attr);
1734 return NumOfElements++;
1737 int Mesh::AddHex(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int v7,
int v8,
1740 CheckEnlarge(elements, NumOfElements);
1741 elements[NumOfElements] =
1742 new Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8, attr);
1743 return NumOfElements++;
1746 int Mesh::AddHex(
const int *vi,
int attr)
1748 CheckEnlarge(elements, NumOfElements);
1749 elements[NumOfElements] =
new Hexahedron(vi, attr);
1750 return NumOfElements++;
1753 void Mesh::AddHexAsTets(
const int *vi,
int attr)
1755 static const int hex_to_tet[6][4] =
1757 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
1758 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
1762 for (
int i = 0; i < 6; i++)
1764 for (
int j = 0; j < 4; j++)
1766 ti[j] = vi[hex_to_tet[i][j]];
1772 void Mesh::AddHexAsWedges(
const int *vi,
int attr)
1774 static const int hex_to_wdg[2][6] =
1776 { 0, 1, 2, 4, 5, 6 }, { 0, 2, 3, 4, 6, 7 }
1780 for (
int i = 0; i < 2; i++)
1782 for (
int j = 0; j < 6; j++)
1784 ti[j] = vi[hex_to_wdg[i][j]];
1790 void Mesh::AddHexAsPyramids(
const int *vi,
int attr)
1792 static const int hex_to_pyr[6][5] =
1794 { 0, 1, 2, 3, 8 }, { 0, 4, 5, 1, 8 }, { 1, 5, 6, 2, 8 },
1795 { 2, 6, 7, 3, 8 }, { 3, 7, 4, 0, 8 }, { 7, 6, 5, 4, 8 }
1799 for (
int i = 0; i < 6; i++)
1801 for (
int j = 0; j < 5; j++)
1803 ti[j] = vi[hex_to_pyr[i][j]];
1805 AddPyramid(ti, attr);
1811 CheckEnlarge(elements, NumOfElements);
1812 elements[NumOfElements] = elem;
1813 return NumOfElements++;
1818 CheckEnlarge(boundary, NumOfBdrElements);
1819 boundary[NumOfBdrElements] = elem;
1820 return NumOfBdrElements++;
1823 int Mesh::AddBdrSegment(
int v1,
int v2,
int attr)
1825 CheckEnlarge(boundary, NumOfBdrElements);
1826 boundary[NumOfBdrElements] =
new Segment(v1, v2, attr);
1827 return NumOfBdrElements++;
1830 int Mesh::AddBdrSegment(
const int *vi,
int attr)
1832 CheckEnlarge(boundary, NumOfBdrElements);
1833 boundary[NumOfBdrElements] =
new Segment(vi, attr);
1834 return NumOfBdrElements++;
1837 int Mesh::AddBdrTriangle(
int v1,
int v2,
int v3,
int attr)
1839 CheckEnlarge(boundary, NumOfBdrElements);
1840 boundary[NumOfBdrElements] =
new Triangle(v1, v2, v3, attr);
1841 return NumOfBdrElements++;
1844 int Mesh::AddBdrTriangle(
const int *vi,
int attr)
1846 CheckEnlarge(boundary, NumOfBdrElements);
1847 boundary[NumOfBdrElements] =
new Triangle(vi, attr);
1848 return NumOfBdrElements++;
1851 int Mesh::AddBdrQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1853 CheckEnlarge(boundary, NumOfBdrElements);
1854 boundary[NumOfBdrElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1855 return NumOfBdrElements++;
1858 int Mesh::AddBdrQuad(
const int *vi,
int attr)
1860 CheckEnlarge(boundary, NumOfBdrElements);
1862 return NumOfBdrElements++;
1865 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1867 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1870 for (
int i = 0; i < 2; i++)
1872 for (
int j = 0; j < 3; j++)
1874 ti[j] = vi[quad_to_tri[i][j]];
1876 AddBdrTriangle(ti, attr);
1880 int Mesh::AddBdrPoint(
int v,
int attr)
1882 CheckEnlarge(boundary, NumOfBdrElements);
1883 boundary[NumOfBdrElements] =
new Point(&v, attr);
1884 return NumOfBdrElements++;
1887 void Mesh::GenerateBoundaryElements()
1890 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1894 for (i = 0; i < boundary.Size(); i++)
1896 FreeElement(boundary[i]);
1906 NumOfBdrElements = 0;
1907 for (i = 0; i < faces_info.Size(); i++)
1909 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1912 boundary.SetSize(NumOfBdrElements);
1913 be2face.
SetSize(NumOfBdrElements);
1914 for (j = i = 0; i < faces_info.Size(); i++)
1916 if (faces_info[i].Elem2No < 0)
1918 boundary[j] = faces[i]->Duplicate(
this);
1925 void Mesh::FinalizeCheck()
1927 MFEM_VERIFY(vertices.Size() == NumOfVertices ||
1928 vertices.Size() == 0,
1929 "incorrect number of vertices: preallocated: " << vertices.Size()
1930 <<
", actually added: " << NumOfVertices);
1931 MFEM_VERIFY(elements.Size() == NumOfElements,
1932 "incorrect number of elements: preallocated: " << elements.Size()
1933 <<
", actually added: " << NumOfElements);
1934 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1935 "incorrect number of boundary elements: preallocated: "
1936 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1939 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1942 CheckElementOrientation(fix_orientation);
1946 MarkTriMeshForRefinement();
1951 el_to_edge =
new Table;
1952 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1954 CheckBdrElementOrientation();
1968 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1969 bool fix_orientation)
1972 if (fix_orientation)
1974 CheckElementOrientation(fix_orientation);
1979 el_to_edge =
new Table;
1980 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1982 CheckBdrElementOrientation();
2002 GeckoProgress(
double limit) : limit(limit) { sw.Start(); }
2003 virtual bool quit()
const {
return limit > 0 && sw.UserTime() > limit; }
2006 class GeckoVerboseProgress :
public GeckoProgress
2012 GeckoVerboseProgress(
double limit) : GeckoProgress(limit) {}
2014 virtual void beginorder(
const Graph* graph,
Float cost)
const
2015 {
mfem::out <<
"Begin Gecko ordering, cost = " << cost << std::endl; }
2016 virtual void endorder(
const Graph* graph,
Float cost)
const
2017 {
mfem::out <<
"End ordering, cost = " << cost << std::endl; }
2019 virtual void beginiter(
const Graph* graph,
2022 mfem::out <<
"Iteration " << iter <<
"/" << maxiter <<
", window "
2023 << window << std::flush;
2025 virtual void enditer(
const Graph* graph,
Float mincost,
Float cost)
const
2026 {
mfem::out <<
", cost = " << cost << endl; }
2031 int iterations,
int window,
2032 int period,
int seed,
bool verbose,
2038 GeckoProgress progress(time_limit);
2039 GeckoVerboseProgress vprogress(time_limit);
2042 for (
int elemid = 0; elemid < GetNE(); ++elemid)
2049 const Table &my_el_to_el = ElementToElementTable();
2050 for (
int elemid = 0; elemid < GetNE(); ++elemid)
2052 const int *neighid = my_el_to_el.
GetRow(elemid);
2053 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
2055 graph.
insert_arc(elemid + 1, neighid[i] + 1);
2060 graph.
order(&functional, iterations, window, period, seed,
2061 verbose ? &vprogress : &progress);
2067 ordering[gnodeid - 1] = graph.
rank(gnodeid);
2070 return graph.
cost();
2081 HilbertCmp(
int coord,
bool dir,
const Array<double> &points,
double mid)
2082 : coord(coord), dir(dir), points(points), mid(mid) {}
2084 bool operator()(
int i)
const
2086 return (points[3*i + coord] < mid) != dir;
2090 static void HilbertSort2D(
int coord1,
2093 const Array<double> &points,
int *beg,
int *end,
2094 double xmin,
double ymin,
double xmax,
double ymax)
2096 if (end - beg <= 1) {
return; }
2098 double xmid = (xmin + xmax)*0.5;
2099 double ymid = (ymin + ymax)*0.5;
2101 int coord2 = (coord1 + 1) % 2;
2104 int *p0 = beg, *p4 = end;
2105 int *p2 = std::partition(p0, p4, HilbertCmp(coord1, dir1, points, xmid));
2106 int *p1 = std::partition(p0, p2, HilbertCmp(coord2, dir2, points, ymid));
2107 int *p3 = std::partition(p2, p4, HilbertCmp(coord2, !dir2, points, ymid));
2111 HilbertSort2D(coord2, dir2, dir1, points, p0, p1,
2112 ymin, xmin, ymid, xmid);
2114 if (p1 != p0 || p2 != p4)
2116 HilbertSort2D(coord1, dir1, dir2, points, p1, p2,
2117 xmin, ymid, xmid, ymax);
2119 if (p2 != p0 || p3 != p4)
2121 HilbertSort2D(coord1, dir1, dir2, points, p2, p3,
2122 xmid, ymid, xmax, ymax);
2126 HilbertSort2D(coord2, !dir2, !dir1, points, p3, p4,
2127 ymid, xmax, ymin, xmid);
2131 static void HilbertSort3D(
int coord1,
bool dir1,
bool dir2,
bool dir3,
2132 const Array<double> &points,
int *beg,
int *end,
2133 double xmin,
double ymin,
double zmin,
2134 double xmax,
double ymax,
double zmax)
2136 if (end - beg <= 1) {
return; }
2138 double xmid = (xmin + xmax)*0.5;
2139 double ymid = (ymin + ymax)*0.5;
2140 double zmid = (zmin + zmax)*0.5;
2142 int coord2 = (coord1 + 1) % 3;
2143 int coord3 = (coord1 + 2) % 3;
2146 int *p0 = beg, *p8 = end;
2147 int *p4 = std::partition(p0, p8, HilbertCmp(coord1, dir1, points, xmid));
2148 int *p2 = std::partition(p0, p4, HilbertCmp(coord2, dir2, points, ymid));
2149 int *p6 = std::partition(p4, p8, HilbertCmp(coord2, !dir2, points, ymid));
2150 int *p1 = std::partition(p0, p2, HilbertCmp(coord3, dir3, points, zmid));
2151 int *p3 = std::partition(p2, p4, HilbertCmp(coord3, !dir3, points, zmid));
2152 int *p5 = std::partition(p4, p6, HilbertCmp(coord3, dir3, points, zmid));
2153 int *p7 = std::partition(p6, p8, HilbertCmp(coord3, !dir3, points, zmid));
2157 HilbertSort3D(coord3, dir3, dir1, dir2, points, p0, p1,
2158 zmin, xmin, ymin, zmid, xmid, ymid);
2160 if (p1 != p0 || p2 != p8)
2162 HilbertSort3D(coord2, dir2, dir3, dir1, points, p1, p2,
2163 ymin, zmid, xmin, ymid, zmax, xmid);
2165 if (p2 != p0 || p3 != p8)
2167 HilbertSort3D(coord2, dir2, dir3, dir1, points, p2, p3,
2168 ymid, zmid, xmin, ymax, zmax, xmid);
2170 if (p3 != p0 || p4 != p8)
2172 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p3, p4,
2173 xmin, ymax, zmid, xmid, ymid, zmin);
2175 if (p4 != p0 || p5 != p8)
2177 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p4, p5,
2178 xmid, ymax, zmid, xmax, ymid, zmin);
2180 if (p5 != p0 || p6 != p8)
2182 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p5, p6,
2183 ymax, zmid, xmax, ymid, zmax, xmid);
2185 if (p6 != p0 || p7 != p8)
2187 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p6, p7,
2188 ymid, zmid, xmax, ymin, zmax, xmid);
2192 HilbertSort3D(coord3, !dir3, !dir1, dir2, points, p7, p8,
2193 zmid, xmax, ymin, zmin, xmid, ymid);
2199 MFEM_VERIFY(spaceDim <= 3,
"");
2202 GetBoundingBox(min, max);
2207 if (spaceDim < 3) { points = 0.0; }
2210 for (
int i = 0; i < GetNE(); i++)
2212 GetElementCenter(i, center);
2213 for (
int j = 0; j < spaceDim; j++)
2215 points[3*i + j] = center(j);
2222 indices.
Sort([&](
int a,
int b)
2223 {
return points[3*
a] < points[3*
b]; });
2225 else if (spaceDim == 2)
2228 HilbertSort2D(0,
false,
false,
2229 points, indices.
begin(), indices.
end(),
2230 min(0), min(1), max(0), max(1));
2235 HilbertSort3D(0,
false,
false,
false,
2236 points, indices.
begin(), indices.
end(),
2237 min(0), min(1), min(2), max(0), max(1), max(2));
2242 for (
int i = 0; i < GetNE(); i++)
2244 ordering[indices[i]] = i;
2249 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
2253 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
2258 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
2262 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
2292 old_elem_node_vals.SetSize(GetNE());
2293 nodes_fes = Nodes->FESpace();
2296 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2298 nodes_fes->GetElementVDofs(old_elid, old_dofs);
2300 old_elem_node_vals[old_elid] =
new Vector(vals);
2306 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
2308 int new_elid = ordering[old_elid];
2309 new_elements[new_elid] = elements[old_elid];
2314 if (reorder_vertices)
2319 vertex_ordering = -1;
2321 int new_vertex_ind = 0;
2322 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
2324 int *elem_vert = elements[new_elid]->GetVertices();
2325 int nv = elements[new_elid]->GetNVertices();
2326 for (
int vi = 0; vi < nv; ++vi)
2328 int old_vertex_ind = elem_vert[vi];
2329 if (vertex_ordering[old_vertex_ind] == -1)
2331 vertex_ordering[old_vertex_ind] = new_vertex_ind;
2332 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
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 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
2353 for (
int belid = 0; belid < GetNBE(); ++belid)
2355 int *be_vert = boundary[belid]->GetVertices();
2356 int nv = boundary[belid]->GetNVertices();
2357 for (
int vi = 0; vi < nv; ++vi)
2359 be_vert[vi] = vertex_ordering[be_vert[vi]];
2370 el_to_edge =
new Table;
2371 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2376 GetElementToFaceTable();
2386 last_operation = Mesh::NONE;
2387 nodes_fes->Update(
false);
2390 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2392 int new_elid = ordering[old_elid];
2393 nodes_fes->GetElementVDofs(new_elid, new_dofs);
2394 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
2395 delete old_elem_node_vals[old_elid];
2401 void Mesh::MarkForRefinement()
2407 MarkTriMeshForRefinement();
2411 DSTable v_to_v(NumOfVertices);
2412 GetVertexToVertexTable(v_to_v);
2413 MarkTetMeshForRefinement(v_to_v);
2418 void Mesh::MarkTriMeshForRefinement()
2423 for (
int i = 0; i < NumOfElements; i++)
2425 if (elements[i]->GetType() == Element::TRIANGLE)
2427 GetPointMatrix(i, pmat);
2428 static_cast<Triangle*
>(elements[i])->MarkEdge(pmat);
2439 for (
int i = 0; i < NumOfVertices; i++)
2444 length_idx[j].one = GetLength(i, it.Column());
2445 length_idx[j].two = j;
2452 for (
int i = 0; i < NumOfEdges; i++)
2454 order[length_idx[i].two] = i;
2458 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
2463 GetEdgeOrdering(v_to_v, order);
2465 for (
int i = 0; i < NumOfElements; i++)
2467 if (elements[i]->GetType() == Element::TETRAHEDRON)
2469 elements[i]->MarkEdge(v_to_v, order);
2472 for (
int i = 0; i < NumOfBdrElements; i++)
2474 if (boundary[i]->GetType() == Element::TRIANGLE)
2476 boundary[i]->MarkEdge(v_to_v, order);
2483 if (*old_v_to_v && *old_elem_vert)
2490 if (*old_v_to_v == NULL)
2492 bool need_v_to_v =
false;
2494 for (
int i = 0; i < GetNEdges(); i++)
2500 if (dofs.
Size() > 0)
2508 *old_v_to_v =
new DSTable(NumOfVertices);
2509 GetVertexToVertexTable(*(*old_v_to_v));
2512 if (*old_elem_vert == NULL)
2514 bool need_elem_vert =
false;
2516 for (
int i = 0; i < GetNE(); i++)
2522 if (dofs.
Size() > 1)
2524 need_elem_vert =
true;
2530 *old_elem_vert =
new Table;
2531 (*old_elem_vert)->
MakeI(GetNE());
2532 for (
int i = 0; i < GetNE(); i++)
2534 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
2536 (*old_elem_vert)->MakeJ();
2537 for (
int i = 0; i < GetNE(); i++)
2539 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
2540 elements[i]->GetNVertices());
2542 (*old_elem_vert)->ShiftUpI();
2555 const int num_edge_dofs = old_dofs.
Size();
2558 const Vector onodes = *Nodes;
2562 int offset = NumOfVertices * old_dofs.
Size();
2566 if (num_edge_dofs > 0)
2568 DSTable new_v_to_v(NumOfVertices);
2569 GetVertexToVertexTable(new_v_to_v);
2571 for (
int i = 0; i < NumOfVertices; i++)
2575 const int old_i = (*old_v_to_v)(i, it.Column());
2576 const int new_i = it.Index();
2577 if (new_i == old_i) {
continue; }
2579 old_dofs.
SetSize(num_edge_dofs);
2580 new_dofs.
SetSize(num_edge_dofs);
2581 for (
int j = 0; j < num_edge_dofs; j++)
2583 old_dofs[j] = offset + old_i * num_edge_dofs + j;
2584 new_dofs[j] = offset + new_i * num_edge_dofs + j;
2588 for (
int j = 0; j < old_dofs.
Size(); j++)
2590 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2594 offset += NumOfEdges * num_edge_dofs;
2602 Table old_face_vertex;
2603 old_face_vertex.
MakeI(NumOfFaces);
2604 for (
int i = 0; i < NumOfFaces; i++)
2608 old_face_vertex.
MakeJ();
2609 for (
int i = 0; i < NumOfFaces; i++)
2611 faces[i]->GetNVertices());
2615 STable3D *faces_tbl = GetElementToFaceTable(1);
2621 for (
int i = 0; i < NumOfFaces; i++)
2623 const int *old_v = old_face_vertex.
GetRow(i);
2625 switch (old_face_vertex.
RowSize(i))
2628 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2632 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2636 new_fdofs[new_i+1] = old_dofs.
Size();
2641 for (
int i = 0; i < NumOfFaces; i++)
2643 const int *old_v = old_face_vertex.
GetRow(i), *new_v;
2646 switch (old_face_vertex.
RowSize(i))
2649 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2650 new_v = faces[new_i]->GetVertices();
2651 new_or = GetTriOrientation(old_v, new_v);
2656 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2657 new_v = faces[new_i]->GetVertices();
2658 new_or = GetQuadOrientation(old_v, new_v);
2665 for (
int j = 0; j < old_dofs.
Size(); j++)
2668 const int old_j = dof_ord[j];
2669 new_dofs[old_j] = offset + new_fdofs[new_i] + j;
2673 for (
int j = 0; j < old_dofs.
Size(); j++)
2675 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2697 for (
int i = 0; i < GetNE(); i++)
2699 const int *old_v = old_elem_vert->
GetRow(i);
2700 const int *new_v = elements[i]->GetVertices();
2706 case Geometry::SEGMENT:
2707 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
2709 case Geometry::TRIANGLE:
2710 new_or = GetTriOrientation(old_v, new_v);
2712 case Geometry::SQUARE:
2713 new_or = GetQuadOrientation(old_v, new_v);
2715 case Geometry::TETRAHEDRON:
2716 new_or = GetTetOrientation(old_v, new_v);
2720 MFEM_ABORT(Geometry::Name[geom] <<
" elements (" << fec->
Name()
2721 <<
" FE collection) are not supported yet!");
2725 MFEM_VERIFY(dof_ord != NULL,
2726 "FE collection '" << fec->
Name()
2727 <<
"' does not define reordering for "
2728 << Geometry::Name[geom] <<
" elements!");
2731 for (
int j = 0; j < new_dofs.
Size(); j++)
2734 const int old_j = dof_ord[j];
2735 new_dofs[old_j] = offset + j;
2737 offset += new_dofs.
Size();
2740 for (
int j = 0; j < old_dofs.
Size(); j++)
2742 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2754 GetElementToFaceTable();
2757 CheckBdrElementOrientation();
2762 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2767 CheckBdrElementOrientation();
2772 last_operation = Mesh::NONE;
2777 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
2780 CheckElementOrientation(fix_orientation);
2782 if (NumOfBdrElements == 0)
2784 GetElementToFaceTable();
2786 GenerateBoundaryElements();
2791 DSTable v_to_v(NumOfVertices);
2792 GetVertexToVertexTable(v_to_v);
2793 MarkTetMeshForRefinement(v_to_v);
2796 GetElementToFaceTable();
2799 CheckBdrElementOrientation();
2801 if (generate_edges == 1)
2803 el_to_edge =
new Table;
2804 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2818 void Mesh::FinalizeWedgeMesh(
int generate_edges,
int refine,
2819 bool fix_orientation)
2822 CheckElementOrientation(fix_orientation);
2824 if (NumOfBdrElements == 0)
2826 GetElementToFaceTable();
2828 GenerateBoundaryElements();
2831 GetElementToFaceTable();
2834 CheckBdrElementOrientation();
2836 if (generate_edges == 1)
2838 el_to_edge =
new Table;
2839 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2853 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
2856 CheckElementOrientation(fix_orientation);
2858 GetElementToFaceTable();
2861 if (NumOfBdrElements == 0)
2863 GenerateBoundaryElements();
2866 CheckBdrElementOrientation();
2870 el_to_edge =
new Table;
2871 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2883 void Mesh::FinalizeMesh(
int refine,
bool fix_orientation)
2887 Finalize(refine, fix_orientation);
2890 void Mesh::FinalizeTopology(
bool generate_bdr)
2902 bool generate_edges =
true;
2904 if (spaceDim == 0) { spaceDim = Dim; }
2905 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2909 if (tmp_vertex_parents.Size())
2911 MFEM_VERIFY(ncmesh == NULL,
"");
2912 ncmesh =
new NCMesh(
this);
2916 InitFromNCMesh(*ncmesh);
2917 ncmesh->OnMeshUpdated(
this);
2918 GenerateNCFaceInfo();
2922 tmp_vertex_parents.DeleteAll();
2932 GetElementToFaceTable();
2934 if (NumOfBdrElements == 0 && generate_bdr)
2936 GenerateBoundaryElements();
2937 GetElementToFaceTable();
2946 if (Dim > 1 && generate_edges)
2949 if (!el_to_edge) { el_to_edge =
new Table; }
2950 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2954 if (NumOfBdrElements == 0 && generate_bdr)
2956 GenerateBoundaryElements();
2973 ncmesh->OnMeshUpdated(
this);
2976 GenerateNCFaceInfo();
2983 void Mesh::Finalize(
bool refine,
bool fix_orientation)
2985 if (NURBSext || ncmesh)
2987 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
2988 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
2997 const bool check_orientation =
true;
2998 const bool curved = (Nodes != NULL);
2999 const bool may_change_topology =
3000 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
3001 ( check_orientation && fix_orientation &&
3002 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
3005 Table *old_elem_vert = NULL;
3007 if (curved && may_change_topology)
3009 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
3012 if (check_orientation)
3015 CheckElementOrientation(fix_orientation);
3019 MarkForRefinement();
3022 if (may_change_topology)
3026 DoNodeReorder(old_v_to_v, old_elem_vert);
3027 delete old_elem_vert;
3040 CheckBdrElementOrientation();
3045 if (Dim >= 2 && Dim == spaceDim)
3047 const int num_faces = GetNumFaces();
3048 for (
int i = 0; i < num_faces; i++)
3050 MFEM_VERIFY(faces_info[i].Elem2No < 0 ||
3051 faces_info[i].Elem2Inf%2 != 0,
"Invalid mesh topology."
3052 " Interior face with incompatible orientations.");
3059 double sx,
double sy,
double sz,
bool sfc_ordering)
3063 int NVert, NElem, NBdrElem;
3065 NVert = (nx+1) * (ny+1) * (nz+1);
3066 NElem = nx * ny * nz;
3067 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
3068 if (type == Element::TETRAHEDRON)
3073 else if (type == Element::WEDGE)
3076 NBdrElem += 2*nx*ny;
3078 else if (type == Element::PYRAMID)
3081 NVert += nx * ny * nz;
3084 InitMesh(3, 3, NVert, NElem, NBdrElem);
3090 for (z = 0; z <= nz; z++)
3092 coord[2] = ((double) z / nz) * sz;
3093 for (y = 0; y <= ny; y++)
3095 coord[1] = ((double) y / ny) * sy;
3096 for (x = 0; x <= nx; x++)
3098 coord[0] = ((double) x / nx) * sx;
3103 if (type == Element::PYRAMID)
3105 for (z = 0; z < nz; z++)
3107 coord[2] = (((double) z + 0.5) / nz) * sz;
3108 for (y = 0; y < ny; y++)
3110 coord[1] = (((double) y + 0.5 ) / ny) * sy;
3111 for (x = 0; x < nx; x++)
3113 coord[0] = (((double) x + 0.5 ) / nx) * sx;
3120 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
3121 #define VTXP(XC, YC, ZC) ((nx+1)*(ny+1)*(nz+1)+(XC)+((YC)+(ZC)*ny)*nx)
3124 if (sfc_ordering && type == Element::HEXAHEDRON)
3127 NCMesh::GridSfcOrdering3D(nx, ny, nz, sfc);
3128 MFEM_VERIFY(sfc.
Size() == 3*nx*ny*nz,
"");
3130 for (
int k = 0; k < nx*ny*nz; k++)
3137 ind[0] = VTX(x , y , z );
3138 ind[1] = VTX(x+1, y , z );
3139 ind[2] = VTX(x+1, y+1, z );
3140 ind[3] = VTX(x , y+1, z );
3141 ind[4] = VTX(x , y , z+1);
3142 ind[5] = VTX(x+1, y , z+1);
3143 ind[6] = VTX(x+1, y+1, z+1);
3144 ind[7] = VTX(x , y+1, z+1);
3152 for (z = 0; z < nz; z++)
3154 for (y = 0; y < ny; y++)
3156 for (x = 0; x < nx; x++)
3159 ind[0] = VTX(x , y , z );
3160 ind[1] = VTX(x+1, y , z );
3161 ind[2] = VTX(x+1, y+1, z );
3162 ind[3] = VTX(x , y+1, z );
3163 ind[4] = VTX(x , y , z+1);
3164 ind[5] = VTX(x+1, y , z+1);
3165 ind[6] = VTX(x+1, y+1, z+1);
3166 ind[7] = VTX( x, y+1, z+1);
3168 if (type == Element::TETRAHEDRON)
3170 AddHexAsTets(ind, 1);
3172 else if (type == Element::WEDGE)
3174 AddHexAsWedges(ind, 1);
3176 else if (type == Element::PYRAMID)
3178 ind[8] = VTXP(x, y, z);
3179 AddHexAsPyramids(ind, 1);
3192 for (y = 0; y < ny; y++)
3194 for (x = 0; x < nx; x++)
3197 ind[0] = VTX(x , y , 0);
3198 ind[1] = VTX(x , y+1, 0);
3199 ind[2] = VTX(x+1, y+1, 0);
3200 ind[3] = VTX(x+1, y , 0);
3202 if (type == Element::TETRAHEDRON)
3204 AddBdrQuadAsTriangles(ind, 1);
3206 else if (type == Element::WEDGE)
3208 AddBdrQuadAsTriangles(ind, 1);
3217 for (y = 0; y < ny; y++)
3219 for (x = 0; x < nx; x++)
3222 ind[0] = VTX(x , y , nz);
3223 ind[1] = VTX(x+1, y , nz);
3224 ind[2] = VTX(x+1, y+1, nz);
3225 ind[3] = VTX(x , y+1, nz);
3227 if (type == Element::TETRAHEDRON)
3229 AddBdrQuadAsTriangles(ind, 6);
3231 else if (type == Element::WEDGE)
3233 AddBdrQuadAsTriangles(ind, 6);
3242 for (z = 0; z < nz; z++)
3244 for (y = 0; y < ny; y++)
3247 ind[0] = VTX(0 , y , z );
3248 ind[1] = VTX(0 , y , z+1);
3249 ind[2] = VTX(0 , y+1, z+1);
3250 ind[3] = VTX(0 , y+1, z );
3252 if (type == Element::TETRAHEDRON)
3254 AddBdrQuadAsTriangles(ind, 5);
3263 for (z = 0; z < nz; z++)
3265 for (y = 0; y < ny; y++)
3268 ind[0] = VTX(nx, y , z );
3269 ind[1] = VTX(nx, y+1, z );
3270 ind[2] = VTX(nx, y+1, z+1);
3271 ind[3] = VTX(nx, y , z+1);
3273 if (type == Element::TETRAHEDRON)
3275 AddBdrQuadAsTriangles(ind, 3);
3284 for (x = 0; x < nx; x++)
3286 for (z = 0; z < nz; z++)
3289 ind[0] = VTX(x , 0, z );
3290 ind[1] = VTX(x+1, 0, z );
3291 ind[2] = VTX(x+1, 0, z+1);
3292 ind[3] = VTX(x , 0, z+1);
3294 if (type == Element::TETRAHEDRON)
3296 AddBdrQuadAsTriangles(ind, 2);
3305 for (x = 0; x < nx; x++)
3307 for (z = 0; z < nz; z++)
3310 ind[0] = VTX(x , ny, z );
3311 ind[1] = VTX(x , ny, z+1);
3312 ind[2] = VTX(x+1, ny, z+1);
3313 ind[3] = VTX(x+1, ny, z );
3315 if (type == Element::TETRAHEDRON)
3317 AddBdrQuadAsTriangles(ind, 4);
3329 ofstream test_stream(
"debug.mesh");
3331 test_stream.close();
3340 double sx,
double sy,
3341 bool generate_edges,
bool sfc_ordering)
3350 if (type == Element::QUADRILATERAL)
3352 NumOfVertices = (nx+1) * (ny+1);
3353 NumOfElements = nx * ny;
3354 NumOfBdrElements = 2 * nx + 2 * ny;
3356 vertices.SetSize(NumOfVertices);
3357 elements.SetSize(NumOfElements);
3358 boundary.SetSize(NumOfBdrElements);
3365 for (j = 0; j < ny+1; j++)
3367 cy = ((double) j / ny) * sy;
3368 for (i = 0; i < nx+1; i++)
3370 cx = ((double) i / nx) * sx;
3371 vertices[k](0) = cx;
3372 vertices[k](1) = cy;
3381 NCMesh::GridSfcOrdering2D(nx, ny, sfc);
3382 MFEM_VERIFY(sfc.
Size() == 2*nx*ny,
"");
3384 for (k = 0; k < nx*ny; k++)
3388 ind[0] = i + j*(nx+1);
3389 ind[1] = i + 1 +j*(nx+1);
3390 ind[2] = i + 1 + (j+1)*(nx+1);
3391 ind[3] = i + (j+1)*(nx+1);
3398 for (j = 0; j < ny; j++)
3400 for (i = 0; i < nx; i++)
3402 ind[0] = i + j*(nx+1);
3403 ind[1] = i + 1 +j*(nx+1);
3404 ind[2] = i + 1 + (j+1)*(nx+1);
3405 ind[3] = i + (j+1)*(nx+1);
3414 for (i = 0; i < nx; i++)
3416 boundary[i] =
new Segment(i, i+1, 1);
3417 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3420 for (j = 0; j < ny; j++)
3422 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3423 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3427 else if (type == Element::TRIANGLE)
3429 NumOfVertices = (nx+1) * (ny+1);
3430 NumOfElements = 2 * nx * ny;
3431 NumOfBdrElements = 2 * nx + 2 * ny;
3433 vertices.SetSize(NumOfVertices);
3434 elements.SetSize(NumOfElements);
3435 boundary.SetSize(NumOfBdrElements);
3442 for (j = 0; j < ny+1; j++)
3444 cy = ((double) j / ny) * sy;
3445 for (i = 0; i < nx+1; i++)
3447 cx = ((double) i / nx) * sx;
3448 vertices[k](0) = cx;
3449 vertices[k](1) = cy;
3456 for (j = 0; j < ny; j++)
3458 for (i = 0; i < nx; i++)
3460 ind[0] = i + j*(nx+1);
3461 ind[1] = i + 1 + (j+1)*(nx+1);
3462 ind[2] = i + (j+1)*(nx+1);
3465 ind[1] = i + 1 + j*(nx+1);
3466 ind[2] = i + 1 + (j+1)*(nx+1);
3474 for (i = 0; i < nx; i++)
3476 boundary[i] =
new Segment(i, i+1, 1);
3477 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3480 for (j = 0; j < ny; j++)
3482 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3483 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3490 MFEM_ABORT(
"Unsupported element type.");
3494 CheckElementOrientation();
3496 if (generate_edges == 1)
3498 el_to_edge =
new Table;
3499 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3501 CheckBdrElementOrientation();
3510 attributes.Append(1);
3511 bdr_attributes.Append(1); bdr_attributes.Append(2);
3512 bdr_attributes.Append(3); bdr_attributes.Append(4);
3517 void Mesh::Make1D(
int n,
double sx)
3526 NumOfVertices = n + 1;
3528 NumOfBdrElements = 2;
3529 vertices.SetSize(NumOfVertices);
3530 elements.SetSize(NumOfElements);
3531 boundary.SetSize(NumOfBdrElements);
3534 for (j = 0; j < n+1; j++)
3536 vertices[j](0) = ((
double) j / n) * sx;
3540 for (j = 0; j < n; j++)
3542 elements[j] =
new Segment(j, j+1, 1);
3547 boundary[0] =
new Point(ind, 1);
3549 boundary[1] =
new Point(ind, 2);
3557 attributes.Append(1);
3558 bdr_attributes.Append(1); bdr_attributes.Append(2);
3561 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
3579 last_operation = Mesh::NONE;
3582 elements.SetSize(NumOfElements);
3583 for (
int i = 0; i < NumOfElements; i++)
3585 elements[i] = mesh.
elements[i]->Duplicate(
this);
3592 boundary.SetSize(NumOfBdrElements);
3593 for (
int i = 0; i < NumOfBdrElements; i++)
3595 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
3614 faces.SetSize(mesh.
faces.Size());
3615 for (
int i = 0; i < faces.Size(); i++)
3618 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
3652 if (dynamic_cast<const ParMesh*>(&mesh))
3664 if (mesh.
Nodes && copy_nodes)
3669 FiniteElementCollection::New(fec->
Name());
3673 Nodes->MakeOwner(fec_copy);
3674 *Nodes = *mesh.
Nodes;
3696 bool fix_orientation)
3700 if (!imesh) { MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n'); }
3701 else { mesh.
Load(imesh, generate_edges, refine, fix_orientation); }
3715 double sx,
double sy,
bool sfc_ordering)
3718 mesh.
Make2D(nx, ny, type, sx, sy, generate_edges, sfc_ordering);
3725 double sx,
double sy,
double sz,
bool sfc_ordering)
3728 mesh.
Make3D(nx, ny, nz, type, sx, sy, sz, sfc_ordering);
3737 ref_factors = ref_factor;
3751 bool fix_orientation)
3760 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
3764 Load(imesh, generate_edges, refine, fix_orientation);
3769 bool fix_orientation)
3772 Load(input, generate_edges, refine, fix_orientation);
3781 "Not enough vertices in external array : "
3782 "len_vertex_data = "<< len_vertex_data <<
", "
3785 if (vertex_data == (
double *)(
vertices.GetData()))
3787 MFEM_ASSERT(!
vertices.OwnsData(),
"invalid ownership");
3792 memcpy(vertex_data,
vertices.GetData(),
3801 int *element_attributes,
int num_elements,
3803 int *boundary_attributes,
int num_boundary_elements,
3806 if (space_dimension == -1)
3811 InitMesh(dimension, space_dimension, 0, num_elements,
3812 num_boundary_elements);
3815 int boundary_index_stride = num_boundary_elements > 0 ?
3819 vertices.MakeRef(reinterpret_cast<Vertex*>(vertices_), num_vertices);
3822 for (
int i = 0; i < num_elements; i++)
3825 elements[i]->SetVertices(element_indices + i * element_index_stride);
3826 elements[i]->SetAttribute(element_attributes[i]);
3830 for (
int i = 0; i < num_boundary_elements; i++)
3833 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
3834 boundary[i]->SetAttribute(boundary_attributes[i]);
3850 #ifdef MFEM_USE_MEMALLOC
3859 MFEM_ABORT(
"invalid Geometry::Type, geom = " << geom);
3872 MFEM_VERIFY(el,
"Unsupported element type: " << geom);
3875 for (
int i = 0; i < nv; i++)
3888 for (
int j = 0; j < nv; j++)
3960 MFEM_ABORT(
"invalid element type: " << type);
3967 std::string parse_tag)
3969 int curved = 0, read_gf = 1;
3970 bool finalize_topo =
true;
3974 MFEM_ABORT(
"Input stream is not open");
3981 getline(input, mesh_type);
3985 int mfem_version = 0;
3986 if (mesh_type ==
"MFEM mesh v1.0") { mfem_version = 10; }
3987 else if (mesh_type ==
"MFEM mesh v1.2") { mfem_version = 12; }
3991 int mfem_nc_version = 0;
3992 if (mesh_type ==
"MFEM NC mesh v1.0") { mfem_nc_version = 10; }
3993 else if (mesh_type ==
"MFEM mesh v1.1") { mfem_nc_version = 1 ; }
4001 if (mfem_version == 12 && parse_tag.empty())
4003 parse_tag =
"mfem_mesh_end";
4007 else if (mfem_nc_version)
4009 MFEM_ASSERT(
ncmesh == NULL,
"internal error");
4016 MFEM_VERIFY(mfem_nc_version >= 10,
4017 "Legacy nonconforming format (MFEM mesh v1.1) cannot be "
4018 "used to load a parallel nonconforming mesh, sorry.");
4021 input, mfem_nc_version, curved, is_nc);
4026 ncmesh =
new NCMesh(input, mfem_nc_version, curved, is_nc);
4039 else if (mesh_type ==
"linemesh")
4043 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
4045 if (mesh_type ==
"curved_areamesh2")
4051 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
4055 else if (mesh_type ==
"TrueGrid")
4059 else if (mesh_type.rfind(
"# vtk DataFile Version") == 0)
4061 int major_vtk_version = mesh_type[mesh_type.length()-3] -
'0';
4063 MFEM_VERIFY(major_vtk_version >= 2 && major_vtk_version <= 4,
4064 "Unsupported VTK format");
4065 ReadVTKMesh(input, curved, read_gf, finalize_topo);
4067 else if (mesh_type.rfind(
"<VTKFile ") == 0 || mesh_type.rfind(
"<?xml") == 0)
4071 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
4075 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
4080 else if (mesh_type ==
"$MeshFormat")
4085 ((mesh_type.size() > 2 &&
4086 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
4087 (mesh_type.size() > 3 &&
4088 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
4093 #ifdef MFEM_USE_NETCDF
4096 MFEM_ABORT(
"NetCDF support requires configuration with"
4097 " MFEM_USE_NETCDF=YES");
4103 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
4104 " Use mfem::named_ifgzstream for input.");
4110 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
4136 bool generate_bdr =
false;
4141 if (curved && read_gf)
4155 if (mfem_version == 12)
4161 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
4162 getline(input, line);
4168 if (line ==
"mfem_mesh_end") {
break; }
4170 while (line != parse_tag);
4172 else if (mfem_nc_version >= 10)
4177 MFEM_VERIFY(ident ==
"mfem_mesh_end",
4178 "invalid mesh: end of file tag not found");
4186 int i, j, ie, ib, iv, *v, nv;
4217 for (i = 0; i < num_pieces; i++)
4224 for (i = 0; i < num_pieces; i++)
4230 for (j = 0; j < m->
GetNE(); j++)
4235 for (j = 0; j < m->
GetNBE(); j++)
4240 for (
int k = 0; k < nv; k++)
4242 v[k] = lvert_vert[v[k]];
4247 for (j = 0; j < m->
GetNV(); j++)
4259 for (i = 0; i < num_pieces; i++)
4270 for (i = 0; i < num_pieces; i++)
4274 for (j = 0; j < m->
GetNE(); j++)
4279 for (
int k = 0; k < nv; k++)
4286 for (j = 0; j < m->
GetNBE(); j++)
4291 for (
int k = 0; k < nv; k++)
4298 for (j = 0; j < m->
GetNV(); j++)
4312 for (i = 0; i < num_pieces; i++)
4314 gf_array[i] = mesh_array[i]->
GetNodes();
4329 ref_factors = ref_factor;
4340 int orig_ne = orig_mesh.
GetNE();
4341 MFEM_VERIFY(ref_factors.
Size() == orig_ne && orig_ne > 0,
4342 "Number of refinement factors must equal number of elements")
4343 MFEM_VERIFY(ref_factors.
Min() >= 1,
"Refinement factor must be >= 1");
4346 "Invalid refinement type. Must use closed basis type.");
4348 int min_ref = ref_factors.
Min();
4349 int max_ref = ref_factors.
Max();
4351 bool var_order = (min_ref != max_ref);
4364 for (
int i = 0; i < orig_ne; i++)
4382 for (
int el = 0; el < orig_ne; el++)
4394 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[el]);
4395 for (
int i = 0; i < phys_pts.
Width(); i++)
4404 for (
int k = 0; k < nvert; k++)
4407 v[k] = rdofs[c2h_map[cid]];
4420 for (
int el = 0; el < orig_mesh.
GetNBE(); el++)
4431 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[i]);
4437 for (
int k = 0; k < nvert; k++)
4440 v[k] = rdofs[c2h_map[cid]];
4462 for (
int iel = 0; iel < orig_ne; iel++)
4471 const int *node_map = NULL;
4474 if (h1_fec != NULL) { node_map = h1_fec->
GetDofMap(geom); }
4475 const int *vertex_map = vertex_fec.
GetDofMap(geom);
4476 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[iel]);
4477 for (
int jel = 0; jel < RG.
RefGeoms.
Size()/nvert; jel++)
4480 for (
int iv_lex=0; iv_lex<nvert; ++iv_lex)
4483 int iv = vertex_map[iv_lex];
4485 int pt_idx = c2h_map[RG.
RefGeoms[iv+nvert*jel]];
4487 int node_idx = node_map ? node_map[iv_lex] : iv_lex;
4490 (*Nodes)[dofs[node_idx + d*nvert]] = phys_pts(d,pt_idx);
4501 using GeomRef = std::pair<Geometry::Type, int>;
4502 std::map<GeomRef, int> point_matrices_offsets;
4504 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4508 GeomRef id(geom, ref_factors[el_coarse]);
4509 if (point_matrices_offsets.find(
id) == point_matrices_offsets.end())
4515 point_matrices_offsets[id] = n_point_matrices[geom];
4516 n_point_matrices[geom] += nref_el;
4523 int nmatrices = n_point_matrices[geom];
4530 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4533 int ref = ref_factors[el_coarse];
4534 int offset = point_matrices_offsets[GeomRef(geom, ref)];
4540 for (
int k = 0; k < nvert; k++)
4572 "Mesh::MakeSimplicial requires a properly oriented input mesh");
4574 "Mesh::MakeSimplicial does not support non-conforming meshes.")
4581 Mesh copy(orig_mesh);
4586 int nv = orig_mesh.
GetNV();
4587 int ne = orig_mesh.
GetNE();
4588 int nbe = orig_mesh.
GetNBE();
4601 int new_ne = 0, new_nbe = 0;
4602 for (
int i=0; i<ne; ++i)
4606 for (
int i=0; i<nbe; ++i)
4615 for (
int i=0; i<nv; ++i)
4625 if (vglobal == NULL)
4628 for (
int i=0; i<nv; ++i) { vglobal_id[i] = i; }
4629 vglobal = vglobal_id.
GetData();
4632 constexpr
int nv_tri = 3, nv_quad = 4, nv_tet = 4, nv_prism = 6, nv_hex = 8;
4633 constexpr
int quad_ntris = 2, prism_ntets = 3;
4634 static const int quad_trimap[2][nv_tri*quad_ntris] =
4646 static const int prism_rot[nv_prism*nv_prism] =
4655 static const int prism_f[nv_quad] = {1, 2, 5, 4};
4656 static const int prism_tetmaps[2][nv_prism*prism_ntets] =
4670 static const int hex_rot[nv_hex*nv_hex] =
4672 0, 1, 2, 3, 4, 5, 6, 7,
4673 1, 0, 4, 5, 2, 3, 7, 6,
4674 2, 1, 5, 6, 3, 0, 4, 7,
4675 3, 0, 1, 2, 7, 4, 5, 6,
4676 4, 0, 3, 7, 5, 1, 2, 6,
4677 5, 1, 0, 4, 6, 2, 3, 7,
4678 6, 2, 1, 5, 7, 3, 0, 4,
4679 7, 3, 2, 6, 4, 0, 1, 5
4681 static const int hex_f0[nv_quad] = {1, 2, 6, 5};
4682 static const int hex_f1[nv_quad] = {2, 3, 7, 6};
4683 static const int hex_f2[nv_quad] = {4, 5, 6, 7};
4684 static const int num_rot[8] = {0, 1, 2, 0, 0, 2, 1, 0};
4685 static const int hex_tetmap0[nv_tet*5] =
4692 static const int hex_tetmap1[nv_tet*6] =
4699 static const int hex_tetmap2[nv_tet*6] =
4706 static const int hex_tetmap3[nv_tet*6] =
4713 static const int *hex_tetmaps[4] =
4715 hex_tetmap0, hex_tetmap1, hex_tetmap2, hex_tetmap3
4718 auto find_min = [](
const int*
a,
int n) {
return std::min_element(a,a+n)-
a; };
4720 for (
int i=0; i<ne; ++i)
4722 const int *v = orig_mesh.
elements[i]->GetVertices();
4726 if (num_subdivisions[orig_geom] == 1)
4738 for (
int itri=0; itri<quad_ntris; ++itri)
4743 for (
int iv=0; iv<nv_tri; ++iv)
4745 v2[iv] = v[quad_trimap[0][itri + iv*quad_ntris]];
4753 for (
int iv=0; iv<nv_prism; ++iv) { vg[iv] = vglobal[v[iv]]; }
4756 int irot = find_min(vg, nv_prism);
4757 for (
int iv=0; iv<nv_prism; ++iv)
4759 int jv = prism_rot[iv + irot*nv_prism];
4764 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[prism_f[iv]]]; }
4765 int j = find_min(q, nv_quad);
4766 const int *tetmap = (j == 0 || j == 2) ? prism_tetmaps[0] : prism_tetmaps[1];
4767 for (
int itet=0; itet<prism_ntets; ++itet)
4772 for (
int iv=0; iv<nv_tet; ++iv)
4774 v2[iv] = vg[tetmap[itet + iv*prism_ntets]];
4782 for (
int iv=0; iv<nv_hex; ++iv) { vg[iv] = vglobal[v[iv]]; }
4786 int irot = find_min(vg, nv_hex);
4787 for (
int iv=0; iv<nv_hex; ++iv)
4789 int jv = hex_rot[iv + irot*nv_hex];
4799 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f0[iv]]]; }
4800 j = find_min(q, nv_quad);
4801 if (j == 0 || j == 2) { bitmask += 4; }
4803 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f1[iv]]]; }
4804 j = find_min(q, nv_quad);
4805 if (j == 1 || j == 3) { bitmask += 2; }
4807 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f2[iv]]]; }
4808 j = find_min(q, nv_quad);
4809 if (j == 0 || j == 2) { bitmask += 1; }
4812 int nrot = num_rot[bitmask];
4813 for (
int k=0; k<nrot; ++k)
4827 int ndiags = ((bitmask&4) >> 2) + ((bitmask&2) >> 1) + (bitmask&1);
4828 int ntets = (ndiags == 0) ? 5 : 6;
4829 const int *tetmap = hex_tetmaps[ndiags];
4830 for (
int itet=0; itet<ntets; ++itet)
4835 for (
int iv=0; iv<nv_tet; ++iv)
4837 v2[iv] = vg[tetmap[itet + iv*ntets]];
4846 for (
int i=0; i<nbe; ++i)
4848 const int *v = orig_mesh.
boundary[i]->GetVertices();
4851 if (num_subdivisions[orig_geom] == 1)
4861 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
4863 int iv_min = find_min(vg, nv_quad);
4864 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
4865 for (
int itri=0; itri<quad_ntris; ++itri)
4870 for (
int iv=0; iv<nv_tri; ++iv)
4872 v2[iv] = v[quad_trimap[isplit][itri + iv*quad_ntris]];
4879 MFEM_ABORT(
"Unreachable");
4893 Mesh periodic_mesh(orig_mesh,
true);
4899 for (
int i = 0; i < periodic_mesh.
GetNE(); i++)
4904 for (
int j = 0; j < nv; j++)
4910 for (
int i = 0; i < periodic_mesh.
GetNBE(); i++)
4915 for (
int j = 0; j < nv; j++)
4922 return periodic_mesh;
4926 const std::vector<Vector> &translations,
double tol)
const
4930 Vector coord(sdim), at(sdim), dx(sdim);
4931 Vector xMax(sdim), xMin(sdim), xDiff(sdim);
4932 xMax = xMin = xDiff = 0.0;
4936 for (
int be = 0; be <
GetNBE(); be++)
4941 for (
int i = 0; i < dofs.
Size(); i++)
4943 bdr_v.insert(dofs[i]);
4946 for (
int j = 0; j < sdim; j++)
4948 xMax[j] = max(xMax[j], coord[j]);
4949 xMin[j] = min(xMin[j], coord[j]);
4953 add(xMax, -1.0, xMin, xDiff);
4954 double dia = xDiff.
Norml2();
4962 map<int, int> replica2primary;
4964 map<int, set<int>> primary2replicas;
4968 for (
int v : bdr_v) { primary2replicas[v]; }
4972 auto make_replica = [&replica2primary, &primary2replicas](
int r,
int p)
4974 if (r ==
p) {
return; }
4975 primary2replicas[
p].insert(r);
4976 replica2primary[r] =
p;
4977 for (
int s : primary2replicas[r])
4979 primary2replicas[
p].insert(
s);
4980 replica2primary[
s] =
p;
4982 primary2replicas.erase(r);
4985 for (
unsigned int i = 0; i < translations.size(); i++)
4987 for (
int vi : bdr_v)
4990 add(coord, translations[i], at);
4992 for (
int vj : bdr_v)
4995 add(at, -1.0, coord, dx);
4996 if (dx.
Norml2() > dia*tol) {
continue; }
5001 bool pi = primary2replicas.find(vi) != primary2replicas.end();
5002 bool pj = primary2replicas.find(vj) != primary2replicas.end();
5008 make_replica(vj, vi);
5013 int owner_of_vj = replica2primary[vj];
5015 make_replica(vi, owner_of_vj);
5021 int owner_of_vi = replica2primary[vi];
5022 make_replica(vj, owner_of_vi);
5029 int owner_of_vi = replica2primary[vi];
5030 int owner_of_vj = replica2primary[vj];
5031 make_replica(owner_of_vj, owner_of_vi);
5038 std::vector<int> v2v(
GetNV());
5039 for (
size_t i = 0; i < v2v.size(); i++)
5043 for (
auto &&r2p : replica2primary)
5045 v2v[r2p.first] = r2p.second;
5054 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
5059 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
5076 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
5081 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
5111 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
5135 for (
int i = 0; i <
elements.Size(); i++)
5145 for (
int i = 0; i <
boundary.Size(); i++)
5162 for (
int i = 0; i < vd; i++)
5216 boundary.SetSize(NumOfBdrElements);
5227 edge_to_knot.
SetSize(NumOfEdges);
5231 input >> edge_to_knot[j] >> v[0] >> v[1];
5234 edge_to_knot[j] = -1 - edge_to_knot[j];
5252 for (
int d = 0; d < v.
Size(); d++)
5260 for (d = 0; d < p.
Size(); d++)
5264 for ( ; d < v.
Size(); d++)
5296 if (dynamic_cast<const H1_FECollection*>(fec)
5297 || dynamic_cast<const L2_FECollection*>(fec))
5306 #ifndef MFEM_USE_MPI
5307 const bool warn =
true;
5310 const bool warn = !pmesh || pmesh->
GetMyRank() == 0;
5314 MFEM_WARNING(
"converting NURBS mesh to order " << order <<
5315 " H1-continuous mesh!\n "
5316 "If this is the desired behavior, you can silence"
5317 " this warning by converting\n "
5318 "the NURBS mesh to high-order mesh in advance by"
5319 " calling the method\n "
5320 "Mesh::SetCurvature().");
5345 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
5364 MFEM_ASSERT(nodes != NULL,
"");
5380 case 1:
return GetNV();
5416 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
5417 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
5422 int i, j, k, wo = 0, fo = 0;
5431 int *vi =
elements[i]->GetVertices();
5434 for (j = 0; j < 3; j++)
5438 for (j = 0; j < 2; j++)
5439 for (k = 0; k < 2; k++)
5441 J(j, k) = v[j+1][k] - v[0][k];
5462 MFEM_ABORT(
"Invalid 2D element type \""
5479 int *vi =
elements[i]->GetVertices();
5485 for (j = 0; j < 4; j++)
5489 for (j = 0; j < 3; j++)
5490 for (k = 0; k < 3; k++)
5492 J(j, k) = v[j+1][k] - v[0][k];
5551 MFEM_ABORT(
"Invalid 3D element type \""
5557 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
5560 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / "
5561 <<
NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
5576 if (test[0] == base[0])
5577 if (test[1] == base[1])
5585 else if (test[0] == base[1])
5586 if (test[1] == base[0])
5595 if (test[1] == base[0])
5606 for (
int j = 0; j < 3; j++)
5607 if (test[aor[j]] != base[j])
5620 for (i = 0; i < 4; i++)
5621 if (test[i] == base[0])
5628 if (test[(i+1)%4] == base[1])
5637 for (
int j = 0; j < 4; j++)
5638 if (test[aor[j]] != base[j])
5640 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
5642 for (
int k = 0; k < 4; k++)
5647 for (
int k = 0; k < 4; k++)
5656 if (test[(i+1)%4] == base[1])
5672 if (test[0] == base[0])
5673 if (test[1] == base[1])
5674 if (test[2] == base[2])
5682 else if (test[2] == base[1])
5683 if (test[3] == base[2])
5692 if (test[1] == base[2])
5700 else if (test[1] == base[0])
5701 if (test[2] == base[1])
5702 if (test[0] == base[2])
5710 else if (test[3] == base[1])
5711 if (test[2] == base[2])
5720 if (test[3] == base[2])
5728 else if (test[2] == base[0])
5729 if (test[3] == base[1])
5730 if (test[0] == base[2])
5738 else if (test[0] == base[1])
5739 if (test[1] == base[2])
5748 if (test[3] == base[2])
5757 if (test[0] == base[1])
5758 if (test[2] == base[2])
5766 else if (test[1] == base[1])
5767 if (test[0] == base[2])
5776 if (test[1] == base[2])
5787 for (
int j = 0; j < 4; j++)
5788 if (test[aor[j]] != base[j])
5813 int *bv =
boundary[i]->GetVertices();
5819 mfem::Swap<int>(bv[0], bv[1]);
5833 if (
faces_info[fi].Elem2No >= 0) {
continue; }
5836 int *bv =
boundary[i]->GetVertices();
5838 MFEM_ASSERT(fi <
faces.Size(),
"internal error");
5839 const int *fv =
faces[fi]->GetVertices();
5856 MFEM_ABORT(
"Invalid 2D boundary element type \""
5857 << bdr_type <<
"\"");
5862 if (orientation % 2 == 0) {
continue; }
5864 if (!fix_it) {
continue; }
5872 mfem::Swap<int>(bv[0], bv[1]);
5876 mfem::Swap<int>(be[1], be[2]);
5882 mfem::Swap<int>(bv[0], bv[2]);
5886 mfem::Swap<int>(be[0], be[1]);
5887 mfem::Swap<int>(be[2], be[3]);
5900 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / "
5910 MFEM_ASSERT(0 <= dim && dim <=
Dim,
"invalid dim: " << dim);
5921 MFEM_ASSERT(0 <= dim && dim <=
Dim,
"invalid dim: " << dim);
5940 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
5941 "is not generated.");
5944 const int *v =
elements[i]->GetVertices();
5945 const int ne =
elements[i]->GetNEdges();
5947 for (
int j = 0; j < ne; j++)
5949 const int *e =
elements[i]->GetEdgeVertices(j);
5950 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5961 const int *v =
boundary[i]->GetVertices();
5962 cor[0] = (v[0] < v[1]) ? (1) : (-1);
5975 const int *v =
boundary[i]->GetVertices();
5976 const int ne =
boundary[i]->GetNEdges();
5978 for (
int j = 0; j < ne; j++)
5980 const int *e =
boundary[i]->GetEdgeVertices(j);
5981 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5993 const int *v =
faces[i]->GetVertices();
5994 o[0] = (v[0] < v[1]) ? (1) : (-1);
6006 const int *v =
faces[i]->GetVertices();
6007 const int ne =
faces[i]->GetNEdges();
6009 for (
int j = 0; j < ne; j++)
6011 const int *e =
faces[i]->GetEdgeVertices(j);
6012 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
6040 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
6091 for (j = 0; j < nv; j++)
6103 for (j = 0; j < nv; j++)
6150 MFEM_VERIFY(
el_to_face != NULL,
"el_to_face not generated");
6154 int n = el_faces.
Size();
6157 for (
int j = 0; j < n; j++)
6161 ori[j] =
faces_info[el_faces[j]].Elem1Inf % 64;
6165 MFEM_ASSERT(
faces_info[el_faces[j]].Elem2No == i,
"internal error");
6166 ori[j] =
faces_info[el_faces[j]].Elem2Inf % 64;
6190 MFEM_ABORT(
"invalid geometry");
6198 case 1:
return boundary[i]->GetVertices()[0];
6201 default: MFEM_ABORT(
"invalid dimension!");
6211 MFEM_ASSERT(fi.
Elem1Inf % 64 == 0,
"internal error");
6214 const int *bv =
boundary[bdr_el]->GetVertices();
6222 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
6233 MFEM_ASSERT(fi.
Elem1Inf % 64 == 0,
"internal error");
6236 const int *bv =
boundary[bdr_el]->GetVertices();
6244 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
6271 for (j = 0; j < nv; j++)
6273 pointmat(k, j) =
vertices[v[j]](k);
6288 for (j = 0; j < nv; j++)
6290 pointmat(k, j) =
vertices[v[j]](k);
6302 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
6305 return sqrt(length);
6313 for (
int i = 0; i < elem_array.
Size(); i++)
6318 for (
int i = 0; i < elem_array.
Size(); i++)
6320 const int *v = elem_array[i]->GetVertices();
6321 const int ne = elem_array[i]->GetNEdges();
6322 for (
int j = 0; j < ne; j++)
6324 const int *e = elem_array[i]->GetEdgeVertices(j);
6338 v_to_v.
Push(v[0], v[1]);
6345 const int *v =
elements[i]->GetVertices();
6346 const int ne =
elements[i]->GetNEdges();
6347 for (
int j = 0; j < ne; j++)
6349 const int *e =
elements[i]->GetEdgeVertices(j);
6350 v_to_v.
Push(v[e[0]], v[e[1]]);
6358 int i, NumberOfEdges;
6374 const int *v =
boundary[i]->GetVertices();
6375 be_to_f[i] = v_to_v(v[0], v[1]);
6388 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
6392 return NumberOfEdges;