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.
Det()), 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) { out <<
" + "; }
238 out << num_elems_by_geom[g] <<
' ' << Geometry::Name[g] <<
"(s)";
244 double h_min, h_max, kappa_min, kappa_max;
246 out <<
"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, out);
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, out);
312 <<
"Number of elements : " << GetNE() <<
" -- ";
313 PrintElementsByGeometry(Dim, num_elems_by_geom, out);
315 <<
"Number of bdr elem : " << GetNBE() <<
" -- ";
316 PrintElementsByGeometry(Dim-1, num_bdr_elems_by_geom, out);
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 out <<
'\n' << std::flush;
331 case Element::POINT :
return &
PointFE;
332 case Element::SEGMENT :
return &
SegmentFE;
337 case Element::WEDGE :
return &
WedgeFE;
339 MFEM_ABORT(
"Unknown element type \"" << ElemType <<
"\"");
342 MFEM_ABORT(
"Unknown element type");
351 ElTr->
ElementType = ElementTransformation::ELEMENT;
356 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
362 Nodes->FESpace()->GetElementVDofs(i, vdofs);
365 int n = vdofs.
Size()/spaceDim;
367 for (
int k = 0; k < spaceDim; k++)
369 for (
int j = 0; j < n; j++)
371 pm(k,j) = nodes(vdofs[n*k+j]);
374 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
378 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
383 ElTr->
ElementType = ElementTransformation::ELEMENT;
389 MFEM_ASSERT(nodes.
Size() == spaceDim*GetNV(),
"");
390 int nv = elements[i]->GetNVertices();
391 const int *v = elements[i]->GetVertices();
392 int n = vertices.Size();
394 for (
int k = 0; k < spaceDim; k++)
396 for (
int j = 0; j < nv; j++)
398 pm(k, j) = nodes(k*n+v[j]);
401 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
405 MFEM_ASSERT(nodes.
Size() == Nodes->Size(),
"");
407 Nodes->FESpace()->GetElementVDofs(i, vdofs);
408 int n = vdofs.
Size()/spaceDim;
410 for (
int k = 0; k < spaceDim; k++)
412 for (
int j = 0; j < n; j++)
414 pm(k,j) = nodes(vdofs[n*k+j]);
417 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
423 GetElementTransformation(i, &Transformation);
425 return &Transformation;
430 GetBdrElementTransformation(i, &BdrTransformation);
431 return &BdrTransformation;
438 ElTr->
ElementType = ElementTransformation::BDR_ELEMENT;
443 GetBdrPointMatrix(i, pm);
444 ElTr->
SetFE(GetTransformationFEforElementType(GetBdrElementType(i)));
454 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
455 int n = vdofs.
Size()/spaceDim;
457 for (
int k = 0; k < spaceDim; k++)
459 for (
int j = 0; j < n; j++)
461 pm(k,j) = nodes(vdofs[n*k+j]);
468 int elem_id, face_info;
469 GetBdrElementAdjacentElement(i, elem_id, face_info);
471 GetLocalFaceTransformation(GetBdrElementType(i),
472 GetElementType(elem_id),
473 FaceElemTr.Loc1.Transf, face_info);
478 Nodes->FESpace()->GetTraceElement(elem_id, face_geom);
479 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
480 "Mesh requires nodal Finite Element.");
482 FaceElemTr.Loc1.Transf.ElementNo = elem_id;
483 FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
484 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
485 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
487 ElTr->
SetFE(face_el);
494 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
501 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
502 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
504 for (
int i = 0; i < spaceDim; i++)
506 for (
int j = 0; j < nv; j++)
508 pm(i, j) = vertices[v[j]](i);
511 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
515 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
521 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
522 int n = vdofs.
Size()/spaceDim;
524 for (
int i = 0; i < spaceDim; i++)
526 for (
int j = 0; j < n; j++)
528 pm(i, j) = nodes(vdofs[n*i+j]);
535 FaceInfo &face_info = faces_info[FaceNo];
540 GetLocalFaceTransformation(face_type,
541 GetElementType(face_info.
Elem1No),
542 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
545 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
547 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
548 "Mesh requires nodal Finite Element.");
551 FaceElemTr.Loc1.Transf.ElementNo = face_info.
Elem1No;
552 FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
553 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
554 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
563 GetFaceTransformation(FaceNo, &FaceTransformation);
564 return &FaceTransformation;
571 GetFaceTransformation(EdgeNo, EdTr);
576 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
587 GetEdgeVertices(EdgeNo, v);
590 for (
int i = 0; i < spaceDim; i++)
592 for (
int j = 0; j < nv; j++)
594 pm(i, j) = vertices[v[j]](i);
597 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
601 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
607 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
608 int n = vdofs.
Size()/spaceDim;
610 for (
int i = 0; i < spaceDim; i++)
612 for (
int j = 0; j < n; j++)
614 pm(i, j) = nodes(vdofs[n*i+j]);
617 EdTr->
SetFE(edge_el);
621 MFEM_ABORT(
"Not implemented.");
628 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
629 return &EdgeTransformation;
633 void Mesh::GetLocalPtToSegTransformation(
648 void Mesh::GetLocalSegToTriTransformation(
657 tv = tri_t::Edges[i/64];
658 so = seg_t::Orient[i%64];
661 for (
int j = 0; j < 2; j++)
663 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
664 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
668 void Mesh::GetLocalSegToQuadTransformation(
677 qv = quad_t::Edges[i/64];
678 so = seg_t::Orient[i%64];
681 for (
int j = 0; j < 2; j++)
683 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
684 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
688 void Mesh::GetLocalTriToTetTransformation(
696 const int *tv = tet_t::FaceVert[i/64];
699 const int *to = tri_t::Orient[i%64];
703 for (
int j = 0; j < 3; j++)
706 locpm(0, j) = vert.
x;
707 locpm(1, j) = vert.
y;
708 locpm(2, j) = vert.
z;
712 void Mesh::GetLocalTriToWdgTransformation(
720 MFEM_VERIFY(i < 128,
"Local face index " << i/64
721 <<
" is not a triangular face of a wedge.");
722 const int *pv = pri_t::FaceVert[i/64];
725 const int *to = tri_t::Orient[i%64];
729 for (
int j = 0; j < 3; j++)
732 locpm(0, j) = vert.
x;
733 locpm(1, j) = vert.
y;
734 locpm(2, j) = vert.
z;
738 void Mesh::GetLocalQuadToHexTransformation(
746 const int *hv = hex_t::FaceVert[i/64];
748 const int *qo = quad_t::Orient[i%64];
751 for (
int j = 0; j < 4; j++)
754 locpm(0, j) = vert.
x;
755 locpm(1, j) = vert.
y;
756 locpm(2, j) = vert.
z;
760 void Mesh::GetLocalQuadToWdgTransformation(
768 MFEM_VERIFY(i >= 128,
"Local face index " << i/64
769 <<
" is not a quadrilateral face of a wedge.");
770 const int *pv = pri_t::FaceVert[i/64];
772 const int *qo = quad_t::Orient[i%64];
775 for (
int j = 0; j < 4; j++)
778 locpm(0, j) = vert.
x;
779 locpm(1, j) = vert.
y;
780 locpm(2, j) = vert.
z;
788 for (
int i = 0; i < geom_factors.Size(); i++)
800 geom_factors.Append(gf);
808 for (
int i = 0; i < face_geom_factors.Size(); i++)
821 face_geom_factors.Append(gf);
825 void Mesh::DeleteGeometricFactors()
827 for (
int i = 0; i < geom_factors.Size(); i++)
829 delete geom_factors[i];
831 geom_factors.SetSize(0);
832 for (
int i = 0; i < face_geom_factors.Size(); i++)
834 delete face_geom_factors[i];
836 face_geom_factors.SetSize(0);
839 void Mesh::GetLocalFaceTransformation(
845 GetLocalPtToSegTransformation(Transf, info);
848 case Element::SEGMENT:
849 if (elem_type == Element::TRIANGLE)
851 GetLocalSegToTriTransformation(Transf, info);
855 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
856 GetLocalSegToQuadTransformation(Transf, info);
860 case Element::TRIANGLE:
861 if (elem_type == Element::TETRAHEDRON)
863 GetLocalTriToTetTransformation(Transf, info);
867 MFEM_ASSERT(elem_type == Element::WEDGE,
"");
868 GetLocalTriToWdgTransformation(Transf, info);
872 case Element::QUADRILATERAL:
873 if (elem_type == Element::HEXAHEDRON)
875 GetLocalQuadToHexTransformation(Transf, info);
879 MFEM_ASSERT(elem_type == Element::WEDGE,
"");
880 GetLocalQuadToWdgTransformation(Transf, info);
889 FaceInfo &face_info = faces_info[FaceNo];
892 FaceElemTr.SetConfigurationMask(cmask);
893 FaceElemTr.Elem1 = NULL;
894 FaceElemTr.Elem2 = NULL;
898 if (mask & FaceElementTransformations::HAVE_ELEM1)
900 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
901 FaceElemTr.Elem1 = &Transformation;
908 FaceElemTr.Elem2No = face_info.
Elem2No;
909 if ((mask & FaceElementTransformations::HAVE_ELEM2) &&
910 FaceElemTr.Elem2No >= 0)
913 if (NURBSext && (mask & FaceElementTransformations::HAVE_ELEM1))
914 { MFEM_ABORT(
"NURBS mesh not supported!"); }
916 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
917 FaceElemTr.Elem2 = &Transformation2;
922 if (mask & FaceElementTransformations::HAVE_FACE)
924 GetFaceTransformation(FaceNo, &FaceElemTr);
929 FaceElemTr.SetGeometryType(GetFaceGeometryType(FaceNo));
933 int face_type = GetFaceElementType(FaceNo);
934 if (mask & FaceElementTransformations::HAVE_LOC1)
936 int elem_type = GetElementType(face_info.
Elem1No);
937 GetLocalFaceTransformation(face_type, elem_type,
938 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
941 if ((mask & FaceElementTransformations::HAVE_LOC2) &&
942 FaceElemTr.Elem2No >= 0)
944 int elem_type = GetElementType(face_info.
Elem2No);
945 GetLocalFaceTransformation(face_type, elem_type,
946 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
949 if (Nonconforming() && IsSlaveFace(face_info))
951 ApplyLocalSlaveTransformation(FaceElemTr, face_info,
false);
956 FaceElemTr.SetConfigurationMask(cmask);
962 double dist = FaceElemTr.CheckConsistency();
965 mfem::out <<
"\nInternal error: face id = " << FaceNo
966 <<
", dist = " << dist <<
'\n';
967 FaceElemTr.CheckConsistency(1);
968 MFEM_ABORT(
"internal error");
978 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
984 #ifdef MFEM_THREAD_SAFE
989 MFEM_ASSERT(fi.
NCFace >= 0,
"");
990 MFEM_ASSERT(nc_faces_info[fi.
NCFace].Slave,
"internal error");
1001 std::swap(composition(0,0), composition(0,1));
1002 std::swap(composition(1,0), composition(1,1));
1023 int fn = GetBdrFace(BdrElemNo);
1026 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
1030 tr = GetFaceElementTransformations(fn, 21);
1031 tr->
Attribute = boundary[BdrElemNo]->GetAttribute();
1033 tr->
ElementType = ElementTransformation::BDR_FACE;
1037 int Mesh::GetBdrFace(
int BdrElemNo)
const
1042 fn = be_to_face[BdrElemNo];
1046 fn = be_to_edge[BdrElemNo];
1050 fn = boundary[BdrElemNo]->GetVertices()[0];
1055 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
const
1057 *Elem1 = faces_info[Face].
Elem1No;
1058 *Elem2 = faces_info[Face].Elem2No;
1061 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
const
1063 *Inf1 = faces_info[Face].Elem1Inf;
1064 *Inf2 = faces_info[Face].Elem2Inf;
1067 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2,
int *NCFace)
const
1069 *Inf1 = faces_info[Face].Elem1Inf;
1070 *Inf2 = faces_info[Face].Elem2Inf;
1071 *NCFace = faces_info[Face].NCFace;
1078 case 1:
return Geometry::POINT;
1079 case 2:
return Geometry::SEGMENT;
1081 if (Face < NumOfFaces)
1083 return faces[Face]->GetGeometryType();
1086 const int nc_face_id = faces_info[Face].NCFace;
1087 MFEM_ASSERT(nc_face_id >= 0,
"parent ghost faces are not supported");
1088 return faces[nc_faces_info[nc_face_id].MasterFace]->GetGeometryType();
1090 return Geometry::INVALID;
1095 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
1103 NumOfElements = NumOfBdrElements = 0;
1104 NumOfEdges = NumOfFaces = 0;
1105 nbInteriorFaces = -1;
1106 nbBoundaryFaces = -1;
1107 meshgen = mesh_geoms = 0;
1113 last_operation = Mesh::NONE;
1116 void Mesh::InitTables()
1119 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
1122 void Mesh::SetEmpty()
1128 void Mesh::DestroyTables()
1133 DeleteGeometricFactors();
1144 void Mesh::DestroyPointers()
1146 if (own_nodes) {
delete Nodes; }
1152 for (
int i = 0; i < NumOfElements; i++)
1154 FreeElement(elements[i]);
1157 for (
int i = 0; i < NumOfBdrElements; i++)
1159 FreeElement(boundary[i]);
1162 for (
int i = 0; i < faces.Size(); i++)
1164 FreeElement(faces[i]);
1170 void Mesh::Destroy()
1174 elements.DeleteAll();
1175 vertices.DeleteAll();
1176 boundary.DeleteAll();
1178 faces_info.DeleteAll();
1179 nc_faces_info.DeleteAll();
1180 be_to_edge.DeleteAll();
1181 be_to_face.DeleteAll();
1189 CoarseFineTr.Clear();
1191 #ifdef MFEM_USE_MEMALLOC
1195 attributes.DeleteAll();
1196 bdr_attributes.DeleteAll();
1199 void Mesh::ResetLazyData()
1201 delete el_to_el; el_to_el = NULL;
1202 delete face_edge; face_edge = NULL;
1203 delete edge_vertex; edge_vertex = NULL;
1204 DeleteGeometricFactors();
1205 nbInteriorFaces = -1;
1206 nbBoundaryFaces = -1;
1209 void Mesh::SetAttributes()
1214 for (
int i = 0; i < attribs.
Size(); i++)
1216 attribs[i] = GetBdrAttribute(i);
1220 attribs.
Copy(bdr_attributes);
1221 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
1223 MFEM_WARNING(
"Non-positive attributes on the boundary!");
1227 for (
int i = 0; i < attribs.
Size(); i++)
1229 attribs[i] = GetAttribute(i);
1233 attribs.
Copy(attributes);
1234 if (attributes.Size() > 0 && attributes[0] <= 0)
1236 MFEM_WARNING(
"Non-positive attributes in the domain!");
1240 void Mesh::InitMesh(
int Dim_,
int spaceDim_,
int NVert,
int NElem,
int NBdrElem)
1245 spaceDim = spaceDim_;
1248 vertices.SetSize(NVert);
1251 elements.SetSize(NElem);
1253 NumOfBdrElements = 0;
1254 boundary.SetSize(NBdrElem);
1257 template<
typename T>
1258 static void CheckEnlarge(
Array<T> &array,
int size)
1260 if (size >= array.
Size()) { array.
SetSize(size + 1); }
1263 int Mesh::AddVertex(
double x,
double y,
double z)
1265 CheckEnlarge(vertices, NumOfVertices);
1266 double *v = vertices[NumOfVertices]();
1270 return NumOfVertices++;
1273 int Mesh::AddVertex(
const double *coords)
1275 CheckEnlarge(vertices, NumOfVertices);
1276 vertices[NumOfVertices].SetCoords(spaceDim, coords);
1277 return NumOfVertices++;
1280 void Mesh::AddVertexParents(
int i,
int p1,
int p2)
1286 if (i < vertices.Size())
1288 double *vi = vertices[i](), *vp1 = vertices[p1](), *vp2 = vertices[p2]();
1289 for (
int j = 0; j < 3; j++)
1291 vi[j] = (vp1[j] + vp2[j]) * 0.5;
1296 int Mesh::AddSegment(
int v1,
int v2,
int attr)
1298 CheckEnlarge(elements, NumOfElements);
1299 elements[NumOfElements] =
new Segment(v1, v2, attr);
1300 return NumOfElements++;
1303 int Mesh::AddSegment(
const int *vi,
int attr)
1305 CheckEnlarge(elements, NumOfElements);
1306 elements[NumOfElements] =
new Segment(vi, attr);
1307 return NumOfElements++;
1310 int Mesh::AddTriangle(
int v1,
int v2,
int v3,
int attr)
1312 CheckEnlarge(elements, NumOfElements);
1313 elements[NumOfElements] =
new Triangle(v1, v2, v3, attr);
1314 return NumOfElements++;
1317 int Mesh::AddTriangle(
const int *vi,
int attr)
1319 CheckEnlarge(elements, NumOfElements);
1320 elements[NumOfElements] =
new Triangle(vi, attr);
1321 return NumOfElements++;
1324 int Mesh::AddQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1326 CheckEnlarge(elements, NumOfElements);
1327 elements[NumOfElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1328 return NumOfElements++;
1331 int Mesh::AddQuad(
const int *vi,
int attr)
1333 CheckEnlarge(elements, NumOfElements);
1335 return NumOfElements++;
1338 int Mesh::AddTet(
int v1,
int v2,
int v3,
int v4,
int attr)
1340 int vi[4] = {v1, v2, v3, v4};
1341 return AddTet(vi, attr);
1344 int Mesh::AddTet(
const int *vi,
int attr)
1346 CheckEnlarge(elements, NumOfElements);
1347 #ifdef MFEM_USE_MEMALLOC
1349 tet = TetMemory.Alloc();
1352 elements[NumOfElements] = tet;
1354 elements[NumOfElements] =
new Tetrahedron(vi, attr);
1356 return NumOfElements++;
1359 int Mesh::AddWedge(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int attr)
1361 CheckEnlarge(elements, NumOfElements);
1362 elements[NumOfElements] =
new Wedge(v1, v2, v3, v4, v5, v6, attr);
1363 return NumOfElements++;
1366 int Mesh::AddWedge(
const int *vi,
int attr)
1368 CheckEnlarge(elements, NumOfElements);
1369 elements[NumOfElements] =
new Wedge(vi, attr);
1370 return NumOfElements++;
1373 int Mesh::AddHex(
int v1,
int v2,
int v3,
int v4,
int v5,
int v6,
int v7,
int v8,
1376 CheckEnlarge(elements, NumOfElements);
1377 elements[NumOfElements] =
1378 new Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8, attr);
1379 return NumOfElements++;
1382 int Mesh::AddHex(
const int *vi,
int attr)
1384 CheckEnlarge(elements, NumOfElements);
1385 elements[NumOfElements] =
new Hexahedron(vi, attr);
1386 return NumOfElements++;
1389 void Mesh::AddHexAsTets(
const int *vi,
int attr)
1391 static const int hex_to_tet[6][4] =
1393 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
1394 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
1398 for (
int i = 0; i < 6; i++)
1400 for (
int j = 0; j < 4; j++)
1402 ti[j] = vi[hex_to_tet[i][j]];
1408 void Mesh::AddHexAsWedges(
const int *vi,
int attr)
1410 static const int hex_to_wdg[2][6] =
1412 { 0, 1, 2, 4, 5, 6 }, { 0, 2, 3, 4, 6, 7 }
1416 for (
int i = 0; i < 2; i++)
1418 for (
int j = 0; j < 6; j++)
1420 ti[j] = vi[hex_to_wdg[i][j]];
1428 CheckEnlarge(elements, NumOfElements);
1429 elements[NumOfElements] = elem;
1430 return NumOfElements++;
1435 CheckEnlarge(boundary, NumOfBdrElements);
1436 boundary[NumOfBdrElements] = elem;
1437 return NumOfBdrElements++;
1440 int Mesh::AddBdrSegment(
int v1,
int v2,
int attr)
1442 CheckEnlarge(boundary, NumOfBdrElements);
1443 boundary[NumOfBdrElements] =
new Segment(v1, v2, attr);
1444 return NumOfBdrElements++;
1447 int Mesh::AddBdrSegment(
const int *vi,
int attr)
1449 CheckEnlarge(boundary, NumOfBdrElements);
1450 boundary[NumOfBdrElements] =
new Segment(vi, attr);
1451 return NumOfBdrElements++;
1454 int Mesh::AddBdrTriangle(
int v1,
int v2,
int v3,
int attr)
1456 CheckEnlarge(boundary, NumOfBdrElements);
1457 boundary[NumOfBdrElements] =
new Triangle(v1, v2, v3, attr);
1458 return NumOfBdrElements++;
1461 int Mesh::AddBdrTriangle(
const int *vi,
int attr)
1463 CheckEnlarge(boundary, NumOfBdrElements);
1464 boundary[NumOfBdrElements] =
new Triangle(vi, attr);
1465 return NumOfBdrElements++;
1468 int Mesh::AddBdrQuad(
int v1,
int v2,
int v3,
int v4,
int attr)
1470 CheckEnlarge(boundary, NumOfBdrElements);
1471 boundary[NumOfBdrElements] =
new Quadrilateral(v1, v2, v3, v4, attr);
1472 return NumOfBdrElements++;
1475 int Mesh::AddBdrQuad(
const int *vi,
int attr)
1477 CheckEnlarge(boundary, NumOfBdrElements);
1479 return NumOfBdrElements++;
1482 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1484 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1487 for (
int i = 0; i < 2; i++)
1489 for (
int j = 0; j < 3; j++)
1491 ti[j] = vi[quad_to_tri[i][j]];
1493 AddBdrTriangle(ti, attr);
1497 int Mesh::AddBdrPoint(
int v,
int attr)
1499 CheckEnlarge(boundary, NumOfBdrElements);
1500 boundary[NumOfBdrElements] =
new Point(&v, attr);
1501 return NumOfBdrElements++;
1504 void Mesh::GenerateBoundaryElements()
1507 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1511 for (i = 0; i < boundary.Size(); i++)
1513 FreeElement(boundary[i]);
1523 NumOfBdrElements = 0;
1524 for (i = 0; i < faces_info.Size(); i++)
1526 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1529 boundary.SetSize(NumOfBdrElements);
1530 be2face.
SetSize(NumOfBdrElements);
1531 for (j = i = 0; i < faces_info.Size(); i++)
1533 if (faces_info[i].Elem2No < 0)
1535 boundary[j] = faces[i]->Duplicate(
this);
1542 void Mesh::FinalizeCheck()
1544 MFEM_VERIFY(vertices.Size() == NumOfVertices ||
1545 vertices.Size() == 0,
1546 "incorrect number of vertices: preallocated: " << vertices.Size()
1547 <<
", actually added: " << NumOfVertices);
1548 MFEM_VERIFY(elements.Size() == NumOfElements,
1549 "incorrect number of elements: preallocated: " << elements.Size()
1550 <<
", actually added: " << NumOfElements);
1551 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1552 "incorrect number of boundary elements: preallocated: "
1553 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1556 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1559 CheckElementOrientation(fix_orientation);
1563 MarkTriMeshForRefinement();
1568 el_to_edge =
new Table;
1569 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1571 CheckBdrElementOrientation();
1585 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1586 bool fix_orientation)
1589 if (fix_orientation)
1591 CheckElementOrientation(fix_orientation);
1596 el_to_edge =
new Table;
1597 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1599 CheckBdrElementOrientation();
1619 GeckoProgress(
double limit) : limit(limit) { sw.Start(); }
1620 virtual bool quit()
const {
return limit > 0 && sw.UserTime() > limit; }
1623 class GeckoVerboseProgress :
public GeckoProgress
1629 GeckoVerboseProgress(
double limit) : GeckoProgress(limit) {}
1631 virtual void beginorder(
const Graph* graph,
Float cost)
const
1632 {
mfem::out <<
"Begin Gecko ordering, cost = " << cost << std::endl; }
1633 virtual void endorder(
const Graph* graph,
Float cost)
const
1634 {
mfem::out <<
"End ordering, cost = " << cost << std::endl; }
1636 virtual void beginiter(
const Graph* graph,
1639 mfem::out <<
"Iteration " << iter <<
"/" << maxiter <<
", window "
1640 << window << std::flush;
1642 virtual void enditer(
const Graph* graph,
Float mincost,
Float cost)
const
1643 {
mfem::out <<
", cost = " << cost << endl; }
1648 int iterations,
int window,
1649 int period,
int seed,
bool verbose,
1655 GeckoProgress progress(time_limit);
1656 GeckoVerboseProgress vprogress(time_limit);
1659 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1666 const Table &my_el_to_el = ElementToElementTable();
1667 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1669 const int *neighid = my_el_to_el.
GetRow(elemid);
1670 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
1672 graph.
insert_arc(elemid + 1, neighid[i] + 1);
1677 graph.
order(&functional, iterations, window, period, seed,
1678 verbose ? &vprogress : &progress);
1684 ordering[gnodeid - 1] = graph.
rank(gnodeid);
1687 return graph.
cost();
1698 HilbertCmp(
int coord,
bool dir,
const Array<double> &points,
double mid)
1699 : coord(coord), dir(dir), points(points), mid(mid) {}
1701 bool operator()(
int i)
const
1703 return (points[3*i + coord] < mid) != dir;
1707 static void HilbertSort2D(
int coord1,
1710 const Array<double> &points,
int *beg,
int *end,
1711 double xmin,
double ymin,
double xmax,
double ymax)
1713 if (end - beg <= 1) {
return; }
1715 double xmid = (xmin + xmax)*0.5;
1716 double ymid = (ymin + ymax)*0.5;
1718 int coord2 = (coord1 + 1) % 2;
1721 int *p0 = beg, *p4 = end;
1722 int *p2 = std::partition(p0, p4, HilbertCmp(coord1, dir1, points, xmid));
1723 int *p1 = std::partition(p0, p2, HilbertCmp(coord2, dir2, points, ymid));
1724 int *p3 = std::partition(p2, p4, HilbertCmp(coord2, !dir2, points, ymid));
1728 HilbertSort2D(coord2, dir2, dir1, points, p0, p1,
1729 ymin, xmin, ymid, xmid);
1731 if (p1 != p0 || p2 != p4)
1733 HilbertSort2D(coord1, dir1, dir2, points, p1, p2,
1734 xmin, ymid, xmid, ymax);
1736 if (p2 != p0 || p3 != p4)
1738 HilbertSort2D(coord1, dir1, dir2, points, p2, p3,
1739 xmid, ymid, xmax, ymax);
1743 HilbertSort2D(coord2, !dir2, !dir1, points, p3, p4,
1744 ymid, xmax, ymin, xmid);
1748 static void HilbertSort3D(
int coord1,
bool dir1,
bool dir2,
bool dir3,
1749 const Array<double> &points,
int *beg,
int *end,
1750 double xmin,
double ymin,
double zmin,
1751 double xmax,
double ymax,
double zmax)
1753 if (end - beg <= 1) {
return; }
1755 double xmid = (xmin + xmax)*0.5;
1756 double ymid = (ymin + ymax)*0.5;
1757 double zmid = (zmin + zmax)*0.5;
1759 int coord2 = (coord1 + 1) % 3;
1760 int coord3 = (coord1 + 2) % 3;
1763 int *p0 = beg, *p8 = end;
1764 int *p4 = std::partition(p0, p8, HilbertCmp(coord1, dir1, points, xmid));
1765 int *p2 = std::partition(p0, p4, HilbertCmp(coord2, dir2, points, ymid));
1766 int *p6 = std::partition(p4, p8, HilbertCmp(coord2, !dir2, points, ymid));
1767 int *p1 = std::partition(p0, p2, HilbertCmp(coord3, dir3, points, zmid));
1768 int *p3 = std::partition(p2, p4, HilbertCmp(coord3, !dir3, points, zmid));
1769 int *p5 = std::partition(p4, p6, HilbertCmp(coord3, dir3, points, zmid));
1770 int *p7 = std::partition(p6, p8, HilbertCmp(coord3, !dir3, points, zmid));
1774 HilbertSort3D(coord3, dir3, dir1, dir2, points, p0, p1,
1775 zmin, xmin, ymin, zmid, xmid, ymid);
1777 if (p1 != p0 || p2 != p8)
1779 HilbertSort3D(coord2, dir2, dir3, dir1, points, p1, p2,
1780 ymin, zmid, xmin, ymid, zmax, xmid);
1782 if (p2 != p0 || p3 != p8)
1784 HilbertSort3D(coord2, dir2, dir3, dir1, points, p2, p3,
1785 ymid, zmid, xmin, ymax, zmax, xmid);
1787 if (p3 != p0 || p4 != p8)
1789 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p3, p4,
1790 xmin, ymax, zmid, xmid, ymid, zmin);
1792 if (p4 != p0 || p5 != p8)
1794 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p4, p5,
1795 xmid, ymax, zmid, xmax, ymid, zmin);
1797 if (p5 != p0 || p6 != p8)
1799 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p5, p6,
1800 ymax, zmid, xmax, ymid, zmax, xmid);
1802 if (p6 != p0 || p7 != p8)
1804 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p6, p7,
1805 ymid, zmid, xmax, ymin, zmax, xmid);
1809 HilbertSort3D(coord3, !dir3, !dir1, dir2, points, p7, p8,
1810 zmid, xmax, ymin, zmin, xmid, ymid);
1816 MFEM_VERIFY(spaceDim <= 3,
"");
1819 GetBoundingBox(min, max);
1824 if (spaceDim < 3) { points = 0.0; }
1827 for (
int i = 0; i < GetNE(); i++)
1829 GetElementCenter(i, center);
1830 for (
int j = 0; j < spaceDim; j++)
1832 points[3*i + j] = center(j);
1839 indices.
Sort([&](
int a,
int b)
1840 {
return points[3*
a] < points[3*
b]; });
1842 else if (spaceDim == 2)
1845 HilbertSort2D(0,
false,
false,
1846 points, indices.
begin(), indices.
end(),
1847 min(0), min(1), max(0), max(1));
1852 HilbertSort3D(0,
false,
false,
false,
1853 points, indices.
begin(), indices.
end(),
1854 min(0), min(1), min(2), max(0), max(1), max(2));
1859 for (
int i = 0; i < GetNE(); i++)
1861 ordering[indices[i]] = i;
1866 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
1870 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
1875 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
1879 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
1909 old_elem_node_vals.SetSize(GetNE());
1910 nodes_fes = Nodes->FESpace();
1913 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1915 nodes_fes->GetElementVDofs(old_elid, old_dofs);
1917 old_elem_node_vals[old_elid] =
new Vector(vals);
1923 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
1925 int new_elid = ordering[old_elid];
1926 new_elements[new_elid] = elements[old_elid];
1931 if (reorder_vertices)
1936 vertex_ordering = -1;
1938 int new_vertex_ind = 0;
1939 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1941 int *elem_vert = elements[new_elid]->GetVertices();
1942 int nv = elements[new_elid]->GetNVertices();
1943 for (
int vi = 0; vi < nv; ++vi)
1945 int old_vertex_ind = elem_vert[vi];
1946 if (vertex_ordering[old_vertex_ind] == -1)
1948 vertex_ordering[old_vertex_ind] = new_vertex_ind;
1949 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
1959 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1961 int *elem_vert = elements[new_elid]->GetVertices();
1962 int nv = elements[new_elid]->GetNVertices();
1963 for (
int vi = 0; vi < nv; ++vi)
1965 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
1970 for (
int belid = 0; belid < GetNBE(); ++belid)
1972 int *be_vert = boundary[belid]->GetVertices();
1973 int nv = boundary[belid]->GetNVertices();
1974 for (
int vi = 0; vi < nv; ++vi)
1976 be_vert[vi] = vertex_ordering[be_vert[vi]];
1987 el_to_edge =
new Table;
1988 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1993 GetElementToFaceTable();
2003 last_operation = Mesh::NONE;
2004 nodes_fes->Update(
false);
2007 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
2009 int new_elid = ordering[old_elid];
2010 nodes_fes->GetElementVDofs(new_elid, new_dofs);
2011 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
2012 delete old_elem_node_vals[old_elid];
2018 void Mesh::MarkForRefinement()
2024 MarkTriMeshForRefinement();
2028 DSTable v_to_v(NumOfVertices);
2029 GetVertexToVertexTable(v_to_v);
2030 MarkTetMeshForRefinement(v_to_v);
2035 void Mesh::MarkTriMeshForRefinement()
2040 for (
int i = 0; i < NumOfElements; i++)
2042 if (elements[i]->GetType() == Element::TRIANGLE)
2044 GetPointMatrix(i, pmat);
2045 static_cast<Triangle*
>(elements[i])->MarkEdge(pmat);
2056 for (
int i = 0; i < NumOfVertices; i++)
2061 length_idx[j].one = GetLength(i, it.Column());
2062 length_idx[j].two = j;
2069 for (
int i = 0; i < NumOfEdges; i++)
2071 order[length_idx[i].two] = i;
2075 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
2080 GetEdgeOrdering(v_to_v, order);
2082 for (
int i = 0; i < NumOfElements; i++)
2084 if (elements[i]->GetType() == Element::TETRAHEDRON)
2086 elements[i]->MarkEdge(v_to_v, order);
2089 for (
int i = 0; i < NumOfBdrElements; i++)
2091 if (boundary[i]->GetType() == Element::TRIANGLE)
2093 boundary[i]->MarkEdge(v_to_v, order);
2100 if (*old_v_to_v && *old_elem_vert)
2107 if (*old_v_to_v == NULL)
2109 bool need_v_to_v =
false;
2111 for (
int i = 0; i < GetNEdges(); i++)
2117 if (dofs.
Size() > 0)
2125 *old_v_to_v =
new DSTable(NumOfVertices);
2126 GetVertexToVertexTable(*(*old_v_to_v));
2129 if (*old_elem_vert == NULL)
2131 bool need_elem_vert =
false;
2133 for (
int i = 0; i < GetNE(); i++)
2139 if (dofs.
Size() > 1)
2141 need_elem_vert =
true;
2147 *old_elem_vert =
new Table;
2148 (*old_elem_vert)->
MakeI(GetNE());
2149 for (
int i = 0; i < GetNE(); i++)
2151 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
2153 (*old_elem_vert)->MakeJ();
2154 for (
int i = 0; i < GetNE(); i++)
2156 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
2157 elements[i]->GetNVertices());
2159 (*old_elem_vert)->ShiftUpI();
2172 const int num_edge_dofs = old_dofs.
Size();
2175 const Vector onodes = *Nodes;
2179 int offset = NumOfVertices * old_dofs.
Size();
2183 if (num_edge_dofs > 0)
2185 DSTable new_v_to_v(NumOfVertices);
2186 GetVertexToVertexTable(new_v_to_v);
2188 for (
int i = 0; i < NumOfVertices; i++)
2192 const int old_i = (*old_v_to_v)(i, it.Column());
2193 const int new_i = it.Index();
2194 if (new_i == old_i) {
continue; }
2196 old_dofs.
SetSize(num_edge_dofs);
2197 new_dofs.
SetSize(num_edge_dofs);
2198 for (
int j = 0; j < num_edge_dofs; j++)
2200 old_dofs[j] = offset + old_i * num_edge_dofs + j;
2201 new_dofs[j] = offset + new_i * num_edge_dofs + j;
2205 for (
int j = 0; j < old_dofs.
Size(); j++)
2207 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2211 offset += NumOfEdges * num_edge_dofs;
2219 Table old_face_vertex;
2220 old_face_vertex.
MakeI(NumOfFaces);
2221 for (
int i = 0; i < NumOfFaces; i++)
2225 old_face_vertex.
MakeJ();
2226 for (
int i = 0; i < NumOfFaces; i++)
2228 faces[i]->GetNVertices());
2232 STable3D *faces_tbl = GetElementToFaceTable(1);
2238 for (
int i = 0; i < NumOfFaces; i++)
2240 const int *old_v = old_face_vertex.
GetRow(i);
2242 switch (old_face_vertex.
RowSize(i))
2245 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2249 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2253 new_fdofs[new_i+1] = old_dofs.
Size();
2258 for (
int i = 0; i < NumOfFaces; i++)
2260 const int *old_v = old_face_vertex.
GetRow(i), *new_v;
2263 switch (old_face_vertex.
RowSize(i))
2266 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2267 new_v = faces[new_i]->GetVertices();
2268 new_or = GetTriOrientation(old_v, new_v);
2273 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2274 new_v = faces[new_i]->GetVertices();
2275 new_or = GetQuadOrientation(old_v, new_v);
2282 for (
int j = 0; j < old_dofs.
Size(); j++)
2285 const int old_j = dof_ord[j];
2286 new_dofs[old_j] = offset + new_fdofs[new_i] + j;
2290 for (
int j = 0; j < old_dofs.
Size(); j++)
2292 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2314 for (
int i = 0; i < GetNE(); i++)
2316 const int *old_v = old_elem_vert->
GetRow(i);
2317 const int *new_v = elements[i]->GetVertices();
2323 case Geometry::SEGMENT:
2324 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
2326 case Geometry::TRIANGLE:
2327 new_or = GetTriOrientation(old_v, new_v);
2329 case Geometry::SQUARE:
2330 new_or = GetQuadOrientation(old_v, new_v);
2332 case Geometry::TETRAHEDRON:
2333 new_or = GetTetOrientation(old_v, new_v);
2337 MFEM_ABORT(Geometry::Name[geom] <<
" elements (" << fec->
Name()
2338 <<
" FE collection) are not supported yet!");
2342 MFEM_VERIFY(dof_ord != NULL,
2343 "FE collection '" << fec->
Name()
2344 <<
"' does not define reordering for "
2345 << Geometry::Name[
geom] <<
" elements!");
2348 for (
int j = 0; j < new_dofs.
Size(); j++)
2351 const int old_j = dof_ord[j];
2352 new_dofs[old_j] = offset + j;
2354 offset += new_dofs.
Size();
2357 for (
int j = 0; j < old_dofs.
Size(); j++)
2359 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2371 GetElementToFaceTable();
2374 CheckBdrElementOrientation();
2379 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2384 CheckBdrElementOrientation();
2389 last_operation = Mesh::NONE;
2394 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
2397 CheckElementOrientation(fix_orientation);
2399 if (NumOfBdrElements == 0)
2401 GetElementToFaceTable();
2403 GenerateBoundaryElements();
2408 DSTable v_to_v(NumOfVertices);
2409 GetVertexToVertexTable(v_to_v);
2410 MarkTetMeshForRefinement(v_to_v);
2413 GetElementToFaceTable();
2416 CheckBdrElementOrientation();
2418 if (generate_edges == 1)
2420 el_to_edge =
new Table;
2421 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2435 void Mesh::FinalizeWedgeMesh(
int generate_edges,
int refine,
2436 bool fix_orientation)
2439 CheckElementOrientation(fix_orientation);
2441 if (NumOfBdrElements == 0)
2443 GetElementToFaceTable();
2445 GenerateBoundaryElements();
2448 GetElementToFaceTable();
2451 CheckBdrElementOrientation();
2453 if (generate_edges == 1)
2455 el_to_edge =
new Table;
2456 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2470 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
2473 CheckElementOrientation(fix_orientation);
2475 GetElementToFaceTable();
2478 if (NumOfBdrElements == 0)
2480 GenerateBoundaryElements();
2483 CheckBdrElementOrientation();
2487 el_to_edge =
new Table;
2488 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2500 void Mesh::FinalizeMesh(
int refine,
bool fix_orientation)
2504 Finalize(refine, fix_orientation);
2507 void Mesh::FinalizeTopology(
bool generate_bdr)
2519 bool generate_edges =
true;
2521 if (spaceDim == 0) { spaceDim = Dim; }
2522 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2526 if (tmp_vertex_parents.Size())
2528 MFEM_VERIFY(ncmesh == NULL,
"");
2529 ncmesh =
new NCMesh(
this);
2533 InitFromNCMesh(*ncmesh);
2534 ncmesh->OnMeshUpdated(
this);
2535 GenerateNCFaceInfo();
2539 tmp_vertex_parents.DeleteAll();
2549 GetElementToFaceTable();
2551 if (NumOfBdrElements == 0 && generate_bdr)
2553 GenerateBoundaryElements();
2554 GetElementToFaceTable();
2563 if (Dim > 1 && generate_edges)
2566 if (!el_to_edge) { el_to_edge =
new Table; }
2567 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2571 if (NumOfBdrElements == 0 && generate_bdr)
2573 GenerateBoundaryElements();
2590 ncmesh->OnMeshUpdated(
this);
2593 GenerateNCFaceInfo();
2600 void Mesh::Finalize(
bool refine,
bool fix_orientation)
2602 if (NURBSext || ncmesh)
2604 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
2605 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
2614 const bool check_orientation =
true;
2615 const bool curved = (Nodes != NULL);
2616 const bool may_change_topology =
2617 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
2618 ( check_orientation && fix_orientation &&
2619 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
2622 Table *old_elem_vert = NULL;
2624 if (curved && may_change_topology)
2626 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
2629 if (check_orientation)
2632 CheckElementOrientation(fix_orientation);
2636 MarkForRefinement();
2639 if (may_change_topology)
2643 DoNodeReorder(old_v_to_v, old_elem_vert);
2644 delete old_elem_vert;
2657 CheckBdrElementOrientation();
2662 if (Dim >= 2 && Dim == spaceDim)
2664 const int num_faces = GetNumFaces();
2665 for (
int i = 0; i < num_faces; i++)
2667 MFEM_VERIFY(faces_info[i].Elem2No < 0 ||
2668 faces_info[i].Elem2Inf%2 != 0,
"Invalid mesh topology."
2669 " Interior face with incompatible orientations.");
2676 double sx,
double sy,
double sz,
bool sfc_ordering)
2680 int NVert, NElem, NBdrElem;
2682 NVert = (nx+1) * (ny+1) * (nz+1);
2683 NElem = nx * ny * nz;
2684 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
2685 if (type == Element::TETRAHEDRON)
2690 else if (type == Element::WEDGE)
2693 NBdrElem += 2*nx*ny;
2696 InitMesh(3, 3, NVert, NElem, NBdrElem);
2702 for (z = 0; z <= nz; z++)
2704 coord[2] = ((double) z / nz) * sz;
2705 for (y = 0; y <= ny; y++)
2707 coord[1] = ((double) y / ny) * sy;
2708 for (x = 0; x <= nx; x++)
2710 coord[0] = ((double) x / nx) * sx;
2716 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
2719 if (sfc_ordering && type == Element::HEXAHEDRON)
2722 NCMesh::GridSfcOrdering3D(nx, ny, nz, sfc);
2723 MFEM_VERIFY(sfc.
Size() == 3*nx*ny*nz,
"");
2725 for (
int k = 0; k < nx*ny*nz; k++)
2731 ind[0] = VTX(x , y , z );
2732 ind[1] = VTX(x+1, y , z );
2733 ind[2] = VTX(x+1, y+1, z );
2734 ind[3] = VTX(x , y+1, z );
2735 ind[4] = VTX(x , y , z+1);
2736 ind[5] = VTX(x+1, y , z+1);
2737 ind[6] = VTX(x+1, y+1, z+1);
2738 ind[7] = VTX(x , y+1, z+1);
2745 for (z = 0; z < nz; z++)
2747 for (y = 0; y < ny; y++)
2749 for (x = 0; x < nx; x++)
2751 ind[0] = VTX(x , y , z );
2752 ind[1] = VTX(x+1, y , z );
2753 ind[2] = VTX(x+1, y+1, z );
2754 ind[3] = VTX(x , y+1, z );
2755 ind[4] = VTX(x , y , z+1);
2756 ind[5] = VTX(x+1, y , z+1);
2757 ind[6] = VTX(x+1, y+1, z+1);
2758 ind[7] = VTX( x, y+1, z+1);
2759 if (type == Element::TETRAHEDRON)
2761 AddHexAsTets(ind, 1);
2763 else if (type == Element::WEDGE)
2765 AddHexAsWedges(ind, 1);
2778 for (y = 0; y < ny; y++)
2780 for (x = 0; x < nx; x++)
2782 ind[0] = VTX(x , y , 0);
2783 ind[1] = VTX(x , y+1, 0);
2784 ind[2] = VTX(x+1, y+1, 0);
2785 ind[3] = VTX(x+1, y , 0);
2786 if (type == Element::TETRAHEDRON)
2788 AddBdrQuadAsTriangles(ind, 1);
2790 else if (type == Element::WEDGE)
2792 AddBdrQuadAsTriangles(ind, 1);
2801 for (y = 0; y < ny; y++)
2803 for (x = 0; x < nx; x++)
2805 ind[0] = VTX(x , y , nz);
2806 ind[1] = VTX(x+1, y , nz);
2807 ind[2] = VTX(x+1, y+1, nz);
2808 ind[3] = VTX(x , y+1, nz);
2809 if (type == Element::TETRAHEDRON)
2811 AddBdrQuadAsTriangles(ind, 6);
2813 else if (type == Element::WEDGE)
2815 AddBdrQuadAsTriangles(ind, 1);
2824 for (z = 0; z < nz; z++)
2826 for (y = 0; y < ny; y++)
2828 ind[0] = VTX(0 , y , z );
2829 ind[1] = VTX(0 , y , z+1);
2830 ind[2] = VTX(0 , y+1, z+1);
2831 ind[3] = VTX(0 , y+1, z );
2832 if (type == Element::TETRAHEDRON)
2834 AddBdrQuadAsTriangles(ind, 5);
2843 for (z = 0; z < nz; z++)
2845 for (y = 0; y < ny; y++)
2847 ind[0] = VTX(nx, y , z );
2848 ind[1] = VTX(nx, y+1, z );
2849 ind[2] = VTX(nx, y+1, z+1);
2850 ind[3] = VTX(nx, y , z+1);
2851 if (type == Element::TETRAHEDRON)
2853 AddBdrQuadAsTriangles(ind, 3);
2862 for (x = 0; x < nx; x++)
2864 for (z = 0; z < nz; z++)
2866 ind[0] = VTX(x , 0, z );
2867 ind[1] = VTX(x+1, 0, z );
2868 ind[2] = VTX(x+1, 0, z+1);
2869 ind[3] = VTX(x , 0, z+1);
2870 if (type == Element::TETRAHEDRON)
2872 AddBdrQuadAsTriangles(ind, 2);
2881 for (x = 0; x < nx; x++)
2883 for (z = 0; z < nz; z++)
2885 ind[0] = VTX(x , ny, z );
2886 ind[1] = VTX(x , ny, z+1);
2887 ind[2] = VTX(x+1, ny, z+1);
2888 ind[3] = VTX(x+1, ny, z );
2889 if (type == Element::TETRAHEDRON)
2891 AddBdrQuadAsTriangles(ind, 4);
2903 ofstream test_stream(
"debug.mesh");
2905 test_stream.close();
2914 double sx,
double sy,
2915 bool generate_edges,
bool sfc_ordering)
2924 if (type == Element::QUADRILATERAL)
2926 NumOfVertices = (nx+1) * (ny+1);
2927 NumOfElements = nx * ny;
2928 NumOfBdrElements = 2 * nx + 2 * ny;
2930 vertices.SetSize(NumOfVertices);
2931 elements.SetSize(NumOfElements);
2932 boundary.SetSize(NumOfBdrElements);
2939 for (j = 0; j < ny+1; j++)
2941 cy = ((double) j / ny) * sy;
2942 for (i = 0; i < nx+1; i++)
2944 cx = ((double) i / nx) * sx;
2945 vertices[k](0) = cx;
2946 vertices[k](1) = cy;
2955 NCMesh::GridSfcOrdering2D(nx, ny, sfc);
2956 MFEM_VERIFY(sfc.
Size() == 2*nx*ny,
"");
2958 for (k = 0; k < nx*ny; k++)
2962 ind[0] = i + j*(nx+1);
2963 ind[1] = i + 1 +j*(nx+1);
2964 ind[2] = i + 1 + (j+1)*(nx+1);
2965 ind[3] = i + (j+1)*(nx+1);
2972 for (j = 0; j < ny; j++)
2974 for (i = 0; i < nx; i++)
2976 ind[0] = i + j*(nx+1);
2977 ind[1] = i + 1 +j*(nx+1);
2978 ind[2] = i + 1 + (j+1)*(nx+1);
2979 ind[3] = i + (j+1)*(nx+1);
2988 for (i = 0; i < nx; i++)
2990 boundary[i] =
new Segment(i, i+1, 1);
2991 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2994 for (j = 0; j < ny; j++)
2996 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2997 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3001 else if (type == Element::TRIANGLE)
3003 NumOfVertices = (nx+1) * (ny+1);
3004 NumOfElements = 2 * nx * ny;
3005 NumOfBdrElements = 2 * nx + 2 * ny;
3007 vertices.SetSize(NumOfVertices);
3008 elements.SetSize(NumOfElements);
3009 boundary.SetSize(NumOfBdrElements);
3016 for (j = 0; j < ny+1; j++)
3018 cy = ((double) j / ny) * sy;
3019 for (i = 0; i < nx+1; i++)
3021 cx = ((double) i / nx) * sx;
3022 vertices[k](0) = cx;
3023 vertices[k](1) = cy;
3030 for (j = 0; j < ny; j++)
3032 for (i = 0; i < nx; i++)
3034 ind[0] = i + j*(nx+1);
3035 ind[1] = i + 1 + (j+1)*(nx+1);
3036 ind[2] = i + (j+1)*(nx+1);
3039 ind[1] = i + 1 + j*(nx+1);
3040 ind[2] = i + 1 + (j+1)*(nx+1);
3048 for (i = 0; i < nx; i++)
3050 boundary[i] =
new Segment(i, i+1, 1);
3051 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
3054 for (j = 0; j < ny; j++)
3056 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
3057 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
3064 MFEM_ABORT(
"Unsupported element type.");
3068 CheckElementOrientation();
3070 if (generate_edges == 1)
3072 el_to_edge =
new Table;
3073 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3075 CheckBdrElementOrientation();
3084 attributes.Append(1);
3085 bdr_attributes.Append(1); bdr_attributes.Append(2);
3086 bdr_attributes.Append(3); bdr_attributes.Append(4);
3091 void Mesh::Make1D(
int n,
double sx)
3100 NumOfVertices = n + 1;
3102 NumOfBdrElements = 2;
3103 vertices.SetSize(NumOfVertices);
3104 elements.SetSize(NumOfElements);
3105 boundary.SetSize(NumOfBdrElements);
3108 for (j = 0; j < n+1; j++)
3110 vertices[j](0) = ((
double) j / n) * sx;
3114 for (j = 0; j < n; j++)
3116 elements[j] =
new Segment(j, j+1, 1);
3121 boundary[0] =
new Point(ind, 1);
3123 boundary[1] =
new Point(ind, 2);
3131 attributes.Append(1);
3132 bdr_attributes.Append(1); bdr_attributes.Append(2);
3135 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
3153 last_operation = Mesh::NONE;
3156 elements.SetSize(NumOfElements);
3157 for (
int i = 0; i < NumOfElements; i++)
3159 elements[i] = mesh.
elements[i]->Duplicate(
this);
3166 boundary.SetSize(NumOfBdrElements);
3167 for (
int i = 0; i < NumOfBdrElements; i++)
3169 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
3188 faces.SetSize(mesh.
faces.Size());
3189 for (
int i = 0; i < faces.Size(); i++)
3192 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
3226 if (dynamic_cast<const ParMesh*>(&mesh))
3238 if (mesh.
Nodes && copy_nodes)
3243 FiniteElementCollection::New(fec->
Name());
3247 Nodes->MakeOwner(fec_copy);
3248 *Nodes = *mesh.
Nodes;
3270 bool fix_orientation)
3274 if (!imesh) { MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n'); }
3275 else { mesh.
Load(imesh, generate_edges, refine, fix_orientation); }
3289 double sx,
double sy,
bool sfc_ordering)
3292 mesh.
Make2D(nx, ny, type, sx, sy, generate_edges, sfc_ordering);
3299 double sx,
double sy,
double sz,
bool sfc_ordering)
3302 mesh.
Make3D(nx, ny, nz, type, sx, sy, sz, sfc_ordering);
3311 ref_factors = ref_factor;
3325 bool fix_orientation)
3334 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
3338 Load(imesh, generate_edges, refine, fix_orientation);
3343 bool fix_orientation)
3346 Load(input, generate_edges, refine, fix_orientation);
3355 "Not enough vertices in external array : "
3356 "len_vertex_data = "<< len_vertex_data <<
", "
3359 if (vertex_data == (
double *)(
vertices.GetData()))
3361 MFEM_ASSERT(!
vertices.OwnsData(),
"invalid ownership");
3366 memcpy(vertex_data,
vertices.GetData(),
3375 int *element_attributes,
int num_elements,
3377 int *boundary_attributes,
int num_boundary_elements,
3378 int dimension,
int space_dimension)
3380 if (space_dimension == -1)
3382 space_dimension = dimension;
3385 InitMesh(dimension, space_dimension, 0, num_elements,
3386 num_boundary_elements);
3389 int boundary_index_stride = num_boundary_elements > 0 ?
3393 vertices.MakeRef(reinterpret_cast<Vertex*>(vertices_), num_vertices);
3396 for (
int i = 0; i < num_elements; i++)
3399 elements[i]->SetVertices(element_indices + i * element_index_stride);
3400 elements[i]->SetAttribute(element_attributes[i]);
3404 for (
int i = 0; i < num_boundary_elements; i++)
3407 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
3408 boundary[i]->SetAttribute(boundary_attributes[i]);
3424 #ifdef MFEM_USE_MEMALLOC
3432 MFEM_ABORT(
"invalid Geometry::Type, geom = " << geom);
3445 MFEM_VERIFY(el,
"Unsupported element type: " << geom);
3448 for (
int i = 0; i < nv; i++)
3461 for (
int j = 0; j < nv; j++)
3524 MFEM_ABORT(
"invalid element type: " << type);
3531 std::string parse_tag)
3533 int curved = 0, read_gf = 1;
3534 bool finalize_topo =
true;
3538 MFEM_ABORT(
"Input stream is not open");
3545 getline(input, mesh_type);
3549 int mfem_version = 0;
3550 if (mesh_type ==
"MFEM mesh v1.0") { mfem_version = 10; }
3551 else if (mesh_type ==
"MFEM mesh v1.2") { mfem_version = 12; }
3555 int mfem_nc_version = 0;
3556 if (mesh_type ==
"MFEM NC mesh v1.0") { mfem_nc_version = 10; }
3557 else if (mesh_type ==
"MFEM mesh v1.1") { mfem_nc_version = 1 ; }
3565 if (mfem_version == 12 && parse_tag.empty())
3567 parse_tag =
"mfem_mesh_end";
3571 else if (mfem_nc_version)
3573 MFEM_ASSERT(
ncmesh == NULL,
"internal error");
3580 MFEM_VERIFY(mfem_nc_version >= 10,
3581 "Legacy nonconforming format (MFEM mesh v1.1) cannot be "
3582 "used to load a parallel nonconforming mesh, sorry.");
3585 input, mfem_nc_version, curved, is_nc);
3590 ncmesh =
new NCMesh(input, mfem_nc_version, curved, is_nc);
3603 else if (mesh_type ==
"linemesh")
3607 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
3609 if (mesh_type ==
"curved_areamesh2")
3615 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
3619 else if (mesh_type ==
"TrueGrid")
3623 else if (mesh_type.rfind(
"# vtk DataFile Version") == 0)
3625 int major_vtk_version = mesh_type[mesh_type.length()-3] -
'0';
3627 MFEM_VERIFY(major_vtk_version >= 2 && major_vtk_version <= 4,
3628 "Unsupported VTK format");
3629 ReadVTKMesh(input, curved, read_gf, finalize_topo);
3631 else if (mesh_type.rfind(
"<VTKFile ") == 0 || mesh_type.rfind(
"<?xml") == 0)
3635 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
3639 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
3644 else if (mesh_type ==
"$MeshFormat")
3649 ((mesh_type.size() > 2 &&
3650 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
3651 (mesh_type.size() > 3 &&
3652 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
3657 #ifdef MFEM_USE_NETCDF
3660 MFEM_ABORT(
"NetCDF support requires configuration with"
3661 " MFEM_USE_NETCDF=YES");
3667 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
3668 " Use mfem::named_ifgzstream for input.");
3674 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
3700 bool generate_bdr =
false;
3705 if (curved && read_gf)
3719 if (mfem_version == 12)
3725 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
3726 getline(input, line);
3732 if (line ==
"mfem_mesh_end") {
break; }
3734 while (line != parse_tag);
3736 else if (mfem_nc_version >= 10)
3741 MFEM_VERIFY(ident ==
"mfem_mesh_end",
3742 "invalid mesh: end of file tag not found");
3750 int i, j, ie, ib, iv, *v, nv;
3781 for (i = 0; i < num_pieces; i++)
3788 for (i = 0; i < num_pieces; i++)
3794 for (j = 0; j < m->
GetNE(); j++)
3799 for (j = 0; j < m->
GetNBE(); j++)
3804 for (
int k = 0; k < nv; k++)
3806 v[k] = lvert_vert[v[k]];
3811 for (j = 0; j < m->
GetNV(); j++)
3823 for (i = 0; i < num_pieces; i++)
3834 for (i = 0; i < num_pieces; i++)
3838 for (j = 0; j < m->
GetNE(); j++)
3843 for (
int k = 0; k < nv; k++)
3850 for (j = 0; j < m->
GetNBE(); j++)
3855 for (
int k = 0; k < nv; k++)
3862 for (j = 0; j < m->
GetNV(); j++)
3876 for (i = 0; i < num_pieces; i++)
3878 gf_array[i] = mesh_array[i]->
GetNodes();
3893 ref_factors = ref_factor;
3904 int orig_ne = orig_mesh.
GetNE();
3905 MFEM_VERIFY(ref_factors.
Size() == orig_ne && orig_ne > 0,
3906 "Number of refinement factors must equal number of elements")
3907 MFEM_VERIFY(ref_factors.
Min() >= 1,
"Refinement factor must be >= 1");
3910 "Invalid refinement type. Must use closed basis type.");
3912 int min_ref = ref_factors.
Min();
3913 int max_ref = ref_factors.
Max();
3915 bool var_order = (min_ref != max_ref);
3928 for (
int i = 0; i < orig_ne; i++)
3946 for (
int el = 0; el < orig_ne; el++)
3958 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[el]);
3959 for (
int i = 0; i < phys_pts.
Width(); i++)
3968 for (
int k = 0; k < nvert; k++)
3971 v[k] = rdofs[c2h_map[cid]];
3978 for (
int el = 0; el < orig_mesh.
GetNBE(); el++)
3989 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[i]);
3995 for (
int k = 0; k < nvert; k++)
3998 v[k] = rdofs[c2h_map[cid]];
4020 for (
int iel = 0; iel < orig_ne; iel++)
4029 const int *node_map = NULL;
4032 if (h1_fec != NULL) { node_map = h1_fec->
GetDofMap(geom); }
4033 const int *vertex_map = vertex_fec.
GetDofMap(geom);
4034 const int *c2h_map = rfec.
GetDofMap(geom, ref_factors[iel]);
4035 for (
int jel = 0; jel < RG.
RefGeoms.
Size()/nvert; jel++)
4038 for (
int iv_lex=0; iv_lex<nvert; ++iv_lex)
4041 int iv = vertex_map[iv_lex];
4043 int pt_idx = c2h_map[RG.
RefGeoms[iv+nvert*jel]];
4045 int node_idx = node_map ? node_map[iv_lex] : iv_lex;
4048 (*Nodes)[dofs[node_idx + d*nvert]] = phys_pts(d,pt_idx);
4059 using GeomRef = std::pair<Geometry::Type, int>;
4060 std::map<GeomRef, int> point_matrices_offsets;
4062 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4066 GeomRef id(geom, ref_factors[el_coarse]);
4067 if (point_matrices_offsets.find(
id) == point_matrices_offsets.end())
4073 point_matrices_offsets[id] = n_point_matrices[
geom];
4074 n_point_matrices[
geom] += nref_el;
4081 int nmatrices = n_point_matrices[
geom];
4088 for (
int el_coarse = 0; el_coarse < orig_ne; ++el_coarse)
4091 int ref = ref_factors[el_coarse];
4092 int offset = point_matrices_offsets[GeomRef(geom, ref)];
4098 for (
int k = 0; k < nvert; k++)
4130 "Mesh::MakeSimplicial requires a properly oriented input mesh");
4132 "Mesh::MakeSimplicial does not support non-conforming meshes.")
4139 Mesh copy(orig_mesh);
4144 int nv = orig_mesh.
GetNV();
4145 int ne = orig_mesh.
GetNE();
4146 int nbe = orig_mesh.
GetNBE();
4159 int new_ne = 0, new_nbe = 0;
4160 for (
int i=0; i<ne; ++i)
4164 for (
int i=0; i<nbe; ++i)
4173 for (
int i=0; i<nv; ++i)
4183 if (vglobal == NULL)
4186 for (
int i=0; i<nv; ++i) { vglobal_id[i] = i; }
4187 vglobal = vglobal_id.
GetData();
4190 constexpr
int nv_tri = 3, nv_quad = 4, nv_tet = 4, nv_prism = 6, nv_hex = 8;
4191 constexpr
int quad_ntris = 2, prism_ntets = 3;
4192 static const int quad_trimap[2][nv_tri*quad_ntris] =
4204 static const int prism_rot[nv_prism*nv_prism] =
4213 static const int prism_f[nv_quad] = {1, 2, 5, 4};
4214 static const int prism_tetmaps[2][nv_prism*prism_ntets] =
4228 static const int hex_rot[nv_hex*nv_hex] =
4230 0, 1, 2, 3, 4, 5, 6, 7,
4231 1, 0, 4, 5, 2, 3, 7, 6,
4232 2, 1, 5, 6, 3, 0, 4, 7,
4233 3, 0, 1, 2, 7, 4, 5, 6,
4234 4, 0, 3, 7, 5, 1, 2, 6,
4235 5, 1, 0, 4, 6, 2, 3, 7,
4236 6, 2, 1, 5, 7, 3, 0, 4,
4237 7, 3, 2, 6, 4, 0, 1, 5
4239 static const int hex_f0[nv_quad] = {1, 2, 6, 5};
4240 static const int hex_f1[nv_quad] = {2, 3, 7, 6};
4241 static const int hex_f2[nv_quad] = {4, 5, 6, 7};
4242 static const int num_rot[8] = {0, 1, 2, 0, 0, 2, 1, 0};
4243 static const int hex_tetmap0[nv_tet*5] =
4250 static const int hex_tetmap1[nv_tet*6] =
4257 static const int hex_tetmap2[nv_tet*6] =
4264 static const int hex_tetmap3[nv_tet*6] =
4271 static const int *hex_tetmaps[4] =
4273 hex_tetmap0, hex_tetmap1, hex_tetmap2, hex_tetmap3
4276 auto find_min = [](
const int*
a,
int n) {
return std::min_element(a,a+n)-
a; };
4278 for (
int i=0; i<ne; ++i)
4280 const int *v = orig_mesh.
elements[i]->GetVertices();
4284 if (num_subdivisions[orig_geom] == 1)
4296 for (
int itri=0; itri<quad_ntris; ++itri)
4301 for (
int iv=0; iv<nv_tri; ++iv)
4303 v2[iv] = v[quad_trimap[0][itri + iv*quad_ntris]];
4311 for (
int iv=0; iv<nv_prism; ++iv) { vg[iv] = vglobal[v[iv]]; }
4314 int irot = find_min(vg, nv_prism);
4315 for (
int iv=0; iv<nv_prism; ++iv)
4317 int jv = prism_rot[iv + irot*nv_prism];
4322 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[prism_f[iv]]]; }
4323 int j = find_min(q, nv_quad);
4324 const int *tetmap = (j == 0 || j == 2) ? prism_tetmaps[0] : prism_tetmaps[1];
4325 for (
int itet=0; itet<prism_ntets; ++itet)
4330 for (
int iv=0; iv<nv_tet; ++iv)
4332 v2[iv] = vg[tetmap[itet + iv*prism_ntets]];
4340 for (
int iv=0; iv<nv_hex; ++iv) { vg[iv] = vglobal[v[iv]]; }
4344 int irot = find_min(vg, nv_hex);
4345 for (
int iv=0; iv<nv_hex; ++iv)
4347 int jv = hex_rot[iv + irot*nv_hex];
4357 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f0[iv]]]; }
4358 j = find_min(q, nv_quad);
4359 if (j == 0 || j == 2) { bitmask += 4; }
4361 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f1[iv]]]; }
4362 j = find_min(q, nv_quad);
4363 if (j == 1 || j == 3) { bitmask += 2; }
4365 for (
int iv=0; iv<nv_quad; ++iv) { q[iv] = vglobal[vg[hex_f2[iv]]]; }
4366 j = find_min(q, nv_quad);
4367 if (j == 0 || j == 2) { bitmask += 1; }
4370 int nrot = num_rot[bitmask];
4371 for (
int irot=0; irot<nrot; ++irot)
4385 int ndiags = ((bitmask&4) >> 2) + ((bitmask&2) >> 1) + (bitmask&1);
4386 int ntets = (ndiags == 0) ? 5 : 6;
4387 const int *tetmap = hex_tetmaps[ndiags];
4388 for (
int itet=0; itet<ntets; ++itet)
4393 for (
int iv=0; iv<nv_tet; ++iv)
4395 v2[iv] = vg[tetmap[itet + iv*ntets]];
4404 for (
int i=0; i<nbe; ++i)
4406 const int *v = orig_mesh.
boundary[i]->GetVertices();
4409 if (num_subdivisions[orig_geom] == 1)
4419 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
4421 int iv_min = find_min(vg, nv_quad);
4422 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
4423 for (
int itri=0; itri<quad_ntris; ++itri)
4428 for (
int iv=0; iv<nv_tri; ++iv)
4430 v2[iv] = v[quad_trimap[isplit][itri + iv*quad_ntris]];
4437 MFEM_ABORT(
"Unreachable");
4451 Mesh periodic_mesh(orig_mesh,
true);
4457 for (
int i = 0; i < periodic_mesh.
GetNE(); i++)
4462 for (
int j = 0; j < nv; j++)
4468 for (
int i = 0; i < periodic_mesh.
GetNBE(); i++)
4473 for (
int j = 0; j < nv; j++)
4480 return periodic_mesh;
4484 const std::vector<Vector> &translations,
double tol)
const
4488 Vector coord(sdim), at(sdim), dx(sdim);
4489 Vector xMax(sdim), xMin(sdim), xDiff(sdim);
4490 xMax = xMin = xDiff = 0.0;
4494 for (
int be = 0; be <
GetNBE(); be++)
4499 for (
int i = 0; i < dofs.
Size(); i++)
4501 bdr_v.insert(dofs[i]);
4504 for (
int j = 0; j < sdim; j++)
4506 xMax[j] = max(xMax[j], coord[j]);
4507 xMin[j] = min(xMin[j], coord[j]);
4511 add(xMax, -1.0, xMin, xDiff);
4512 double dia = xDiff.
Norml2();
4520 map<int, int> replica2primary;
4522 map<int, set<int>> primary2replicas;
4526 for (
int v : bdr_v) { primary2replicas[v]; }
4530 auto make_replica = [&replica2primary, &primary2replicas](
int r,
int p)
4532 if (r ==
p) {
return; }
4533 primary2replicas[
p].insert(r);
4534 replica2primary[r] =
p;
4535 for (
int s : primary2replicas[r])
4537 primary2replicas[
p].insert(
s);
4538 replica2primary[
s] =
p;
4540 primary2replicas.erase(r);
4543 for (
unsigned int i = 0; i < translations.size(); i++)
4545 for (
int vi : bdr_v)
4548 add(coord, translations[i], at);
4550 for (
int vj : bdr_v)
4553 add(at, -1.0, coord, dx);
4554 if (dx.
Norml2() > dia*tol) {
continue; }
4559 bool pi = primary2replicas.find(vi) != primary2replicas.end();
4560 bool pj = primary2replicas.find(vj) != primary2replicas.end();
4566 make_replica(vj, vi);
4571 int owner_of_vj = replica2primary[vj];
4573 make_replica(vi, owner_of_vj);
4579 int owner_of_vi = replica2primary[vi];
4580 make_replica(vj, owner_of_vi);
4587 int owner_of_vi = replica2primary[vi];
4588 int owner_of_vj = replica2primary[vj];
4589 make_replica(owner_of_vj, owner_of_vi);
4596 std::vector<int> v2v(
GetNV());
4597 for (
size_t i = 0; i < v2v.size(); i++)
4601 for (
auto &&r2p : replica2primary)
4603 v2v[r2p.first] = r2p.second;
4612 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
4617 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
4634 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
4639 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
4669 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
4693 for (
int i = 0; i <
elements.Size(); i++)
4703 for (
int i = 0; i <
boundary.Size(); i++)
4720 for (
int i = 0; i < vd; i++)
4774 boundary.SetSize(NumOfBdrElements);
4785 edge_to_knot.
SetSize(NumOfEdges);
4789 input >> edge_to_knot[j] >> v[0] >> v[1];
4792 edge_to_knot[j] = -1 - edge_to_knot[j];
4810 for (
int d = 0; d < v.
Size(); d++)
4818 for (d = 0; d < p.
Size(); d++)
4822 for ( ; d < v.
Size(); d++)
4854 if (dynamic_cast<const H1_FECollection*>(fec)
4855 || dynamic_cast<const L2_FECollection*>(fec))
4884 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
4903 MFEM_ASSERT(nodes != NULL,
"");
4919 case 1:
return GetNV();
4926 static int CountFacesByType(
const Mesh &mesh,
const FaceType type)
4945 if (nf<0) { nf = CountFacesByType(*
this, type); }
4949 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
4950 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
4955 int i, j, k, wo = 0, fo = 0;
4964 int *vi =
elements[i]->GetVertices();
4967 for (j = 0; j < 3; j++)
4971 for (j = 0; j < 2; j++)
4972 for (k = 0; k < 2; k++)
4974 J(j, k) = v[j+1][k] - v[0][k];
4995 MFEM_ABORT(
"Invalid 2D element type \""
5012 int *vi =
elements[i]->GetVertices();
5018 for (j = 0; j < 4; j++)
5022 for (j = 0; j < 3; j++)
5023 for (k = 0; k < 3; k++)
5025 J(j, k) = v[j+1][k] - v[0][k];
5071 MFEM_ABORT(
"Invalid 3D element type \""
5077 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
5080 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / "
5081 <<
NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
5096 if (test[0] == base[0])
5097 if (test[1] == base[1])
5105 else if (test[0] == base[1])
5106 if (test[1] == base[0])
5115 if (test[1] == base[0])
5126 for (
int j = 0; j < 3; j++)
5127 if (test[aor[j]] != base[j])
5140 for (i = 0; i < 4; i++)
5141 if (test[i] == base[0])
5148 if (test[(i+1)%4] == base[1])
5157 for (
int j = 0; j < 4; j++)
5158 if (test[aor[j]] != base[j])
5160 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
5162 for (
int k = 0; k < 4; k++)
5167 for (
int k = 0; k < 4; k++)
5176 if (test[(i+1)%4] == base[1])
5192 if (test[0] == base[0])
5193 if (test[1] == base[1])
5194 if (test[2] == base[2])
5202 else if (test[2] == base[1])
5203 if (test[3] == base[2])
5212 if (test[1] == base[2])
5220 else if (test[1] == base[0])
5221 if (test[2] == base[1])
5222 if (test[0] == base[2])
5230 else if (test[3] == base[1])
5231 if (test[2] == base[2])
5240 if (test[3] == base[2])
5248 else if (test[2] == base[0])
5249 if (test[3] == base[1])
5250 if (test[0] == base[2])
5258 else if (test[0] == base[1])
5259 if (test[1] == base[2])
5268 if (test[3] == base[2])
5277 if (test[0] == base[1])
5278 if (test[2] == base[2])
5286 else if (test[1] == base[1])
5287 if (test[0] == base[2])
5296 if (test[1] == base[2])
5307 for (
int j = 0; j < 4; j++)
5308 if (test[aor[j]] != base[j])
5333 int *bv =
boundary[i]->GetVertices();
5339 mfem::Swap<int>(bv[0], bv[1]);
5353 if (
faces_info[fi].Elem2No >= 0) {
continue; }
5356 int *bv =
boundary[i]->GetVertices();
5358 MFEM_ASSERT(fi <
faces.Size(),
"internal error");
5359 const int *fv =
faces[fi]->GetVertices();
5376 MFEM_ABORT(
"Invalid 2D boundary element type \""
5377 << bdr_type <<
"\"");
5382 if (orientation % 2 == 0) {
continue; }
5384 if (!fix_it) {
continue; }
5392 mfem::Swap<int>(bv[0], bv[1]);
5396 mfem::Swap<int>(be[1], be[2]);
5402 mfem::Swap<int>(bv[0], bv[2]);
5406 mfem::Swap<int>(be[0], be[1]);
5407 mfem::Swap<int>(be[2], be[3]);
5420 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / "
5430 MFEM_ASSERT(0 <= dim && dim <=
Dim,
"invalid dim: " << dim);
5441 MFEM_ASSERT(0 <= dim && dim <=
Dim,
"invalid dim: " << dim);
5460 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
5461 "is not generated.");
5464 const int *v =
elements[i]->GetVertices();
5465 const int ne =
elements[i]->GetNEdges();
5467 for (
int j = 0; j < ne; j++)
5469 const int *e =
elements[i]->GetEdgeVertices(j);
5470 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5481 const int *v =
boundary[i]->GetVertices();
5482 cor[0] = (v[0] < v[1]) ? (1) : (-1);
5495 const int *v =
boundary[i]->GetVertices();
5496 const int ne =
boundary[i]->GetNEdges();
5498 for (
int j = 0; j < ne; j++)
5500 const int *e =
boundary[i]->GetEdgeVertices(j);
5501 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5513 const int *v =
faces[i]->GetVertices();
5514 o[0] = (v[0] < v[1]) ? (1) : (-1);
5526 const int *v =
faces[i]->GetVertices();
5527 const int ne =
faces[i]->GetNEdges();
5529 for (
int j = 0; j < ne; j++)
5531 const int *e =
faces[i]->GetEdgeVertices(j);
5532 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
5560 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
5611 for (j = 0; j < nv; j++)
5623 for (j = 0; j < nv; j++)
5670 MFEM_VERIFY(
el_to_face != NULL,
"el_to_face not generated");
5674 int n = faces.
Size();
5677 for (
int j = 0; j < n; j++)
5685 MFEM_ASSERT(
faces_info[faces[j]].Elem2No == i,
"internal error");
5710 MFEM_ABORT(
"invalid geometry");
5718 case 1:
return boundary[i]->GetVertices()[0];
5721 default: MFEM_ABORT(
"invalid dimension!");
5731 MFEM_ASSERT(fi.
Elem1Inf % 64 == 0,
"internal error");
5734 const int *bv =
boundary[bdr_el]->GetVertices();
5742 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
5769 for (j = 0; j < nv; j++)
5771 pointmat(k, j) =
vertices[v[j]](k);
5786 for (j = 0; j < nv; j++)
5788 pointmat(k, j) =
vertices[v[j]](k);
5800 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
5803 return sqrt(length);
5811 for (
int i = 0; i < elem_array.
Size(); i++)
5816 for (
int i = 0; i < elem_array.
Size(); i++)
5818 const int *v = elem_array[i]->GetVertices();
5819 const int ne = elem_array[i]->GetNEdges();
5820 for (
int j = 0; j < ne; j++)
5822 const int *e = elem_array[i]->GetEdgeVertices(j);
5836 v_to_v.
Push(v[0], v[1]);
5843 const int *v =
elements[i]->GetVertices();
5844 const int ne =
elements[i]->GetNEdges();
5845 for (
int j = 0; j < ne; j++)
5847 const int *e =
elements[i]->GetEdgeVertices(j);
5848 v_to_v.
Push(v[e[0]], v[e[1]]);
5856 int i, NumberOfEdges;
5872 const int *v =
boundary[i]->GetVertices();
5873 be_to_f[i] = v_to_v(v[0], v[1]);
5886 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
5890 return NumberOfEdges;
5981 if (
faces[gf] == NULL)
5991 MFEM_VERIFY(
faces_info[gf].Elem2No < 0,
"Invalid mesh topology. "
5992 "Interior edge found between 2D elements "
5994 <<
" and " << el <<
".");
5995 int *v =
faces[gf]->GetVertices();
5997 if ( v[1] == v0 && v[0] == v1 )
6001 else if ( v[0] == v0 && v[1] == v1 )
6011 MFEM_ABORT(
"internal error");
6017 int v0,
int v1,
int v2)
6019 if (
faces[gf] == NULL)
6029 MFEM_VERIFY(
faces_info[gf].Elem2No < 0,
"Invalid mesh topology. "
6030 "Interior triangular face found connecting elements "
6032 <<
" and " << el <<
".");
6033 int orientation, vv[3] = { v0, v1, v2 };
6040 faces_info[gf].Elem2Inf = 64 * lf + orientation;
6045 int v0,
int v1,
int v2,
int v3)
6057 MFEM_VERIFY(
faces_info[gf].Elem2No < 0,
"Invalid mesh topology. "
6058 "Interior quadrilateral face found connecting elements "
6060 <<
" and " << el <<
".");
6061 int vv[4] = { v0, v1, v2, v3 };
6075 for (i = 0; i <
faces.Size(); i++)
6081 faces.SetSize(nfaces);
6083 for (i = 0; i < nfaces; i++)
6091 const int *v =
elements[i]->GetVertices();
6101 const int ne =
elements[i]->GetNEdges();
6102 for (
int j = 0; j < ne; j++)
6104 const int *e =
elements[i]->GetEdgeVertices(j);
6115 for (
int j = 0; j < 4; j++)
6119 v[fv[0]], v[fv[1]], v[fv[2]]);
6125 for (
int j = 0; j < 2; j++)
6129 v[fv[0]], v[fv[1]], v[fv[2]]);
6131 for (
int j = 2; j < 5; j++)
6135 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
6141 for (
int j = 0; j < 6; j++)
6145 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
6150 MFEM_ABORT(
"Unexpected type of Element.");
6158 MFEM_VERIFY(
ncmesh,
"missing NCMesh.");
6174 for (
int i = 0; i < list.
masters.Size(); i++)
6177 if (master.
index >= nfaces) {
continue; }
6185 for (
int i = 0; i < list.
slaves.Size(); i++)
6189 if (slave.
index < 0 ||
6190 slave.
index >= nfaces ||
6219 const int *v =
elements[i]->GetVertices();
6224 for (
int j = 0; j < 4; j++)
6227 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
6233 for (
int j = 0; j < 2; j++)
6236 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
6238 for (
int j = 2; j < 5; j++)
6241 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
6249 for (
int j = 0; j < 6; j++)
6252 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
6257 MFEM_ABORT(
"Unexpected type of Element.");
6281 for (
int j = 0; j < 4; j++)
6285 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
6291 for (
int j = 0; j < 2; j++)
6295 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
6297 for (
int j = 2; j < 5; j++)
6301 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
6309 for (
int j = 0; j < 6; j++)
6313 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
6318 MFEM_ABORT(
"Unexpected type of Element.");
6331 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2]);
6336 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
6340 MFEM_ABORT(
"Unexpected type of boundary Element.");
6354 void Rotate3(
int &
a,
int &
b,
int &c)
6386 Table *old_elem_vert = NULL;
6397 int *v =
elements[i]->GetVertices();
6399 Rotate3(v[0], v[1], v[2]);
6402 Rotate3(v[1], v[2], v[3]);
6415 int *v =
boundary[i]->GetVertices();
6417 Rotate3(v[0], v[1], v[2]);
6433 delete old_elem_vert;
6449 if (p[i] < pmin[i]) { pmin[i] = p[i]; }
6450 if (p[i] > pmax[i]) { pmax[i] = p[i]; }
6464 for (
int i =
spaceDim-1; i >= 0; i--)
6466 int idx = (int)floor(nxyz[i]*((pt(i) - pmin[i])/(pmax[i] - pmin[i])));
6467 if (idx < 0) { idx = 0; }