15 #include "../fem/fem.hpp"
16 #include "../general/sort_pairs.hpp"
17 #include "../general/text.hpp"
30 #if defined(MFEM_USE_METIS) && defined(MFEM_USE_METIS_5)
35 #if defined(MFEM_USE_METIS) && !defined(MFEM_USE_METIS_5)
39 int*,
int*,
int*,
int*,
int*,
idxtype*);
41 int*,
int*,
int*,
int*,
int*,
idxtype*);
43 int*,
int*,
int*,
int*,
int*,
idxtype*);
58 int geom = GetElementBaseGeometry(i);
64 double Mesh::GetElementSize(
int i,
int type)
67 GetElementJacobian(i, J);
70 return pow(fabs(J.
Det()), 1./Dim);
82 double Mesh::GetElementSize(
int i,
const Vector &dir)
86 GetElementJacobian(i, J);
88 return sqrt((d_hat * d_hat) / (dir * dir));
91 double Mesh::GetElementVolume(
int i)
113 for (
int d = 0; d < spaceDim; d++)
122 for (
int i = 0; i < NumOfVertices; i++)
124 coord = GetVertex(i);
125 for (
int d = 0; d < spaceDim; d++)
127 if (coord[d] < min(d)) { min(d) = coord[d]; }
128 if (coord[d] > max(d)) { max(d) = coord[d]; }
134 const bool use_boundary =
false;
135 int ne = use_boundary ? GetNBE() : GetNE();
143 for (
int i = 0; i < ne; i++)
147 GetBdrElementFace(i, &fn, &fo);
149 Tr = GetFaceElementTransformations(fn, 5);
156 T = GetElementTransformation(i);
160 for (
int j = 0; j < pointmat.
Width(); j++)
162 for (
int d = 0; d < pointmat.
Height(); d++)
164 if (pointmat(d,j) < min(d)) { min(d) = pointmat(d,j); }
165 if (pointmat(d,j) > max(d)) { max(d) = pointmat(d,j); }
172 void Mesh::GetCharacteristics(
double &h_min,
double &h_max,
173 double &kappa_min,
double &kappa_max,
181 sdim = SpaceDimension();
183 if (Vh) { Vh->
SetSize(NumOfElements); }
184 if (Vk) { Vk->
SetSize(NumOfElements); }
187 h_max = kappa_max = -h_min;
188 if (dim == 0) {
if (Vh) { *Vh = 1.0; }
if (Vk) {*Vk = 1.0; }
return; }
190 for (i = 0; i < NumOfElements; i++)
192 GetElementJacobian(i, J);
193 h = pow(fabs(J.
Weight()), 1.0/
double(dim));
194 kappa = (dim == sdim) ?
196 if (Vh) { (*Vh)(i) = h; }
197 if (Vk) { (*Vk)(i) = kappa; }
199 if (h < h_min) { h_min = h; }
200 if (h > h_max) { h_max = h; }
201 if (kappa < kappa_min) { kappa_min =
kappa; }
202 if (kappa > kappa_max) { kappa_max =
kappa; }
208 double h_min, h_max, kappa_min, kappa_max;
210 out <<
"Mesh Characteristics:";
212 this->GetCharacteristics(h_min, h_max, kappa_min, kappa_max, Vh, Vk);
215 <<
"Dimension : " << Dimension() <<
'\n'
216 <<
"Space dimension : " << SpaceDimension();
220 <<
"Number of vertices : " << GetNV() <<
'\n'
221 <<
"Number of elements : " << GetNE() <<
'\n'
222 <<
"Number of bdr elem : " << GetNBE() <<
'\n';
227 <<
"Number of vertices : " << GetNV() <<
'\n'
228 <<
"Number of elements : " << GetNE() <<
'\n'
229 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
230 <<
"h_min : " << h_min <<
'\n'
231 <<
"h_max : " << h_max <<
'\n';
236 <<
"Number of vertices : " << GetNV() <<
'\n'
237 <<
"Number of edges : " << GetNEdges() <<
'\n'
238 <<
"Number of elements : " << GetNE() <<
'\n'
239 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
240 <<
"Euler Number : " << EulerNumber2D() <<
'\n'
241 <<
"h_min : " << h_min <<
'\n'
242 <<
"h_max : " << h_max <<
'\n'
243 <<
"kappa_min : " << kappa_min <<
'\n'
244 <<
"kappa_max : " << kappa_max <<
'\n';
249 <<
"Number of vertices : " << GetNV() <<
'\n'
250 <<
"Number of edges : " << GetNEdges() <<
'\n'
251 <<
"Number of faces : " << GetNFaces() <<
'\n'
252 <<
"Number of elements : " << GetNE() <<
'\n'
253 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
254 <<
"Euler Number : " << EulerNumber() <<
'\n'
255 <<
"h_min : " << h_min <<
'\n'
256 <<
"h_max : " << h_max <<
'\n'
257 <<
"kappa_min : " << kappa_min <<
'\n'
258 <<
"kappa_max : " << kappa_max <<
'\n';
260 out <<
'\n' << std::flush;
267 case Element::POINT :
return &
PointFE;
268 case Element::SEGMENT :
return &
SegmentFE;
274 MFEM_ABORT(
"Unknown element type");
286 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
292 Nodes->FESpace()->GetElementVDofs(i, vdofs);
294 int n = vdofs.
Size()/spaceDim;
296 for (
int k = 0; k < spaceDim; k++)
298 for (
int j = 0; j < n; j++)
300 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
303 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
308 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
316 MFEM_ASSERT(nodes.
Size() == spaceDim*GetNV(),
"");
317 int nv = elements[i]->GetNVertices();
318 const int *v = elements[i]->GetVertices();
319 int n = vertices.
Size();
321 for (
int k = 0; k < spaceDim; k++)
323 for (
int j = 0; j < nv; j++)
325 pm(k, j) = nodes(k*n+v[j]);
328 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
332 MFEM_ASSERT(nodes.
Size() == Nodes->Size(),
"");
334 Nodes->FESpace()->GetElementVDofs(i, vdofs);
335 int n = vdofs.
Size()/spaceDim;
337 for (
int k = 0; k < spaceDim; k++)
339 for (
int j = 0; j < n; j++)
341 pm(k,j) = nodes(vdofs[n*k+j]);
344 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
351 GetElementTransformation(i, &Transformation);
353 return &Transformation;
358 GetBdrElementTransformation(i, &FaceTransformation);
359 return &FaceTransformation;
370 GetTransformationFEforElementType(GetBdrElementType(i)));
376 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
377 int n = vdofs.
Size()/spaceDim;
379 for (
int k = 0; k < spaceDim; k++)
381 for (
int j = 0; j < n; j++)
383 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
386 ElTr->
SetFE(Nodes->FESpace()->GetBE(i));
393 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
398 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
399 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
401 for (
int i = 0; i < spaceDim; i++)
403 for (
int j = 0; j < nv; j++)
405 pm(i, j) = vertices[v[j]](i);
408 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
412 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
416 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
417 int n = vdofs.
Size()/spaceDim;
419 for (
int i = 0; i < spaceDim; i++)
421 for (
int j = 0; j < n; j++)
423 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
430 FaceInfo &face_info = faces_info[FaceNo];
432 int face_geom = GetFaceGeometryType(FaceNo);
433 int face_type = GetFaceElementType(FaceNo);
435 GetLocalFaceTransformation(face_type,
436 GetElementType(face_info.
Elem1No),
437 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
440 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
444 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
446 Nodes->GetVectorValues(Transformation, eir, pm);
456 GetFaceTransformation(FaceNo, &FaceTransformation);
457 return &FaceTransformation;
464 GetFaceTransformation(EdgeNo, EdTr);
469 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
478 GetEdgeVertices(EdgeNo, v);
481 for (
int i = 0; i < spaceDim; i++)
483 for (
int j = 0; j < nv; j++)
485 pm(i, j) = vertices[v[j]](i);
488 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
492 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
496 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
497 int n = vdofs.
Size()/spaceDim;
499 for (
int i = 0; i < spaceDim; i++)
501 for (
int j = 0; j < n; j++)
503 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
506 EdTr->
SetFE(edge_el);
510 MFEM_ABORT(
"Not implemented.");
518 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
519 return &EdgeTransformation;
523 void Mesh::GetLocalPtToSegTransformation(
538 void Mesh::GetLocalSegToTriTransformation(
546 tv = tri_t::Edges[i/64];
547 so = seg_t::Orient[i%64];
550 for (
int j = 0; j < 2; j++)
552 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
553 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
558 void Mesh::GetLocalSegToQuadTransformation(
566 qv = quad_t::Edges[i/64];
567 so = seg_t::Orient[i%64];
570 for (
int j = 0; j < 2; j++)
572 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
573 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
578 void Mesh::GetLocalTriToTetTransformation(
585 const int *tv = tet_t::FaceVert[i/64];
588 const int *to = tri_t::Orient[i%64];
592 for (
int j = 0; j < 3; j++)
595 locpm(0, j) = vert.
x;
596 locpm(1, j) = vert.
y;
597 locpm(2, j) = vert.
z;
602 void Mesh::GetLocalQuadToHexTransformation(
609 const int *hv = hex_t::FaceVert[i/64];
611 const int *qo = quad_t::Orient[i%64];
614 for (
int j = 0; j < 4; j++)
617 locpm(0, j) = vert.
x;
618 locpm(1, j) = vert.
y;
619 locpm(2, j) = vert.
z;
624 void Mesh::GetLocalFaceTransformation(
630 GetLocalPtToSegTransformation(Transf, info);
633 case Element::SEGMENT:
634 if (elem_type == Element::TRIANGLE)
636 GetLocalSegToTriTransformation(Transf, info);
640 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
641 GetLocalSegToQuadTransformation(Transf, info);
645 case Element::TRIANGLE:
646 MFEM_ASSERT(elem_type == Element::TETRAHEDRON,
"");
647 GetLocalTriToTetTransformation(Transf, info);
650 case Element::QUADRILATERAL:
651 MFEM_ASSERT(elem_type == Element::HEXAHEDRON,
"");
652 GetLocalQuadToHexTransformation(Transf, info);
660 FaceInfo &face_info = faces_info[FaceNo];
662 FaceElemTr.Elem1 = NULL;
663 FaceElemTr.Elem2 = NULL;
669 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
670 FaceElemTr.Elem1 = &Transformation;
676 FaceElemTr.Elem2No = face_info.
Elem2No;
677 if ((mask & 2) && FaceElemTr.Elem2No >= 0)
680 if (NURBSext && (mask & 1)) { MFEM_ABORT(
"NURBS mesh not supported!"); }
682 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
683 FaceElemTr.Elem2 = &Transformation2;
687 FaceElemTr.FaceGeom = GetFaceGeometryType(FaceNo);
688 FaceElemTr.Face = (mask & 16) ? GetFaceTransformation(FaceNo) : NULL;
691 int face_type = GetFaceElementType(FaceNo);
694 int elem_type = GetElementType(face_info.
Elem1No);
695 GetLocalFaceTransformation(face_type, elem_type,
696 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
698 if ((mask & 8) && FaceElemTr.Elem2No >= 0)
700 int elem_type = GetElementType(face_info.
Elem2No);
701 GetLocalFaceTransformation(face_type, elem_type,
702 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
705 if (Nonconforming() && IsSlaveFace(face_info))
707 ApplyLocalSlaveTransformation(FaceElemTr.Loc2.Transf, face_info);
709 if (face_type == Element::SEGMENT)
712 DenseMatrix &pm = FaceElemTr.Loc2.Transf.GetPointMat();
713 std::swap(pm(0,0), pm(0,1));
714 std::swap(pm(1,0), pm(1,1));
724 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
730 #ifdef MFEM_THREAD_SAFE
735 MFEM_ASSERT(fi.
NCFace >= 0,
"");
747 fn = be_to_face[BdrElemNo];
751 fn = be_to_edge[BdrElemNo];
755 fn = boundary[BdrElemNo]->GetVertices()[0];
758 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
762 tr = GetFaceElementTransformations(fn);
767 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
769 *Elem1 = faces_info[Face].
Elem1No;
770 *Elem2 = faces_info[Face].Elem2No;
773 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
775 *Inf1 = faces_info[Face].Elem1Inf;
776 *Inf2 = faces_info[Face].Elem2Inf;
779 int Mesh::GetFaceGeometryType(
int Face)
const
781 return (Dim == 1) ? Geometry::POINT : faces[Face]->GetGeometryType();
784 int Mesh::GetFaceElementType(
int Face)
const
786 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
794 NumOfElements = NumOfBdrElements = 0;
795 NumOfEdges = NumOfFaces = 0;
796 BaseGeom = BaseBdrGeom = -2;
803 last_operation = Mesh::NONE;
806 void Mesh::InitTables()
809 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
812 void Mesh::SetEmpty()
816 BaseGeom = BaseBdrGeom = -1;
824 void Mesh::DestroyTables()
839 void Mesh::DestroyPointers()
841 if (own_nodes) {
delete Nodes; }
847 for (
int i = 0; i < NumOfElements; i++)
849 FreeElement(elements[i]);
852 for (
int i = 0; i < NumOfBdrElements; i++)
854 FreeElement(boundary[i]);
857 for (
int i = 0; i < faces.Size(); i++)
859 FreeElement(faces[i]);
869 elements.DeleteAll();
870 vertices.DeleteAll();
871 boundary.DeleteAll();
873 faces_info.DeleteAll();
874 nc_faces_info.DeleteAll();
875 be_to_edge.DeleteAll();
876 be_to_face.DeleteAll();
883 CoarseFineTr.Clear();
885 #ifdef MFEM_USE_MEMALLOC
889 attributes.DeleteAll();
890 bdr_attributes.DeleteAll();
893 void Mesh::DeleteLazyTables()
895 delete el_to_el; el_to_el = NULL;
896 delete face_edge; face_edge = NULL;
897 delete edge_vertex; edge_vertex = NULL;
900 void Mesh::SetAttributes()
905 for (
int i = 0; i < attribs.
Size(); i++)
907 attribs[i] = GetBdrAttribute(i);
911 attribs.
Copy(bdr_attributes);
912 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
914 MFEM_WARNING(
"Non-positive attributes on the boundary!");
918 for (
int i = 0; i < attribs.
Size(); i++)
920 attribs[i] = GetAttribute(i);
924 attribs.
Copy(attributes);
925 if (attributes.Size() > 0 && attributes[0] <= 0)
927 MFEM_WARNING(
"Non-positive attributes in the domain!");
931 void Mesh::InitMesh(
int _Dim,
int _spaceDim,
int NVert,
int NElem,
int NBdrElem)
936 spaceDim = _spaceDim;
939 vertices.SetSize(NVert);
942 elements.SetSize(NElem);
944 NumOfBdrElements = 0;
945 boundary.SetSize(NBdrElem);
948 void Mesh::InitBaseGeom()
950 BaseGeom = BaseBdrGeom = -1;
951 for (
int i = 0; i < NumOfElements; i++)
953 int geom = elements[i]->GetGeometryType();
954 if (geom != BaseGeom && BaseGeom >= 0)
956 BaseGeom = -1;
break;
960 for (
int i = 0; i < NumOfBdrElements; i++)
962 int geom = boundary[i]->GetGeometryType();
963 if (geom != BaseBdrGeom && BaseBdrGeom >= 0)
965 BaseBdrGeom = -1;
break;
971 void Mesh::AddVertex(
const double *x)
973 double *y = vertices[NumOfVertices]();
975 for (
int i = 0; i < spaceDim; i++)
982 void Mesh::AddTri(
const int *vi,
int attr)
984 elements[NumOfElements++] =
new Triangle(vi, attr);
987 void Mesh::AddTriangle(
const int *vi,
int attr)
989 elements[NumOfElements++] =
new Triangle(vi, attr);
992 void Mesh::AddQuad(
const int *vi,
int attr)
997 void Mesh::AddTet(
const int *vi,
int attr)
999 #ifdef MFEM_USE_MEMALLOC
1001 tet = TetMemory.Alloc();
1004 elements[NumOfElements++] = tet;
1006 elements[NumOfElements++] =
new Tetrahedron(vi, attr);
1010 void Mesh::AddHex(
const int *vi,
int attr)
1012 elements[NumOfElements++] =
new Hexahedron(vi, attr);
1015 void Mesh::AddHexAsTets(
const int *vi,
int attr)
1017 static const int hex_to_tet[6][4] =
1019 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
1020 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
1024 for (
int i = 0; i < 6; i++)
1026 for (
int j = 0; j < 4; j++)
1028 ti[j] = vi[hex_to_tet[i][j]];
1034 void Mesh::AddBdrSegment(
const int *vi,
int attr)
1036 boundary[NumOfBdrElements++] =
new Segment(vi, attr);
1039 void Mesh::AddBdrTriangle(
const int *vi,
int attr)
1041 boundary[NumOfBdrElements++] =
new Triangle(vi, attr);
1044 void Mesh::AddBdrQuad(
const int *vi,
int attr)
1049 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
1051 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
1054 for (
int i = 0; i < 2; i++)
1056 for (
int j = 0; j < 3; j++)
1058 ti[j] = vi[quad_to_tri[i][j]];
1060 AddBdrTriangle(ti, attr);
1064 void Mesh::GenerateBoundaryElements()
1067 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
1071 for (i = 0; i < boundary.Size(); i++)
1073 FreeElement(boundary[i]);
1083 NumOfBdrElements = 0;
1084 for (i = 0; i < faces_info.Size(); i++)
1086 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
1089 boundary.SetSize(NumOfBdrElements);
1090 be2face.
SetSize(NumOfBdrElements);
1091 for (j = i = 0; i < faces_info.Size(); i++)
1093 if (faces_info[i].Elem2No < 0)
1095 boundary[j] = faces[i]->Duplicate(
this);
1102 void Mesh::FinalizeCheck()
1104 MFEM_VERIFY(vertices.Size() == NumOfVertices,
1105 "incorrect number of vertices: preallocated: " << vertices.Size()
1106 <<
", actually added: " << NumOfVertices);
1107 MFEM_VERIFY(elements.Size() == NumOfElements,
1108 "incorrect number of elements: preallocated: " << elements.Size()
1109 <<
", actually added: " << NumOfElements);
1110 MFEM_VERIFY(boundary.Size() == NumOfBdrElements,
1111 "incorrect number of boundary elements: preallocated: "
1112 << boundary.Size() <<
", actually added: " << NumOfBdrElements);
1115 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
1118 CheckElementOrientation(fix_orientation);
1122 MarkTriMeshForRefinement();
1127 el_to_edge =
new Table;
1128 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1130 CheckBdrElementOrientation();
1141 BaseGeom = Geometry::TRIANGLE;
1142 BaseBdrGeom = Geometry::SEGMENT;
1147 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1148 bool fix_orientation)
1151 if (fix_orientation)
1153 CheckElementOrientation(fix_orientation);
1158 el_to_edge =
new Table;
1159 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1161 CheckBdrElementOrientation();
1172 BaseGeom = Geometry::SQUARE;
1173 BaseBdrGeom = Geometry::SEGMENT;
1179 #ifdef MFEM_USE_GECKO
1185 Gecko::Functional *functional =
1186 new Gecko::FunctionalGeometric();
1187 unsigned int iterations = 1;
1188 unsigned int window = 2;
1189 unsigned int period = 1;
1190 unsigned int seed = 0;
1193 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1200 const Table &my_el_to_el = ElementToElementTable();
1201 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1203 const int *neighid = my_el_to_el.
GetRow(elemid);
1204 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
1206 graph.insert(elemid + 1, neighid[i] + 1);
1211 graph.order(functional, iterations, window, period, seed);
1214 Gecko::Node::Index NE = GetNE();
1215 for (Gecko::Node::Index gnodeid = 1; gnodeid <= NE; ++gnodeid)
1217 ordering[gnodeid - 1] = graph.rank(gnodeid);
1225 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
1229 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
1234 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
1238 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
1267 old_elem_node_vals.SetSize(GetNE());
1268 nodes_fes = Nodes->FESpace();
1271 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1273 nodes_fes->GetElementVDofs(old_elid, old_dofs);
1275 old_elem_node_vals[old_elid] =
new Vector(vals);
1281 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
1283 int new_elid = ordering[old_elid];
1284 new_elements[new_elid] = elements[old_elid];
1289 if (reorder_vertices)
1294 vertex_ordering = -1;
1296 int new_vertex_ind = 0;
1297 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1299 int *elem_vert = elements[new_elid]->GetVertices();
1300 int nv = elements[new_elid]->GetNVertices();
1301 for (
int vi = 0; vi < nv; ++vi)
1303 int old_vertex_ind = elem_vert[vi];
1304 if (vertex_ordering[old_vertex_ind] == -1)
1306 vertex_ordering[old_vertex_ind] = new_vertex_ind;
1307 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
1317 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1319 int *elem_vert = elements[new_elid]->GetVertices();
1320 int nv = elements[new_elid]->GetNVertices();
1321 for (
int vi = 0; vi < nv; ++vi)
1323 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
1328 for (
int belid = 0; belid < GetNBE(); ++belid)
1330 int *be_vert = boundary[belid]->GetVertices();
1331 int nv = boundary[belid]->GetNVertices();
1332 for (
int vi = 0; vi < nv; ++vi)
1334 be_vert[vi] = vertex_ordering[be_vert[vi]];
1345 el_to_edge =
new Table;
1346 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1351 GetElementToFaceTable();
1359 nodes_fes->Update();
1361 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1363 int new_elid = ordering[old_elid];
1364 nodes_fes->GetElementVDofs(new_elid, new_dofs);
1365 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
1366 delete old_elem_node_vals[old_elid];
1372 void Mesh::MarkForRefinement()
1378 MarkTriMeshForRefinement();
1382 DSTable v_to_v(NumOfVertices);
1383 GetVertexToVertexTable(v_to_v);
1384 MarkTetMeshForRefinement(v_to_v);
1389 void Mesh::MarkTriMeshForRefinement()
1394 for (
int i = 0; i < NumOfElements; i++)
1396 if (elements[i]->GetType() == Element::TRIANGLE)
1398 GetPointMatrix(i, pmat);
1399 elements[i]->MarkEdge(pmat);
1410 for (
int i = 0; i < NumOfVertices; i++)
1415 length_idx[j].one = GetLength(i, it.Column());
1416 length_idx[j].two = j;
1423 for (
int i = 0; i < NumOfEdges; i++)
1425 order[length_idx[i].two] = i;
1429 void Mesh::MarkTetMeshForRefinement(
DSTable &v_to_v)
1434 GetEdgeOrdering(v_to_v, order);
1436 for (
int i = 0; i < NumOfElements; i++)
1438 if (elements[i]->GetType() == Element::TETRAHEDRON)
1440 elements[i]->MarkEdge(v_to_v, order);
1443 for (
int i = 0; i < NumOfBdrElements; i++)
1445 if (boundary[i]->GetType() == Element::TRIANGLE)
1447 boundary[i]->MarkEdge(v_to_v, order);
1454 if (*old_v_to_v && *old_elem_vert)
1462 if (*old_v_to_v == NULL)
1465 if (num_edge_dofs > 0)
1467 *old_v_to_v =
new DSTable(NumOfVertices);
1468 GetVertexToVertexTable(*(*old_v_to_v));
1471 if (*old_elem_vert == NULL)
1474 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1475 if (num_elem_dofs > 1)
1477 *old_elem_vert =
new Table;
1478 (*old_elem_vert)->
MakeI(GetNE());
1479 for (
int i = 0; i < GetNE(); i++)
1481 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
1483 (*old_elem_vert)->MakeJ();
1484 for (
int i = 0; i < GetNE(); i++)
1486 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
1487 elements[i]->GetNVertices());
1489 (*old_elem_vert)->ShiftUpI();
1503 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1519 if (num_edge_dofs > 0)
1521 DSTable new_v_to_v(NumOfVertices);
1522 GetVertexToVertexTable(new_v_to_v);
1524 for (
int i = 0; i < NumOfVertices; i++)
1528 int old_i = (*old_v_to_v)(i, it.Column());
1529 int new_i = it.Index();
1536 old_dofs.
SetSize(num_edge_dofs);
1537 new_dofs.
SetSize(num_edge_dofs);
1538 for (
int j = 0; j < num_edge_dofs; j++)
1540 old_dofs[j] = offset + old_i * num_edge_dofs + j;
1541 new_dofs[j] = offset + new_i * num_edge_dofs + j;
1545 for (
int j = 0; j < old_dofs.
Size(); j++)
1547 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1551 offset += NumOfEdges * num_edge_dofs;
1554 mfem::out <<
"Mesh::DoNodeReorder : redges = " << redges << endl;
1559 if (num_face_dofs > 0)
1562 Table old_face_vertex;
1563 old_face_vertex.
MakeI(NumOfFaces);
1564 for (
int i = 0; i < NumOfFaces; i++)
1568 old_face_vertex.
MakeJ();
1569 for (
int i = 0; i < NumOfFaces; i++)
1571 faces[i]->GetNVertices());
1575 STable3D *faces_tbl = GetElementToFaceTable(1);
1579 for (
int i = 0; i < NumOfFaces; i++)
1581 int *old_v = old_face_vertex.
GetRow(i), *new_v;
1582 int new_i, new_or, *dof_ord;
1583 switch (old_face_vertex.
RowSize(i))
1586 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
1587 new_v = faces[new_i]->GetVertices();
1588 new_or = GetTriOrientation(old_v, new_v);
1593 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
1594 new_v = faces[new_i]->GetVertices();
1595 new_or = GetQuadOrientation(old_v, new_v);
1600 old_dofs.
SetSize(num_face_dofs);
1601 new_dofs.
SetSize(num_face_dofs);
1602 for (
int j = 0; j < num_face_dofs; j++)
1604 old_dofs[j] = offset + i * num_face_dofs + j;
1605 new_dofs[j] = offset + new_i * num_face_dofs + dof_ord[j];
1611 for (
int j = 0; j < old_dofs.
Size(); j++)
1613 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1617 offset += NumOfFaces * num_face_dofs;
1623 if (num_elem_dofs > 1)
1635 for (
int i = 0; i < GetNE(); i++)
1637 int *old_v = old_elem_vert->
GetRow(i);
1638 int *new_v = elements[i]->GetVertices();
1639 int new_or, *dof_ord;
1640 int geom = elements[i]->GetGeometryType();
1643 case Geometry::SEGMENT:
1644 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
1646 case Geometry::TRIANGLE:
1647 new_or = GetTriOrientation(old_v, new_v);
1649 case Geometry::SQUARE:
1650 new_or = GetQuadOrientation(old_v, new_v);
1654 mfem::err <<
"Mesh::DoNodeReorder : " << Geometry::Name[
geom]
1655 <<
" elements (" << fec->
Name()
1656 <<
" FE collection) are not supported yet!" << endl;
1661 if (dof_ord == NULL)
1663 mfem::err <<
"Mesh::DoNodeReorder : FE collection '" << fec->
Name()
1664 <<
"' does not define reordering for " << Geometry::Name[
geom]
1665 <<
" elements!" << endl;
1668 old_dofs.
SetSize(num_elem_dofs);
1669 new_dofs.
SetSize(num_elem_dofs);
1670 for (
int j = 0; j < num_elem_dofs; j++)
1673 old_dofs[j] = offset + dof_ord[j];
1674 new_dofs[j] = offset + j;
1678 for (
int j = 0; j < old_dofs.
Size(); j++)
1680 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1683 offset += num_elem_dofs;
1690 if (num_face_dofs == 0)
1694 GetElementToFaceTable();
1697 CheckBdrElementOrientation();
1702 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1707 CheckBdrElementOrientation();
1710 Nodes->FESpace()->RebuildElementToDofTable();
1713 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
1716 CheckElementOrientation(fix_orientation);
1718 if (NumOfBdrElements == 0)
1720 GetElementToFaceTable();
1722 GenerateBoundaryElements();
1727 DSTable v_to_v(NumOfVertices);
1728 GetVertexToVertexTable(v_to_v);
1729 MarkTetMeshForRefinement(v_to_v);
1732 GetElementToFaceTable();
1735 CheckBdrElementOrientation();
1737 if (generate_edges == 1)
1739 el_to_edge =
new Table;
1740 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1751 BaseGeom = Geometry::TETRAHEDRON;
1752 BaseBdrGeom = Geometry::TRIANGLE;
1757 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
1760 CheckElementOrientation(fix_orientation);
1762 GetElementToFaceTable();
1765 if (NumOfBdrElements == 0)
1767 GenerateBoundaryElements();
1770 CheckBdrElementOrientation();
1774 el_to_edge =
new Table;
1775 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1784 BaseGeom = Geometry::CUBE;
1785 BaseBdrGeom = Geometry::SQUARE;
1790 void Mesh::FinalizeTopology()
1802 bool generate_edges =
true;
1804 if (spaceDim == 0) { spaceDim = Dim; }
1805 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
1812 if (NumOfBdrElements == 0 && Dim > 2)
1815 GetElementToFaceTable();
1817 GenerateBoundaryElements();
1827 GetElementToFaceTable();
1836 if (Dim > 1 && generate_edges)
1839 if (!el_to_edge) { el_to_edge =
new Table; }
1840 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1844 if (NumOfBdrElements == 0)
1846 GenerateBoundaryElements();
1858 ncmesh->OnMeshUpdated(
this);
1861 GenerateNCFaceInfo();
1868 void Mesh::Finalize(
bool refine,
bool fix_orientation)
1870 if (NURBSext || ncmesh)
1872 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
1873 MFEM_ASSERT(CheckBdrElementOrientation() == 0,
"");
1882 const bool check_orientation =
true;
1883 const bool curved = (Nodes != NULL);
1884 const bool may_change_topology =
1885 ( refine && (Dim > 1 && (meshgen & 1)) ) ||
1886 ( check_orientation && fix_orientation &&
1887 (Dim == 2 || (Dim == 3 && (meshgen & 1))) );
1890 Table *old_elem_vert = NULL;
1892 if (curved && may_change_topology)
1894 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
1897 if (check_orientation)
1900 CheckElementOrientation(fix_orientation);
1904 MarkForRefinement();
1907 if (may_change_topology)
1911 DoNodeReorder(old_v_to_v, old_elem_vert);
1912 delete old_elem_vert;
1925 CheckBdrElementOrientation();
1929 int generate_edges,
double sx,
double sy,
double sz)
1933 int NVert, NElem, NBdrElem;
1935 NVert = (nx+1) * (ny+1) * (nz+1);
1936 NElem = nx * ny * nz;
1937 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
1938 if (type == Element::TETRAHEDRON)
1944 InitMesh(3, 3, NVert, NElem, NBdrElem);
1950 for (z = 0; z <= nz; z++)
1952 coord[2] = ((double) z / nz) * sz;
1953 for (y = 0; y <= ny; y++)
1955 coord[1] = ((double) y / ny) * sy;
1956 for (x = 0; x <= nx; x++)
1958 coord[0] = ((double) x / nx) * sx;
1964 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
1967 for (z = 0; z < nz; z++)
1969 for (y = 0; y < ny; y++)
1971 for (x = 0; x < nx; x++)
1973 ind[0] = VTX(x , y , z );
1974 ind[1] = VTX(x+1, y , z );
1975 ind[2] = VTX(x+1, y+1, z );
1976 ind[3] = VTX(x , y+1, z );
1977 ind[4] = VTX(x , y , z+1);
1978 ind[5] = VTX(x+1, y , z+1);
1979 ind[6] = VTX(x+1, y+1, z+1);
1980 ind[7] = VTX(x , y+1, z+1);
1981 if (type == Element::TETRAHEDRON)
1983 AddHexAsTets(ind, 1);
1995 for (y = 0; y < ny; y++)
1996 for (x = 0; x < nx; x++)
1998 ind[0] = VTX(x , y , 0);
1999 ind[1] = VTX(x , y+1, 0);
2000 ind[2] = VTX(x+1, y+1, 0);
2001 ind[3] = VTX(x+1, y , 0);
2002 if (type == Element::TETRAHEDRON)
2004 AddBdrQuadAsTriangles(ind, 1);
2012 for (y = 0; y < ny; y++)
2013 for (x = 0; x < nx; x++)
2015 ind[0] = VTX(x , y , nz);
2016 ind[1] = VTX(x+1, y , nz);
2017 ind[2] = VTX(x+1, y+1, nz);
2018 ind[3] = VTX(x , y+1, nz);
2019 if (type == Element::TETRAHEDRON)
2021 AddBdrQuadAsTriangles(ind, 6);
2029 for (z = 0; z < nz; z++)
2030 for (y = 0; y < ny; y++)
2032 ind[0] = VTX(0 , y , z );
2033 ind[1] = VTX(0 , y , z+1);
2034 ind[2] = VTX(0 , y+1, z+1);
2035 ind[3] = VTX(0 , y+1, z );
2036 if (type == Element::TETRAHEDRON)
2038 AddBdrQuadAsTriangles(ind, 5);
2046 for (z = 0; z < nz; z++)
2047 for (y = 0; y < ny; y++)
2049 ind[0] = VTX(nx, y , z );
2050 ind[1] = VTX(nx, y+1, z );
2051 ind[2] = VTX(nx, y+1, z+1);
2052 ind[3] = VTX(nx, y , z+1);
2053 if (type == Element::TETRAHEDRON)
2055 AddBdrQuadAsTriangles(ind, 3);
2063 for (x = 0; x < nx; x++)
2064 for (z = 0; z < nz; z++)
2066 ind[0] = VTX(x , 0, z );
2067 ind[1] = VTX(x+1, 0, z );
2068 ind[2] = VTX(x+1, 0, z+1);
2069 ind[3] = VTX(x , 0, z+1);
2070 if (type == Element::TETRAHEDRON)
2072 AddBdrQuadAsTriangles(ind, 2);
2080 for (x = 0; x < nx; x++)
2081 for (z = 0; z < nz; z++)
2083 ind[0] = VTX(x , ny, z );
2084 ind[1] = VTX(x , ny, z+1);
2085 ind[2] = VTX(x+1, ny, z+1);
2086 ind[3] = VTX(x+1, ny, z );
2087 if (type == Element::TETRAHEDRON)
2089 AddBdrQuadAsTriangles(ind, 4);
2098 ofstream test_stream(
"debug.mesh");
2100 test_stream.close();
2104 bool fix_orientation =
true;
2106 if (type == Element::TETRAHEDRON)
2108 FinalizeTetMesh(generate_edges, refine, fix_orientation);
2112 FinalizeHexMesh(generate_edges, refine, fix_orientation);
2117 double sx,
double sy)
2126 if (type == Element::QUADRILATERAL)
2129 NumOfVertices = (nx+1) * (ny+1);
2130 NumOfElements = nx * ny;
2131 NumOfBdrElements = 2 * nx + 2 * ny;
2132 BaseGeom = Geometry::SQUARE;
2133 BaseBdrGeom = Geometry::SEGMENT;
2135 vertices.SetSize(NumOfVertices);
2136 elements.SetSize(NumOfElements);
2137 boundary.SetSize(NumOfBdrElements);
2144 for (j = 0; j < ny+1; j++)
2146 cy = ((double) j / ny) * sy;
2147 for (i = 0; i < nx+1; i++)
2149 cx = ((double) i / nx) * sx;
2150 vertices[k](0) = cx;
2151 vertices[k](1) = cy;
2158 for (j = 0; j < ny; j++)
2160 for (i = 0; i < nx; i++)
2162 ind[0] = i + j*(nx+1);
2163 ind[1] = i + 1 +j*(nx+1);
2164 ind[2] = i + 1 + (j+1)*(nx+1);
2165 ind[3] = i + (j+1)*(nx+1);
2173 for (i = 0; i < nx; i++)
2175 boundary[i] =
new Segment(i, i+1, 1);
2176 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2179 for (j = 0; j < ny; j++)
2181 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2182 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2186 else if (type == Element::TRIANGLE)
2189 NumOfVertices = (nx+1) * (ny+1);
2190 NumOfElements = 2 * nx * ny;
2191 NumOfBdrElements = 2 * nx + 2 * ny;
2192 BaseGeom = Geometry::TRIANGLE;
2193 BaseBdrGeom = Geometry::SEGMENT;
2195 vertices.SetSize(NumOfVertices);
2196 elements.SetSize(NumOfElements);
2197 boundary.SetSize(NumOfBdrElements);
2204 for (j = 0; j < ny+1; j++)
2206 cy = ((double) j / ny) * sy;
2207 for (i = 0; i < nx+1; i++)
2209 cx = ((double) i / nx) * sx;
2210 vertices[k](0) = cx;
2211 vertices[k](1) = cy;
2218 for (j = 0; j < ny; j++)
2220 for (i = 0; i < nx; i++)
2222 ind[0] = i + j*(nx+1);
2223 ind[1] = i + 1 + (j+1)*(nx+1);
2224 ind[2] = i + (j+1)*(nx+1);
2227 ind[1] = i + 1 + j*(nx+1);
2228 ind[2] = i + 1 + (j+1)*(nx+1);
2236 for (i = 0; i < nx; i++)
2238 boundary[i] =
new Segment(i, i+1, 1);
2239 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
2242 for (j = 0; j < ny; j++)
2244 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
2245 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
2248 MarkTriMeshForRefinement();
2252 MFEM_ABORT(
"Unsupported element type.");
2255 CheckElementOrientation();
2257 if (generate_edges == 1)
2259 el_to_edge =
new Table;
2260 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2262 CheckBdrElementOrientation();
2271 attributes.Append(1);
2272 bdr_attributes.Append(1); bdr_attributes.Append(2);
2273 bdr_attributes.Append(3); bdr_attributes.Append(4);
2276 void Mesh::Make1D(
int n,
double sx)
2285 BaseGeom = Geometry::SEGMENT;
2286 BaseBdrGeom = Geometry::POINT;
2290 NumOfVertices = n + 1;
2292 NumOfBdrElements = 2;
2293 vertices.SetSize(NumOfVertices);
2294 elements.SetSize(NumOfElements);
2295 boundary.SetSize(NumOfBdrElements);
2298 for (j = 0; j < n+1; j++)
2300 vertices[j](0) = ((
double) j / n) * sx;
2304 for (j = 0; j < n; j++)
2306 elements[j] =
new Segment(j, j+1, 1);
2311 boundary[0] =
new Point(ind, 1);
2313 boundary[1] =
new Point(ind, 2);
2320 attributes.Append(1);
2321 bdr_attributes.Append(1); bdr_attributes.Append(2);
2324 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
2342 last_operation = Mesh::NONE;
2345 elements.SetSize(NumOfElements);
2346 for (
int i = 0; i < NumOfElements; i++)
2348 elements[i] = mesh.
elements[i]->Duplicate(
this);
2355 boundary.SetSize(NumOfBdrElements);
2356 for (
int i = 0; i < NumOfBdrElements; i++)
2358 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
2377 faces.SetSize(mesh.
faces.Size());
2378 for (
int i = 0; i < faces.Size(); i++)
2381 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
2419 if (mesh.
Nodes && copy_nodes)
2424 FiniteElementCollection::New(fec->
Name());
2428 Nodes->MakeOwner(fec_copy);
2429 *Nodes = *mesh.
Nodes;
2439 Mesh::Mesh(
const char *filename,
int generate_edges,
int refine,
2440 bool fix_orientation)
2449 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
2453 Load(imesh, generate_edges, refine, fix_orientation);
2457 Mesh::Mesh(std::istream &input,
int generate_edges,
int refine,
2458 bool fix_orientation)
2461 Load(input, generate_edges, refine, fix_orientation);
2464 void Mesh::ChangeVertexDataOwnership(
double *vertex_data,
int len_vertex_data,
2469 MFEM_VERIFY(len_vertex_data >= NumOfVertices * 3,
2470 "Not enough vertices in external array : "
2471 "len_vertex_data = "<< len_vertex_data <<
", "
2472 "NumOfVertices * 3 = " << NumOfVertices * 3);
2474 if (vertex_data == (
double *)(vertices.GetData()))
2476 MFEM_ASSERT(!vertices.OwnsData(),
"invalid ownership");
2481 memcpy(vertex_data, vertices.GetData(),
2482 NumOfVertices * 3 *
sizeof(double));
2485 vertices.MakeRef(reinterpret_cast<Vertex*>(vertex_data), NumOfVertices);
2488 Mesh::Mesh(
double *_vertices,
int num_vertices,
2490 int *element_attributes,
int num_elements,
2492 int *boundary_attributes,
int num_boundary_elements,
2493 int dimension,
int space_dimension)
2495 if (space_dimension == -1)
2497 space_dimension = dimension;
2500 InitMesh(dimension, space_dimension, 0, num_elements,
2501 num_boundary_elements);
2503 int element_index_stride = Geometry::NumVerts[element_type];
2504 int boundary_index_stride = num_boundary_elements > 0 ?
2505 Geometry::NumVerts[boundary_type] : 0;
2508 vertices.MakeRef(reinterpret_cast<Vertex*>(_vertices), num_vertices);
2509 NumOfVertices = num_vertices;
2511 for (
int i = 0; i < num_elements; i++)
2513 elements[i] = NewElement(element_type);
2514 elements[i]->SetVertices(element_indices + i * element_index_stride);
2515 elements[i]->SetAttribute(element_attributes[i]);
2517 NumOfElements = num_elements;
2519 for (
int i = 0; i < num_boundary_elements; i++)
2521 boundary[i] = NewElement(boundary_type);
2522 boundary[i]->SetVertices(boundary_indices + i * boundary_index_stride);
2523 boundary[i]->SetAttribute(boundary_attributes[i]);
2525 NumOfBdrElements = num_boundary_elements;
2534 case Geometry::POINT:
return (
new Point);
2535 case Geometry::SEGMENT:
return (
new Segment);
2536 case Geometry::TRIANGLE:
return (
new Triangle);
2538 case Geometry::CUBE:
return (
new Hexahedron);
2539 case Geometry::TETRAHEDRON:
2540 #ifdef MFEM_USE_MEMALLOC
2541 return TetMemory.Alloc();
2550 Element *Mesh::ReadElementWithoutAttr(std::istream &input)
2556 el = NewElement(geom);
2557 MFEM_VERIFY(el,
"Unsupported element type: " << geom);
2560 for (
int i = 0; i < nv; i++)
2568 void Mesh::PrintElementWithoutAttr(
const Element *el, std::ostream &
out)
2573 for (
int j = 0; j < nv; j++)
2586 el = ReadElementWithoutAttr(input);
2595 PrintElementWithoutAttr(el, out);
2598 void Mesh::SetMeshGen()
2601 for (
int i = 0; i < NumOfElements; i++)
2603 switch (elements[i]->GetType())
2605 case Element::POINT:
2606 case Element::SEGMENT:
2607 case Element::TRIANGLE:
2608 case Element::TETRAHEDRON:
2609 meshgen |= 1;
break;
2611 case Element::QUADRILATERAL:
2612 case Element::HEXAHEDRON:
2618 void Mesh::Loader(std::istream &input,
int generate_edges,
2619 std::string parse_tag)
2621 int curved = 0, read_gf = 1;
2625 MFEM_ABORT(
"Input stream is not open");
2632 getline(input, mesh_type);
2636 bool mfem_v10 = (mesh_type ==
"MFEM mesh v1.0");
2637 bool mfem_v11 = (mesh_type ==
"MFEM mesh v1.1");
2638 bool mfem_v12 = (mesh_type ==
"MFEM mesh v1.2");
2639 if (mfem_v10 || mfem_v11 || mfem_v12)
2645 if ( mfem_v12 && parse_tag.empty() )
2647 parse_tag =
"mfem_mesh_end";
2649 ReadMFEMMesh(input, mfem_v11, curved);
2651 else if (mesh_type ==
"linemesh")
2653 ReadLineMesh(input);
2655 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
2657 if (mesh_type ==
"curved_areamesh2")
2661 ReadNetgen2DMesh(input, curved);
2663 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
2665 ReadNetgen3DMesh(input);
2667 else if (mesh_type ==
"TrueGrid")
2669 ReadTrueGridMesh(input);
2671 else if (mesh_type ==
"# vtk DataFile Version 3.0" ||
2672 mesh_type ==
"# vtk DataFile Version 2.0")
2674 ReadVTKMesh(input, curved, read_gf);
2676 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
2678 ReadNURBSMesh(input, curved, read_gf);
2680 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
2682 ReadInlineMesh(input, generate_edges);
2685 else if (mesh_type ==
"$MeshFormat")
2687 ReadGmshMesh(input);
2690 ((mesh_type.size() > 2 &&
2691 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F') ||
2692 (mesh_type.size() > 3 &&
2693 mesh_type[1] ==
'H' && mesh_type[2] ==
'D' && mesh_type[3] ==
'F'))
2698 #ifdef MFEM_USE_NETCDF
2699 ReadCubit(mesh_input->
filename, curved, read_gf);
2701 MFEM_ABORT(
"NetCDF support requires configuration with"
2702 " MFEM_USE_NETCDF=YES");
2708 MFEM_ABORT(
"Can not determine Cubit mesh filename!"
2709 " Use mfem::named_ifgzstream for input.");
2715 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
2740 if (curved && read_gf)
2744 spaceDim = Nodes->VectorDim();
2745 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2747 for (
int i = 0; i < spaceDim; i++)
2750 Nodes->GetNodalValues(vert_val, i+1);
2751 for (
int j = 0; j < NumOfVertices; j++)
2753 vertices[j](i) = vert_val(j);
2766 MFEM_VERIFY(input.good(),
"Required mesh-end tag not found");
2767 getline(input, line);
2773 if (line ==
"mfem_mesh_end") {
break; }
2775 while (line != parse_tag);
2781 Mesh::Mesh(
Mesh *mesh_array[],
int num_pieces)
2783 int i, j, ie, ib, iv, *v, nv;
2792 BaseGeom = mesh_array[0]->
BaseGeom;
2795 if (mesh_array[0]->NURBSext)
2800 NumOfVertices = NURBSext->GetNV();
2801 NumOfElements = NURBSext->GetNE();
2803 NURBSext->GetElementTopo(elements);
2816 NumOfBdrElements = 0;
2817 for (i = 0; i < num_pieces; i++)
2819 NumOfBdrElements += mesh_array[i]->
GetNBE();
2821 boundary.SetSize(NumOfBdrElements);
2822 vertices.SetSize(NumOfVertices);
2824 for (i = 0; i < num_pieces; i++)
2830 for (j = 0; j < m->
GetNE(); j++)
2832 elements[lelem_elem[j]]->SetAttribute(m->
GetAttribute(j));
2835 for (j = 0; j < m->
GetNBE(); j++)
2840 for (
int k = 0; k < nv; k++)
2842 v[k] = lvert_vert[v[k]];
2844 boundary[ib++] = el;
2847 for (j = 0; j < m->
GetNV(); j++)
2857 NumOfBdrElements = 0;
2859 for (i = 0; i < num_pieces; i++)
2862 NumOfElements += m->
GetNE();
2863 NumOfBdrElements += m->
GetNBE();
2864 NumOfVertices += m->
GetNV();
2866 elements.SetSize(NumOfElements);
2867 boundary.SetSize(NumOfBdrElements);
2868 vertices.SetSize(NumOfVertices);
2870 for (i = 0; i < num_pieces; i++)
2874 for (j = 0; j < m->
GetNE(); j++)
2879 for (
int k = 0; k < nv; k++)
2883 elements[ie++] = el;
2886 for (j = 0; j < m->
GetNBE(); j++)
2891 for (
int k = 0; k < nv; k++)
2895 boundary[ib++] = el;
2898 for (j = 0; j < m->
GetNV(); j++)
2907 for (i = 0; i < num_pieces; i++)
2915 GetElementToFaceTable();
2926 el_to_edge =
new Table;
2927 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2946 for (i = 0; i < num_pieces; i++)
2948 gf_array[i] = mesh_array[i]->
GetNodes();
2955 CheckElementOrientation(
false);
2956 CheckBdrElementOrientation(
false);
2960 Mesh::Mesh(
Mesh *orig_mesh,
int ref_factor,
int ref_type)
2963 MFEM_VERIFY(ref_factor > 1,
"the refinement factor must be > 1");
2964 MFEM_VERIFY(ref_type == BasisType::ClosedUniform ||
2965 ref_type == BasisType::GaussLobatto,
"invalid refinement type");
2966 MFEM_VERIFY(Dim == 2 || Dim == 3,
2967 "only implemented for Hexahedron and Quadrilateral elements in "
2975 int r_bndr_factor = ref_factor * (Dim == 2 ? 1 : ref_factor);
2976 int r_elem_factor = ref_factor * r_bndr_factor;
2979 int r_num_elem = orig_mesh->
GetNE() * r_elem_factor;
2980 int r_num_bndr = orig_mesh->
GetNBE() * r_bndr_factor;
2982 InitMesh(Dim, orig_mesh->
SpaceDimension(), r_num_vert, r_num_elem,
2986 NumOfVertices = r_num_vert;
2991 for (
int el = 0; el < orig_mesh->
GetNE(); el++)
2995 int nvert = Geometry::NumVerts[
geom];
2998 max_nv = std::max(max_nv, nvert);
3004 const int *c2h_map = rfec.
GetDofMap(geom);
3005 for (
int i = 0; i < phys_pts.
Width(); i++)
3007 vertices[rdofs[i]].SetCoords(spaceDim, phys_pts.
GetColumn(i));
3011 Element *elem = NewElement(geom);
3014 for (
int k = 0; k < nvert; k++)
3017 v[k] = rdofs[c2h_map[cid]];
3023 for (
int el = 0; el < orig_mesh->
GetNBE(); el++)
3027 int nvert = Geometry::NumVerts[
geom];
3032 const int *c2h_map = rfec.
GetDofMap(geom);
3035 Element *elem = NewElement(geom);
3038 for (
int k = 0; k < nvert; k++)
3041 v[k] = rdofs[c2h_map[cid]];
3043 AddBdrElement(elem);
3049 last_operation = Mesh::REFINE;
3052 MFEM_VERIFY(BaseGeom != -1,
"meshes with mixed elements are not supported");
3053 CoarseFineTr.point_matrices.SetSize(Dim, max_nv, r_elem_factor);
3054 CoarseFineTr.embeddings.SetSize(GetNE());
3055 if (orig_mesh->
GetNE() > 0)
3059 int nvert = Geometry::NumVerts[
geom];
3061 const int *c2h_map = rfec.
GetDofMap(geom);
3066 for (
int k = 0; k < nvert; k++)
3074 for (
int el = 0; el < GetNE(); el++)
3076 Embedding &emb = CoarseFineTr.embeddings[el];
3077 emb.
parent = el / r_elem_factor;
3078 emb.
matrix = el % r_elem_factor;
3081 MFEM_ASSERT(CheckElementOrientation(
false) == 0,
"");
3082 MFEM_ASSERT(CheckBdrElementOrientation(
false) == 0,
"");
3087 if (NURBSext == NULL)
3089 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
3092 if (kv.
Size() != NURBSext->GetNKV())
3094 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
3097 NURBSext->ConvertToPatches(*Nodes);
3099 NURBSext->KnotInsert(kv);
3101 last_operation = Mesh::NONE;
3107 void Mesh::NURBSUniformRefinement()
3110 NURBSext->ConvertToPatches(*Nodes);
3112 NURBSext->UniformRefinement();
3114 last_operation = Mesh::NONE;
3120 void Mesh::DegreeElevate(
int rel_degree,
int degree)
3122 if (NURBSext == NULL)
3124 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
3127 NURBSext->ConvertToPatches(*Nodes);
3129 NURBSext->DegreeElevate(rel_degree, degree);
3131 last_operation = Mesh::NONE;
3137 void Mesh::UpdateNURBS()
3139 NURBSext->SetKnotsFromPatches();
3141 Dim = NURBSext->Dimension();
3144 if (NumOfElements != NURBSext->GetNE())
3146 for (
int i = 0; i < elements.Size(); i++)
3148 FreeElement(elements[i]);
3150 NumOfElements = NURBSext->GetNE();
3151 NURBSext->GetElementTopo(elements);
3154 if (NumOfBdrElements != NURBSext->GetNBE())
3156 for (
int i = 0; i < boundary.Size(); i++)
3158 FreeElement(boundary[i]);
3160 NumOfBdrElements = NURBSext->GetNBE();
3161 NURBSext->GetBdrElementTopo(boundary);
3164 Nodes->FESpace()->Update();
3166 NURBSext->SetCoordsFromPatches(*Nodes);
3168 if (NumOfVertices != NURBSext->GetNV())
3170 NumOfVertices = NURBSext->GetNV();
3171 vertices.SetSize(NumOfVertices);
3172 int vd = Nodes->VectorDim();
3173 for (
int i = 0; i < vd; i++)
3176 Nodes->GetNodalValues(vert_val, i+1);
3177 for (
int j = 0; j < NumOfVertices; j++)
3179 vertices[j](i) = vert_val(j);
3186 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3195 GetElementToFaceTable();
3200 void Mesh::LoadPatchTopo(std::istream &input,
Array<int> &edge_to_knot)
3218 input >> NumOfElements;
3219 elements.SetSize(NumOfElements);
3220 for (j = 0; j < NumOfElements; j++)
3222 elements[j] = ReadElement(input);
3228 input >> NumOfBdrElements;
3229 boundary.SetSize(NumOfBdrElements);
3230 for (j = 0; j < NumOfBdrElements; j++)
3232 boundary[j] = ReadElement(input);
3238 input >> NumOfEdges;
3239 edge_vertex =
new Table(NumOfEdges, 2);
3240 edge_to_knot.
SetSize(NumOfEdges);
3241 for (j = 0; j < NumOfEdges; j++)
3243 int *v = edge_vertex->GetRow(j);
3244 input >> edge_to_knot[j] >> v[0] >> v[1];
3247 edge_to_knot[j] = -1 - edge_to_knot[j];
3254 input >> NumOfVertices;
3255 vertices.SetSize(0);
3264 GetElementToFaceTable();
3266 if (NumOfBdrElements == 0)
3268 GenerateBoundaryElements();
3270 CheckBdrElementOrientation();
3280 el_to_edge =
new Table;
3281 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
3285 if (NumOfBdrElements == 0)
3287 GenerateBoundaryElements();
3289 CheckBdrElementOrientation();
3305 for (
int d = 0; d < v.
Size(); d++)
3313 for (d = 0; d < p.
Size(); d++)
3317 for ( ; d < v.
Size(); d++)
3326 if (Nodes == NULL || Nodes->FESpace() != nodes.
FESpace())
3341 SetNodalGridFunction(nodes,
true);
3347 NewNodes(*nodes, make_owner);
3352 return ((Nodes) ? Nodes->FESpace() : NULL);
3355 void Mesh::SetCurvature(
int order,
bool discont,
int space_dim,
int ordering)
3357 space_dim = (space_dim == -1) ? spaceDim : space_dim;
3370 SetNodalFESpace(nfes);
3371 Nodes->MakeOwner(nfec);
3374 int Mesh::GetNumFaces()
const
3378 case 1:
return GetNV();
3379 case 2:
return GetNEdges();
3380 case 3:
return GetNFaces();
3385 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3386 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
3389 int Mesh::CheckElementOrientation(
bool fix_it)
3391 int i, j, k, wo = 0, fo = 0, *vi = 0;
3394 if (Dim == 2 && spaceDim == 2)
3398 for (i = 0; i < NumOfElements; i++)
3402 vi = elements[i]->GetVertices();
3403 for (j = 0; j < 3; j++)
3405 v[j] = vertices[vi[j]]();
3407 for (j = 0; j < 2; j++)
3408 for (k = 0; k < 2; k++)
3410 J(j, k) = v[j+1][k] - v[0][k];
3416 GetElementJacobian(i, J);
3422 switch (GetElementType(i))
3424 case Element::TRIANGLE:
3427 case Element::QUADRILATERAL:
3442 for (i = 0; i < NumOfElements; i++)
3444 vi = elements[i]->GetVertices();
3445 switch (GetElementType(i))
3447 case Element::TETRAHEDRON:
3450 for (j = 0; j < 4; j++)
3452 v[j] = vertices[vi[j]]();
3454 for (j = 0; j < 3; j++)
3455 for (k = 0; k < 3; k++)
3457 J(j, k) = v[j+1][k] - v[0][k];
3463 GetElementJacobian(i, J);
3476 case Element::HEXAHEDRON:
3478 GetElementJacobian(i, J);
3491 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3493 mfem::out <<
"Elements with wrong orientation: " << wo <<
" / "
3494 << NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
3500 int Mesh::GetTriOrientation(
const int *base,
const int *test)
3508 if (test[0] == base[0])
3509 if (test[1] == base[1])
3517 else if (test[0] == base[1])
3518 if (test[1] == base[0])
3527 if (test[1] == base[0])
3537 const int *aor = tri_t::Orient[orient];
3538 for (
int j = 0; j < 3; j++)
3539 if (test[aor[j]] != base[j])
3548 int Mesh::GetQuadOrientation(
const int *base,
const int *test)
3552 for (i = 0; i < 4; i++)
3553 if (test[i] == base[0])
3560 if (test[(i+1)%4] == base[1])
3568 const int *aor = quad_t::Orient[orient];
3569 for (
int j = 0; j < 4; j++)
3570 if (test[aor[j]] != base[j])
3572 mfem::err <<
"Mesh::GetQuadOrientation(...)" << endl;
3574 for (
int k = 0; k < 4; k++)
3579 for (
int k = 0; k < 4; k++)
3588 if (test[(i+1)%4] == base[1])
3596 int Mesh::CheckBdrElementOrientation(
bool fix_it)
3602 for (i = 0; i < NumOfBdrElements; i++)
3604 if (faces_info[be_to_edge[i]].Elem2No < 0)
3606 int *bv = boundary[i]->GetVertices();
3607 int *fv = faces[be_to_edge[i]]->GetVertices();
3612 mfem::Swap<int>(bv[0], bv[1]);
3625 for (i = 0; i < NumOfBdrElements; i++)
3627 if (faces_info[be_to_face[i]].Elem2No < 0)
3630 bv = boundary[i]->GetVertices();
3631 el = faces_info[be_to_face[i]].Elem1No;
3632 ev = elements[el]->GetVertices();
3633 switch (GetElementType(el))
3635 case Element::TETRAHEDRON:
3637 int *fv = faces[be_to_face[i]]->GetVertices();
3640 orientation = GetTriOrientation(fv, bv);
3641 if (orientation % 2)
3647 mfem::Swap<int>(bv[0], bv[1]);
3650 int *be = bel_to_edge->GetRow(i);
3651 mfem::Swap<int>(be[1], be[2]);
3659 case Element::HEXAHEDRON:
3661 int lf = faces_info[be_to_face[i]].Elem1Inf/64;
3662 for (
int j = 0; j < 4; j++)
3664 v[j] = ev[hex_t::FaceVert[lf][j]];
3666 if (GetQuadOrientation(v, bv) % 2)
3670 mfem::Swap<int>(bv[0], bv[2]);
3673 int *be = bel_to_edge->GetRow(i);
3674 mfem::Swap<int>(be[0], be[1]);
3675 mfem::Swap<int>(be[2], be[3]);
3690 mfem::out <<
"Boundary elements with wrong orientation: " << wo <<
" / "
3691 << NumOfBdrElements <<
" (" << fixed_or_not[fix_it ? 0 : 1]
3702 el_to_edge->GetRow(i, edges);
3706 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
3707 "is not generated.");
3710 const int *v = elements[i]->GetVertices();
3711 const int ne = elements[i]->GetNEdges();
3713 for (
int j = 0; j < ne; j++)
3715 const int *e = elements[i]->GetEdgeVertices(j);
3716 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3726 edges[0] = be_to_edge[i];
3727 const int *v = boundary[i]->GetVertices();
3728 cor[0] = (v[0] < v[1]) ? (1) : (-1);
3734 bel_to_edge->GetRow(i, edges);
3741 const int *v = boundary[i]->GetVertices();
3742 const int ne = boundary[i]->GetNEdges();
3744 for (
int j = 0; j < ne; j++)
3746 const int *e = boundary[i]->GetEdgeVertices(j);
3747 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3759 const int *v = faces[i]->GetVertices();
3760 o[0] = (v[0] < v[1]) ? (1) : (-1);
3770 face_edge->GetRow(i, edges);
3772 const int *v = faces[i]->GetVertices();
3773 const int ne = faces[i]->GetNEdges();
3775 for (
int j = 0; j < ne; j++)
3777 const int *e = faces[i]->GetEdgeVertices(j);
3778 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3787 if (!edge_vertex) { GetEdgeVertexTable(); }
3788 edge_vertex->GetRow(i, vert);
3804 if (faces.Size() != NumOfFaces)
3806 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
3810 DSTable v_to_v(NumOfVertices);
3811 GetVertexToVertexTable(v_to_v);
3813 face_edge =
new Table;
3814 GetElementArrayEdgeTable(faces, v_to_v, *face_edge);
3826 DSTable v_to_v(NumOfVertices);
3827 GetVertexToVertexTable(v_to_v);
3830 edge_vertex =
new Table(nedges, 2);
3831 for (
int i = 0; i < NumOfVertices; i++)
3836 edge_vertex->Push(j, i);
3837 edge_vertex->Push(j, it.Column());
3840 edge_vertex->Finalize();
3851 vert_elem->
MakeI(NumOfVertices);
3853 for (i = 0; i < NumOfElements; i++)
3855 nv = elements[i]->GetNVertices();
3856 v = elements[i]->GetVertices();
3857 for (j = 0; j < nv; j++)
3865 for (i = 0; i < NumOfElements; i++)
3867 nv = elements[i]->GetNVertices();
3868 v = elements[i]->GetVertices();
3869 for (j = 0; j < nv; j++)
3880 Table *Mesh::GetFaceToElementTable()
const
3884 face_elem->
MakeI(faces_info.Size());
3886 for (
int i = 0; i < faces_info.Size(); i++)
3888 if (faces_info[i].Elem2No >= 0)
3900 for (
int i = 0; i < faces_info.Size(); i++)
3903 if (faces_info[i].Elem2No >= 0)
3921 el_to_face->
GetRow(i, fcs);
3925 mfem_error(
"Mesh::GetElementFaces(...) : el_to_face not generated.");
3930 for (j = 0; j < n; j++)
3931 if (faces_info[fcs[j]].Elem1No == i)
3933 cor[j] = faces_info[fcs[j]].Elem1Inf % 64;
3936 else if (faces_info[fcs[j]].Elem2No == i)
3938 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3942 mfem_error(
"Mesh::GetElementFaces(...) : 2");
3947 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3952 void Mesh::GetBdrElementFace(
int i,
int *f,
int *o)
const
3957 bv = boundary[i]->GetVertices();
3958 fv = faces[be_to_face[i]]->GetVertices();
3962 switch (GetBdrElementType(i))
3964 case Element::TRIANGLE:
3965 *o = GetTriOrientation(fv, bv);
3967 case Element::QUADRILATERAL:
3968 *o = GetQuadOrientation(fv, bv);
3971 mfem_error(
"Mesh::GetBdrElementFace(...) 2");
3975 int Mesh::GetFaceBaseGeometry(
int i)
const
3978 switch (GetElementType(0))
3980 case Element::SEGMENT:
3981 return Geometry::POINT;
3983 case Element::TRIANGLE:
3984 case Element::QUADRILATERAL:
3985 return Geometry::SEGMENT;
3987 case Element::TETRAHEDRON:
3988 return Geometry::TRIANGLE;
3989 case Element::HEXAHEDRON:
3990 return Geometry::SQUARE;
3992 mfem_error(
"Mesh::GetFaceBaseGeometry(...) #1");
3997 int Mesh::GetBdrElementEdgeIndex(
int i)
const
4001 case 1:
return boundary[i]->GetVertices()[0];
4002 case 2:
return be_to_edge[i];
4003 case 3:
return be_to_face[i];
4004 default:
mfem_error(
"Mesh::GetBdrElementEdgeIndex: invalid dimension!");
4009 void Mesh::GetBdrElementAdjacentElement(
int bdr_el,
int &el,
int &info)
const
4011 int fid = GetBdrElementEdgeIndex(bdr_el);
4012 const FaceInfo &fi = faces_info[fid];
4013 MFEM_ASSERT(fi.
Elem1Inf%64 == 0,
"internal error");
4014 const int *fv = (Dim > 1) ? faces[fid]->GetVertices() : NULL;
4015 const int *bv = boundary[bdr_el]->GetVertices();
4017 switch (GetBdrElementBaseGeometry(bdr_el))
4019 case Geometry::POINT: ori = 0;
break;
4020 case Geometry::SEGMENT: ori = (fv[0] == bv[0]) ? 0 : 1;
break;
4021 case Geometry::TRIANGLE: ori = GetTriOrientation(fv, bv);
break;
4022 case Geometry::SQUARE: ori = GetQuadOrientation(fv, bv);
break;
4023 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
4029 int Mesh::GetElementType(
int i)
const
4031 return elements[i]->GetType();
4034 int Mesh::GetBdrElementType(
int i)
const
4036 return boundary[i]->GetType();
4044 v = elements[i]->GetVertices();
4045 nv = elements[i]->GetNVertices();
4047 pointmat.
SetSize(spaceDim, nv);
4048 for (k = 0; k < spaceDim; k++)
4049 for (j = 0; j < nv; j++)
4051 pointmat(k, j) = vertices[v[j]](k);
4060 v = boundary[i]->GetVertices();
4061 nv = boundary[i]->GetNVertices();
4063 pointmat.
SetSize(spaceDim, nv);
4064 for (k = 0; k < spaceDim; k++)
4065 for (j = 0; j < nv; j++)
4067 pointmat(k, j) = vertices[v[j]](k);
4071 double Mesh::GetLength(
int i,
int j)
const
4073 const double *vi = vertices[i]();
4074 const double *vj = vertices[j]();
4077 for (
int k = 0; k < spaceDim; k++)
4079 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
4082 return sqrt(length);
4090 for (
int i = 0; i < elem_array.
Size(); i++)
4095 for (
int i = 0; i < elem_array.
Size(); i++)
4097 const int *v = elem_array[i]->GetVertices();
4098 const int ne = elem_array[i]->GetNEdges();
4099 for (
int j = 0; j < ne; j++)
4101 const int *e = elem_array[i]->GetEdgeVertices(j);
4108 void Mesh::GetVertexToVertexTable(
DSTable &v_to_v)
const
4112 for (
int i = 0; i < edge_vertex->Size(); i++)
4114 const int *v = edge_vertex->GetRow(i);
4115 v_to_v.
Push(v[0], v[1]);
4120 for (
int i = 0; i < NumOfElements; i++)
4122 const int *v = elements[i]->GetVertices();
4123 const int ne = elements[i]->GetNEdges();
4124 for (
int j = 0; j < ne; j++)
4126 const int *e = elements[i]->GetEdgeVertices(j);
4127 v_to_v.
Push(v[e[0]], v[e[1]]);
4135 int i, NumberOfEdges;
4137 DSTable v_to_v(NumOfVertices);
4138 GetVertexToVertexTable(v_to_v);
4143 GetElementArrayEdgeTable(elements, v_to_v, e_to_f);
4148 be_to_f.
SetSize(NumOfBdrElements);
4149 for (i = 0; i < NumOfBdrElements; i++)
4151 const int *v = boundary[i]->GetVertices();
4152 be_to_f[i] = v_to_v(v[0], v[1]);
4157 if (bel_to_edge == NULL)
4159 bel_to_edge =
new Table;
4161 GetElementArrayEdgeTable(boundary, v_to_v, *bel_to_edge);
4165 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
4169 return NumberOfEdges;
4172 const Table & Mesh::ElementToElementTable()
4180 MFEM_ASSERT(faces_info.Size() >= GetNumFaces(),
"faces were not generated!");
4183 conn.
Reserve(2*faces_info.Size());
4185 for (
int i = 0; i < faces_info.Size(); i++)
4187 const FaceInfo &fi = faces_info[i];
4195 int nbr_elem_idx = NumOfElements - 1 - fi.
Elem2No;
4203 el_to_el =
new Table(NumOfElements, conn);
4208 const Table & Mesh::ElementToFaceTable()
const
4210 if (el_to_face == NULL)
4217 const Table & Mesh::ElementToEdgeTable()
const
4219 if (el_to_edge == NULL)
4226 void Mesh::AddPointFaceElement(
int lf,
int gf,
int el)
4228 if (faces_info[gf].Elem1No == -1)
4231 faces_info[gf].Elem1No = el;
4232 faces_info[gf].Elem1Inf = 64 * lf;
4233 faces_info[gf].Elem2No = -1;
4234 faces_info[gf].Elem2Inf = -1;
4238 faces_info[gf].Elem2No = el;
4239 faces_info[gf].Elem2Inf = 64 * lf + 1;
4243 void Mesh::AddSegmentFaceElement(
int lf,
int gf,
int el,
int v0,
int v1)
4245 if (faces[gf] == NULL)
4247 faces[gf] =
new Segment(v0, v1);
4248 faces_info[gf].Elem1No = el;
4249 faces_info[gf].Elem1Inf = 64 * lf;
4250 faces_info[gf].Elem2No = -1;
4251 faces_info[gf].Elem2Inf = -1;
4255 int *v = faces[gf]->GetVertices();
4256 faces_info[gf].Elem2No = el;
4257 if ( v[1] == v0 && v[0] == v1 )
4259 faces_info[gf].Elem2Inf = 64 * lf + 1;
4261 else if ( v[0] == v0 && v[1] == v1 )
4263 faces_info[gf].Elem2Inf = 64 * lf;
4267 MFEM_ASSERT((v[1] == v0 && v[0] == v1)||
4268 (v[0] == v0 && v[1] == v1),
"");
4273 void Mesh::AddTriangleFaceElement(
int lf,
int gf,
int el,
4274 int v0,
int v1,
int v2)
4276 if (faces[gf] == NULL)
4278 faces[gf] =
new Triangle(v0, v1, v2);
4279 faces_info[gf].Elem1No = el;
4280 faces_info[gf].Elem1Inf = 64 * lf;
4281 faces_info[gf].Elem2No = -1;
4282 faces_info[gf].Elem2Inf = -1;
4286 int orientation, vv[3] = { v0, v1, v2 };
4287 orientation = GetTriOrientation(faces[gf]->GetVertices(), vv);
4288 MFEM_ASSERT(orientation % 2 != 0,
"");
4289 faces_info[gf].Elem2No = el;
4290 faces_info[gf].Elem2Inf = 64 * lf + orientation;
4294 void Mesh::AddQuadFaceElement(
int lf,
int gf,
int el,
4295 int v0,
int v1,
int v2,
int v3)
4297 if (faces_info[gf].Elem1No < 0)
4300 faces_info[gf].Elem1No = el;
4301 faces_info[gf].Elem1Inf = 64 * lf;
4302 faces_info[gf].Elem2No = -1;
4303 faces_info[gf].Elem2Inf = -1;
4307 int vv[4] = { v0, v1, v2, v3 };
4308 int oo = GetQuadOrientation(faces[gf]->GetVertices(), vv);
4309 MFEM_ASSERT(oo % 2 != 0,
"");
4310 faces_info[gf].Elem2No = el;
4311 faces_info[gf].Elem2Inf = 64 * lf + oo;
4315 void Mesh::GenerateFaces()
4317 int i, nfaces = GetNumFaces();
4319 for (i = 0; i < faces.Size(); i++)
4321 FreeElement(faces[i]);
4325 faces.SetSize(nfaces);
4326 faces_info.SetSize(nfaces);
4327 for (i = 0; i < nfaces; i++)
4330 faces_info[i].Elem1No = -1;
4331 faces_info[i].NCFace = -1;
4333 for (i = 0; i < NumOfElements; i++)
4335 const int *v = elements[i]->GetVertices();
4339 AddPointFaceElement(0, v[0], i);
4340 AddPointFaceElement(1, v[1], i);
4344 ef = el_to_edge->GetRow(i);
4345 const int ne = elements[i]->GetNEdges();
4346 for (
int j = 0; j < ne; j++)
4348 const int *e = elements[i]->GetEdgeVertices(j);
4349 AddSegmentFaceElement(j, ef[j], i, v[e[0]], v[e[1]]);
4354 ef = el_to_face->GetRow(i);
4355 switch (GetElementType(i))
4357 case Element::TETRAHEDRON:
4359 for (
int j = 0; j < 4; j++)
4361 const int *fv = tet_t::FaceVert[j];
4362 AddTriangleFaceElement(j, ef[j], i,
4363 v[fv[0]], v[fv[1]], v[fv[2]]);
4367 case Element::HEXAHEDRON:
4369 for (
int j = 0; j < 6; j++)
4371 const int *fv = hex_t::FaceVert[j];
4372 AddQuadFaceElement(j, ef[j], i,
4373 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4378 MFEM_ABORT(
"Unexpected type of Element.");
4384 void Mesh::GenerateNCFaceInfo()
4386 MFEM_VERIFY(ncmesh,
"missing NCMesh.");
4388 for (
int i = 0; i < faces_info.Size(); i++)
4390 faces_info[i].NCFace = -1;
4394 (Dim == 2) ? ncmesh->GetEdgeList() : ncmesh->GetFaceList();
4396 nc_faces_info.SetSize(0);
4397 nc_faces_info.Reserve(list.
masters.size() + list.
slaves.size());
4399 int nfaces = GetNumFaces();
4402 for (
unsigned i = 0; i < list.
masters.size(); i++)
4405 if (master.
index >= nfaces) {
continue; }
4407 faces_info[master.
index].NCFace = nc_faces_info.Size();
4413 for (
unsigned i = 0; i < list.
slaves.size(); i++)
4416 if (slave.
index >= nfaces || slave.
master >= nfaces) {
continue; }
4422 slave_fi.
NCFace = nc_faces_info.Size();
4434 for (
int i = 0; i < NumOfElements; i++)
4436 const int *v = elements[i]->GetVertices();
4437 switch (GetElementType(i))
4439 case Element::TETRAHEDRON:
4441 for (
int j = 0; j < 4; j++)
4443 const int *fv = tet_t::FaceVert[j];
4444 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
4448 case Element::HEXAHEDRON:
4452 for (
int j = 0; j < 6; j++)
4454 const int *fv = hex_t::FaceVert[j];
4455 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4460 MFEM_ABORT(
"Unexpected type of Element.");
4471 if (el_to_face != NULL)
4475 el_to_face =
new Table(NumOfElements, 6);
4476 faces_tbl =
new STable3D(NumOfVertices);
4477 for (i = 0; i < NumOfElements; i++)
4479 v = elements[i]->GetVertices();
4480 switch (GetElementType(i))
4482 case Element::TETRAHEDRON:
4484 for (
int j = 0; j < 4; j++)
4486 const int *fv = tet_t::FaceVert[j];
4488 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
4492 case Element::HEXAHEDRON:
4496 for (
int j = 0; j < 6; j++)
4498 const int *fv = hex_t::FaceVert[j];
4500 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
4505 MFEM_ABORT(
"Unexpected type of Element.");
4508 el_to_face->Finalize();
4510 be_to_face.SetSize(NumOfBdrElements);
4511 for (i = 0; i < NumOfBdrElements; i++)
4513 v = boundary[i]->GetVertices();
4514 switch (GetBdrElementType(i))
4516 case Element::TRIANGLE:
4518 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2]);
4521 case Element::QUADRILATERAL:
4523 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
4527 MFEM_ABORT(
"Unexpected type of boundary Element.");
4539 void Mesh::ReorientTetMesh()
4543 if (Dim != 3 || !(meshgen & 1))
4549 Table *old_elem_vert = NULL;
4553 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
4556 for (
int i = 0; i < NumOfElements; i++)
4558 if (GetElementType(i) == Element::TETRAHEDRON)
4560 v = elements[i]->GetVertices();
4562 Rotate3(v[0], v[1], v[2]);
4565 Rotate3(v[1], v[2], v[3]);
4569 ShiftL2R(v[0], v[1], v[3]);
4574 for (
int i = 0; i < NumOfBdrElements; i++)
4576 if (GetBdrElementType(i) == Element::TRIANGLE)
4578 v = boundary[i]->GetVertices();
4580 Rotate3(v[0], v[1], v[2]);
4586 GetElementToFaceTable();
4590 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
4595 DoNodeReorder(old_v_to_v, old_elem_vert);
4596 delete old_elem_vert;
4601 int *Mesh::CartesianPartitioning(
int nxyz[])
4607 for (
int vi = 0; vi < NumOfVertices; vi++)
4609 const double *p = vertices[vi]();
4610 for (
int i = 0; i < spaceDim; i++)
4612 if (p[i] < pmin[i]) { pmin[i] = p[i]; }
4613 if (p[i] > pmax[i]) { pmax[i] = p[i]; }
4617 partitioning =
new int[NumOfElements];
4621 Vector pt(ppt, spaceDim);
4622 for (
int el = 0; el < NumOfElements; el++)
4624 GetElementTransformation(el)->Transform(
4627 for (
int i = spaceDim-1; i >= 0; i--)
4629 int idx = (int)floor(nxyz[i]*((pt(i) - pmin[i])/(pmax[i] - pmin[i])));
4630 if (idx < 0) { idx = 0; }
4631 if (idx >= nxyz[i]) { idx = nxyz[i]-1; }
4632 part = part * nxyz[i] + idx;
4634 partitioning[el] = part;
4637 return partitioning;
4640 int *Mesh::GeneratePartitioning(
int nparts,
int part_method)
4642 #ifdef MFEM_USE_METIS
4643 int i, *partitioning;
4645 ElementToElementTable();
4647 partitioning =
new int[NumOfElements];
4651 for (i = 0; i < NumOfElements; i++)
4653 partitioning[i] = 0;
4659 #ifndef MFEM_USE_METIS_5
4671 I = el_to_el->GetI();
4672 J = el_to_el->GetJ();
4673 #ifndef MFEM_USE_METIS_5
4676 METIS_SetDefaultOptions(options);
4677 options[METIS_OPTION_CONTIG] = 1;
4681 if (part_method >= 0 && part_method <= 2)
4683 for (i = 0; i < n; i++)
4689 std::sort(J+I[i], J+I[i+1], std::greater<int>());
4695 if (part_method == 0 || part_method == 3)
4697 #ifndef MFEM_USE_METIS_5
4725 " error in METIS_PartGraphRecursive!");
4731 if (part_method == 1 || part_method == 4)
4733 #ifndef MFEM_USE_METIS_5
4761 " error in METIS_PartGraphKway!");
4767 if (part_method == 2 || part_method == 5)
4769 #ifndef MFEM_USE_METIS_5
4782 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_VOL;
4798 " error in METIS_PartGraphKway!");
4803 mfem::out <<
"Mesh::GeneratePartitioning(...): edgecut = "
4817 for (i = 0; i < nparts; i++)
4823 for (i = 0; i < NumOfElements; i++)
4825 psize[partitioning[i]].one++;
4828 int empty_parts = 0;
4829 for (i = 0; i < nparts; i++)
4830 if (psize[i].one == 0)
4839 mfem::err <<
"Mesh::GeneratePartitioning returned " << empty_parts
4840 <<
" empty parts!" << endl;
4842 SortPairs<int,int>(psize, nparts);
4844 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4849 for (
int j = 0; j < NumOfElements; j++)
4850 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4851 if (psize[i].one == 0 || partitioning[j] != psize[i].two)
4857 partitioning[j] = psize[nparts-1-i].two;
4863 return partitioning;
4867 mfem_error(
"Mesh::GeneratePartitioning(...): "
4868 "MFEM was compiled without Metis.");
4882 int num_elem, *i_elem_elem, *j_elem_elem;
4884 num_elem = elem_elem.
Size();
4885 i_elem_elem = elem_elem.
GetI();
4886 j_elem_elem = elem_elem.
GetJ();
4891 int stack_p, stack_top_p, elem;
4895 for (i = 0; i < num_elem; i++)
4897 if (partitioning[i] > num_part)
4899 num_part = partitioning[i];
4906 for (i = 0; i < num_part; i++)
4913 for (elem = 0; elem < num_elem; elem++)
4915 if (component[elem] >= 0)
4920 component[elem] = num_comp[partitioning[elem]]++;
4922 elem_stack[stack_top_p++] = elem;
4924 for ( ; stack_p < stack_top_p; stack_p++)
4926 i = elem_stack[stack_p];
4927 for (j = i_elem_elem[i]; j < i_elem_elem[i+1]; j++)
4930 if (partitioning[k] == partitioning[i])
4932 if (component[k] < 0)
4934 component[k] = component[i];
4935 elem_stack[stack_top_p++] = k;
4937 else if (component[k] != component[i])
4947 void Mesh::CheckPartitioning(
int *partitioning)
4949 int i, n_empty, n_mcomp;
4951 const Array<int> _partitioning(partitioning, GetNE());
4953 ElementToElementTable();
4957 n_empty = n_mcomp = 0;
4958 for (i = 0; i < num_comp.
Size(); i++)
4959 if (num_comp[i] == 0)
4963 else if (num_comp[i] > 1)
4970 mfem::out <<
"Mesh::CheckPartitioning(...) :\n"
4971 <<
"The following subdomains are empty :\n";
4972 for (i = 0; i < num_comp.
Size(); i++)
4973 if (num_comp[i] == 0)
4981 mfem::out <<
"Mesh::CheckPartitioning(...) :\n"
4982 <<
"The following subdomains are NOT connected :\n";
4983 for (i = 0; i < num_comp.
Size(); i++)
4984 if (num_comp[i] > 1)
4990 if (n_empty == 0 && n_mcomp == 0)
4991 mfem::out <<
"Mesh::CheckPartitioning(...) : "
4992 "All subdomains are connected." << endl;
5006 const double *a = A.
Data();
5007 const double *b = B.
Data();
5016 c(0) = a[0]*a[3]-a[1]*a[2];
5017 c(1) = a[0]*b[3]-a[1]*b[2]+b[0]*a[3]-b[1]*a[2];
5018 c(2) = b[0]*b[3]-b[1]*b[2];
5039 c(0) = (a[0] * (a[4] * a[8] - a[5] * a[7]) +
5040 a[1] * (a[5] * a[6] - a[3] * a[8]) +
5041 a[2] * (a[3] * a[7] - a[4] * a[6]));
5043 c(1) = (b[0] * (a[4] * a[8] - a[5] * a[7]) +
5044 b[1] * (a[5] * a[6] - a[3] * a[8]) +
5045 b[2] * (a[3] * a[7] - a[4] * a[6]) +
5047 a[0] * (b[4] * a[8] - b[5] * a[7]) +
5048 a[1] * (b[5] * a[6] - b[3] * a[8]) +
5049 a[2] * (b[3] * a[7] - b[4] * a[6]) +
5051 a[0] * (a[4] * b[8] - a[5] * b[7]) +
5052 a[1] * (a[5] * b[6] - a[3] * b[8]) +
5053 a[2] * (a[3] * b[7] - a[4] * b[6]));
5055 c(2) = (a[0] * (b[4] * b[8] - b[5] * b[7]) +
5056 a[1] * (b[5] * b[6] - b[3] * b[8]) +
5057 a[2] * (b[3] * b[7] - b[4] * b[6]) +
5059 b[0] * (a[4] * b[8] - a[5] * b[7]) +
5060 b[1] * (a[5] * b[6] - a[3] * b[8]) +
5061 b[2] * (a[3] * b[7] - a[4] * b[6]) +
5063 b[0] * (b[4] * a[8] - b[5] * a[7]) +
5064 b[1] * (b[5] * a[6] - b[3] * a[8]) +
5065 b[2] * (b[3] * a[7] - b[4] * a[6]));
5067 c(3) = (b[0] * (b[4] * b[8] - b[5] * b[7]) +
5068 b[1] * (b[5] * b[6] - b[3] * b[8]) +
5069 b[2] * (b[3] * b[7] - b[4] * b[6]));
5115 double a = z(2), b = z(1), c = z(0);
5116 double D = b*b-4*a*c;
5123 x(0) = x(1) = -0.5 * b / a;
5128 x(0) = -(x(1) = fabs(0.5 * sqrt(D) / a));
5136 t = -0.5 * (b + sqrt(D));
5140 t = -0.5 * (b - sqrt(D));
5146 Swap<double>(x(0), x(1));
5154 double a = z(2)/z(3), b = z(1)/z(3), c = z(0)/z(3);
5157 double Q = (a * a - 3 * b) / 9;
5158 double R = (2 * a * a * a - 9 * a * b + 27 * c) / 54;
5159 double Q3 = Q * Q * Q;
5166 x(0) = x(1) = x(2) = - a / 3;
5170 double sqrtQ = sqrt(Q);
5174 x(0) = -2 * sqrtQ - a / 3;
5175 x(1) = x(2) = sqrtQ - a / 3;
5179 x(0) = x(1) = - sqrtQ - a / 3;
5180 x(2) = 2 * sqrtQ - a / 3;
5187 double theta = acos(R / sqrt(Q3));
5188 double A = -2 * sqrt(Q);
5190 x0 = A * cos(theta / 3) - a / 3;
5191 x1 = A * cos((theta + 2.0 * M_PI) / 3) - a / 3;
5192 x2 = A * cos((theta - 2.0 * M_PI) / 3) - a / 3;
5197 Swap<double>(x0, x1);
5201 Swap<double>(x1, x2);
5204 Swap<double>(x0, x1);
5217 A = -pow(sqrt(R2 - Q3) + R, 1.0/3.0);
5221 A = pow(sqrt(R2 - Q3) - R, 1.0/3.0);
5223 x(0) = A + Q / A - a / 3;
5232 const double factor,
const int Dim)
5234 const double c0 = c(0);
5235 c(0) = c0 * (1.0 - pow(factor, -Dim));
5237 for (
int j = 0; j < nr; j++)
5249 c(0) = c0 * (1.0 - pow(factor, Dim));
5251 for (
int j = 0; j < nr; j++)
5265 void Mesh::CheckDisplacements(
const Vector &displacements,
double &tmax)
5267 int nvs = vertices.Size();
5268 DenseMatrix P, V, DS, PDS(spaceDim), VDS(spaceDim);
5269 Vector c(spaceDim+1), x(spaceDim);
5270 const double factor = 2.0;
5277 for (
int i = 0; i < NumOfElements; i++)
5284 for (
int j = 0; j < spaceDim; j++)
5285 for (
int k = 0; k < nv; k++)
5287 P(j, k) = vertices[v[k]](j);
5288 V(j, k) = displacements(v[k]+j*nvs);
5292 GetTransformationFEforElementType(el->
GetType());
5296 case Element::TRIANGLE:
5297 case Element::TETRAHEDRON:
5315 case Element::QUADRILATERAL:
5318 for (
int j = 0; j < nv; j++)
5342 void Mesh::MoveVertices(
const Vector &displacements)
5344 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5345 for (
int j = 0; j < spaceDim; j++)
5347 vertices[i](j) += displacements(j*nv+i);
5351 void Mesh::GetVertices(
Vector &vert_coord)
const
5353 int nv = vertices.Size();
5354 vert_coord.
SetSize(nv*spaceDim);
5355 for (
int i = 0; i < nv; i++)
5356 for (
int j = 0; j < spaceDim; j++)
5358 vert_coord(j*nv+i) = vertices[i](j);
5362 void Mesh::SetVertices(
const Vector &vert_coord)
5364 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5365 for (
int j = 0; j < spaceDim; j++)
5367 vertices[i](j) = vert_coord(j*nv+i);
5371 void Mesh::GetNode(
int i,
double *coord)
5376 for (
int j = 0; j < spaceDim; j++)
5378 coord[j] = (*Nodes)(fes->
DofToVDof(i, j));
5383 for (
int j = 0; j < spaceDim; j++)
5385 coord[j] = vertices[i](j);
5390 void Mesh::SetNode(
int i,
const double *coord)
5395 for (
int j = 0; j < spaceDim; j++)
5397 (*Nodes)(fes->
DofToVDof(i, j)) = coord[j];
5402 for (
int j = 0; j < spaceDim; j++)
5404 vertices[i](j) = coord[j];
5410 void Mesh::MoveNodes(
const Vector &displacements)
5414 (*Nodes) += displacements;
5418 MoveVertices(displacements);
5422 void Mesh::GetNodes(
Vector &node_coord)
const
5426 node_coord = (*Nodes);
5430 GetVertices(node_coord);
5434 void Mesh::SetNodes(
const Vector &node_coord)
5438 (*Nodes) = node_coord;
5442 SetVertices(node_coord);
5448 if (own_nodes) {
delete Nodes; }
5451 own_nodes = (int)make_owner;
5462 mfem::Swap<GridFunction*>(Nodes, nodes);
5463 mfem::Swap<int>(own_nodes, own_nodes_);
5470 void Mesh::AverageVertices(
int * indexes,
int n,
int result)
5474 for (k = 0; k < spaceDim; k++)
5476 vertices[result](k) = vertices[indexes[0]](k);
5479 for (j = 1; j < n; j++)
5480 for (k = 0; k < spaceDim; k++)
5482 vertices[result](k) += vertices[indexes[j]](k);
5485 for (k = 0; k < spaceDim; k++)
5487 vertices[result](k) *= (1.0 / n);
5491 void Mesh::UpdateNodes()
5495 Nodes->FESpace()->Update();
5500 void Mesh::QuadUniformRefinement()
5502 int i, j, *v, vv[2], attr;
5505 if (el_to_edge == NULL)
5507 el_to_edge =
new Table;
5508 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5511 int oedge = NumOfVertices;
5512 int oelem = oedge + NumOfEdges;
5514 vertices.SetSize(oelem + NumOfElements);
5516 for (i = 0; i < NumOfElements; i++)
5518 v = elements[i]->GetVertices();
5520 AverageVertices(v, 4, oelem+i);
5522 e = el_to_edge->GetRow(i);
5524 vv[0] = v[0], vv[1] = v[1]; AverageVertices(vv, 2, oedge+e[0]);
5525 vv[0] = v[1], vv[1] = v[2]; AverageVertices(vv, 2, oedge+e[1]);
5526 vv[0] = v[2], vv[1] = v[3]; AverageVertices(vv, 2, oedge+e[2]);
5527 vv[0] = v[3], vv[1] = v[0]; AverageVertices(vv, 2, oedge+e[3]);
5530 elements.SetSize(4 * NumOfElements);
5531 for (i = 0; i < NumOfElements; i++)
5533 attr = elements[i]->GetAttribute();
5534 v = elements[i]->GetVertices();
5535 e = el_to_edge->GetRow(i);
5536 j = NumOfElements + 3 * i;
5538 elements[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5540 elements[j+1] =
new Quadrilateral(oelem+i, oedge+e[1], v[2],
5542 elements[j+2] =
new Quadrilateral(oedge+e[3], oelem+i, oedge+e[2],
5550 boundary.SetSize(2 * NumOfBdrElements);
5551 for (i = 0; i < NumOfBdrElements; i++)
5553 attr = boundary[i]->GetAttribute();
5554 v = boundary[i]->GetVertices();
5555 j = NumOfBdrElements + i;
5557 boundary[j] =
new Segment(oedge+be_to_edge[i], v[1], attr);
5559 v[1] = oedge+be_to_edge[i];
5562 static double quad_children[2*4*4] =
5564 0.0,0.0, 0.5,0.0, 0.5,0.5, 0.0,0.5,
5565 0.5,0.0, 1.0,0.0, 1.0,0.5, 0.5,0.5,
5566 0.5,0.5, 1.0,0.5, 1.0,1.0, 0.5,1.0,
5567 0.0,0.5, 0.5,0.5, 0.5,1.0, 0.0,1.0
5570 CoarseFineTr.point_matrices.UseExternalData(quad_children, 2, 4, 4);
5571 CoarseFineTr.embeddings.SetSize(elements.Size());
5573 for (i = 0; i < elements.Size(); i++)
5575 Embedding &emb = CoarseFineTr.embeddings[i];
5576 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 3;
5577 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 3 + 1;
5580 NumOfVertices = oelem + NumOfElements;
5581 NumOfElements = 4 * NumOfElements;
5582 NumOfBdrElements = 2 * NumOfBdrElements;
5585 if (el_to_edge != NULL)
5587 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5591 last_operation = Mesh::REFINE;
5597 CheckElementOrientation(
false);
5598 CheckBdrElementOrientation(
false);
5602 void Mesh::HexUniformRefinement()
5609 if (el_to_edge == NULL)
5611 el_to_edge =
new Table;
5612 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5614 if (el_to_face == NULL)
5616 GetElementToFaceTable();
5619 int oedge = NumOfVertices;
5620 int oface = oedge + NumOfEdges;
5621 int oelem = oface + NumOfFaces;
5623 vertices.SetSize(oelem + NumOfElements);
5624 for (i = 0; i < NumOfElements; i++)
5626 MFEM_ASSERT(elements[i]->GetType() == Element::HEXAHEDRON,
5627 "Element is not a hex!");
5628 v = elements[i]->GetVertices();
5630 AverageVertices(v, 8, oelem+i);
5632 f = el_to_face->GetRow(i);
5634 for (
int j = 0; j < 6; j++)
5636 for (
int k = 0; k < 4; k++)
5638 vv[k] = v[hex_t::FaceVert[j][k]];
5640 AverageVertices(vv, 4, oface+f[j]);
5643 e = el_to_edge->GetRow(i);
5645 for (
int j = 0; j < 12; j++)
5647 for (
int k = 0; k < 2; k++)
5649 vv[k] = v[hex_t::Edges[j][k]];
5651 AverageVertices(vv, 2, oedge+e[j]);
5656 elements.SetSize(8 * NumOfElements);
5657 for (i = 0; i < NumOfElements; i++)
5659 attr = elements[i]->GetAttribute();
5660 v = elements[i]->GetVertices();
5661 e = el_to_edge->GetRow(i);
5662 f = el_to_face->GetRow(i);
5663 j = NumOfElements + 7 * i;
5665 elements[j+0] =
new Hexahedron(oedge+e[0], v[1], oedge+e[1], oface+f[0],
5666 oface+f[1], oedge+e[9], oface+f[2],
5668 elements[j+1] =
new Hexahedron(oface+f[0], oedge+e[1], v[2], oedge+e[2],
5669 oelem+i, oface+f[2], oedge+e[10],
5671 elements[j+2] =
new Hexahedron(oedge+e[3], oface+f[0], oedge+e[2], v[3],
5672 oface+f[4], oelem+i, oface+f[3],
5674 elements[j+3] =
new Hexahedron(oedge+e[8], oface+f[1], oelem+i,
5675 oface+f[4], v[4], oedge+e[4], oface+f[5],
5677 elements[j+4] =
new Hexahedron(oface+f[1], oedge+e[9], oface+f[2],
5678 oelem+i, oedge+e[4], v[5], oedge+e[5],
5680 elements[j+5] =
new Hexahedron(oelem+i, oface+f[2], oedge+e[10],
5681 oface+f[3], oface+f[5], oedge+e[5], v[6],
5683 elements[j+6] =
new Hexahedron(oface+f[4], oelem+i, oface+f[3],
5684 oedge+e[11], oedge+e[7], oface+f[5],
5685 oedge+e[6], v[7], attr);
5696 boundary.SetSize(4 * NumOfBdrElements);
5697 for (i = 0; i < NumOfBdrElements; i++)
5699 MFEM_ASSERT(boundary[i]->GetType() == Element::QUADRILATERAL,
5700 "boundary Element is not a quad!");
5701 attr = boundary[i]->GetAttribute();
5702 v = boundary[i]->GetVertices();
5703 e = bel_to_edge->GetRow(i);
5704 f = & be_to_face[i];
5705 j = NumOfBdrElements + 3 * i;
5707 boundary[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5709 boundary[j+1] =
new Quadrilateral(oface+f[0], oedge+e[1], v[2],
5711 boundary[j+2] =
new Quadrilateral(oedge+e[3], oface+f[0], oedge+e[2],
5719 static const double A = 0.0, B = 0.5, C = 1.0;
5720 static double hex_children[3*8*8] =
5722 A,A,A, B,A,A, B,B,A, A,B,A, A,A,B, B,A,B, B,B,B, A,B,B,
5723 B,A,A, C,A,A, C,B,A, B,B,A, B,A,B, C,A,B, C,B,B, B,B,B,
5724 B,B,A, C,B,A, C,C,A, B,C,A, B,B,B, C,B,B, C,C,B, B,C,B,
5725 A,B,A, B,B,A, B,C,A, A,C,A, A,B,B, B,B,B, B,C,B, A,C,B,
5726 A,A,B, B,A,B, B,B,B, A,B,B, A,A,C, B,A,C, B,B,C, A,B,C,
5727 B,A,B, C,A,B, C,B,B, B,B,B, B,A,C, C,A,C, C,B,C, B,B,C,
5728 B,B,B, C,B,B, C,C,B, B,C,B, B,B,C, C,B,C, C,C,C, B,C,C,
5729 A,B,B, B,B,B, B,C,B, A,C,B, A,B,C, B,B,C, B,C,C, A,C,C
5732 CoarseFineTr.point_matrices.UseExternalData(hex_children, 3, 8, 8);
5733 CoarseFineTr.embeddings.SetSize(elements.Size());
5735 for (i = 0; i < elements.Size(); i++)
5737 Embedding &emb = CoarseFineTr.embeddings[i];
5738 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 7;
5739 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 7 + 1;
5742 NumOfVertices = oelem + NumOfElements;
5743 NumOfElements = 8 * NumOfElements;
5744 NumOfBdrElements = 4 * NumOfBdrElements;
5746 if (el_to_face != NULL)
5748 GetElementToFaceTable();
5753 CheckBdrElementOrientation(
false);
5756 if (el_to_edge != NULL)
5758 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5761 last_operation = Mesh::REFINE;
5767 void Mesh::LocalRefinement(
const Array<int> &marked_el,
int type)
5769 int i, j, ind, nedges;
5774 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
5777 InitRefinementTransforms();
5781 int cne = NumOfElements, cnv = NumOfVertices;
5782 NumOfVertices += marked_el.
Size();
5783 NumOfElements += marked_el.
Size();
5784 vertices.SetSize(NumOfVertices);
5785 elements.SetSize(NumOfElements);
5786 CoarseFineTr.embeddings.SetSize(NumOfElements);
5788 for (j = 0; j < marked_el.
Size(); j++)
5793 int new_v = cnv + j, new_e = cne + j;
5794 AverageVertices(vert, 2, new_v);
5795 elements[new_e] =
new Segment(new_v, vert[1], attr);
5798 CoarseFineTr.embeddings[i] =
Embedding(i, 1);
5799 CoarseFineTr.embeddings[new_e] =
Embedding(i, 2);
5802 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
5803 CoarseFineTr.point_matrices.UseExternalData(seg_children, 1, 2, 3);
5811 DSTable v_to_v(NumOfVertices);
5812 GetVertexToVertexTable(v_to_v);
5816 int *edge1 =
new int[nedges];
5817 int *edge2 =
new int[nedges];
5818 int *middle =
new int[nedges];
5820 for (i = 0; i < nedges; i++)
5822 edge1[i] = edge2[i] = middle[i] = -1;
5825 for (i = 0; i < NumOfElements; i++)
5827 elements[i]->GetVertices(v);
5828 for (j = 1; j < v.
Size(); j++)
5830 ind = v_to_v(v[j-1], v[j]);
5831 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5833 ind = v_to_v(v[0], v[v.
Size()-1]);
5834 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5838 for (i = 0; i < marked_el.
Size(); i++)
5840 RedRefinement(marked_el[i], v_to_v, edge1, edge2, middle);
5844 int need_refinement;
5847 need_refinement = 0;
5848 for (i = 0; i < nedges; i++)
5850 if (middle[i] != -1 && edge1[i] != -1)
5852 need_refinement = 1;
5853 GreenRefinement(edge1[i], v_to_v, edge1, edge2, middle);
5857 while (need_refinement == 1);
5860 int v1[2], v2[2], bisect, temp;
5861 temp = NumOfBdrElements;
5862 for (i = 0; i < temp; i++)
5864 boundary[i]->GetVertices(v);
5865 bisect = v_to_v(v[0], v[1]);
5866 if (middle[bisect] != -1)
5868 if (boundary[i]->GetType() == Element::SEGMENT)
5870 v1[0] = v[0]; v1[1] = middle[bisect];
5871 v2[0] = middle[bisect]; v2[1] = v[1];
5873 boundary[i]->SetVertices(v1);
5874 boundary.
Append(
new Segment(v2, boundary[i]->GetAttribute()));
5877 mfem_error(
"Only bisection of segment is implemented"
5881 NumOfBdrElements = boundary.Size();
5889 if (el_to_edge != NULL)
5891 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5899 DSTable v_to_v(NumOfVertices);
5900 GetVertexToVertexTable(v_to_v);
5904 int *middle =
new int[nedges];
5906 for (i = 0; i < nedges; i++)
5916 for (i = 0; i < marked_el.
Size(); i++)
5918 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5922 for (i = 0; i < marked_el.
Size(); i++)
5924 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5926 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5927 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5931 for (i = 0; i < marked_el.
Size(); i++)
5933 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5935 ii = NumOfElements - 1;
5936 Bisection(ii, v_to_v, NULL, NULL, middle);
5937 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5938 Bisection(ii, v_to_v, NULL, NULL, middle);
5940 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5941 Bisection(NumOfElements-1, v_to_v, NULL, NULL, middle);
5942 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5948 int need_refinement;
5953 need_refinement = 0;
5956 for (i = 0; i < NumOfElements; i++)
5961 if (elements[i]->NeedRefinement(v_to_v, middle))
5963 need_refinement = 1;
5964 Bisection(i, v_to_v, NULL, NULL, middle);
5968 while (need_refinement == 1);
5975 need_refinement = 0;
5976 for (i = 0; i < NumOfBdrElements; i++)
5977 if (boundary[i]->NeedRefinement(v_to_v, middle))
5979 need_refinement = 1;
5980 Bisection(i, v_to_v, middle);
5983 while (need_refinement == 1);
5986 int refinement_edges[2], type, flag;
5987 for (i = 0; i < NumOfElements; i++)
5992 if (type == Tetrahedron::TYPE_PF)
5999 NumOfBdrElements = boundary.Size();
6005 if (el_to_edge != NULL)
6007 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6009 if (el_to_face != NULL)
6011 GetElementToFaceTable();
6017 last_operation = Mesh::REFINE;
6023 CheckElementOrientation(
false);
6030 MFEM_VERIFY(!NURBSext,
"Nonconforming refinement of NURBS meshes is "
6031 "not supported. Project the NURBS to Nodes first.");
6036 ncmesh =
new NCMesh(
this);
6039 if (!refinements.
Size())
6041 last_operation = Mesh::NONE;
6046 ncmesh->MarkCoarseLevel();
6047 ncmesh->Refine(refinements);
6051 ncmesh->LimitNCLevel(nc_limit);
6056 ncmesh->OnMeshUpdated(mesh2);
6060 Swap(*mesh2,
false);
6063 GenerateNCFaceInfo();
6065 last_operation = Mesh::REFINE;
6070 Nodes->FESpace()->Update();
6077 MFEM_VERIFY(ncmesh,
"only supported for non-conforming meshes.");
6078 MFEM_VERIFY(!NURBSext,
"Derefinement of NURBS meshes is not supported. "
6079 "Project the NURBS to Nodes first.");
6081 ncmesh->Derefine(derefinements);
6084 ncmesh->OnMeshUpdated(mesh2);
6086 Swap(*mesh2,
false);
6089 GenerateNCFaceInfo();
6091 last_operation = Mesh::DEREFINE;
6096 Nodes->FESpace()->Update();
6102 double threshold,
int nc_limit,
int op)
6104 const Table &dt = ncmesh->GetDerefinementTable();
6109 ncmesh->CheckDerefinementNCLevel(dt, level_ok, nc_limit);
6113 for (
int i = 0; i < dt.
Size(); i++)
6115 if (nc_limit > 0 && !level_ok[i]) {
continue; }
6117 const int* fine = dt.
GetRow(i);
6121 for (
int j = 0; j < size; j++)
6123 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
6125 double err_fine = elem_error[fine[j]];
6128 case 0: error = std::min(error, err_fine);
break;
6129 case 1: error += err_fine;
break;
6130 case 2: error = std::max(error, err_fine);
break;
6134 if (error < threshold) { derefs.
Append(i); }
6139 DerefineMesh(derefs);
6147 int nc_limit,
int op)
6151 if (Nonconforming())
6153 return NonconformingDerefinement(elem_error, threshold, nc_limit, op);
6157 MFEM_ABORT(
"Derefinement is currently supported for non-conforming "
6163 bool Mesh::DerefineByError(
const Vector &elem_error,
double threshold,
6164 int nc_limit,
int op)
6167 for (
int i = 0; i < tmp.Size(); i++)
6169 tmp[i] = elem_error(i);
6171 return DerefineByError(tmp, threshold, nc_limit, op);
6175 void Mesh::InitFromNCMesh(
const NCMesh &ncmesh)
6184 case Geometry::TRIANGLE:
6185 case Geometry::SQUARE:
6186 BaseBdrGeom = Geometry::SEGMENT;
6188 case Geometry::CUBE:
6189 BaseBdrGeom = Geometry::SQUARE;
6199 NumOfVertices = vertices.Size();
6200 NumOfElements = elements.Size();
6201 NumOfBdrElements = boundary.Size();
6205 NumOfEdges = NumOfFaces = 0;
6209 el_to_edge =
new Table;
6210 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
6214 GetElementToFaceTable();
6218 CheckBdrElementOrientation(
false);
6229 InitFromNCMesh(ncmesh);
6279 const int nv = Geometry::NumVerts[
geom];
6281 for (
int i = 0; i < elem_array.
Size(); i++)
6283 if (elem_array[i]->GetGeometryType() ==
geom)
6288 elem_vtx.
SetSize(nv*num_elems);
6292 for (
int i = 0; i < elem_array.
Size(); i++)
6298 elem_vtx.
Append(loc_vtx);
6303 void Mesh::UniformRefinement()
6307 NURBSUniformRefinement();
6309 else if (meshgen == 1 || ncmesh)
6312 for (
int i = 0; i < elem_to_refine.
Size(); i++)
6314 elem_to_refine[i] = i;
6321 LocalRefinement(elem_to_refine);
6325 GeneralRefinement(elem_to_refine, 1);
6330 QuadUniformRefinement();
6334 HexUniformRefinement();
6343 int nonconforming,
int nc_limit)
6345 if (Dim == 1 || (Dim == 3 && meshgen & 1))
6349 else if (nonconforming < 0)
6352 int geom = GetElementBaseGeometry();
6353 if (geom == Geometry::CUBE || geom == Geometry::SQUARE)
6363 if (nonconforming || ncmesh != NULL)
6366 NonconformingRefinement(refinements, nc_limit);
6371 for (
int i = 0; i < refinements.
Size(); i++)
6373 el_to_refine[i] = refinements[i].index;
6377 int type, rt = (refinements.
Size() ? refinements[0].ref_type : 7);
6378 if (rt == 1 || rt == 2 || rt == 4)
6382 else if (rt == 3 || rt == 5 || rt == 6)
6392 LocalRefinement(el_to_refine, type);
6396 void Mesh::GeneralRefinement(
const Array<int> &el_to_refine,
int nonconforming,
6400 for (
int i = 0; i < el_to_refine.
Size(); i++)
6402 refinements[i] =
Refinement(el_to_refine[i]);
6404 GeneralRefinement(refinements, nonconforming, nc_limit);
6407 void Mesh::EnsureNCMesh(
bool triangles_nonconforming)
6409 MFEM_VERIFY(!NURBSext,
"Cannot convert a NURBS mesh to an NC mesh. "
6410 "Project the NURBS to Nodes first.");
6414 if ((meshgen & 2) ||
6415 (triangles_nonconforming && BaseGeom == Geometry::TRIANGLE))
6417 ncmesh =
new NCMesh(
this);
6418 ncmesh->OnMeshUpdated(
this);
6419 GenerateNCFaceInfo();
6424 void Mesh::RandomRefinement(
double prob,
bool aniso,
int nonconforming,
6428 for (
int i = 0; i < GetNE(); i++)
6430 if ((
double) rand() / RAND_MAX < prob)
6435 type = (Dim == 3) ? (rand() % 7 + 1) : (rand() % 3 + 1);
6440 GeneralRefinement(refs, nonconforming, nc_limit);
6443 void Mesh::RefineAtVertex(
const Vertex& vert,
double eps,
int nonconforming)
6447 for (
int i = 0; i < GetNE(); i++)
6449 GetElementVertices(i, v);
6450 bool refine =
false;
6451 for (
int j = 0; j < v.
Size(); j++)
6454 for (
int l = 0; l < spaceDim; l++)
6456 double d = vert(l) - vertices[v[j]](l);
6459 if (dist <= eps*eps) { refine =
true;
break; }
6466 GeneralRefinement(refs, nonconforming);
6470 int nonconforming,
int nc_limit)
6472 MFEM_VERIFY(elem_error.
Size() == GetNE(),
"");
6474 for (
int i = 0; i < GetNE(); i++)
6476 if (elem_error[i] > threshold)
6481 if (ReduceInt(refs.Size()))
6483 GeneralRefinement(refs, nonconforming, nc_limit);
6489 bool Mesh::RefineByError(
const Vector &elem_error,
double threshold,
6490 int nonconforming,
int nc_limit)
6494 return RefineByError(tmp, threshold, nonconforming, nc_limit);
6498 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
6499 int *edge1,
int *edge2,
int *middle)
6502 int v[2][4], v_new, bisect, t;
6507 if (t == Element::TRIANGLE)
6514 bisect = v_to_v(vert[0], vert[1]);
6515 MFEM_ASSERT(bisect >= 0,
"");
6517 if (middle[bisect] == -1)
6519 v_new = NumOfVertices++;
6520 for (
int d = 0; d < spaceDim; d++)
6522 V(d) = 0.5 * (vertices[vert[0]](d) + vertices[vert[1]](d));
6528 if (edge1[bisect] == i)
6530 edge1[bisect] = edge2[bisect];
6533 middle[bisect] = v_new;
6537 v_new = middle[bisect];
6545 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6546 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6551 elements.Append(tri_new);
6560 int coarse = FindCoarseElement(i);
6561 CoarseFineTr.embeddings[i].parent = coarse;
6562 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6567 bisect = v_to_v(v[1][0], v[1][1]);
6568 MFEM_ASSERT(bisect >= 0,
"");
6570 if (edge1[bisect] == i)
6572 edge1[bisect] = NumOfElements;
6574 else if (edge2[bisect] == i)
6576 edge2[bisect] = NumOfElements;
6581 else if (t == Element::TETRAHEDRON)
6583 int j, type, new_type, old_redges[2], new_redges[2][2], flag;
6587 "TETRAHEDRON element is not marked for refinement.");
6592 bisect = v_to_v(vert[0], vert[1]);
6596 mfem::err <<
"Error in Bisection(...) of tetrahedron!" << endl
6597 <<
" redge[0] = " << old_redges[0]
6598 <<
" redge[1] = " << old_redges[1]
6599 <<
" type = " << type
6600 <<
" flag = " << flag << endl;
6604 if (middle[bisect] == -1)
6606 v_new = NumOfVertices++;
6607 for (j = 0; j < 3; j++)
6609 V(j) = 0.5 * (vertices[vert[0]](j) + vertices[vert[1]](j));
6613 middle[bisect] = v_new;
6617 v_new = middle[bisect];
6626 new_redges[0][0] = 2;
6627 new_redges[0][1] = 1;
6628 new_redges[1][0] = 2;
6629 new_redges[1][1] = 1;
6630 int tr1 = -1, tr2 = -1;
6631 switch (old_redges[0])
6634 v[0][0] = vert[0]; v[0][1] = vert[2]; v[0][2] = vert[3];
6635 if (type == Tetrahedron::TYPE_PF) { new_redges[0][1] = 4; }
6639 v[0][0] = vert[3]; v[0][1] = vert[0]; v[0][2] = vert[2];
6643 v[0][0] = vert[2]; v[0][1] = vert[3]; v[0][2] = vert[0];
6646 switch (old_redges[1])
6649 v[1][0] = vert[2]; v[1][1] = vert[1]; v[1][2] = vert[3];
6650 if (type == Tetrahedron::TYPE_PF) { new_redges[1][0] = 3; }
6654 v[1][0] = vert[1]; v[1][1] = vert[3]; v[1][2] = vert[2];
6658 v[1][0] = vert[3]; v[1][1] = vert[2]; v[1][2] = vert[1];
6665 #ifdef MFEM_USE_MEMALLOC
6673 elements.Append(tet2);
6679 int coarse = FindCoarseElement(i);
6680 CoarseFineTr.embeddings[i].parent = coarse;
6681 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6686 case Tetrahedron::TYPE_PU:
6687 new_type = Tetrahedron::TYPE_PF;
break;
6688 case Tetrahedron::TYPE_PF:
6689 new_type = Tetrahedron::TYPE_A;
break;
6691 new_type = Tetrahedron::TYPE_PU;
6701 MFEM_ABORT(
"Bisection for now works only for triangles & tetrahedra.");
6705 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
int *middle)
6708 int v[2][3], v_new, bisect, t;
6709 Element *bdr_el = boundary[i];
6712 if (t == Element::TRIANGLE)
6719 bisect = v_to_v(vert[0], vert[1]);
6720 MFEM_ASSERT(bisect >= 0,
"");
6721 v_new = middle[bisect];
6722 MFEM_ASSERT(v_new != -1,
"");
6726 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6727 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6737 MFEM_ABORT(
"Bisection of boundary elements works only for triangles!");
6741 void Mesh::UniformRefinement(
int i,
const DSTable &v_to_v,
6742 int *edge1,
int *edge2,
int *middle)
6745 int j, v1[3], v2[3], v3[3], v4[3], v_new[3], bisect[3];
6748 if (elements[i]->GetType() == Element::TRIANGLE)
6754 bisect[0] = v_to_v(v[0],v[1]);
6755 bisect[1] = v_to_v(v[1],v[2]);
6756 bisect[2] = v_to_v(v[0],v[2]);
6757 MFEM_ASSERT(bisect[0] >= 0 && bisect[1] >= 0 && bisect[2] >= 0,
"");
6759 for (j = 0; j < 3; j++)
6761 if (middle[bisect[j]] == -1)
6763 v_new[j] = NumOfVertices++;
6764 for (
int d = 0; d < spaceDim; d++)
6766 V(d) = (vertices[v[j]](d) + vertices[v[(j+1)%3]](d))/2.;
6772 if (edge1[bisect[j]] == i)
6774 edge1[bisect[j]] = edge2[bisect[j]];
6777 middle[bisect[j]] = v_new[j];
6781 v_new[j] = middle[bisect[j]];
6784 edge1[bisect[j]] = -1;
6790 v1[0] = v[0]; v1[1] = v_new[0]; v1[2] = v_new[2];
6791 v2[0] = v_new[0]; v2[1] = v[1]; v2[2] = v_new[1];
6792 v3[0] = v_new[2]; v3[1] = v_new[1]; v3[2] = v[2];
6793 v4[0] = v_new[1]; v4[1] = v_new[2]; v4[2] = v_new[0];
6799 elements.Append(tri1);
6800 elements.Append(tri2);
6801 elements.Append(tri3);
6808 tri2->ResetTransform(code);
6809 tri3->ResetTransform(code);
6813 tri2->PushTransform(1);
6814 tri3->PushTransform(2);
6817 int coarse = FindCoarseElement(i);
6818 CoarseFineTr.embeddings[i] =
Embedding(coarse);
6819 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6820 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6821 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6827 MFEM_ABORT(
"Uniform refinement for now works only for triangles.");
6831 void Mesh::InitRefinementTransforms()
6834 CoarseFineTr.point_matrices.SetSize(0, 0, 0);
6835 CoarseFineTr.embeddings.SetSize(NumOfElements);
6836 for (
int i = 0; i < NumOfElements; i++)
6838 elements[i]->ResetTransform(0);
6839 CoarseFineTr.embeddings[i] =
Embedding(i);
6843 int Mesh::FindCoarseElement(
int i)
6846 while ((coarse = CoarseFineTr.embeddings[i].parent) != i)
6855 MFEM_VERIFY(GetLastOperation() == Mesh::REFINE,
"");
6859 return ncmesh->GetRefinementTransforms();
6862 if (!CoarseFineTr.point_matrices.SizeK())
6864 if (BaseGeom == Geometry::TRIANGLE ||
6865 BaseGeom == Geometry::TETRAHEDRON)
6867 std::map<unsigned, int> mat_no;
6871 for (
int i = 0; i < elements.Size(); i++)
6874 unsigned code = elements[i]->GetTransform();
6877 int &matrix = mat_no[code];
6878 if (!matrix) { matrix = mat_no.size(); }
6881 CoarseFineTr.embeddings[i].matrix = index;
6885 pmats.
SetSize(Dim, Dim+1, mat_no.size());
6888 std::map<unsigned, int>::iterator it;
6889 for (it = mat_no.begin(); it != mat_no.end(); ++it)
6891 if (BaseGeom == Geometry::TRIANGLE)
6893 Triangle::GetPointMatrix(it->first, pmats(it->second-1));
6897 Tetrahedron::GetPointMatrix(it->first, pmats(it->second-1));
6903 MFEM_ABORT(
"Don't know how to construct CoarseFineTr.");
6908 return CoarseFineTr;
6911 void Mesh::PrintXG(std::ostream &
out)
const
6913 MFEM_ASSERT(Dim==spaceDim,
"2D Manifold meshes not supported");
6922 out <<
"areamesh2\n\n";
6926 out <<
"curved_areamesh2\n\n";
6930 out << NumOfBdrElements <<
'\n';
6931 for (i = 0; i < NumOfBdrElements; i++)
6933 boundary[i]->GetVertices(v);
6935 out << boundary[i]->GetAttribute();
6936 for (j = 0; j < v.
Size(); j++)
6938 out <<
' ' << v[j] + 1;
6944 out << NumOfElements <<
'\n';
6945 for (i = 0; i < NumOfElements; i++)
6947 elements[i]->GetVertices(v);
6949 out << elements[i]->GetAttribute() <<
' ' << v.
Size();
6950 for (j = 0; j < v.
Size(); j++)
6952 out <<
' ' << v[j] + 1;
6960 out << NumOfVertices <<
'\n';
6961 for (i = 0; i < NumOfVertices; i++)
6963 out << vertices[i](0);
6964 for (j = 1; j < Dim; j++)
6966 out <<
' ' << vertices[i](j);
6973 out << NumOfVertices <<
'\n';
6981 mfem_error(
"Mesh::PrintXG(...) : Curved mesh in 3D");
6989 out <<
"NETGEN_Neutral_Format\n";
6991 out << NumOfVertices <<
'\n';
6992 for (i = 0; i < NumOfVertices; i++)
6994 for (j = 0; j < Dim; j++)
6996 out <<
' ' << vertices[i](j);
7002 out << NumOfElements <<
'\n';
7003 for (i = 0; i < NumOfElements; i++)
7005 nv = elements[i]->GetNVertices();
7006 ind = elements[i]->GetVertices();
7007 out << elements[i]->GetAttribute();
7008 for (j = 0; j < nv; j++)
7010 out <<
' ' << ind[j]+1;
7016 out << NumOfBdrElements <<
'\n';
7017 for (i = 0; i < NumOfBdrElements; i++)
7019 nv = boundary[i]->GetNVertices();
7020 ind = boundary[i]->GetVertices();
7021 out << boundary[i]->GetAttribute();
7022 for (j = 0; j < nv; j++)
7024 out <<
' ' << ind[j]+1;
7029 else if (meshgen == 2)
7035 <<
"1 " << NumOfVertices <<
" " << NumOfElements
7036 <<
" 0 0 0 0 0 0 0\n"
7037 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
7038 <<
"0 0 " << NumOfBdrElements <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
7039 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
7040 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
7042 for (i = 0; i < NumOfVertices; i++)
7043 out << i+1 <<
" 0.0 " << vertices[i](0) <<
' ' << vertices[i](1)
7044 <<
' ' << vertices[i](2) <<
" 0.0\n";
7046 for (i = 0; i < NumOfElements; i++)
7048 nv = elements[i]->GetNVertices();
7049 ind = elements[i]->GetVertices();
7050 out << i+1 <<
' ' << elements[i]->GetAttribute();
7051 for (j = 0; j < nv; j++)
7053 out <<
' ' << ind[j]+1;
7058 for (i = 0; i < NumOfBdrElements; i++)
7060 nv = boundary[i]->GetNVertices();
7061 ind = boundary[i]->GetVertices();
7062 out << boundary[i]->GetAttribute();
7063 for (j = 0; j < nv; j++)
7065 out <<
' ' << ind[j]+1;
7067 out <<
" 1.0 1.0 1.0 1.0\n";
7075 void Mesh::Printer(std::ostream &
out, std::string section_delimiter)
const
7082 NURBSext->Print(out);
7093 out << (ncmesh ?
"MFEM mesh v1.1\n" :
7094 section_delimiter.empty() ?
"MFEM mesh v1.0\n" :
7095 "MFEM mesh v1.2\n");
7099 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7104 "# TETRAHEDRON = 4\n"
7108 out <<
"\ndimension\n" << Dim
7109 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7110 for (i = 0; i < NumOfElements; i++)
7112 PrintElement(elements[i], out);
7115 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
7116 for (i = 0; i < NumOfBdrElements; i++)
7118 PrintElement(boundary[i], out);
7123 out <<
"\nvertex_parents\n";
7124 ncmesh->PrintVertexParents(out);
7126 out <<
"\ncoarse_elements\n";
7127 ncmesh->PrintCoarseElements(out);
7130 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7133 out << spaceDim <<
'\n';
7134 for (i = 0; i < NumOfVertices; i++)
7136 out << vertices[i](0);
7137 for (j = 1; j < spaceDim; j++)
7139 out <<
' ' << vertices[i](j);
7151 if (!ncmesh && !section_delimiter.empty())
7153 out << section_delimiter << endl;
7162 out <<
"MFEM NURBS mesh v1.0\n";
7166 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7172 out <<
"\ndimension\n" << Dim
7173 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7174 for (i = 0; i < NumOfElements; i++)
7176 PrintElement(elements[i], out);
7179 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
7180 for (i = 0; i < NumOfBdrElements; i++)
7182 PrintElement(boundary[i], out);
7185 out <<
"\nedges\n" << NumOfEdges <<
'\n';
7186 for (i = 0; i < NumOfEdges; i++)
7188 edge_vertex->GetRow(i, vert);
7194 out << ki <<
' ' << vert[0] <<
' ' << vert[1] <<
'\n';
7196 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7199 void Mesh::PrintVTK(std::ostream &
out)
7202 "# vtk DataFile Version 3.0\n"
7203 "Generated by MFEM\n"
7205 "DATASET UNSTRUCTURED_GRID\n";
7209 out <<
"POINTS " << NumOfVertices <<
" double\n";
7210 for (
int i = 0; i < NumOfVertices; i++)
7212 out << vertices[i](0);
7214 for (j = 1; j < spaceDim; j++)
7216 out <<
' ' << vertices[i](j);
7228 out <<
"POINTS " << Nodes->FESpace()->GetNDofs() <<
" double\n";
7229 for (
int i = 0; i < Nodes->FESpace()->GetNDofs(); i++)
7233 Nodes->FESpace()->DofsToVDofs(vdofs);
7234 out << (*Nodes)(vdofs[0]);
7236 for (j = 1; j < spaceDim; j++)
7238 out <<
' ' << (*Nodes)(vdofs[j]);
7252 for (
int i = 0; i < NumOfElements; i++)
7254 size += elements[i]->GetNVertices() + 1;
7256 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
7257 for (
int i = 0; i < NumOfElements; i++)
7259 const int *v = elements[i]->GetVertices();
7260 const int nv = elements[i]->GetNVertices();
7262 for (
int j = 0; j < nv; j++)
7274 for (
int i = 0; i < NumOfElements; i++)
7276 Nodes->FESpace()->GetElementDofs(i, dofs);
7277 MFEM_ASSERT(Dim != 0 || dofs.
Size() == 1,
7278 "Point meshes should have a single dof per element");
7279 size += dofs.
Size() + 1;
7281 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
7282 const char *fec_name = Nodes->FESpace()->FEColl()->Name();
7284 if (!strcmp(fec_name,
"Linear") ||
7285 !strcmp(fec_name,
"H1_0D_P1") ||
7286 !strcmp(fec_name,
"H1_1D_P1") ||
7287 !strcmp(fec_name,
"H1_2D_P1") ||
7288 !strcmp(fec_name,
"H1_3D_P1"))
7292 else if (!strcmp(fec_name,
"Quadratic") ||
7293 !strcmp(fec_name,
"H1_1D_P2") ||
7294 !strcmp(fec_name,
"H1_2D_P2") ||
7295 !strcmp(fec_name,
"H1_3D_P2"))
7301 mfem::err <<
"Mesh::PrintVTK : can not save '"
7302 << fec_name <<
"' elements!" << endl;
7305 for (
int i = 0; i < NumOfElements; i++)
7307 Nodes->FESpace()->GetElementDofs(i, dofs);
7311 for (
int j = 0; j < dofs.
Size(); j++)
7313 out <<
' ' << dofs[j];
7316 else if (order == 2)
7318 const int *vtk_mfem;
7319 switch (elements[i]->GetGeometryType())
7321 case Geometry::SEGMENT:
7322 case Geometry::TRIANGLE:
7323 case Geometry::SQUARE:
7324 vtk_mfem = vtk_quadratic_hex;
break;
7325 case Geometry::TETRAHEDRON:
7326 vtk_mfem = vtk_quadratic_tet;
break;
7327 case Geometry::CUBE:
7329 vtk_mfem = vtk_quadratic_hex;
break;
7331 for (
int j = 0; j < dofs.
Size(); j++)
7333 out <<
' ' << dofs[vtk_mfem[j]];
7340 out <<
"CELL_TYPES " << NumOfElements <<
'\n';
7341 for (
int i = 0; i < NumOfElements; i++)
7343 int vtk_cell_type = 5;
7346 switch (elements[i]->GetGeometryType())
7348 case Geometry::POINT: vtk_cell_type = 1;
break;
7349 case Geometry::SEGMENT: vtk_cell_type = 3;
break;
7350 case Geometry::TRIANGLE: vtk_cell_type = 5;
break;
7351 case Geometry::SQUARE: vtk_cell_type = 9;
break;
7352 case Geometry::TETRAHEDRON: vtk_cell_type = 10;
break;
7353 case Geometry::CUBE: vtk_cell_type = 12;
break;
7356 else if (order == 2)
7358 switch (elements[i]->GetGeometryType())
7360 case Geometry::SEGMENT: vtk_cell_type = 21;
break;
7361 case Geometry::TRIANGLE: vtk_cell_type = 22;
break;
7362 case Geometry::SQUARE: vtk_cell_type = 28;
break;
7363 case Geometry::TETRAHEDRON: vtk_cell_type = 24;
break;
7364 case Geometry::CUBE: vtk_cell_type = 29;
break;
7368 out << vtk_cell_type <<
'\n';
7372 out <<
"CELL_DATA " << NumOfElements <<
'\n'
7373 <<
"SCALARS material int\n"
7374 <<
"LOOKUP_TABLE default\n";
7375 for (
int i = 0; i < NumOfElements; i++)
7377 out << elements[i]->GetAttribute() <<
'\n';
7382 void Mesh::PrintVTK(std::ostream &
out,
int ref,
int field_data)
7389 "# vtk DataFile Version 3.0\n"
7390 "Generated by MFEM\n"
7392 "DATASET UNSTRUCTURED_GRID\n";
7397 out <<
"FIELD FieldData 1\n"
7398 <<
"MaterialIds " << 1 <<
" " << attributes.
Size() <<
" int\n";
7399 for (
int i = 0; i < attributes.Size(); i++)
7401 out <<
' ' << attributes[i];
7408 for (
int i = 0; i < GetNE(); i++)
7410 int geom = GetElementBaseGeometry(i);
7417 out <<
"POINTS " << np <<
" double\n";
7419 for (
int i = 0; i < GetNE(); i++)
7422 GetElementBaseGeometry(i), ref, 1);
7424 GetElementTransformation(i)->Transform(RefG->
RefPts, pmat);
7426 for (
int j = 0; j < pmat.
Width(); j++)
7428 out << pmat(0, j) <<
' ';
7431 out << pmat(1, j) <<
' ';
7443 out << 0.0 <<
' ' << 0.0;
7450 out <<
"CELLS " << nc <<
' ' << size <<
'\n';
7452 for (
int i = 0; i < GetNE(); i++)
7454 int geom = GetElementBaseGeometry(i);
7459 for (
int j = 0; j < RG.
Size(); )
7462 for (
int k = 0; k < nv; k++, j++)
7464 out <<
' ' << np + RG[j];
7470 out <<
"CELL_TYPES " << nc <<
'\n';
7471 for (
int i = 0; i < GetNE(); i++)
7473 int geom = GetElementBaseGeometry(i);
7477 int vtk_cell_type = 5;
7481 case Geometry::POINT: vtk_cell_type = 1;
break;
7482 case Geometry::SEGMENT: vtk_cell_type = 3;
break;
7483 case Geometry::TRIANGLE: vtk_cell_type = 5;
break;
7484 case Geometry::SQUARE: vtk_cell_type = 9;
break;
7485 case Geometry::TETRAHEDRON: vtk_cell_type = 10;
break;
7486 case Geometry::CUBE: vtk_cell_type = 12;
break;
7489 for (
int j = 0; j < RG.
Size(); j += nv)
7491 out << vtk_cell_type <<
'\n';
7495 out <<
"CELL_DATA " << nc <<
'\n'
7496 <<
"SCALARS material int\n"
7497 <<
"LOOKUP_TABLE default\n";
7498 for (
int i = 0; i < GetNE(); i++)
7500 int geom = GetElementBaseGeometry(i);
7503 int attr = GetAttribute(i);
7506 out << attr <<
'\n';
7513 srand((
unsigned)time(0));
7514 double a = double(rand()) / (double(RAND_MAX) + 1.);
7515 int el0 = (int)floor(a * GetNE());
7516 GetElementColoring(coloring, el0);
7517 out <<
"SCALARS element_coloring int\n"
7518 <<
"LOOKUP_TABLE default\n";
7519 for (
int i = 0; i < GetNE(); i++)
7521 int geom = GetElementBaseGeometry(i);
7526 out << coloring[i] + 1 <<
'\n';
7532 out <<
"POINT_DATA " << np <<
'\n' << flush;
7537 int delete_el_to_el = (el_to_el) ? (0) : (1);
7538 const Table &el_el = ElementToElementTable();
7539 int num_el = GetNE(), stack_p, stack_top_p, max_num_col;
7542 const int *i_el_el = el_el.
GetI();
7543 const int *j_el_el = el_el.
GetJ();
7548 stack_p = stack_top_p = 0;
7549 for (
int el = el0; stack_top_p < num_el; el=(el+1)%num_el)
7551 if (colors[el] != -2)
7557 el_stack[stack_top_p++] = el;
7559 for ( ; stack_p < stack_top_p; stack_p++)
7561 int i = el_stack[stack_p];
7562 int num_nb = i_el_el[i+1] - i_el_el[i];
7563 if (max_num_col < num_nb + 1)
7565 max_num_col = num_nb + 1;
7567 for (
int j = i_el_el[i]; j < i_el_el[i+1]; j++)
7570 if (colors[k] == -2)
7573 el_stack[stack_top_p++] = k;
7581 for (stack_p = 0; stack_p < stack_top_p; stack_p++)
7583 int i = el_stack[stack_p], col;
7585 for (
int j = i_el_el[i]; j < i_el_el[i+1]; j++)
7587 col = colors[j_el_el[j]];
7590 col_marker[col] = 1;
7594 for (col = 0; col < max_num_col; col++)
7595 if (col_marker[col] == 0)
7603 if (delete_el_to_el)
7610 void Mesh::PrintWithPartitioning(
int *partitioning, std::ostream &
out,
7611 int elem_attr)
const
7613 if (Dim != 3 && Dim != 2) {
return; }
7615 int i, j, k, l, nv, nbe, *v;
7617 out <<
"MFEM mesh v1.0\n";
7621 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7626 "# TETRAHEDRON = 4\n"
7630 out <<
"\ndimension\n" << Dim
7631 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7632 for (i = 0; i < NumOfElements; i++)
7634 out << int((elem_attr) ? partitioning[i]+1 : elements[i]->GetAttribute())
7635 <<
' ' << elements[i]->GetGeometryType();
7636 nv = elements[i]->GetNVertices();
7637 v = elements[i]->GetVertices();
7638 for (j = 0; j < nv; j++)
7645 for (i = 0; i < faces_info.Size(); i++)
7647 if ((l = faces_info[i].Elem2No) >= 0)
7649 k = partitioning[faces_info[i].Elem1No];
7650 l = partitioning[l];
7654 if (!Nonconforming() || !IsSlaveFace(faces_info[i]))
7665 out <<
"\nboundary\n" << nbe <<
'\n';
7666 for (i = 0; i < faces_info.Size(); i++)
7668 if ((l = faces_info[i].Elem2No) >= 0)
7670 k = partitioning[faces_info[i].Elem1No];
7671 l = partitioning[l];
7674 nv = faces[i]->GetNVertices();
7675 v = faces[i]->GetVertices();
7676 out << k+1 <<
' ' << faces[i]->GetGeometryType();
7677 for (j = 0; j < nv; j++)
7682 if (!Nonconforming() || !IsSlaveFace(faces_info[i]))
7684 out << l+1 <<
' ' << faces[i]->GetGeometryType();
7685 for (j = nv-1; j >= 0; j--)
7695 k = partitioning[faces_info[i].Elem1No];
7696 nv = faces[i]->GetNVertices();
7697 v = faces[i]->GetVertices();
7698 out << k+1 <<
' ' << faces[i]->GetGeometryType();
7699 for (j = 0; j < nv; j++)
7706 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7709 out << spaceDim <<
'\n';
7710 for (i = 0; i < NumOfVertices; i++)
7712 out << vertices[i](0);
7713 for (j = 1; j < spaceDim; j++)
7715 out <<
' ' << vertices[i](j);
7728 void Mesh::PrintElementsWithPartitioning(
int *partitioning,
7732 MFEM_ASSERT(Dim == spaceDim,
"2D Manifolds not supported\n");
7733 if (Dim != 3 && Dim != 2) {
return; }
7740 int *vcount =
new int[NumOfVertices];
7741 for (i = 0; i < NumOfVertices; i++)
7745 for (i = 0; i < NumOfElements; i++)
7747 nv = elements[i]->GetNVertices();
7748 ind = elements[i]->GetVertices();
7749 for (j = 0; j < nv; j++)
7755 int *voff =
new int[NumOfVertices+1];
7757 for (i = 1; i <= NumOfVertices; i++)
7759 voff[i] = vcount[i-1] + voff[i-1];
7762 int **vown =
new int*[NumOfVertices];
7763 for (i = 0; i < NumOfVertices; i++)
7765 vown[i] =
new int[vcount[i]];
7775 Transpose(ElementToEdgeTable(), edge_el);
7778 for (i = 0; i < NumOfElements; i++)
7780 nv = elements[i]->GetNVertices();
7781 ind = elements[i]->GetVertices();
7782 for (j = 0; j < nv; j++)
7785 vown[ind[j]][vcount[ind[j]]] = i;
7789 for (i = 0; i < NumOfVertices; i++)
7791 vcount[i] = voff[i+1] - voff[i];
7795 for (i = 0; i < edge_el.
Size(); i++)
7797 const int *el = edge_el.
GetRow(i);
7800 k = partitioning[el[0]];
7801 l = partitioning[el[1]];
7802 if (interior_faces || k != l)
7814 out <<
"areamesh2\n\n" << nbe <<
'\n';
7816 for (i = 0; i < edge_el.
Size(); i++)
7818 const int *el = edge_el.
GetRow(i);
7821 k = partitioning[el[0]];
7822 l = partitioning[el[1]];
7823 if (interior_faces || k != l)
7826 GetEdgeVertices(i,ev);
7828 for (j = 0; j < 2; j++)
7829 for (s = 0; s < vcount[ev[j]]; s++)
7830 if (vown[ev[j]][s] == el[0])
7832 out <<
' ' << voff[ev[j]]+s+1;
7836 for (j = 1; j >= 0; j--)
7837 for (s = 0; s < vcount[ev[j]]; s++)
7838 if (vown[ev[j]][s] == el[1])
7840 out <<
' ' << voff[ev[j]]+s+1;
7847 k = partitioning[el[0]];
7849 GetEdgeVertices(i,ev);
7851 for (j = 0; j < 2; j++)
7852 for (s = 0; s < vcount[ev[j]]; s++)
7853 if (vown[ev[j]][s] == el[0])
7855 out <<
' ' << voff[ev[j]]+s+1;
7862 out << NumOfElements <<
'\n';
7863 for (i = 0; i < NumOfElements; i++)
7865 nv = elements[i]->GetNVertices();
7866 ind = elements[i]->GetVertices();
7867 out << partitioning[i]+1 <<
' ';
7869 for (j = 0; j < nv; j++)
7871 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7872 vown[ind[j]][vcount[ind[j]]] = i;
7877 for (i = 0; i < NumOfVertices; i++)
7879 vcount[i] = voff[i+1] - voff[i];
7883 out << voff[NumOfVertices] <<
'\n';
7884 for (i = 0; i < NumOfVertices; i++)
7885 for (k = 0; k < vcount[i]; k++)
7887 for (j = 0; j < Dim; j++)
7889 out << vertices[i](j) <<
' ';
7895 else if (meshgen == 1)
7897 out <<
"NETGEN_Neutral_Format\n";
7899 out << voff[NumOfVertices] <<
'\n';
7900 for (i = 0; i < NumOfVertices; i++)
7901 for (k = 0; k < vcount[i]; k++)
7903 for (j = 0; j < Dim; j++)
7905 out <<
' ' << vertices[i](j);
7911 out << NumOfElements <<
'\n';
7912 for (i = 0; i < NumOfElements; i++)
7914 nv = elements[i]->GetNVertices();
7915 ind = elements[i]->GetVertices();
7916 out << partitioning[i]+1;
7917 for (j = 0; j < nv; j++)
7919 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7920 vown[ind[j]][vcount[ind[j]]] = i;
7925 for (i = 0; i < NumOfVertices; i++)
7927 vcount[i] = voff[i+1] - voff[i];
7933 for (i = 0; i < NumOfFaces; i++)
7934 if ((l = faces_info[i].Elem2No) >= 0)
7936 k = partitioning[faces_info[i].Elem1No];
7937 l = partitioning[l];
7938 if (interior_faces || k != l)
7949 for (i = 0; i < NumOfFaces; i++)
7950 if ((l = faces_info[i].Elem2No) >= 0)
7952 k = partitioning[faces_info[i].Elem1No];
7953 l = partitioning[l];
7954 if (interior_faces || k != l)
7956 nv = faces[i]->GetNVertices();
7957 ind = faces[i]->GetVertices();
7959 for (j = 0; j < nv; j++)
7960 for (s = 0; s < vcount[ind[j]]; s++)
7961 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7963 out <<
' ' << voff[ind[j]]+s+1;
7967 for (j = nv-1; j >= 0; j--)
7968 for (s = 0; s < vcount[ind[j]]; s++)
7969 if (vown[ind[j]][s] == faces_info[i].Elem2No)
7971 out <<
' ' << voff[ind[j]]+s+1;
7978 k = partitioning[faces_info[i].Elem1No];
7979 nv = faces[i]->GetNVertices();
7980 ind = faces[i]->GetVertices();
7982 for (j = 0; j < nv; j++)
7983 for (s = 0; s < vcount[ind[j]]; s++)
7984 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7986 out <<
' ' << voff[ind[j]]+s+1;
7992 else if (meshgen == 2)
7997 for (i = 0; i < NumOfFaces; i++)
7998 if ((l = faces_info[i].Elem2No) >= 0)
8000 k = partitioning[faces_info[i].Elem1No];
8001 l = partitioning[l];
8002 if (interior_faces || k != l)
8014 <<
"1 " << voff[NumOfVertices] <<
" " << NumOfElements
8015 <<
" 0 0 0 0 0 0 0\n"
8016 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
8017 <<
"0 0 " << nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
8018 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
8019 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
8021 for (i = 0; i < NumOfVertices; i++)
8022 for (k = 0; k < vcount[i]; k++)
8023 out << voff[i]+k <<
" 0.0 " << vertices[i](0) <<
' '
8024 << vertices[i](1) <<
' ' << vertices[i](2) <<
" 0.0\n";
8026 for (i = 0; i < NumOfElements; i++)
8028 nv = elements[i]->GetNVertices();
8029 ind = elements[i]->GetVertices();
8030 out << i+1 <<
' ' << partitioning[i]+1;
8031 for (j = 0; j < nv; j++)
8033 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
8034 vown[ind[j]][vcount[ind[j]]] = i;
8039 for (i = 0; i < NumOfVertices; i++)
8041 vcount[i] = voff[i+1] - voff[i];
8045 for (i = 0; i < NumOfFaces; i++)
8046 if ((l = faces_info[i].Elem2No) >= 0)
8048 k = partitioning[faces_info[i].Elem1No];
8049 l = partitioning[l];
8050 if (interior_faces || k != l)
8052 nv = faces[i]->GetNVertices();
8053 ind = faces[i]->GetVertices();
8055 for (j = 0; j < nv; j++)
8056 for (s = 0; s < vcount[ind[j]]; s++)
8057 if (vown[ind[j]][s] == faces_info[i].Elem1No)
8059 out <<
' ' << voff[ind[j]]+s+1;
8061 out <<
" 1.0 1.0 1.0 1.0\n";
8063 for (j = nv-1; j >= 0; j--)
8064 for (s = 0; s < vcount[ind[j]]; s++)
8065 if (vown[ind[j]][s] == faces_info[i].Elem2No)
8067 out <<
' ' << voff[ind[j]]+s+1;
8069 out <<
" 1.0 1.0 1.0 1.0\n";
8074 k = partitioning[faces_info[i].Elem1No];
8075 nv = faces[i]->GetNVertices();
8076 ind = faces[i]->GetVertices();
8078 for (j = 0; j < nv; j++)
8079 for (s = 0; s < vcount[ind[j]]; s++)
8080 if (vown[ind[j]][s] == faces_info[i].Elem1No)
8082 out <<
' ' << voff[ind[j]]+s+1;
8084 out <<
" 1.0 1.0 1.0 1.0\n";
8090 for (i = 0; i < NumOfVertices; i++)
8100 void Mesh::PrintSurfaces(
const Table & Aface_face, std::ostream &
out)
const
8107 " NURBS mesh is not supported!");
8111 out <<
"MFEM mesh v1.0\n";
8115 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
8120 "# TETRAHEDRON = 4\n"
8124 out <<
"\ndimension\n" << Dim
8125 <<
"\n\nelements\n" << NumOfElements <<
'\n';
8126 for (i = 0; i < NumOfElements; i++)
8128 PrintElement(elements[i], out);
8132 const int *
const i_AF_f = Aface_face.
GetI();
8133 const int *
const j_AF_f = Aface_face.
GetJ();
8135 for (
int iAF=0; iAF < Aface_face.
Size(); ++iAF)
8136 for (
const int * iface = j_AF_f + i_AF_f[iAF];
8137 iface < j_AF_f + i_AF_f[iAF+1];
8140 out << iAF+1 <<
' ';
8141 PrintElementWithoutAttr(faces[*iface],out);
8144 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
8147 out << spaceDim <<
'\n';
8148 for (i = 0; i < NumOfVertices; i++)
8150 out << vertices[i](0);
8151 for (j = 1; j < spaceDim; j++)
8153 out <<
' ' << vertices[i](j);
8166 void Mesh::ScaleSubdomains(
double sf)
8171 int na = attributes.
Size();
8172 double *cg =
new double[na*spaceDim];
8173 int *nbea =
new int[na];
8175 int *vn =
new int[NumOfVertices];
8176 for (i = 0; i < NumOfVertices; i++)
8180 for (i = 0; i < na; i++)
8182 for (j = 0; j < spaceDim; j++)
8184 cg[i*spaceDim+j] = 0.0;
8189 for (i = 0; i < NumOfElements; i++)
8191 GetElementVertices(i, vert);
8192 for (k = 0; k < vert.
Size(); k++)
8198 for (i = 0; i < NumOfElements; i++)
8200 int bea = GetAttribute(i)-1;
8201 GetPointMatrix(i, pointmat);
8202 GetElementVertices(i, vert);
8204 for (k = 0; k < vert.
Size(); k++)
8205 if (vn[vert[k]] == 1)
8208 for (j = 0; j < spaceDim; j++)
8210 cg[bea*spaceDim+j] += pointmat(j,k);
8216 for (i = 0; i < NumOfElements; i++)
8218 int bea = GetAttribute(i)-1;
8219 GetElementVertices (i, vert);
8221 for (k = 0; k < vert.
Size(); k++)
8224 for (j = 0; j < spaceDim; j++)
8225 vertices[vert[k]](j) = sf*vertices[vert[k]](j) +
8226 (1-sf)*cg[bea*spaceDim+j]/nbea[bea];
8236 void Mesh::ScaleElements(
double sf)
8241 int na = NumOfElements;
8242 double *cg =
new double[na*spaceDim];
8243 int *nbea =
new int[na];
8245 int *vn =
new int[NumOfVertices];
8246 for (i = 0; i < NumOfVertices; i++)
8250 for (i = 0; i < na; i++)
8252 for (j = 0; j < spaceDim; j++)
8254 cg[i*spaceDim+j] = 0.0;
8259 for (i = 0; i < NumOfElements; i++)
8261 GetElementVertices(i, vert);
8262 for (k = 0; k < vert.
Size(); k++)
8268 for (i = 0; i < NumOfElements; i++)
8271 GetPointMatrix(i, pointmat);
8272 GetElementVertices(i, vert);
8274 for (k = 0; k < vert.
Size(); k++)
8275 if (vn[vert[k]] == 1)
8278 for (j = 0; j < spaceDim; j++)
8280 cg[bea*spaceDim+j] += pointmat(j,k);
8286 for (i = 0; i < NumOfElements; i++)
8289 GetElementVertices(i, vert);
8291 for (k = 0; k < vert.
Size(); k++)
8294 for (j = 0; j < spaceDim; j++)
8295 vertices[vert[k]](j) = sf*vertices[vert[k]](j) +
8296 (1-sf)*cg[bea*spaceDim+j]/nbea[bea];
8311 Vector vold(spaceDim), vnew(NULL, spaceDim);
8312 for (
int i = 0; i < vertices.Size(); i++)
8314 for (
int j = 0; j < spaceDim; j++)
8316 vold(j) = vertices[i](j);
8326 xnew.ProjectCoefficient(f_pert);
8333 MFEM_VERIFY(spaceDim == deformation.
GetVDim(),
8334 "incompatible vector dimensions");
8341 for (
int i = 0; i < NumOfVertices; i++)
8342 for (
int d = 0; d < spaceDim; d++)
8344 vertices[i](d) = xnew(d + spaceDim*i);
8355 void Mesh::RemoveUnusedVertices()
8357 if (NURBSext || ncmesh) {
return; }
8361 for (
int i = 0; i < GetNE(); i++)
8366 for (
int j = 0; j < nv; j++)
8371 for (
int i = 0; i < GetNBE(); i++)
8373 Element *el = GetBdrElement(i);
8376 for (
int j = 0; j < nv; j++)
8382 for (
int i = 0; i < v2v.
Size(); i++)
8386 vertices[num_vert] = vertices[i];
8387 v2v[i] = num_vert++;
8391 if (num_vert == v2v.
Size()) {
return; }
8398 for (
int i = 0; i < GetNE(); i++)
8400 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8405 for (
int i = 0; i < GetNE(); i++)
8407 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8408 Nodes->GetSubVector(vdofs, &nodes_by_element(s));
8412 vertices.SetSize(num_vert);
8413 NumOfVertices = num_vert;
8414 for (
int i = 0; i < GetNE(); i++)
8419 for (
int j = 0; j < nv; j++)
8424 for (
int i = 0; i < GetNBE(); i++)
8426 Element *el = GetBdrElement(i);
8429 for (
int j = 0; j < nv; j++)
8438 el_to_edge =
new Table;
8439 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
8444 GetElementToFaceTable();
8450 Nodes->FESpace()->Update();
8453 for (
int i = 0; i < GetNE(); i++)
8455 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8456 Nodes->SetSubVector(vdofs, &nodes_by_element(s));
8462 void Mesh::RemoveInternalBoundaries()
8464 if (NURBSext || ncmesh) {
return; }
8466 int num_bdr_elem = 0;
8467 int new_bel_to_edge_nnz = 0;
8468 for (
int i = 0; i < GetNBE(); i++)
8470 if (FaceIsInterior(GetBdrElementEdgeIndex(i)))
8472 FreeElement(boundary[i]);
8479 new_bel_to_edge_nnz += bel_to_edge->RowSize(i);
8484 if (num_bdr_elem == GetNBE()) {
return; }
8488 Table *new_bel_to_edge = NULL;
8492 new_be_to_edge.
Reserve(num_bdr_elem);
8496 new_be_to_face.
Reserve(num_bdr_elem);
8497 new_bel_to_edge =
new Table;
8498 new_bel_to_edge->
SetDims(num_bdr_elem, new_bel_to_edge_nnz);
8500 for (
int i = 0; i < GetNBE(); i++)
8502 if (!FaceIsInterior(GetBdrElementEdgeIndex(i)))
8504 new_boundary.
Append(boundary[i]);
8507 new_be_to_edge.
Append(be_to_edge[i]);
8511 int row = new_be_to_face.
Size();
8512 new_be_to_face.
Append(be_to_face[i]);
8513 int *e = bel_to_edge->GetRow(i);
8514 int ne = bel_to_edge->RowSize(i);
8515 int *new_e = new_bel_to_edge->
GetRow(row);
8516 for (
int j = 0; j < ne; j++)
8520 new_bel_to_edge->
GetI()[row+1] = new_bel_to_edge->
GetI()[row] + ne;
8525 NumOfBdrElements = new_boundary.
Size();
8536 bel_to_edge = new_bel_to_edge;
8540 for (
int i = 0; i < attribs.
Size(); i++)
8542 attribs[i] = GetBdrAttribute(i);
8546 bdr_attributes.DeleteAll();
8547 attribs.
Copy(bdr_attributes);
8552 #ifdef MFEM_USE_MEMALLOC
8555 if (E->
GetType() == Element::TETRAHEDRON)
8579 const int npts = point_mat.
Width();
8580 if (!npts) {
return 0; }
8581 MFEM_VERIFY(point_mat.
Height() == spaceDim,
"Invalid points matrix");
8585 if (!GetNE()) {
return 0; }
8587 double *data = point_mat.
GetData();
8594 min_dist = std::numeric_limits<double>::max();
8598 for (
int i = 0; i < GetNE(); i++)
8600 GetElementTransformation(i)->Transform(
8602 for (
int k = 0; k < npts; k++)
8604 double dist = pt.
DistanceTo(data+k*spaceDim);
8605 if (dist < min_dist(k))
8616 for (
int k = 0; k < npts; k++)
8620 int res = inv_tr->
Transform(pt, ips[k]);
8621 if (res == InverseElementTransformation::Inside)
8623 elem_ids[k] = e_idx[k];
8627 if (pts_found != npts)
8630 Table *vtoel = GetVertexToElementTable();
8631 for (
int k = 0; k < npts; k++)
8633 if (elem_ids[k] != -1) {
continue; }
8636 GetElementVertices(e_idx[k], vertices);
8637 for (
int v = 0; v < vertices.
Size(); v++)
8639 int vv = vertices[v];
8641 const int* els = vtoel->
GetRow(vv);
8642 for (
int e = 0; e < ne; e++)
8644 if (els[e] == e_idx[k]) {
continue; }
8646 int res = inv_tr->
Transform(pt, ips[k]);
8647 if (res == InverseElementTransformation::Inside)
8649 elem_ids[k] = els[e];
8659 if (inv_trans == NULL) {
delete inv_tr; }
8661 if (warn && pts_found != npts)
8663 MFEM_WARNING((npts-pts_found) <<
" points were not found");
8668 NodeExtrudeCoefficient::NodeExtrudeCoefficient(
const int dim,
const int _n,
8682 V(1) = s * ((ip.
y + layer) / n);
8687 V(2) = s * ((ip.
z + layer) / n);
8696 mfem::err <<
"Extrude1D : Not a 1D mesh!" << endl;
8700 int nvy = (closed) ? (ny) : (ny + 1);
8701 int nvt = mesh->
GetNV() * nvy;
8710 mesh2d =
new Mesh(2, nvt, mesh->
GetNE()*ny,
8715 for (
int i = 0; i < mesh->
GetNV(); i++)
8718 for (
int j = 0; j < nvy; j++)
8720 vc[1] = sy * (double(j) / ny);
8726 for (
int i = 0; i < mesh->
GetNE(); i++)
8731 for (
int j = 0; j < ny; j++)
8734 qv[0] = vert[0] * nvy + j;
8735 qv[1] = vert[1] * nvy + j;
8736 qv[2] = vert[1] * nvy + (j + 1) % nvy;
8737 qv[3] = vert[0] * nvy + (j + 1) % nvy;
8743 for (
int i = 0; i < mesh->
GetNBE(); i++)
8748 for (
int j = 0; j < ny; j++)
8751 sv[0] = vert[0] * nvy + j;
8752 sv[1] = vert[0] * nvy + (j + 1) % nvy;
8756 Swap<int>(sv[0], sv[1]);
8768 for (
int i = 0; i < mesh->
GetNE(); i++)
8774 sv[0] = vert[0] * nvy;
8775 sv[1] = vert[1] * nvy;
8779 sv[0] = vert[1] * nvy + ny;
8780 sv[1] = vert[0] * nvy + ny;
8796 string cname = name;
8797 if (cname ==
"Linear")
8801 else if (cname ==
"Quadratic")
8805 else if (cname ==
"Cubic")
8809 else if (!strncmp(name,
"H1_", 3))
8813 else if (!strncmp(name,
"L2_T", 4))
8817 else if (!strncmp(name,
"L2_", 3))
8824 mfem::err <<
"Extrude1D : The mesh uses unknown FE collection : "
8836 for (
int i = 0; i < mesh->
GetNE(); i++)
8839 for (
int j = ny-1; j >= 0; j--)
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
int Size() const
For backward compatibility define Size to be synonym of Width()
std::ostream & operator<<(std::ostream &out, const Mesh &mesh)
int Size() const
Logical size of the array.
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
void Get(double *p, const int dim) const
virtual void Print(std::ostream &out=mfem::out) const
void METIS_PartGraphVKway(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
int GetNDofs() const
Returns number of degrees of freedom.
Class for an integration rule - an Array of IntegrationPoint.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void NewDataAndSize(double *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Class for grid function - Vector with associated FE space.
int DofToVDof(int dof, int vd, int ndofs=-1) const
virtual Element * Duplicate(Mesh *m) const =0
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void AddColumnsInRow(int r, int ncol)
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
void METIS_PartGraphRecursive(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
virtual void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
Array< Element * > boundary
void JacToPerfJac(int GeomType, const DenseMatrix &J, DenseMatrix &PJ) const
void SetSize(int s)
Resize the vector to size s.
int GetNBE() const
Returns number of boundary elements.
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
void MakeOwner(FiniteElementCollection *_fec)
Make the GridFunction the owner of 'fec' and 'fes'.
int GetElementGeometry() const
Return the type of elements in the mesh.
Lists all edges/faces in the nonconforming mesh.
void GetMeshComponents(Array< mfem::Vertex > &mvertices, Array< mfem::Element * > &melements, Array< mfem::Element * > &mboundary) const
Return the basic Mesh arrays for the current finest level.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void SetDims(int rows, int nnz)
void Copy(Array ©) const
Create a copy of the current array.
RefinedGeometry * Refine(int Geom, int Times, int ETimes=1)
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
int Push(int r, int c, int f)
Piecewise-(bi)linear continuous finite elements.
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
Mesh * Extrude1D(Mesh *mesh, const int ny, const double sy, const bool closed)
Extrude a 1D mesh.
void Save(std::ostream &out, int fmt=0) const
Save the Array to the stream out using the format fmt. The format fmt can be:
void SetSize(int i, int j, int k)
int GetNE() const
Returns number of elements.
void GetElementLocalToGlobal(Array< int > &lelem_elem)
virtual void SetVertices(const int *ind)
Set the vertices according to the given input.
Data type quadrilateral element.
void AddBdrSegment(const int *vi, int attr=1)
double * GetData() const
Returns the matrix data array.
const IntegrationPoint & GetCenter(int GeomType)
Return the center of the given Geometry::Type, GeomType.
void GetVertexLocalToGlobal(Array< int > &lvert_vert)
double * GetData() const
Return a pointer to the beginning of the Vector data.
int Size_of_connections() const
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
void skip_comment_lines(std::istream &is, const char comment_char)
int GetGeometryType() const
void DeleteAll()
Delete whole array.
void AddConnections(int r, const int *c, int nc)
int master
master number (in Mesh numbering)
Array< NCFaceInfo > nc_faces_info
void AddVertex(const double *)
Piecewise-(bi)cubic continuous finite elements.
PointFiniteElement PointFE
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
Data type hexahedron element.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
void DetOfLinComb(const DenseMatrix &A, const DenseMatrix &B, Vector &c)
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int local
local number within 'element'
int Append(const T &el)
Append element to array, resize if necessary.
virtual void ResetTransform(int tr)
Set current coarse-fine transformation number.
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
std::vector< Master > masters
void METIS_PartGraphKway(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
TriLinear3DFiniteElement HexahedronFE
void AddConnection(int r, int c)
int MeshGenerator()
Get the mesh generator/type.
Type
Constants for the classes derived from Element.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
virtual void GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
const int * GetDofMap(int GeomType) const
Get the Cartesian to local H1 dof map.
NURBSExtension * StealNURBSext()
const IntegrationRule & GetNodes() const
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
GeometryRefiner GlobGeometryRefiner
void SetLayer(const int l)
int GetAttribute() const
Return element's attribute.
Data type triangle element.
const Element * GetElement(int i) const
virtual void SetVertices(const int *ind)
Set the vertices according to the given input.
void Sort()
Sorts the array. This requires operator< to be defined for T.
int GetVDim()
Returns dimension of the vector.
void SetNodalFESpace(FiniteElementSpace *nfes)
virtual void ResetTransform(int tr)
Set current coarse-fine transformation number.
int Size() const
Returns the number of TYPE I elements.
int GetVDim() const
Returns vector dimension.
A class for non-conforming AMR on higher-order hexahedral, quadrilateral or triangular meshes...
FiniteElementSpace * FESpace()
void GetColumn(int c, Vector &col) const
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
double DistanceTo(const double *p) const
Compute the Euclidean distance to another vector.
virtual unsigned GetTransform() const
Return current coarse-fine transformation.
void FindPartitioningComponents(Table &elem_elem, const Array< int > &partitioning, Array< int > &component, Array< int > &num_comp)
Data type tetrahedron element.
int GetGeomType() const
Returns the Geometry::Type of the reference element.
int SpaceDimension() const
virtual unsigned GetTransform() const
Return current coarse-fine transformation.
double * Data() const
Returns the matrix data array.
void Swap(Array< T > &, Array< T > &)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
virtual void PushTransform(int tr)
Add 'tr' to the current chain of coarse-fine transformations.
const NURBSExtension * GetNURBSext() const
int SpaceDimension() const
std::vector< Slave > slaves
Nonconforming edge/face within a bigger edge/face.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void AddAColumnInRow(int r)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
int FindRoots(const Vector &z, Vector &x)
void AddQuad(const int *vi, int attr=1)
int Push4(int r, int c, int f, int t)
Helper struct for defining a connectivity table, see Table::MakeFromList.
Linear3DFiniteElement TetrahedronFE
Array< Element * > elements
Linear2DFiniteElement TriangleFE
int GetElementBaseGeometry(int i=0) const
virtual int * DofOrderForOrientation(int GeomType, int Or) const =0
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
virtual void GetBdrElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom for i'th boundary element.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual const char * Name() const
Class for integration point with weight.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
void FinalizeQuadMesh(int generate_edges=0, int refine=0, bool fix_orientation=true)
Finalize the construction of a quadrilateral Mesh.
void FindTMax(Vector &c, Vector &x, double &tmax, const double factor, const int Dim)
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i'th element.
double CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
Array< FaceInfo > faces_info
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
virtual int GetNVertices() const =0
int parent
element index in the coarse mesh
void SetAttribute(const int attr)
Set element's attribute.
virtual void ProjectCoefficient(Coefficient &coeff)
Piecewise-(bi)quadratic continuous finite elements.
NCMesh * ncmesh
Optional non-conforming mesh extension.
void filter_dos(std::string &line)
const FiniteElementCollection * FEColl() const
void GetNodes(Vector &node_coord) const
int NumberOfEntries() const
virtual void PushTransform(int tr)
Add 'tr' to the current chain of coarse-fine transformations.
Arbitrary order H1-conforming (continuous) finite elements.
void XYZ_VectorFunction(const Vector &p, Vector &v)
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
virtual int GetRefinementFlag()
virtual int DofForGeometry(int GeomType) const =0
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
BiLinear2DFiniteElement QuadrilateralFE
Rank 3 tensor (array of matrices)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Abstract data type element.
int GetAttribute(int i) const
Return the attribute of element i.
Data type line segment element.
Linear1DFiniteElement SegmentFE
int GetBdrElementBaseGeometry(int i=0) const
Array< int > attributes
A list of all unique element attributes used by the Mesh.
const Element * GetBdrElement(int i) const
virtual int GetType() const =0
Returns element's type.
DenseMatrix point_matrix
position within the master edge/face
Defines the position of a fine element within a coarse element.
int matrix
index into CoarseFineTransformations::point_matrices
Arbitrary order "L2-conforming" discontinuous finite elements.
Class used to extrude the nodes of a mesh.
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const