18 #include "../fem/fem.hpp"
19 #include "../general/sort_pairs.hpp"
20 #include "../general/text.hpp"
21 #include "../general/sets.hpp"
36 static void ReadPumiElement(apf::MeshEntity* Ent,
38 const int Attr, apf::Numbering* vert_num,
45 nv = el->GetNVertices();
46 v = el->GetVertices();
49 for (
int i = 0; i < nv; ++i)
51 v[i] = apf::getNumber(vert_num, Verts[i], 0, 0);
55 el->SetAttribute(Attr);
59 static int const tet_rotation[12][4]=
76 static int const tet_inv_rotation[12][4]=
93 static int const tri_rotation[6][3]=
104 static int const tri_inv_rotation[6][3]=
116 static bool same(
int n,
120 for (
int i = 0; i < n; i++)
130 static void rotateSimplex(
int type,
132 apf::MeshEntity** in,
133 apf::MeshEntity**
out)
136 if (type == apf::Mesh::TRIANGLE)
138 MFEM_ASSERT(r>=0 && r<6,
"incorrect rotation");
141 else if (type == apf::Mesh::TET)
143 MFEM_ASSERT(r>=0 && r<12,
"incorrect rotation");
148 MFEM_ASSERT(0,
"unsupported case!");
151 for (
int i = 0; i < n; i++)
154 out[i] = in[tri_rotation[r][i]];
158 out[i] = in[tet_rotation[r][i]];
163 static int findSimplexRotation(apf::Mesh2* apf_mesh,
164 apf::MeshEntity* simplex,
165 apf::MeshEntity** vs)
167 int type = apf_mesh->getType(simplex);
169 if (type == apf::Mesh::TET)
173 else if (type == apf::Mesh::TRIANGLE)
179 MFEM_ASSERT(0,
"unsupported entity type");
182 apf::MeshEntity* dvs[12];
183 apf::MeshEntity* rotated_dvs[12];
184 int nd = apf_mesh->getDownward(simplex, 0, dvs);
186 int first = apf::findIn(dvs, nd, vs[0]);
187 int begin = first*
dim;
188 int end = first*dim +
dim;
189 for (
int r = begin; r < end; r++)
191 rotateSimplex(type, r, dvs, rotated_dvs);
192 if (same(nd, rotated_dvs, vs))
200 static void rotateSimplexXi(apf::Vector3& xi,
int dim,
int rot)
204 for (
int i = 0; i <
dim; i++)
211 int const* inverseIdx = dim == 2 ? tri_inv_rotation[rot] :
212 tet_inv_rotation[rot];
214 for (
int i = 0; i <=
dim; i++)
216 b[inverseIdx[i]] = a[i];
220 xi[2] = dim == 2 ? 1.-xi[0]-xi[1] : b[3];
223 static void unrotateSimplexXi(apf::Vector3& xi,
int dim,
int rot)
227 for (
int i = 0; i <
dim; i++)
234 int const* originalIdx = dim == 2 ? tri_rotation[rot] : tet_rotation[rot];
236 for (
int i = 0; i <=
dim; i++)
238 b[originalIdx[i]] = a[i];
242 xi[2] = dim == 2 ? 1.-xi[0]-xi[1] : b[3];
245 PumiMesh::PumiMesh(apf::Mesh2* apf_mesh,
int generate_edges,
int refine,
246 bool fix_orientation)
248 Load(apf_mesh, generate_edges, refine, fix_orientation);
253 void PumiMesh::CountBoundaryEntity(apf::Mesh2* apf_mesh,
const int BcDim,
256 apf::MeshEntity* ent;
257 apf::MeshIterator* itr = apf_mesh->begin(BcDim);
259 while ((ent=apf_mesh->iterate(itr)))
261 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
262 if (apf_mesh->getModelType(mdEnt) == BcDim)
272 MFEM_ABORT(
"no boundary detected!");
276 void PumiMesh::Load(apf::Mesh2* apf_mesh,
int generate_edges,
int refine,
277 bool fix_orientation)
279 int curved = 0, read_gf = 1;
285 apf::Field* apf_field_crd = apf_mesh->getCoordinateField();
286 apf::FieldShape* crd_shape = apf::getShape(apf_field_crd);
287 apf::Numbering* v_num_loc = apf::createNumbering(apf_mesh,
"VertexNumbering",
290 curved = (crd_shape->getOrder() > 1) ? 1 : 0;
293 ReadSCORECMesh(apf_mesh, v_num_loc, curved);
295 mfem::out <<
"After ReadSCORECMesh" << endl;
315 if (curved && read_gf)
319 crd_shape->getOrder());
325 for (
int i = 0; i < spaceDim; i++)
328 Nodes->GetNodalValues(vert_val, i+1);
329 for (
int j = 0; j < NumOfVertices; j++)
331 vertices[j](i) = vert_val(j);
337 apf::destroyNumbering(v_num_loc);
339 Finalize(refine, fix_orientation);
342 void PumiMesh::ReadSCORECMesh(apf::Mesh2* apf_mesh, apf::Numbering* v_num_loc,
348 apf::MeshIterator* itr = apf_mesh->begin(0);
349 apf::MeshEntity* ent;
351 while ((ent = apf_mesh->iterate(itr)))
354 apf::number(v_num_loc, ent, 0, 0, NumOfVertices);
359 Dim = apf_mesh->getDimension();
360 NumOfElements = countOwned(apf_mesh,Dim);
361 elements.SetSize(NumOfElements);
364 itr = apf_mesh->begin(Dim);
366 while ((ent = apf_mesh->iterate(itr)))
370 apf_mesh->getDownward(ent,0,verts);
374 int geom_type = apf_mesh->getType(ent);
375 elements[j] = NewElement(geom_type);
376 ReadPumiElement(ent, verts, attr, v_num_loc, elements[j]);
385 NumOfBdrElements = 0;
386 CountBoundaryEntity(apf_mesh, BCdim, NumOfBdrElements);
387 boundary.SetSize(NumOfBdrElements);
391 itr = apf_mesh->begin(BCdim);
392 while ((ent = apf_mesh->iterate(itr)))
395 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
396 if (apf_mesh->getModelType(mdEnt) == BCdim)
399 apf_mesh->getDownward(ent, 0, verts);
401 int geom_type = apf_mesh->getType(ent);
402 boundary[j] = NewElement(geom_type);
403 ReadPumiElement(ent, verts, attr, v_num_loc, boundary[j]);
410 vertices.SetSize(NumOfVertices);
414 apf::MeshIterator* itr = apf_mesh->begin(0);
417 while ((ent = apf_mesh->iterate(itr)))
419 unsigned int id = apf::getNumber(v_num_loc, ent, 0, 0);
421 apf_mesh->getPoint(ent,0,Crds);
423 for (
int ii=0; ii<spaceDim; ii++)
425 vertices[id](ii) = Crds[ii];
435 ParPumiMesh::ParPumiMesh(MPI_Comm comm, apf::Mesh2* apf_mesh,
436 int refine,
bool fix_orientation)
442 MPI_Comm_size(MyComm, &NRanks);
443 MPI_Comm_rank(MyComm, &MyRank);
445 Dim = apf_mesh->getDimension();
448 apf::MeshIterator* itr;
449 apf::MeshEntity* ent;
453 apf::Numbering* vLocNum =
454 apf::numberOwnedDimension(apf_mesh,
"AuxVertexNumbering", 0);
455 apf::GlobalNumbering* VertexNumbering = apf::makeGlobal(vLocNum,
true);
456 apf::synchronize(VertexNumbering);
460 itr = apf_mesh->
begin(0);
461 for (
int i = 0; (ent = apf_mesh->iterate(itr)); i++)
463 long id = apf::getNumber(VertexNumbering, ent, 0, 0);
467 apf::destroyGlobalNumbering(VertexNumbering);
472 for (
int j = 0; j < thisVertIds.Size(); j++)
474 const int i = thisVertIds[j].two;
475 thisVertIds[i].one = j;
479 apf::Field* apf_field_crd = apf_mesh->getCoordinateField();
480 apf::FieldShape* crd_shape = apf::getShape(apf_field_crd);
483 v_num_loc = apf_mesh->findNumbering(
"LocalVertexNumbering");
485 v_num_loc = apf::createNumbering(apf_mesh,
486 "LocalVertexNumbering",
490 NumOfVertices = thisVertIds.Size();
491 vertices.SetSize(NumOfVertices);
492 itr = apf_mesh->
begin(0);
493 for (
int i = 0; (ent = apf_mesh->iterate(itr)); i++)
495 const int id = thisVertIds[i].one;
497 apf::number(v_num_loc, ent, 0, 0,
id);
500 apf_mesh->getPoint(ent,0,Crds);
502 for (
int ii=0; ii<spaceDim; ii++)
504 vertices[id](ii) = Crds[ii];
508 thisVertIds.DeleteAll();
511 NumOfElements = countOwned(apf_mesh,Dim);
512 elements.SetSize(NumOfElements);
515 itr = apf_mesh->
begin(Dim);
516 for (
int j = 0; (ent = apf_mesh->iterate(itr)); j++)
520 apf_mesh->getDownward(ent,0,verts);
524 int geom_type = apf_mesh->getType(ent);
525 elements[j] = NewElement(geom_type);
526 ReadPumiElement(ent, verts, attr, v_num_loc, elements[j]);
533 itr = apf_mesh->
begin(BcDim);
534 NumOfBdrElements = 0;
535 while ((ent=apf_mesh->iterate(itr)))
537 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
538 if (apf_mesh->getModelType(mdEnt) == BcDim)
545 boundary.SetSize(NumOfBdrElements);
547 itr = apf_mesh->
begin(BcDim);
548 for (
int bdr_ctr = 0; (ent = apf_mesh->iterate(itr)); )
551 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
552 if (apf_mesh->getModelType(mdEnt) == BcDim)
555 apf_mesh->getDownward(ent, 0, verts);
557 int geom_type = apf_mesh->getType(ent);
558 boundary[bdr_ctr] = NewElement(geom_type);
559 ReadPumiElement(ent, verts, attr, v_num_loc, boundary[bdr_ctr]);
572 this->FinalizeTopology();
581 MFEM_ASSERT(Dim >= 3 || GetNFaces() == 0,
582 "[proc " << MyRank <<
"]: invalid state");
594 apf::Numbering* AuxFaceNum =
595 apf::numberOwnedDimension(apf_mesh,
"AuxFaceNumbering", 2);
596 apf::GlobalNumbering* GlobalFaceNum = apf::makeGlobal(AuxFaceNum,
true);
597 apf::synchronize(GlobalFaceNum);
599 itr = apf_mesh->
begin(2);
600 while ((ent = apf_mesh->iterate(itr)))
602 if (apf_mesh->isShared(ent))
604 long id = apf::getNumber(GlobalFaceNum, ent, 0, 0);
610 apf::destroyGlobalNumbering(GlobalFaceNum);
613 for (
int i = 0; i < sfaces.
Size(); i++)
617 const int thisNumAdjs = 2;
618 int eleRanks[thisNumAdjs];
622 apf_mesh->getResidence(ent, res);
624 for (std::set<int>::iterator itr = res.
begin();
625 itr != res.
end(); ++itr)
627 eleRanks[kk++] = *itr;
631 sfaces[i].one = groups.
Insert(group) - 1;
645 apf::Numbering* AuxEdgeNum =
646 apf::numberOwnedDimension(apf_mesh,
"EdgeNumbering", 1);
647 apf::GlobalNumbering* GlobalEdgeNum = apf::makeGlobal(AuxEdgeNum,
true);
648 apf::synchronize(GlobalEdgeNum);
650 itr = apf_mesh->
begin(1);
651 while ((ent = apf_mesh->iterate(itr)))
653 if (apf_mesh->isShared(ent))
655 long id = apf::getNumber(GlobalEdgeNum, ent, 0, 0);
661 apf::destroyGlobalNumbering(GlobalEdgeNum);
665 for (
int i = 0; i < sedges.
Size(); i++)
671 apf_mesh->getResidence(ent, res);
676 for (std::set<int>::iterator itr = res.
begin();
677 itr != res.
end(); itr++)
679 eleRanks[kk++] = *itr;
684 sedges[i].one = groups.
Insert(group) - 1;
693 itr = apf_mesh->
begin(0);
694 while ((ent = apf_mesh->iterate(itr)))
696 if (apf_mesh->isShared(ent))
698 int vtId = apf::getNumber(v_num_loc, ent, 0, 0);
708 for (
int i = 0; i < sverts.
Size(); i++)
714 apf_mesh->getResidence(ent, res);
719 for (std::set<int>::iterator itr = res.
begin();
720 itr != res.
end(); itr++)
722 eleRanks[kk++] = *itr;
726 svert_group[i] = groups.
Insert(group) - 1;
732 group_stria.MakeI(groups.
Size()-1);
733 group_squad.MakeI(groups.
Size()-1);
734 for (
int i = 0; i < sfaces.
Size(); i++)
736 apf::Mesh::Type ftype = apf_mesh->getType(sfaces[i].two);
737 if (ftype == apf::Mesh::TRIANGLE)
739 group_stria.AddAColumnInRow(sfaces[i].one);
743 group_squad.AddAColumnInRow(sfaces[i].one);
750 for (
int i = 0; i < sfaces.
Size(); i++)
752 apf::Mesh::Type ftype = apf_mesh->getType(sfaces[i].two);
753 if (ftype == apf::Mesh::TRIANGLE)
755 group_stria.AddConnection(sfaces[i].one, nst++);
759 group_squad.AddConnection(sfaces[i].one, i-nst);
762 shared_trias.SetSize(nst);
763 shared_quads.SetSize(sfaces.
Size()-nst);
764 sface_lface.SetSize(sfaces.
Size());
766 group_stria.ShiftUpI();
767 group_squad.ShiftUpI();
770 group_sedge.MakeI(groups.
Size()-1);
771 for (
int i = 0; i < sedges.
Size(); i++)
773 group_sedge.AddAColumnInRow(sedges[i].one);
776 for (
int i = 0; i < sedges.
Size(); i++)
778 group_sedge.AddConnection(sedges[i].one, i);
780 group_sedge.ShiftUpI();
783 group_svert.MakeI(groups.
Size()-1);
784 for (
int i = 0; i < svert_group.
Size(); i++)
786 group_svert.AddAColumnInRow(svert_group[i]);
789 for (
int i = 0; i < svert_group.
Size(); i++)
791 group_svert.AddConnection(svert_group[i], i);
793 group_svert.ShiftUpI();
798 for (
int i = 0; i < sfaces.
Size(); i++)
803 apf_mesh->getDownward(ent,0,verts);
806 apf::Mesh::Type ftype = apf_mesh->getType(ent);
807 if (ftype == apf::Mesh::TRIANGLE)
809 v = shared_trias[nst++].v;
814 v = shared_quads[i-nst].v;
817 for (
int j = 0; j < nv; ++j)
819 v[j] = apf::getNumber(v_num_loc, verts[j], 0, 0);
825 shared_edges.SetSize(sedges.
Size());
826 sedge_ledge. SetSize(sedges.
Size());
827 for (
int i = 0; i < sedges.
Size(); i++)
832 apf_mesh->getDownward(ent, 0, verts);
834 id1 = apf::getNumber(v_num_loc, verts[0], 0, 0);
835 id2 = apf::getNumber(v_num_loc, verts[1], 0, 0);
836 if (id1 > id2) { swap(id1,id2); }
838 shared_edges[i] =
new Segment(id1, id2, 1);
842 svert_lvert.SetSize(sverts.
Size());
843 for (
int i = 0; i < sverts.
Size(); i++)
845 svert_lvert[i] = sverts[i].one;
849 gtopo.Create(groups, 822);
855 int curved = (crd_shape->getOrder() > 1) ? 1 : 0;
859 crd_shape->getOrder());
861 Nodes->Vector::Swap(auxNodes);
862 this->edge_vertex = NULL;
866 Finalize(refine, fix_orientation);
870 GridFunctionPumi::GridFunctionPumi(
Mesh* m, apf::Mesh2* PumiM,
871 apf::Numbering* v_num_loc,
872 const int mesh_order)
877 int ordering = Ordering::byVDIM;
879 int data_size = fes->GetVSize();
882 this->SetSize(data_size);
883 double* PumiData = this->GetData();
885 apf::MeshEntity* ent;
886 apf::MeshIterator* itr;
891 int nnodes = All_nodes.
Size();
894 apf::Field* crd_field = PumiM->getCoordinateField();
896 int nc = apf::countComponents(crd_field);
899 while ((ent = PumiM->iterate(itr)))
902 fes->GetElementVDofs(iel, vdofs);
905 apf::MeshElement* mE = apf::createMeshElement(PumiM, ent);
906 apf::Element* elem = apf::createElement(crd_field, mE);
909 for (
int ip = 0; ip < nnodes; ip++)
918 apf::DynamicVector phCrd(nc);
919 apf::getComponents(elem, param, &phCrd[0]);
922 for (
int kk = 0; kk < spDim; ++kk)
924 int dof_ctr = ip + kk * nnodes;
925 PumiData[vdofs[dof_ctr]] = phCrd[kk];
929 apf::destroyElement(elem);
930 apf::destroyMeshElement(mE);
939 void ParPumiMesh::UpdateMesh(
const ParMesh* AdaptedpMesh)
947 for (
int i = 0; i < shared_edges.Size(); i++)
949 FreeElement(shared_edges[i]);
951 shared_quads.DeleteAll();
952 shared_trias.DeleteAll();
953 shared_edges.DeleteAll();
958 svert_lvert.DeleteAll();
959 sedge_ledge.DeleteAll();
960 sface_lface.DeleteAll();
966 MFEM_ASSERT(Dim == AdaptedpMesh->
Dim,
"");
967 MFEM_ASSERT(spaceDim == AdaptedpMesh->
spaceDim,
"");
968 MFEM_ASSERT(meshgen == AdaptedpMesh->
meshgen,
"");
970 NumOfVertices = AdaptedpMesh->
GetNV();
971 NumOfElements = AdaptedpMesh->
GetNE();
972 NumOfBdrElements = AdaptedpMesh->
GetNBE();
976 meshgen = AdaptedpMesh->
meshgen;
980 last_operation = Mesh::NONE;
983 elements.SetSize(NumOfElements);
984 for (
int i = 0; i < NumOfElements; i++)
990 AdaptedpMesh->
vertices.Copy(vertices);
993 boundary.SetSize(NumOfBdrElements);
994 for (
int i = 0; i < NumOfBdrElements; i++)
1018 faces.SetSize(AdaptedpMesh->
faces.Size());
1019 for (
int i = 0; i < faces.Size(); i++)
1022 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
1041 MFEM_VERIFY(AdaptedpMesh->
NURBSext == NULL,
1042 "invalid adapted mesh: it is a NURBS mesh");
1046 MFEM_VERIFY(AdaptedpMesh->
ncmesh == NULL && AdaptedpMesh->
pncmesh == NULL,
1047 "invalid adapted mesh: it is a non-conforming mesh");
1058 MyComm = AdaptedpMesh->
MyComm;
1059 NRanks = AdaptedpMesh->
NRanks;
1060 MyRank = AdaptedpMesh->
MyRank;
1063 shared_edges.SetSize(AdaptedpMesh->
shared_edges.Size());
1064 for (
int i = 0; i < shared_edges.Size(); i++)
1066 shared_edges[i] = AdaptedpMesh->
shared_edges[i]->Duplicate(
this);
1079 have_face_nbr_data =
false;
1083 if (AdaptedpMesh->
Nodes)
1088 FiniteElementCollection::New(fec->
Name());
1093 Nodes->MakeOwner(fec_copy);
1094 *Nodes = *(AdaptedpMesh->
Nodes);
1099 int ParPumiMesh::RotationPUMItoMFEM(apf::Mesh2* apf_mesh,
1100 apf::MeshEntity* ent,
1103 int type = apf_mesh->getType(ent);
1104 MFEM_ASSERT(apf::isSimplex(type),
1105 "only implemented for simplex entity types");
1108 int nv = apf_mesh->getDownward(ent,0,vs);
1110 for (
int i = 0; i < nv; i++)
1112 pumi_vid[i] = apf::getNumber(v_num_loc, vs[i], 0, 0);
1117 this->GetElementVertices(elemId, mfem_vid);
1120 int pumi_vid_rot[12];
1121 for (
int i = 0; i < nv; i++)
1123 pumi_vid_rot[i] = mfem_vid.
Find(pumi_vid[i]);
1125 apf::Downward vs_rot;
1126 for (
int i = 0; i < nv; i++)
1128 vs_rot[i] = vs[pumi_vid_rot[i]];
1130 return findSimplexRotation(apf_mesh, ent, vs_rot);
1135 apf::MeshEntity* tet,
1137 apf::NewArray<apf::Vector3>& pumi_xi,
1138 bool checkOrientation)
1140 int type = apf_mesh->getType(tet);
1141 MFEM_ASSERT(apf::isSimplex(type),
1142 "only implemented for simplex entity types");
1143 int num_nodes = pumi_xi.size();
1145 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
1146 for (
int i = 0; i < num_nodes; i++)
1151 unrotateSimplexXi(pumi_xi[i], apf::Mesh::typeDimension[type], rotation);
1155 pumi_xi[i].toArray(tmp_xi);
1162 void ParPumiMesh::ParentXisMFEMtoPUMI(apf::Mesh2* apf_mesh,
1164 apf::MeshEntity* tet,
1166 apf::NewArray<apf::Vector3>& pumi_xi,
1167 bool checkOrientation)
1169 int type = apf_mesh->getType(tet);
1170 MFEM_ASSERT(apf::isSimplex(type),
1171 "only implemented for simplex entity types");
1172 int num_nodes = mfem_xi.
Size();
1173 if (!pumi_xi.allocated())
1175 pumi_xi.allocate(num_nodes);
1179 pumi_xi.resize(num_nodes);
1182 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
1183 for (
int i = 0; i < num_nodes; i++)
1186 pumi_xi[i] = apf::Vector3(ip.
x, ip.
y, ip.
z);
1191 rotateSimplexXi(pumi_xi[i], apf::Mesh::typeDimension[type], rotation);
1199 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1202 apf::Field* vel_field,
1203 apf::Field* pr_field,
1204 apf::Field* vel_mag_field)
1206 apf::FieldShape* field_shape = getShape(vel_field);
1207 int dim = apf_mesh->getDimension();
1209 apf::MeshEntity* ent;
1210 apf::MeshIterator* itr = apf_mesh->begin(dim);
1212 while ((ent = apf_mesh->iterate(itr)))
1214 apf::NewArray<apf::Vector3> pumi_nodes;
1215 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1217 apf_mesh, ent, iel, pumi_nodes,
true);
1223 grid_pr->
GetValues(iel, mfem_nodes, pr, 1);
1226 for (
int d = 0; d <=
dim; d++)
1228 if (!field_shape->hasNodesIn(d)) {
continue; }
1230 int na = apf_mesh->getDownward(ent,d,a);
1231 for (
int i = 0; i < na; i++)
1233 int type = apf_mesh->getType(a[i]);
1234 int nan = field_shape->countNodesOn(type);
1235 for (
int n = 0; n < nan; n++)
1238 apf::setVector(vel_field, a[i], n, v);
1239 apf::setScalar(pr_field, a[i], n, pr[non]);
1240 apf::setScalar(vel_mag_field, a[i], n, v.getLength());
1251 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1253 apf::Field* pr_field,
1254 apf::Field* pr_mag_field)
1256 apf::FieldShape* field_shape = getShape(pr_field);
1257 int dim = apf_mesh->getDimension();
1259 apf::MeshEntity* ent;
1260 apf::MeshIterator* itr = apf_mesh->begin(dim);
1262 while ((ent = apf_mesh->iterate(itr)))
1264 apf::NewArray<apf::Vector3> pumi_nodes;
1265 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1267 apf_mesh, ent, iel, pumi_nodes,
true);
1270 grid_pr->
GetValues(iel, mfem_nodes, vals, 1);
1273 for (
int d = 0; d <=
dim; d++)
1275 if (!field_shape->hasNodesIn(d)) {
continue; }
1277 int na = apf_mesh->getDownward(ent,d,a);
1278 for (
int i = 0; i < na; i++)
1280 int type = apf_mesh->getType(a[i]);
1281 int nan = field_shape->countNodesOn(type);
1282 for (
int n = 0; n < nan; n++)
1284 double pr = vals[non];
1285 double pr_mag = pr >= 0 ? pr : -pr;
1286 apf::setScalar(pr_field, a[i], n, pr);
1287 apf::setScalar(pr_mag_field, a[i], n, pr_mag);
1299 void ParPumiMesh::VectorFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1301 apf::Field* vel_field,
1302 apf::Field* vel_mag_field)
1304 apf::FieldShape* field_shape = getShape(vel_field);
1305 int dim = apf_mesh->getDimension();
1307 apf::MeshEntity* ent;
1308 apf::MeshIterator* itr = apf_mesh->begin(dim);
1310 while ((ent = apf_mesh->iterate(itr)))
1312 apf::NewArray<apf::Vector3> pumi_nodes;
1313 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1315 apf_mesh, ent, iel, pumi_nodes,
true);
1322 for (
int d = 0; d <=
dim; d++)
1324 if (!field_shape->hasNodesIn(d)) {
continue; }
1326 int na = apf_mesh->getDownward(ent,d,a);
1327 for (
int i = 0; i < na; i++)
1329 int type = apf_mesh->getType(a[i]);
1330 int nan = field_shape->countNodesOn(type);
1331 for (
int n = 0; n < nan; n++)
1334 apf::setScalar(vel_mag_field, a[i], n, v.getLength());
1335 apf::setVector(vel_field, a[i], n, v);
1345 void ParPumiMesh::NedelecFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1347 apf::Field* nedelec_field)
1349 apf::FieldShape* nedelecFieldShape = nedelec_field->getShape();
1350 int dim = apf_mesh->getDimension();
1354 apf::MeshEntity* ent;
1355 apf::MeshIterator* it = apf_mesh->begin(dim);
1356 while ( (ent = apf_mesh->iterate(it)) )
1359 apf::NewArray<apf::Vector3> pumi_nodes;
1360 apf::getElementNodeXis(nedelecFieldShape, apf_mesh, ent, pumi_nodes);
1362 apf_mesh, ent, elemNo, pumi_nodes,
true);
1370 for (
int d = 0; d <=
dim; d++)
1372 if (!nedelecFieldShape->hasNodesIn(d)) {
continue; }
1374 int na = apf_mesh->getDownward(ent,d,a);
1375 for (
int i = 0; i < na; i++)
1377 int type = apf_mesh->getType(a[i]);
1378 int nan = nedelecFieldShape->countNodesOn(type);
1379 apf::MeshElement* me = apf::createMeshElement(apf_mesh, a[i]);
1380 for (
int n = 0; n < nan; n++)
1382 apf::Vector3 xi, tangent;
1383 nedelecFieldShape->getNodeXi(type, n, xi);
1384 nedelecFieldShape->getNodeTangent(type, n, tangent);
1385 apf::Vector3 pumi_field_vector(mfem_field_vals.
GetColumn(non));
1387 apf::getJacobian(me, xi, J);
1388 double dof = (J * pumi_field_vector) * tangent;
1389 apf::setScalar(nedelec_field, a[i], n, dof);
1392 apf::destroyMeshElement(me);
1400 void ParPumiMesh::FieldPUMItoMFEM(apf::Mesh2* apf_mesh,
1404 int nc = apf::countComponents(field);
1408 int dim = apf_mesh->getDimension();
1410 apf::MeshIterator* it = apf_mesh->begin(dim);
1411 for (
int i = 0; i < pmesh->
GetNE(); i++)
1415 int non = mfem_xi.
Size();
1416 apf::MeshEntity* ent = apf_mesh->iterate(it);
1417 apf::NewArray<apf::Vector3> pumi_xi(non);
1418 ParentXisMFEMtoPUMI(apf_mesh,
1426 apf::MeshElement* me = apf::createMeshElement(apf_mesh, ent);
1427 apf::Element* el = apf::createElement(field, me);
1428 for (
int j = 0; j < non; j++)
1430 apf::DynamicVector values(nc);
1431 apf::getComponents(el, pumi_xi[j], &values[0]);
1433 for (
int c = 0; c < nc; c++)
1435 int dof_loc = j + c * non;
1436 (grid->
GetData())[vdofs[dof_loc]] = values[c];
1439 apf::destroyElement(el);
1440 apf::destroyMeshElement(me);
1447 #endif // MFEM_USE_MPI
1448 #endif // MFEM_USE_SCOREC
Abstract class for all finite elements.
void Set(const double *p, const int dim)
Ordering::Type GetOrdering() const
Return the ordering method.
int Size() const
Return the logical size of the array.
void Recreate(const int n, const int *p)
Create an integer set from C-array 'p' of 'n' integers. Overwrites any existing set data...
Class for an integration rule - an Array of IntegrationPoint.
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
T * end()
STL-like end. Returns pointer after the last element of the array.
virtual Element * Duplicate(Mesh *m) const =0
ParMesh * GetParMesh() const
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 Copy(Array ©) const
Create a copy of the internal array to the provided copy.
Class for PUMI grid functions.
Data type dense matrix using column-major storage.
int GetNE() const
Returns number of elements.
Abstract parallel finite element space.
Array< Vert3 > shared_trias
constexpr Element::Type QUAD
double * GetData() const
Return a pointer to the beginning of the Vector data.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
virtual const FiniteElement * GetFE(int i) const
Array< Element * > shared_edges
int Append(const T &el)
Append element 'el' to array, resize if necessary.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
int Insert(IntegerSet &s)
Check to see if set 's' is in the list. If not append it to the end of the list. Returns the index of...
T * begin()
STL-like begin. Returns pointer to the first element of the array.
const Element * GetElement(int i) const
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
int GetVDim() const
Returns vector dimension.
FiniteElementSpace * FESpace()
int Size()
Return the number of integer sets in the list.
void GetColumn(int c, Vector &col) const
Array< Vert4 > shared_quads
void Copy(GroupTopology ©) const
Copy the internal data to the external 'copy'.
int SpaceDimension() const
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual const char * Name() const
Class for integration point with weight.
void vel(const Vector &x, double t, Vector &u)
Table group_svert
Shared objects in each group.
Array< FaceInfo > faces_info
NCMesh * ncmesh
Optional non-conforming mesh extension.
int GetNEdges() const
Return the number of edges.
int GetNFaces() const
Return the number of faces in a 3D mesh.
const FiniteElementCollection * FEColl() const
Arbitrary order H1-conforming (continuous) finite elements.
Array< int > svert_lvert
Shared to local index mapping.
Class for parallel grid function.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Class for parallel meshes.
Abstract data type element.
Data type line segment element.
void Copy(Table ©) const
Array< int > attributes
A list of all unique element attributes used by the Mesh.
const Element * GetBdrElement(int i) const
ParFiniteElementSpace * ParFESpace() const