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 "../fem/quadinterpolator.hpp"
33 #if defined(MFEM_USE_METIS) && defined(MFEM_USE_METIS_5)
38 #if defined(MFEM_USE_METIS) && !defined(MFEM_USE_METIS_5)
43 int*,
int*,
int*,
int*,
int*,
idxtype*);
45 int*,
int*,
int*,
int*,
int*,
idxtype*);
47 int*,
int*,
int*,
int*,
int*,
idxtype*);
68 void Mesh::GetElementCenter(
int i,
Vector ¢er)
71 int geom = GetElementBaseGeometry(i);
76 double Mesh::GetElementSize(
int i,
int type)
79 GetElementJacobian(i, J);
82 return pow(fabs(J.
Det()), 1./Dim);
94 double Mesh::GetElementSize(
int i,
const Vector &dir)
98 GetElementJacobian(i, J);
100 return sqrt((d_hat * d_hat) / (dir * dir));
103 double Mesh::GetElementVolume(
int i)
125 for (
int d = 0; d < spaceDim; d++)
134 for (
int i = 0; i < NumOfVertices; i++)
136 coord = GetVertex(i);
137 for (
int d = 0; d < spaceDim; d++)
139 if (coord[d] < min(d)) { min(d) = coord[d]; }
140 if (coord[d] > max(d)) { max(d) = coord[d]; }
146 const bool use_boundary =
false;
147 int ne = use_boundary ? GetNBE() : GetNE();
155 for (
int i = 0; i < ne; i++)
159 GetBdrElementFace(i, &fn, &fo);
161 Tr = GetFaceElementTransformations(fn, 5);
168 T = GetElementTransformation(i);
172 for (
int j = 0; j < pointmat.
Width(); j++)
174 for (
int d = 0; d < pointmat.
Height(); d++)
176 if (pointmat(d,j) < min(d)) { min(d) = pointmat(d,j); }
177 if (pointmat(d,j) > max(d)) { max(d) = pointmat(d,j); }
184 void Mesh::GetCharacteristics(
double &h_min,
double &h_max,
185 double &kappa_min,
double &kappa_max,
193 sdim = SpaceDimension();
195 if (Vh) { Vh->
SetSize(NumOfElements); }
196 if (Vk) { Vk->
SetSize(NumOfElements); }
199 h_max = kappa_max = -h_min;
200 if (dim == 0) {
if (Vh) { *Vh = 1.0; }
if (Vk) {*Vk = 1.0; }
return; }
202 for (i = 0; i < NumOfElements; i++)
204 GetElementJacobian(i, J);
205 h = pow(fabs(J.
Weight()), 1.0/
double(dim));
206 kappa = (dim == sdim) ?
208 if (Vh) { (*Vh)(i) = h; }
209 if (Vk) { (*Vk)(i) = kappa; }
211 if (h < h_min) { h_min = h; }
212 if (h > h_max) { h_max = h; }
213 if (kappa < kappa_min) { kappa_min =
kappa; }
214 if (kappa > kappa_max) { kappa_max =
kappa; }
219 void Mesh::PrintElementsByGeometry(
int dim,
223 for (
int g = Geometry::DimStart[dim], first = 1;
224 g < Geometry::DimStart[dim+1]; g++)
226 if (!num_elems_by_geom[g]) {
continue; }
227 if (!first) { out <<
" + "; }
229 out << num_elems_by_geom[g] <<
' ' << Geometry::Name[g] <<
"(s)";
235 double h_min, h_max, kappa_min, kappa_max;
237 out <<
"Mesh Characteristics:";
239 this->GetCharacteristics(h_min, h_max, kappa_min, kappa_max, Vh, Vk);
241 Array<int> num_elems_by_geom(Geometry::NumGeom);
242 num_elems_by_geom = 0;
243 for (
int i = 0; i < GetNE(); i++)
245 num_elems_by_geom[GetElementBaseGeometry(i)]++;
249 <<
"Dimension : " << Dimension() <<
'\n'
250 <<
"Space dimension : " << SpaceDimension();
254 <<
"Number of vertices : " << GetNV() <<
'\n'
255 <<
"Number of elements : " << GetNE() <<
'\n'
256 <<
"Number of bdr elem : " << GetNBE() <<
'\n';
261 <<
"Number of vertices : " << GetNV() <<
'\n'
262 <<
"Number of elements : " << GetNE() <<
'\n'
263 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
264 <<
"h_min : " << h_min <<
'\n'
265 <<
"h_max : " << h_max <<
'\n';
270 <<
"Number of vertices : " << GetNV() <<
'\n'
271 <<
"Number of edges : " << GetNEdges() <<
'\n'
272 <<
"Number of elements : " << GetNE() <<
" -- ";
273 PrintElementsByGeometry(2, num_elems_by_geom, out);
275 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
276 <<
"Euler Number : " << EulerNumber2D() <<
'\n'
277 <<
"h_min : " << h_min <<
'\n'
278 <<
"h_max : " << h_max <<
'\n'
279 <<
"kappa_min : " << kappa_min <<
'\n'
280 <<
"kappa_max : " << kappa_max <<
'\n';
284 Array<int> num_bdr_elems_by_geom(Geometry::NumGeom);
285 num_bdr_elems_by_geom = 0;
286 for (
int i = 0; i < GetNBE(); i++)
288 num_bdr_elems_by_geom[GetBdrElementBaseGeometry(i)]++;
290 Array<int> num_faces_by_geom(Geometry::NumGeom);
291 num_faces_by_geom = 0;
292 for (
int i = 0; i < GetNFaces(); i++)
294 num_faces_by_geom[GetFaceBaseGeometry(i)]++;
298 <<
"Number of vertices : " << GetNV() <<
'\n'
299 <<
"Number of edges : " << GetNEdges() <<
'\n'
300 <<
"Number of faces : " << GetNFaces() <<
" -- ";
301 PrintElementsByGeometry(Dim-1, num_faces_by_geom, out);
303 <<
"Number of elements : " << GetNE() <<
" -- ";
304 PrintElementsByGeometry(Dim, num_elems_by_geom, out);
306 <<
"Number of bdr elem : " << GetNBE() <<
" -- ";
307 PrintElementsByGeometry(Dim-1, num_bdr_elems_by_geom, out);
309 <<
"Euler Number : " << EulerNumber() <<
'\n'
310 <<
"h_min : " << h_min <<
'\n'
311 <<
"h_max : " << h_max <<
'\n'
312 <<
"kappa_min : " << kappa_min <<
'\n'
313 <<
"kappa_max : " << kappa_max <<
'\n';
315 out <<
'\n' << std::flush;
322 case Element::POINT :
return &
PointFE;
323 case Element::SEGMENT :
return &
SegmentFE;
328 case Element::WEDGE :
return &
WedgeFE;
330 MFEM_ABORT(
"Unknown element type \"" << ElemType <<
"\"");
333 MFEM_ABORT(
"Unknown element type");
345 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
351 Nodes->FESpace()->GetElementVDofs(i, vdofs);
354 int n = vdofs.
Size()/spaceDim;
356 for (
int k = 0; k < spaceDim; k++)
358 for (
int j = 0; j < n; j++)
360 pm(k,j) = nodes(vdofs[n*k+j]);
363 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
368 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
377 MFEM_ASSERT(nodes.
Size() == spaceDim*GetNV(),
"");
378 int nv = elements[i]->GetNVertices();
379 const int *v = elements[i]->GetVertices();
380 int n = vertices.Size();
382 for (
int k = 0; k < spaceDim; k++)
384 for (
int j = 0; j < nv; j++)
386 pm(k, j) = nodes(k*n+v[j]);
389 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
393 MFEM_ASSERT(nodes.
Size() == Nodes->Size(),
"");
395 Nodes->FESpace()->GetElementVDofs(i, vdofs);
396 int n = vdofs.
Size()/spaceDim;
398 for (
int k = 0; k < spaceDim; k++)
400 for (
int j = 0; j < n; j++)
402 pm(k,j) = nodes(vdofs[n*k+j]);
405 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
412 GetElementTransformation(i, &Transformation);
414 return &Transformation;
419 GetBdrElementTransformation(i, &BdrTransformation);
420 return &BdrTransformation;
430 GetBdrPointMatrix(i, pm);
431 ElTr->
SetFE(GetTransformationFEforElementType(GetBdrElementType(i)));
441 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
442 int n = vdofs.
Size()/spaceDim;
444 for (
int k = 0; k < spaceDim; k++)
446 for (
int j = 0; j < n; j++)
448 pm(k,j) = nodes(vdofs[n*k+j]);
455 int elem_id, face_info;
456 GetBdrElementAdjacentElement(i, elem_id, face_info);
458 GetLocalFaceTransformation(GetBdrElementType(i),
459 GetElementType(elem_id),
460 FaceElemTr.Loc1.Transf, face_info);
464 Nodes->FESpace()->GetTraceElement(elem_id,
465 GetBdrElementBaseGeometry(i));
468 FaceElemTr.Loc1.Transf.ElementNo = elem_id;
469 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
470 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
472 ElTr->
SetFE(face_el);
480 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
485 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
486 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
488 for (
int i = 0; i < spaceDim; i++)
490 for (
int j = 0; j < nv; j++)
492 pm(i, j) = vertices[v[j]](i);
495 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
499 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
505 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
506 int n = vdofs.
Size()/spaceDim;
508 for (
int i = 0; i < spaceDim; i++)
510 for (
int j = 0; j < n; j++)
512 pm(i, j) = nodes(vdofs[n*i+j]);
519 FaceInfo &face_info = faces_info[FaceNo];
524 GetLocalFaceTransformation(face_type,
525 GetElementType(face_info.
Elem1No),
526 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
529 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
533 FaceElemTr.Loc1.Transf.ElementNo = face_info.
Elem1No;
534 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
535 Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
545 GetFaceTransformation(FaceNo, &FaceTransformation);
546 return &FaceTransformation;
553 GetFaceTransformation(EdgeNo, EdTr);
558 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
567 GetEdgeVertices(EdgeNo, v);
570 for (
int i = 0; i < spaceDim; i++)
572 for (
int j = 0; j < nv; j++)
574 pm(i, j) = vertices[v[j]](i);
577 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
581 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
585 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
586 int n = vdofs.
Size()/spaceDim;
588 for (
int i = 0; i < spaceDim; i++)
590 for (
int j = 0; j < n; j++)
592 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
595 EdTr->
SetFE(edge_el);
599 MFEM_ABORT(
"Not implemented.");
607 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
608 return &EdgeTransformation;
612 void Mesh::GetLocalPtToSegTransformation(
627 void Mesh::GetLocalSegToTriTransformation(
635 tv = tri_t::Edges[i/64];
636 so = seg_t::Orient[i%64];
639 for (
int j = 0; j < 2; j++)
641 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
642 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
647 void Mesh::GetLocalSegToQuadTransformation(
655 qv = quad_t::Edges[i/64];
656 so = seg_t::Orient[i%64];
659 for (
int j = 0; j < 2; j++)
661 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
662 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
667 void Mesh::GetLocalTriToTetTransformation(
674 const int *tv = tet_t::FaceVert[i/64];
677 const int *to = tri_t::Orient[i%64];
681 for (
int j = 0; j < 3; j++)
684 locpm(0, j) = vert.
x;
685 locpm(1, j) = vert.
y;
686 locpm(2, j) = vert.
z;
691 void Mesh::GetLocalTriToWdgTransformation(
698 MFEM_VERIFY(i < 128,
"Local face index " << i/64
699 <<
" is not a triangular face of a wedge.");
700 const int *pv = pri_t::FaceVert[i/64];
703 const int *to = tri_t::Orient[i%64];
707 for (
int j = 0; j < 3; j++)
710 locpm(0, j) = vert.
x;
711 locpm(1, j) = vert.
y;
712 locpm(2, j) = vert.
z;
717 void Mesh::GetLocalQuadToHexTransformation(
724 const int *hv = hex_t::FaceVert[i/64];
726 const int *qo = quad_t::Orient[i%64];
729 for (
int j = 0; j < 4; j++)
732 locpm(0, j) = vert.
x;
733 locpm(1, j) = vert.
y;
734 locpm(2, j) = vert.
z;
739 void Mesh::GetLocalQuadToWdgTransformation(
746 MFEM_VERIFY(i >= 128,
"Local face index " << i/64
747 <<
" is not a quadrilateral face of a wedge.");
748 const int *pv = pri_t::FaceVert[i/64];
750 const int *qo = quad_t::Orient[i%64];
753 for (
int j = 0; j < 4; j++)
756 locpm(0, j) = vert.
x;
757 locpm(1, j) = vert.
y;
758 locpm(2, j) = vert.
z;
766 for (
int i = 0; i < geom_factors.Size(); i++)
778 geom_factors.Append(gf);
786 for (
int i = 0; i < face_geom_factors.Size(); i++)
799 face_geom_factors.Append(gf);
803 void Mesh::DeleteGeometricFactors()
805 for (
int i = 0; i < geom_factors.Size(); i++)
807 delete geom_factors[i];
809 geom_factors.SetSize(0);
810 for (
int i = 0; i < face_geom_factors.Size(); i++)
812 delete face_geom_factors[i];
814 face_geom_factors.SetSize(0);
817 void Mesh::GetLocalFaceTransformation(
823 GetLocalPtToSegTransformation(Transf, info);
826 case Element::SEGMENT:
827 if (elem_type == Element::TRIANGLE)
829 GetLocalSegToTriTransformation(Transf, info);
833 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
834 GetLocalSegToQuadTransformation(Transf, info);
838 case Element::TRIANGLE:
839 if (elem_type == Element::TETRAHEDRON)
841 GetLocalTriToTetTransformation(Transf, info);
845 MFEM_ASSERT(elem_type == Element::WEDGE,
"");
846 GetLocalTriToWdgTransformation(Transf, info);
850 case Element::QUADRILATERAL:
851 if (elem_type == Element::HEXAHEDRON)
853 GetLocalQuadToHexTransformation(Transf, info);
857 MFEM_ASSERT(elem_type == Element::WEDGE,
"");
858 GetLocalQuadToWdgTransformation(Transf, info);
867 FaceInfo &face_info = faces_info[FaceNo];
869 FaceElemTr.Elem1 = NULL;
870 FaceElemTr.Elem2 = NULL;
876 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
877 FaceElemTr.Elem1 = &Transformation;
883 FaceElemTr.Elem2No = face_info.
Elem2No;
884 if ((mask & 2) && FaceElemTr.Elem2No >= 0)
887 if (NURBSext && (mask & 1)) { MFEM_ABORT(
"NURBS mesh not supported!"); }
889 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
890 FaceElemTr.Elem2 = &Transformation2;
894 FaceElemTr.FaceGeom = GetFaceGeometryType(FaceNo);
895 FaceElemTr.Face = (mask & 16) ? GetFaceTransformation(FaceNo) : NULL;
898 int face_type = GetFaceElementType(FaceNo);
901 int elem_type = GetElementType(face_info.
Elem1No);
902 GetLocalFaceTransformation(face_type, elem_type,
903 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
905 if ((mask & 8) && FaceElemTr.Elem2No >= 0)
907 int elem_type = GetElementType(face_info.
Elem2No);
908 GetLocalFaceTransformation(face_type, elem_type,
909 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
912 if (Nonconforming() && IsSlaveFace(face_info))
914 ApplyLocalSlaveTransformation(FaceElemTr.Loc2.Transf, face_info);
916 if (face_type == Element::SEGMENT)
919 DenseMatrix &pm = FaceElemTr.Loc2.Transf.GetPointMat();
920 std::swap(pm(0,0), pm(0,1));
921 std::swap(pm(1,0), pm(1,1));
931 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
937 #ifdef MFEM_THREAD_SAFE
942 MFEM_ASSERT(fi.
NCFace >= 0,
"");
954 fn = be_to_face[BdrElemNo];
958 fn = be_to_edge[BdrElemNo];
962 fn = boundary[BdrElemNo]->GetVertices()[0];
965 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
969 tr = GetFaceElementTransformations(fn);
974 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
const
976 *Elem1 = faces_info[Face].
Elem1No;
977 *Elem2 = faces_info[Face].Elem2No;
980 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
const
982 *Inf1 = faces_info[Face].Elem1Inf;
983 *Inf2 = faces_info[Face].Elem2Inf;
988 return (Dim == 1) ? Geometry::POINT : faces[Face]->GetGeometryType();
993 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
1001 NumOfElements = NumOfBdrElements = 0;
1002 NumOfEdges = NumOfFaces = 0;
1003 nbInteriorFaces = -1;
1004 nbBoundaryFaces = -1;
1005 meshgen = mesh_geoms = 0;
1011 last_operation = Mesh::NONE;
1014 void Mesh::InitTables()
1017 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
1020 void Mesh::SetEmpty()
1026 void Mesh::DestroyTables()
1031 DeleteGeometricFactors();
1042 void Mesh::DestroyPointers()
1044 if (own_nodes) {
delete Nodes; }
1050 for (
int i = 0; i < NumOfElements; i++)
1052 FreeElement(elements[i]);
1055 for (
int i = 0; i < NumOfBdrElements; i++)
1057 FreeElement(boundary[i]);
1060 for (
int i = 0; i < faces.Size(); i++)
1062 FreeElement(faces[i]);
1068 void Mesh::Destroy()
1072 elements.DeleteAll();
1073 vertices.DeleteAll();
1074 boundary.DeleteAll();
1076 faces_info.DeleteAll();
1077 nc_faces_info.DeleteAll();
1078 be_to_edge.DeleteAll();
1079 be_to_face.DeleteAll();
1087 CoarseFineTr.Clear();
1089 #ifdef MFEM_USE_MEMALLOC
1093 attributes.DeleteAll();
1094 bdr_attributes.DeleteAll();
1097 void Mesh::ResetLazyData()
1099 delete el_to_el; el_to_el = NULL;
1100 delete face_edge; face_edge = NULL;
1101 delete edge_vertex; edge_vertex = NULL;
1102 DeleteGeometricFactors();
1103 nbInteriorFaces = -1;
1104 nbBoundaryFaces = -1;
1107 void Mesh::SetAttributes()
1112 for (
int i = 0; i < attribs.
Size(); i++)
1114 attribs[i] = GetBdrAttribute(i);
1118 attribs.
Copy(bdr_attributes);
1119 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
1121 MFEM_WARNING(
"Non-positive attributes on the boundary!");
1125 for (
int i = 0; i < attribs.
Size(); i++)
1127 attribs[i] = GetAttribute(i);
1131 attribs.
Copy(attributes);
1132 if (attributes.Size() > 0 && attributes[0] <= 0)
1134 MFEM_WARNING(
"Non-positive attributes in the domain!");
1138 void Mesh::InitMesh(
int _Dim,
int _spaceDim,
int NVert,
int NElem,
int NBdrElem)
1143 spaceDim = _spaceDim;
1146 vertices.SetSize(NVert);
1149 elements.SetSize(NElem);
1151 NumOfBdrElements = 0;
1152 boundary.SetSize(NBdrElem);
1155 void Mesh::AddVertex(
const double *x)
1157 double *y = vertices[NumOfVertices]();
1159 for (
int i = 0; i < spaceDim; i++)
1166 void Mesh::AddSegment(
const int *vi,
int attr)
1168 elements[NumOfElements++] =
new Segment(vi, attr);
1171 void Mesh::AddTri(
const int *vi,
int attr)
1173 elements[NumOfElements++] =
new Triangle(vi, attr);
1176 void Mesh::AddTriangle(
const int *vi,
int attr)
1178 elements[NumOfElements++] =
new Triangle(vi, attr);
1181 void Mesh::AddQuad(
const int *vi,
int attr)
1186 void Mesh::AddTet(
const int *vi,
int attr)
1188 #ifdef MFEM_USE_MEMALLOC
1190 tet = TetMemory.Alloc();
1193 elements[NumOfElements++] = tet;
1195 elements[NumOfElements++] =
new Tetrahedron(vi, attr);
1199 void Mesh::AddWedge(
const int *vi,
int attr)
1201 elements[NumOfElements++] =
new Wedge(vi, attr);
1204 void Mesh::AddHex(
const int *vi,
int attr)
1206 elements[NumOfElements++] =
new Hexahedron(vi, attr);
1209 void Mesh::AddHexAsTets(
const int *vi,
int attr)
1211 static const int hex_to_tet[6][4] =
1213 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
1214 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
1218 for (
int i = 0; i < 6; i++)
1220 for (
int j = 0; j < 4; j++)
1222 ti[j] = vi[hex_to_tet[i][j]];
1228 void Mesh::AddHexAsWedges(
const int *vi,
int attr)
1230 static const int hex_to_wdg[2][6] =
1232 { 0, 1, 2, 4, 5, 6 }, { 0, 2, 3, 4, 6, 7 }
1236 for (
int i = 0; i < 2; i++)
1238 for (
int j = 0; j < 6; j++)
1240 ti[j] = vi[hex_to_wdg[i][j]];
1246 void Mesh::AddBdrSegment(
const int *vi,
int attr)
1248 boundary[NumOfBdrElements++] =
new Segment(vi, attr);
1251 void Mesh::AddBdrTriangle(
const int *vi,
int attr)
1253 boundary[NumOfBdrElements++] =
new Triangle(vi, attr);
1256 void Mesh::AddBdrQuad(
const int *vi,
int attr)
1261 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1263 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1266 for (
int i = 0; i < 2; i++)
1268 for (
int j = 0; j < 3; j++)
1270 ti[j] = vi[quad_to_tri[i][j]];
1272 AddBdrTriangle(ti, attr);
1276 void Mesh::GenerateBoundaryElements()
1279 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1283 for (i = 0; i < boundary.Size(); i++)
1285 FreeElement(boundary[i]);
1295 NumOfBdrElements = 0;
1296 for (i = 0; i < faces_info.Size(); i++)
1298 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1301 boundary.SetSize(NumOfBdrElements);
1302 be2face.
SetSize(NumOfBdrElements);
1303 for (j = i = 0; i < faces_info.Size(); i++)
1305 if (faces_info[i].Elem2No < 0)
1307 boundary[j] = faces[i]->Duplicate(
this);
1314 void Mesh::FinalizeCheck()
1316 MFEM_VERIFY(vertices.Size() == NumOfVertices ||
1317 vertices.Size() == 0,
1318 "incorrect number of vertices: preallocated: " << vertices.Size()
1319 <<
", actually added: " << NumOfVertices);
1320 MFEM_VERIFY(elements.Size() == NumOfElements,
1321 "incorrect number of elements: preallocated: " << elements.Size()
1322 <<
", actually added: " << NumOfElements);
1323 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1324 "incorrect number of boundary elements: preallocated: "
1325 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1328 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1331 CheckElementOrientation(fix_orientation);
1335 MarkTriMeshForRefinement();
1340 el_to_edge =
new Table;
1341 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1343 CheckBdrElementOrientation();
1357 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1358 bool fix_orientation)
1361 if (fix_orientation)
1363 CheckElementOrientation(fix_orientation);
1368 el_to_edge =
new Table;
1369 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1371 CheckBdrElementOrientation();
1386 #ifdef MFEM_USE_GECKO
1388 int iterations,
int window,
1389 int period,
int seed)
1393 Gecko::Functional *functional =
1394 new Gecko::FunctionalGeometric();
1397 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1404 const Table &my_el_to_el = ElementToElementTable();
1405 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1407 const int *neighid = my_el_to_el.
GetRow(elemid);
1408 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
1410 graph.insert(elemid + 1, neighid[i] + 1);
1415 graph.order(functional, iterations, window, period, seed);
1418 Gecko::Node::Index NE = GetNE();
1419 for (Gecko::Node::Index gnodeid = 1; gnodeid <= NE; ++gnodeid)
1421 ordering[gnodeid - 1] = graph.rank(gnodeid);
1436 HilbertCmp(
int coord,
bool dir,
const Array<double> &points,
double mid)
1437 : coord(coord), dir(dir), points(points), mid(mid) {}
1439 bool operator()(
int i)
const
1441 return (points[3*i + coord] < mid) != dir;
1445 static void HilbertSort2D(
int coord1,
1448 const Array<double> &points,
int *beg,
int *end,
1449 double xmin,
double ymin,
double xmax,
double ymax)
1451 if (end - beg <= 1) {
return; }
1453 double xmid = (xmin + xmax)*0.5;
1454 double ymid = (ymin + ymax)*0.5;
1456 int coord2 = (coord1 + 1) % 2;
1459 int *p0 = beg, *p4 = end;
1460 int *p2 = std::partition(p0, p4, HilbertCmp(coord1, dir1, points, xmid));
1461 int *p1 = std::partition(p0, p2, HilbertCmp(coord2, dir2, points, ymid));
1462 int *p3 = std::partition(p2, p4, HilbertCmp(coord2, !dir2, points, ymid));
1466 HilbertSort2D(coord2, dir2, dir1, points, p0, p1,
1467 ymin, xmin, ymid, xmid);
1469 if (p1 != p0 || p2 != p4)
1471 HilbertSort2D(coord1, dir1, dir2, points, p1, p2,
1472 xmin, ymid, xmid, ymax);
1474 if (p2 != p0 || p3 != p4)
1476 HilbertSort2D(coord1, dir1, dir2, points, p2, p3,
1477 xmid, ymid, xmax, ymax);
1481 HilbertSort2D(coord2, !dir2, !dir1, points, p3, p4,
1482 ymid, xmax, ymin, xmid);
1486 static void HilbertSort3D(
int coord1,
bool dir1,
bool dir2,
bool dir3,
1487 const Array<double> &points,
int *beg,
int *end,
1488 double xmin,
double ymin,
double zmin,
1489 double xmax,
double ymax,
double zmax)
1491 if (end - beg <= 1) {
return; }
1493 double xmid = (xmin + xmax)*0.5;
1494 double ymid = (ymin + ymax)*0.5;
1495 double zmid = (zmin + zmax)*0.5;
1497 int coord2 = (coord1 + 1) % 3;
1498 int coord3 = (coord1 + 2) % 3;
1501 int *p0 = beg, *p8 = end;
1502 int *p4 = std::partition(p0, p8, HilbertCmp(coord1, dir1, points, xmid));
1503 int *p2 = std::partition(p0, p4, HilbertCmp(coord2, dir2, points, ymid));
1504 int *p6 = std::partition(p4, p8, HilbertCmp(coord2, !dir2, points, ymid));
1505 int *p1 = std::partition(p0, p2, HilbertCmp(coord3, dir3, points, zmid));
1506 int *p3 = std::partition(p2, p4, HilbertCmp(coord3, !dir3, points, zmid));
1507 int *p5 = std::partition(p4, p6, HilbertCmp(coord3, dir3, points, zmid));
1508 int *p7 = std::partition(p6, p8, HilbertCmp(coord3, !dir3, points, zmid));
1512 HilbertSort3D(coord3, dir3, dir1, dir2, points, p0, p1,
1513 zmin, xmin, ymin, zmid, xmid, ymid);
1515 if (p1 != p0 || p2 != p8)
1517 HilbertSort3D(coord2, dir2, dir3, dir1, points, p1, p2,
1518 ymin, zmid, xmin, ymid, zmax, xmid);
1520 if (p2 != p0 || p3 != p8)
1522 HilbertSort3D(coord2, dir2, dir3, dir1, points, p2, p3,
1523 ymid, zmid, xmin, ymax, zmax, xmid);
1525 if (p3 != p0 || p4 != p8)
1527 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p3, p4,
1528 xmin, ymax, zmid, xmid, ymid, zmin);
1530 if (p4 != p0 || p5 != p8)
1532 HilbertSort3D(coord1, dir1, !dir2, !dir3, points, p4, p5,
1533 xmid, ymax, zmid, xmax, ymid, zmin);
1535 if (p5 != p0 || p6 != p8)
1537 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p5, p6,
1538 ymax, zmid, xmax, ymid, zmax, xmid);
1540 if (p6 != p0 || p7 != p8)
1542 HilbertSort3D(coord2, !dir2, dir3, !dir1, points, p6, p7,
1543 ymid, zmid, xmax, ymin, zmax, xmid);
1547 HilbertSort3D(coord3, !dir3, !dir1, dir2, points, p7, p8,
1548 zmid, xmax, ymin, zmin, xmid, ymid);
1554 MFEM_VERIFY(spaceDim <= 3,
"");
1557 GetBoundingBox(min, max);
1562 if (spaceDim < 3) { points = 0.0; }
1565 for (
int i = 0; i < GetNE(); i++)
1567 GetElementCenter(i, center);
1568 for (
int j = 0; j < spaceDim; j++)
1570 points[3*i + j] = center(j);
1577 indices.
Sort([&](
int a,
int b)
1578 {
return points[3*
a] < points[3*
b]; });
1580 else if (spaceDim == 2)
1583 HilbertSort2D(0,
false,
false,
1584 points, indices.
begin(), indices.
end(),
1585 min(0), min(1), max(0), max(1));
1590 HilbertSort3D(0,
false,
false,
false,
1591 points, indices.
begin(), indices.
end(),
1592 min(0), min(1), min(2), max(0), max(1), max(2));
1597 for (
int i = 0; i < GetNE(); i++)
1599 ordering[indices[i]] = i;
1604 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
1608 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
1613 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
1617 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
1647 old_elem_node_vals.SetSize(GetNE());
1648 nodes_fes = Nodes->FESpace();
1651 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1653 nodes_fes->GetElementVDofs(old_elid, old_dofs);
1655 old_elem_node_vals[old_elid] =
new Vector(vals);
1661 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
1663 int new_elid = ordering[old_elid];
1664 new_elements[new_elid] = elements[old_elid];
1669 if (reorder_vertices)
1674 vertex_ordering = -1;
1676 int new_vertex_ind = 0;
1677 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1679 int *elem_vert = elements[new_elid]->GetVertices();
1680 int nv = elements[new_elid]->GetNVertices();
1681 for (
int vi = 0; vi < nv; ++vi)
1683 int old_vertex_ind = elem_vert[vi];
1684 if (vertex_ordering[old_vertex_ind] == -1)
1686 vertex_ordering[old_vertex_ind] = new_vertex_ind;
1687 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
1697 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1699 int *elem_vert = elements[new_elid]->GetVertices();
1700 int nv = elements[new_elid]->GetNVertices();
1701 for (
int vi = 0; vi < nv; ++vi)
1703 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
1708 for (
int belid = 0; belid < GetNBE(); ++belid)
1710 int *be_vert = boundary[belid]->GetVertices();
1711 int nv = boundary[belid]->GetNVertices();
1712 for (
int vi = 0; vi < nv; ++vi)
1714 be_vert[vi] = vertex_ordering[be_vert[vi]];
1725 el_to_edge =
new Table;
1726 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1731 GetElementToFaceTable();
1741 last_operation = Mesh::NONE;
1742 nodes_fes->Update(
false);
1745 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1747 int new_elid = ordering[old_elid];
1748 nodes_fes->GetElementVDofs(new_elid, new_dofs);
1749 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
1750 delete old_elem_node_vals[old_elid];
1756 void Mesh::MarkForRefinement()
1762 MarkTriMeshForRefinement();
1766 DSTable v_to_v(NumOfVertices);
1767 GetVertexToVertexTable(v_to_v);
1768 MarkTetMeshForRefinement(v_to_v);
1773 void Mesh::MarkTriMeshForRefinement()
1778 for (
int i = 0; i < NumOfElements; i++)
1780 if (elements[i]->GetType() == Element::TRIANGLE)
1782 GetPointMatrix(i, pmat);
1783 static_cast<Triangle*
>(elements[i])->MarkEdge(pmat);
1794 for (
int i = 0; i < NumOfVertices; i++)
1799 length_idx[j].one = GetLength(i, it.Column());
1800 length_idx[j].two = j;
1807 for (
int i = 0; i < NumOfEdges; i++)
1809 order[length_idx[i].two] = i;
1813 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
1818 GetEdgeOrdering(v_to_v, order);
1820 for (
int i = 0; i < NumOfElements; i++)
1822 if (elements[i]->GetType() == Element::TETRAHEDRON)
1824 elements[i]->MarkEdge(v_to_v, order);
1827 for (
int i = 0; i < NumOfBdrElements; i++)
1829 if (boundary[i]->GetType() == Element::TRIANGLE)
1831 boundary[i]->MarkEdge(v_to_v, order);
1838 if (*old_v_to_v && *old_elem_vert)
1845 if (*old_v_to_v == NULL)
1847 bool need_v_to_v =
false;
1849 for (
int i = 0; i < GetNEdges(); i++)
1855 if (dofs.
Size() > 0)
1863 *old_v_to_v =
new DSTable(NumOfVertices);
1864 GetVertexToVertexTable(*(*old_v_to_v));
1867 if (*old_elem_vert == NULL)
1869 bool need_elem_vert =
false;
1871 for (
int i = 0; i < GetNE(); i++)
1877 if (dofs.
Size() > 1)
1879 need_elem_vert =
true;
1885 *old_elem_vert =
new Table;
1886 (*old_elem_vert)->
MakeI(GetNE());
1887 for (
int i = 0; i < GetNE(); i++)
1889 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
1891 (*old_elem_vert)->MakeJ();
1892 for (
int i = 0; i < GetNE(); i++)
1894 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
1895 elements[i]->GetNVertices());
1897 (*old_elem_vert)->ShiftUpI();
1910 const int num_edge_dofs = old_dofs.
Size();
1913 const Vector onodes = *Nodes;
1917 int offset = NumOfVertices * old_dofs.
Size();
1921 if (num_edge_dofs > 0)
1923 DSTable new_v_to_v(NumOfVertices);
1924 GetVertexToVertexTable(new_v_to_v);
1926 for (
int i = 0; i < NumOfVertices; i++)
1930 const int old_i = (*old_v_to_v)(i, it.Column());
1931 const int new_i = it.Index();
1932 if (new_i == old_i) {
continue; }
1934 old_dofs.
SetSize(num_edge_dofs);
1935 new_dofs.
SetSize(num_edge_dofs);
1936 for (
int j = 0; j < num_edge_dofs; j++)
1938 old_dofs[j] = offset + old_i * num_edge_dofs + j;
1939 new_dofs[j] = offset + new_i * num_edge_dofs + j;
1943 for (
int j = 0; j < old_dofs.
Size(); j++)
1945 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1949 offset += NumOfEdges * num_edge_dofs;
1957 Table old_face_vertex;
1958 old_face_vertex.
MakeI(NumOfFaces);
1959 for (
int i = 0; i < NumOfFaces; i++)
1963 old_face_vertex.
MakeJ();
1964 for (
int i = 0; i < NumOfFaces; i++)
1966 faces[i]->GetNVertices());
1970 STable3D *faces_tbl = GetElementToFaceTable(1);
1976 for (
int i = 0; i < NumOfFaces; i++)
1978 const int *old_v = old_face_vertex.
GetRow(i);
1980 switch (old_face_vertex.
RowSize(i))
1983 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
1987 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
1991 new_fdofs[new_i+1] = old_dofs.
Size();
1996 for (
int i = 0; i < NumOfFaces; i++)
1998 const int *old_v = old_face_vertex.
GetRow(i), *new_v;
2001 switch (old_face_vertex.
RowSize(i))
2004 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
2005 new_v = faces[new_i]->GetVertices();
2006 new_or = GetTriOrientation(old_v, new_v);
2011 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
2012 new_v = faces[new_i]->GetVertices();
2013 new_or = GetQuadOrientation(old_v, new_v);
2020 for (
int j = 0; j < old_dofs.
Size(); j++)
2023 const int old_j = dof_ord[j];
2024 new_dofs[old_j] = offset + new_fdofs[new_i] + j;
2028 for (
int j = 0; j < old_dofs.
Size(); j++)
2030 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2052 for (
int i = 0; i < GetNE(); i++)
2054 const int *old_v = old_elem_vert->
GetRow(i);
2055 const int *new_v = elements[i]->GetVertices();
2061 case Geometry::SEGMENT:
2062 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
2064 case Geometry::TRIANGLE:
2065 new_or = GetTriOrientation(old_v, new_v);
2067 case Geometry::SQUARE:
2068 new_or = GetQuadOrientation(old_v, new_v);
2072 MFEM_ABORT(Geometry::Name[geom] <<
" elements (" << fec->
Name()
2073 <<
" FE collection) are not supported yet!");
2077 MFEM_VERIFY(dof_ord != NULL,
2078 "FE collection '" << fec->
Name()
2079 <<
"' does not define reordering for "
2080 << Geometry::Name[
geom] <<
" elements!");
2083 for (
int j = 0; j < new_dofs.
Size(); j++)
2086 const int old_j = dof_ord[j];
2087 new_dofs[old_j] = offset + j;
2089 offset += new_dofs.
Size();
2092 for (
int j = 0; j < old_dofs.
Size(); j++)
2094 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
2106 GetElementToFaceTable();
2109 CheckBdrElementOrientation();
2114 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2119 CheckBdrElementOrientation();
2124 last_operation = Mesh::NONE;
2129 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
2132 CheckElementOrientation(fix_orientation);
2134 if (NumOfBdrElements == 0)
2136 GetElementToFaceTable();
2138 GenerateBoundaryElements();
2143 DSTable v_to_v(NumOfVertices);
2144 GetVertexToVertexTable(v_to_v);
2145 MarkTetMeshForRefinement(v_to_v);
2148 GetElementToFaceTable();
2151 CheckBdrElementOrientation();
2153 if (generate_edges == 1)
2155 el_to_edge =
new Table;
2156 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2170 void Mesh::FinalizeWedgeMesh(
int generate_edges,
int refine,
2171 bool fix_orientation)
2174 CheckElementOrientation(fix_orientation);
2176 if (NumOfBdrElements == 0)
2178 GetElementToFaceTable();
2180 GenerateBoundaryElements();
2183 GetElementToFaceTable();
2186 CheckBdrElementOrientation();
2188 if (generate_edges == 1)
2190 el_to_edge =
new Table;
2191 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2205 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
2208 CheckElementOrientation(fix_orientation);
2210 GetElementToFaceTable();
2213 if (NumOfBdrElements == 0)
2215 GenerateBoundaryElements();
2218 CheckBdrElementOrientation();
2222 el_to_edge =
new Table;
2223 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2235 void Mesh::FinalizeMesh(
int refine,
bool fix_orientation)
2239 Finalize(refine, fix_orientation);
2242 void Mesh::FinalizeTopology(
bool generate_bdr)
2254 bool generate_edges =
true;
2256 if (spaceDim == 0) { spaceDim = Dim; }
2257 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2265 GetElementToFaceTable();
2267 if (NumOfBdrElements == 0 && generate_bdr)
2269 GenerateBoundaryElements();
2270 GetElementToFaceTable();
2279 if (Dim > 1 && generate_edges)
2282 if (!el_to_edge) { el_to_edge =
new Table; }
2283 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2287 if (NumOfBdrElements == 0 && generate_bdr)
2289 GenerateBoundaryElements();
2306 ncmesh->OnMeshUpdated(
this);
2309 GenerateNCFaceInfo();
2316 void Mesh::Finalize(
bool refine,
bool fix_orientation)
2318 if (NURBSext || ncmesh)
2320 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
2321 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
2330 const bool check_orientation =
true;
2331 const bool curved = (Nodes != NULL);
2332 const bool may_change_topology =
2333 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
2334 ( check_orientation && fix_orientation &&
2335 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
2338 Table *old_elem_vert = NULL;
2340 if (curved && may_change_topology)
2342 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
2345 if (check_orientation)
2348 CheckElementOrientation(fix_orientation);
2352 MarkForRefinement();
2355 if (may_change_topology)
2359 DoNodeReorder(old_v_to_v, old_elem_vert);
2360 delete old_elem_vert;
2373 CheckBdrElementOrientation();
2378 if (Dim >= 2 && Dim == spaceDim)
2380 const int num_faces = GetNumFaces();
2381 for (
int i = 0; i < num_faces; i++)
2383 MFEM_VERIFY(faces_info[i].Elem2No < 0 ||
2384 faces_info[i].Elem2Inf%2 != 0,
"invalid mesh topology");
2391 double sx,
double sy,
double sz,
bool sfc_ordering)
2395 int NVert, NElem, NBdrElem;
2397 NVert = (nx+1) * (ny+1) * (nz+1);
2398 NElem = nx * ny * nz;
2399 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
2400 if (type == Element::TETRAHEDRON)
2405 else if (type == Element::WEDGE)
2408 NBdrElem += 2*nx*ny;
2411 InitMesh(3, 3, NVert, NElem, NBdrElem);
2417 for (z = 0; z <= nz; z++)
2419 coord[2] = ((double) z / nz) * sz;
2420 for (y = 0; y <= ny; y++)
2422 coord[1] = ((double) y / ny) * sy;
2423 for (x = 0; x <= nx; x++)
2425 coord[0] = ((double) x / nx) * sx;
2431 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
2434 if (sfc_ordering && type == Element::HEXAHEDRON)
2437 NCMesh::GridSfcOrdering3D(nx, ny, nz, sfc);
2438 MFEM_VERIFY(sfc.
Size() == 3*nx*ny*nz,
"");
2440 for (
int k = 0; k < nx*ny*nz; k++)
2446 ind[0] = VTX(x , y , z );
2447 ind[1] = VTX(x+1, y , z );
2448 ind[2] = VTX(x+1, y+1, z );
2449 ind[3] = VTX(x , y+1, z );
2450 ind[4] = VTX(x , y , z+1);
2451 ind[5] = VTX(x+1, y , z+1);
2452 ind[6] = VTX(x+1, y+1, z+1);
2453 ind[7] = VTX(x , y+1, z+1);
2460 for (z = 0; z < nz; z++)
2462 for (y = 0; y < ny; y++)
2464 for (x = 0; x < nx; x++)
2466 ind[0] = VTX(x , y , z );
2467 ind[1] = VTX(x+1, y , z );
2468 ind[2] = VTX(x+1, y+1, z );
2469 ind[3] = VTX(x , y+1, z );
2470 ind[4] = VTX(x , y , z+1);
2471 ind[5] = VTX(x+1, y , z+1);
2472 ind[6] = VTX(x+1, y+1, z+1);
2473 ind[7] = VTX( x, y+1, z+1);
2474 if (type == Element::TETRAHEDRON)
2476 AddHexAsTets(ind, 1);
2478 else if (type == Element::WEDGE)
2480 AddHexAsWedges(ind, 1);
2493 for (y = 0; y < ny; y++)
2495 for (x = 0; x < nx; x++)
2497 ind[0] = VTX(x , y , 0);
2498 ind[1] = VTX(x , y+1, 0);
2499 ind[2] = VTX(x+1, y+1, 0);
2500 ind[3] = VTX(x+1, y , 0);
2501 if (type == Element::TETRAHEDRON)
2503 AddBdrQuadAsTriangles(ind, 1);
2505 else if (type == Element::WEDGE)
2507 AddBdrQuadAsTriangles(ind, 1);
2516 for (y = 0; y < ny; y++)
2518 for (x = 0; x < nx; x++)
2520 ind[0] = VTX(x , y , nz);
2521 ind[1] = VTX(x+1, y , nz);
2522 ind[2] = VTX(x+1, y+1, nz);
2523 ind[3] = VTX(x , y+1, nz);
2524 if (type == Element::TETRAHEDRON)
2526 AddBdrQuadAsTriangles(ind, 6);
2528 else if (type == Element::WEDGE)
2530 AddBdrQuadAsTriangles(ind, 1);
2539 for (z = 0; z < nz; z++)
2541 for (y = 0; y < ny; y++)
2543 ind[0] = VTX(0 , y , z );
2544 ind[1] = VTX(0 , y , z+1);
2545 ind[2] = VTX(0 , y+1, z+1);
2546 ind[3] = VTX(0 , y+1, z );
2547 if (type == Element::TETRAHEDRON)
2549 AddBdrQuadAsTriangles(ind, 5);
2558 for (z = 0; z < nz; z++)
2560 for (y = 0; y < ny; y++)
2562 ind[0] = VTX(nx, y , z );
2563 ind[1] = VTX(nx, y+1, z );
2564 ind[2] = VTX(nx, y+1, z+1);
2565 ind[3] = VTX(nx, y , z+1);
2566 if (type == Element::TETRAHEDRON)
2568 AddBdrQuadAsTriangles(ind, 3);
2577 for (x = 0; x < nx; x++)
2579 for (z = 0; z < nz; z++)
2581 ind[0] = VTX(x , 0, z );
2582 ind[1] = VTX(x+1, 0, z );
2583 ind[2] = VTX(x+1, 0, z+1);
2584 ind[3] = VTX(x , 0, z+1);
2585 if (type == Element::TETRAHEDRON)
2587 AddBdrQuadAsTriangles(ind, 2);
2596 for (x = 0; x < nx; x++)
2598 for (z = 0; z < nz; z++)
2600 ind[0] = VTX(x , ny, z );
2601 ind[1] = VTX(x , ny, z+1);
2602 ind[2] = VTX(x+1, ny, z+1);
2603 ind[3] = VTX(x+1, ny, z );
2604 if (type == Element::TETRAHEDRON)
2606 AddBdrQuadAsTriangles(ind, 4);
2618 ofstream test_stream(
"debug.mesh");
2620 test_stream.close();
2629 double sx,
double sy,
2630 bool generate_edges,
bool sfc_ordering)
2639 if (type == Element::QUADRILATERAL)
2641 NumOfVertices = (nx+1) * (ny+1);
2642 NumOfElements = nx * ny;
2643 NumOfBdrElements = 2 * nx + 2 * ny;
2645 vertices.SetSize(NumOfVertices);
2646 elements.SetSize(NumOfElements);
2647 boundary.SetSize(NumOfBdrElements);
2654 for (j = 0; j < ny+1; j++)
2656 cy = ((double) j / ny) * sy;
2657 for (i = 0; i < nx+1; i++)
2659 cx = ((double) i / nx) * sx;
2660 vertices[k](0) = cx;
2661 vertices[k](1) = cy;
2670 NCMesh::GridSfcOrdering2D(nx, ny, sfc);
2671 MFEM_VERIFY(sfc.
Size() == 2*nx*ny,
"");
2673 for (k = 0; k < nx*ny; k++)
2677 ind[0] = i + j*(nx+1);
2678 ind[1] = i + 1 +j*(nx+1);
2679 ind[2] = i + 1 + (j+1)*(nx+1);
2680 ind[3] = i + (j+1)*(nx+1);
2687 for (j = 0; j < ny; j++)
2689 for (i = 0; i < nx; i++)
2691 ind[0] = i + j*(nx+1);
2692 ind[1] = i + 1 +j*(nx+1);
2693 ind[2] = i + 1 + (j+1)*(nx+1);
2694 ind[3] = i + (j+1)*(nx+1);
2703 for (i = 0; i < nx; i++)
2705 boundary[i] =
new Segment(i, i+1, 1);
2706 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2709 for (j = 0; j < ny; j++)
2711 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2712 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2716 else if (type == Element::TRIANGLE)
2718 NumOfVertices = (nx+1) * (ny+1);
2719 NumOfElements = 2 * nx * ny;
2720 NumOfBdrElements = 2 * nx + 2 * ny;
2722 vertices.SetSize(NumOfVertices);
2723 elements.SetSize(NumOfElements);
2724 boundary.SetSize(NumOfBdrElements);
2731 for (j = 0; j < ny+1; j++)
2733 cy = ((double) j / ny) * sy;
2734 for (i = 0; i < nx+1; i++)
2736 cx = ((double) i / nx) * sx;
2737 vertices[k](0) = cx;
2738 vertices[k](1) = cy;
2745 for (j = 0; j < ny; j++)
2747 for (i = 0; i < nx; i++)
2749 ind[0] = i + j*(nx+1);
2750 ind[1] = i + 1 + (j+1)*(nx+1);
2751 ind[2] = i + (j+1)*(nx+1);
2754 ind[1] = i + 1 + j*(nx+1);
2755 ind[2] = i + 1 + (j+1)*(nx+1);
2763 for (i = 0; i < nx; i++)
2765 boundary[i] =
new Segment(i, i+1, 1);
2766 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2769 for (j = 0; j < ny; j++)
2771 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2772 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2779 MFEM_ABORT(
"Unsupported element type.");
2783 CheckElementOrientation();
2785 if (generate_edges == 1)
2787 el_to_edge =
new Table;
2788 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2790 CheckBdrElementOrientation();
2799 attributes.Append(1);
2800 bdr_attributes.Append(1); bdr_attributes.Append(2);
2801 bdr_attributes.Append(3); bdr_attributes.Append(4);
2806 void Mesh::Make1D(
int n,
double sx)
2815 NumOfVertices = n + 1;
2817 NumOfBdrElements = 2;
2818 vertices.SetSize(NumOfVertices);
2819 elements.SetSize(NumOfElements);
2820 boundary.SetSize(NumOfBdrElements);
2823 for (j = 0; j < n+1; j++)
2825 vertices[j](0) = ((
double) j / n) * sx;
2829 for (j = 0; j < n; j++)
2831 elements[j] =
new Segment(j, j+1, 1);
2836 boundary[0] =
new Point(ind, 1);
2838 boundary[1] =
new Point(ind, 2);
2846 attributes.Append(1);
2847 bdr_attributes.Append(1); bdr_attributes.Append(2);
2850 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
2868 last_operation = Mesh::NONE;
2871 elements.SetSize(NumOfElements);
2872 for (
int i = 0; i < NumOfElements; i++)
2874 elements[i] = mesh.
elements[i]->Duplicate(
this);
2881 boundary.SetSize(NumOfBdrElements);
2882 for (
int i = 0; i < NumOfBdrElements; i++)
2884 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
2903 faces.SetSize(mesh.
faces.Size());
2904 for (
int i = 0; i < faces.Size(); i++)
2907 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
2941 if (dynamic_cast<const ParMesh*>(&mesh))
2953 if (mesh.
Nodes && copy_nodes)
2958 FiniteElementCollection::New(fec->
Name());
2962 Nodes->MakeOwner(fec_copy);
2963 *Nodes = *mesh.
Nodes;
2973 Mesh::Mesh(
const char *filename,
int generate_edges,
int refine,
2974 bool fix_orientation)
2983 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
2987 Load(imesh, generate_edges, refine, fix_orientation);
2991 Mesh::Mesh(std::istream &input,
int generate_edges,
int refine,
2992 bool fix_orientation)
2995 Load(input, generate_edges, refine, fix_orientation);
2998 void Mesh::ChangeVertexDataOwnership(
double *vertex_data,
int len_vertex_data,
3003 MFEM_VERIFY(len_vertex_data >= NumOfVertices * 3,
3004 "Not enough vertices in external array : "
3005 "len_vertex_data = "<< len_vertex_data <<
", "
3006 "NumOfVertices * 3 = " << NumOfVertices * 3);
3008 if (vertex_data == (
double *)(vertices.GetData()))
3010 MFEM_ASSERT(!vertices.OwnsData(),
"invalid ownership");
3015 memcpy(vertex_data, vertices.GetData(),
3016 NumOfVertices * 3 *
sizeof(double));
3019 vertices.MakeRef(reinterpret_cast<Vertex*>(vertex_data), NumOfVertices);
3022 Mesh::Mesh(
double *_vertices,
int num_vertices,
3024 int *element_attributes,
int num_elements,
3026 int *boundary_attributes,
int num_boundary_elements,
3027 int dimension,
int space_dimension)
3029 if (space_dimension == -1)
3031 space_dimension = dimension;
3034 InitMesh(dimension, space_dimension, 0, num_elements,
3035 num_boundary_elements);
3037 int element_index_stride = Geometry::NumVerts[element_type];
3038 int boundary_index_stride = num_boundary_elements > 0 ?
3039 Geometry::NumVerts[boundary_type] : 0;
3042 vertices.MakeRef(reinterpret_cast<Vertex*>(_vertices), num_vertices);
3043 NumOfVertices = num_vertices;
3045 for (
int i = 0; i < num_elements; i++)
3047 elements[i] = NewElement(element_type);
3048 elements[i]->SetVertices(element_indices + i * element_index_stride);
3049 elements[i]->SetAttribute(element_attributes[i]);
3051 NumOfElements = num_elements;
3053 for (
int i = 0; i < num_boundary_elements; i++)
3055 boundary[i] = NewElement(boundary_type);
3056 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
3057 boundary[i]->SetAttribute(boundary_attributes[i]);
3059 NumOfBdrElements = num_boundary_elements;
3068 case Geometry::POINT:
return (
new Point);
3069 case Geometry::SEGMENT:
return (
new Segment);
3070 case Geometry::TRIANGLE:
return (
new Triangle);
3072 case Geometry::TETRAHEDRON:
3073 #ifdef MFEM_USE_MEMALLOC
3074 return TetMemory.Alloc();
3078 case Geometry::CUBE:
return (
new Hexahedron);
3079 case Geometry::PRISM:
return (
new Wedge);
3081 MFEM_ABORT(
"invalid Geometry::Type, geom = " << geom);
3087 Element *Mesh::ReadElementWithoutAttr(std::istream &input)
3093 el = NewElement(geom);
3094 MFEM_VERIFY(el,
"Unsupported element type: " << geom);
3097 for (
int i = 0; i < nv; i++)
3105 void Mesh::PrintElementWithoutAttr(
const Element *el, std::ostream &
out)
3110 for (
int j = 0; j < nv; j++)
3123 el = ReadElementWithoutAttr(input);
3132 PrintElementWithoutAttr(el, out);
3135 void Mesh::SetMeshGen()
3137 meshgen = mesh_geoms = 0;
3138 for (
int i = 0; i < NumOfElements; i++)
3143 case Element::TETRAHEDRON:
3144 mesh_geoms |= (1 << Geometry::TETRAHEDRON);
3145 case Element::TRIANGLE:
3146 mesh_geoms |= (1 << Geometry::TRIANGLE);
3147 case Element::SEGMENT:
3148 mesh_geoms |= (1 << Geometry::SEGMENT);
3149 case Element::POINT:
3150 mesh_geoms |= (1 << Geometry::POINT);
3154 case Element::HEXAHEDRON:
3155 mesh_geoms |= (1 << Geometry::CUBE);
3156 case Element::QUADRILATERAL:
3157 mesh_geoms |= (1 << Geometry::SQUARE);
3158 mesh_geoms |= (1 << Geometry::SEGMENT);
3159 mesh_geoms |= (1 << Geometry::POINT);
3163 case Element::WEDGE:
3164 mesh_geoms |= (1 << Geometry::PRISM);
3165 mesh_geoms |= (1 << Geometry::SQUARE);
3166 mesh_geoms |= (1 << Geometry::TRIANGLE);
3167 mesh_geoms |= (1 << Geometry::SEGMENT);
3168 mesh_geoms |= (1 << Geometry::POINT);
3173 MFEM_ABORT(
"invalid element type: " << type);
3179 void Mesh::Loader(std::istream &input,
int generate_edges,
3180 std::string parse_tag)
3182 int curved = 0, read_gf = 1;
3183 bool finalize_topo =
true;
3187 MFEM_ABORT(
"Input stream is not open");
3194 getline(input, mesh_type);
3198 bool mfem_v10 = (mesh_type ==
"MFEM mesh v1.0");
3199 bool mfem_v11 = (mesh_type ==
"MFEM mesh v1.1");
3200 bool mfem_v12 = (mesh_type ==
"MFEM mesh v1.2");
3201 if (mfem_v10 || mfem_v11 || mfem_v12)
3207 if ( mfem_v12 && parse_tag.empty() )
3209 parse_tag =
"mfem_mesh_end";
3211 ReadMFEMMesh(input, mfem_v11, curved);
3213 else if (mesh_type ==
"linemesh")
3215 ReadLineMesh(input);
3217 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
3219 if (mesh_type ==
"curved_areamesh2")
3223 ReadNetgen2DMesh(input, curved);
3225 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
3227 ReadNetgen3DMesh(input);
3229 else if (mesh_type ==
"TrueGrid")
3231 ReadTrueGridMesh(input);
3233 else if (mesh_type ==
"# vtk DataFile Version 3.0" ||
3234 mesh_type ==
"# vtk DataFile Version 2.0")
3236 ReadVTKMesh(input, curved, read_gf, finalize_topo);
3238 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
3240 ReadNURBSMesh(input, curved, read_gf);
3242 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
3244 ReadInlineMesh(input, generate_edges);
3247 else if (mesh_type ==
"$MeshFormat")
3249 ReadGmshMesh(input);
3252 ((mesh_type.size() > 2 &&
3253 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
3254 (mesh_type.size() > 3 &&
3255 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
3260 #ifdef MFEM_USE_NETCDF
3261 ReadCubit(mesh_input->
filename.c_str(), curved, read_gf);
3263 MFEM_ABORT(
"NetCDF support requires configuration with"
3264 " MFEM_USE_NETCDF=YES");
3270 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
3271 " Use mfem::named_ifgzstream for input.");
3277 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
3305 if (curved && read_gf)
3309 spaceDim = Nodes->VectorDim();
3310 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
3312 for (
int i = 0; i < spaceDim; i++)
3315 Nodes->GetNodalValues(vert_val, i+1);
3316 for (
int j = 0; j < NumOfVertices; j++)
3318 vertices[j](i) = vert_val(j);
3331 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
3332 getline(input, line);
3338 if (line ==
"mfem_mesh_end") {
break; }
3340 while (line != parse_tag);
3346 Mesh::Mesh(
Mesh *mesh_array[],
int num_pieces)
3348 int i, j, ie, ib, iv, *v, nv;
3357 if (mesh_array[0]->NURBSext)
3362 NumOfVertices = NURBSext->GetNV();
3363 NumOfElements = NURBSext->GetNE();
3365 NURBSext->GetElementTopo(elements);
3378 NumOfBdrElements = 0;
3379 for (i = 0; i < num_pieces; i++)
3381 NumOfBdrElements += mesh_array[i]->
GetNBE();
3383 boundary.SetSize(NumOfBdrElements);
3384 vertices.SetSize(NumOfVertices);
3386 for (i = 0; i < num_pieces; i++)
3392 for (j = 0; j < m->
GetNE(); j++)
3394 elements[lelem_elem[j]]->SetAttribute(m->
GetAttribute(j));
3397 for (j = 0; j < m->
GetNBE(); j++)
3402 for (
int k = 0; k < nv; k++)
3404 v[k] = lvert_vert[v[k]];
3406 boundary[ib++] = el;
3409 for (j = 0; j < m->
GetNV(); j++)
3419 NumOfBdrElements = 0;
3421 for (i = 0; i < num_pieces; i++)
3424 NumOfElements += m->
GetNE();
3425 NumOfBdrElements += m->
GetNBE();
3426 NumOfVertices += m->
GetNV();
3428 elements.SetSize(NumOfElements);
3429 boundary.SetSize(NumOfBdrElements);
3430 vertices.SetSize(NumOfVertices);
3432 for (i = 0; i < num_pieces; i++)
3436 for (j = 0; j < m->
GetNE(); j++)
3441 for (
int k = 0; k < nv; k++)
3445 elements[ie++] = el;
3448 for (j = 0; j < m->
GetNBE(); j++)
3453 for (
int k = 0; k < nv; k++)
3457 boundary[ib++] = el;
3460 for (j = 0; j < m->
GetNV(); j++)
3474 for (i = 0; i < num_pieces; i++)
3476 gf_array[i] = mesh_array[i]->
GetNodes();
3483 CheckElementOrientation(
false);
3484 CheckBdrElementOrientation(
false);
3488 Mesh::Mesh(
Mesh *orig_mesh,
int ref_factor,
int ref_type)
3491 MFEM_VERIFY(ref_factor >= 1,
"the refinement factor must be >= 1");
3492 MFEM_VERIFY(ref_type == BasisType::ClosedUniform ||
3493 ref_type == BasisType::GaussLobatto,
"invalid refinement type");
3494 MFEM_VERIFY(Dim == 1 || Dim == 2 || Dim == 3,
3495 "only implemented for Segment, Quadrilateral and Hexahedron "
3496 "elements in 1D/2D/3D");
3498 "meshes with mixed elements are not supported");
3505 int r_bndr_factor = pow(ref_factor, Dim - 1);
3506 int r_elem_factor = ref_factor * r_bndr_factor;
3509 int r_num_elem = orig_mesh->
GetNE() * r_elem_factor;
3510 int r_num_bndr = orig_mesh->
GetNBE() * r_bndr_factor;
3512 InitMesh(Dim, orig_mesh->
SpaceDimension(), r_num_vert, r_num_elem,
3516 NumOfVertices = r_num_vert;
3522 DenseMatrix node_coordinates(spaceDim*pow(2, Dim), r_num_elem);
3525 for (
int el = 0; el < orig_mesh->
GetNE(); el++)
3529 int nvert = Geometry::NumVerts[
geom];
3532 max_nv = std::max(max_nv, nvert);
3538 const int *c2h_map = rfec.GetDofMap(geom);
3539 const int *vertex_map = vertex_fec.
GetDofMap(geom);
3540 for (
int i = 0; i < phys_pts.
Width(); i++)
3542 vertices[rdofs[i]].SetCoords(spaceDim, phys_pts.
GetColumn(i));
3546 Element *elem = NewElement(geom);
3549 for (
int k = 0; k < nvert; k++)
3552 v[k] = rdofs[c2h_map[cid]];
3554 for (
int k = 0; k < nvert; k++)
3556 for (
int j = 0; j < spaceDim; ++j)
3558 node_coordinates(k*spaceDim + j, NumOfElements)
3559 = vertices[v[vertex_map[k]]](j);
3566 SetCurvature(1,
true, spaceDim);
3567 Vector node_coordinates_vec(
3568 node_coordinates.
Data(),
3569 node_coordinates.
Width()*node_coordinates.
Height());
3570 SetNodes(node_coordinates_vec);
3573 for (
int el = 0; el < orig_mesh->
GetNBE(); el++)
3577 int nvert = Geometry::NumVerts[
geom];
3588 Element *elem = NewElement(geom);
3591 v[0] = rdofs[RG.
RefGeoms[nvert*j]];
3592 AddBdrElement(elem);
3597 const int *c2h_map = rfec.GetDofMap(geom);
3600 Element *elem = NewElement(geom);
3603 for (
int k = 0; k < nvert; k++)
3606 v[k] = rdofs[c2h_map[cid]];
3608 AddBdrElement(elem);
3613 FinalizeTopology(
false);
3615 last_operation = Mesh::REFINE;
3618 CoarseFineTr.embeddings.SetSize(GetNE());
3619 if (orig_mesh->
GetNE() > 0)
3623 CoarseFineTr.point_matrices[
geom].SetSize(Dim, max_nv, r_elem_factor);
3624 int nvert = Geometry::NumVerts[
geom];
3626 const int *c2h_map = rfec.GetDofMap(geom);
3631 for (
int k = 0; k < nvert; k++)
3639 for (
int el = 0; el < GetNE(); el++)
3641 Embedding &emb = CoarseFineTr.embeddings[el];
3642 emb.
parent = el / r_elem_factor;
3643 emb.
matrix = el % r_elem_factor;
3646 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
3647 MFEM_ASSERT(CheckBdrElementOrientation(
false) == 0,
"");
3652 if (NURBSext == NULL)
3654 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
3657 if (kv.
Size() != NURBSext->GetNKV())
3659 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
3662 NURBSext->ConvertToPatches(*Nodes);
3664 NURBSext->KnotInsert(kv);
3666 last_operation = Mesh::NONE;
3674 if (NURBSext == NULL)
3676 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
3679 if (kv.
Size() != NURBSext->GetNKV())
3681 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
3684 NURBSext->ConvertToPatches(*Nodes);
3686 NURBSext->KnotInsert(kv);
3688 last_operation = Mesh::NONE;
3694 void Mesh::NURBSUniformRefinement()
3697 NURBSext->ConvertToPatches(*Nodes);
3699 NURBSext->UniformRefinement();
3701 last_operation = Mesh::NONE;
3707 void Mesh::DegreeElevate(
int rel_degree,
int degree)
3709 if (NURBSext == NULL)
3711 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
3714 NURBSext->ConvertToPatches(*Nodes);
3716 NURBSext->DegreeElevate(rel_degree, degree);
3718 last_operation = Mesh::NONE;
3724 void Mesh::UpdateNURBS()
3728 NURBSext->SetKnotsFromPatches();
3730 Dim = NURBSext->Dimension();
3733 if (NumOfElements != NURBSext->GetNE())
3735 for (
int i = 0; i < elements.Size(); i++)
3737 FreeElement(elements[i]);
3739 NumOfElements = NURBSext->GetNE();
3740 NURBSext->GetElementTopo(elements);
3743 if (NumOfBdrElements != NURBSext->GetNBE())
3745 for (
int i = 0; i < boundary.Size(); i++)
3747 FreeElement(boundary[i]);
3749 NumOfBdrElements = NURBSext->GetNBE();
3750 NURBSext->GetBdrElementTopo(boundary);
3753 Nodes->FESpace()->Update();
3755 NURBSext->SetCoordsFromPatches(*Nodes);
3757 if (NumOfVertices != NURBSext->GetNV())
3759 NumOfVertices = NURBSext->GetNV();
3760 vertices.SetSize(NumOfVertices);
3761 int vd = Nodes->VectorDim();
3762 for (
int i = 0; i < vd; i++)
3765 Nodes->GetNodalValues(vert_val, i+1);
3766 for (
int j = 0; j < NumOfVertices; j++)
3768 vertices[j](i) = vert_val(j);
3775 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3784 GetElementToFaceTable();
3789 void Mesh::LoadPatchTopo(std::istream &input,
Array<int> &edge_to_knot)
3805 input >> NumOfElements;
3806 elements.SetSize(NumOfElements);
3807 for (
int j = 0; j < NumOfElements; j++)
3809 elements[j] = ReadElement(input);
3815 input >> NumOfBdrElements;
3816 boundary.SetSize(NumOfBdrElements);
3817 for (
int j = 0; j < NumOfBdrElements; j++)
3819 boundary[j] = ReadElement(input);
3825 input >> NumOfEdges;
3826 edge_vertex =
new Table(NumOfEdges, 2);
3827 edge_to_knot.
SetSize(NumOfEdges);
3828 for (
int j = 0; j < NumOfEdges; j++)
3830 int *v = edge_vertex->GetRow(j);
3831 input >> edge_to_knot[j] >> v[0] >> v[1];
3834 edge_to_knot[j] = -1 - edge_to_knot[j];
3841 input >> NumOfVertices;
3842 vertices.SetSize(0);
3845 CheckBdrElementOrientation();
3852 for (
int d = 0; d < v.
Size(); d++)
3860 for (d = 0; d < p.
Size(); d++)
3864 for ( ; d < v.
Size(); d++)
3873 if (Nodes == NULL || Nodes->FESpace() != nodes.
FESpace())
3888 SetNodalGridFunction(nodes,
true);
3891 void Mesh::EnsureNodes()
3896 if (dynamic_cast<const H1_FECollection*>(fec)
3897 || dynamic_cast<const L2_FECollection*>(fec))
3903 const int order = GetNodalFESpace()->GetOrder(0);
3904 SetCurvature(order,
false, -1, Ordering::byVDIM);
3909 SetCurvature(1,
false, -1, Ordering::byVDIM);
3916 NewNodes(*nodes, make_owner);
3921 return ((Nodes) ? Nodes->FESpace() : NULL);
3924 void Mesh::SetCurvature(
int order,
bool discont,
int space_dim,
int ordering)
3926 space_dim = (space_dim == -1) ? spaceDim : space_dim;
3939 SetNodalFESpace(nfes);
3940 Nodes->MakeOwner(nfec);
3943 int Mesh::GetNumFaces()
const
3947 case 1:
return GetNV();
3948 case 2:
return GetNEdges();
3949 case 3:
return GetNFaces();
3954 static int CountFacesByType(
const Mesh &mesh,
const FaceType type)
3963 if ((type==FaceType::Interior && (e2>=0 || (e2<0 && inf2>=0))) ||
3964 (type==FaceType::Boundary && e2<0 && inf2<0) ) { nf++; }
3971 const bool isInt = type==FaceType::Interior;
3972 int &nf = isInt ? nbInteriorFaces : nbBoundaryFaces;
3973 if (nf<0) { nf = CountFacesByType(*
this, type); }
3977 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3978 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
3981 int Mesh::CheckElementOrientation(
bool fix_it)
3983 int i, j, k, wo = 0, fo = 0, *vi = 0;
3986 if (Dim == 2 && spaceDim == 2)
3990 for (i = 0; i < NumOfElements; i++)
3994 vi = elements[i]->GetVertices();
3995 for (j = 0; j < 3; j++)
3997 v[j] = vertices[vi[j]]();
3999 for (j = 0; j < 2; j++)
4000 for (k = 0; k < 2; k++)
4002 J(j, k) = v[j+1][k] - v[0][k];
4008 GetElementJacobian(i, J);
4014 switch (GetElementType(i))
4016 case Element::TRIANGLE:
4019 case Element::QUADRILATERAL:
4023 MFEM_ABORT(
"Invalid 2D element type \""
4024 << GetElementType(i) <<
"\"");
4038 for (i = 0; i < NumOfElements; i++)
4040 vi = elements[i]->GetVertices();
4041 switch (GetElementType(i))
4043 case Element::TETRAHEDRON:
4046 for (j = 0; j < 4; j++)
4048 v[j] = vertices[vi[j]]();
4050 for (j = 0; j < 3; j++)
4051 for (k = 0; k < 3; k++)
4053 J(j, k) = v[j+1][k] - v[0][k];
4059 GetElementJacobian(i, J);
4072 case Element::WEDGE:
4074 GetElementJacobian(i, J);
4085 case Element::HEXAHEDRON:
4087 GetElementJacobian(i, J);
4099 MFEM_ABORT(
"Invalid 3D element type \""
4100 << GetElementType(i) <<
"\"");
4105 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
4108 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / "
4109 << NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
4116 int Mesh::GetTriOrientation(
const int *base,
const int *test)
4124 if (test[0] == base[0])
4125 if (test[1] == base[1])
4133 else if (test[0] == base[1])
4134 if (test[1] == base[0])
4143 if (test[1] == base[0])
4153 const int *aor = tri_t::Orient[orient];
4154 for (
int j = 0; j < 3; j++)
4155 if (test[aor[j]] != base[j])
4164 int Mesh::GetQuadOrientation(
const int *base,
const int *test)
4168 for (i = 0; i < 4; i++)
4169 if (test[i] == base[0])
4176 if (test[(i+1)%4] == base[1])
4184 const int *aor = quad_t::Orient[orient];
4185 for (
int j = 0; j < 4; j++)
4186 if (test[aor[j]] != base[j])
4188 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
4190 for (
int k = 0; k < 4; k++)
4195 for (
int k = 0; k < 4; k++)
4204 if (test[(i+1)%4] == base[1])
4212 int Mesh::CheckBdrElementOrientation(
bool fix_it)
4218 if (el_to_edge == NULL)
4220 el_to_edge =
new Table;
4221 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
4224 for (
int i = 0; i < NumOfBdrElements; i++)
4226 if (faces_info[be_to_edge[i]].Elem2No < 0)
4228 int *bv = boundary[i]->GetVertices();
4229 int *fv = faces[be_to_edge[i]]->GetVertices();
4234 mfem::Swap<int>(bv[0], bv[1]);
4244 for (
int i = 0; i < NumOfBdrElements; i++)
4246 const int fi = be_to_face[i];
4248 if (faces_info[fi].Elem2No >= 0) {
continue; }
4251 int *bv = boundary[i]->GetVertices();
4253 MFEM_ASSERT(fi < faces.Size(),
"internal error");
4254 const int *fv = faces[fi]->GetVertices();
4260 case Element::TRIANGLE:
4262 orientation = GetTriOrientation(fv, bv);
4265 case Element::QUADRILATERAL:
4267 orientation = GetQuadOrientation(fv, bv);
4271 MFEM_ABORT(
"Invalid 2D boundary element type \""
4272 << bdr_type <<
"\"");
4277 if (orientation % 2 == 0) {
continue; }
4279 if (!fix_it) {
continue; }
4283 case Element::TRIANGLE:
4287 mfem::Swap<int>(bv[0], bv[1]);
4290 int *be = bel_to_edge->GetRow(i);
4291 mfem::Swap<int>(be[1], be[2]);
4295 case Element::QUADRILATERAL:
4297 mfem::Swap<int>(bv[0], bv[2]);
4300 int *be = bel_to_edge->GetRow(i);
4301 mfem::Swap<int>(be[0], be[1]);
4302 mfem::Swap<int>(be[2], be[3]);
4315 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / "
4316 << NumOfBdrElements <<
" (" << fixed_or_not[fix_it ? 0 : 1]
4323 int Mesh::GetNumGeometries(
int dim)
const
4325 MFEM_ASSERT(0 <= dim && dim <= Dim,
"invalid dim: " << dim);
4327 for (
int g = Geometry::DimStart[dim]; g < Geometry::DimStart[dim+1]; g++)
4336 MFEM_ASSERT(0 <= dim && dim <= Dim,
"invalid dim: " << dim);
4338 for (
int g = Geometry::DimStart[dim]; g < Geometry::DimStart[dim+1]; g++)
4351 el_to_edge->GetRow(i, edges);
4355 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
4356 "is not generated.");
4359 const int *v = elements[i]->GetVertices();
4360 const int ne = elements[i]->GetNEdges();
4362 for (
int j = 0; j < ne; j++)
4364 const int *e = elements[i]->GetEdgeVertices(j);
4365 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
4375 edges[0] = be_to_edge[i];
4376 const int *v = boundary[i]->GetVertices();
4377 cor[0] = (v[0] < v[1]) ? (1) : (-1);
4383 bel_to_edge->GetRow(i, edges);
4390 const int *v = boundary[i]->GetVertices();
4391 const int ne = boundary[i]->GetNEdges();
4393 for (
int j = 0; j < ne; j++)
4395 const int *e = boundary[i]->GetEdgeVertices(j);
4396 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
4408 const int *v = faces[i]->GetVertices();
4409 o[0] = (v[0] < v[1]) ? (1) : (-1);
4419 face_edge->GetRow(i, edges);
4421 const int *v = faces[i]->GetVertices();
4422 const int ne = faces[i]->GetNEdges();
4424 for (
int j = 0; j < ne; j++)
4426 const int *e = faces[i]->GetEdgeVertices(j);
4427 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
4436 if (!edge_vertex) { GetEdgeVertexTable(); }
4437 edge_vertex->GetRow(i, vert);
4453 if (faces.Size() != NumOfFaces)
4455 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
4459 DSTable v_to_v(NumOfVertices);
4460 GetVertexToVertexTable(v_to_v);
4462 face_edge =
new Table;
4463 GetElementArrayEdgeTable(faces, v_to_v, *face_edge);
4475 DSTable v_to_v(NumOfVertices);
4476 GetVertexToVertexTable(v_to_v);
4479 edge_vertex =
new Table(nedges, 2);
4480 for (
int i = 0; i < NumOfVertices; i++)
4485 edge_vertex->Push(j, i);
4486 edge_vertex->Push(j, it.Column());
4489 edge_vertex->Finalize();
4500 vert_elem->
MakeI(NumOfVertices);
4502 for (i = 0; i < NumOfElements; i++)
4504 nv = elements[i]->GetNVertices();
4505 v = elements[i]->GetVertices();
4506 for (j = 0; j < nv; j++)
4514 for (i = 0; i < NumOfElements; i++)
4516 nv = elements[i]->GetNVertices();
4517 v = elements[i]->GetVertices();
4518 for (j = 0; j < nv; j++)
4529 Table *Mesh::GetFaceToElementTable()
const
4533 face_elem->
MakeI(faces_info.Size());
4535 for (
int i = 0; i < faces_info.Size(); i++)
4537 if (faces_info[i].Elem2No >= 0)
4549 for (
int i = 0; i < faces_info.Size(); i++)
4552 if (faces_info[i].Elem2No >= 0)
4570 el_to_face->
GetRow(i, fcs);
4574 mfem_error(
"Mesh::GetElementFaces(...) : el_to_face not generated.");
4579 for (j = 0; j < n; j++)
4580 if (faces_info[fcs[j]].Elem1No == i)
4582 cor[j] = faces_info[fcs[j]].Elem1Inf % 64;
4585 else if (faces_info[fcs[j]].Elem2No == i)
4587 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
4591 mfem_error(
"Mesh::GetElementFaces(...) : 2");
4596 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
4601 void Mesh::GetBdrElementFace(
int i,
int *f,
int *o)
const
4606 bv = boundary[i]->GetVertices();
4607 fv = faces[be_to_face[i]]->GetVertices();
4611 switch (GetBdrElementType(i))
4613 case Element::TRIANGLE:
4614 *o = GetTriOrientation(fv, bv);
4616 case Element::QUADRILATERAL:
4617 *o = GetQuadOrientation(fv, bv);
4620 mfem_error(
"Mesh::GetBdrElementFace(...) 2");
4624 int Mesh::GetBdrElementEdgeIndex(
int i)
const
4628 case 1:
return boundary[i]->GetVertices()[0];
4629 case 2:
return be_to_edge[i];
4630 case 3:
return be_to_face[i];
4631 default:
mfem_error(
"Mesh::GetBdrElementEdgeIndex: invalid dimension!");
4636 void Mesh::GetBdrElementAdjacentElement(
int bdr_el,
int &el,
int &info)
const
4638 int fid = GetBdrElementEdgeIndex(bdr_el);
4639 const FaceInfo &fi = faces_info[fid];
4640 MFEM_ASSERT(fi.
Elem1Inf%64 == 0,
"internal error");
4641 const int *fv = (Dim > 1) ? faces[fid]->GetVertices() : NULL;
4642 const int *bv = boundary[bdr_el]->GetVertices();
4644 switch (GetBdrElementBaseGeometry(bdr_el))
4646 case Geometry::POINT: ori = 0;
break;
4647 case Geometry::SEGMENT: ori = (fv[0] == bv[0]) ? 0 : 1;
break;
4648 case Geometry::TRIANGLE: ori = GetTriOrientation(fv, bv);
break;
4649 case Geometry::SQUARE: ori = GetQuadOrientation(fv, bv);
break;
4650 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
4658 return elements[i]->GetType();
4663 return boundary[i]->GetType();
4671 v = elements[i]->GetVertices();
4672 nv = elements[i]->GetNVertices();
4674 pointmat.
SetSize(spaceDim, nv);
4675 for (k = 0; k < spaceDim; k++)
4676 for (j = 0; j < nv; j++)
4678 pointmat(k, j) = vertices[v[j]](k);
4687 v = boundary[i]->GetVertices();
4688 nv = boundary[i]->GetNVertices();
4690 pointmat.
SetSize(spaceDim, nv);
4691 for (k = 0; k < spaceDim; k++)
4692 for (j = 0; j < nv; j++)
4694 pointmat(k, j) = vertices[v[j]](k);
4698 double Mesh::GetLength(
int i,
int j)
const
4700 const double *vi = vertices[i]();
4701 const double *vj = vertices[j]();
4704 for (
int k = 0; k < spaceDim; k++)
4706 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
4709 return sqrt(length);
4717 for (
int i = 0; i < elem_array.
Size(); i++)
4722 for (
int i = 0; i < elem_array.
Size(); i++)
4724 const int *v = elem_array[i]->GetVertices();
4725 const int ne = elem_array[i]->GetNEdges();
4726 for (
int j = 0; j < ne; j++)
4728 const int *e = elem_array[i]->GetEdgeVertices(j);
4735 void Mesh::GetVertexToVertexTable(
DSTable &v_to_v)
const
4739 for (
int i = 0; i < edge_vertex->Size(); i++)
4741 const int *v = edge_vertex->GetRow(i);
4742 v_to_v.
Push(v[0], v[1]);
4747 for (
int i = 0; i < NumOfElements; i++)
4749 const int *v = elements[i]->GetVertices();
4750 const int ne = elements[i]->GetNEdges();
4751 for (
int j = 0; j < ne; j++)
4753 const int *e = elements[i]->GetEdgeVertices(j);
4754 v_to_v.
Push(v[e[0]], v[e[1]]);
4762 int i, NumberOfEdges;
4764 DSTable v_to_v(NumOfVertices);
4765 GetVertexToVertexTable(v_to_v);
4770 GetElementArrayEdgeTable(elements, v_to_v, e_to_f);
4775 be_to_f.
SetSize(NumOfBdrElements);
4776 for (i = 0; i < NumOfBdrElements; i++)
4778 const int *v = boundary[i]->GetVertices();
4779 be_to_f[i] = v_to_v(v[0], v[1]);
4784 if (bel_to_edge == NULL)
4786 bel_to_edge =
new Table;
4788 GetElementArrayEdgeTable(boundary, v_to_v, *bel_to_edge);
4792 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
4796 return NumberOfEdges;
4799 const Table & Mesh::ElementToElementTable()
4807 MFEM_ASSERT(faces_info.Size() >= GetNumFaces(),
"faces were not generated!");
4810 conn.
Reserve(2*faces_info.Size());
4812 for (
int i = 0; i < faces_info.Size(); i++)
4814 const FaceInfo &fi = faces_info[i];
4822 int nbr_elem_idx = NumOfElements - 1 - fi.
Elem2No;
4830 el_to_el =
new Table(NumOfElements, conn);
4835 const Table & Mesh::ElementToFaceTable()
const
4837 if (el_to_face == NULL)
4844 const Table & Mesh::ElementToEdgeTable()
const
4846 if (el_to_edge == NULL)
4853 void Mesh::AddPointFaceElement(
int lf,
int gf,
int el)
4855 if (faces_info[gf].Elem1No == -1)
4858 faces_info[gf].Elem1No = el;
4859 faces_info[gf].Elem1Inf = 64 * lf;
4860 faces_info[gf].Elem2No = -1;
4861 faces_info[gf].Elem2Inf = -1;
4865 faces_info[gf].Elem2No = el;
4866 faces_info[gf].Elem2Inf = 64 * lf + 1;
4870 void Mesh::AddSegmentFaceElement(
int lf,
int gf,
int el,
int v0,
int v1)
4872 if (faces[gf] == NULL)
4874 faces[gf] =
new Segment(v0, v1);
4875 faces_info[gf].Elem1No = el;
4876 faces_info[gf].Elem1Inf = 64 * lf;
4877 faces_info[gf].Elem2No = -1;
4878 faces_info[gf].Elem2Inf = -1;
4882 int *v = faces[gf]->GetVertices();
4883 faces_info[gf].Elem2No = el;
4884 if ( v[1] == v0 && v[0] == v1 )
4886 faces_info[gf].Elem2Inf = 64 * lf + 1;
4888 else if ( v[0] == v0 && v[1] == v1 )
4894 faces_info[gf].Elem2Inf = 64 * lf;
4898 MFEM_ABORT(
"internal error");
4903 void Mesh::AddTriangleFaceElement(
int lf,
int gf,
int el,
4904 int v0,
int v1,
int v2)
4906 if (faces[gf] == NULL)
4908 faces[gf] =
new Triangle(v0, v1, v2);
4909 faces_info[gf].Elem1No = el;
4910 faces_info[gf].Elem1Inf = 64 * lf;
4911 faces_info[gf].Elem2No = -1;
4912 faces_info[gf].Elem2Inf = -1;
4916 int orientation, vv[3] = { v0, v1, v2 };
4917 orientation = GetTriOrientation(faces[gf]->GetVertices(), vv);
4922 faces_info[gf].Elem2No = el;
4923 faces_info[gf].Elem2Inf = 64 * lf + orientation;
4927 void Mesh::AddQuadFaceElement(
int lf,
int gf,
int el,
4928 int v0,
int v1,
int v2,
int v3)
4930 if (faces_info[gf].Elem1No < 0)
4933 faces_info[gf].Elem1No = el;
4934 faces_info[gf].Elem1Inf = 64 * lf;
4935 faces_info[gf].Elem2No = -1;
4936 faces_info[gf].Elem2Inf = -1;
4940 int vv[4] = { v0, v1, v2, v3 };
4941 int oo = GetQuadOrientation(faces[gf]->GetVertices(), vv);
4945 faces_info[gf].Elem2No = el;
4946 faces_info[gf].Elem2Inf = 64 * lf + oo;
4950 void Mesh::GenerateFaces()
4952 int i, nfaces = GetNumFaces();
4954 for (i = 0; i < faces.Size(); i++)
4956 FreeElement(faces[i]);
4960 faces.SetSize(nfaces);
4961 faces_info.SetSize(nfaces);
4962 for (i = 0; i < nfaces; i++)
4965 faces_info[i].Elem1No = -1;
4966 faces_info[i].NCFace = -1;
4968 for (i = 0; i < NumOfElements; i++)
4970 const int *v = elements[i]->GetVertices();
4974 AddPointFaceElement(0, v[0], i);
4975 AddPointFaceElement(1, v[1], i);
4979 ef = el_to_edge->GetRow(i);
4980 const int ne = elements[i]->GetNEdges();
4981 for (
int j = 0; j < ne; j++)
4983 const int *e = elements[i]->GetEdgeVertices(j);
4984 AddSegmentFaceElement(j, ef[j], i, v[e[0]], v[e[1]]);
4989 ef = el_to_face->GetRow(i);
4990 switch (GetElementType(i))
4992 case Element::TETRAHEDRON:
4994 for (
int j = 0; j < 4; j++)
4996 const int *fv = tet_t::FaceVert[j];
4997 AddTriangleFaceElement(j, ef[j], i,
4998 v[fv[0]], v[fv[1]], v[fv[2]]);
5002 case Element::WEDGE:
5004 for (
int j = 0; j < 2; j++)
5006 const int *fv = pri_t::FaceVert[j];
5007 AddTriangleFaceElement(j, ef[j], i,
5008 v[fv[0]], v[fv[1]], v[fv[2]]);
5010 for (
int j = 2; j < 5; j++)
5012 const int *fv = pri_t::FaceVert[j];
5013 AddQuadFaceElement(j, ef[j], i,
5014 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
5018 case Element::HEXAHEDRON:
5020 for (
int j = 0; j < 6; j++)
5022 const int *fv = hex_t::FaceVert[j];
5023 AddQuadFaceElement(j, ef[j], i,
5024 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
5029 MFEM_ABORT(
"Unexpected type of Element.");
5035 void Mesh::GenerateNCFaceInfo()
5037 MFEM_VERIFY(ncmesh,
"missing NCMesh.");
5039 for (
int i = 0; i < faces_info.Size(); i++)
5041 faces_info[i].NCFace = -1;
5045 (Dim == 2) ? ncmesh->GetEdgeList() : ncmesh->GetFaceList();
5047 nc_faces_info.SetSize(0);
5048 nc_faces_info.Reserve(list.
masters.size() + list.
slaves.size());
5050 int nfaces = GetNumFaces();
5053 for (
unsigned i = 0; i < list.
masters.size(); i++)
5056 if (master.
index >= nfaces) {
continue; }
5058 faces_info[master.
index].NCFace = nc_faces_info.Size();
5064 for (
unsigned i = 0; i < list.
slaves.size(); i++)
5068 if (slave.
index < 0 ||
5069 slave.
index >= nfaces ||
5079 slave_fi.
NCFace = nc_faces_info.Size();
5091 for (
int i = 0; i < NumOfElements; i++)
5093 const int *v = elements[i]->GetVertices();
5094 switch (GetElementType(i))
5096 case Element::TETRAHEDRON:
5098 for (
int j = 0; j < 4; j++)
5100 const int *fv = tet_t::FaceVert[j];
5101 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
5105 case Element::WEDGE:
5107 for (
int j = 0; j < 2; j++)
5109 const int *fv = pri_t::FaceVert[j];
5110 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
5112 for (
int j = 2; j < 5; j++)
5114 const int *fv = pri_t::FaceVert[j];
5115 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
5119 case Element::HEXAHEDRON:
5123 for (
int j = 0; j < 6; j++)
5125 const int *fv = hex_t::FaceVert[j];
5126 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
5131 MFEM_ABORT(
"Unexpected type of Element.");
5142 if (el_to_face != NULL)
5146 el_to_face =
new Table(NumOfElements, 6);
5147 faces_tbl =
new STable3D(NumOfVertices);
5148 for (i = 0; i < NumOfElements; i++)
5150 v = elements[i]->GetVertices();
5151 switch (GetElementType(i))
5153 case Element::TETRAHEDRON:
5155 for (
int j = 0; j < 4; j++)
5157 const int *fv = tet_t::FaceVert[j];
5159 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
5163 case Element::WEDGE:
5165 for (
int j = 0; j < 2; j++)
5167 const int *fv = pri_t::FaceVert[j];
5169 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
5171 for (
int j = 2; j < 5; j++)
5173 const int *fv = pri_t::FaceVert[j];
5175 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
5179 case Element::HEXAHEDRON:
5183 for (
int j = 0; j < 6; j++)
5185 const int *fv = hex_t::FaceVert[j];
5187 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
5192 MFEM_ABORT(
"Unexpected type of Element.");
5195 el_to_face->Finalize();
5197 be_to_face.SetSize(NumOfBdrElements);
5198 for (i = 0; i < NumOfBdrElements; i++)
5200 v = boundary[i]->GetVertices();
5201 switch (GetBdrElementType(i))
5203 case Element::TRIANGLE:
5205 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2]);
5208 case Element::QUADRILATERAL:
5210 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
5214 MFEM_ABORT(
"Unexpected type of boundary Element.");
5228 void Rotate3(
int &
a,
int &
b,
int &c)
5250 void Mesh::ReorientTetMesh()
5252 if (Dim != 3 || !(meshgen & 1))
5260 Table *old_elem_vert = NULL;
5264 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
5267 for (
int i = 0; i < NumOfElements; i++)
5269 if (GetElementType(i) == Element::TETRAHEDRON)
5271 int *v = elements[i]->GetVertices();
5273 Rotate3(v[0], v[1], v[2]);
5276 Rotate3(v[1], v[2], v[3]);
5285 for (
int i = 0; i < NumOfBdrElements; i++)
5287 if (GetBdrElementType(i) == Element::TRIANGLE)
5289 int *v = boundary[i]->GetVertices();
5291 Rotate3(v[0], v[1], v[2]);
5297 GetElementToFaceTable();
5301 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5306 DoNodeReorder(old_v_to_v, old_elem_vert);
5307 delete old_elem_vert;
5312 int *Mesh::CartesianPartitioning(
int nxyz[])
5318 for (
int vi = 0; vi < NumOfVertices; vi++)
5320 const double *p = vertices[vi]();
5321 for (
int i = 0; i < spaceDim; i++)
5323 if (p[i] < pmin[i]) { pmin[i] = p[i]; }
5324 if (p[i] > pmax[i]) { pmax[i] = p[i]; }
5328 partitioning =
new int[NumOfElements];
5332 Vector pt(ppt, spaceDim);
5333 for (
int el = 0; el < NumOfElements; el++)
5335 GetElementTransformation(el)->Transform(
5338 for (
int i = spaceDim-1; i >= 0; i--)
5340 int idx = (int)floor(nxyz[i]*((pt(i) - pmin[i])/(pmax[i] - pmin[i])));
5341 if (idx < 0) { idx = 0; }
5342 if (idx >= nxyz[i]) { idx = nxyz[i]-1; }
5343 part = part * nxyz[i] + idx;
5345 partitioning[el] = part;
5348 return partitioning;
5351 int *Mesh::GeneratePartitioning(
int nparts,
int part_method)
5353 #ifdef MFEM_USE_METIS
5355 int print_messages = 1;
5358 int init_flag, fin_flag;
5359 MPI_Initialized(&init_flag);
5360 MPI_Finalized(&fin_flag);
5361 if (init_flag && !fin_flag)
5365 if (rank != 0) { print_messages = 0; }
5369 int i, *partitioning;
5371 ElementToElementTable();
5373 partitioning =
new int[NumOfElements];
5377 for (i = 0; i < NumOfElements; i++)
5379 partitioning[i] = 0;
5382 else if (NumOfElements <= nparts)
5384 for (i = 0; i < NumOfElements; i++)
5386 partitioning[i] = i;
5392 #ifndef MFEM_USE_METIS_5
5404 bool freedata =
false;
5406 idx_t *mpartitioning;
5409 if (
sizeof(
idx_t) ==
sizeof(int))
5411 I = (
idx_t*) el_to_el->GetI();
5412 J = (
idx_t*) el_to_el->GetJ();
5413 mpartitioning = (
idx_t*) partitioning;
5417 int *iI = el_to_el->GetI();
5418 int *iJ = el_to_el->GetJ();
5422 for (
int k = 0; k < n+1; k++) { I[k] = iI[k]; }
5423 for (
int k = 0; k < m; k++) { J[k] = iJ[k]; }
5424 mpartitioning =
new idx_t[n];
5427 #ifndef MFEM_USE_METIS_5
5430 METIS_SetDefaultOptions(options);
5431 options[METIS_OPTION_CONTIG] = 1;
5435 if (part_method >= 0 && part_method <= 2)
5437 for (i = 0; i < n; i++)
5443 std::sort(J+I[i], J+I[i+1], std::greater<idx_t>());
5449 if (part_method == 0 || part_method == 3)
5451 #ifndef MFEM_USE_METIS_5
5480 " error in METIS_PartGraphRecursive!");
5487 if (part_method == 1 || part_method == 4)
5489 #ifndef MFEM_USE_METIS_5
5518 " error in METIS_PartGraphKway!");
5525 if (part_method == 2 || part_method == 5)
5527 #ifndef MFEM_USE_METIS_5
5540 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_VOL;
5557 " error in METIS_PartGraphKway!");
5565 mfem::out <<
"Mesh::GeneratePartitioning(...): edgecut = "
5569 nparts = (int) mparts;
5570 if (mpartitioning != (
idx_t*)partitioning)
5572 for (
int k = 0; k<NumOfElements; k++)
5574 partitioning[k] = mpartitioning[k];
5581 delete[] mpartitioning;
5591 for (i = 0; i < nparts; i++)
5597 for (i = 0; i < NumOfElements; i++)
5599 psize[partitioning[i]].one++;
5602 int empty_parts = 0;
5603 for (i = 0; i < nparts; i++)
5605 if (psize[i].one == 0) { empty_parts++; }
5614 mfem::err <<
"Mesh::GeneratePartitioning(...): METIS returned "
5615 << empty_parts <<
" empty parts!"
5616 <<
" Applying a simple fix ..." << endl;
5619 SortPairs<int,int>(psize, nparts);
5621 for (i = nparts-1; i > nparts-1-empty_parts; i--)
5626 for (
int j = 0; j < NumOfElements; j++)
5628 for (i = nparts-1; i > nparts-1-empty_parts; i--)
5630 if (psize[i].one == 0 || partitioning[j] != psize[i].two)
5636 partitioning[j] = psize[nparts-1-i].two;
5644 return partitioning;
5648 mfem_error(
"Mesh::GeneratePartitioning(...): "
5649 "MFEM was compiled without Metis.");
5663 int num_elem, *i_elem_elem, *j_elem_elem;
5665 num_elem = elem_elem.
Size();
5666 i_elem_elem = elem_elem.
GetI();
5667 j_elem_elem = elem_elem.
GetJ();
5672 int stack_p, stack_top_p, elem;
5676 for (i = 0; i < num_elem; i++)
5678 if (partitioning[i] > num_part)
5680 num_part = partitioning[i];
5687 for (i = 0; i < num_part; i++)
5694 for (elem = 0; elem < num_elem; elem++)
5696 if (component[elem] >= 0)
5701 component[elem] = num_comp[partitioning[elem]]++;
5703 elem_stack[stack_top_p++] = elem;
5705 for ( ; stack_p < stack_top_p; stack_p++)
5707 i = elem_stack[stack_p];
5708 for (j = i_elem_elem[i]; j < i_elem_elem[i+1]; j++)
5711 if (partitioning[k] == partitioning[i])
5713 if (component[k] < 0)
5715 component[k] = component[i];
5716 elem_stack[stack_top_p++] = k;
5718 else if (component[k] != component[i])
5728 void Mesh::CheckPartitioning(
int *partitioning)
5730 int i, n_empty, n_mcomp;
5732 const Array<int> _partitioning(partitioning, GetNE());
5734 ElementToElementTable();
5738 n_empty = n_mcomp = 0;
5739 for (i = 0; i < num_comp.
Size(); i++)
5740 if (num_comp[i] == 0)
5744 else if (num_comp[i] > 1)
5751 mfem::out <<
"Mesh::CheckPartitioning(...) :\n"
5752 <<
"The following subdomains are empty :\n";
5753 for (i = 0; i < num_comp.
Size(); i++)
5754 if (num_comp[i] == 0)
5762 mfem::out <<
"Mesh::CheckPartitioning(...) :\n"
5763 <<
"The following subdomains are NOT connected :\n";
5764 for (i = 0; i < num_comp.
Size(); i++)
5765 if (num_comp[i] > 1)
5771 if (n_empty == 0 && n_mcomp == 0)
5772 mfem::out <<
"Mesh::CheckPartitioning(...) : "
5773 "All subdomains are connected." << endl;
5787 const double *a = A.
Data();
5788 const double *b = B.
Data();
5797 c(0) = a[0]*a[3]-a[1]*a[2];
5798 c(1) = a[0]*b[3]-a[1]*b[2]+b[0]*a[3]-b[1]*a[2];
5799 c(2) = b[0]*b[3]-b[1]*b[2];
5820 c(0) = (a[0] * (a[4] * a[8] - a[5] * a[7]) +
5821 a[1] * (a[5] * a[6] - a[3] * a[8]) +
5822 a[2] * (a[3] * a[7] - a[4] * a[6]));
5824 c(1) = (b[0] * (a[4] * a[8] - a[5] * a[7]) +
5825 b[1] * (a[5] * a[6] - a[3] * a[8]) +
5826 b[2] * (a[3] * a[7] - a[4] * a[6]) +
5828 a[0] * (b[4] * a[8] - b[5] * a[7]) +
5829 a[1] * (b[5] * a[6] - b[3] * a[8]) +
5830 a[2] * (b[3] * a[7] - b[4] * a[6]) +
5832 a[0] * (a[4] * b[8] - a[5] * b[7]) +
5833 a[1] * (a[5] * b[6] - a[3] * b[8]) +
5834 a[2] * (a[3] * b[7] - a[4] * b[6]));
5836 c(2) = (a[0] * (b[4] * b[8] - b[5] * b[7]) +
5837 a[1] * (b[5] * b[6] - b[3] * b[8]) +
5838 a[2] * (b[3] * b[7] - b[4] * b[6]) +
5840 b[0] * (a[4] * b[8] - a[5] * b[7]) +
5841 b[1] * (a[5] * b[6] - a[3] * b[8]) +
5842 b[2] * (a[3] * b[7] - a[4] * b[6]) +
5844 b[0] * (b[4] * a[8] - b[5] * a[7]) +
5845 b[1] * (b[5] * a[6] - b[3] * a[8]) +
5846 b[2] * (b[3] * a[7] - b[4] * a[6]));
5848 c(3) = (b[0] * (b[4] * b[8] - b[5] * b[7]) +
5849 b[1] * (b[5] * b[6] - b[3] * b[8]) +
5850 b[2] * (b[3] * b[7] - b[4] * b[6]));
5896 double a = z(2), b = z(1), c = z(0);
5897 double D = b*b-4*a*c;
5904 x(0) = x(1) = -0.5 * b /
a;
5909 x(0) = -(x(1) = fabs(0.5 * sqrt(D) / a));
5917 t = -0.5 * (b + sqrt(D));
5921 t = -0.5 * (b - sqrt(D));
5927 Swap<double>(x(0), x(1));
5935 double a = z(2)/z(3), b = z(1)/z(3), c = z(0)/z(3);
5938 double Q = (a * a - 3 *
b) / 9;
5939 double R = (2 * a * a * a - 9 * a * b + 27 * c) / 54;
5940 double Q3 = Q * Q * Q;
5947 x(0) = x(1) = x(2) = - a / 3;
5951 double sqrtQ = sqrt(Q);
5955 x(0) = -2 * sqrtQ - a / 3;
5956 x(1) = x(2) = sqrtQ - a / 3;
5960 x(0) = x(1) = - sqrtQ - a / 3;
5961 x(2) = 2 * sqrtQ - a / 3;
5968 double theta = acos(R / sqrt(Q3));
5969 double A = -2 * sqrt(Q);
5971 x0 = A * cos(theta / 3) - a / 3;
5972 x1 = A * cos((theta + 2.0 * M_PI) / 3) - a / 3;
5973 x2 = A * cos((theta - 2.0 * M_PI) / 3) - a / 3;
5978 Swap<double>(x0, x1);
5982 Swap<double>(x1, x2);
5985 Swap<double>(x0, x1);
5998 A = -pow(sqrt(R2 - Q3) + R, 1.0/3.0);
6002 A = pow(sqrt(R2 - Q3) - R, 1.0/3.0);
6004 x(0) = A + Q / A - a / 3;
6013 const double factor,
const int Dim)
6015 const double c0 = c(0);
6016 c(0) = c0 * (1.0 - pow(factor, -Dim));
6018 for (
int j = 0; j < nr; j++)
6030 c(0) = c0 * (1.0 - pow(factor, Dim));
6032 for (
int j = 0; j < nr; j++)
6046 void Mesh::CheckDisplacements(
const Vector &displacements,
double &tmax)
6048 int nvs = vertices.Size();
6049 DenseMatrix P, V, DS, PDS(spaceDim), VDS(spaceDim);
6050 Vector c(spaceDim+1), x(spaceDim);
6051 const double factor = 2.0;
6058 for (
int i = 0; i < NumOfElements; i++)
6065 for (
int j = 0; j < spaceDim; j++)
6066 for (
int k = 0; k < nv; k++)
6068 P(j, k) = vertices[v[k]](j);
6069 V(j, k) = displacements(v[k]+j*nvs);
6073 GetTransformationFEforElementType(el->
GetType());
6077 case Element::TRIANGLE:
6078 case Element::TETRAHEDRON:
6096 case Element::QUADRILATERAL:
6099 for (
int j = 0; j < nv; j++)
6123 void Mesh::MoveVertices(
const Vector &displacements)
6125 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
6126 for (
int j = 0; j < spaceDim; j++)
6128 vertices[i](j) += displacements(j*nv+i);
6132 void Mesh::GetVertices(
Vector &vert_coord)
const
6134 int nv = vertices.Size();
6135 vert_coord.
SetSize(nv*spaceDim);
6136 for (
int i = 0; i < nv; i++)
6137 for (
int j = 0; j < spaceDim; j++)
6139 vert_coord(j*nv+i) = vertices[i](j);
6143 void Mesh::SetVertices(
const Vector &vert_coord)
6145 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
6146 for (
int j = 0; j < spaceDim; j++)
6148 vertices[i](j) = vert_coord(j*nv+i);
6152 void Mesh::GetNode(
int i,
double *coord)
const
6157 for (
int j = 0; j < spaceDim; j++)
6159 coord[j] = (*Nodes)(fes->
DofToVDof(i, j));
6164 for (
int j = 0; j < spaceDim; j++)
6166 coord[j] = vertices[i](j);
6171 void Mesh::SetNode(
int i,
const double *coord)
6176 for (
int j = 0; j < spaceDim; j++)
6178 (*Nodes)(fes->
DofToVDof(i, j)) = coord[j];
6183 for (
int j = 0; j < spaceDim; j++)
6185 vertices[i](j) = coord[j];
6191 void Mesh::MoveNodes(
const Vector &displacements)
6195 (*Nodes) += displacements;
6199 MoveVertices(displacements);
6203 void Mesh::GetNodes(
Vector &node_coord)
const
6207 node_coord = (*Nodes);
6211 GetVertices(node_coord);
6215 void Mesh::SetNodes(
const Vector &node_coord)
6219 (*Nodes) = node_coord;
6223 SetVertices(node_coord);
6229 if (own_nodes) {
delete Nodes; }
6232 own_nodes = (int)make_owner;
6243 mfem::Swap<GridFunction*>(Nodes, nodes);
6244 mfem::Swap<int>(own_nodes, own_nodes_);
6251 void Mesh::AverageVertices(
const int *indexes,
int n,
int result)
6255 for (k = 0; k < spaceDim; k++)
6257 vertices[result](k) = vertices[indexes[0]](k);
6260 for (j = 1; j < n; j++)
6261 for (k = 0; k < spaceDim; k++)
6263 vertices[result](k) += vertices[indexes[j]](k);
6266 for (k = 0; k < spaceDim; k++)
6268 vertices[result](k) *= (1.0 / n);
6272 void Mesh::UpdateNodes()
6276 Nodes->FESpace()->Update();
6281 void Mesh::UniformRefinement2D_base(
bool update_nodes)
6285 if (el_to_edge == NULL)
6287 el_to_edge =
new Table;
6288 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6291 int quad_counter = 0;
6292 for (
int i = 0; i < NumOfElements; i++)
6294 if (elements[i]->GetType() == Element::QUADRILATERAL)
6300 const int oedge = NumOfVertices;
6301 const int oelem = oedge + NumOfEdges;
6306 vertices.
SetSize(oelem + quad_counter);
6307 new_elements.
SetSize(4 * NumOfElements);
6310 for (
int i = 0, j = 0; i < NumOfElements; i++)
6313 const int attr = elements[i]->GetAttribute();
6314 int *v = elements[i]->GetVertices();
6315 const int *e = el_to_edge->GetRow(i);
6318 if (el_type == Element::TRIANGLE)
6320 for (
int ei = 0; ei < 3; ei++)
6322 for (
int k = 0; k < 2; k++)
6324 vv[k] = v[tri_t::Edges[ei][k]];
6326 AverageVertices(vv, 2, oedge+e[ei]);
6330 new Triangle(v[0], oedge+e[0], oedge+e[2], attr);
6332 new Triangle(oedge+e[1], oedge+e[2], oedge+e[0], attr);
6334 new Triangle(oedge+e[0], v[1], oedge+e[1], attr);
6336 new Triangle(oedge+e[2], oedge+e[1], v[2], attr);
6338 else if (el_type == Element::QUADRILATERAL)
6340 const int qe = quad_counter;
6342 AverageVertices(v, 4, oelem+qe);
6344 for (
int ei = 0; ei < 4; ei++)
6346 for (
int k = 0; k < 2; k++)
6348 vv[k] = v[quad_t::Edges[ei][k]];
6350 AverageVertices(vv, 2, oedge+e[ei]);
6354 new Quadrilateral(v[0], oedge+e[0], oelem+qe, oedge+e[3], attr);
6356 new Quadrilateral(oedge+e[0], v[1], oedge+e[1], oelem+qe, attr);
6358 new Quadrilateral(oelem+qe, oedge+e[1], v[2], oedge+e[2], attr);
6360 new Quadrilateral(oedge+e[3], oelem+qe, oedge+e[2], v[3], attr);
6364 MFEM_ABORT(
"unknown element type: " << el_type);
6366 FreeElement(elements[i]);
6371 new_boundary.
SetSize(2 * NumOfBdrElements);
6372 for (
int i = 0, j = 0; i < NumOfBdrElements; i++)
6374 const int attr = boundary[i]->GetAttribute();
6375 int *v = boundary[i]->GetVertices();
6377 new_boundary[j++] =
new Segment(v[0], oedge+be_to_edge[i], attr);
6378 new_boundary[j++] =
new Segment(oedge+be_to_edge[i], v[1], attr);
6380 FreeElement(boundary[i]);
6384 static const double A = 0.0, B = 0.5, C = 1.0;
6385 static double tri_children[2*3*4] =
6392 static double quad_children[2*4*4] =
6400 CoarseFineTr.point_matrices[Geometry::TRIANGLE]
6401 .UseExternalData(tri_children, 2, 3, 4);
6402 CoarseFineTr.point_matrices[Geometry::SQUARE]
6403 .UseExternalData(quad_children, 2, 4, 4);
6404 CoarseFineTr.embeddings.SetSize(elements.Size());
6406 for (
int i = 0; i < elements.Size(); i++)
6408 Embedding &emb = CoarseFineTr.embeddings[i];
6413 NumOfVertices = vertices.Size();
6414 NumOfElements = 4 * NumOfElements;
6415 NumOfBdrElements = 2 * NumOfBdrElements;
6418 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6421 last_operation = Mesh::REFINE;
6424 if (update_nodes) { UpdateNodes(); }
6427 if (!Nodes || update_nodes)
6429 CheckElementOrientation(
false);
6431 CheckBdrElementOrientation(
false);
6435 static inline double sqr(
const double &x)
6445 if (el_to_edge == NULL)
6447 el_to_edge =
new Table;
6448 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6451 if (el_to_face == NULL)
6453 GetElementToFaceTable();
6457 Array<int> &f2qf = f2qf_ptr ? *f2qf_ptr : f2qf_loc;
6460 int NumOfQuadFaces = 0;
6461 if (HasGeometry(Geometry::SQUARE))
6463 if (HasGeometry(Geometry::TRIANGLE))
6466 for (
int i = 0; i < faces.Size(); i++)
6468 if (faces[i]->GetType() == Element::QUADRILATERAL)
6470 f2qf[i] = NumOfQuadFaces;
6477 NumOfQuadFaces = faces.
Size();
6481 int hex_counter = 0;
6482 if (HasGeometry(Geometry::CUBE))
6484 for (
int i = 0; i < elements.Size(); i++)
6486 if (elements[i]->GetType() == Element::HEXAHEDRON)
6496 if (HasGeometry(Geometry::TETRAHEDRON))
6500 DSTable *v_to_v_ptr = v_to_v_p;
6503 v_to_v_ptr =
new DSTable(NumOfVertices);
6504 GetVertexToVertexTable(*v_to_v_ptr);
6509 for (
int i = 0; i < NumOfVertices; i++)
6516 std::sort(row_start, J_v2v.
end());
6519 for (
int i = 0; i < J_v2v.
Size(); i++)
6521 e2v[J_v2v[i].two] = i;
6530 for (
int i = 0; i < NumOfVertices; i++)
6534 it.SetIndex(e2v[it.Index()]);
6542 const int oedge = NumOfVertices;
6543 const int oface = oedge + NumOfEdges;
6544 const int oelem = oface + NumOfQuadFaces;
6549 vertices.
SetSize(oelem + hex_counter);
6550 new_elements.
SetSize(8 * NumOfElements);
6551 CoarseFineTr.embeddings.SetSize(new_elements.
Size());
6554 for (
int i = 0, j = 0; i < NumOfElements; i++)
6557 const int attr = elements[i]->GetAttribute();
6558 int *v = elements[i]->GetVertices();
6559 const int *e = el_to_edge->GetRow(i);
6564 const int ne = el_to_edge->RowSize(i);
6565 for (
int k = 0; k < ne; k++) { ev[k] = e2v[e[k]]; }
6571 case Element::TETRAHEDRON:
6573 for (
int ei = 0; ei < 6; ei++)
6575 for (
int k = 0; k < 2; k++)
6577 vv[k] = v[tet_t::Edges[ei][k]];
6579 AverageVertices(vv, 2, oedge+e[ei]);
6585 const int rt_algo = 1;
6596 double len_sqr, min_len;
6598 min_len = sqr(J(0,0)-J(0,1)-J(0,2)) +
6599 sqr(J(1,0)-J(1,1)-J(1,2)) +
6600 sqr(J(2,0)-J(2,1)-J(2,2));
6603 len_sqr = sqr(J(0,1)-J(0,0)-J(0,2)) +
6604 sqr(J(1,1)-J(1,0)-J(1,2)) +
6605 sqr(J(2,1)-J(2,0)-J(2,2));
6606 if (len_sqr < min_len) { min_len = len_sqr; rt = 1; }
6608 len_sqr = sqr(J(0,2)-J(0,0)-J(0,1)) +
6609 sqr(J(1,2)-J(1,0)-J(1,1)) +
6610 sqr(J(2,2)-J(2,0)-J(2,1));
6611 if (len_sqr < min_len) { rt = 2; }
6616 double Em_data[18], Js_data[9], Jp_data[9];
6619 double ar1, ar2,
kappa, kappa_min;
6621 for (
int s = 0; s < 3; s++)
6623 for (
int t = 0; t < 3; t++)
6625 Em(t,s) = 0.5*J(t,s);
6628 for (
int t = 0; t < 3; t++)
6630 Em(t,3) = 0.5*(J(t,0)+J(t,1));
6631 Em(t,4) = 0.5*(J(t,0)+J(t,2));
6632 Em(t,5) = 0.5*(J(t,1)+J(t,2));
6636 for (
int t = 0; t < 3; t++)
6638 Js(t,0) = Em(t,5)-Em(t,0);
6639 Js(t,1) = Em(t,1)-Em(t,0);
6640 Js(t,2) = Em(t,2)-Em(t,0);
6644 for (
int t = 0; t < 3; t++)
6646 Js(t,0) = Em(t,5)-Em(t,0);
6647 Js(t,1) = Em(t,2)-Em(t,0);
6648 Js(t,2) = Em(t,4)-Em(t,0);
6652 kappa_min = std::max(ar1, ar2);
6656 for (
int t = 0; t < 3; t++)
6658 Js(t,0) = Em(t,0)-Em(t,1);
6659 Js(t,1) = Em(t,4)-Em(t,1);
6660 Js(t,2) = Em(t,2)-Em(t,1);
6664 for (
int t = 0; t < 3; t++)
6666 Js(t,0) = Em(t,2)-Em(t,1);
6667 Js(t,1) = Em(t,4)-Em(t,1);
6668 Js(t,2) = Em(t,5)-Em(t,1);
6672 kappa = std::max(ar1, ar2);
6673 if (kappa < kappa_min) { kappa_min =
kappa; rt = 1; }
6676 for (
int t = 0; t < 3; t++)
6678 Js(t,0) = Em(t,0)-Em(t,2);
6679 Js(t,1) = Em(t,1)-Em(t,2);
6680 Js(t,2) = Em(t,3)-Em(t,2);
6684 for (
int t = 0; t < 3; t++)
6686 Js(t,0) = Em(t,1)-Em(t,2);
6687 Js(t,1) = Em(t,5)-Em(t,2);
6688 Js(t,2) = Em(t,3)-Em(t,2);
6692 kappa = std::max(ar1, ar2);
6693 if (kappa < kappa_min) { rt = 2; }
6696 static const int mv_all[3][4][4] =
6698 { {0,5,1,2}, {0,5,2,4}, {0,5,4,3}, {0,5,3,1} },
6699 { {1,0,4,2}, {1,2,4,5}, {1,5,4,3}, {1,3,4,0} },
6700 { {2,0,1,3}, {2,1,5,3}, {2,5,4,3}, {2,4,0,3} }
6702 const int (&mv)[4][4] = mv_all[rt];
6704 #ifndef MFEM_USE_MEMALLOC
6706 new Tetrahedron(v[0], oedge+e[0], oedge+e[1], oedge+e[2], attr);
6708 new Tetrahedron(oedge+e[0], v[1], oedge+e[3], oedge+e[4], attr);
6710 new Tetrahedron(oedge+e[1], oedge+e[3], v[2], oedge+e[5], attr);
6712 new Tetrahedron(oedge+e[2], oedge+e[4], oedge+e[5], v[3], attr);
6714 for (
int k = 0; k < 4; k++)
6716 new_elements[j+4+k] =
6717 new Tetrahedron(oedge+e[mv[k][0]], oedge+e[mv[k][1]],
6718 oedge+e[mv[k][2]], oedge+e[mv[k][3]], attr);
6722 new_elements[j+0] = tet = TetMemory.Alloc();
6723 tet->
Init(v[0], oedge+e[0], oedge+e[1], oedge+e[2], attr);
6725 new_elements[j+1] = tet = TetMemory.Alloc();
6726 tet->
Init(oedge+e[0], v[1], oedge+e[3], oedge+e[4], attr);
6728 new_elements[j+2] = tet = TetMemory.Alloc();
6729 tet->
Init(oedge+e[1], oedge+e[3], v[2], oedge+e[5], attr);
6731 new_elements[j+3] = tet = TetMemory.Alloc();
6732 tet->
Init(oedge+e[2], oedge+e[4], oedge+e[5], v[3], attr);
6734 for (
int k = 0; k < 4; k++)
6736 new_elements[j+4+k] = tet = TetMemory.Alloc();
6737 tet->
Init(oedge+e[mv[k][0]], oedge+e[mv[k][1]],
6738 oedge+e[mv[k][2]], oedge+e[mv[k][3]], attr);
6741 for (
int k = 0; k < 4; k++)
6743 CoarseFineTr.embeddings[j+k].parent = i;
6744 CoarseFineTr.embeddings[j+k].matrix = k;
6746 for (
int k = 0; k < 4; k++)
6748 CoarseFineTr.embeddings[j+4+k].parent = i;
6749 CoarseFineTr.embeddings[j+4+k].matrix = 4*(rt+1)+k;
6756 case Element::WEDGE:
6758 const int *f = el_to_face->GetRow(i);
6760 for (
int fi = 2; fi < 5; fi++)
6762 for (
int k = 0; k < 4; k++)
6764 vv[k] = v[pri_t::FaceVert[fi][k]];
6766 AverageVertices(vv, 4, oface + f2qf[f[fi]]);
6769 for (
int ei = 0; ei < 9; ei++)
6771 for (
int k = 0; k < 2; k++)
6773 vv[k] = v[pri_t::Edges[ei][k]];
6775 AverageVertices(vv, 2, oedge+e[ei]);
6778 const int qf2 = f2qf[f[2]];
6779 const int qf3 = f2qf[f[3]];
6780 const int qf4 = f2qf[f[4]];
6783 new Wedge(v[0], oedge+e[0], oedge+e[2],
6784 oedge+e[6], oface+qf2, oface+qf4, attr);
6787 new Wedge(oedge+e[1], oedge+e[2], oedge+e[0],
6788 oface+qf3, oface+qf4, oface+qf2, attr);
6791 new Wedge(oedge+e[0], v[1], oedge+e[1],
6792 oface+qf2, oedge+e[7], oface+qf3, attr);
6795 new Wedge(oedge+e[2], oedge+e[1], v[2],
6796 oface+qf4, oface+qf3, oedge+e[8], attr);
6799 new Wedge(oedge+e[6], oface+qf2, oface+qf4,
6800 v[3], oedge+e[3], oedge+e[5], attr);
6803 new Wedge(oface+qf3, oface+qf4, oface+qf2,
6804 oedge+e[4], oedge+e[5], oedge+e[3], attr);
6807 new Wedge(oface+qf2, oedge+e[7], oface+qf3,
6808 oedge+e[3], v[4], oedge+e[4], attr);
6811 new Wedge(oface+qf4, oface+qf3, oedge+e[8],
6812 oedge+e[5], oedge+e[4], v[5], attr);
6816 case Element::HEXAHEDRON:
6818 const int *f = el_to_face->GetRow(i);
6819 const int he = hex_counter;
6824 if (f2qf.
Size() == 0)
6830 for (
int k = 0; k < 6; k++) { qf_data[k] = f2qf[f[k]]; }
6834 AverageVertices(v, 8, oelem+he);
6836 for (
int fi = 0; fi < 6; fi++)
6838 for (
int k = 0; k < 4; k++)
6840 vv[k] = v[hex_t::FaceVert[fi][k]];
6842 AverageVertices(vv, 4, oface + qf[fi]);
6845 for (
int ei = 0; ei < 12; ei++)
6847 for (
int k = 0; k < 2; k++)
6849 vv[k] = v[hex_t::Edges[ei][k]];
6851 AverageVertices(vv, 2, oedge+e[ei]);
6855 new Hexahedron(v[0], oedge+e[0], oface+qf[0],
6856 oedge+e[3], oedge+e[8], oface+qf[1],
6857 oelem+he, oface+qf[4], attr);
6860 oface+qf[0], oface+qf[1], oedge+e[9],
6861 oface+qf[2], oelem+he, attr);
6863 new Hexahedron(oface+qf[0], oedge+e[1], v[2],
6864 oedge+e[2], oelem+he, oface+qf[2],
6865 oedge+e[10], oface+qf[3], attr);
6867 new Hexahedron(oedge+e[3], oface+qf[0], oedge+e[2],
6868 v[3], oface+qf[4], oelem+he,
6869 oface+qf[3], oedge+e[11], attr);
6871 new Hexahedron(oedge+e[8], oface+qf[1], oelem+he,
6872 oface+qf[4], v[4], oedge+e[4],
6873 oface+qf[5], oedge+e[7], attr);
6875 new Hexahedron(oface+qf[1], oedge+e[9], oface+qf[2],
6876 oelem+he, oedge+e[4], v[5],
6877 oedge+e[5], oface+qf[5], attr);
6879 new Hexahedron(oelem+he, oface+qf[2], oedge+e[10],
6880 oface+qf[3], oface+qf[5], oedge+e[5],
6881 v[6], oedge+e[6], attr);
6883 new Hexahedron(oface+qf[4], oelem+he, oface+qf[3],
6884 oedge+e[11], oedge+e[7], oface+qf[5],
6885 oedge+e[6], v[7], attr);
6890 MFEM_ABORT(
"Unknown 3D element type \"" << el_type <<
"\"");
6893 FreeElement(elements[i]);
6898 new_boundary.
SetSize(4 * NumOfBdrElements);
6899 for (
int i = 0, j = 0; i < NumOfBdrElements; i++)
6902 const int attr = boundary[i]->GetAttribute();
6903 int *v = boundary[i]->GetVertices();
6904 const int *e = bel_to_edge->GetRow(i);
6909 const int ne = bel_to_edge->RowSize(i);
6910 for (
int k = 0; k < ne; k++) { ev[k] = e2v[e[k]]; }
6914 if (bdr_el_type == Element::TRIANGLE)
6917 new Triangle(v[0], oedge+e[0], oedge+e[2], attr);
6919 new Triangle(oedge+e[1], oedge+e[2], oedge+e[0], attr);
6921 new Triangle(oedge+e[0], v[1], oedge+e[1], attr);
6923 new Triangle(oedge+e[2], oedge+e[1], v[2], attr);
6925 else if (bdr_el_type == Element::QUADRILATERAL)
6928 (f2qf.
Size() == 0) ? be_to_face[i] : f2qf[be_to_face[i]];
6931 new Quadrilateral(v[0], oedge+e[0], oface+qf, oedge+e[3], attr);
6933 new Quadrilateral(oedge+e[0], v[1], oedge+e[1], oface+qf, attr);
6935 new Quadrilateral(oface+qf, oedge+e[1], v[2], oedge+e[2], attr);
6937 new Quadrilateral(oedge+e[3], oface+qf, oedge+e[2], v[3], attr);
6941 MFEM_ABORT(
"boundary Element is not a triangle or a quad!");
6943 FreeElement(boundary[i]);
6947 static const double A = 0.0, B = 0.5, C = 1.0;
6948 static double tet_children[3*4*16] =
6950 A,A,A, B,A,A, A,B,A, A,A,B,
6951 B,A,A, C,A,A, B,B,A, B,A,B,
6952 A,B,A, B,B,A, A,C,A, A,B,B,
6953 A,A,B, B,A,B, A,B,B, A,A,C,
6958 B,A,A, A,B,B, A,B,A, A,A,B,
6959 B,A,A, A,B,B, A,A,B, B,A,B,
6960 B,A,A, A,B,B, B,A,B, B,B,A,
6961 B,A,A, A,B,B, B,B,A, A,B,A,
6963 A,B,A, B,A,A, B,A,B, A,A,B,
6964 A,B,A, A,A,B, B,A,B, A,B,B,
6965 A,B,A, A,B,B, B,A,B, B,B,A,
6966 A,B,A, B,B,A, B,A,B, B,A,A,
6968 A,A,B, B,A,A, A,B,A, B,B,A,
6969 A,A,B, A,B,A, A,B,B, B,B,A,
6970 A,A,B, A,B,B, B,A,B, B,B,A,
6971 A,A,B, B,A,B, B,A,A, B,B,A
6973 static double pri_children[3*6*8] =
6975 A,A,A, B,A,A, A,B,A, A,A,B, B,A,B, A,B,B,
6976 B,B,A, A,B,A, B,A,A, B,B,B, A,B,B, B,A,B,
6977 B,A,A, C,A,A, B,B,A, B,A,B, C,A,B, B,B,B,
6978 A,B,A, B,B,A, A,C,A, A,B,B, B,B,B, A,C,B,
6979 A,A,B, B,A,B, A,B,B, A,A,C, B,A,C, A,B,C,
6980 B,B,B, A,B,B, B,A,B, B,B,C, A,B,C, B,A,C,
6981 B,A,B, C,A,B, B,B,B, B,A,C, C,A,C, B,B,C,
6982 A,B,B, B,B,B, A,C,B, A,B,C, B,B,C, A,C,C
6984 static double hex_children[3*8*8] =
6986 A,A,A, B,A,A, B,B,A, A,B,A, A,A,B, B,A,B, B,B,B, A,B,B,
6987 B,A,A, C,A,A, C,B,A, B,B,A, B,A,B, C,A,B, C,B,B, B,B,B,
6988 B,B,A, C,B,A, C,C,A, B,C,A, B,B,B, C,B,B, C,C,B, B,C,B,
6989 A,B,A, B,B,A, B,C,A, A,C,A, A,B,B, B,B,B, B,C,B, A,C,B,
6990 A,A,B, B,A,B, B,B,B, A,B,B, A,A,C, B,A,C, B,B,C, A,B,C,
6991 B,A,B, C,A,B, C,B,B, B,B,B, B,A,C, C,A,C, C,B,C, B,B,C,
6992 B,B,B, C,B,B, C,C,B, B,C,B, B,B,C, C,B,C, C,C,C, B,C,C,
6993 A,B,B, B,B,B, B,C,B, A,C,B, A,B,C, B,B,C, B,C,C, A,C,C
6996 CoarseFineTr.point_matrices[Geometry::TETRAHEDRON]
6997 .UseExternalData(tet_children, 3, 4, 16);
6998 CoarseFineTr.point_matrices[Geometry::PRISM]
6999 .UseExternalData(pri_children, 3, 6, 8);
7000 CoarseFineTr.point_matrices[Geometry::CUBE]
7001 .UseExternalData(hex_children, 3, 8, 8);
7003 for (
int i = 0; i < elements.Size(); i++)
7006 if (elements[i]->GetType() == Element::TETRAHEDRON) {
continue; }
7008 Embedding &emb = CoarseFineTr.embeddings[i];
7013 NumOfVertices = vertices.Size();
7014 NumOfElements = 8 * NumOfElements;
7015 NumOfBdrElements = 4 * NumOfBdrElements;
7017 GetElementToFaceTable();
7021 CheckBdrElementOrientation(
false);
7024 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
7026 last_operation = Mesh::REFINE;
7029 if (update_nodes) { UpdateNodes(); }
7032 void Mesh::LocalRefinement(
const Array<int> &marked_el,
int type)
7034 int i, j, ind, nedges;
7041 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
7044 InitRefinementTransforms();
7048 int cne = NumOfElements, cnv = NumOfVertices;
7049 NumOfVertices += marked_el.
Size();
7050 NumOfElements += marked_el.
Size();
7051 vertices.SetSize(NumOfVertices);
7052 elements.SetSize(NumOfElements);
7053 CoarseFineTr.embeddings.SetSize(NumOfElements);
7055 for (j = 0; j < marked_el.
Size(); j++)
7060 int new_v = cnv + j, new_e = cne + j;
7061 AverageVertices(vert, 2, new_v);
7062 elements[new_e] =
new Segment(new_v, vert[1], attr);
7065 CoarseFineTr.embeddings[i] =
Embedding(i, 1);
7066 CoarseFineTr.embeddings[new_e] =
Embedding(i, 2);
7069 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
7070 CoarseFineTr.point_matrices[Geometry::SEGMENT].
7071 UseExternalData(seg_children, 1, 2, 3);
7079 DSTable v_to_v(NumOfVertices);
7080 GetVertexToVertexTable(v_to_v);
7084 int *edge1 =
new int[nedges];
7085 int *edge2 =
new int[nedges];
7086 int *middle =
new int[nedges];
7088 for (i = 0; i < nedges; i++)
7090 edge1[i] = edge2[i] = middle[i] = -1;
7093 for (i = 0; i < NumOfElements; i++)
7095 elements[i]->GetVertices(v);
7096 for (j = 1; j < v.
Size(); j++)
7098 ind = v_to_v(v[j-1], v[j]);
7099 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
7101 ind = v_to_v(v[0], v[v.
Size()-1]);
7102 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
7106 for (i = 0; i < marked_el.
Size(); i++)
7108 RedRefinement(marked_el[i], v_to_v, edge1, edge2, middle);
7112 int need_refinement;
7115 need_refinement = 0;
7116 for (i = 0; i < nedges; i++)
7118 if (middle[i] != -1 && edge1[i] != -1)
7120 need_refinement = 1;
7121 GreenRefinement(edge1[i], v_to_v, edge1, edge2, middle);
7125 while (need_refinement == 1);
7128 int v1[2], v2[2], bisect, temp;
7129 temp = NumOfBdrElements;
7130 for (i = 0; i < temp; i++)
7132 boundary[i]->GetVertices(v);
7133 bisect = v_to_v(v[0], v[1]);
7134 if (middle[bisect] != -1)
7136 if (boundary[i]->GetType() == Element::SEGMENT)
7138 v1[0] = v[0]; v1[1] = middle[bisect];
7139 v2[0] = middle[bisect]; v2[1] = v[1];
7141 boundary[i]->SetVertices(v1);
7142 boundary.
Append(
new Segment(v2, boundary[i]->GetAttribute()));
7145 mfem_error(
"Only bisection of segment is implemented"
7149 NumOfBdrElements = boundary.Size();
7156 if (el_to_edge != NULL)
7158 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
7169 MFEM_VERIFY(GetNE() == 0 ||
7170 ((
Tetrahedron*)elements[0])->GetRefinementFlag() != 0,
7171 "tetrahedral mesh is not marked for refinement:"
7172 " call Finalize(true)");
7179 for (i = 0; i < marked_el.
Size(); i++)
7181 Bisection(marked_el[i], v_to_v);
7185 for (i = 0; i < marked_el.
Size(); i++)
7187 Bisection(marked_el[i], v_to_v);
7189 Bisection(NumOfElements - 1, v_to_v);
7190 Bisection(marked_el[i], v_to_v);