15 #include "../fem/fem.hpp"
16 #include "../general/sort_pairs.hpp"
37 int geom = GetElementBaseGeometry(i);
43 double Mesh::GetElementSize(
int i,
int type)
46 GetElementJacobian(i, J);
49 return pow(fabs(J.
Det()), 1./Dim);
61 double Mesh::GetElementSize(
int i,
const Vector &dir)
65 GetElementJacobian(i, J);
67 return sqrt((d_hat * d_hat) / (dir * dir));
70 double Mesh::GetElementVolume(
int i)
92 for (
int d = 0; d < Dim; d++)
94 min[d] = numeric_limits<double>::infinity();
95 max[d] = -numeric_limits<double>::infinity();
101 for (
int i = 0; i < NumOfVertices; i++)
103 coord = GetVertex(i);
104 for (
int d = 0; d < Dim; d++)
106 if (coord[d] < min[d]) { min[d] = coord[d]; }
107 if (coord[d] > max[d]) { max[d] = coord[d]; }
113 int ne = (Dim == 3) ? GetNBE() : GetNE();
121 for (
int i = 0; i < ne; i++)
125 GetBdrElementFace(i, &fn, &fo);
127 Tr = GetFaceElementTransformations(fn, 5);
134 T = GetElementTransformation(i);
138 for (
int j = 0; j < pointmat.
Width(); j++)
140 for (
int d = 0; d < Dim; d++)
142 if (pointmat(d,j) < min[d]) { min[d] = pointmat(d,j); }
143 if (pointmat(d,j) > max[d]) { max[d] = pointmat(d,j); }
150 void Mesh::PrintCharacteristics(
Vector *Vh,
Vector *Vk, std::ostream &out)
154 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
156 out <<
"Mesh Characteristics:";
159 sdim = SpaceDimension();
162 if (Vh) { Vh->
SetSize(NumOfElements); }
163 if (Vk) { Vk->
SetSize(NumOfElements); }
165 h_min = kappa_min = numeric_limits<double>::infinity();
166 h_max = kappa_max = -h_min;
167 for (i = 0; i < NumOfElements; i++)
169 GetElementJacobian(i, J);
170 h = pow(fabs(J.
Weight()), 1.0/
double(dim));
171 kappa = (dim == sdim) ?
173 if (Vh) { (*Vh)(i) = h; }
174 if (Vk) { (*Vk)(i) = kappa; }
176 if (h < h_min) { h_min = h; }
177 if (h > h_max) { h_max = h; }
178 if (kappa < kappa_min) { kappa_min =
kappa; }
179 if (kappa > kappa_max) { kappa_max =
kappa; }
185 <<
"Number of vertices : " << GetNV() <<
'\n'
186 <<
"Number of elements : " << GetNE() <<
'\n'
187 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
188 <<
"h_min : " << h_min <<
'\n'
189 <<
"h_max : " << h_max <<
'\n';
194 <<
"Number of vertices : " << GetNV() <<
'\n'
195 <<
"Number of edges : " << GetNEdges() <<
'\n'
196 <<
"Number of elements : " << GetNE() <<
'\n'
197 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
198 <<
"Euler Number : " << EulerNumber2D() <<
'\n'
199 <<
"h_min : " << h_min <<
'\n'
200 <<
"h_max : " << h_max <<
'\n'
201 <<
"kappa_min : " << kappa_min <<
'\n'
202 <<
"kappa_max : " << kappa_max <<
'\n';
207 <<
"Number of vertices : " << GetNV() <<
'\n'
208 <<
"Number of edges : " << GetNEdges() <<
'\n'
209 <<
"Number of faces : " << GetNFaces() <<
'\n'
210 <<
"Number of elements : " << GetNE() <<
'\n'
211 <<
"Number of bdr elem : " << GetNBE() <<
'\n'
212 <<
"Euler Number : " << EulerNumber() <<
'\n'
213 <<
"h_min : " << h_min <<
'\n'
214 <<
"h_max : " << h_max <<
'\n'
215 <<
"kappa_min : " << kappa_min <<
'\n'
216 <<
"kappa_max : " << kappa_max <<
'\n';
218 out <<
'\n' << std::flush;
225 case Element::POINT :
return &
PointFE;
226 case Element::SEGMENT :
return &
SegmentFE;
232 MFEM_ABORT(
"Unknown element type");
244 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
250 Nodes->FESpace()->GetElementVDofs(i, vdofs);
252 int n = vdofs.
Size()/spaceDim;
254 for (
int k = 0; k < spaceDim; k++)
256 for (
int j = 0; j < n; j++)
258 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
261 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
265 void Mesh::GetElementTransformation(
int i,
const Vector &nodes,
273 int nv = elements[i]->GetNVertices();
274 const int *v = elements[i]->GetVertices();
275 int n = vertices.
Size();
277 for (
int k = 0; k < spaceDim; k++)
279 for (
int j = 0; j < nv; j++)
281 pm(k, j) = nodes(k*n+v[j]);
284 ElTr->
SetFE(GetTransformationFEforElementType(GetElementType(i)));
289 Nodes->FESpace()->GetElementVDofs(i, vdofs);
290 int n = vdofs.
Size()/spaceDim;
292 for (
int k = 0; k < spaceDim; k++)
294 for (
int j = 0; j < n; j++)
296 pm(k,j) = nodes(vdofs[n*k+j]);
299 ElTr->
SetFE(Nodes->FESpace()->GetFE(i));
305 GetElementTransformation(i, &Transformation);
307 return &Transformation;
312 GetBdrElementTransformation(i, &FaceTransformation);
313 return &FaceTransformation;
324 GetTransformationFEforElementType(GetBdrElementType(i)));
330 Nodes->FESpace()->GetBdrElementVDofs(i, vdofs);
331 int n = vdofs.
Size()/spaceDim;
333 for (
int k = 0; k < spaceDim; k++)
335 for (
int j = 0; j < n; j++)
337 pm(k,j) = (*Nodes)(vdofs[n*k+j]);
340 ElTr->
SetFE(Nodes->FESpace()->GetBE(i));
346 FTr->
Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
351 const int *v = (Dim == 1) ? &FaceNo : faces[FaceNo]->GetVertices();
352 const int nv = (Dim == 1) ? 1 : faces[FaceNo]->GetNVertices();
354 for (
int i = 0; i < spaceDim; i++)
356 for (
int j = 0; j < nv; j++)
358 pm(i, j) = vertices[v[j]](i);
361 FTr->
SetFE(GetTransformationFEforElementType(GetFaceElementType(FaceNo)));
365 const FiniteElement *face_el = Nodes->FESpace()->GetFaceElement(FaceNo);
369 Nodes->FESpace()->GetFaceVDofs(FaceNo, vdofs);
370 int n = vdofs.
Size()/spaceDim;
372 for (
int i = 0; i < spaceDim; i++)
374 for (
int j = 0; j < n; j++)
376 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
383 FaceInfo &face_info = faces_info[FaceNo];
385 int face_geom = GetFaceGeometryType(FaceNo);
386 int face_type = GetFaceElementType(FaceNo);
388 GetLocalFaceTransformation(face_type,
389 GetElementType(face_info.
Elem1No),
390 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
393 face_el = Nodes->FESpace()->GetTraceElement(face_info.
Elem1No,
397 FaceElemTr.Loc1.Transform(face_el->
GetNodes(), eir);
399 Nodes->GetVectorValues(Transformation, eir, pm);
408 GetFaceTransformation(FaceNo, &FaceTransformation);
409 return &FaceTransformation;
416 GetFaceTransformation(EdgeNo, EdTr);
421 mfem_error(
"Mesh::GetEdgeTransformation not defined in 1D \n");
430 GetEdgeVertices(EdgeNo, v);
433 for (
int i = 0; i < spaceDim; i++)
435 for (
int j = 0; j < nv; j++)
437 pm(i, j) = vertices[v[j]](i);
440 EdTr->
SetFE(GetTransformationFEforElementType(Element::SEGMENT));
444 const FiniteElement *edge_el = Nodes->FESpace()->GetEdgeElement(EdgeNo);
448 Nodes->FESpace()->GetEdgeVDofs(EdgeNo, vdofs);
449 int n = vdofs.
Size()/spaceDim;
451 for (
int i = 0; i < spaceDim; i++)
453 for (
int j = 0; j < n; j++)
455 pm(i, j) = (*Nodes)(vdofs[n*i+j]);
458 EdTr->
SetFE(edge_el);
462 MFEM_ABORT(
"Not implemented.");
469 GetEdgeTransformation(EdgeNo, &EdgeTransformation);
470 return &EdgeTransformation;
474 void Mesh::GetLocalPtToSegTransformation(
488 void Mesh::GetLocalSegToTriTransformation(
496 tv = tri_t::Edges[i/64];
497 so = seg_t::Orient[i%64];
500 for (
int j = 0; j < 2; j++)
502 locpm(0, so[j]) = TriVert->
IntPoint(tv[j]).
x;
503 locpm(1, so[j]) = TriVert->
IntPoint(tv[j]).
y;
507 void Mesh::GetLocalSegToQuadTransformation(
515 qv = quad_t::Edges[i/64];
516 so = seg_t::Orient[i%64];
519 for (
int j = 0; j < 2; j++)
521 locpm(0, so[j]) = QuadVert->
IntPoint(qv[j]).
x;
522 locpm(1, so[j]) = QuadVert->
IntPoint(qv[j]).
y;
526 void Mesh::GetLocalTriToTetTransformation(
533 const int *tv = tet_t::FaceVert[i/64];
536 const int *to = tri_t::Orient[i%64];
540 for (
int j = 0; j < 3; j++)
543 locpm(0, j) = vert.
x;
544 locpm(1, j) = vert.
y;
545 locpm(2, j) = vert.
z;
549 void Mesh::GetLocalQuadToHexTransformation(
556 const int *hv = hex_t::FaceVert[i/64];
558 const int *qo = quad_t::Orient[i%64];
561 for (
int j = 0; j < 4; j++)
564 locpm(0, j) = vert.
x;
565 locpm(1, j) = vert.
y;
566 locpm(2, j) = vert.
z;
570 void Mesh::GetLocalFaceTransformation(
576 GetLocalPtToSegTransformation(Transf, inf);
579 case Element::SEGMENT:
580 if (elem_type == Element::TRIANGLE)
582 GetLocalSegToTriTransformation(Transf, inf);
586 MFEM_ASSERT(elem_type == Element::QUADRILATERAL,
"");
587 GetLocalSegToQuadTransformation(Transf, inf);
591 case Element::TRIANGLE:
592 MFEM_ASSERT(elem_type == Element::TETRAHEDRON,
"");
593 GetLocalTriToTetTransformation(Transf, inf);
596 case Element::QUADRILATERAL:
597 MFEM_ASSERT(elem_type == Element::HEXAHEDRON,
"");
598 GetLocalQuadToHexTransformation(Transf, inf);
606 FaceInfo &face_info = faces_info[FaceNo];
608 FaceElemTr.Elem1 = NULL;
609 FaceElemTr.Elem2 = NULL;
615 GetElementTransformation(FaceElemTr.Elem1No, &Transformation);
616 FaceElemTr.Elem1 = &Transformation;
622 FaceElemTr.Elem2No = face_info.
Elem2No;
623 if ((mask & 2) && FaceElemTr.Elem2No >= 0)
626 if (NURBSext && (mask & 1)) { MFEM_ABORT(
"NURBS mesh not supported!"); }
628 GetElementTransformation(FaceElemTr.Elem2No, &Transformation2);
629 FaceElemTr.Elem2 = &Transformation2;
633 FaceElemTr.FaceGeom = GetFaceGeometryType(FaceNo);
634 FaceElemTr.Face = (mask & 16) ? GetFaceTransformation(FaceNo) : NULL;
637 int face_type = GetFaceElementType(FaceNo);
640 int elem_type = GetElementType(face_info.
Elem1No);
641 GetLocalFaceTransformation(face_type, elem_type,
642 FaceElemTr.Loc1.Transf, face_info.
Elem1Inf);
644 if ((mask & 8) && FaceElemTr.Elem2No >= 0)
646 int elem_type = GetElementType(face_info.
Elem2No);
647 GetLocalFaceTransformation(face_type, elem_type,
648 FaceElemTr.Loc2.Transf, face_info.
Elem2Inf);
651 if (Nonconforming() && IsSlaveFace(face_info))
653 ApplyLocalSlaveTransformation(FaceElemTr.Loc2.Transf, face_info);
655 if (face_type == Element::SEGMENT)
658 DenseMatrix &pm = FaceElemTr.Loc2.Transf.GetPointMat();
659 std::swap(pm(0,0), pm(0,1));
660 std::swap(pm(1,0), pm(1,1));
670 return fi.
NCFace >= 0 && nc_faces_info[fi.
NCFace].Slave;
676 #ifdef MFEM_THREAD_SAFE
681 MFEM_ASSERT(fi.
NCFace >= 0,
"");
692 fn = be_to_face[BdrElemNo];
696 fn = be_to_edge[BdrElemNo];
700 fn = boundary[BdrElemNo]->GetVertices()[0];
703 if (FaceIsTrueInterior(fn) || faces_info[fn].NCFace >= 0)
707 tr = GetFaceElementTransformations(fn);
712 void Mesh::GetFaceElements(
int Face,
int *Elem1,
int *Elem2)
714 *Elem1 = faces_info[Face].
Elem1No;
715 *Elem2 = faces_info[Face].Elem2No;
718 void Mesh::GetFaceInfos(
int Face,
int *Inf1,
int *Inf2)
720 *Inf1 = faces_info[Face].Elem1Inf;
721 *Inf2 = faces_info[Face].Elem2Inf;
724 int Mesh::GetFaceGeometryType(
int Face)
const
726 return (Dim == 1) ? Geometry::POINT : faces[Face]->GetGeometryType();
729 int Mesh::GetFaceElementType(
int Face)
const
731 return (Dim == 1) ? Element::POINT : faces[Face]->GetType();
736 NumOfVertices = NumOfElements = NumOfBdrElements = NumOfEdges = -1;
741 last_operation = Mesh::NONE;
745 void Mesh::InitTables()
748 el_to_face = el_to_el = bel_to_edge = face_edge = edge_vertex = NULL;
751 void Mesh::DeleteTables()
768 void Mesh::SetAttributes()
773 for (
int i = 0; i < attribs.
Size(); i++)
775 attribs[i] = GetBdrAttribute(i);
779 attribs.
Copy(bdr_attributes);
780 if (bdr_attributes.Size() > 0 && bdr_attributes[0] <= 0)
782 MFEM_WARNING(
"Non-positive attributes on the boundary!");
786 for (
int i = 0; i < attribs.
Size(); i++)
788 attribs[i] = GetAttribute(i);
792 attribs.
Copy(attributes);
793 if (attributes.Size() > 0 && attributes[0] <= 0)
795 MFEM_WARNING(
"Non-positive attributes in the domain!");
799 void Mesh::InitMesh(
int _Dim,
int _spaceDim,
int NVert,
int NElem,
int NBdrElem)
802 spaceDim = _spaceDim;
804 BaseGeom = BaseBdrGeom = -1;
810 vertices.SetSize(NVert);
813 elements.SetSize(NElem);
815 NumOfBdrElements = 0;
816 boundary.SetSize(NBdrElem);
819 void Mesh::InitBaseGeom()
821 BaseGeom = BaseBdrGeom = -1;
822 for (
int i = 0; i < NumOfElements; i++)
824 int geom = elements[i]->GetGeometryType();
825 if (geom != BaseGeom && BaseGeom >= 0)
827 BaseGeom = -1;
break;
831 for (
int i = 0; i < NumOfBdrElements; i++)
833 int geom = boundary[i]->GetGeometryType();
834 if (geom != BaseBdrGeom && BaseBdrGeom >= 0)
836 BaseBdrGeom = -1;
break;
842 void Mesh::AddVertex(
const double *x)
844 double *y = vertices[NumOfVertices]();
846 for (
int i = 0; i < spaceDim; i++)
853 void Mesh::AddTri(
const int *vi,
int attr)
855 elements[NumOfElements++] =
new Triangle(vi, attr);
858 void Mesh::AddTriangle(
const int *vi,
int attr)
860 elements[NumOfElements++] =
new Triangle(vi, attr);
863 void Mesh::AddQuad(
const int *vi,
int attr)
868 void Mesh::AddTet(
const int *vi,
int attr)
870 #ifdef MFEM_USE_MEMALLOC
872 tet = TetMemory.Alloc();
875 elements[NumOfElements++] = tet;
877 elements[NumOfElements++] =
new Tetrahedron(vi, attr);
881 void Mesh::AddHex(
const int *vi,
int attr)
883 elements[NumOfElements++] =
new Hexahedron(vi, attr);
886 void Mesh::AddHexAsTets(
const int *vi,
int attr)
888 static const int hex_to_tet[6][4] =
890 { 0, 1, 2, 6 }, { 0, 5, 1, 6 }, { 0, 4, 5, 6 },
891 { 0, 2, 3, 6 }, { 0, 3, 7, 6 }, { 0, 7, 4, 6 }
895 for (
int i = 0; i < 6; i++)
897 for (
int j = 0; j < 4; j++)
899 ti[j] = vi[hex_to_tet[i][j]];
905 void Mesh::AddBdrSegment(
const int *vi,
int attr)
907 boundary[NumOfBdrElements++] =
new Segment(vi, attr);
910 void Mesh::AddBdrTriangle(
const int *vi,
int attr)
912 boundary[NumOfBdrElements++] =
new Triangle(vi, attr);
915 void Mesh::AddBdrQuad(
const int *vi,
int attr)
920 void Mesh::AddBdrQuadAsTriangles(
const int *vi,
int attr)
922 static const int quad_to_tri[2][3] = { { 0, 1, 2 }, { 0, 2, 3 } };
925 for (
int i = 0; i < 2; i++)
927 for (
int j = 0; j < 3; j++)
929 ti[j] = vi[quad_to_tri[i][j]];
931 AddBdrTriangle(ti, attr);
935 void Mesh::GenerateBoundaryElements()
938 Array<int> &be2face = (Dim == 2) ? be_to_edge : be_to_face;
942 for (i = 0; i < boundary.Size(); i++)
944 FreeElement(boundary[i]);
954 NumOfBdrElements = 0;
955 for (i = 0; i < faces_info.Size(); i++)
957 if (faces_info[i].Elem2No < 0) { NumOfBdrElements++; }
960 boundary.SetSize(NumOfBdrElements);
961 be2face.
SetSize(NumOfBdrElements);
962 for (j = i = 0; i < faces_info.Size(); i++)
964 if (faces_info[i].Elem2No < 0)
966 boundary[j] = faces[i]->Duplicate(
this);
981 static int edge_compare(
const void *ii,
const void *jj)
983 edge_length *i = (edge_length *)ii, *j = (edge_length *)jj;
984 if (i->length > j->length) {
return (1); }
985 if (i->length < j->length) {
return (-1); }
989 void Mesh::FinalizeTriMesh(
int generate_edges,
int refine,
bool fix_orientation)
991 CheckElementOrientation(fix_orientation);
995 MarkTriMeshForRefinement();
1000 el_to_edge =
new Table;
1001 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1003 CheckBdrElementOrientation();
1014 BaseGeom = Geometry::TRIANGLE;
1015 BaseBdrGeom = Geometry::SEGMENT;
1020 void Mesh::FinalizeQuadMesh(
int generate_edges,
int refine,
1021 bool fix_orientation)
1023 if (fix_orientation)
1025 CheckElementOrientation(fix_orientation);
1030 el_to_edge =
new Table;
1031 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1033 CheckBdrElementOrientation();
1044 BaseGeom = Geometry::SQUARE;
1045 BaseBdrGeom = Geometry::SEGMENT;
1051 #ifdef MFEM_USE_GECKO
1057 Gecko::Functional *functional =
1058 new Gecko::FunctionalGeometric();
1059 unsigned int iterations = 1;
1060 unsigned int window = 2;
1061 unsigned int period = 1;
1062 unsigned int seed = 0;
1065 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1072 const Table &my_el_to_el = ElementToElementTable();
1073 for (
int elemid = 0; elemid < GetNE(); ++elemid)
1075 const int *neighid = my_el_to_el.
GetRow(elemid);
1076 for (
int i = 0; i < my_el_to_el.
RowSize(elemid); ++i)
1078 graph.insert(elemid + 1, neighid[i] + 1);
1083 graph.order(functional, iterations, window, period, seed);
1086 Gecko::Node::Index NE = GetNE();
1087 for (Gecko::Node::Index gnodeid = 1; gnodeid <= NE; ++gnodeid)
1089 ordering[gnodeid - 1] = graph.rank(gnodeid);
1097 void Mesh::ReorderElements(
const Array<int> &ordering,
bool reorder_vertices)
1101 MFEM_WARNING(
"element reordering of NURBS meshes is not supported.");
1106 MFEM_WARNING(
"element reordering of non-conforming meshes is not"
1110 MFEM_VERIFY(ordering.
Size() == GetNE(),
"invalid reordering array.")
1139 old_elem_node_vals.SetSize(GetNE());
1140 nodes_fes = Nodes->FESpace();
1143 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1145 nodes_fes->GetElementVDofs(old_elid, old_dofs);
1147 old_elem_node_vals[old_elid] =
new Vector(vals);
1153 for (
int old_elid = 0; old_elid < ordering.
Size(); ++old_elid)
1155 int new_elid = ordering[old_elid];
1156 new_elements[new_elid] = elements[old_elid];
1161 if (reorder_vertices)
1166 vertex_ordering = -1;
1168 int new_vertex_ind = 0;
1169 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1171 int *elem_vert = elements[new_elid]->GetVertices();
1172 int nv = elements[new_elid]->GetNVertices();
1173 for (
int vi = 0; vi < nv; ++vi)
1175 int old_vertex_ind = elem_vert[vi];
1176 if (vertex_ordering[old_vertex_ind] == -1)
1178 vertex_ordering[old_vertex_ind] = new_vertex_ind;
1179 new_vertices[new_vertex_ind] = vertices[old_vertex_ind];
1189 for (
int new_elid = 0; new_elid < GetNE(); ++new_elid)
1191 int *elem_vert = elements[new_elid]->GetVertices();
1192 int nv = elements[new_elid]->GetNVertices();
1193 for (
int vi = 0; vi < nv; ++vi)
1195 elem_vert[vi] = vertex_ordering[elem_vert[vi]];
1200 for (
int belid = 0; belid < GetNBE(); ++belid)
1202 int *be_vert = boundary[belid]->GetVertices();
1203 int nv = boundary[belid]->GetNVertices();
1204 for (
int vi = 0; vi < nv; ++vi)
1206 be_vert[vi] = vertex_ordering[be_vert[vi]];
1217 el_to_edge =
new Table;
1218 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1223 GetElementToFaceTable();
1231 nodes_fes->Update();
1233 for (
int old_elid = 0; old_elid < GetNE(); ++old_elid)
1235 int new_elid = ordering[old_elid];
1236 nodes_fes->GetElementVDofs(new_elid, new_dofs);
1237 Nodes->SetSubVector(new_dofs, *(old_elem_node_vals[old_elid]));
1238 delete old_elem_node_vals[old_elid];
1244 void Mesh::MarkForRefinement()
1250 MarkTriMeshForRefinement();
1254 MarkTetMeshForRefinement();
1259 void Mesh::MarkTriMeshForRefinement()
1264 for (
int i = 0; i < NumOfElements; i++)
1266 if (elements[i]->GetType() == Element::TRIANGLE)
1268 GetPointMatrix(i, pmat);
1269 elements[i]->MarkEdge(pmat);
1277 edge_length *length =
new edge_length[NumOfEdges];
1278 for (
int i = 0; i < NumOfVertices; i++)
1283 length[j].length = GetLength(i, it.Column());
1289 qsort(length, NumOfEdges,
sizeof(edge_length), edge_compare);
1292 for (
int i = 0; i < NumOfEdges; i++)
1294 order[length[i].edge] = i;
1300 void Mesh::MarkTetMeshForRefinement()
1304 DSTable v_to_v(NumOfVertices);
1305 GetVertexToVertexTable(v_to_v);
1308 GetEdgeOrdering(v_to_v, order);
1310 for (
int i = 0; i < NumOfElements; i++)
1312 if (elements[i]->GetType() == Element::TETRAHEDRON)
1314 elements[i]->MarkEdge(v_to_v, order);
1317 for (
int i = 0; i < NumOfBdrElements; i++)
1319 if (boundary[i]->GetType() == Element::TRIANGLE)
1321 boundary[i]->MarkEdge(v_to_v, order);
1328 if (*old_v_to_v && *old_elem_vert)
1336 if (*old_v_to_v == NULL)
1339 if (num_edge_dofs > 0)
1341 *old_v_to_v =
new DSTable(NumOfVertices);
1342 GetVertexToVertexTable(*(*old_v_to_v));
1345 if (*old_elem_vert == NULL)
1348 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1349 if (num_elem_dofs > 1)
1351 *old_elem_vert =
new Table;
1352 (*old_elem_vert)->
MakeI(GetNE());
1353 for (
int i = 0; i < GetNE(); i++)
1355 (*old_elem_vert)->AddColumnsInRow(i, elements[i]->GetNVertices());
1357 (*old_elem_vert)->MakeJ();
1358 for (
int i = 0; i < GetNE(); i++)
1360 (*old_elem_vert)->AddConnections(i, elements[i]->GetVertices(),
1361 elements[i]->GetNVertices());
1363 (*old_elem_vert)->ShiftUpI();
1377 int num_elem_dofs = fec->
DofForGeometry(GetElementBaseGeometry(0));
1393 if (num_edge_dofs > 0)
1395 DSTable new_v_to_v(NumOfVertices);
1396 GetVertexToVertexTable(new_v_to_v);
1398 for (
int i = 0; i < NumOfVertices; i++)
1402 int old_i = (*old_v_to_v)(i, it.Column());
1403 int new_i = it.Index();
1410 old_dofs.
SetSize(num_edge_dofs);
1411 new_dofs.
SetSize(num_edge_dofs);
1412 for (
int j = 0; j < num_edge_dofs; j++)
1414 old_dofs[j] = offset + old_i * num_edge_dofs + j;
1415 new_dofs[j] = offset + new_i * num_edge_dofs + j;
1419 for (
int j = 0; j < old_dofs.
Size(); j++)
1421 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1425 offset += NumOfEdges * num_edge_dofs;
1428 cout <<
"Mesh::DoNodeReorder : redges = " << redges << endl;
1433 if (num_face_dofs > 0)
1436 Table old_face_vertex;
1437 old_face_vertex.
MakeI(NumOfFaces);
1438 for (
int i = 0; i < NumOfFaces; i++)
1442 old_face_vertex.
MakeJ();
1443 for (
int i = 0; i < NumOfFaces; i++)
1445 faces[i]->GetNVertices());
1449 STable3D *faces_tbl = GetElementToFaceTable(1);
1453 for (
int i = 0; i < NumOfFaces; i++)
1455 int *old_v = old_face_vertex.
GetRow(i), *new_v;
1456 int new_i, new_or, *dof_ord;
1457 switch (old_face_vertex.
RowSize(i))
1460 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2]);
1461 new_v = faces[new_i]->GetVertices();
1462 new_or = GetTriOrientation(old_v, new_v);
1467 new_i = (*faces_tbl)(old_v[0], old_v[1], old_v[2], old_v[3]);
1468 new_v = faces[new_i]->GetVertices();
1469 new_or = GetQuadOrientation(old_v, new_v);
1474 old_dofs.
SetSize(num_face_dofs);
1475 new_dofs.
SetSize(num_face_dofs);
1476 for (
int j = 0; j < num_face_dofs; j++)
1478 old_dofs[j] = offset + i * num_face_dofs + j;
1479 new_dofs[j] = offset + new_i * num_face_dofs + dof_ord[j];
1485 for (
int j = 0; j < old_dofs.
Size(); j++)
1487 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1491 offset += NumOfFaces * num_face_dofs;
1497 if (num_elem_dofs > 1)
1509 for (
int i = 0; i < GetNE(); i++)
1511 int *old_v = old_elem_vert->
GetRow(i);
1512 int *new_v = elements[i]->GetVertices();
1513 int new_or, *dof_ord;
1514 int geom = elements[i]->GetGeometryType();
1517 case Geometry::SEGMENT:
1518 new_or = (old_v[0] == new_v[0]) ? +1 : -1;
1520 case Geometry::TRIANGLE:
1521 new_or = GetTriOrientation(old_v, new_v);
1523 case Geometry::SQUARE:
1524 new_or = GetQuadOrientation(old_v, new_v);
1528 cerr <<
"Mesh::DoNodeReorder : " << Geometry::Name[
geom]
1529 <<
" elements (" << fec->
Name()
1530 <<
" FE collection) are not supported yet!" << endl;
1535 if (dof_ord == NULL)
1537 cerr <<
"Mesh::DoNodeReorder : FE collection '" << fec->
Name()
1538 <<
"' does not define reordering for " << Geometry::Name[
geom]
1539 <<
" elements!" << endl;
1542 old_dofs.
SetSize(num_elem_dofs);
1543 new_dofs.
SetSize(num_elem_dofs);
1544 for (
int j = 0; j < num_elem_dofs; j++)
1547 old_dofs[j] = offset + dof_ord[j];
1548 new_dofs[j] = offset + j;
1552 for (
int j = 0; j < old_dofs.
Size(); j++)
1554 (*Nodes)(new_dofs[j]) = onodes(old_dofs[j]);
1557 offset += num_elem_dofs;
1564 if (num_face_dofs == 0)
1568 GetElementToFaceTable();
1571 CheckBdrElementOrientation();
1576 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1581 CheckBdrElementOrientation();
1586 void Mesh::FinalizeTetMesh(
int generate_edges,
int refine,
bool fix_orientation)
1588 CheckElementOrientation(fix_orientation);
1590 if (NumOfBdrElements == 0)
1592 GetElementToFaceTable();
1594 GenerateBoundaryElements();
1599 MarkTetMeshForRefinement();
1602 GetElementToFaceTable();
1605 CheckBdrElementOrientation();
1607 if (generate_edges == 1)
1609 el_to_edge =
new Table;
1610 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1621 BaseGeom = Geometry::TETRAHEDRON;
1622 BaseBdrGeom = Geometry::TRIANGLE;
1627 void Mesh::FinalizeHexMesh(
int generate_edges,
int refine,
bool fix_orientation)
1629 CheckElementOrientation(fix_orientation);
1631 GetElementToFaceTable();
1634 if (NumOfBdrElements == 0)
1636 GenerateBoundaryElements();
1639 CheckBdrElementOrientation();
1643 el_to_edge =
new Table;
1644 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1653 BaseGeom = Geometry::CUBE;
1654 BaseBdrGeom = Geometry::SQUARE;
1660 int generate_edges,
double sx,
double sy,
double sz)
1664 int NVert, NElem, NBdrElem;
1666 NVert = (nx+1) * (ny+1) * (nz+1);
1667 NElem = nx * ny * nz;
1668 NBdrElem = 2*(nx*ny+nx*nz+ny*nz);
1669 if (type == Element::TETRAHEDRON)
1675 InitMesh(3, 3, NVert, NElem, NBdrElem);
1681 for (z = 0; z <= nz; z++)
1683 coord[2] = ((double) z / nz) * sz;
1684 for (y = 0; y <= ny; y++)
1686 coord[1] = ((double) y / ny) * sy;
1687 for (x = 0; x <= nx; x++)
1689 coord[0] = ((double) x / nx) * sx;
1695 #define VTX(XC, YC, ZC) ((XC)+((YC)+(ZC)*(ny+1))*(nx+1))
1698 for (z = 0; z < nz; z++)
1700 for (y = 0; y < ny; y++)
1702 for (x = 0; x < nx; x++)
1704 ind[0] = VTX(x , y , z );
1705 ind[1] = VTX(x+1, y , z );
1706 ind[2] = VTX(x+1, y+1, z );
1707 ind[3] = VTX(x , y+1, z );
1708 ind[4] = VTX(x , y , z+1);
1709 ind[5] = VTX(x+1, y , z+1);
1710 ind[6] = VTX(x+1, y+1, z+1);
1711 ind[7] = VTX(x , y+1, z+1);
1712 if (type == Element::TETRAHEDRON)
1714 AddHexAsTets(ind, 1);
1726 for (y = 0; y < ny; y++)
1727 for (x = 0; x < nx; x++)
1729 ind[0] = VTX(x , y , 0);
1730 ind[1] = VTX(x , y+1, 0);
1731 ind[2] = VTX(x+1, y+1, 0);
1732 ind[3] = VTX(x+1, y , 0);
1733 if (type == Element::TETRAHEDRON)
1735 AddBdrQuadAsTriangles(ind, 1);
1743 for (y = 0; y < ny; y++)
1744 for (x = 0; x < nx; x++)
1746 ind[0] = VTX(x , y , nz);
1747 ind[1] = VTX(x+1, y , nz);
1748 ind[2] = VTX(x+1, y+1, nz);
1749 ind[3] = VTX(x , y+1, nz);
1750 if (type == Element::TETRAHEDRON)
1752 AddBdrQuadAsTriangles(ind, 6);
1760 for (z = 0; z < nz; z++)
1761 for (y = 0; y < ny; y++)
1763 ind[0] = VTX(0 , y , z );
1764 ind[1] = VTX(0 , y , z+1);
1765 ind[2] = VTX(0 , y+1, z+1);
1766 ind[3] = VTX(0 , y+1, z );
1767 if (type == Element::TETRAHEDRON)
1769 AddBdrQuadAsTriangles(ind, 5);
1777 for (z = 0; z < nz; z++)
1778 for (y = 0; y < ny; y++)
1780 ind[0] = VTX(nx, y , z );
1781 ind[1] = VTX(nx, y+1, z );
1782 ind[2] = VTX(nx, y+1, z+1);
1783 ind[3] = VTX(nx, y , z+1);
1784 if (type == Element::TETRAHEDRON)
1786 AddBdrQuadAsTriangles(ind, 3);
1794 for (x = 0; x < nx; x++)
1795 for (z = 0; z < nz; z++)
1797 ind[0] = VTX(x , 0, z );
1798 ind[1] = VTX(x+1, 0, z );
1799 ind[2] = VTX(x+1, 0, z+1);
1800 ind[3] = VTX(x , 0, z+1);
1801 if (type == Element::TETRAHEDRON)
1803 AddBdrQuadAsTriangles(ind, 2);
1811 for (x = 0; x < nx; x++)
1812 for (z = 0; z < nz; z++)
1814 ind[0] = VTX(x , ny, z );
1815 ind[1] = VTX(x , ny, z+1);
1816 ind[2] = VTX(x+1, ny, z+1);
1817 ind[3] = VTX(x+1, ny, z );
1818 if (type == Element::TETRAHEDRON)
1820 AddBdrQuadAsTriangles(ind, 4);
1829 ofstream test_stream(
"debug.mesh");
1831 test_stream.close();
1835 bool fix_orientation =
true;
1837 if (type == Element::TETRAHEDRON)
1839 FinalizeTetMesh(generate_edges, refine, fix_orientation);
1843 FinalizeHexMesh(generate_edges, refine, fix_orientation);
1848 double sx,
double sy)
1858 if (type == Element::QUADRILATERAL)
1861 NumOfVertices = (nx+1) * (ny+1);
1862 NumOfElements = nx * ny;
1863 NumOfBdrElements = 2 * nx + 2 * ny;
1864 BaseGeom = Geometry::SQUARE;
1865 BaseBdrGeom = Geometry::SEGMENT;
1867 vertices.SetSize(NumOfVertices);
1868 elements.SetSize(NumOfElements);
1869 boundary.SetSize(NumOfBdrElements);
1876 for (j = 0; j < ny+1; j++)
1878 cy = ((double) j / ny) * sy;
1879 for (i = 0; i < nx+1; i++)
1881 cx = ((double) i / nx) * sx;
1882 vertices[k](0) = cx;
1883 vertices[k](1) = cy;
1890 for (j = 0; j < ny; j++)
1892 for (i = 0; i < nx; i++)
1894 ind[0] = i + j*(nx+1);
1895 ind[1] = i + 1 +j*(nx+1);
1896 ind[2] = i + 1 + (j+1)*(nx+1);
1897 ind[3] = i + (j+1)*(nx+1);
1905 for (i = 0; i < nx; i++)
1907 boundary[i] =
new Segment(i, i+1, 1);
1908 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
1911 for (j = 0; j < ny; j++)
1913 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
1914 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
1918 else if (type == Element::TRIANGLE)
1921 NumOfVertices = (nx+1) * (ny+1);
1922 NumOfElements = 2 * nx * ny;
1923 NumOfBdrElements = 2 * nx + 2 * ny;
1924 BaseGeom = Geometry::TRIANGLE;
1925 BaseBdrGeom = Geometry::SEGMENT;
1927 vertices.SetSize(NumOfVertices);
1928 elements.SetSize(NumOfElements);
1929 boundary.SetSize(NumOfBdrElements);
1936 for (j = 0; j < ny+1; j++)
1938 cy = ((double) j / ny) * sy;
1939 for (i = 0; i < nx+1; i++)
1941 cx = ((double) i / nx) * sx;
1942 vertices[k](0) = cx;
1943 vertices[k](1) = cy;
1950 for (j = 0; j < ny; j++)
1952 for (i = 0; i < nx; i++)
1954 ind[0] = i + j*(nx+1);
1955 ind[1] = i + 1 + (j+1)*(nx+1);
1956 ind[2] = i + (j+1)*(nx+1);
1959 ind[1] = i + 1 + j*(nx+1);
1960 ind[2] = i + 1 + (j+1)*(nx+1);
1968 for (i = 0; i < nx; i++)
1970 boundary[i] =
new Segment(i, i+1, 1);
1971 boundary[nx+i] =
new Segment(m+i+1, m+i, 3);
1974 for (j = 0; j < ny; j++)
1976 boundary[2*nx+j] =
new Segment((j+1)*m, j*m, 4);
1977 boundary[2*nx+ny+j] =
new Segment(j*m+nx, (j+1)*m+nx, 2);
1980 MarkTriMeshForRefinement();
1984 MFEM_ABORT(
"Unsupported element type.");
1987 CheckElementOrientation();
1989 if (generate_edges == 1)
1991 el_to_edge =
new Table;
1992 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
1994 CheckBdrElementOrientation();
2003 attributes.Append(1);
2004 bdr_attributes.Append(1); bdr_attributes.Append(2);
2005 bdr_attributes.Append(3); bdr_attributes.Append(4);
2008 void Mesh::Make1D(
int n,
double sx)
2015 BaseGeom = Geometry::SEGMENT;
2016 BaseBdrGeom = Geometry::POINT;
2023 NumOfVertices = n + 1;
2025 NumOfBdrElements = 2;
2026 vertices.SetSize(NumOfVertices);
2027 elements.SetSize(NumOfElements);
2028 boundary.SetSize(NumOfBdrElements);
2031 for (j = 0; j < n+1; j++)
2033 vertices[j](0) = ((
double) j / n) * sx;
2037 for (j = 0; j < n; j++)
2039 elements[j] =
new Segment(j, j+1, 1);
2044 boundary[0] =
new Point(ind, 1);
2046 boundary[1] =
new Point(ind, 2);
2053 attributes.Append(1);
2054 bdr_attributes.Append(1); bdr_attributes.Append(2);
2057 Mesh::Mesh(
const Mesh &mesh,
bool copy_nodes)
2074 elements.SetSize(NumOfElements);
2075 for (
int i = 0; i < NumOfElements; i++)
2077 elements[i] = mesh.
elements[i]->Duplicate(
this);
2081 MFEM_ASSERT(mesh.
vertices.Size() == NumOfVertices,
"internal MFEM error!");
2085 boundary.SetSize(NumOfBdrElements);
2086 for (
int i = 0; i < NumOfBdrElements; i++)
2088 boundary[i] = mesh.
boundary[i]->Duplicate(
this);
2107 faces.SetSize(mesh.
faces.Size());
2108 for (
int i = 0; i < faces.Size(); i++)
2111 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
2133 "copying NURBS meshes is not implemented");
2137 MFEM_VERIFY(mesh.
ncmesh == NULL,
2138 "copying non-conforming meshes is not implemented");
2143 if (mesh.
Nodes && copy_nodes)
2148 FiniteElementCollection::New(fec->
Name());
2153 Nodes->MakeOwner(fec_copy);
2154 *Nodes = *mesh.
Nodes;
2164 Mesh::Mesh(
const char *filename,
int generate_edges,
int refine,
2165 bool fix_orientation)
2177 MFEM_ABORT(
"Mesh file not found: " << filename <<
'\n');
2181 Load(imesh, generate_edges, refine, fix_orientation);
2185 Mesh::Mesh(std::istream &input,
int generate_edges,
int refine,
2186 bool fix_orientation)
2190 Load(input, generate_edges, refine, fix_orientation);
2197 case Geometry::POINT:
return (
new Point);
2198 case Geometry::SEGMENT:
return (
new Segment);
2199 case Geometry::TRIANGLE:
return (
new Triangle);
2201 case Geometry::CUBE:
return (
new Hexahedron);
2202 case Geometry::TETRAHEDRON:
2203 #ifdef MFEM_USE_MEMALLOC
2204 return TetMemory.Alloc();
2213 Element *Mesh::ReadElementWithoutAttr(std::istream &input)
2219 el = NewElement(geom);
2222 for (
int i = 0; i < nv; i++)
2230 void Mesh::PrintElementWithoutAttr(
const Element *el, std::ostream &out)
2235 for (
int j = 0; j < nv; j++)
2248 el = ReadElementWithoutAttr(input);
2254 void Mesh::PrintElement(
const Element *el, std::ostream &out)
2257 PrintElementWithoutAttr(el, out);
2260 void Mesh::SetMeshGen()
2263 for (
int i = 0; i < NumOfElements; i++)
2265 switch (elements[i]->GetType())
2267 case Element::SEGMENT:
2268 case Element::TRIANGLE:
2269 case Element::TETRAHEDRON:
2270 meshgen |= 1;
break;
2272 case Element::QUADRILATERAL:
2273 case Element::HEXAHEDRON:
2279 void Mesh::Load(std::istream &input,
int generate_edges,
int refine,
2280 bool fix_orientation)
2282 int i, j, curved = 0, read_gf = 1;
2286 MFEM_ABORT(
"Input stream is not open");
2289 if (NumOfVertices != -1)
2292 for (i = 0; i < NumOfElements; i++)
2294 FreeElement(elements[i]);
2296 elements.DeleteAll();
2300 vertices.DeleteAll();
2304 for (i = 0; i < NumOfBdrElements; i++)
2306 FreeElement(boundary[i]);
2308 boundary.DeleteAll();
2309 NumOfBdrElements = 0;
2312 for (i = 0; i < faces.Size(); i++)
2314 FreeElement(faces[i]);
2319 faces_info.DeleteAll();
2323 be_to_edge.DeleteAll();
2324 be_to_face.DeleteAll();
2333 if (own_nodes) {
delete Nodes; }
2341 getline(input, mesh_type);
2342 filter_dos(mesh_type);
2344 bool mfem_v10 = (mesh_type ==
"MFEM mesh v1.0");
2345 bool mfem_v11 = (mesh_type ==
"MFEM mesh v1.1");
2347 if (mfem_v10 || mfem_v11)
2349 ReadMFEMMesh(input, mfem_v11, curved);
2351 else if (mesh_type ==
"linemesh")
2353 ReadLineMesh(input);
2355 else if (mesh_type ==
"areamesh2" || mesh_type ==
"curved_areamesh2")
2357 if (mesh_type ==
"curved_areamesh2")
2361 ReadNetgen2DMesh(input, curved);
2363 else if (mesh_type ==
"NETGEN" || mesh_type ==
"NETGEN_Neutral_Format")
2365 ReadNetgen3DMesh(input);
2367 else if (mesh_type ==
"TrueGrid")
2369 ReadTrueGridMesh(input);
2371 else if (mesh_type ==
"# vtk DataFile Version 3.0" ||
2372 mesh_type ==
"# vtk DataFile Version 2.0")
2374 ReadVTKMesh(input, curved, read_gf);
2376 else if (mesh_type ==
"MFEM NURBS mesh v1.0")
2378 ReadNURBSMesh(input, curved, read_gf);
2380 else if (mesh_type ==
"MFEM INLINE mesh v1.0")
2382 ReadInlineMesh(input, generate_edges);
2385 else if (mesh_type ==
"$MeshFormat")
2387 ReadGmshMesh(input);
2389 else if (mesh_type.size() > 2 &&
2390 mesh_type[0] ==
'C' && mesh_type[1] ==
'D' && mesh_type[2] ==
'F')
2395 #ifdef MFEM_USE_NETCDF
2396 ReadCubit(*mesh_input, curved, read_gf);
2398 MFEM_ABORT(
"NetCDF support requires configuration with"
2399 " MFEM_USE_NETCDF=YES");
2405 MFEM_ABORT(
"Need to use mfem_ifstream with NetCDF");
2411 MFEM_ABORT(
"Unknown input mesh format: " << mesh_type);
2437 if (NumOfBdrElements == 0 && Dim > 2)
2440 GetElementToFaceTable();
2442 GenerateBoundaryElements();
2448 CheckElementOrientation(fix_orientation);
2452 MarkForRefinement();
2464 GetElementToFaceTable();
2467 if ( !(curved && (meshgen & 1)) )
2469 CheckBdrElementOrientation();
2478 if (Dim > 1 && generate_edges == 1)
2481 if (!el_to_edge) { el_to_edge =
new Table; }
2482 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2486 if (NumOfBdrElements == 0)
2488 GenerateBoundaryElements();
2491 if ( !(curved && (meshgen & 1)) )
2493 CheckBdrElementOrientation();
2505 ncmesh->OnMeshUpdated(
this);
2508 GenerateNCFaceInfo();
2520 spaceDim = Nodes->VectorDim();
2522 for (i = 0; i < spaceDim; i++)
2525 Nodes->GetNodalValues(vert_val, i+1);
2526 for (j = 0; j < NumOfVertices; j++)
2528 vertices[j](i) = vert_val(j);
2537 Table *old_elem_vert = NULL;
2538 if (fix_orientation || refine)
2540 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
2545 CheckElementOrientation(fix_orientation);
2548 MarkForRefinement();
2551 if (fix_orientation || refine)
2553 DoNodeReorder(old_v_to_v, old_elem_vert);
2554 delete old_elem_vert;
2558 Nodes->FESpace()->RebuildElementToDofTable();
2565 if (ncmesh) { ncmesh->spaceDim = spaceDim; }
2568 Mesh::Mesh(
Mesh *mesh_array[],
int num_pieces)
2570 int i, j, ie, ib, iv, *v, nv;
2580 BaseGeom = mesh_array[0]->
BaseGeom;
2583 if (mesh_array[0]->NURBSext)
2588 NumOfVertices = NURBSext->GetNV();
2589 NumOfElements = NURBSext->GetNE();
2591 NURBSext->GetElementTopo(elements);
2604 NumOfBdrElements = 0;
2605 for (i = 0; i < num_pieces; i++)
2607 NumOfBdrElements += mesh_array[i]->
GetNBE();
2609 boundary.SetSize(NumOfBdrElements);
2610 vertices.SetSize(NumOfVertices);
2612 for (i = 0; i < num_pieces; i++)
2618 for (j = 0; j < m->
GetNE(); j++)
2620 elements[lelem_elem[j]]->SetAttribute(m->
GetAttribute(j));
2623 for (j = 0; j < m->
GetNBE(); j++)
2628 for (
int k = 0; k < nv; k++)
2630 v[k] = lvert_vert[v[k]];
2632 boundary[ib++] = el;
2635 for (j = 0; j < m->
GetNV(); j++)
2637 vertices[lvert_vert[j]].SetCoords(m->
GetVertex(j));
2644 NumOfBdrElements = 0;
2646 for (i = 0; i < num_pieces; i++)
2649 NumOfElements += m->
GetNE();
2650 NumOfBdrElements += m->
GetNBE();
2651 NumOfVertices += m->
GetNV();
2653 elements.SetSize(NumOfElements);
2654 boundary.SetSize(NumOfBdrElements);
2655 vertices.SetSize(NumOfVertices);
2657 for (i = 0; i < num_pieces; i++)
2661 for (j = 0; j < m->
GetNE(); j++)
2666 for (
int k = 0; k < nv; k++)
2670 elements[ie++] = el;
2673 for (j = 0; j < m->
GetNBE(); j++)
2678 for (
int k = 0; k < nv; k++)
2682 boundary[ib++] = el;
2685 for (j = 0; j < m->
GetNV(); j++)
2687 vertices[iv++].SetCoords(m->
GetVertex(j));
2694 for (i = 0; i < num_pieces; i++)
2702 GetElementToFaceTable();
2713 el_to_edge =
new Table;
2714 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2733 for (i = 0; i < num_pieces; i++)
2735 gf_array[i] = mesh_array[i]->
GetNodes();
2742 CheckElementOrientation(
false);
2743 CheckBdrElementOrientation(
false);
2749 if (NURBSext == NULL)
2751 mfem_error(
"Mesh::KnotInsert : Not a NURBS mesh!");
2754 if (kv.
Size() != NURBSext->GetNKV())
2756 mfem_error(
"Mesh::KnotInsert : KnotVector array size mismatch!");
2759 NURBSext->ConvertToPatches(*Nodes);
2761 NURBSext->KnotInsert(kv);
2766 void Mesh::NURBSUniformRefinement()
2769 NURBSext->ConvertToPatches(*Nodes);
2771 NURBSext->UniformRefinement();
2773 last_operation = Mesh::REFINE;
2779 void Mesh::DegreeElevate(
int t)
2781 if (NURBSext == NULL)
2783 mfem_error(
"Mesh::DegreeElevate : Not a NURBS mesh!");
2786 NURBSext->ConvertToPatches(*Nodes);
2788 NURBSext->DegreeElevate(t);
2801 void Mesh::UpdateNURBS()
2803 NURBSext->SetKnotsFromPatches();
2805 Dim = NURBSext->Dimension();
2808 if (NumOfElements != NURBSext->GetNE())
2810 for (
int i = 0; i < elements.Size(); i++)
2812 FreeElement(elements[i]);
2814 NumOfElements = NURBSext->GetNE();
2815 NURBSext->GetElementTopo(elements);
2818 if (NumOfBdrElements != NURBSext->GetNBE())
2820 for (
int i = 0; i < boundary.Size(); i++)
2822 FreeElement(boundary[i]);
2824 NumOfBdrElements = NURBSext->GetNBE();
2825 NURBSext->GetBdrElementTopo(boundary);
2828 Nodes->FESpace()->Update();
2830 NURBSext->SetCoordsFromPatches(*Nodes);
2832 if (NumOfVertices != NURBSext->GetNV())
2834 NumOfVertices = NURBSext->GetNV();
2835 vertices.SetSize(NumOfVertices);
2836 int vd = Nodes->VectorDim();
2837 for (
int i = 0; i < vd; i++)
2840 Nodes->GetNodalValues(vert_val, i+1);
2841 for (
int j = 0; j < NumOfVertices; j++)
2843 vertices[j](i) = vert_val(j);
2850 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2859 GetElementToFaceTable();
2864 void Mesh::LoadPatchTopo(std::istream &input,
Array<int> &edge_to_knot)
2874 skip_comment_lines(input,
'#');
2880 skip_comment_lines(input,
'#');
2883 input >> NumOfElements;
2884 elements.SetSize(NumOfElements);
2885 for (j = 0; j < NumOfElements; j++)
2887 elements[j] = ReadElement(input);
2890 skip_comment_lines(input,
'#');
2893 input >> NumOfBdrElements;
2894 boundary.SetSize(NumOfBdrElements);
2895 for (j = 0; j < NumOfBdrElements; j++)
2897 boundary[j] = ReadElement(input);
2900 skip_comment_lines(input,
'#');
2903 input >> NumOfEdges;
2904 edge_vertex =
new Table(NumOfEdges, 2);
2905 edge_to_knot.
SetSize(NumOfEdges);
2906 for (j = 0; j < NumOfEdges; j++)
2908 int *v = edge_vertex->GetRow(j);
2909 input >> edge_to_knot[j] >> v[0] >> v[1];
2912 edge_to_knot[j] = -1 - edge_to_knot[j];
2916 skip_comment_lines(input,
'#');
2919 input >> NumOfVertices;
2920 vertices.SetSize(0);
2929 GetElementToFaceTable();
2931 if (NumOfBdrElements == 0)
2933 GenerateBoundaryElements();
2935 CheckBdrElementOrientation();
2945 el_to_edge =
new Table;
2946 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
2950 if (NumOfBdrElements == 0)
2952 GenerateBoundaryElements();
2954 CheckBdrElementOrientation();
2970 for (
int d = 0; d < v.
Size(); d++)
2978 for (d = 0; d < p.
Size(); d++)
2982 for ( ; d < v.
Size(); d++)
2991 if (Nodes == NULL || Nodes->FESpace() != nodes.
FESpace())
3006 SetNodalGridFunction(nodes,
true);
3012 NewNodes(*nodes, make_owner);
3017 return ((Nodes) ? Nodes->FESpace() : NULL);
3020 void Mesh::SetCurvature(
int order,
bool discont,
int space_dim,
int ordering)
3022 space_dim = (space_dim == -1) ? spaceDim : space_dim;
3035 SetNodalFESpace(nfes);
3036 Nodes->MakeOwner(nfec);
3039 int Mesh::GetNumFaces()
const
3043 case 1:
return GetNV();
3044 case 2:
return GetNEdges();
3045 case 3:
return GetNFaces();
3050 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3051 static const char *fixed_or_not[] = {
"fixed",
"NOT FIXED" };
3054 void Mesh::CheckElementOrientation(
bool fix_it)
3056 int i, j, k, wo = 0, fo = 0, *vi = 0;
3059 if (Dim == 2 && spaceDim == 2)
3063 for (i = 0; i < NumOfElements; i++)
3067 vi = elements[i]->GetVertices();
3068 for (j = 0; j < 3; j++)
3070 v[j] = vertices[vi[j]]();
3072 for (j = 0; j < 2; j++)
3073 for (k = 0; k < 2; k++)
3075 J(j, k) = v[j+1][k] - v[0][k];
3081 GetElementJacobian(i, J);
3087 switch (GetElementType(i))
3089 case Element::TRIANGLE:
3092 case Element::QUADRILATERAL:
3107 for (i = 0; i < NumOfElements; i++)
3109 vi = elements[i]->GetVertices();
3110 switch (GetElementType(i))
3112 case Element::TETRAHEDRON:
3115 for (j = 0; j < 4; j++)
3117 v[j] = vertices[vi[j]]();
3119 for (j = 0; j < 3; j++)
3120 for (k = 0; k < 3; k++)
3122 J(j, k) = v[j+1][k] - v[0][k];
3128 GetElementJacobian(i, J);
3141 case Element::HEXAHEDRON:
3143 GetElementJacobian(i, J);
3156 #if (!defined(MFEM_USE_MPI) || defined(MFEM_DEBUG))
3158 cout <<
"Elements with wrong orientation: " << wo <<
" / "
3159 << NumOfElements <<
" (" << fixed_or_not[(wo == fo) ? 0 : 1]
3164 int Mesh::GetTriOrientation(
const int *base,
const int *test)
3172 if (test[0] == base[0])
3173 if (test[1] == base[1])
3181 else if (test[0] == base[1])
3182 if (test[1] == base[0])
3191 if (test[1] == base[0])
3201 const int *aor = tri_t::Orient[orient];
3202 for (
int j = 0; j < 3; j++)
3203 if (test[aor[j]] != base[j])
3212 int Mesh::GetQuadOrientation(
const int *base,
const int *test)
3216 for (i = 0; i < 4; i++)
3217 if (test[i] == base[0])
3224 if (test[(i+1)%4] == base[1])
3232 const int *aor = quad_t::Orient[orient];
3233 for (
int j = 0; j < 4; j++)
3234 if (test[aor[j]] != base[j])
3236 cerr <<
"Mesh::GetQuadOrientation(...)" << endl;
3237 cerr <<
" base = [";
3238 for (
int k = 0; k < 4; k++)
3240 cerr <<
" " << base[k];
3242 cerr <<
" ]\n test = [";
3243 for (
int k = 0; k < 4; k++)
3245 cerr <<
" " << test[k];
3247 cerr <<
" ]" << endl;
3252 if (test[(i+1)%4] == base[1])
3260 void Mesh::CheckBdrElementOrientation(
bool fix_it)
3266 for (i = 0; i < NumOfBdrElements; i++)
3268 if (faces_info[be_to_edge[i]].Elem2No < 0)
3270 int *bv = boundary[i]->GetVertices();
3271 int *fv = faces[be_to_edge[i]]->GetVertices();
3276 mfem::Swap<int>(bv[0], bv[1]);
3289 for (i = 0; i < NumOfBdrElements; i++)
3291 if (faces_info[be_to_face[i]].Elem2No < 0)
3294 bv = boundary[i]->GetVertices();
3295 el = faces_info[be_to_face[i]].Elem1No;
3296 ev = elements[el]->GetVertices();
3297 switch (GetElementType(el))
3299 case Element::TETRAHEDRON:
3301 int *fv = faces[be_to_face[i]]->GetVertices();
3304 orientation = GetTriOrientation(fv, bv);
3305 if (orientation % 2)
3311 mfem::Swap<int>(bv[0], bv[1]);
3318 case Element::HEXAHEDRON:
3320 int lf = faces_info[be_to_face[i]].Elem1Inf/64;
3321 for (
int j = 0; j < 4; j++)
3323 v[j] = ev[hex_t::FaceVert[lf][j]];
3325 if (GetQuadOrientation(v, bv) % 2)
3329 mfem::Swap<int>(bv[0], bv[2]);
3343 cout <<
"Boundary elements with wrong orientation: " << wo <<
" / "
3344 << NumOfBdrElements <<
" (" << fixed_or_not[fix_it ? 0 : 1]
3354 el_to_edge->GetRow(i, edges);
3358 mfem_error(
"Mesh::GetElementEdges(...) element to edge table "
3359 "is not generated.");
3362 const int *v = elements[i]->GetVertices();
3363 const int ne = elements[i]->GetNEdges();
3365 for (
int j = 0; j < ne; j++)
3367 const int *e = elements[i]->GetEdgeVertices(j);
3368 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3378 edges[0] = be_to_edge[i];
3379 const int *v = boundary[i]->GetVertices();
3380 cor[0] = (v[0] < v[1]) ? (1) : (-1);
3386 bel_to_edge->GetRow(i, edges);
3393 const int *v = boundary[i]->GetVertices();
3394 const int ne = boundary[i]->GetNEdges();
3396 for (
int j = 0; j < ne; j++)
3398 const int *e = boundary[i]->GetEdgeVertices(j);
3399 cor[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3411 const int *v = faces[i]->GetVertices();
3412 o[0] = (v[0] < v[1]) ? (1) : (-1);
3422 face_edge->GetRow(i, edges);
3424 const int *v = faces[i]->GetVertices();
3425 const int ne = faces[i]->GetNEdges();
3427 for (
int j = 0; j < ne; j++)
3429 const int *e = faces[i]->GetEdgeVertices(j);
3430 o[j] = (v[e[0]] < v[e[1]]) ? (1) : (-1);
3438 GetEdgeVertexTable();
3439 edge_vertex->GetRow(i, vert);
3455 if (faces.Size() != NumOfFaces)
3457 mfem_error(
"Mesh::GetFaceEdgeTable : faces were not generated!");
3461 DSTable v_to_v(NumOfVertices);
3462 GetVertexToVertexTable(v_to_v);
3464 face_edge =
new Table;
3465 GetElementArrayEdgeTable(faces, v_to_v, *face_edge);
3477 DSTable v_to_v(NumOfVertices);
3478 GetVertexToVertexTable(v_to_v);
3481 edge_vertex =
new Table(nedges, 2);
3482 for (
int i = 0; i < NumOfVertices; i++)
3487 edge_vertex->Push(j, i);
3488 edge_vertex->Push(j, it.Column());
3491 edge_vertex->Finalize();
3502 vert_elem->
MakeI(NumOfVertices);
3504 for (i = 0; i < NumOfElements; i++)
3506 nv = elements[i]->GetNVertices();
3507 v = elements[i]->GetVertices();
3508 for (j = 0; j < nv; j++)
3516 for (i = 0; i < NumOfElements; i++)
3518 nv = elements[i]->GetNVertices();
3519 v = elements[i]->GetVertices();
3520 for (j = 0; j < nv; j++)
3531 Table *Mesh::GetFaceToElementTable()
const
3535 face_elem->
MakeI(faces_info.Size());
3537 for (
int i = 0; i < faces_info.Size(); i++)
3539 if (faces_info[i].Elem2No >= 0)
3551 for (
int i = 0; i < faces_info.Size(); i++)
3554 if (faces_info[i].Elem2No >= 0)
3572 el_to_face->
GetRow(i, fcs);
3576 mfem_error(
"Mesh::GetElementFaces(...) : el_to_face not generated.");
3581 for (j = 0; j < n; j++)
3582 if (faces_info[fcs[j]].Elem1No == i)
3584 cor[j] = faces_info[fcs[j]].Elem1Inf % 64;
3587 else if (faces_info[fcs[j]].Elem2No == i)
3589 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3593 mfem_error(
"Mesh::GetElementFaces(...) : 2");
3598 cor[j] = faces_info[fcs[j]].Elem2Inf % 64;
3603 void Mesh::GetBdrElementFace(
int i,
int *f,
int *o)
const
3608 bv = boundary[i]->GetVertices();
3609 fv = faces[be_to_face[i]]->GetVertices();
3613 switch (GetBdrElementType(i))
3615 case Element::TRIANGLE:
3616 *o = GetTriOrientation(fv, bv);
3618 case Element::QUADRILATERAL:
3619 *o = GetQuadOrientation(fv, bv);
3622 mfem_error(
"Mesh::GetBdrElementFace(...) 2");
3626 int Mesh::GetFaceBaseGeometry(
int i)
const
3629 switch (GetElementType(0))
3631 case Element::SEGMENT:
3632 return Geometry::POINT;
3634 case Element::TRIANGLE:
3635 case Element::QUADRILATERAL:
3636 return Geometry::SEGMENT;
3638 case Element::TETRAHEDRON:
3639 return Geometry::TRIANGLE;
3640 case Element::HEXAHEDRON:
3641 return Geometry::SQUARE;
3643 mfem_error(
"Mesh::GetFaceBaseGeometry(...) #1");
3648 int Mesh::GetBdrElementEdgeIndex(
int i)
const
3652 case 1:
return boundary[i]->GetVertices()[0];
3653 case 2:
return be_to_edge[i];
3654 case 3:
return be_to_face[i];
3655 default:
mfem_error(
"Mesh::GetBdrElementEdgeIndex: invalid dimension!");
3660 void Mesh::GetBdrElementAdjacentElement(
int bdr_el,
int &el,
int &info)
const
3662 int fid = GetBdrElementEdgeIndex(bdr_el);
3663 const FaceInfo &fi = faces_info[fid];
3664 MFEM_ASSERT(fi.
Elem1Inf%64 == 0,
"internal error");
3665 const int *fv = (Dim > 1) ? faces[fid]->GetVertices() : NULL;
3666 const int *bv = boundary[bdr_el]->GetVertices();
3668 switch (GetBdrElementBaseGeometry(bdr_el))
3670 case Geometry::POINT: ori = 0;
break;
3671 case Geometry::SEGMENT: ori = (fv[0] == bv[0]) ? 0 : 1;
break;
3672 case Geometry::TRIANGLE: ori = GetTriOrientation(fv, bv);
break;
3673 case Geometry::SQUARE: ori = GetQuadOrientation(fv, bv);
break;
3674 default: MFEM_ABORT(
"boundary element type not implemented"); ori = 0;
3680 int Mesh::GetElementType(
int i)
const
3682 return elements[i]->GetType();
3685 int Mesh::GetBdrElementType(
int i)
const
3687 return boundary[i]->GetType();
3695 v = elements[i]->GetVertices();
3696 nv = elements[i]->GetNVertices();
3698 pointmat.
SetSize(spaceDim, nv);
3699 for (k = 0; k < spaceDim; k++)
3700 for (j = 0; j < nv; j++)
3702 pointmat(k, j) = vertices[v[j]](k);
3711 v = boundary[i]->GetVertices();
3712 nv = boundary[i]->GetNVertices();
3714 pointmat.
SetSize(spaceDim, nv);
3715 for (k = 0; k < spaceDim; k++)
3716 for (j = 0; j < nv; j++)
3718 pointmat(k, j) = vertices[v[j]](k);
3722 double Mesh::GetLength(
int i,
int j)
const
3724 const double *vi = vertices[i]();
3725 const double *vj = vertices[j]();
3728 for (
int k = 0; k < spaceDim; k++)
3730 length += (vi[k]-vj[k])*(vi[k]-vj[k]);
3733 return sqrt(length);
3741 for (
int i = 0; i < elem_array.
Size(); i++)
3746 for (
int i = 0; i < elem_array.
Size(); i++)
3748 const int *v = elem_array[i]->GetVertices();
3749 const int ne = elem_array[i]->GetNEdges();
3750 for (
int j = 0; j < ne; j++)
3752 const int *e = elem_array[i]->GetEdgeVertices(j);
3759 void Mesh::GetVertexToVertexTable(
DSTable &v_to_v)
const
3763 for (
int i = 0; i < edge_vertex->Size(); i++)
3765 const int *v = edge_vertex->GetRow(i);
3766 v_to_v.
Push(v[0], v[1]);
3771 for (
int i = 0; i < NumOfElements; i++)
3773 const int *v = elements[i]->GetVertices();
3774 const int ne = elements[i]->GetNEdges();
3775 for (
int j = 0; j < ne; j++)
3777 const int *e = elements[i]->GetEdgeVertices(j);
3778 v_to_v.
Push(v[e[0]], v[e[1]]);
3786 int i, NumberOfEdges;
3788 DSTable v_to_v(NumOfVertices);
3789 GetVertexToVertexTable(v_to_v);
3794 GetElementArrayEdgeTable(elements, v_to_v, e_to_f);
3799 be_to_f.
SetSize(NumOfBdrElements);
3800 for (i = 0; i < NumOfBdrElements; i++)
3802 const int *v = boundary[i]->GetVertices();
3803 be_to_f[i] = v_to_v(v[0], v[1]);
3808 if (bel_to_edge == NULL)
3810 bel_to_edge =
new Table;
3812 GetElementArrayEdgeTable(boundary, v_to_v, *bel_to_edge);
3816 mfem_error(
"1D GetElementToEdgeTable is not yet implemented.");
3820 return NumberOfEdges;
3823 const Table & Mesh::ElementToElementTable()
3830 int num_faces = GetNumFaces();
3831 MFEM_ASSERT(faces_info.Size() == num_faces,
"faces were not generated!");
3836 for (
int i = 0; i < faces_info.Size(); i++)
3838 const FaceInfo &fi = faces_info[i];
3848 el_to_el =
new Table(NumOfElements, conn);
3853 const Table & Mesh::ElementToFaceTable()
const
3855 if (el_to_face == NULL)
3862 const Table & Mesh::ElementToEdgeTable()
const
3864 if (el_to_edge == NULL)
3871 void Mesh::AddPointFaceElement(
int lf,
int gf,
int el)
3873 if (faces_info[gf].Elem1No == -1)
3876 faces_info[gf].Elem1No = el;
3877 faces_info[gf].Elem1Inf = 64 * lf;
3878 faces_info[gf].Elem2No = -1;
3879 faces_info[gf].Elem2Inf = -1;
3883 faces_info[gf].Elem2No = el;
3884 faces_info[gf].Elem2Inf = 64 * lf + 1;
3888 void Mesh::AddSegmentFaceElement(
int lf,
int gf,
int el,
int v0,
int v1)
3890 if (faces[gf] == NULL)
3892 faces[gf] =
new Segment(v0, v1);
3893 faces_info[gf].Elem1No = el;
3894 faces_info[gf].Elem1Inf = 64 * lf;
3895 faces_info[gf].Elem2No = -1;
3896 faces_info[gf].Elem2Inf = -1;
3900 int *v = faces[gf]->GetVertices();
3901 faces_info[gf].Elem2No = el;
3902 if ( v[1] == v0 && v[0] == v1 )
3904 faces_info[gf].Elem2Inf = 64 * lf + 1;
3906 else if ( v[0] == v0 && v[1] == v1 )
3908 faces_info[gf].Elem2Inf = 64 * lf;
3912 MFEM_ASSERT((v[1] == v0 && v[0] == v1)||
3913 (v[0] == v0 && v[1] == v1),
"");
3918 void Mesh::AddTriangleFaceElement(
int lf,
int gf,
int el,
3919 int v0,
int v1,
int v2)
3921 if (faces[gf] == NULL)
3923 faces[gf] =
new Triangle(v0, v1, v2);
3924 faces_info[gf].Elem1No = el;
3925 faces_info[gf].Elem1Inf = 64 * lf;
3926 faces_info[gf].Elem2No = -1;
3927 faces_info[gf].Elem2Inf = -1;
3931 int orientation, vv[3] = { v0, v1, v2 };
3932 orientation = GetTriOrientation(faces[gf]->GetVertices(), vv);
3933 MFEM_ASSERT(orientation % 2 != 0,
"");
3934 faces_info[gf].Elem2No = el;
3935 faces_info[gf].Elem2Inf = 64 * lf + orientation;
3939 void Mesh::AddQuadFaceElement(
int lf,
int gf,
int el,
3940 int v0,
int v1,
int v2,
int v3)
3942 if (faces_info[gf].Elem1No < 0)
3945 faces_info[gf].Elem1No = el;
3946 faces_info[gf].Elem1Inf = 64 * lf;
3947 faces_info[gf].Elem2No = -1;
3948 faces_info[gf].Elem2Inf = -1;
3952 int vv[4] = { v0, v1, v2, v3 };
3953 int oo = GetQuadOrientation(faces[gf]->GetVertices(), vv);
3954 MFEM_ASSERT(oo % 2 != 0,
"");
3955 faces_info[gf].Elem2No = el;
3956 faces_info[gf].Elem2Inf = 64 * lf + oo;
3960 void Mesh::GenerateFaces()
3962 int i, nfaces = GetNumFaces();
3964 for (i = 0; i < faces.Size(); i++)
3966 FreeElement(faces[i]);
3970 faces.SetSize(nfaces);
3971 faces_info.SetSize(nfaces);
3972 for (i = 0; i < nfaces; i++)
3975 faces_info[i].Elem1No = -1;
3976 faces_info[i].NCFace = -1;
3978 for (i = 0; i < NumOfElements; i++)
3980 const int *v = elements[i]->GetVertices();
3984 AddPointFaceElement(0, v[0], i);
3985 AddPointFaceElement(1, v[1], i);
3989 ef = el_to_edge->GetRow(i);
3990 const int ne = elements[i]->GetNEdges();
3991 for (
int j = 0; j < ne; j++)
3993 const int *e = elements[i]->GetEdgeVertices(j);
3994 AddSegmentFaceElement(j, ef[j], i, v[e[0]], v[e[1]]);
3999 ef = el_to_face->GetRow(i);
4000 switch (GetElementType(i))
4002 case Element::TETRAHEDRON:
4004 for (
int j = 0; j < 4; j++)
4006 const int *fv = tet_t::FaceVert[j];
4007 AddTriangleFaceElement(j, ef[j], i,
4008 v[fv[0]], v[fv[1]], v[fv[2]]);
4012 case Element::HEXAHEDRON:
4014 for (
int j = 0; j < 6; j++)
4016 const int *fv = hex_t::FaceVert[j];
4017 AddQuadFaceElement(j, ef[j], i,
4018 v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4023 MFEM_ABORT(
"Unexpected type of Element.");
4029 void Mesh::GenerateNCFaceInfo()
4031 MFEM_VERIFY(ncmesh,
"missing NCMesh.");
4033 for (
int i = 0; i < faces_info.Size(); i++)
4035 faces_info[i].NCFace = -1;
4039 (Dim == 2) ? ncmesh->GetEdgeList() : ncmesh->GetFaceList();
4041 nc_faces_info.SetSize(0);
4042 nc_faces_info.Reserve(list.
masters.size() + list.
slaves.size());
4044 int nfaces = GetNumFaces();
4047 for (
unsigned i = 0; i < list.
masters.size(); i++)
4050 if (master.
index >= nfaces) {
continue; }
4052 faces_info[master.
index].NCFace = nc_faces_info.Size();
4058 for (
unsigned i = 0; i < list.
slaves.size(); i++)
4061 if (slave.
index >= nfaces || slave.
master >= nfaces) {
continue; }
4067 slave_fi.
NCFace = nc_faces_info.Size();
4079 for (
int i = 0; i < NumOfElements; i++)
4081 const int *v = elements[i]->GetVertices();
4082 switch (GetElementType(i))
4084 case Element::TETRAHEDRON:
4086 for (
int j = 0; j < 4; j++)
4088 const int *fv = tet_t::FaceVert[j];
4089 faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
4093 case Element::HEXAHEDRON:
4097 for (
int j = 0; j < 6; j++)
4099 const int *fv = hex_t::FaceVert[j];
4100 faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
4105 MFEM_ABORT(
"Unexpected type of Element.");
4116 if (el_to_face != NULL)
4120 el_to_face =
new Table(NumOfElements, 6);
4121 faces_tbl =
new STable3D(NumOfVertices);
4122 for (i = 0; i < NumOfElements; i++)
4124 v = elements[i]->GetVertices();
4125 switch (GetElementType(i))
4127 case Element::TETRAHEDRON:
4129 for (
int j = 0; j < 4; j++)
4131 const int *fv = tet_t::FaceVert[j];
4133 i, faces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]));
4137 case Element::HEXAHEDRON:
4141 for (
int j = 0; j < 6; j++)
4143 const int *fv = hex_t::FaceVert[j];
4145 i, faces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]));
4150 MFEM_ABORT(
"Unexpected type of Element.");
4153 el_to_face->Finalize();
4155 be_to_face.SetSize(NumOfBdrElements);
4156 for (i = 0; i < NumOfBdrElements; i++)
4158 v = boundary[i]->GetVertices();
4159 switch (GetBdrElementType(i))
4161 case Element::TRIANGLE:
4163 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2]);
4166 case Element::QUADRILATERAL:
4168 be_to_face[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
4172 MFEM_ABORT(
"Unexpected type of boundary Element.");
4184 void Mesh::ReorientTetMesh()
4188 if (Dim != 3 || !(meshgen & 1))
4194 Table *old_elem_vert = NULL;
4198 PrepareNodeReorder(&old_v_to_v, &old_elem_vert);
4201 for (
int i = 0; i < NumOfElements; i++)
4203 if (GetElementType(i) == Element::TETRAHEDRON)
4205 v = elements[i]->GetVertices();
4207 Rotate3(v[0], v[1], v[2]);
4210 Rotate3(v[1], v[2], v[3]);
4214 ShiftL2R(v[0], v[1], v[3]);
4219 for (
int i = 0; i < NumOfBdrElements; i++)
4221 if (GetBdrElementType(i) == Element::TRIANGLE)
4223 v = boundary[i]->GetVertices();
4225 Rotate3(v[0], v[1], v[2]);
4231 GetElementToFaceTable();
4235 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
4240 DoNodeReorder(old_v_to_v, old_elem_vert);
4241 delete old_elem_vert;
4244 Nodes->FESpace()->RebuildElementToDofTable();
4250 static int mfem_less(
const void *x,
const void *y)
4252 if (*(
int*)x < *(
int*)y)
4256 if (*(
int*)x > *(
int*)y)
4262 #ifndef MFEM_USE_METIS_5
4267 int*,
int*,
int*,
int*,
int*,
idxtype*);
4269 int*,
int*,
int*,
int*,
int*,
idxtype*);
4271 int*,
int*,
int*,
int*,
int*,
idxtype*);
4293 int *Mesh::CartesianPartitioning(
int nxyz[])
4296 double pmin[3] = { numeric_limits<double>::infinity(),
4297 numeric_limits<double>::infinity(),
4298 numeric_limits<double>::infinity()
4300 double pmax[3] = { -numeric_limits<double>::infinity(),
4301 -numeric_limits<double>::infinity(),
4302 -numeric_limits<double>::infinity()
4305 for (
int vi = 0; vi < NumOfVertices; vi++)
4307 const double *p = vertices[vi]();
4308 for (
int i = 0; i < spaceDim; i++)
4310 if (p[i] < pmin[i]) { pmin[i] = p[i]; }
4311 if (p[i] > pmax[i]) { pmax[i] = p[i]; }
4315 partitioning =
new int[NumOfElements];
4319 Vector pt(ppt, spaceDim);
4320 for (
int el = 0; el < NumOfElements; el++)
4322 GetElementTransformation(el)->Transform(
4325 for (
int i = spaceDim-1; i >= 0; i--)
4327 int idx = (int)floor(nxyz[i]*((pt(i) - pmin[i])/(pmax[i] - pmin[i])));
4328 if (idx < 0) { idx = 0; }
4329 if (idx >= nxyz[i]) { idx = nxyz[i]-1; }
4330 part = part * nxyz[i] + idx;
4332 partitioning[el] = part;
4335 return partitioning;
4338 int *Mesh::GeneratePartitioning(
int nparts,
int part_method)
4341 int i, *partitioning;
4343 ElementToElementTable();
4345 partitioning =
new int[NumOfElements];
4349 for (i = 0; i < NumOfElements; i++)
4351 partitioning[i] = 0;
4357 #ifndef MFEM_USE_METIS_5
4369 I = el_to_el->GetI();
4370 J = el_to_el->GetJ();
4371 #ifndef MFEM_USE_METIS_5
4379 if (part_method >= 0 && part_method <= 2)
4380 for (i = 0; i < n; i++)
4382 qsort(&J[I[i]], I[i+1]-I[i],
sizeof(
int), &mfem_less);
4387 if (part_method == 0 || part_method == 3)
4389 #ifndef MFEM_USE_METIS_5
4417 " error in METIS_PartGraphRecursive!");
4423 if (part_method == 1 || part_method == 4)
4425 #ifndef MFEM_USE_METIS_5
4453 " error in METIS_PartGraphKway!");
4459 if (part_method == 2 || part_method == 5)
4461 #ifndef MFEM_USE_METIS_5
4490 " error in METIS_PartGraphKway!");
4495 cout <<
"Mesh::GeneratePartitioning(...): edgecut = "
4509 for (i = 0; i < nparts; i++)
4515 for (i = 0; i < NumOfElements; i++)
4517 psize[partitioning[i]].one++;
4520 int empty_parts = 0;
4521 for (i = 0; i < nparts; i++)
4522 if (psize[i].one == 0)
4531 cerr <<
"Mesh::GeneratePartitioning returned " << empty_parts
4532 <<
" empty parts!" << endl;
4534 SortPairs<int,int>(psize, nparts);
4536 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4541 for (
int j = 0; j < NumOfElements; j++)
4542 for (i = nparts-1; i > nparts-1-empty_parts; i--)
4543 if (psize[i].one == 0 || partitioning[j] != psize[i].two)
4549 partitioning[j] = psize[nparts-1-i].two;
4555 return partitioning;
4559 mfem_error(
"Mesh::GeneratePartitioning(...): "
4560 "MFEM was compiled without Metis.");
4574 int num_elem, *i_elem_elem, *j_elem_elem;
4576 num_elem = elem_elem.
Size();
4577 i_elem_elem = elem_elem.
GetI();
4578 j_elem_elem = elem_elem.
GetJ();
4583 int stack_p, stack_top_p, elem;
4587 for (i = 0; i < num_elem; i++)
4589 if (partitioning[i] > num_part)
4591 num_part = partitioning[i];
4598 for (i = 0; i < num_part; i++)
4605 for (elem = 0; elem < num_elem; elem++)
4607 if (component[elem] >= 0)
4612 component[elem] = num_comp[partitioning[elem]]++;
4614 elem_stack[stack_top_p++] = elem;
4616 for ( ; stack_p < stack_top_p; stack_p++)
4618 i = elem_stack[stack_p];
4619 for (j = i_elem_elem[i]; j < i_elem_elem[i+1]; j++)
4622 if (partitioning[k] == partitioning[i])
4624 if (component[k] < 0)
4626 component[k] = component[i];
4627 elem_stack[stack_top_p++] = k;
4629 else if (component[k] != component[i])
4639 void Mesh::CheckPartitioning(
int *partitioning)
4641 int i, n_empty, n_mcomp;
4643 const Array<int> _partitioning(partitioning, GetNE());
4645 ElementToElementTable();
4649 n_empty = n_mcomp = 0;
4650 for (i = 0; i < num_comp.
Size(); i++)
4651 if (num_comp[i] == 0)
4655 else if (num_comp[i] > 1)
4662 cout <<
"Mesh::CheckPartitioning(...) :\n"
4663 <<
"The following subdomains are empty :\n";
4664 for (i = 0; i < num_comp.
Size(); i++)
4665 if (num_comp[i] == 0)
4673 cout <<
"Mesh::CheckPartitioning(...) :\n"
4674 <<
"The following subdomains are NOT connected :\n";
4675 for (i = 0; i < num_comp.
Size(); i++)
4676 if (num_comp[i] > 1)
4682 if (n_empty == 0 && n_mcomp == 0)
4683 cout <<
"Mesh::CheckPartitioning(...) : "
4684 "All subdomains are connected." << endl;
4698 const double *a = A.
Data();
4699 const double *b = B.
Data();
4708 c(0) = a[0]*a[3]-a[1]*a[2];
4709 c(1) = a[0]*b[3]-a[1]*b[2]+b[0]*a[3]-b[1]*a[2];
4710 c(2) = b[0]*b[3]-b[1]*b[2];
4731 c(0) = (a[0] * (a[4] * a[8] - a[5] * a[7]) +
4732 a[1] * (a[5] * a[6] - a[3] * a[8]) +
4733 a[2] * (a[3] * a[7] - a[4] * a[6]));
4735 c(1) = (b[0] * (a[4] * a[8] - a[5] * a[7]) +
4736 b[1] * (a[5] * a[6] - a[3] * a[8]) +
4737 b[2] * (a[3] * a[7] - a[4] * a[6]) +
4739 a[0] * (b[4] * a[8] - b[5] * a[7]) +
4740 a[1] * (b[5] * a[6] - b[3] * a[8]) +
4741 a[2] * (b[3] * a[7] - b[4] * a[6]) +
4743 a[0] * (a[4] * b[8] - a[5] * b[7]) +
4744 a[1] * (a[5] * b[6] - a[3] * b[8]) +
4745 a[2] * (a[3] * b[7] - a[4] * b[6]));
4747 c(2) = (a[0] * (b[4] * b[8] - b[5] * b[7]) +
4748 a[1] * (b[5] * b[6] - b[3] * b[8]) +
4749 a[2] * (b[3] * b[7] - b[4] * b[6]) +
4751 b[0] * (a[4] * b[8] - a[5] * b[7]) +
4752 b[1] * (a[5] * b[6] - a[3] * b[8]) +
4753 b[2] * (a[3] * b[7] - a[4] * b[6]) +
4755 b[0] * (b[4] * a[8] - b[5] * a[7]) +
4756 b[1] * (b[5] * a[6] - b[3] * a[8]) +
4757 b[2] * (b[3] * a[7] - b[4] * a[6]));
4759 c(3) = (b[0] * (b[4] * b[8] - b[5] * b[7]) +
4760 b[1] * (b[5] * b[6] - b[3] * b[8]) +
4761 b[2] * (b[3] * b[7] - b[4] * b[6]));
4807 double a = z(2), b = z(1), c = z(0);
4808 double D = b*b-4*a*c;
4815 x(0) = x(1) = -0.5 * b / a;
4820 x(0) = -(x(1) = fabs(0.5 * sqrt(D) / a));
4828 t = -0.5 * (b + sqrt(D));
4832 t = -0.5 * (b - sqrt(D));
4838 Swap<double>(x(0), x(1));
4846 double a = z(2)/z(3), b = z(1)/z(3), c = z(0)/z(3);
4849 double Q = (a * a - 3 * b) / 9;
4850 double R = (2 * a * a * a - 9 * a * b + 27 * c) / 54;
4851 double Q3 = Q * Q * Q;
4858 x(0) = x(1) = x(2) = - a / 3;
4862 double sqrtQ = sqrt(Q);
4866 x(0) = -2 * sqrtQ - a / 3;
4867 x(1) = x(2) = sqrtQ - a / 3;
4871 x(0) = x(1) = - sqrtQ - a / 3;
4872 x(2) = 2 * sqrtQ - a / 3;
4879 double theta = acos(R / sqrt(Q3));
4880 double A = -2 * sqrt(Q);
4882 x0 = A * cos(theta / 3) - a / 3;
4883 x1 = A * cos((theta + 2.0 * M_PI) / 3) - a / 3;
4884 x2 = A * cos((theta - 2.0 * M_PI) / 3) - a / 3;
4889 Swap<double>(x0, x1);
4893 Swap<double>(x1, x2);
4896 Swap<double>(x0, x1);
4909 A = -pow(sqrt(R2 - Q3) + R, 1.0/3.0);
4913 A = pow(sqrt(R2 - Q3) - R, 1.0/3.0);
4915 x(0) = A + Q / A - a / 3;
4924 const double factor,
const int Dim)
4926 const double c0 = c(0);
4927 c(0) = c0 * (1.0 - pow(factor, -Dim));
4929 for (
int j = 0; j < nr; j++)
4941 c(0) = c0 * (1.0 - pow(factor, Dim));
4943 for (
int j = 0; j < nr; j++)
4957 void Mesh::CheckDisplacements(
const Vector &displacements,
double &tmax)
4959 int nvs = vertices.Size();
4960 DenseMatrix P, V, DS, PDS(spaceDim), VDS(spaceDim);
4961 Vector c(spaceDim+1), x(spaceDim);
4962 const double factor = 2.0;
4969 for (
int i = 0; i < NumOfElements; i++)
4976 for (
int j = 0; j < spaceDim; j++)
4977 for (
int k = 0; k < nv; k++)
4979 P(j, k) = vertices[v[k]](j);
4980 V(j, k) = displacements(v[k]+j*nvs);
4984 GetTransformationFEforElementType(el->
GetType());
4988 case Element::TRIANGLE:
4989 case Element::TETRAHEDRON:
5007 case Element::QUADRILATERAL:
5010 for (
int j = 0; j < nv; j++)
5034 void Mesh::MoveVertices(
const Vector &displacements)
5036 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5037 for (
int j = 0; j < spaceDim; j++)
5039 vertices[i](j) += displacements(j*nv+i);
5043 void Mesh::GetVertices(
Vector &vert_coord)
const
5045 int nv = vertices.Size();
5046 vert_coord.
SetSize(nv*spaceDim);
5047 for (
int i = 0; i < nv; i++)
5048 for (
int j = 0; j < spaceDim; j++)
5050 vert_coord(j*nv+i) = vertices[i](j);
5054 void Mesh::SetVertices(
const Vector &vert_coord)
5056 for (
int i = 0, nv = vertices.Size(); i < nv; i++)
5057 for (
int j = 0; j < spaceDim; j++)
5059 vertices[i](j) = vert_coord(j*nv+i);
5063 void Mesh::GetNode(
int i,
double *coord)
5068 for (
int j = 0; j < spaceDim; j++)
5070 coord[j] = (*Nodes)(fes->
DofToVDof(i, j));
5075 for (
int j = 0; j < spaceDim; j++)
5077 coord[j] = vertices[i](j);
5082 void Mesh::SetNode(
int i,
const double *coord)
5087 for (
int j = 0; j < spaceDim; j++)
5089 (*Nodes)(fes->
DofToVDof(i, j)) = coord[j];
5094 for (
int j = 0; j < spaceDim; j++)
5096 vertices[i](j) = coord[j];
5102 void Mesh::MoveNodes(
const Vector &displacements)
5106 (*Nodes) += displacements;
5110 MoveVertices(displacements);
5114 void Mesh::GetNodes(
Vector &node_coord)
const
5118 node_coord = (*Nodes);
5122 GetVertices(node_coord);
5126 void Mesh::SetNodes(
const Vector &node_coord)
5130 (*Nodes) = node_coord;
5134 SetVertices(node_coord);
5140 if (own_nodes) {
delete Nodes; }
5143 own_nodes = (int)make_owner;
5154 mfem::Swap<GridFunction*>(Nodes, nodes);
5155 mfem::Swap<int>(own_nodes, own_nodes_);
5162 void Mesh::AverageVertices(
int * indexes,
int n,
int result)
5166 for (k = 0; k < spaceDim; k++)
5168 vertices[result](k) = vertices[indexes[0]](k);
5171 for (j = 1; j < n; j++)
5172 for (k = 0; k < spaceDim; k++)
5174 vertices[result](k) += vertices[indexes[j]](k);
5177 for (k = 0; k < spaceDim; k++)
5179 vertices[result](k) *= (1.0 / n);
5183 void Mesh::UpdateNodes()
5187 Nodes->FESpace()->Update();
5192 void Mesh::QuadUniformRefinement()
5194 int i, j, *v, vv[2], attr;
5197 if (el_to_edge == NULL)
5199 el_to_edge =
new Table;
5200 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5203 int oedge = NumOfVertices;
5204 int oelem = oedge + NumOfEdges;
5206 vertices.SetSize(oelem + NumOfElements);
5208 for (i = 0; i < NumOfElements; i++)
5210 v = elements[i]->GetVertices();
5212 AverageVertices(v, 4, oelem+i);
5214 e = el_to_edge->GetRow(i);
5216 vv[0] = v[0], vv[1] = v[1]; AverageVertices(vv, 2, oedge+e[0]);
5217 vv[0] = v[1], vv[1] = v[2]; AverageVertices(vv, 2, oedge+e[1]);
5218 vv[0] = v[2], vv[1] = v[3]; AverageVertices(vv, 2, oedge+e[2]);
5219 vv[0] = v[3], vv[1] = v[0]; AverageVertices(vv, 2, oedge+e[3]);
5222 elements.SetSize(4 * NumOfElements);
5223 for (i = 0; i < NumOfElements; i++)
5225 attr = elements[i]->GetAttribute();
5226 v = elements[i]->GetVertices();
5227 e = el_to_edge->GetRow(i);
5228 j = NumOfElements + 3 * i;
5230 elements[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5232 elements[j+1] =
new Quadrilateral(oelem+i, oedge+e[1], v[2],
5234 elements[j+2] =
new Quadrilateral(oedge+e[3], oelem+i, oedge+e[2],
5242 boundary.SetSize(2 * NumOfBdrElements);
5243 for (i = 0; i < NumOfBdrElements; i++)
5245 attr = boundary[i]->GetAttribute();
5246 v = boundary[i]->GetVertices();
5247 j = NumOfBdrElements + i;
5249 boundary[j] =
new Segment(oedge+be_to_edge[i], v[1], attr);
5251 v[1] = oedge+be_to_edge[i];
5254 static double quad_children[2*4*4] =
5256 0.0,0.0, 0.5,0.0, 0.5,0.5, 0.0,0.5,
5257 0.5,0.0, 1.0,0.0, 1.0,0.5, 0.5,0.5,
5258 0.5,0.5, 1.0,0.5, 1.0,1.0, 0.5,1.0,
5259 0.0,0.5, 0.5,0.5, 0.5,1.0, 0.0,1.0
5262 CoarseFineTr.point_matrices.UseExternalData(quad_children, 2, 4, 4);
5263 CoarseFineTr.embeddings.SetSize(elements.Size());
5265 for (i = 0; i < elements.Size(); i++)
5267 Embedding &emb = CoarseFineTr.embeddings[i];
5268 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 3;
5269 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 3 + 1;
5272 NumOfVertices = oelem + NumOfElements;
5273 NumOfElements = 4 * NumOfElements;
5274 NumOfBdrElements = 2 * NumOfBdrElements;
5277 if (el_to_edge != NULL)
5279 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5283 last_operation = Mesh::REFINE;
5289 CheckElementOrientation(
false);
5290 CheckBdrElementOrientation(
false);
5294 void Mesh::HexUniformRefinement()
5301 if (el_to_edge == NULL)
5303 el_to_edge =
new Table;
5304 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5306 if (el_to_face == NULL)
5308 GetElementToFaceTable();
5311 int oedge = NumOfVertices;
5312 int oface = oedge + NumOfEdges;
5313 int oelem = oface + NumOfFaces;
5315 vertices.SetSize(oelem + NumOfElements);
5316 for (i = 0; i < NumOfElements; i++)
5318 MFEM_ASSERT(elements[i]->GetType() == Element::HEXAHEDRON,
5319 "Element is not a hex!");
5320 v = elements[i]->GetVertices();
5322 AverageVertices(v, 8, oelem+i);
5324 f = el_to_face->GetRow(i);
5326 for (
int j = 0; j < 6; j++)
5328 for (
int k = 0; k < 4; k++)
5330 vv[k] = v[hex_t::FaceVert[j][k]];
5332 AverageVertices(vv, 4, oface+f[j]);
5335 e = el_to_edge->GetRow(i);
5337 for (
int j = 0; j < 12; j++)
5339 for (
int k = 0; k < 2; k++)
5341 vv[k] = v[hex_t::Edges[j][k]];
5343 AverageVertices(vv, 2, oedge+e[j]);
5348 elements.SetSize(8 * NumOfElements);
5349 for (i = 0; i < NumOfElements; i++)
5351 attr = elements[i]->GetAttribute();
5352 v = elements[i]->GetVertices();
5353 e = el_to_edge->GetRow(i);
5354 f = el_to_face->GetRow(i);
5355 j = NumOfElements + 7 * i;
5357 elements[j+0] =
new Hexahedron(oedge+e[0], v[1], oedge+e[1], oface+f[0],
5358 oface+f[1], oedge+e[9], oface+f[2],
5360 elements[j+1] =
new Hexahedron(oface+f[0], oedge+e[1], v[2], oedge+e[2],
5361 oelem+i, oface+f[2], oedge+e[10],
5363 elements[j+2] =
new Hexahedron(oedge+e[3], oface+f[0], oedge+e[2], v[3],
5364 oface+f[4], oelem+i, oface+f[3],
5366 elements[j+3] =
new Hexahedron(oedge+e[8], oface+f[1], oelem+i,
5367 oface+f[4], v[4], oedge+e[4], oface+f[5],
5369 elements[j+4] =
new Hexahedron(oface+f[1], oedge+e[9], oface+f[2],
5370 oelem+i, oedge+e[4], v[5], oedge+e[5],
5372 elements[j+5] =
new Hexahedron(oelem+i, oface+f[2], oedge+e[10],
5373 oface+f[3], oface+f[5], oedge+e[5], v[6],
5375 elements[j+6] =
new Hexahedron(oface+f[4], oelem+i, oface+f[3],
5376 oedge+e[11], oedge+e[7], oface+f[5],
5377 oedge+e[6], v[7], attr);
5388 boundary.SetSize(4 * NumOfBdrElements);
5389 for (i = 0; i < NumOfBdrElements; i++)
5391 MFEM_ASSERT(boundary[i]->GetType() == Element::QUADRILATERAL,
5392 "boundary Element is not a quad!");
5393 attr = boundary[i]->GetAttribute();
5394 v = boundary[i]->GetVertices();
5395 e = bel_to_edge->GetRow(i);
5396 f = & be_to_face[i];
5397 j = NumOfBdrElements + 3 * i;
5399 boundary[j+0] =
new Quadrilateral(oedge+e[0], v[1], oedge+e[1],
5401 boundary[j+1] =
new Quadrilateral(oface+f[0], oedge+e[1], v[2],
5403 boundary[j+2] =
new Quadrilateral(oedge+e[3], oface+f[0], oedge+e[2],
5411 static const double A = 0.0, B = 0.5, C = 1.0;
5412 static double hex_children[3*8*8] =
5414 A,A,A, B,A,A, B,B,A, A,B,A, A,A,B, B,A,B, B,B,B, A,B,B,
5415 B,A,A, C,A,A, C,B,A, B,B,A, B,A,B, C,A,B, C,B,B, B,B,B,
5416 B,B,A, C,B,A, C,C,A, B,C,A, B,B,B, C,B,B, C,C,B, B,C,B,
5417 A,B,A, B,B,A, B,C,A, A,C,A, A,B,B, B,B,B, B,C,B, A,C,B,
5418 A,A,B, B,A,B, B,B,B, A,B,B, A,A,C, B,A,C, B,B,C, A,B,C,
5419 B,A,B, C,A,B, C,B,B, B,B,B, B,A,C, C,A,C, C,B,C, B,B,C,
5420 B,B,B, C,B,B, C,C,B, B,C,B, B,B,C, C,B,C, C,C,C, B,C,C,
5421 A,B,B, B,B,B, B,C,B, A,C,B, A,B,C, B,B,C, B,C,C, A,C,C
5424 CoarseFineTr.point_matrices.UseExternalData(hex_children, 3, 8, 8);
5425 CoarseFineTr.embeddings.SetSize(elements.Size());
5427 for (i = 0; i < elements.Size(); i++)
5429 Embedding &emb = CoarseFineTr.embeddings[i];
5430 emb.
parent = (i < NumOfElements) ? i : (i - NumOfElements) / 7;
5431 emb.
matrix = (i < NumOfElements) ? 0 : (i - NumOfElements) % 7 + 1;
5434 NumOfVertices = oelem + NumOfElements;
5435 NumOfElements = 8 * NumOfElements;
5436 NumOfBdrElements = 4 * NumOfBdrElements;
5438 if (el_to_face != NULL)
5440 GetElementToFaceTable();
5445 CheckBdrElementOrientation(
false);
5448 if (el_to_edge != NULL)
5450 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5453 last_operation = Mesh::REFINE;
5459 void Mesh::LocalRefinement(
const Array<int> &marked_el,
int type)
5461 int i, j, ind, nedges;
5466 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
5469 InitRefinementTransforms();
5473 int cne = NumOfElements, cnv = NumOfVertices;
5474 NumOfVertices += marked_el.
Size();
5475 NumOfElements += marked_el.
Size();
5476 vertices.SetSize(NumOfVertices);
5477 elements.SetSize(NumOfElements);
5478 CoarseFineTr.embeddings.SetSize(NumOfElements);
5480 for (j = 0; j < marked_el.
Size(); j++)
5485 int new_v = cnv + j, new_e = cne + j;
5486 AverageVertices(vert, 2, new_v);
5487 elements[new_e] =
new Segment(new_v, vert[1], attr);
5490 CoarseFineTr.embeddings[i] =
Embedding(i, 1);
5491 CoarseFineTr.embeddings[new_e] =
Embedding(i, 2);
5494 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
5495 CoarseFineTr.point_matrices.UseExternalData(seg_children, 1, 2, 3);
5503 DSTable v_to_v(NumOfVertices);
5504 GetVertexToVertexTable(v_to_v);
5508 int *edge1 =
new int[nedges];
5509 int *edge2 =
new int[nedges];
5510 int *middle =
new int[nedges];
5512 for (i = 0; i < nedges; i++)
5514 edge1[i] = edge2[i] = middle[i] = -1;
5517 for (i = 0; i < NumOfElements; i++)
5519 elements[i]->GetVertices(v);
5520 for (j = 1; j < v.
Size(); j++)
5522 ind = v_to_v(v[j-1], v[j]);
5523 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5525 ind = v_to_v(v[0], v[v.
Size()-1]);
5526 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
5530 for (i = 0; i < marked_el.
Size(); i++)
5532 RedRefinement(marked_el[i], v_to_v, edge1, edge2, middle);
5536 int need_refinement;
5539 need_refinement = 0;
5540 for (i = 0; i < nedges; i++)
5542 if (middle[i] != -1 && edge1[i] != -1)
5544 need_refinement = 1;
5545 GreenRefinement(edge1[i], v_to_v, edge1, edge2, middle);
5549 while (need_refinement == 1);
5552 int v1[2], v2[2], bisect, temp;
5553 temp = NumOfBdrElements;
5554 for (i = 0; i < temp; i++)
5556 boundary[i]->GetVertices(v);
5557 bisect = v_to_v(v[0], v[1]);
5558 if (middle[bisect] != -1)
5560 if (boundary[i]->GetType() == Element::SEGMENT)
5562 v1[0] = v[0]; v1[1] = middle[bisect];
5563 v2[0] = middle[bisect]; v2[1] = v[1];
5565 boundary[i]->SetVertices(v1);
5566 boundary.
Append(
new Segment(v2, boundary[i]->GetAttribute()));
5569 mfem_error(
"Only bisection of segment is implemented"
5573 NumOfBdrElements = boundary.Size();
5580 if (el_to_edge != NULL)
5582 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5590 DSTable v_to_v(NumOfVertices);
5591 GetVertexToVertexTable(v_to_v);
5595 int *middle =
new int[nedges];
5597 for (i = 0; i < nedges; i++)
5607 for (i = 0; i < marked_el.
Size(); i++)
5609 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5613 for (i = 0; i < marked_el.
Size(); i++)
5615 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5617 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5618 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5622 for (i = 0; i < marked_el.
Size(); i++)
5624 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5626 ii = NumOfElements - 1;
5627 Bisection(ii, v_to_v, NULL, NULL, middle);
5628 Bisection(NumOfElements - 1, v_to_v, NULL, NULL, middle);
5629 Bisection(ii, v_to_v, NULL, NULL, middle);
5631 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5632 Bisection(NumOfElements-1, v_to_v, NULL, NULL, middle);
5633 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
5639 int need_refinement;
5644 need_refinement = 0;
5647 for (i = 0; i < NumOfElements; i++)
5651 if (elements[i]->NeedRefinement(v_to_v, middle))
5653 need_refinement = 1;
5654 Bisection(i, v_to_v, NULL, NULL, middle);
5658 while (need_refinement == 1);
5665 need_refinement = 0;
5666 for (i = 0; i < NumOfBdrElements; i++)
5667 if (boundary[i]->NeedRefinement(v_to_v, middle))
5669 need_refinement = 1;
5670 Bisection(i, v_to_v, middle);
5673 while (need_refinement == 1);
5676 int refinement_edges[2], type, flag;
5677 for (i = 0; i < NumOfElements; i++)
5682 if (type == Tetrahedron::TYPE_PF)
5689 NumOfBdrElements = boundary.Size();
5694 if (el_to_edge != NULL)
5696 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5698 if (el_to_face != NULL)
5700 GetElementToFaceTable();
5706 last_operation = Mesh::REFINE;
5712 CheckElementOrientation(
false);
5719 MFEM_VERIFY(!NURBSext,
"Nonconforming refinement of NURBS meshes is "
5720 "not supported. Project the NURBS to Nodes first.");
5725 ncmesh =
new NCMesh(
this);
5728 if (!refinements.
Size())
5730 last_operation = Mesh::NONE;
5735 ncmesh->MarkCoarseLevel();
5736 ncmesh->Refine(refinements);
5740 ncmesh->LimitNCLevel(nc_limit);
5745 ncmesh->OnMeshUpdated(mesh2);
5749 Swap(*mesh2,
false);
5752 GenerateNCFaceInfo();
5754 last_operation = Mesh::REFINE;
5759 Nodes->FESpace()->Update();
5766 MFEM_VERIFY(ncmesh,
"only supported for non-conforming meshes.");
5767 MFEM_VERIFY(!NURBSext,
"Derefinement of NURBS meshes is not supported. "
5768 "Project the NURBS to Nodes first.");
5770 ncmesh->Derefine(derefinements);
5773 ncmesh->OnMeshUpdated(mesh2);
5775 Swap(*mesh2,
false);
5778 GenerateNCFaceInfo();
5780 last_operation = Mesh::DEREFINE;
5785 Nodes->FESpace()->Update();
5791 double threshold,
int nc_limit,
int op)
5793 const Table &dt = ncmesh->GetDerefinementTable();
5798 ncmesh->CheckDerefinementNCLevel(dt, level_ok, nc_limit);
5802 for (
int i = 0; i < dt.
Size(); i++)
5804 if (nc_limit > 0 && !level_ok[i]) {
continue; }
5806 const int* fine = dt.
GetRow(i);
5810 for (
int j = 0; j < size; j++)
5812 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
5814 double err_fine = elem_error[fine[j]];
5817 case 0: error = std::min(error, err_fine);
break;
5818 case 1: error += err_fine;
break;
5819 case 2: error = std::max(error, err_fine);
break;
5823 if (error < threshold) { derefs.
Append(i); }
5828 DerefineMesh(derefs);
5836 int nc_limit,
int op)
5840 if (Nonconforming())
5842 return NonconformingDerefinement(elem_error, threshold, nc_limit, op);
5846 MFEM_ABORT(
"Derefinement is currently supported for non-conforming "
5852 bool Mesh::DerefineByError(
const Vector &elem_error,
double threshold,
5853 int nc_limit,
int op)
5856 for (
int i = 0; i < tmp.Size(); i++)
5858 tmp[i] = elem_error(i);
5860 return DerefineByError(tmp, threshold, nc_limit, op);
5864 void Mesh::InitFromNCMesh(
const NCMesh &ncmesh)
5873 case Geometry::TRIANGLE:
5874 case Geometry::SQUARE:
5875 BaseBdrGeom = Geometry::SEGMENT;
5877 case Geometry::CUBE:
5878 BaseBdrGeom = Geometry::SQUARE;
5888 NumOfVertices = vertices.Size();
5889 NumOfElements = elements.Size();
5890 NumOfBdrElements = boundary.Size();
5894 NumOfEdges = NumOfFaces = 0;
5898 el_to_edge =
new Table;
5899 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
5903 GetElementToFaceTable();
5907 CheckBdrElementOrientation(
false);
5918 InitFromNCMesh(ncmesh);
5964 void Mesh::UniformRefinement()
5968 NURBSUniformRefinement();
5970 else if (meshgen == 1 || ncmesh)
5973 for (
int i = 0; i < elem_to_refine.
Size(); i++)
5975 elem_to_refine[i] = i;
5982 LocalRefinement(elem_to_refine);
5986 GeneralRefinement(elem_to_refine, 1);
5991 QuadUniformRefinement();
5995 HexUniformRefinement();
6004 int nonconforming,
int nc_limit)
6006 if (Dim == 1 || (Dim == 3 && meshgen & 1))
6010 else if (nonconforming < 0)
6013 int geom = GetElementBaseGeometry();
6014 if (geom == Geometry::CUBE || geom == Geometry::SQUARE)
6024 if (nonconforming || ncmesh != NULL)
6027 NonconformingRefinement(refinements, nc_limit);
6032 for (
int i = 0; i < refinements.
Size(); i++)
6034 el_to_refine[i] = refinements[i].index;
6038 int type, rt = (refinements.
Size() ? refinements[0].ref_type : 7);
6039 if (rt == 1 || rt == 2 || rt == 4)
6043 else if (rt == 3 || rt == 5 || rt == 6)
6053 LocalRefinement(el_to_refine, type);
6057 void Mesh::GeneralRefinement(
const Array<int> &el_to_refine,
int nonconforming,
6061 for (
int i = 0; i < el_to_refine.
Size(); i++)
6063 refinements[i] =
Refinement(el_to_refine[i]);
6065 GeneralRefinement(refinements, nonconforming, nc_limit);
6068 void Mesh::EnsureNCMesh(
bool triangles_nonconforming)
6070 MFEM_VERIFY(!NURBSext,
"Cannot convert a NURBS mesh to an NC mesh. "
6071 "Project the NURBS to Nodes first.");
6075 if ((meshgen & 2) ||
6076 (triangles_nonconforming && BaseGeom == Geometry::TRIANGLE))
6078 ncmesh =
new NCMesh(
this);
6079 ncmesh->OnMeshUpdated(
this);
6080 GenerateNCFaceInfo();
6085 void Mesh::RandomRefinement(
double prob,
bool aniso,
int nonconforming,
6089 for (
int i = 0; i < GetNE(); i++)
6091 if ((
double) rand() / RAND_MAX < prob)
6096 type = (Dim == 3) ? (rand() % 7 + 1) : (rand() % 3 + 1);
6101 GeneralRefinement(refs, nonconforming, nc_limit);
6104 void Mesh::RefineAtVertex(
const Vertex& vert,
double eps,
int nonconforming)
6108 for (
int i = 0; i < GetNE(); i++)
6110 GetElementVertices(i, v);
6111 bool refine =
false;
6112 for (
int j = 0; j < v.
Size(); j++)
6115 for (
int l = 0; l < spaceDim; l++)
6117 double d = vert(l) - vertices[v[j]](l);
6120 if (dist <= eps*eps) { refine =
true;
break; }
6127 GeneralRefinement(refs, nonconforming);
6131 int nonconforming,
int nc_limit)
6133 MFEM_VERIFY(elem_error.
Size() == GetNE(),
"");
6135 for (
int i = 0; i < GetNE(); i++)
6137 if (elem_error[i] > threshold)
6142 if (ReduceInt(refs.Size()))
6144 GeneralRefinement(refs, nonconforming, nc_limit);
6150 bool Mesh::RefineByError(
const Vector &elem_error,
double threshold,
6151 int nonconforming,
int nc_limit)
6155 return RefineByError(tmp, threshold, nonconforming, nc_limit);
6159 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
6160 int *edge1,
int *edge2,
int *middle)
6163 int v[2][4], v_new, bisect, t;
6168 if (t == Element::TRIANGLE)
6175 bisect = v_to_v(vert[0], vert[1]);
6176 MFEM_ASSERT(bisect >= 0,
"");
6178 if (middle[bisect] == -1)
6180 v_new = NumOfVertices++;
6181 for (
int d = 0; d < spaceDim; d++)
6183 V(d) = 0.5 * (vertices[vert[0]](d) + vertices[vert[1]](d));
6189 if (edge1[bisect] == i)
6191 edge1[bisect] = edge2[bisect];
6194 middle[bisect] = v_new;
6198 v_new = middle[bisect];
6206 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6207 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6212 elements.Append(tri_new);
6221 int coarse = FindCoarseElement(i);
6222 CoarseFineTr.embeddings[i].parent = coarse;
6223 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6228 bisect = v_to_v(v[1][0], v[1][1]);
6229 MFEM_ASSERT(bisect >= 0,
"");
6231 if (edge1[bisect] == i)
6233 edge1[bisect] = NumOfElements;
6235 else if (edge2[bisect] == i)
6237 edge2[bisect] = NumOfElements;
6242 else if (t == Element::TETRAHEDRON)
6244 int j, type, new_type, old_redges[2], new_redges[2][2], flag;
6248 "TETRAHEDRON element is not marked for refinement.");
6253 bisect = v_to_v(vert[0], vert[1]);
6257 cerr <<
"Error in Bisection(...) of tetrahedron!" << endl
6258 <<
" redge[0] = " << old_redges[0]
6259 <<
" redge[1] = " << old_redges[1]
6260 <<
" type = " << type
6261 <<
" flag = " << flag << endl;
6265 if (middle[bisect] == -1)
6267 v_new = NumOfVertices++;
6268 for (j = 0; j < 3; j++)
6270 V(j) = 0.5 * (vertices[vert[0]](j) + vertices[vert[1]](j));
6274 middle[bisect] = v_new;
6278 v_new = middle[bisect];
6287 new_redges[0][0] = 2;
6288 new_redges[0][1] = 1;
6289 new_redges[1][0] = 2;
6290 new_redges[1][1] = 1;
6291 int tr1 = -1, tr2 = -1;
6292 switch (old_redges[0])
6295 v[0][0] = vert[0]; v[0][1] = vert[2]; v[0][2] = vert[3];
6296 if (type == Tetrahedron::TYPE_PF) { new_redges[0][1] = 4; }
6300 v[0][0] = vert[3]; v[0][1] = vert[0]; v[0][2] = vert[2];
6304 v[0][0] = vert[2]; v[0][1] = vert[3]; v[0][2] = vert[0];
6307 switch (old_redges[1])
6310 v[1][0] = vert[2]; v[1][1] = vert[1]; v[1][2] = vert[3];
6311 if (type == Tetrahedron::TYPE_PF) { new_redges[1][0] = 3; }
6315 v[1][0] = vert[1]; v[1][1] = vert[3]; v[1][2] = vert[2];
6319 v[1][0] = vert[3]; v[1][1] = vert[2]; v[1][2] = vert[1];
6326 #ifdef MFEM_USE_MEMALLOC
6334 elements.Append(tet2);
6340 int coarse = FindCoarseElement(i);
6341 CoarseFineTr.embeddings[i].parent = coarse;
6342 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6347 case Tetrahedron::TYPE_PU:
6348 new_type = Tetrahedron::TYPE_PF;
break;
6349 case Tetrahedron::TYPE_PF:
6350 new_type = Tetrahedron::TYPE_A;
break;
6352 new_type = Tetrahedron::TYPE_PU;
6362 MFEM_ABORT(
"Bisection for now works only for triangles & tetrahedra.");
6366 void Mesh::Bisection(
int i,
const DSTable &v_to_v,
int *middle)
6369 int v[2][3], v_new, bisect, t;
6370 Element *bdr_el = boundary[i];
6373 if (t == Element::TRIANGLE)
6380 bisect = v_to_v(vert[0], vert[1]);
6381 MFEM_ASSERT(bisect >= 0,
"");
6382 v_new = middle[bisect];
6383 MFEM_ASSERT(v_new != -1,
"");
6387 v[0][0] = vert[2]; v[0][1] = vert[0]; v[0][2] = v_new;
6388 v[1][0] = vert[1]; v[1][1] = vert[2]; v[1][2] = v_new;
6398 MFEM_ABORT(
"Bisection of boundary elements works only for triangles!");
6402 void Mesh::UniformRefinement(
int i,
const DSTable &v_to_v,
6403 int *edge1,
int *edge2,
int *middle)
6406 int j, v1[3], v2[3], v3[3], v4[3], v_new[3], bisect[3];
6409 if (elements[i]->GetType() == Element::TRIANGLE)
6415 bisect[0] = v_to_v(v[0],v[1]);
6416 bisect[1] = v_to_v(v[1],v[2]);
6417 bisect[2] = v_to_v(v[0],v[2]);
6418 MFEM_ASSERT(bisect[0] >= 0 && bisect[1] >= 0 && bisect[2] >= 0,
"");
6420 for (j = 0; j < 3; j++)
6422 if (middle[bisect[j]] == -1)
6424 v_new[j] = NumOfVertices++;
6425 for (
int d = 0; d < spaceDim; d++)
6427 V(d) = (vertices[v[j]](d) + vertices[v[(j+1)%3]](d))/2.;
6433 if (edge1[bisect[j]] == i)
6435 edge1[bisect[j]] = edge2[bisect[j]];
6438 middle[bisect[j]] = v_new[j];
6442 v_new[j] = middle[bisect[j]];
6445 edge1[bisect[j]] = -1;
6451 v1[0] = v[0]; v1[1] = v_new[0]; v1[2] = v_new[2];
6452 v2[0] = v_new[0]; v2[1] = v[1]; v2[2] = v_new[1];
6453 v3[0] = v_new[2]; v3[1] = v_new[1]; v3[2] = v[2];
6454 v4[0] = v_new[1]; v4[1] = v_new[2]; v4[2] = v_new[0];
6460 elements.Append(tri1);
6461 elements.Append(tri2);
6462 elements.Append(tri3);
6469 tri2->ResetTransform(code);
6470 tri3->ResetTransform(code);
6474 tri2->PushTransform(1);
6475 tri3->PushTransform(2);
6478 int coarse = FindCoarseElement(i);
6479 CoarseFineTr.embeddings[i] =
Embedding(coarse);
6480 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6481 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6482 CoarseFineTr.embeddings.Append(
Embedding(coarse));
6488 MFEM_ABORT(
"Uniform refinement for now works only for triangles.");
6492 void Mesh::InitRefinementTransforms()
6495 CoarseFineTr.point_matrices.SetSize(0, 0, 0);
6496 CoarseFineTr.embeddings.SetSize(NumOfElements);
6497 for (
int i = 0; i < NumOfElements; i++)
6499 elements[i]->ResetTransform(0);
6500 CoarseFineTr.embeddings[i] =
Embedding(i);
6504 int Mesh::FindCoarseElement(
int i)
6507 while ((coarse = CoarseFineTr.embeddings[i].parent) != i)
6516 MFEM_VERIFY(GetLastOperation() == Mesh::REFINE,
"");
6520 return ncmesh->GetRefinementTransforms();
6523 if (!CoarseFineTr.point_matrices.SizeK())
6525 if (BaseGeom == Geometry::TRIANGLE ||
6526 BaseGeom == Geometry::TETRAHEDRON)
6528 std::map<unsigned, int> mat_no;
6532 for (
int i = 0; i < elements.Size(); i++)
6535 unsigned code = elements[i]->GetTransform();
6538 int &matrix = mat_no[code];
6539 if (!matrix) { matrix = mat_no.size(); }
6542 CoarseFineTr.embeddings[i].matrix = index;
6546 pmats.
SetSize(Dim, Dim+1, mat_no.size());
6549 std::map<unsigned, int>::iterator it;
6550 for (it = mat_no.begin(); it != mat_no.end(); ++it)
6552 if (BaseGeom == Geometry::TRIANGLE)
6554 Triangle::GetPointMatrix(it->first, pmats(it->second-1));
6558 Tetrahedron::GetPointMatrix(it->first, pmats(it->second-1));
6564 MFEM_ABORT(
"Don't know how to construct CoarseFineTr.");
6569 return CoarseFineTr;
6572 void Mesh::PrintXG(std::ostream &out)
const
6574 MFEM_ASSERT(Dim==spaceDim,
"2D Manifold meshes not supported");
6583 out <<
"areamesh2\n\n";
6587 out <<
"curved_areamesh2\n\n";
6591 out << NumOfBdrElements <<
'\n';
6592 for (i = 0; i < NumOfBdrElements; i++)
6594 boundary[i]->GetVertices(v);
6596 out << boundary[i]->GetAttribute();
6597 for (j = 0; j < v.
Size(); j++)
6599 out <<
' ' << v[j] + 1;
6605 out << NumOfElements <<
'\n';
6606 for (i = 0; i < NumOfElements; i++)
6608 elements[i]->GetVertices(v);
6610 out << elements[i]->GetAttribute() <<
' ' << v.
Size();
6611 for (j = 0; j < v.
Size(); j++)
6613 out <<
' ' << v[j] + 1;
6621 out << NumOfVertices <<
'\n';
6622 for (i = 0; i < NumOfVertices; i++)
6624 out << vertices[i](0);
6625 for (j = 1; j < Dim; j++)
6627 out <<
' ' << vertices[i](j);
6634 out << NumOfVertices <<
'\n';
6642 mfem_error(
"Mesh::PrintXG(...) : Curved mesh in 3D");
6650 out <<
"NETGEN_Neutral_Format\n";
6652 out << NumOfVertices <<
'\n';
6653 for (i = 0; i < NumOfVertices; i++)
6655 for (j = 0; j < Dim; j++)
6657 out <<
' ' << vertices[i](j);
6663 out << NumOfElements <<
'\n';
6664 for (i = 0; i < NumOfElements; i++)
6666 nv = elements[i]->GetNVertices();
6667 ind = elements[i]->GetVertices();
6668 out << elements[i]->GetAttribute();
6669 for (j = 0; j < nv; j++)
6671 out <<
' ' << ind[j]+1;
6677 out << NumOfBdrElements <<
'\n';
6678 for (i = 0; i < NumOfBdrElements; i++)
6680 nv = boundary[i]->GetNVertices();
6681 ind = boundary[i]->GetVertices();
6682 out << boundary[i]->GetAttribute();
6683 for (j = 0; j < nv; j++)
6685 out <<
' ' << ind[j]+1;
6690 else if (meshgen == 2)
6696 <<
"1 " << NumOfVertices <<
" " << NumOfElements
6697 <<
" 0 0 0 0 0 0 0\n"
6698 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
6699 <<
"0 0 " << NumOfBdrElements <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
6700 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
6701 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
6703 for (i = 0; i < NumOfVertices; i++)
6704 out << i+1 <<
" 0.0 " << vertices[i](0) <<
' ' << vertices[i](1)
6705 <<
' ' << vertices[i](2) <<
" 0.0\n";
6707 for (i = 0; i < NumOfElements; i++)
6709 nv = elements[i]->GetNVertices();
6710 ind = elements[i]->GetVertices();
6711 out << i+1 <<
' ' << elements[i]->GetAttribute();
6712 for (j = 0; j < nv; j++)
6714 out <<
' ' << ind[j]+1;
6719 for (i = 0; i < NumOfBdrElements; i++)
6721 nv = boundary[i]->GetNVertices();
6722 ind = boundary[i]->GetVertices();
6723 out << boundary[i]->GetAttribute();
6724 for (j = 0; j < nv; j++)
6726 out <<
' ' << ind[j]+1;
6728 out <<
" 1.0 1.0 1.0 1.0\n";
6736 void Mesh::Print(std::ostream &out)
const
6743 NURBSext->Print(out);
6754 out << (ncmesh ?
"MFEM mesh v1.1\n" :
"MFEM mesh v1.0\n");
6758 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
6763 "# TETRAHEDRON = 4\n"
6767 out <<
"\ndimension\n" << Dim
6768 <<
"\n\nelements\n" << NumOfElements <<
'\n';
6769 for (i = 0; i < NumOfElements; i++)
6771 PrintElement(elements[i], out);
6774 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
6775 for (i = 0; i < NumOfBdrElements; i++)
6777 PrintElement(boundary[i], out);
6782 out <<
"\nvertex_parents\n";
6783 ncmesh->PrintVertexParents(out);
6785 out <<
"\ncoarse_elements\n";
6786 ncmesh->PrintCoarseElements(out);
6789 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
6792 out << spaceDim <<
'\n';
6793 for (i = 0; i < NumOfVertices; i++)
6795 out << vertices[i](0);
6796 for (j = 1; j < spaceDim; j++)
6798 out <<
' ' << vertices[i](j);
6811 void Mesh::PrintTopo(std::ostream &out,
const Array<int> &e_to_k)
const
6816 out <<
"MFEM NURBS mesh v1.0\n";
6820 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
6826 out <<
"\ndimension\n" << Dim
6827 <<
"\n\nelements\n" << NumOfElements <<
'\n';
6828 for (i = 0; i < NumOfElements; i++)
6830 PrintElement(elements[i], out);
6833 out <<
"\nboundary\n" << NumOfBdrElements <<
'\n';
6834 for (i = 0; i < NumOfBdrElements; i++)
6836 PrintElement(boundary[i], out);
6839 out <<
"\nedges\n" << NumOfEdges <<
'\n';
6840 for (i = 0; i < NumOfEdges; i++)
6842 edge_vertex->GetRow(i, vert);
6848 out << ki <<
' ' << vert[0] <<
' ' << vert[1] <<
'\n';
6850 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
6853 void Mesh::PrintVTK(std::ostream &out)
6856 "# vtk DataFile Version 3.0\n"
6857 "Generated by MFEM\n"
6859 "DATASET UNSTRUCTURED_GRID\n";
6863 out <<
"POINTS " << NumOfVertices <<
" double\n";
6864 for (
int i = 0; i < NumOfVertices; i++)
6866 out << vertices[i](0);
6868 for (j = 1; j < spaceDim; j++)
6870 out <<
' ' << vertices[i](j);
6882 out <<
"POINTS " << Nodes->FESpace()->GetNDofs() <<
" double\n";
6883 for (
int i = 0; i < Nodes->FESpace()->GetNDofs(); i++)
6887 Nodes->FESpace()->DofsToVDofs(vdofs);
6888 out << (*Nodes)(vdofs[0]);
6890 for (j = 1; j < spaceDim; j++)
6892 out <<
' ' << (*Nodes)(vdofs[j]);
6906 for (
int i = 0; i < NumOfElements; i++)
6908 size += elements[i]->GetNVertices() + 1;
6910 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
6911 for (
int i = 0; i < NumOfElements; i++)
6913 const int *v = elements[i]->GetVertices();
6914 const int nv = elements[i]->GetNVertices();
6916 for (
int j = 0; j < nv; j++)
6928 for (
int i = 0; i < NumOfElements; i++)
6930 Nodes->FESpace()->GetElementDofs(i, dofs);
6931 size += dofs.
Size() + 1;
6933 out <<
"CELLS " << NumOfElements <<
' ' << size <<
'\n';
6934 const char *fec_name = Nodes->FESpace()->FEColl()->Name();
6935 if (!strcmp(fec_name,
"Linear") ||
6936 !strcmp(fec_name,
"H1_2D_P1") ||
6937 !strcmp(fec_name,
"H1_3D_P1"))
6941 else if (!strcmp(fec_name,
"Quadratic") ||
6942 !strcmp(fec_name,
"H1_2D_P2") ||
6943 !strcmp(fec_name,
"H1_3D_P2"))
6949 cerr <<
"Mesh::PrintVTK : can not save '"
6950 << fec_name <<
"' elements!" << endl;
6953 for (
int i = 0; i < NumOfElements; i++)
6955 Nodes->FESpace()->GetElementDofs(i, dofs);
6959 for (
int j = 0; j < dofs.
Size(); j++)
6961 out <<
' ' << dofs[j];
6964 else if (order == 2)
6966 const int *vtk_mfem;
6967 switch (elements[i]->GetGeometryType())
6969 case Geometry::TRIANGLE:
6970 case Geometry::SQUARE:
6971 vtk_mfem = vtk_quadratic_hex;
break;
6972 case Geometry::TETRAHEDRON:
6973 vtk_mfem = vtk_quadratic_tet;
break;
6974 case Geometry::CUBE:
6976 vtk_mfem = vtk_quadratic_hex;
break;
6978 for (
int j = 0; j < dofs.
Size(); j++)
6980 out <<
' ' << dofs[vtk_mfem[j]];
6987 out <<
"CELL_TYPES " << NumOfElements <<
'\n';
6988 for (
int i = 0; i < NumOfElements; i++)
6990 int vtk_cell_type = 5;
6993 switch (elements[i]->GetGeometryType())
6995 case Geometry::TRIANGLE: vtk_cell_type = 5;
break;
6996 case Geometry::SQUARE: vtk_cell_type = 9;
break;
6997 case Geometry::TETRAHEDRON: vtk_cell_type = 10;
break;
6998 case Geometry::CUBE: vtk_cell_type = 12;
break;
7001 else if (order == 2)
7003 switch (elements[i]->GetGeometryType())
7005 case Geometry::TRIANGLE: vtk_cell_type = 22;
break;
7006 case Geometry::SQUARE: vtk_cell_type = 28;
break;
7007 case Geometry::TETRAHEDRON: vtk_cell_type = 24;
break;
7008 case Geometry::CUBE: vtk_cell_type = 29;
break;
7012 out << vtk_cell_type <<
'\n';
7016 out <<
"CELL_DATA " << NumOfElements <<
'\n'
7017 <<
"SCALARS material int\n"
7018 <<
"LOOKUP_TABLE default\n";
7019 for (
int i = 0; i < NumOfElements; i++)
7021 out << elements[i]->GetAttribute() <<
'\n';
7026 void Mesh::PrintVTK(std::ostream &out,
int ref,
int field_data)
7033 "# vtk DataFile Version 3.0\n"
7034 "Generated by MFEM\n"
7036 "DATASET UNSTRUCTURED_GRID\n";
7041 out <<
"FIELD FieldData 1\n"
7042 <<
"MaterialIds " << 1 <<
" " << attributes.
Size() <<
" int\n";
7043 for (
int i = 0; i < attributes.Size(); i++)
7045 out <<
' ' << attributes[i];
7052 for (
int i = 0; i < GetNE(); i++)
7054 int geom = GetElementBaseGeometry(i);
7061 out <<
"POINTS " << np <<
" double\n";
7063 for (
int i = 0; i < GetNE(); i++)
7066 GetElementBaseGeometry(i), ref, 1);
7068 GetElementTransformation(i)->Transform(RefG->
RefPts, pmat);
7070 for (
int j = 0; j < pmat.
Width(); j++)
7072 out << pmat(0, j) <<
' ';
7075 out << pmat(1, j) <<
' ';
7087 out << 0.0 <<
' ' << 0.0;
7094 out <<
"CELLS " << nc <<
' ' << size <<
'\n';
7096 for (
int i = 0; i < GetNE(); i++)
7098 int geom = GetElementBaseGeometry(i);
7103 for (
int j = 0; j < RG.
Size(); )
7106 for (
int k = 0; k < nv; k++, j++)
7108 out <<
' ' << np + RG[j];
7114 out <<
"CELL_TYPES " << nc <<
'\n';
7115 for (
int i = 0; i < GetNE(); i++)
7117 int geom = GetElementBaseGeometry(i);
7121 int vtk_cell_type = 5;
7125 case Geometry::SEGMENT: vtk_cell_type = 3;
break;
7126 case Geometry::TRIANGLE: vtk_cell_type = 5;
break;
7127 case Geometry::SQUARE: vtk_cell_type = 9;
break;
7128 case Geometry::TETRAHEDRON: vtk_cell_type = 10;
break;
7129 case Geometry::CUBE: vtk_cell_type = 12;
break;
7132 for (
int j = 0; j < RG.
Size(); j += nv)
7134 out << vtk_cell_type <<
'\n';
7138 out <<
"CELL_DATA " << nc <<
'\n'
7139 <<
"SCALARS material int\n"
7140 <<
"LOOKUP_TABLE default\n";
7141 for (
int i = 0; i < GetNE(); i++)
7143 int geom = GetElementBaseGeometry(i);
7146 int attr = GetAttribute(i);
7149 out << attr <<
'\n';
7154 srand((
unsigned)time(0));
7155 double a = double(rand()) / (double(RAND_MAX) + 1.);
7156 int el0 = (int)floor(a * GetNE());
7157 GetElementColoring(coloring, el0);
7158 out <<
"SCALARS element_coloring int\n"
7159 <<
"LOOKUP_TABLE default\n";
7160 for (
int i = 0; i < GetNE(); i++)
7162 int geom = GetElementBaseGeometry(i);
7167 out << coloring[i] + 1 <<
'\n';
7171 out <<
"POINT_DATA " << np <<
'\n' << flush;
7176 int delete_el_to_el = (el_to_el) ? (0) : (1);
7177 const Table &el_el = ElementToElementTable();
7178 int num_el = GetNE(), stack_p, stack_top_p, max_num_col;
7181 const int *i_el_el = el_el.
GetI();
7182 const int *j_el_el = el_el.
GetJ();
7187 stack_p = stack_top_p = 0;
7188 for (
int el = el0; stack_top_p < num_el; el=(el+1)%num_el)
7190 if (colors[el] != -2)
7196 el_stack[stack_top_p++] = el;
7198 for ( ; stack_p < stack_top_p; stack_p++)
7200 int i = el_stack[stack_p];
7201 int num_nb = i_el_el[i+1] - i_el_el[i];
7202 if (max_num_col < num_nb + 1)
7204 max_num_col = num_nb + 1;
7206 for (
int j = i_el_el[i]; j < i_el_el[i+1]; j++)
7209 if (colors[k] == -2)
7212 el_stack[stack_top_p++] = k;
7220 for (stack_p = 0; stack_p < stack_top_p; stack_p++)
7222 int i = el_stack[stack_p], col;
7224 for (
int j = i_el_el[i]; j < i_el_el[i+1]; j++)
7226 col = colors[j_el_el[j]];
7229 col_marker[col] = 1;
7233 for (col = 0; col < max_num_col; col++)
7234 if (col_marker[col] == 0)
7242 if (delete_el_to_el)
7249 void Mesh::PrintWithPartitioning(
int *partitioning, std::ostream &out,
7250 int elem_attr)
const
7252 if (Dim != 3 && Dim != 2) {
return; }
7254 int i, j, k, l, nv, nbe, *v;
7256 out <<
"MFEM mesh v1.0\n";
7260 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7265 "# TETRAHEDRON = 4\n"
7269 out <<
"\ndimension\n" << Dim
7270 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7271 for (i = 0; i < NumOfElements; i++)
7273 out << int((elem_attr) ? partitioning[i]+1 : elements[i]->GetAttribute())
7274 <<
' ' << elements[i]->GetGeometryType();
7275 nv = elements[i]->GetNVertices();
7276 v = elements[i]->GetVertices();
7277 for (j = 0; j < nv; j++)
7284 for (i = 0; i < faces_info.Size(); i++)
7286 if ((l = faces_info[i].Elem2No) >= 0)
7288 k = partitioning[faces_info[i].Elem1No];
7289 l = partitioning[l];
7300 out <<
"\nboundary\n" << nbe <<
'\n';
7301 for (i = 0; i < faces_info.Size(); i++)
7303 if ((l = faces_info[i].Elem2No) >= 0)
7305 k = partitioning[faces_info[i].Elem1No];
7306 l = partitioning[l];
7309 nv = faces[i]->GetNVertices();
7310 v = faces[i]->GetVertices();
7311 out << k+1 <<
' ' << faces[i]->GetGeometryType();
7312 for (j = 0; j < nv; j++)
7317 out << l+1 <<
' ' << faces[i]->GetGeometryType();
7318 for (j = nv-1; j >= 0; j--)
7327 k = partitioning[faces_info[i].Elem1No];
7328 nv = faces[i]->GetNVertices();
7329 v = faces[i]->GetVertices();
7330 out << k+1 <<
' ' << faces[i]->GetGeometryType();
7331 for (j = 0; j < nv; j++)
7338 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7341 out << spaceDim <<
'\n';
7342 for (i = 0; i < NumOfVertices; i++)
7344 out << vertices[i](0);
7345 for (j = 1; j < spaceDim; j++)
7347 out <<
' ' << vertices[i](j);
7360 void Mesh::PrintElementsWithPartitioning(
int *partitioning,
7364 MFEM_ASSERT(Dim == spaceDim,
"2D Manifolds not supported\n");
7365 if (Dim != 3 && Dim != 2) {
return; }
7372 int *vcount =
new int[NumOfVertices];
7373 for (i = 0; i < NumOfVertices; i++)
7377 for (i = 0; i < NumOfElements; i++)
7379 nv = elements[i]->GetNVertices();
7380 ind = elements[i]->GetVertices();
7381 for (j = 0; j < nv; j++)
7387 int *voff =
new int[NumOfVertices+1];
7389 for (i = 1; i <= NumOfVertices; i++)
7391 voff[i] = vcount[i-1] + voff[i-1];
7394 int **vown =
new int*[NumOfVertices];
7395 for (i = 0; i < NumOfVertices; i++)
7397 vown[i] =
new int[vcount[i]];
7407 Transpose(ElementToEdgeTable(), edge_el);
7410 for (i = 0; i < NumOfElements; i++)
7412 nv = elements[i]->GetNVertices();
7413 ind = elements[i]->GetVertices();
7414 for (j = 0; j < nv; j++)
7417 vown[ind[j]][vcount[ind[j]]] = i;
7421 for (i = 0; i < NumOfVertices; i++)
7423 vcount[i] = voff[i+1] - voff[i];
7427 for (i = 0; i < edge_el.
Size(); i++)
7429 const int *el = edge_el.
GetRow(i);
7432 k = partitioning[el[0]];
7433 l = partitioning[el[1]];
7434 if (interior_faces || k != l)
7446 out <<
"areamesh2\n\n" << nbe <<
'\n';
7448 for (i = 0; i < edge_el.
Size(); i++)
7450 const int *el = edge_el.
GetRow(i);
7453 k = partitioning[el[0]];
7454 l = partitioning[el[1]];
7455 if (interior_faces || k != l)
7458 GetEdgeVertices(i,ev);
7460 for (j = 0; j < 2; j++)
7461 for (s = 0; s < vcount[ev[j]]; s++)
7462 if (vown[ev[j]][s] == el[0])
7464 out <<
' ' << voff[ev[j]]+s+1;
7468 for (j = 1; j >= 0; j--)
7469 for (s = 0; s < vcount[ev[j]]; s++)
7470 if (vown[ev[j]][s] == el[1])
7472 out <<
' ' << voff[ev[j]]+s+1;
7479 k = partitioning[el[0]];
7481 GetEdgeVertices(i,ev);
7483 for (j = 0; j < 2; j++)
7484 for (s = 0; s < vcount[ev[j]]; s++)
7485 if (vown[ev[j]][s] == el[0])
7487 out <<
' ' << voff[ev[j]]+s+1;
7494 out << NumOfElements <<
'\n';
7495 for (i = 0; i < NumOfElements; i++)
7497 nv = elements[i]->GetNVertices();
7498 ind = elements[i]->GetVertices();
7499 out << partitioning[i]+1 <<
' ';
7501 for (j = 0; j < nv; j++)
7503 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7504 vown[ind[j]][vcount[ind[j]]] = i;
7509 for (i = 0; i < NumOfVertices; i++)
7511 vcount[i] = voff[i+1] - voff[i];
7515 out << voff[NumOfVertices] <<
'\n';
7516 for (i = 0; i < NumOfVertices; i++)
7517 for (k = 0; k < vcount[i]; k++)
7519 for (j = 0; j < Dim; j++)
7521 out << vertices[i](j) <<
' ';
7532 out <<
"NETGEN_Neutral_Format\n";
7534 out << voff[NumOfVertices] <<
'\n';
7535 for (i = 0; i < NumOfVertices; i++)
7536 for (k = 0; k < vcount[i]; k++)
7538 for (j = 0; j < Dim; j++)
7540 out <<
' ' << vertices[i](j);
7546 out << NumOfElements <<
'\n';
7547 for (i = 0; i < NumOfElements; i++)
7549 nv = elements[i]->GetNVertices();
7550 ind = elements[i]->GetVertices();
7551 out << partitioning[i]+1;
7552 for (j = 0; j < nv; j++)
7554 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7555 vown[ind[j]][vcount[ind[j]]] = i;
7560 for (i = 0; i < NumOfVertices; i++)
7562 vcount[i] = voff[i+1] - voff[i];
7568 for (i = 0; i < NumOfFaces; i++)
7569 if ((l = faces_info[i].Elem2No) >= 0)
7571 k = partitioning[faces_info[i].Elem1No];
7572 l = partitioning[l];
7573 if (interior_faces || k != l)
7584 for (i = 0; i < NumOfFaces; i++)
7585 if ((l = faces_info[i].Elem2No) >= 0)
7587 k = partitioning[faces_info[i].Elem1No];
7588 l = partitioning[l];
7589 if (interior_faces || k != l)
7591 nv = faces[i]->GetNVertices();
7592 ind = faces[i]->GetVertices();
7594 for (j = 0; j < nv; j++)
7595 for (s = 0; s < vcount[ind[j]]; s++)
7596 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7598 out <<
' ' << voff[ind[j]]+s+1;
7602 for (j = nv-1; j >= 0; j--)
7603 for (s = 0; s < vcount[ind[j]]; s++)
7604 if (vown[ind[j]][s] == faces_info[i].Elem2No)
7606 out <<
' ' << voff[ind[j]]+s+1;
7613 k = partitioning[faces_info[i].Elem1No];
7614 nv = faces[i]->GetNVertices();
7615 ind = faces[i]->GetVertices();
7617 for (j = 0; j < nv; j++)
7618 for (s = 0; s < vcount[ind[j]]; s++)
7619 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7621 out <<
' ' << voff[ind[j]]+s+1;
7626 for (i = 0; i < NumOfVertices; i++)
7631 else if (meshgen == 2)
7636 for (i = 0; i < NumOfFaces; i++)
7637 if ((l = faces_info[i].Elem2No) >= 0)
7639 k = partitioning[faces_info[i].Elem1No];
7640 l = partitioning[l];
7641 if (interior_faces || k != l)
7653 <<
"1 " << voff[NumOfVertices] <<
" " << NumOfElements
7654 <<
" 0 0 0 0 0 0 0\n"
7655 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
7656 <<
"0 0 " << nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
7657 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
7658 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
7660 for (i = 0; i < NumOfVertices; i++)
7661 for (k = 0; k < vcount[i]; k++)
7662 out << voff[i]+k <<
" 0.0 " << vertices[i](0) <<
' '
7663 << vertices[i](1) <<
' ' << vertices[i](2) <<
" 0.0\n";
7665 for (i = 0; i < NumOfElements; i++)
7667 nv = elements[i]->GetNVertices();
7668 ind = elements[i]->GetVertices();
7669 out << i+1 <<
' ' << partitioning[i]+1;
7670 for (j = 0; j < nv; j++)
7672 out <<
' ' << voff[ind[j]]+vcount[ind[j]]--;
7673 vown[ind[j]][vcount[ind[j]]] = i;
7678 for (i = 0; i < NumOfVertices; i++)
7680 vcount[i] = voff[i+1] - voff[i];
7684 for (i = 0; i < NumOfFaces; i++)
7685 if ((l = faces_info[i].Elem2No) >= 0)
7687 k = partitioning[faces_info[i].Elem1No];
7688 l = partitioning[l];
7689 if (interior_faces || k != l)
7691 nv = faces[i]->GetNVertices();
7692 ind = faces[i]->GetVertices();
7694 for (j = 0; j < nv; j++)
7695 for (s = 0; s < vcount[ind[j]]; s++)
7696 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7698 out <<
' ' << voff[ind[j]]+s+1;
7700 out <<
" 1.0 1.0 1.0 1.0\n";
7702 for (j = nv-1; j >= 0; j--)
7703 for (s = 0; s < vcount[ind[j]]; s++)
7704 if (vown[ind[j]][s] == faces_info[i].Elem2No)
7706 out <<
' ' << voff[ind[j]]+s+1;
7708 out <<
" 1.0 1.0 1.0 1.0\n";
7713 k = partitioning[faces_info[i].Elem1No];
7714 nv = faces[i]->GetNVertices();
7715 ind = faces[i]->GetVertices();
7717 for (j = 0; j < nv; j++)
7718 for (s = 0; s < vcount[ind[j]]; s++)
7719 if (vown[ind[j]][s] == faces_info[i].Elem1No)
7721 out <<
' ' << voff[ind[j]]+s+1;
7723 out <<
" 1.0 1.0 1.0 1.0\n";
7734 void Mesh::PrintSurfaces(
const Table & Aface_face, std::ostream &out)
const
7741 " NURBS mesh is not supported!");
7745 out <<
"MFEM mesh v1.0\n";
7749 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
7754 "# TETRAHEDRON = 4\n"
7758 out <<
"\ndimension\n" << Dim
7759 <<
"\n\nelements\n" << NumOfElements <<
'\n';
7760 for (i = 0; i < NumOfElements; i++)
7762 PrintElement(elements[i], out);
7766 const int *
const i_AF_f = Aface_face.
GetI();
7767 const int *
const j_AF_f = Aface_face.
GetJ();
7769 for (
int iAF=0; iAF < Aface_face.
Size(); ++iAF)
7770 for (
const int * iface = j_AF_f + i_AF_f[iAF]; iface < j_AF_f + i_AF_f[iAF+1];
7773 out << iAF+1 <<
' ';
7774 PrintElementWithoutAttr(faces[*iface],out);
7777 out <<
"\nvertices\n" << NumOfVertices <<
'\n';
7780 out << spaceDim <<
'\n';
7781 for (i = 0; i < NumOfVertices; i++)
7783 out << vertices[i](0);
7784 for (j = 1; j < spaceDim; j++)
7786 out <<
' ' << vertices[i](j);
7799 void Mesh::ScaleSubdomains(
double sf)
7804 int na = attributes.
Size();
7805 double *cg =
new double[na*spaceDim];
7806 int *nbea =
new int[na];
7808 int *vn =
new int[NumOfVertices];
7809 for (i = 0; i < NumOfVertices; i++)
7813 for (i = 0; i < na; i++)
7815 for (j = 0; j < spaceDim; j++)
7817 cg[i*spaceDim+j] = 0.0;
7822 for (i = 0; i < NumOfElements; i++)
7824 GetElementVertices(i, vert);
7825 for (k = 0; k < vert.
Size(); k++)
7831 for (i = 0; i < NumOfElements; i++)
7833 int bea = GetAttribute(i)-1;
7834 GetPointMatrix(i, pointmat);
7835 GetElementVertices(i, vert);
7837 for (k = 0; k < vert.
Size(); k++)
7838 if (vn[vert[k]] == 1)
7841 for (j = 0; j < spaceDim; j++)
7843 cg[bea*spaceDim+j] += pointmat(j,k);
7849 for (i = 0; i < NumOfElements; i++)
7851 int bea = GetAttribute(i)-1;
7852 GetElementVertices (i, vert);
7854 for (k = 0; k < vert.
Size(); k++)
7857 for (j = 0; j < spaceDim; j++)
7858 vertices[vert[k]](j) = sf*vertices[vert[k]](j) +
7859 (1-sf)*cg[bea*spaceDim+j]/nbea[bea];
7869 void Mesh::ScaleElements(
double sf)
7874 int na = NumOfElements;
7875 double *cg =
new double[na*spaceDim];
7876 int *nbea =
new int[na];
7878 int *vn =
new int[NumOfVertices];
7879 for (i = 0; i < NumOfVertices; i++)
7883 for (i = 0; i < na; i++)
7885 for (j = 0; j < spaceDim; j++)
7887 cg[i*spaceDim+j] = 0.0;
7892 for (i = 0; i < NumOfElements; i++)
7894 GetElementVertices(i, vert);
7895 for (k = 0; k < vert.
Size(); k++)
7901 for (i = 0; i < NumOfElements; i++)
7904 GetPointMatrix(i, pointmat);
7905 GetElementVertices(i, vert);
7907 for (k = 0; k < vert.
Size(); k++)
7908 if (vn[vert[k]] == 1)
7911 for (j = 0; j < spaceDim; j++)
7913 cg[bea*spaceDim+j] += pointmat(j,k);
7919 for (i = 0; i < NumOfElements; i++)
7922 GetElementVertices(i, vert);
7924 for (k = 0; k < vert.
Size(); k++)
7927 for (j = 0; j < spaceDim; j++)
7928 vertices[vert[k]](j) = sf*vertices[vert[k]](j) +
7929 (1-sf)*cg[bea*spaceDim+j]/nbea[bea];
7944 Vector vold(spaceDim), vnew(NULL, spaceDim);
7945 for (
int i = 0; i < vertices.Size(); i++)
7947 for (
int j = 0; j < spaceDim; j++)
7949 vold(j) = vertices[i](j);
7959 xnew.ProjectCoefficient(f_pert);
7966 MFEM_VERIFY(spaceDim == deformation.
GetVDim(),
7967 "incompatible vector dimensions");
7974 for (
int i = 0; i < NumOfVertices; i++)
7975 for (
int d = 0; d < spaceDim; d++)
7977 vertices[i](d) = xnew(d + spaceDim*i);
7988 void Mesh::RemoveUnusedVertices()
7990 if (NURBSext || ncmesh) {
return; }
7994 for (
int i = 0; i < GetNE(); i++)
7999 for (
int j = 0; j < nv; j++)
8004 for (
int i = 0; i < GetNBE(); i++)
8006 Element *el = GetBdrElement(i);
8009 for (
int j = 0; j < nv; j++)
8015 for (
int i = 0; i < v2v.
Size(); i++)
8019 vertices[num_vert] = vertices[i];
8020 v2v[i] = num_vert++;
8024 if (num_vert == v2v.
Size()) {
return; }
8031 for (
int i = 0; i < GetNE(); i++)
8033 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8038 for (
int i = 0; i < GetNE(); i++)
8040 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8041 Nodes->GetSubVector(vdofs, &nodes_by_element(s));
8045 vertices.SetSize(num_vert);
8046 NumOfVertices = num_vert;
8047 for (
int i = 0; i < GetNE(); i++)
8052 for (
int j = 0; j < nv; j++)
8057 for (
int i = 0; i < GetNBE(); i++)
8059 Element *el = GetBdrElement(i);
8062 for (
int j = 0; j < nv; j++)
8071 el_to_edge =
new Table;
8072 NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
8077 GetElementToFaceTable();
8083 Nodes->FESpace()->Update();
8086 for (
int i = 0; i < GetNE(); i++)
8088 Nodes->FESpace()->GetElementVDofs(i, vdofs);
8089 Nodes->SetSubVector(vdofs, &nodes_by_element(s));
8095 void Mesh::RemoveInternalBoundaries()
8097 if (NURBSext || ncmesh) {
return; }
8099 int num_bdr_elem = 0;
8100 int new_bel_to_edge_nnz = 0;
8101 for (
int i = 0; i < GetNBE(); i++)
8103 if (FaceIsInterior(GetBdrElementEdgeIndex(i)))
8105 FreeElement(boundary[i]);
8112 new_bel_to_edge_nnz += bel_to_edge->RowSize(i);
8117 if (num_bdr_elem == GetNBE()) {
return; }
8121 Table *new_bel_to_edge = NULL;
8125 new_be_to_edge.
Reserve(num_bdr_elem);
8129 new_be_to_face.
Reserve(num_bdr_elem);
8130 new_bel_to_edge =
new Table;
8131 new_bel_to_edge->
SetDims(num_bdr_elem, new_bel_to_edge_nnz);
8133 for (
int i = 0; i < GetNBE(); i++)
8135 if (!FaceIsInterior(GetBdrElementEdgeIndex(i)))
8137 new_boundary.
Append(boundary[i]);
8140 new_be_to_edge.
Append(be_to_edge[i]);
8144 int row = new_be_to_face.
Size();
8145 new_be_to_face.
Append(be_to_face[i]);
8146 int *e = bel_to_edge->GetRow(i);
8147 int ne = bel_to_edge->RowSize(i);
8148 int *new_e = new_bel_to_edge->
GetRow(row);
8149 for (
int j = 0; j < ne; j++)
8153 new_bel_to_edge->
GetI()[row+1] = new_bel_to_edge->
GetI()[row] + ne;
8158 NumOfBdrElements = new_boundary.
Size();
8169 bel_to_edge = new_bel_to_edge;
8173 for (
int i = 0; i < attribs.
Size(); i++)
8175 attribs[i] = GetBdrAttribute(i);
8179 bdr_attributes.DeleteAll();
8180 attribs.
Copy(bdr_attributes);
8185 #ifdef MFEM_USE_MEMALLOC
8188 if (E->
GetType() == Element::TETRAHEDRON)
8206 if (own_nodes) {
delete Nodes; }
8212 for (i = 0; i < NumOfElements; i++)
8214 FreeElement(elements[i]);
8217 for (i = 0; i < NumOfBdrElements; i++)
8219 FreeElement(boundary[i]);
8222 for (i = 0; i < faces.Size(); i++)
8224 FreeElement(faces[i]);
8237 NodeExtrudeCoefficient::NodeExtrudeCoefficient(
const int dim,
const int _n,
8251 V(1) = s * ((ip.
y + layer) / n);
8256 V(2) = s * ((ip.
z + layer) / n);
8265 cerr <<
"Extrude1D : Not a 1D mesh!" << endl;
8269 int nvy = (closed) ? (ny) : (ny + 1);
8270 int nvt = mesh->
GetNV() * nvy;
8279 mesh2d =
new Mesh(2, nvt, mesh->
GetNE()*ny,
8284 for (
int i = 0; i < mesh->
GetNV(); i++)
8287 for (
int j = 0; j < nvy; j++)
8289 vc[1] = sy * (double(j) / ny);
8295 for (
int i = 0; i < mesh->
GetNE(); i++)
8300 for (
int j = 0; j < ny; j++)
8303 qv[0] = vert[0] * nvy + j;
8304 qv[1] = vert[1] * nvy + j;
8305 qv[2] = vert[1] * nvy + (j + 1) % nvy;
8306 qv[3] = vert[0] * nvy + (j + 1) % nvy;
8312 for (
int i = 0; i < mesh->
GetNBE(); i++)
8317 for (
int j = 0; j < ny; j++)
8320 sv[0] = vert[0] * nvy + j;
8321 sv[1] = vert[0] * nvy + (j + 1) % nvy;
8325 Swap<int>(sv[0], sv[1]);
8337 for (
int i = 0; i < mesh->
GetNE(); i++)
8343 sv[0] = vert[0] * nvy;
8344 sv[1] = vert[1] * nvy;
8348 sv[0] = vert[1] * nvy + ny;
8349 sv[1] = vert[0] * nvy + ny;
8365 string cname = name;
8366 if (cname ==
"Linear")
8370 else if (cname ==
"Quadratic")
8374 else if (cname ==
"Cubic")
8378 else if (!strncmp(name,
"H1_", 3))
8382 else if (!strncmp(name,
"L2_T", 4))
8386 else if (!strncmp(name,
"L2_", 3))
8393 cerr <<
"Extrude1D : The mesh uses unknown FE collection : "
8405 for (
int i = 0; i < mesh->
GetNE(); i++)
8408 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.
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
int Size() const
For backward compatibility define Size to be synonym of Width()
std::ostream & operator<<(std::ostream &out, const Mesh &mesh)
Ordering::Type GetOrdering() const
Return the ordering method.
int Size() const
Logical size of the array.
Class for integration rule.
void UpdateOrder(int Order)
Change the order of the collection.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
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 METIS_PartGraphRecursive(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
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.
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 if the new size is different.
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'.
double Det() const
Calculates the determinant of the matrix (for 2x2 or 3x3 matrices)
int GetElementGeometry() const
Return the type of elements in the mesh.
Lists all edges/faces in the nonconforming mesh.
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 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)
const IntegrationPoint & GetCenter(int GeomType)
void GetVertexLocalToGlobal(Array< int > &lvert_vert)
NURBSExtension * GetNURBSext()
int Size_of_connections() const
const IntegrationRule * GetVertices(int GeomType)
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.
IntegrationRules IntRules(0)
A global object with all integration rules (defined in intrules.cpp)
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 CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
std::vector< Master > masters
TriLinear3DFiniteElement HexahedronFE
void AddConnection(int r, int c)
Type
Constants for the classes derived from Element.
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()
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
virtual unsigned GetTransform() const
Return current coarse-fine transformation.
int METIS_SetDefaultOptions(idx_t *options)
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:
int SpaceDimension() const
virtual void Print(std::ostream &out=std::cout) const
Print the mesh to the given stream using the default MFEM mesh format.
virtual unsigned GetTransform() const
Return current coarse-fine transformation.
double * Data() const
Returns vector of the elements.
void Swap(Array< T > &, Array< T > &)
Array< int > bdr_attributes
virtual void PushTransform(int tr)
Add 'tr' to the current chain of coarse-fine transformations.
int SpaceDimension() const
std::vector< Slave > slaves
int GetDof() const
Returns the degrees of freedom in the FE space.
void METIS_PartGraphKway(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
void AddAColumnInRow(int r)
void mfem_error(const char *msg)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
void SetSubVector(const Array< int > &dofs, const Vector &elemvect)
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)
void Save(std::ostream &out)
Prints array to stream out.
Helper struct for defining a connectivity table, see Table::MakeFromList.
Linear3DFiniteElement TetrahedronFE
Array< Element * > elements
Linear2DFiniteElement TriangleFE
void METIS_PartGraphVKway(int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *, int *, idxtype *)
virtual int * DofOrderForOrientation(int GeomType, int Or) const =0
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
NURBSExtension * NURBSext
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)
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.
void GetMeshComponents(Array< mfem::Vertex > &vertices, Array< mfem::Element * > &elements, Array< mfem::Element * > &boundary) const
Return the basic Mesh arrays for the current finest level.
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
virtual int GetNVertices() const =0
int parent
element index in the coarse mesh
void SetAttribute(const int attr)
Set element's attribute.
void ProjectCoefficient(Coefficient &coeff)
Piecewise-(bi)quadratic continuous finite elements.
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.
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
BiLinear2DFiniteElement QuadrilateralFE
Rank 3 tensor (array of matrices)
Abstract data type element.
int GetAttribute(int i) const
Return the attribute of element i.
Data type line segment element.
Linear1DFiniteElement SegmentFE
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