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_CONTRACT_VAR(type);
1122 MFEM_ASSERT(apf::isSimplex(type),
1123 "only implemented for simplex entity types");
1126 int nv = apf_mesh->getDownward(ent,0,vs);
1128 for (
int i = 0; i < nv; i++)
1130 pumi_vid[i] = apf::getNumber(v_num_loc, vs[i], 0, 0);
1135 this->GetElementVertices(elemId, mfem_vid);
1138 int pumi_vid_rot[12];
1139 for (
int i = 0; i < nv; i++)
1141 pumi_vid_rot[i] = mfem_vid.
Find(pumi_vid[i]);
1143 apf::Downward vs_rot;
1144 for (
int i = 0; i < nv; i++)
1146 vs_rot[i] = vs[pumi_vid_rot[i]];
1148 return findSimplexRotation(apf_mesh, ent, vs_rot);
1153 apf::MeshEntity* tet,
1155 apf::NewArray<apf::Vector3>& pumi_xi,
1156 bool checkOrientation)
1158 int type = apf_mesh->getType(tet);
1159 MFEM_ASSERT(apf::isSimplex(type),
1160 "only implemented for simplex entity types");
1161 int num_nodes = pumi_xi.size();
1163 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
1164 for (
int i = 0; i < num_nodes; i++)
1169 unrotateSimplexXi(pumi_xi[i], apf::Mesh::typeDimension[type], rotation);
1173 pumi_xi[i].toArray(tmp_xi);
1180 void ParPumiMesh::ParentXisMFEMtoPUMI(apf::Mesh2* apf_mesh,
1182 apf::MeshEntity* tet,
1184 apf::NewArray<apf::Vector3>& pumi_xi,
1185 bool checkOrientation)
1187 int type = apf_mesh->getType(tet);
1188 MFEM_ASSERT(apf::isSimplex(type),
1189 "only implemented for simplex entity types");
1190 int num_nodes = mfem_xi.
Size();
1191 if (!pumi_xi.allocated())
1193 pumi_xi.allocate(num_nodes);
1197 pumi_xi.resize(num_nodes);
1200 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
1201 for (
int i = 0; i < num_nodes; i++)
1204 pumi_xi[i] = apf::Vector3(ip.
x, ip.
y, ip.
z);
1209 rotateSimplexXi(pumi_xi[i], apf::Mesh::typeDimension[type], rotation);
1217 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1220 apf::Field* vel_field,
1221 apf::Field* pr_field,
1222 apf::Field* vel_mag_field)
1224 apf::FieldShape* field_shape = getShape(vel_field);
1225 int dim = apf_mesh->getDimension();
1227 apf::MeshEntity* ent;
1228 apf::MeshIterator* itr = apf_mesh->begin(
dim);
1230 while ((ent = apf_mesh->iterate(itr)))
1232 apf::NewArray<apf::Vector3> pumi_nodes;
1233 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1235 apf_mesh, ent, iel, pumi_nodes,
true);
1241 grid_pr->
GetValues(iel, mfem_nodes, pr, 1);
1244 for (
int d = 0; d <=
dim; d++)
1246 if (!field_shape->hasNodesIn(d)) {
continue; }
1248 int na = apf_mesh->getDownward(ent,d,
a);
1249 for (
int i = 0; i < na; i++)
1251 int type = apf_mesh->getType(
a[i]);
1252 int nan = field_shape->countNodesOn(type);
1253 for (
int n = 0; n < nan; n++)
1255 apf::Vector3 v(
vel.GetColumn(non));
1256 apf::setVector(vel_field,
a[i], n, v);
1257 apf::setScalar(pr_field,
a[i], n, pr[non]);
1258 apf::setScalar(vel_mag_field,
a[i], n, v.getLength());
1269 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1271 apf::Field* pr_field,
1272 apf::Field* pr_mag_field)
1274 apf::FieldShape* field_shape = getShape(pr_field);
1275 int dim = apf_mesh->getDimension();
1277 apf::MeshEntity* ent;
1278 apf::MeshIterator* itr = apf_mesh->begin(
dim);
1280 while ((ent = apf_mesh->iterate(itr)))
1282 apf::NewArray<apf::Vector3> pumi_nodes;
1283 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1285 apf_mesh, ent, iel, pumi_nodes,
true);
1288 grid_pr->
GetValues(iel, mfem_nodes, vals, 1);
1291 for (
int d = 0; d <=
dim; d++)
1293 if (!field_shape->hasNodesIn(d)) {
continue; }
1295 int na = apf_mesh->getDownward(ent,d,
a);
1296 for (
int i = 0; i < na; i++)
1298 int type = apf_mesh->getType(
a[i]);
1299 int nan = field_shape->countNodesOn(type);
1300 for (
int n = 0; n < nan; n++)
1302 double pr = vals[non];
1303 double pr_mag = pr >= 0 ? pr : -pr;
1304 apf::setScalar(pr_field,
a[i], n, pr);
1305 apf::setScalar(pr_mag_field,
a[i], n, pr_mag);
1317 void ParPumiMesh::VectorFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1319 apf::Field* vel_field,
1320 apf::Field* vel_mag_field)
1322 apf::FieldShape* field_shape = getShape(vel_field);
1323 int dim = apf_mesh->getDimension();
1325 apf::MeshEntity* ent;
1326 apf::MeshIterator* itr = apf_mesh->begin(
dim);
1328 while ((ent = apf_mesh->iterate(itr)))
1330 apf::NewArray<apf::Vector3> pumi_nodes;
1331 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1333 apf_mesh, ent, iel, pumi_nodes,
true);
1340 for (
int d = 0; d <=
dim; d++)
1342 if (!field_shape->hasNodesIn(d)) {
continue; }
1344 int na = apf_mesh->getDownward(ent,d,
a);
1345 for (
int i = 0; i < na; i++)
1347 int type = apf_mesh->getType(
a[i]);
1348 int nan = field_shape->countNodesOn(type);
1349 for (
int n = 0; n < nan; n++)
1351 apf::Vector3 v(
vel.GetColumn(non));
1352 apf::setScalar(vel_mag_field,
a[i], n, v.getLength());
1353 apf::setVector(vel_field,
a[i], n, v);
1363 void ParPumiMesh::NedelecFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1365 apf::Field* nedelec_field)
1367 apf::FieldShape* nedelecFieldShape = nedelec_field->getShape();
1368 int dim = apf_mesh->getDimension();
1372 apf::MeshEntity* ent;
1373 apf::MeshIterator* it = apf_mesh->begin(
dim);
1374 while ( (ent = apf_mesh->iterate(it)) )
1377 apf::NewArray<apf::Vector3> pumi_nodes;
1378 apf::getElementNodeXis(nedelecFieldShape, apf_mesh, ent, pumi_nodes);
1380 apf_mesh, ent, elemNo, pumi_nodes,
true);
1388 for (
int d = 0; d <=
dim; d++)
1390 if (!nedelecFieldShape->hasNodesIn(d)) {
continue; }
1392 int na = apf_mesh->getDownward(ent,d,
a);
1393 for (
int i = 0; i < na; i++)
1395 int type = apf_mesh->getType(
a[i]);
1396 int nan = nedelecFieldShape->countNodesOn(type);
1397 apf::MeshElement* me = apf::createMeshElement(apf_mesh,
a[i]);
1398 for (
int n = 0; n < nan; n++)
1400 apf::Vector3 xi, tangent;
1401 nedelecFieldShape->getNodeXi(type, n, xi);
1402 nedelecFieldShape->getNodeTangent(type, n, tangent);
1403 apf::Vector3 pumi_field_vector(mfem_field_vals.
GetColumn(non));
1405 apf::getJacobian(me, xi, J);
1406 double dof = (J * pumi_field_vector) * tangent;
1407 apf::setScalar(nedelec_field,
a[i], n, dof);
1410 apf::destroyMeshElement(me);
1418 void ParPumiMesh::FieldPUMItoMFEM(apf::Mesh2* apf_mesh,
1422 int nc = apf::countComponents(field);
1426 int dim = apf_mesh->getDimension();
1428 apf::MeshIterator* it = apf_mesh->begin(
dim);
1429 for (
int i = 0; i < pmesh->
GetNE(); i++)
1433 int non = mfem_xi.
Size();
1434 apf::MeshEntity* ent = apf_mesh->iterate(it);
1435 apf::NewArray<apf::Vector3> pumi_xi(non);
1436 ParentXisMFEMtoPUMI(apf_mesh,
1444 apf::MeshElement* me = apf::createMeshElement(apf_mesh, ent);
1445 apf::Element* el = apf::createElement(field, me);
1446 for (
int j = 0; j < non; j++)
1448 apf::DynamicVector values(nc);
1449 apf::getComponents(el, pumi_xi[j], &values[0]);
1451 for (
int c = 0; c < nc; c++)
1453 int dof_loc = j + c * non;
1454 (grid->
GetData())[vdofs[dof_loc]] = values[c];
1457 apf::destroyElement(el);
1458 apf::destroyMeshElement(me);
1465 #endif // MFEM_USE_MPI 1466 #endif // MFEM_USE_SCOREC Abstract class for all finite elements.
void Set(const double *p, const int dim)
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.
virtual Element * Duplicate(Mesh *m) const =0
int Dimension() const
Dimension of the reference space used within the elements.
Class for PUMI grid functions.
Data type dense matrix using column-major storage.
int GetNEdges() const
Return the number of edges.
const Element * GetElement(int i) const
Return pointer to the i'th element object.
Abstract parallel finite element space.
Array< Vert3 > shared_trias
constexpr Element::Type QUAD
int GetNBE() const
Returns number of boundary elements.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
Array< Element * > shared_edges
int Append(const T &el)
Append element 'el' to array, resize if necessary.
const FiniteElementCollection * FEColl() const
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
ParMesh * GetParMesh() const
virtual const char * Name() const
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.
void GetColumn(int c, Vector &col) const
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
FiniteElementSpace * FESpace()
int Size()
Return the number of integer sets in the list.
Array< Vert4 > shared_quads
double * GetData() const
Return a pointer to the beginning of the Vector data.
int GetVDim() const
Returns vector dimension.
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
virtual const FiniteElement * GetFE(int i) const
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...
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
ParFiniteElementSpace * ParFESpace() const
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
int GetNE() const
Returns number of elements.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Class for integration point with weight.
Ordering::Type GetOrdering() const
Return the ordering method.
void vel(const Vector &x, double t, Vector &u)
Table group_svert
Shared objects in each group.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
Array< FaceInfo > faces_info
NCMesh * ncmesh
Optional nonconforming mesh extension.
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
int Size() const
Return the logical size of the array.
int GetNFaces() const
Return the number of faces in a 3D mesh.
void Copy(Table ©) const
Arbitrary order H1-conforming (continuous) finite elements.
Array< int > svert_lvert
Shared to local index mapping.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Class for parallel grid function.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
void Copy(GroupTopology ©) const
Copy the internal data to the external 'copy'.
Class for parallel meshes.
Abstract data type element.
Data type line segment element.
Array< int > attributes
A list of all unique element attributes used by the Mesh.