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** simplex_in,
133 apf::MeshEntity** simplex_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 simplex_out[i] = simplex_in[tri_rotation[r][i]];
158 simplex_out[i] = simplex_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 const char* gmshTagName =
"gmsh_physical_entity";
365 apf::MeshTag* gmshPhysEnt = apf_mesh->findTag(gmshTagName);
368 itr = apf_mesh->begin(Dim);
370 while ((ent = apf_mesh->iterate(itr)))
374 apf_mesh->getDownward(ent,0,verts);
379 apf_mesh->getIntTag(ent,gmshPhysEnt,&attr);
382 int geom_type = apf_mesh->getType(ent);
383 elements[j] = NewElement(geom_type);
384 ReadPumiElement(ent, verts, attr, v_num_loc, elements[j]);
393 NumOfBdrElements = 0;
394 CountBoundaryEntity(apf_mesh, BCdim, NumOfBdrElements);
395 boundary.SetSize(NumOfBdrElements);
399 itr = apf_mesh->begin(BCdim);
400 while ((ent = apf_mesh->iterate(itr)))
403 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
404 if (apf_mesh->getModelType(mdEnt) == BCdim)
407 apf_mesh->getDownward(ent, 0, verts);
409 int geom_type = apf_mesh->getType(ent);
410 boundary[j] = NewElement(geom_type);
411 ReadPumiElement(ent, verts, attr, v_num_loc, boundary[j]);
418 vertices.SetSize(NumOfVertices);
422 itr = apf_mesh->begin(0);
425 while ((ent = apf_mesh->iterate(itr)))
427 unsigned int id = apf::getNumber(v_num_loc, ent, 0, 0);
429 apf_mesh->getPoint(ent,0,Crds);
431 for (
int ii=0; ii<spaceDim; ii++)
433 vertices[id](ii) = Crds[ii];
443 ParPumiMesh::ParPumiMesh(MPI_Comm comm, apf::Mesh2* apf_mesh,
444 int refine,
bool fix_orientation)
450 MPI_Comm_size(MyComm, &NRanks);
451 MPI_Comm_rank(MyComm, &MyRank);
453 Dim = apf_mesh->getDimension();
456 apf::MeshIterator* itr;
457 apf::MeshEntity* ent;
461 apf::Numbering* vLocNum =
462 apf::numberOwnedDimension(apf_mesh,
"AuxVertexNumbering", 0);
463 apf::GlobalNumbering* VertexNumbering = apf::makeGlobal(vLocNum,
true);
464 apf::synchronize(VertexNumbering);
468 itr = apf_mesh->
begin(0);
469 for (
int i = 0; (ent = apf_mesh->iterate(itr)); i++)
471 long id = apf::getNumber(VertexNumbering, ent, 0, 0);
475 apf::destroyGlobalNumbering(VertexNumbering);
480 for (
int j = 0; j < thisVertIds.Size(); j++)
482 const int i = thisVertIds[j].two;
483 thisVertIds[i].one = j;
487 apf::Field* apf_field_crd = apf_mesh->getCoordinateField();
488 apf::FieldShape* crd_shape = apf::getShape(apf_field_crd);
491 v_num_loc = apf_mesh->findNumbering(
"LocalVertexNumbering");
493 v_num_loc = apf::createNumbering(apf_mesh,
494 "LocalVertexNumbering",
498 NumOfVertices = thisVertIds.Size();
499 vertices.SetSize(NumOfVertices);
500 itr = apf_mesh->
begin(0);
501 for (
int i = 0; (ent = apf_mesh->iterate(itr)); i++)
503 const int id = thisVertIds[i].one;
505 apf::number(v_num_loc, ent, 0, 0,
id);
508 apf_mesh->getPoint(ent,0,Crds);
510 for (
int ii=0; ii<spaceDim; ii++)
512 vertices[id](ii) = Crds[ii];
516 thisVertIds.DeleteAll();
519 NumOfElements = countOwned(apf_mesh,Dim);
520 elements.SetSize(NumOfElements);
523 const char* gmshTagName =
"gmsh_physical_entity";
524 apf::MeshTag* gmshPhysEnt = apf_mesh->findTag(gmshTagName);
527 itr = apf_mesh->
begin(Dim);
528 for (
int j = 0; (ent = apf_mesh->iterate(itr)); j++)
532 apf_mesh->getDownward(ent,0,verts);
537 apf_mesh->getIntTag(ent,gmshPhysEnt,&attr);
541 int geom_type = apf_mesh->getType(ent);
542 elements[j] = NewElement(geom_type);
543 ReadPumiElement(ent, verts, attr, v_num_loc, elements[j]);
550 itr = apf_mesh->
begin(BcDim);
551 NumOfBdrElements = 0;
552 while ((ent=apf_mesh->iterate(itr)))
554 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
555 if (apf_mesh->getModelType(mdEnt) == BcDim)
562 boundary.SetSize(NumOfBdrElements);
564 itr = apf_mesh->
begin(BcDim);
565 for (
int bdr_ctr = 0; (ent = apf_mesh->iterate(itr)); )
568 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
569 if (apf_mesh->getModelType(mdEnt) == BcDim)
572 apf_mesh->getDownward(ent, 0, verts);
574 int geom_type = apf_mesh->getType(ent);
575 boundary[bdr_ctr] = NewElement(geom_type);
576 ReadPumiElement(ent, verts, attr, v_num_loc, boundary[bdr_ctr]);
589 this->FinalizeTopology();
598 MFEM_ASSERT(Dim >= 3 || GetNFaces() == 0,
599 "[proc " << MyRank <<
"]: invalid state");
611 apf::Numbering* AuxFaceNum =
612 apf::numberOwnedDimension(apf_mesh,
"AuxFaceNumbering", 2);
613 apf::GlobalNumbering* GlobalFaceNum = apf::makeGlobal(AuxFaceNum,
true);
614 apf::synchronize(GlobalFaceNum);
616 itr = apf_mesh->
begin(2);
617 while ((ent = apf_mesh->iterate(itr)))
619 if (apf_mesh->isShared(ent))
621 long id = apf::getNumber(GlobalFaceNum, ent, 0, 0);
627 apf::destroyGlobalNumbering(GlobalFaceNum);
630 for (
int i = 0; i < sfaces.
Size(); i++)
634 const int thisNumAdjs = 2;
635 int eleRanks[thisNumAdjs];
639 apf_mesh->getResidence(ent, res);
641 for (std::set<int>::iterator res_itr = res.begin();
642 res_itr != res.end(); ++res_itr)
644 eleRanks[kk++] = *res_itr;
648 sfaces[i].one = groups.
Insert(group) - 1;
662 apf::Numbering* AuxEdgeNum =
663 apf::numberOwnedDimension(apf_mesh,
"EdgeNumbering", 1);
664 apf::GlobalNumbering* GlobalEdgeNum = apf::makeGlobal(AuxEdgeNum,
true);
665 apf::synchronize(GlobalEdgeNum);
667 itr = apf_mesh->
begin(1);
668 while ((ent = apf_mesh->iterate(itr)))
670 if (apf_mesh->isShared(ent))
672 long id = apf::getNumber(GlobalEdgeNum, ent, 0, 0);
678 apf::destroyGlobalNumbering(GlobalEdgeNum);
682 for (
int i = 0; i < sedges.
Size(); i++)
688 apf_mesh->getResidence(ent, res);
693 for (std::set<int>::iterator res_itr = res.begin();
694 res_itr != res.end(); res_itr++)
696 eleRanks[kk++] = *res_itr;
701 sedges[i].one = groups.
Insert(group) - 1;
710 itr = apf_mesh->
begin(0);
711 while ((ent = apf_mesh->iterate(itr)))
713 if (apf_mesh->isShared(ent))
715 int vtId = apf::getNumber(v_num_loc, ent, 0, 0);
725 for (
int i = 0; i < sverts.
Size(); i++)
731 apf_mesh->getResidence(ent, res);
736 for (std::set<int>::iterator res_itr = res.begin();
737 res_itr != res.end(); res_itr++)
739 eleRanks[kk++] = *res_itr;
743 svert_group[i] = groups.
Insert(group) - 1;
749 group_stria.MakeI(groups.
Size()-1);
750 group_squad.MakeI(groups.
Size()-1);
751 for (
int i = 0; i < sfaces.
Size(); i++)
753 apf::Mesh::Type ftype = apf_mesh->getType(sfaces[i].two);
754 if (ftype == apf::Mesh::TRIANGLE)
756 group_stria.AddAColumnInRow(sfaces[i].one);
760 group_squad.AddAColumnInRow(sfaces[i].one);
767 for (
int i = 0; i < sfaces.
Size(); i++)
769 apf::Mesh::Type ftype = apf_mesh->getType(sfaces[i].two);
770 if (ftype == apf::Mesh::TRIANGLE)
772 group_stria.AddConnection(sfaces[i].one, nst++);
776 group_squad.AddConnection(sfaces[i].one, i-nst);
779 shared_trias.SetSize(nst);
780 shared_quads.SetSize(sfaces.
Size()-nst);
781 sface_lface.SetSize(sfaces.
Size());
783 group_stria.ShiftUpI();
784 group_squad.ShiftUpI();
787 group_sedge.MakeI(groups.
Size()-1);
788 for (
int i = 0; i < sedges.
Size(); i++)
790 group_sedge.AddAColumnInRow(sedges[i].one);
793 for (
int i = 0; i < sedges.
Size(); i++)
795 group_sedge.AddConnection(sedges[i].one, i);
797 group_sedge.ShiftUpI();
800 group_svert.MakeI(groups.
Size()-1);
801 for (
int i = 0; i < svert_group.
Size(); i++)
803 group_svert.AddAColumnInRow(svert_group[i]);
806 for (
int i = 0; i < svert_group.
Size(); i++)
808 group_svert.AddConnection(svert_group[i], i);
810 group_svert.ShiftUpI();
815 for (
int i = 0; i < sfaces.
Size(); i++)
820 apf_mesh->getDownward(ent,0,verts);
823 apf::Mesh::Type ftype = apf_mesh->getType(ent);
824 if (ftype == apf::Mesh::TRIANGLE)
826 v = shared_trias[nst++].v;
831 v = shared_quads[i-nst].v;
834 for (
int j = 0; j < nv; ++j)
836 v[j] = apf::getNumber(v_num_loc, verts[j], 0, 0);
842 shared_edges.SetSize(sedges.
Size());
843 sedge_ledge. SetSize(sedges.
Size());
844 for (
int i = 0; i < sedges.
Size(); i++)
849 apf_mesh->getDownward(ent, 0, verts);
851 id1 = apf::getNumber(v_num_loc, verts[0], 0, 0);
852 id2 = apf::getNumber(v_num_loc, verts[1], 0, 0);
853 if (id1 > id2) { swap(id1,id2); }
855 shared_edges[i] =
new Segment(id1, id2, 1);
859 svert_lvert.SetSize(sverts.
Size());
860 for (
int i = 0; i < sverts.
Size(); i++)
862 svert_lvert[i] = sverts[i].one;
866 gtopo.Create(groups, 822);
872 int curved = (crd_shape->getOrder() > 1) ? 1 : 0;
876 crd_shape->getOrder());
878 Nodes->Vector::Swap(auxNodes);
879 this->edge_vertex = NULL;
883 Finalize(refine, fix_orientation);
887 GridFunctionPumi::GridFunctionPumi(
Mesh* m, apf::Mesh2* PumiM,
888 apf::Numbering* v_num_loc,
889 const int mesh_order)
894 int ordering = Ordering::byVDIM;
896 int data_size = fes->GetVSize();
899 this->SetSize(data_size);
900 double* PumiData = this->GetData();
902 apf::MeshEntity* ent;
903 apf::MeshIterator* itr;
908 int nnodes = All_nodes.
Size();
911 apf::Field* crd_field = PumiM->getCoordinateField();
913 int nc = apf::countComponents(crd_field);
916 while ((ent = PumiM->iterate(itr)))
919 fes->GetElementVDofs(iel, vdofs);
922 apf::MeshElement* mE = apf::createMeshElement(PumiM, ent);
923 apf::Element* elem = apf::createElement(crd_field, mE);
926 for (
int ip = 0; ip < nnodes; ip++)
935 apf::DynamicVector phCrd(nc);
936 apf::getComponents(elem, param, &phCrd[0]);
939 for (
int kk = 0; kk < spDim; ++kk)
941 int dof_ctr = ip + kk * nnodes;
942 PumiData[vdofs[dof_ctr]] = phCrd[kk];
946 apf::destroyElement(elem);
947 apf::destroyMeshElement(mE);
956 void ParPumiMesh::UpdateMesh(
const ParMesh* AdaptedpMesh)
964 for (
int i = 0; i < shared_edges.Size(); i++)
966 FreeElement(shared_edges[i]);
968 shared_quads.DeleteAll();
969 shared_trias.DeleteAll();
970 shared_edges.DeleteAll();
975 svert_lvert.DeleteAll();
976 sedge_ledge.DeleteAll();
977 sface_lface.DeleteAll();
983 MFEM_ASSERT(Dim == AdaptedpMesh->
Dim,
"");
984 MFEM_ASSERT(spaceDim == AdaptedpMesh->
spaceDim,
"");
985 MFEM_ASSERT(meshgen == AdaptedpMesh->
meshgen,
"");
987 NumOfVertices = AdaptedpMesh->
GetNV();
988 NumOfElements = AdaptedpMesh->
GetNE();
989 NumOfBdrElements = AdaptedpMesh->
GetNBE();
993 meshgen = AdaptedpMesh->
meshgen;
997 last_operation = Mesh::NONE;
1000 elements.SetSize(NumOfElements);
1001 for (
int i = 0; i < NumOfElements; i++)
1007 AdaptedpMesh->
vertices.Copy(vertices);
1010 boundary.SetSize(NumOfBdrElements);
1011 for (
int i = 0; i < NumOfBdrElements; i++)
1035 faces.SetSize(AdaptedpMesh->
faces.Size());
1036 for (
int i = 0; i < faces.Size(); i++)
1039 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
1058 MFEM_VERIFY(AdaptedpMesh->
NURBSext == NULL,
1059 "invalid adapted mesh: it is a NURBS mesh");
1063 MFEM_VERIFY(AdaptedpMesh->
ncmesh == NULL && AdaptedpMesh->
pncmesh == NULL,
1064 "invalid adapted mesh: it is a non-conforming mesh");
1075 MyComm = AdaptedpMesh->
MyComm;
1076 NRanks = AdaptedpMesh->
NRanks;
1077 MyRank = AdaptedpMesh->
MyRank;
1080 shared_edges.SetSize(AdaptedpMesh->
shared_edges.Size());
1081 for (
int i = 0; i < shared_edges.Size(); i++)
1083 shared_edges[i] = AdaptedpMesh->
shared_edges[i]->Duplicate(
this);
1096 have_face_nbr_data =
false;
1100 if (AdaptedpMesh->
Nodes)
1105 FiniteElementCollection::New(fec->
Name());
1110 Nodes->MakeOwner(fec_copy);
1111 *Nodes = *(AdaptedpMesh->
Nodes);
1116 int ParPumiMesh::RotationPUMItoMFEM(apf::Mesh2* apf_mesh,
1117 apf::MeshEntity* ent,
1120 int type = apf_mesh->getType(ent);
1121 MFEM_ASSERT(apf::isSimplex(type),
1122 "only implemented for simplex entity types");
1125 int nv = apf_mesh->getDownward(ent,0,vs);
1127 for (
int i = 0; i < nv; i++)
1129 pumi_vid[i] = apf::getNumber(v_num_loc, vs[i], 0, 0);
1134 this->GetElementVertices(elemId, mfem_vid);
1137 int pumi_vid_rot[12];
1138 for (
int i = 0; i < nv; i++)
1140 pumi_vid_rot[i] = mfem_vid.
Find(pumi_vid[i]);
1142 apf::Downward vs_rot;
1143 for (
int i = 0; i < nv; i++)
1145 vs_rot[i] = vs[pumi_vid_rot[i]];
1147 return findSimplexRotation(apf_mesh, ent, vs_rot);
1152 apf::MeshEntity* tet,
1154 apf::NewArray<apf::Vector3>& pumi_xi,
1155 bool checkOrientation)
1157 int type = apf_mesh->getType(tet);
1158 MFEM_ASSERT(apf::isSimplex(type),
1159 "only implemented for simplex entity types");
1160 int num_nodes = pumi_xi.size();
1162 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
1163 for (
int i = 0; i < num_nodes; i++)
1168 unrotateSimplexXi(pumi_xi[i], apf::Mesh::typeDimension[type], rotation);
1172 pumi_xi[i].toArray(tmp_xi);
1179 void ParPumiMesh::ParentXisMFEMtoPUMI(apf::Mesh2* apf_mesh,
1181 apf::MeshEntity* tet,
1183 apf::NewArray<apf::Vector3>& pumi_xi,
1184 bool checkOrientation)
1186 int type = apf_mesh->getType(tet);
1187 MFEM_ASSERT(apf::isSimplex(type),
1188 "only implemented for simplex entity types");
1189 int num_nodes = mfem_xi.
Size();
1190 if (!pumi_xi.allocated())
1192 pumi_xi.allocate(num_nodes);
1196 pumi_xi.resize(num_nodes);
1199 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
1200 for (
int i = 0; i < num_nodes; i++)
1203 pumi_xi[i] = apf::Vector3(ip.
x, ip.
y, ip.
z);
1208 rotateSimplexXi(pumi_xi[i], apf::Mesh::typeDimension[type], rotation);
1216 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1219 apf::Field* vel_field,
1220 apf::Field* pr_field,
1221 apf::Field* vel_mag_field)
1223 apf::FieldShape* field_shape = getShape(vel_field);
1224 int dim = apf_mesh->getDimension();
1226 apf::MeshEntity* ent;
1227 apf::MeshIterator* itr = apf_mesh->begin(dim);
1229 while ((ent = apf_mesh->iterate(itr)))
1231 apf::NewArray<apf::Vector3> pumi_nodes;
1232 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1234 apf_mesh, ent, iel, pumi_nodes,
true);
1240 grid_pr->
GetValues(iel, mfem_nodes, pr, 1);
1243 for (
int d = 0; d <=
dim; d++)
1245 if (!field_shape->hasNodesIn(d)) {
continue; }
1247 int na = apf_mesh->getDownward(ent,d,a);
1248 for (
int i = 0; i < na; i++)
1250 int type = apf_mesh->getType(a[i]);
1251 int nan = field_shape->countNodesOn(type);
1252 for (
int n = 0; n < nan; n++)
1255 apf::setVector(vel_field, a[i], n, v);
1256 apf::setScalar(pr_field, a[i], n, pr[non]);
1257 apf::setScalar(vel_mag_field, a[i], n, v.getLength());
1268 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1270 apf::Field* pr_field,
1271 apf::Field* pr_mag_field)
1273 apf::FieldShape* field_shape = getShape(pr_field);
1274 int dim = apf_mesh->getDimension();
1276 apf::MeshEntity* ent;
1277 apf::MeshIterator* itr = apf_mesh->begin(dim);
1279 while ((ent = apf_mesh->iterate(itr)))
1281 apf::NewArray<apf::Vector3> pumi_nodes;
1282 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1284 apf_mesh, ent, iel, pumi_nodes,
true);
1287 grid_pr->
GetValues(iel, mfem_nodes, vals, 1);
1290 for (
int d = 0; d <=
dim; d++)
1292 if (!field_shape->hasNodesIn(d)) {
continue; }
1294 int na = apf_mesh->getDownward(ent,d,a);
1295 for (
int i = 0; i < na; i++)
1297 int type = apf_mesh->getType(a[i]);
1298 int nan = field_shape->countNodesOn(type);
1299 for (
int n = 0; n < nan; n++)
1301 double pr = vals[non];
1302 double pr_mag = pr >= 0 ? pr : -pr;
1303 apf::setScalar(pr_field, a[i], n, pr);
1304 apf::setScalar(pr_mag_field, a[i], n, pr_mag);
1316 void ParPumiMesh::VectorFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1318 apf::Field* vel_field,
1319 apf::Field* vel_mag_field)
1321 apf::FieldShape* field_shape = getShape(vel_field);
1322 int dim = apf_mesh->getDimension();
1324 apf::MeshEntity* ent;
1325 apf::MeshIterator* itr = apf_mesh->begin(dim);
1327 while ((ent = apf_mesh->iterate(itr)))
1329 apf::NewArray<apf::Vector3> pumi_nodes;
1330 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1332 apf_mesh, ent, iel, pumi_nodes,
true);
1339 for (
int d = 0; d <=
dim; d++)
1341 if (!field_shape->hasNodesIn(d)) {
continue; }
1343 int na = apf_mesh->getDownward(ent,d,a);
1344 for (
int i = 0; i < na; i++)
1346 int type = apf_mesh->getType(a[i]);
1347 int nan = field_shape->countNodesOn(type);
1348 for (
int n = 0; n < nan; n++)
1351 apf::setScalar(vel_mag_field, a[i], n, v.getLength());
1352 apf::setVector(vel_field, a[i], n, v);
1362 void ParPumiMesh::NedelecFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1364 apf::Field* nedelec_field)
1366 apf::FieldShape* nedelecFieldShape = nedelec_field->getShape();
1367 int dim = apf_mesh->getDimension();
1371 apf::MeshEntity* ent;
1372 apf::MeshIterator* it = apf_mesh->begin(dim);
1373 while ( (ent = apf_mesh->iterate(it)) )
1376 apf::NewArray<apf::Vector3> pumi_nodes;
1377 apf::getElementNodeXis(nedelecFieldShape, apf_mesh, ent, pumi_nodes);
1379 apf_mesh, ent, elemNo, pumi_nodes,
true);
1387 for (
int d = 0; d <=
dim; d++)
1389 if (!nedelecFieldShape->hasNodesIn(d)) {
continue; }
1391 int na = apf_mesh->getDownward(ent,d,a);
1392 for (
int i = 0; i < na; i++)
1394 int type = apf_mesh->getType(a[i]);
1395 int nan = nedelecFieldShape->countNodesOn(type);
1396 apf::MeshElement* me = apf::createMeshElement(apf_mesh, a[i]);
1397 for (
int n = 0; n < nan; n++)
1399 apf::Vector3 xi, tangent;
1400 nedelecFieldShape->getNodeXi(type, n, xi);
1401 nedelecFieldShape->getNodeTangent(type, n, tangent);
1402 apf::Vector3 pumi_field_vector(mfem_field_vals.
GetColumn(non));
1404 apf::getJacobian(me, xi, J);
1405 double dof = (J * pumi_field_vector) * tangent;
1406 apf::setScalar(nedelec_field, a[i], n, dof);
1409 apf::destroyMeshElement(me);
1417 void ParPumiMesh::FieldPUMItoMFEM(apf::Mesh2* apf_mesh,
1421 int nc = apf::countComponents(field);
1425 int dim = apf_mesh->getDimension();
1427 apf::MeshIterator* it = apf_mesh->begin(dim);
1428 for (
int i = 0; i < pmesh->
GetNE(); i++)
1432 int non = mfem_xi.
Size();
1433 apf::MeshEntity* ent = apf_mesh->iterate(it);
1434 apf::NewArray<apf::Vector3> pumi_xi(non);
1435 ParentXisMFEMtoPUMI(apf_mesh,
1443 apf::MeshElement* me = apf::createMeshElement(apf_mesh, ent);
1444 apf::Element* el = apf::createElement(field, me);
1445 for (
int j = 0; j < non; j++)
1447 apf::DynamicVector values(nc);
1448 apf::getComponents(el, pumi_xi[j], &values[0]);
1450 for (
int c = 0; c < nc; c++)
1452 int dof_loc = j + c * non;
1453 (grid->
GetData())[vdofs[dof_loc]] = values[c];
1456 apf::destroyElement(el);
1457 apf::destroyMeshElement(me);
1464 #endif // MFEM_USE_MPI
1465 #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
virtual Element * Duplicate(Mesh *m) const =0
ParMesh * GetParMesh() const
int GetNBE() const
Returns number of boundary elements.
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.
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
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 nonconforming 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