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);
58 PumiMesh::PumiMesh(apf::Mesh2* apf_mesh,
int generate_edges,
int refine,
61 Load(apf_mesh, generate_edges, refine, fix_orientation);
66 void PumiMesh::CountBoundaryEntity(apf::Mesh2* apf_mesh,
const int BcDim,
70 apf::MeshIterator* itr = apf_mesh->begin(BcDim);
72 while ((ent=apf_mesh->iterate(itr)))
74 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
75 if (apf_mesh->getModelType(mdEnt) == BcDim)
85 MFEM_ABORT(
"no boundary detected!");
89 void PumiMesh::Load(apf::Mesh2* apf_mesh,
int generate_edges,
int refine,
92 int curved = 0, read_gf = 1;
98 apf::Field* apf_field_crd = apf_mesh->getCoordinateField();
99 apf::FieldShape* crd_shape = apf::getShape(apf_field_crd);
100 apf::Numbering* v_num_loc = apf::createNumbering(apf_mesh,
"VertexNumbering",
103 curved = (crd_shape->getOrder() > 1) ? 1 : 0;
106 ReadSCORECMesh(apf_mesh, v_num_loc, curved);
108 mfem::out <<
"After ReadSCORECMesh" << endl;
128 if (curved && read_gf)
132 crd_shape->getOrder());
138 for (
int i = 0; i < spaceDim; i++)
141 Nodes->GetNodalValues(vert_val, i+1);
142 for (
int j = 0; j < NumOfVertices; j++)
144 vertices[j](i) = vert_val(j);
150 apf::destroyNumbering(v_num_loc);
152 Finalize(refine, fix_orientation);
155 void PumiMesh::ReadSCORECMesh(apf::Mesh2* apf_mesh, apf::Numbering* v_num_loc,
161 apf::MeshIterator* itr = apf_mesh->begin(0);
162 apf::MeshEntity* ent;
164 while ((ent = apf_mesh->iterate(itr)))
167 apf::number(v_num_loc, ent, 0, 0, NumOfVertices);
172 Dim = apf_mesh->getDimension();
173 NumOfElements = countOwned(apf_mesh,Dim);
174 elements.SetSize(NumOfElements);
177 itr = apf_mesh->begin(Dim);
179 while ((ent = apf_mesh->iterate(itr)))
183 apf_mesh->getDownward(ent,0,verts);
187 int geom_type = apf_mesh->getType(ent);
188 elements[j] = NewElement(geom_type);
189 ReadPumiElement(ent, verts, attr, v_num_loc, elements[j]);
198 NumOfBdrElements = 0;
199 CountBoundaryEntity(apf_mesh, BCdim, NumOfBdrElements);
200 boundary.SetSize(NumOfBdrElements);
204 itr = apf_mesh->begin(BCdim);
205 while ((ent = apf_mesh->iterate(itr)))
208 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
209 if (apf_mesh->getModelType(mdEnt) == BCdim)
212 apf_mesh->getDownward(ent, 0, verts);
214 int geom_type = apf_mesh->getType(ent);
215 boundary[j] = NewElement(geom_type);
216 ReadPumiElement(ent, verts, attr, v_num_loc, boundary[j]);
223 vertices.SetSize(NumOfVertices);
227 apf::MeshIterator* itr = apf_mesh->begin(0);
230 while ((ent = apf_mesh->iterate(itr)))
232 unsigned int id = apf::getNumber(v_num_loc, ent, 0, 0);
234 apf_mesh->getPoint(ent,0,Crds);
236 for (
int ii=0; ii<spaceDim; ii++)
238 vertices[id](ii) = Crds[ii];
248 ParPumiMesh::ParPumiMesh(MPI_Comm comm, apf::Mesh2* apf_mesh,
249 int refine,
bool fix_orientation)
255 MPI_Comm_size(MyComm, &NRanks);
256 MPI_Comm_rank(MyComm, &MyRank);
258 Dim = apf_mesh->getDimension();
261 apf::MeshIterator* itr;
262 apf::MeshEntity* ent;
266 apf::Numbering* vLocNum =
267 apf::numberOwnedDimension(apf_mesh,
"AuxVertexNumbering", 0);
268 apf::GlobalNumbering* VertexNumbering = apf::makeGlobal(vLocNum,
true);
269 apf::synchronize(VertexNumbering);
273 itr = apf_mesh->
begin(0);
274 for (
int i = 0; (ent = apf_mesh->iterate(itr)); i++)
276 long id = apf::getNumber(VertexNumbering, ent, 0, 0);
280 apf::destroyGlobalNumbering(VertexNumbering);
285 for (
int j = 0; j < thisVertIds.Size(); j++)
287 const int i = thisVertIds[j].two;
288 thisVertIds[i].one = j;
292 apf::Field* apf_field_crd = apf_mesh->getCoordinateField();
293 apf::FieldShape* crd_shape = apf::getShape(apf_field_crd);
296 v_num_loc = apf_mesh->findNumbering(
"LocalVertexNumbering");
298 v_num_loc = apf::createNumbering(apf_mesh,
299 "LocalVertexNumbering",
303 NumOfVertices = thisVertIds.Size();
304 vertices.SetSize(NumOfVertices);
305 itr = apf_mesh->
begin(0);
306 for (
int i = 0; (ent = apf_mesh->iterate(itr)); i++)
308 const int id = thisVertIds[i].one;
310 apf::number(v_num_loc, ent, 0, 0,
id);
313 apf_mesh->getPoint(ent,0,Crds);
315 for (
int ii=0; ii<spaceDim; ii++)
317 vertices[id](ii) = Crds[ii];
321 thisVertIds.DeleteAll();
324 NumOfElements = countOwned(apf_mesh,Dim);
325 elements.SetSize(NumOfElements);
328 itr = apf_mesh->
begin(Dim);
329 for (
int j = 0; (ent = apf_mesh->iterate(itr)); j++)
333 apf_mesh->getDownward(ent,0,verts);
337 int geom_type = apf_mesh->getType(ent);
338 elements[j] = NewElement(geom_type);
339 ReadPumiElement(ent, verts, attr, v_num_loc, elements[j]);
346 itr = apf_mesh->
begin(BcDim);
347 NumOfBdrElements = 0;
348 while ((ent=apf_mesh->iterate(itr)))
350 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
351 if (apf_mesh->getModelType(mdEnt) == BcDim)
358 boundary.SetSize(NumOfBdrElements);
360 itr = apf_mesh->
begin(BcDim);
361 for (
int bdr_ctr = 0; (ent = apf_mesh->iterate(itr)); )
364 apf::ModelEntity* mdEnt = apf_mesh->toModel(ent);
365 if (apf_mesh->getModelType(mdEnt) == BcDim)
368 apf_mesh->getDownward(ent, 0, verts);
370 int geom_type = apf_mesh->getType(ent);
371 boundary[bdr_ctr] = NewElement(geom_type);
372 ReadPumiElement(ent, verts, attr, v_num_loc, boundary[bdr_ctr]);
385 this->FinalizeTopology();
394 MFEM_ASSERT(Dim >= 3 || GetNFaces() == 0,
395 "[proc " << MyRank <<
"]: invalid state");
407 apf::Numbering* AuxFaceNum =
408 apf::numberOwnedDimension(apf_mesh,
"AuxFaceNumbering", 2);
409 apf::GlobalNumbering* GlobalFaceNum = apf::makeGlobal(AuxFaceNum,
true);
410 apf::synchronize(GlobalFaceNum);
412 itr = apf_mesh->
begin(2);
413 while ((ent = apf_mesh->iterate(itr)))
415 if (apf_mesh->isShared(ent))
417 long id = apf::getNumber(GlobalFaceNum, ent, 0, 0);
423 apf::destroyGlobalNumbering(GlobalFaceNum);
426 for (
int i = 0; i < sfaces.
Size(); i++)
430 const int thisNumAdjs = 2;
431 int eleRanks[thisNumAdjs];
435 apf_mesh->getResidence(ent, res);
437 for (std::set<int>::iterator itr = res.
begin();
438 itr != res.
end(); ++itr)
440 eleRanks[kk++] = *itr;
444 sfaces[i].one = groups.
Insert(group) - 1;
458 apf::Numbering* AuxEdgeNum =
459 apf::numberOwnedDimension(apf_mesh,
"EdgeNumbering", 1);
460 apf::GlobalNumbering* GlobalEdgeNum = apf::makeGlobal(AuxEdgeNum,
true);
461 apf::synchronize(GlobalEdgeNum);
463 itr = apf_mesh->
begin(1);
464 while ((ent = apf_mesh->iterate(itr)))
466 if (apf_mesh->isShared(ent))
468 long id = apf::getNumber(GlobalEdgeNum, ent, 0, 0);
474 apf::destroyGlobalNumbering(GlobalEdgeNum);
478 for (
int i = 0; i < sedges.
Size(); i++)
484 apf_mesh->getResidence(ent, res);
489 for (std::set<int>::iterator itr = res.
begin();
490 itr != res.
end(); itr++)
492 eleRanks[kk++] = *itr;
497 sedges[i].one = groups.
Insert(group) - 1;
506 itr = apf_mesh->
begin(0);
507 while ((ent = apf_mesh->iterate(itr)))
509 if (apf_mesh->isShared(ent))
511 int vtId = apf::getNumber(v_num_loc, ent, 0, 0);
521 for (
int i = 0; i < sverts.
Size(); i++)
527 apf_mesh->getResidence(ent, res);
532 for (std::set<int>::iterator itr = res.
begin();
533 itr != res.
end(); itr++)
535 eleRanks[kk++] = *itr;
539 svert_group[i] = groups.
Insert(group) - 1;
545 group_stria.MakeI(groups.
Size()-1);
546 group_squad.MakeI(groups.
Size()-1);
547 for (
int i = 0; i < sfaces.
Size(); i++)
549 apf::Mesh::Type ftype = apf_mesh->getType(sfaces[i].two);
550 if (ftype == apf::Mesh::TRIANGLE)
552 group_stria.AddAColumnInRow(sfaces[i].one);
556 group_squad.AddAColumnInRow(sfaces[i].one);
563 for (
int i = 0; i < sfaces.
Size(); i++)
565 apf::Mesh::Type ftype = apf_mesh->getType(sfaces[i].two);
566 if (ftype == apf::Mesh::TRIANGLE)
568 group_stria.AddConnection(sfaces[i].one, nst++);
572 group_squad.AddConnection(sfaces[i].one, i-nst);
575 shared_trias.SetSize(nst);
576 shared_quads.SetSize(sfaces.
Size()-nst);
577 sface_lface.SetSize(sfaces.
Size());
579 group_stria.ShiftUpI();
580 group_squad.ShiftUpI();
583 group_sedge.MakeI(groups.
Size()-1);
584 for (
int i = 0; i < sedges.
Size(); i++)
586 group_sedge.AddAColumnInRow(sedges[i].one);
589 for (
int i = 0; i < sedges.
Size(); i++)
591 group_sedge.AddConnection(sedges[i].one, i);
593 group_sedge.ShiftUpI();
596 group_svert.MakeI(groups.
Size()-1);
597 for (
int i = 0; i < svert_group.
Size(); i++)
599 group_svert.AddAColumnInRow(svert_group[i]);
602 for (
int i = 0; i < svert_group.
Size(); i++)
604 group_svert.AddConnection(svert_group[i], i);
606 group_svert.ShiftUpI();
611 for (
int i = 0; i < sfaces.
Size(); i++)
616 apf_mesh->getDownward(ent,0,verts);
619 apf::Mesh::Type ftype = apf_mesh->getType(ent);
620 if (ftype == apf::Mesh::TRIANGLE)
622 v = shared_trias[nst++].v;
627 v = shared_quads[i-nst].v;
630 for (
int j = 0; j < nv; ++j)
632 v[j] = apf::getNumber(v_num_loc, verts[j], 0, 0);
638 shared_edges.SetSize(sedges.
Size());
639 sedge_ledge. SetSize(sedges.
Size());
640 for (
int i = 0; i < sedges.
Size(); i++)
645 apf_mesh->getDownward(ent, 0, verts);
647 id1 = apf::getNumber(v_num_loc, verts[0], 0, 0);
648 id2 = apf::getNumber(v_num_loc, verts[1], 0, 0);
649 if (id1 > id2) { swap(id1,id2); }
651 shared_edges[i] =
new Segment(id1, id2, 1);
655 svert_lvert.SetSize(sverts.
Size());
656 for (
int i = 0; i < sverts.
Size(); i++)
658 svert_lvert[i] = sverts[i].one;
662 gtopo.Create(groups, 822);
668 int curved = (crd_shape->getOrder() > 1) ? 1 : 0;
672 crd_shape->getOrder());
674 Nodes->Vector::Swap(auxNodes);
675 this->edge_vertex = NULL;
679 Finalize(refine, fix_orientation);
683 GridFunctionPumi::GridFunctionPumi(
Mesh* m, apf::Mesh2* PumiM,
684 apf::Numbering* v_num_loc,
685 const int mesh_order)
690 int ordering = Ordering::byVDIM;
692 int data_size = fes->GetVSize();
695 this->SetSize(data_size);
696 double* PumiData = this->GetData();
698 apf::MeshEntity* ent;
699 apf::MeshIterator* itr;
704 int nnodes = All_nodes.
Size();
707 apf::Field* crd_field = PumiM->getCoordinateField();
709 int nc = apf::countComponents(crd_field);
712 while ((ent = PumiM->iterate(itr)))
715 fes->GetElementVDofs(iel, vdofs);
718 apf::MeshElement* mE = apf::createMeshElement(PumiM, ent);
719 apf::Element* elem = apf::createElement(crd_field, mE);
722 for (
int ip = 0; ip < nnodes; ip++)
731 apf::DynamicVector phCrd(nc);
732 apf::getComponents(elem, param, &phCrd[0]);
735 for (
int kk = 0; kk < spDim; ++kk)
737 int dof_ctr = ip + kk * nnodes;
738 PumiData[vdofs[dof_ctr]] = phCrd[kk];
742 apf::destroyElement(elem);
743 apf::destroyMeshElement(mE);
752 void ParPumiMesh::UpdateMesh(
const ParMesh* AdaptedpMesh)
760 for (
int i = 0; i < shared_edges.Size(); i++)
762 FreeElement(shared_edges[i]);
764 shared_quads.DeleteAll();
765 shared_trias.DeleteAll();
766 shared_edges.DeleteAll();
771 svert_lvert.DeleteAll();
772 sedge_ledge.DeleteAll();
773 sface_lface.DeleteAll();
779 MFEM_ASSERT(Dim == AdaptedpMesh->
Dim,
"");
780 MFEM_ASSERT(spaceDim == AdaptedpMesh->
spaceDim,
"");
781 MFEM_ASSERT(meshgen == AdaptedpMesh->
meshgen,
"");
783 NumOfVertices = AdaptedpMesh->
GetNV();
784 NumOfElements = AdaptedpMesh->
GetNE();
785 NumOfBdrElements = AdaptedpMesh->
GetNBE();
789 meshgen = AdaptedpMesh->
meshgen;
793 last_operation = Mesh::NONE;
796 elements.SetSize(NumOfElements);
797 for (
int i = 0; i < NumOfElements; i++)
803 AdaptedpMesh->
vertices.Copy(vertices);
806 boundary.SetSize(NumOfBdrElements);
807 for (
int i = 0; i < NumOfBdrElements; i++)
831 faces.SetSize(AdaptedpMesh->
faces.Size());
832 for (
int i = 0; i < faces.Size(); i++)
835 faces[i] = (face) ? face->
Duplicate(
this) : NULL;
854 MFEM_VERIFY(AdaptedpMesh->
NURBSext == NULL,
855 "invalid adapted mesh: it is a NURBS mesh");
859 MFEM_VERIFY(AdaptedpMesh->
ncmesh == NULL && AdaptedpMesh->
pncmesh == NULL,
860 "invalid adapted mesh: it is a non-conforming mesh");
871 MyComm = AdaptedpMesh->
MyComm;
872 NRanks = AdaptedpMesh->
NRanks;
873 MyRank = AdaptedpMesh->
MyRank;
876 shared_edges.SetSize(AdaptedpMesh->
shared_edges.Size());
877 for (
int i = 0; i < shared_edges.Size(); i++)
879 shared_edges[i] = AdaptedpMesh->
shared_edges[i]->Duplicate(
this);
892 have_face_nbr_data =
false;
896 if (AdaptedpMesh->
Nodes)
901 FiniteElementCollection::New(fec->
Name());
906 Nodes->MakeOwner(fec_copy);
907 *Nodes = *(AdaptedpMesh->
Nodes);
912 int ParPumiMesh::RotationPUMItoMFEM(apf::Mesh2* apf_mesh,
913 apf::MeshEntity* tet,
916 MFEM_ASSERT(apf_mesh->getType(tet) == apf::Mesh::TET,
"");
919 int nv = apf_mesh->getDownward(tet,0,vs);
921 for (
int i = 0; i < nv; i++)
923 pumi_vid[i] = apf::getNumber(v_num_loc, vs[i], 0, 0);
928 this->GetElementVertices(elemId, mfem_vid);
931 int pumi_vid_rot[12];
932 for (
int i = 0; i < nv; i++)
934 pumi_vid_rot[i] = mfem_vid.
Find(pumi_vid[i]);
936 apf::Downward vs_rot;
937 for (
int i = 0; i < nv; i++)
939 vs_rot[i] = vs[pumi_vid_rot[i]];
942 return ma::findTetRotation(apf_mesh, tet, vs_rot);
947 apf::MeshEntity* tet,
949 apf::NewArray<apf::Vector3>& pumi_xi,
950 bool checkOrientation)
952 int num_nodes = pumi_xi.
size();
954 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
955 for (
int i = 0; i < num_nodes; i++)
960 ma::unrotateTetXi(pumi_xi[i], rotation);
964 pumi_xi[i].toArray(tmp_xi);
971 void ParPumiMesh::ParentXisMFEMtoPUMI(apf::Mesh2* apf_mesh,
973 apf::MeshEntity* tet,
975 apf::NewArray<apf::Vector3>& pumi_xi,
976 bool checkOrientation)
978 int num_nodes = mfem_xi.
Size();
979 if (!pumi_xi.allocated())
981 pumi_xi.allocate(num_nodes);
985 pumi_xi.resize(num_nodes);
988 int rotation = checkOrientation ? RotationPUMItoMFEM(apf_mesh, tet, elemId):0;
989 for (
int i = 0; i < num_nodes; i++)
992 pumi_xi[i] = apf::Vector3(ip.
x, ip.
y, ip.
z);
997 ma::rotateTetXi(pumi_xi[i], rotation);
1005 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1008 apf::Field* vel_field,
1009 apf::Field* pr_field,
1010 apf::Field* vel_mag_field)
1012 apf::FieldShape* field_shape = getShape(vel_field);
1013 int dim = apf_mesh->getDimension();
1015 apf::MeshEntity* ent;
1016 apf::MeshIterator* itr = apf_mesh->begin(dim);
1018 while ((ent = apf_mesh->iterate(itr)))
1020 apf::NewArray<apf::Vector3> pumi_nodes;
1021 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1023 apf_mesh, ent, iel, pumi_nodes,
true);
1029 grid_pr->
GetValues(iel, mfem_nodes, pr, 1);
1032 for (
int d = 0; d <=
dim; d++)
1034 if (!field_shape->hasNodesIn(d)) {
continue; }
1036 int na = apf_mesh->getDownward(ent,d,a);
1037 for (
int i = 0; i < na; i++)
1039 int type = apf_mesh->getType(a[i]);
1040 int nan = field_shape->countNodesOn(type);
1041 for (
int n = 0; n < nan; n++)
1044 apf::setVector(vel_field, a[i], n, v);
1045 apf::setScalar(pr_field, a[i], n, pr[non]);
1046 apf::setScalar(vel_mag_field, a[i], n, v.getLength());
1057 void ParPumiMesh::FieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1059 apf::Field* pr_field,
1060 apf::Field* pr_mag_field)
1062 apf::FieldShape* field_shape = getShape(pr_field);
1063 int dim = apf_mesh->getDimension();
1065 apf::MeshEntity* ent;
1066 apf::MeshIterator* itr = apf_mesh->begin(dim);
1068 while ((ent = apf_mesh->iterate(itr)))
1070 apf::NewArray<apf::Vector3> pumi_nodes;
1071 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1073 apf_mesh, ent, iel, pumi_nodes,
true);
1076 grid_pr->
GetValues(iel, mfem_nodes, vals, 1);
1079 for (
int d = 0; d <=
dim; d++)
1081 if (!field_shape->hasNodesIn(d)) {
continue; }
1083 int na = apf_mesh->getDownward(ent,d,a);
1084 for (
int i = 0; i < na; i++)
1086 int type = apf_mesh->getType(a[i]);
1087 int nan = field_shape->countNodesOn(type);
1088 for (
int n = 0; n < nan; n++)
1090 double pr = vals[non];
1091 double pr_mag = pr >= 0 ? pr : -pr;
1092 apf::setScalar(pr_field, a[i], n, pr);
1093 apf::setScalar(pr_mag_field, a[i], n, pr_mag);
1105 void ParPumiMesh::VectorFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1107 apf::Field* vel_field,
1108 apf::Field* vel_mag_field)
1110 apf::FieldShape* field_shape = getShape(vel_field);
1111 int dim = apf_mesh->getDimension();
1113 apf::MeshEntity* ent;
1114 apf::MeshIterator* itr = apf_mesh->begin(dim);
1116 while ((ent = apf_mesh->iterate(itr)))
1118 apf::NewArray<apf::Vector3> pumi_nodes;
1119 apf::getElementNodeXis(field_shape, apf_mesh, ent, pumi_nodes);
1121 apf_mesh, ent, iel, pumi_nodes,
true);
1128 for (
int d = 0; d <=
dim; d++)
1130 if (!field_shape->hasNodesIn(d)) {
continue; }
1132 int na = apf_mesh->getDownward(ent,d,a);
1133 for (
int i = 0; i < na; i++)
1135 int type = apf_mesh->getType(a[i]);
1136 int nan = field_shape->countNodesOn(type);
1137 for (
int n = 0; n < nan; n++)
1140 apf::setScalar(vel_mag_field, a[i], n, v.getLength());
1141 apf::setVector(vel_field, a[i], n, v);
1151 void ParPumiMesh::NedelecFieldMFEMtoPUMI(apf::Mesh2* apf_mesh,
1153 apf::Field* nedelec_field)
1155 apf::FieldShape* nedelecFieldShape = nedelec_field->getShape();
1156 int dim = apf_mesh->getDimension();
1160 apf::MeshEntity* ent;
1161 apf::MeshIterator* it = apf_mesh->begin(dim);
1162 while ( (ent = apf_mesh->iterate(it)) )
1165 apf::NewArray<apf::Vector3> pumi_nodes;
1166 apf::getElementNodeXis(nedelecFieldShape, apf_mesh, ent, pumi_nodes);
1168 apf_mesh, ent, elemNo, pumi_nodes,
true);
1176 for (
int d = 0; d <=
dim; d++)
1178 if (!nedelecFieldShape->hasNodesIn(d)) {
continue; }
1180 int na = apf_mesh->getDownward(ent,d,a);
1181 for (
int i = 0; i < na; i++)
1183 int type = apf_mesh->getType(a[i]);
1184 int nan = nedelecFieldShape->countNodesOn(type);
1185 apf::MeshElement* me = apf::createMeshElement(apf_mesh, a[i]);
1186 for (
int n = 0; n < nan; n++)
1188 apf::Vector3 xi, tangent;
1189 nedelecFieldShape->getNodeXi(type, n, xi);
1190 nedelecFieldShape->getNodeTangent(type, n, tangent);
1191 apf::Vector3 pumi_field_vector(mfem_field_vals.
GetColumn(non));
1193 apf::getJacobian(me, xi, J);
1194 double dof = (J * pumi_field_vector) * tangent;
1195 apf::setScalar(nedelec_field, a[i], n, dof);
1198 apf::destroyMeshElement(me);
1206 void ParPumiMesh::FieldPUMItoMFEM(apf::Mesh2* apf_mesh,
1210 int nc = apf::countComponents(field);
1214 int dim = apf_mesh->getDimension();
1216 apf::MeshIterator* it = apf_mesh->begin(dim);
1217 for (
int i = 0; i < pmesh->
GetNE(); i++)
1221 int non = mfem_xi.
Size();
1222 apf::MeshEntity* ent = apf_mesh->iterate(it);
1223 apf::NewArray<apf::Vector3> pumi_xi(non);
1224 ParentXisMFEMtoPUMI(apf_mesh,
1232 apf::MeshElement* me = apf::createMeshElement(apf_mesh, ent);
1233 apf::Element* el = apf::createElement(field, me);
1234 for (
int j = 0; j < non; j++)
1236 apf::DynamicVector values(nc);
1237 apf::getComponents(el, pumi_xi[j], &values[0]);
1239 for (
int c = 0; c < nc; c++)
1241 int dof_loc = j + c * non;
1242 (grid->
GetData())[vdofs[dof_loc]] = values[c];
1245 apf::destroyElement(el);
1246 apf::destroyMeshElement(me);
1253 #endif // MFEM_USE_MPI
1254 #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.
int size
Size of the array.
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.
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.
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
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