12 #include "../config/config.hpp"
17 #include "../fem/fem.hpp"
18 #include "../general/sets.hpp"
19 #include "../general/sort_pairs.hpp"
20 #include "../general/text.hpp"
21 #include "../general/globals.hpp"
31 ParMesh::ParMesh(
const ParMesh &pmesh,
bool copy_nodes)
33 group_svert(pmesh.group_svert),
34 group_sedge(pmesh.group_sedge),
35 group_stria(pmesh.group_stria),
36 group_squad(pmesh.group_squad),
38 glob_offset_sequence(-1),
80 if (pmesh.
Nodes && copy_nodes)
108 : glob_elem_offset(-1)
109 , glob_offset_sequence(-1)
112 int *partitioning = NULL;
123 partitioning = partitioning_;
128 partitioning =
new int[mesh.
GetNE()];
129 for (
int i = 0; i < mesh.
GetNE(); i++)
159 partitioning = partitioning_;
173 Table *edge_element = NULL;
176 activeBdrElem, edge_element);
214 int nsedges =
FindSharedEdges(mesh, partitioning, edge_element, groups);
221 int ngroups = groups.
Size()-1, nstris, nsquads;
228 face_group, vert_global_local);
247 "invalid NURBS mesh");
267 Nodes->MakeOwner(nfec);
273 int element_counter = 0;
274 for (
int i = 0; i < mesh.
GetNE(); i++)
276 if (partitioning[i] ==
MyRank)
279 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
280 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
291 if (partitioning != partitioning_)
293 delete [] partitioning;
301 const int* partitioning,
305 vert_global_local = -1;
307 int vert_counter = 0;
308 for (
int i = 0; i < mesh.
GetNE(); i++)
310 if (partitioning[i] ==
MyRank)
314 for (
int j = 0; j < vert.
Size(); j++)
316 if (vert_global_local[vert[j]] < 0)
318 vert_global_local[vert[j]] = vert_counter++;
326 for (
int i = 0; i < vert_global_local.
Size(); i++)
328 if (vert_global_local[i] >= 0)
330 vert_global_local[i] = vert_counter++;
336 for (
int i = 0; i < vert_global_local.
Size(); i++)
338 if (vert_global_local[i] >= 0)
352 for (
int i = 0; i < mesh.
GetNE(); i++)
354 if (partitioning[i] ==
MyRank) { nelems++; }
362 int element_counter = 0;
363 for (
int i = 0; i < mesh.
GetNE(); i++)
365 if (partitioning[i] ==
MyRank)
368 int *v =
elements[element_counter]->GetVertices();
369 int nv =
elements[element_counter]->GetNVertices();
370 for (
int j = 0; j < nv; j++)
372 v[j] = vert_global_local[v[j]];
378 return element_counter;
384 Table*& edge_element)
391 activeBdrElem =
false;
396 for (
int i = 0; i < mesh.
GetNBE(); i++)
398 int face, o, el1, el2;
401 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
406 activeBdrElem[i] =
true;
411 int bdrelem_counter = 0;
413 for (
int i = 0; i < mesh.
GetNBE(); i++)
415 int face, o, el1, el2;
418 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
421 int *v =
boundary[bdrelem_counter]->GetVertices();
422 int nv =
boundary[bdrelem_counter]->GetNVertices();
423 for (
int j = 0; j < nv; j++)
425 v[j] = vert_global_local[v[j]];
433 edge_element =
new Table;
436 for (
int i = 0; i < mesh.
GetNBE(); i++)
439 int el1 = edge_element->
GetRow(edge)[0];
440 if (partitioning[el1] ==
MyRank)
445 activeBdrElem[i] =
true;
450 int bdrelem_counter = 0;
452 for (
int i = 0; i < mesh.
GetNBE(); i++)
455 int el1 = edge_element->
GetRow(edge)[0];
456 if (partitioning[el1] ==
MyRank)
459 int *v =
boundary[bdrelem_counter]->GetVertices();
460 int nv =
boundary[bdrelem_counter]->GetNVertices();
461 for (
int j = 0; j < nv; j++)
463 v[j] = vert_global_local[v[j]];
471 for (
int i = 0; i < mesh.
GetNBE(); i++)
473 int vert = mesh.
boundary[i]->GetVertices()[0];
476 if (partitioning[el1] ==
MyRank)
482 int bdrelem_counter = 0;
484 for (
int i = 0; i < mesh.
GetNBE(); i++)
486 int vert = mesh.
boundary[i]->GetVertices()[0];
489 if (partitioning[el1] ==
MyRank)
492 int *v =
boundary[bdrelem_counter]->GetVertices();
493 v[0] = vert_global_local[v[0]];
510 for (
int i = 0; i < face_group.
Size(); i++)
517 el[0] = partitioning[el[0]];
518 el[1] = partitioning[el[1]];
523 face_group[i] = groups.
Insert(group) - 1;
530 Table*& edge_element,
536 int sedge_counter = 0;
539 edge_element =
new Table;
550 for (
int i = 0; i < edge_element->
Size(); i++)
552 int me = 0, others = 0;
553 for (
int j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
555 int k = edge_element->
GetJ()[j];
556 int rank = partitioning[k];
557 edge_element->
GetJ()[j] = rank;
576 edge_element->
GetRow(i)[0] = -1;
580 return sedge_counter;
589 int svert_counter = 0;
590 for (
int i = 0; i < vert_element->
Size(); i++)
592 int me = 0, others = 0;
593 for (
int j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
595 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
610 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
614 vert_element->
GetI()[i] = -1;
617 return svert_counter;
622 int &nstria,
int &nsquad)
628 for (
int i = 0; i < face_group.
Size(); i++)
630 if (face_group[i] >= 0)
647 for (
int i = 0; i < face_group.
Size(); i++)
649 if (face_group[i] >= 0)
670 for (
int i = 0; i < edge_element.
Size(); i++)
672 if (edge_element.
GetRow(i)[0] >= 0)
680 int sedge_counter = 0;
681 for (
int i = 0; i < edge_element.
Size(); i++)
683 if (edge_element.
GetRow(i)[0] >= 0)
696 for (
int i = 0; i < vert_element.
Size(); i++)
698 if (vert_element.
GetI()[i] >= 0)
706 int svert_counter = 0;
707 for (
int i = 0; i < vert_element.
Size(); i++)
709 if (vert_element.
GetI()[i] >= 0)
719 const Mesh& mesh,
int *partitioning,
728 if (
Dim < 3) {
return; }
730 int stria_counter = 0;
731 int squad_counter = 0;
732 for (
int i = 0; i < face_group.
Size(); i++)
734 if (face_group[i] < 0) {
continue; }
744 for (
int j = 0; j < 3; j++)
746 v[j] = vert_global_local[v[j]];
748 const int lface = (*faces_tbl)(v[0], v[1], v[2]);
764 if (
MyRank == partitioning[gl_el2])
766 std::swap(v[0], v[1]);
778 for (
int j = 0; j < 4; j++)
780 v[j] = vert_global_local[v[j]];
783 (*faces_tbl)(v[0], v[1], v[2], v[3]);
789 MFEM_ABORT(
"unknown face type: " << face->
GetType());
797 const Table* edge_element)
809 int sedge_counter = 0;
810 for (
int i = 0; i < edge_element->
Size(); i++)
812 if (edge_element->
GetRow(i)[0] >= 0)
818 new Segment(vert_global_local[vert[0]],
819 vert_global_local[vert[1]], 1);
821 sedge_ledge[sedge_counter] = v_to_v(vert_global_local[vert[0]],
822 vert_global_local[vert[1]]);
824 MFEM_VERIFY(
sedge_ledge[sedge_counter] >= 0,
"Error in v_to_v.");
839 int svert_counter = 0;
840 for (
int i = 0; i < vert_element->
Size(); i++)
842 if (vert_element->
GetI()[i] >= 0)
844 svert_lvert[svert_counter++] = vert_global_local[i];
852 : MyComm(pncmesh.MyComm)
853 , NRanks(pncmesh.NRanks)
854 , MyRank(pncmesh.MyRank)
855 , glob_elem_offset(-1)
856 , glob_offset_sequence(-1)
880 MPI_Allreduce(&loc_meshgen, &
meshgen, 1, MPI_INT, MPI_BOR,
MyComm);
894 const int l_edge = v_to_v(v[0], v[1]);
895 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
906 for (
int st = 0; st < nst; st++)
921 : glob_elem_offset(-1)
922 , glob_offset_sequence(-1)
932 const int gen_edges = 1;
934 Load(input, gen_edges, refine,
true);
938 bool fix_orientation)
945 Loader(input, generate_edges,
"mfem_serial_mesh_end");
957 MFEM_ASSERT(
pncmesh,
"internal error");
980 MFEM_VERIFY(ident ==
"communication_groups",
981 "input stream is not a parallel MFEM mesh");
989 input >> ident >> num_sverts;
990 MFEM_VERIFY(ident ==
"total_shared_vertices",
"invalid mesh file");
999 input >> ident >> num_sedges;
1000 MFEM_VERIFY(ident ==
"total_shared_edges",
"invalid mesh file");
1014 input >> ident >> num_sface;
1015 MFEM_VERIFY(ident ==
"total_shared_faces",
"invalid mesh file");
1028 int svert_counter = 0, sedge_counter = 0;
1035 input >> ident >> g;
1038 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
1039 <<
", read group " << g << endl;
1045 input >> ident >> nv;
1046 MFEM_VERIFY(ident ==
"shared_vertices",
"invalid mesh file");
1047 nv += svert_counter;
1049 "incorrect number of total_shared_vertices");
1051 for ( ; svert_counter < nv; svert_counter++)
1060 input >> ident >> ne;
1061 MFEM_VERIFY(ident ==
"shared_edges",
"invalid mesh file");
1062 ne += sedge_counter;
1064 "incorrect number of total_shared_edges");
1066 for ( ; sedge_counter < ne; sedge_counter++)
1069 input >> v[0] >> v[1];
1076 input >> ident >> nf;
1077 for (
int i = 0; i < nf; i++)
1086 for (
int i = 0; i < 3; i++) { input >> v[i]; }
1091 for (
int i = 0; i < 4; i++) { input >> v[i]; }
1094 MFEM_ABORT(
"invalid shared face geometry: " << geom);
1105 "incorrect number of total_shared_faces");
1139 ref_factors = ref_factor;
1218 for (
int j = 0; j < orig_n_verts; j++)
1225 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1226 if (orig_n_edges > 0)
1231 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1233 for (
int e = 0; e < orig_n_edges; e++)
1238 for (
int j = 2; j < rdofs.
Size(); j++)
1246 for (
int k = 0; k < nvert; k++)
1249 v[k] = rdofs[c2h_map[cid]];
1265 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1267 for (
int f = 0;
f < orig_nt;
f++)
1272 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1281 for (
int k = 0; k < 2; k++)
1283 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1292 for (
int k = 0; k < nvert; k++)
1295 v[k] = rdofs[c2h_map[cid]];
1309 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1311 for (
int f = 0;
f < orig_nq;
f++)
1316 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1325 for (
int k = 0; k < 2; k++)
1327 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1336 for (
int k = 0; k < nvert; k++)
1339 v[k] = rdofs[c2h_map[cid]];
1386 for (
int iv=0; iv<orig_mesh.
GetNV(); ++iv)
1388 vglobal[iv] = fes.GetGlobalTDofNumber(iv);
1397 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1423 constexpr
int ntris = 2, nv_tri = 3, nv_quad = 4;
1426 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1430 for (
int j = 0; j < orig_n_verts; j++)
1432 fes.GetVertexDofs(orig_mesh.
GroupVertex(gr, j), dofs);
1437 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1438 for (
int e = 0; e < orig_n_edges; e++)
1450 for (
int e = 0; e < orig_nt; e++)
1457 for (
int iv=0; iv<nv_tri; ++iv) { v2[iv] = v[iv]; }
1464 static const int trimap[12] =
1470 static const int diagmap[4] = { 0, 2, 1, 3 };
1471 for (
int f = 0;
f < orig_nq; ++
f)
1478 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
1479 int iv_min = std::min_element(vg, vg+nv_quad) - vg;
1480 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
1484 v_diag[0] = v[diagmap[0 + isplit*2]];
1485 v_diag[1] = v[diagmap[1 + isplit*2]];
1488 for (
int itri=0; itri<ntris; ++itri)
1492 for (
int iv=0; iv<nv_tri; ++iv)
1494 v2[iv] = v[trimap[itri + isplit*2 + iv*ntris*2]];
1512 const int meshgen_save =
meshgen;
1541 int max_attr = attr.
Size() ? attr.
Max() : 1 ;
1542 int glb_max_attr = -1;
1543 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1547 bool *attr_marker =
new bool[glb_max_attr];
1548 bool *glb_attr_marker =
new bool[glb_max_attr];
1549 for (
int i = 0; i < glb_max_attr; i++)
1551 attr_marker[i] =
false;
1553 for (
int i = 0; i < attr.
Size(); i++)
1555 attr_marker[attr[i] - 1] =
true;
1557 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1558 MPI_C_BOOL, MPI_LOR,
MyComm);
1559 delete [] attr_marker;
1564 for (
int i = 0; i < glb_max_attr; i++)
1566 if (glb_attr_marker[i])
1571 delete [] glb_attr_marker;
1582 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1588 MFEM_WARNING(
"Non-positive element attributes found!");
1597 o = (v[0] < v[1]) ? (+1) : (-1);
1606 "Expecting a triangular face.");
1617 "Expecting a quadrilateral face.");
1633 gr_sedge.
GetI()[0] = 0;
1652 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1655 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1657 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1660 if (n == 0) {
continue; }
1661 sedge_ord_map.SetSize(n);
1662 for (
int j = 0; j < n; j++)
1664 sedge_ord_map[j].one = sedge_ord[k+j];
1665 sedge_ord_map[j].two = j;
1667 SortPairs<int, int>(sedge_ord_map, n);
1668 for (
int j = 0; j < n; j++)
1671 const int *v =
shared_edges[sedge_from]->GetVertices();
1672 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1674 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1675 for (
int j = 0; j < n; j++)
1679 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1693 ilen_len[j].one = order[j];
1694 ilen_len[j].two =
GetLength(i, it.Column());
1698 SortPairs<int, double>(ilen_len, order.
Size());
1701 for (
int i = 1; i < order.
Size(); i++)
1703 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1713 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1716 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1728 elements[i]->MarkEdge(v_to_v, order);
1736 boundary[i]->MarkEdge(v_to_v, order);
1755 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1772 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1773 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1775 if (bit == 8*
sizeof(
unsigned))
1781 const face_t &
f = face_stack.
Last();
1782 int mid = v_to_v.
FindId(f.one, f.two);
1792 face_stack.
Append(face_t(f.three, f.one, mid));
1793 face_t &r = face_stack[face_stack.
Size()-2];
1794 r = face_t(r.two, r.three, mid);
1806 bool need_refinement = 0;
1807 face_stack.
Append(face_t(v[0], v[1], v[2]));
1808 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1810 if (bit == 8*
sizeof(
unsigned))
1812 code = codes[pos++];
1816 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1818 const face_t &
f = face_stack.
Last();
1819 int mid = v_to_v.
FindId(f.one, f.two);
1822 mid = v_to_v.
GetId(f.one, f.two);
1823 int ind[2] = { f.one, f.two };
1826 need_refinement = 1;
1829 face_stack.
Append(face_t(f.three, f.one, mid));
1830 face_t &r = face_stack[face_stack.
Size()-2];
1831 r = face_t(r.two, r.three, mid);
1833 return need_refinement;
1839 if (HYPRE_AssumedPartitionCheck())
1842 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_BIG_INT, MPI_SUM,
MyComm);
1843 for (
int i = 0; i < N; i++)
1846 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1847 (*offsets[i])[1] = temp[i];
1850 for (
int i = 0; i < N; i++)
1852 (*offsets[i])[2] = temp[i];
1854 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1855 "overflow in offsets");
1861 MPI_Allgather(loc_sizes, N, HYPRE_MPI_BIG_INT, temp.
GetData(), N,
1862 HYPRE_MPI_BIG_INT,
MyComm);
1863 for (
int i = 0; i < N; i++)
1868 for (
int j = 0; j <
NRanks; j++)
1870 offs[j+1] = offs[j] + temp[i+N*j];
1874 "overflow in offsets");
1898 for (
int j = 0; j < nv; j++)
1917 for (
int j = 0; j < n; j++)
1919 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
1927 MFEM_ABORT(
"Nodes are not ParGridFunction!");
1960 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
1986 *new_nodes = *
Nodes;
2019 bool del_tables =
false;
2046 gr_sface =
new Table;
2076 if (del_tables) {
delete gr_sface; }
2087 int num_face_nbrs = 0;
2090 if (gr_sface->
RowSize(g-1) > 0)
2098 if (num_face_nbrs == 0)
2108 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
2110 if (gr_sface->
RowSize(g-1) > 0)
2115 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
2117 rank_group[counter].two = g;
2122 SortPairs<int, int>(rank_group, rank_group.
Size());
2124 for (
int fn = 0; fn < num_face_nbrs; fn++)
2130 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2131 MPI_Request *send_requests = requests;
2132 MPI_Request *recv_requests = requests + num_face_nbrs;
2133 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2135 int *nbr_data =
new int[6*num_face_nbrs];
2136 int *nbr_send_data = nbr_data;
2137 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
2144 Table send_face_nbr_elemdata, send_face_nbr_facedata;
2148 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
2149 send_face_nbr_facedata.
MakeI(num_face_nbrs);
2150 for (
int fn = 0; fn < num_face_nbrs; fn++)
2153 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2154 int *sface = gr_sface->
GetRow(nbr_group-1);
2155 for (
int i = 0; i < num_sfaces; i++)
2157 int lface = s2l_face[sface[i]];
2159 if (el_marker[el] != fn)
2164 const int nv =
elements[el]->GetNVertices();
2165 const int *v =
elements[el]->GetVertices();
2166 for (
int j = 0; j < nv; j++)
2167 if (vertex_marker[v[j]] != fn)
2169 vertex_marker[v[j]] = fn;
2180 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
2185 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2186 &send_requests[fn]);
2187 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2188 &recv_requests[fn]);
2192 send_face_nbr_elemdata.
MakeJ();
2193 send_face_nbr_facedata.
MakeJ();
2197 for (
int fn = 0; fn < num_face_nbrs; fn++)
2200 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2201 int *sface = gr_sface->
GetRow(nbr_group-1);
2202 for (
int i = 0; i < num_sfaces; i++)
2204 const int sf = sface[i];
2205 int lface = s2l_face[sf];
2207 if (el_marker[el] != fn)
2212 const int nv =
elements[el]->GetNVertices();
2213 const int *v =
elements[el]->GetVertices();
2214 for (
int j = 0; j < nv; j++)
2215 if (vertex_marker[v[j]] != fn)
2217 vertex_marker[v[j]] = fn;
2232 const int *lf_v =
faces[lface]->GetVertices();
2252 for (
int fn = 0; fn < num_face_nbrs; fn++)
2258 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
2259 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
2260 int *facedata = send_face_nbr_facedata.
GetRow(fn);
2262 for (
int i = 0; i < num_verts; i++)
2264 vertex_marker[verts[i]] = i;
2267 for (
int el = 0; el < num_elems; el++)
2269 const int nv =
elements[elems[el]]->GetNVertices();
2271 for (
int j = 0; j < nv; j++)
2273 elemdata[j] = vertex_marker[elemdata[j]];
2277 el_marker[elems[el]] = el;
2280 for (
int i = 0; i < num_sfaces; i++)
2282 facedata[2*i] = el_marker[facedata[2*i]];
2286 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2289 Table recv_face_nbr_elemdata;
2294 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2297 for (
int fn = 0; fn < num_face_nbrs; fn++)
2305 recv_face_nbr_elemdata.
MakeJ();
2307 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2310 for (
int fn = 0; fn < num_face_nbrs; fn++)
2315 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2316 send_face_nbr_elemdata.
RowSize(fn),
2317 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2319 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2320 recv_face_nbr_elemdata.
RowSize(fn),
2321 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2329 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2331 if (fn == MPI_UNDEFINED)
2339 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2341 for (
int i = 0; i < num_elems; i++)
2347 for (
int j = 0; j < nv; j++)
2349 recv_elemdata[j] += vert_off;
2352 recv_elemdata += nv;
2357 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2360 recv_face_nbr_facedata.
SetSize(
2362 for (
int fn = 0; fn < num_face_nbrs; fn++)
2367 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2368 send_face_nbr_facedata.
RowSize(fn),
2369 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2372 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2373 send_face_nbr_facedata.
RowSize(fn),
2374 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2381 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2383 if (fn == MPI_UNDEFINED)
2390 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2391 int *sface = gr_sface->
GetRow(nbr_group-1);
2393 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2395 for (
int i = 0; i < num_sfaces; i++)
2397 const int sf = sface[i];
2398 int lface = s2l_face[sf];
2400 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2401 int info = facedata[2*i+1];
2409 int nbr_ori = info%64, nbr_v[4];
2410 const int *lf_v =
faces[lface]->GetVertices();
2417 for (
int j = 0; j < 3; j++)
2419 nbr_v[perm[j]] = sf_v[j];
2429 for (
int j = 0; j < 4; j++)
2431 nbr_v[perm[j]] = sf_v[j];
2437 info = 64*(info/64) + nbr_ori;
2443 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2460 else if (
Nodes == NULL)
2470 if (!num_face_nbrs) {
return; }
2472 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2473 MPI_Request *send_requests = requests;
2474 MPI_Request *recv_requests = requests + num_face_nbrs;
2475 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2479 for (
int i = 0; i < send_vertices.Size(); i++)
2485 for (
int fn = 0; fn < num_face_nbrs; fn++)
2492 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
2497 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
2500 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2501 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2509 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2520 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2562 for (
int i = 0; i < s2l_face->
Size(); i++)
2577 for (
int i = 0; i < s2l_face->
Size(); i++)
2579 int lface = (*s2l_face)[i];
2580 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2605 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
2606 "Mesh requires nodal Finite Element.");
2608 #if 0 // TODO: handle the case of non-interpolatory Nodes
2617 FETr->
SetFE(face_el);
2639 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
2653 Elem2NbrNo = -1 - face_info.
Elem2No;
2697 if (is_ghost || fill2)
2720 mfem::out <<
"\nInternal error: face id = " << FaceNo
2721 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
2723 MFEM_ABORT(
"internal error");
2744 MFEM_ASSERT(
Dim > 1,
"");
2763 MFEM_ASSERT(
Dim > 1,
"");
2766 return sface < csize
2768 : shared.
slaves[sface - csize].index;
2775 void Rotate3Indirect(
int &
a,
int &
b,
int &c,
2778 if (order[a] < order[b])
2780 if (order[a] > order[c])
2787 if (order[b] < order[c])
2808 Table *old_elem_vert = NULL;
2822 gr_svert.
GetI()[0] = 0;
2847 svert_comm.
Bcast(svert_master_index);
2861 for (
int i = 0; i <
vertices.Size(); i++)
2863 int s = lvert_svert[i];
2866 glob_vert_order[i] =
2867 (std::int64_t(svert_master_rank[s]) << 32) + svert_master_index[s];
2871 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
2883 int *v =
elements[i]->GetVertices();
2885 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2887 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
2889 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
2903 int *v =
boundary[i]->GetVertices();
2905 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2909 const bool check_consistency =
true;
2910 if (check_consistency)
2919 gr_stria.
GetI()[0] = 0;
2931 for (
int i = 0; i < stria_flag.Size(); i++)
2934 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
2936 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
2940 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
2945 stria_comm.
Bcast(stria_master_flag);
2946 for (
int i = 0; i < stria_flag.Size(); i++)
2949 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
2950 "inconsistent vertex ordering found, shared triangle "
2952 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
2953 <<
"local flag: " << stria_flag[i]
2954 <<
", master flag: " << stria_master_flag[i]);
2963 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2979 delete old_elem_vert;
2992 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3001 int uniform_refinement = 0;
3005 uniform_refinement = 1;
3016 for (
int i = 0; i < marked_el.
Size(); i++)
3022 for (
int i = 0; i < marked_el.
Size(); i++)
3031 for (
int i = 0; i < marked_el.
Size(); i++)
3048 int need_refinement;
3049 int max_faces_in_group = 0;
3055 face_splittings[i].
Reserve(faces_in_group);
3056 if (faces_in_group > max_faces_in_group)
3058 max_faces_in_group = faces_in_group;
3064 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3067 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3068 int ref_loops_all = 0, ref_loops_par = 0;
3072 need_refinement = 0;
3075 if (
elements[i]->NeedRefinement(v_to_v))
3077 need_refinement = 1;
3081 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3085 if (uniform_refinement)
3092 if (need_refinement == 0)
3094 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3098 const int tag = 293;
3107 if (faces_in_group == 0) {
continue; }
3109 face_splittings[i].
SetSize(0);
3110 for (
int j = 0; j < faces_in_group; j++)
3113 face_splittings[i]);
3117 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3118 MPI_UNSIGNED, neighbor, tag,
MyComm,
3119 &requests[req_count++]);
3127 if (faces_in_group == 0) {
continue; }
3131 MPI_Probe(neighbor, tag,
MyComm, &status);
3133 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3135 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3138 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3145 int nr = need_refinement;
3146 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3148 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3151 while (need_refinement == 1);
3153 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3155 int i = ref_loops_all;
3156 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3159 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3160 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3168 delete [] face_splittings;
3173 need_refinement = 0;
3176 if (
boundary[i]->NeedRefinement(v_to_v))
3178 need_refinement = 1;
3183 while (need_refinement == 1);
3188 " (NumOfBdrElements != boundary.Size())");
3215 int uniform_refinement = 0;
3219 uniform_refinement = 1;
3228 int *edge1 =
new int[nedges];
3229 int *edge2 =
new int[nedges];
3230 int *middle =
new int[nedges];
3232 for (
int i = 0; i < nedges; i++)
3234 edge1[i] = edge2[i] = middle[i] = -1;
3239 int *v =
elements[i]->GetVertices();
3240 for (
int j = 0; j < 3; j++)
3242 int ind = v_to_v(v[j], v[(j+1)%3]);
3243 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3248 for (
int i = 0; i < marked_el.
Size(); i++)
3254 int need_refinement;
3255 int edges_in_group, max_edges_in_group = 0;
3257 int **edge_splittings =
new int*[
GetNGroups()-1];
3261 edge_splittings[i] =
new int[edges_in_group];
3262 if (edges_in_group > max_edges_in_group)
3264 max_edges_in_group = edges_in_group;
3267 int neighbor, *iBuf =
new int[max_edges_in_group];
3271 MPI_Request request;
3276 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3277 int ref_loops_all = 0, ref_loops_par = 0;
3281 need_refinement = 0;
3282 for (
int i = 0; i < nedges; i++)
3284 if (middle[i] != -1 && edge1[i] != -1)
3286 need_refinement = 1;
3290 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3294 if (uniform_refinement)
3301 if (need_refinement == 0)
3303 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3312 edges_in_group = group_edges.
Size();
3314 if (edges_in_group != 0)
3316 for (
int j = 0; j < edges_in_group; j++)
3318 edge_splittings[i][j] =
3331 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3332 neighbor, 0,
MyComm, &request);
3340 edges_in_group = group_edges.
Size();
3341 if (edges_in_group != 0)
3352 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3353 MPI_ANY_TAG,
MyComm, &status);
3355 for (
int j = 0; j < edges_in_group; j++)
3357 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3360 int ii = v_to_v(v[0], v[1]);
3361 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3362 if (middle[ii] != -1)
3364 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3368 need_refinement = 1;
3370 for (
int c = 0; c < 2; c++)
3380 int nr = need_refinement;
3381 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3384 while (need_refinement == 1);
3386 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3388 int i = ref_loops_all;
3389 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3392 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3393 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3401 delete [] edge_splittings[i];
3403 delete [] edge_splittings;
3408 int v1[2], v2[2], bisect, temp;
3410 for (
int i = 0; i < temp; i++)
3412 int *v =
boundary[i]->GetVertices();
3413 bisect = v_to_v(v[0], v[1]);
3414 if (middle[bisect] != -1)
3419 v1[0] = v[0]; v1[1] = middle[bisect];
3420 v2[0] = middle[bisect]; v2[1] = v[1];
3427 mfem_error(
"Only bisection of segment is implemented for bdr"
3460 for (
int j = 0; j < marked_el.
Size(); j++)
3462 int i = marked_el[j];
3465 int new_v = cnv + j, new_e = cne + j;
3474 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3476 UseExternalData(seg_children, 1, 2, 3);
3497 MFEM_ABORT(
"NURBS meshes are not supported. Please project the "
3498 "NURBS to Nodes first with SetCurvature().");
3503 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3504 "(you need to initialize the ParMesh from a nonconforming "
3545 double threshold,
int nc_limit,
int op)
3547 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3548 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3549 "Project the NURBS to Nodes first.");
3562 for (
int i = 0; i < dt.
Size(); i++)
3564 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3569 if (error < threshold) { derefs.
Append(i); }
3573 if (!glob_size) {
return false; }
3616 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
3623 MFEM_VERIFY(dynamic_cast<ParFiniteElementSpace*>(
Nodes->
FESpace())
3624 != NULL,
"internal error");
3654 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
3664 int *I_group_svert, *J_group_svert;
3665 int *I_group_sedge, *J_group_sedge;
3670 I_group_svert[0] = I_group_svert[1] = 0;
3671 I_group_sedge[0] = I_group_sedge[1] = 0;
3678 for (
int group = 0; group <
GetNGroups()-1; group++)
3688 const int ind = middle[v_to_v(v[0], v[1])];
3694 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3701 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3702 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3705 J = J_group_svert+I_group_svert[group];
3706 for (
int i = 0; i < group_verts.
Size(); i++)
3708 J[i] = group_verts[i];
3710 J = J_group_sedge+I_group_sedge[group];
3711 for (
int i = 0; i < group_edges.
Size(); i++)
3713 J[i] = group_edges[i];
3727 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
3729 Array<int> group_verts, group_edges, group_trias;
3748 I_group_svert[0] = 0;
3749 I_group_sedge[0] = 0;
3750 I_group_stria[0] = 0;
3752 for (
int group = 0; group <
GetNGroups()-1; group++)
3763 int ind = v_to_v.
FindId(v[0], v[1]);
3764 if (ind == -1) {
continue; }
3767 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3777 ind = v_to_v.
FindId(v[0], ind);
3785 ind = v_to_v.
FindId(v[0], v[1]);
3806 while (sedge_stack.
Size() > 0);
3813 int ind = v_to_v.
FindId(v[0], v[1]);
3814 if (ind == -1) {
continue; }
3817 const int edge_attr = 1;
3826 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
3827 ind = v_to_v.
FindId(v[0], v[1]);
3835 ind = v_to_v.
FindId(v[0], v[1]);
3853 v = sface_stack[sface_stack.
Size()-2].v;
3855 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
3858 while (sface_stack.
Size() > 0);
3864 ind = v_to_v.
FindId(v[0], v[1]);
3885 while (sedge_stack.
Size() > 0);
3888 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3889 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3890 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3892 J_group_svert.
Append(group_verts);
3893 J_group_sedge.
Append(group_edges);
3894 J_group_stria.
Append(group_trias);
3911 int *I_group_svert, *J_group_svert;
3912 int *I_group_sedge, *J_group_sedge;
3917 I_group_svert[0] = 0;
3918 I_group_sedge[0] = 0;
3925 for (
int group = 0; group <
GetNGroups()-1; group++)
3939 const int attr =
shared_edges[sedges[i]]->GetAttribute();
3945 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
3946 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
3948 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
3949 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3965 Array<int> group_verts, group_edges, group_trias, group_quads;
3967 int *I_group_svert, *J_group_svert;
3968 int *I_group_sedge, *J_group_sedge;
3969 int *I_group_stria, *J_group_stria;
3970 int *I_group_squad, *J_group_squad;
3977 I_group_svert[0] = 0;
3978 I_group_sedge[0] = 0;
3979 I_group_stria[0] = 0;
3980 I_group_squad[0] = 0;
3992 const int oface = old_nv + old_nedges;
3994 for (
int group = 0; group <
GetNGroups()-1; group++)
4006 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4010 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4020 const int stria = group_trias[i];
4023 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4024 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4025 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4026 const int edge_attr = 1;
4041 v[1] = m[0]; v[2] = m[2];
4042 group_trias.
Append(nst+0);
4043 group_trias.
Append(nst+1);
4044 group_trias.
Append(nst+2);
4052 const int squad = group_quads[i];
4054 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4056 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4060 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4061 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4062 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4063 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4064 const int edge_attr = 1;
4081 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4082 group_quads.
Append(nsq+0);
4083 group_quads.
Append(nsq+1);
4084 group_quads.
Append(nsq+2);
4088 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4089 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4090 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4091 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4093 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4094 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4095 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4096 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4115 const bool update_nodes =
false;
4145 const bool update_nodes =
false;
4154 f2qf.
Size() ? &f2qf : NULL);
4164 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4170 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4176 out <<
"NETGEN_Neutral_Format\n";
4181 for (j = 0; j <
Dim; j++)
4194 out <<
elements[i]->GetAttribute();
4195 for (j = 0; j < nv; j++)
4197 out <<
" " << ind[j]+1;
4209 out <<
boundary[i]->GetAttribute();
4210 for (j = 0; j < nv; j++)
4212 out <<
" " << ind[j]+1;
4223 for (j = 0; j < 3; j++)
4225 out <<
' ' << ind[j]+1;
4239 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4241 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4242 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4243 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4249 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4257 out << i+1 <<
" " <<
elements[i]->GetAttribute();
4258 for (j = 0; j < nv; j++)
4260 out <<
" " << ind[j]+1;
4270 out <<
boundary[i]->GetAttribute();
4271 for (j = 0; j < nv; j++)
4273 out <<
" " << ind[j]+1;
4275 out <<
" 1.0 1.0 1.0 1.0\n";
4286 for (j = 0; j < 4; j++)
4288 out <<
' ' << ind[j]+1;
4290 out <<
" 1.0 1.0 1.0 1.0\n";
4299 out <<
"areamesh2\n\n";
4306 attr =
boundary[i]->GetAttribute();
4309 for (j = 0; j < v.
Size(); j++)
4311 out << v[j] + 1 <<
" ";
4321 for (j = 0; j < v.
Size(); j++)
4323 out << v[j] + 1 <<
" ";
4332 attr =
elements[i]->GetAttribute();
4348 for (j = 0; j < v.
Size(); j++)
4350 out << v[j] + 1 <<
" ";
4359 for (j = 0; j <
Dim; j++)
4384 bool print_shared =
true;
4385 int i, j, shared_bdr_attr;
4402 s2l_face = &nc_shared_faces;
4409 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4412 if (index < nfaces) { nc_shared_faces.
Append(index); }
4414 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4418 if (index < nfaces) { nc_shared_faces.
Append(index); }
4420 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4423 if (index < nfaces) { nc_shared_faces.
Append(index); }
4428 out <<
"MFEM mesh v1.0\n";
4432 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4437 "# TETRAHEDRON = 4\n"
4442 out <<
"\ndimension\n" <<
Dim
4450 if (print_shared &&
Dim > 1)
4452 num_bdr_elems += s2l_face->
Size();
4454 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4460 if (print_shared &&
Dim > 1)
4468 shared_bdr_attr =
MyRank + 1;
4470 for (i = 0; i < s2l_face->
Size(); i++)
4473 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4501 ostringstream fname_with_suffix;
4502 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
4503 ofstream ofs(fname_with_suffix.str().c_str());
4504 ofs.precision(precision);
4508 #ifdef MFEM_USE_ADIOS2
4521 for (
int i = 0; i < nv; i++)
4529 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4537 out <<
"MFEM mesh v1.0\n";
4541 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4546 "# TETRAHEDRON = 4\n"
4551 out <<
"\ndimension\n" <<
Dim;
4555 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4558 out <<
"\n\nelements\n" << ne <<
'\n';
4562 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
4566 for (j = 0; j < nv; j++)
4573 for (p = 1; p <
NRanks; p++)
4575 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
4579 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
4581 for (i = 0; i < ne; )
4584 out << p+1 <<
' ' << ints[i];
4587 for (j = 0; j < k; j++)
4589 out <<
' ' << vc + ints[i++];
4602 ne += 1 +
elements[i]->GetNVertices();
4605 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
4613 MFEM_ASSERT(ints.
Size() == ne,
"");
4616 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
4641 dump_element(
boundary[i], ints); ne++;
4679 MFEM_ABORT(
"invalid dimension: " <<
Dim);
4689 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4691 for (i = 0; i < list.
masters.Size(); i++)
4694 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4696 for (i = 0; i < list.
slaves.Size(); i++)
4699 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4703 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4706 out <<
"\nboundary\n" << k <<
'\n';
4708 for (p = 0; p <
NRanks; p++)
4712 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
4724 for (i = 0; i < ne; )
4727 out << p+1 <<
' ' << ints[i];
4730 for (j = 0; j < k; j++)
4732 out <<
' ' << vc + ints[i++];
4743 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
4754 out <<
"\nvertices\n" << nv <<
'\n';
4770 for (p = 1; p <
NRanks; p++)
4772 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
4776 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
4778 for (i = 0; i < nv; i++)
4783 out <<
' ' << vert[i*spaceDim+j];
4798 vert[i*spaceDim+j] =
vertices[i](j);
4803 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
4830 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
4842 ofs.precision(precision);
4849 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
4852 int i, j, k, nv, ne,
p;
4860 out <<
"NETGEN_Neutral_Format\n";
4863 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4867 for (j = 0; j <
Dim; j++)
4873 for (p = 1; p <
NRanks; p++)
4875 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4877 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4878 for (i = 0; i < nv; i++)
4880 for (j = 0; j <
Dim; j++)
4882 out <<
" " << vert[Dim*i+j];
4890 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4897 for (j = 0; j < nv; j++)
4899 out <<
" " << ind[j]+1;
4904 for (p = 1; p <
NRanks; p++)
4906 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4907 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4909 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4910 for (i = 0; i < ne; i++)
4913 for (j = 0; j < 4; j++)
4915 out <<
" " << k+ints[i*4+j]+1;
4923 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4931 for (j = 0; j < nv; j++)
4933 out <<
" " << ind[j]+1;
4944 for (j = 0; j < 3; j++)
4946 out <<
' ' << ind[j]+1;
4952 for (p = 1; p <
NRanks; p++)
4954 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4955 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4957 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4958 for (i = 0; i < ne; i++)
4961 for (j = 0; j < 3; j++)
4963 out <<
' ' << k+ints[i*3+j]+1;
4973 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4977 for (j = 0; j <
Dim; j++)
4981 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4985 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4986 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4992 for (j = 0; j < 4; j++)
4997 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
5000 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5001 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5003 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5008 for (j = 0; j < 3; j++)
5013 for ( ; i < ne; i++)
5016 for (j = 0; j < 3; j++)
5021 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
5027 int i, j, k, nv, ne,
p;
5033 int TG_nv, TG_ne, TG_nbe;
5040 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5043 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
5044 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
5045 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
5046 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
5047 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
5054 <<
" " <<
vertices[i](2) <<
" 0.0\n";
5056 for (p = 1; p <
NRanks; p++)
5058 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5060 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
5061 for (i = 0; i < nv; i++)
5063 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
5064 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
5074 out << i+1 <<
" " << 1;
5075 for (j = 0; j < nv; j++)
5077 out <<
" " << ind[j]+1;
5082 for (p = 1; p <
NRanks; p++)
5084 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5085 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5087 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
5088 for (i = 0; i < ne; i++)
5090 out << i+1 <<
" " << p+1;
5091 for (j = 0; j < 8; j++)
5093 out <<
" " << k+ints[i*8+j]+1;
5108 for (j = 0; j < nv; j++)
5110 out <<
" " << ind[j]+1;
5112 out <<
" 1.0 1.0 1.0 1.0\n";
5122 for (j = 0; j < 4; j++)
5124 out <<
' ' << ind[j]+1;
5126 out <<
" 1.0 1.0 1.0 1.0\n";
5129 for (p = 1; p <
NRanks; p++)
5131 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5132 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5134 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
5135 for (i = 0; i < ne; i++)
5138 for (j = 0; j < 4; j++)
5140 out <<
" " << k+ints[i*4+j]+1;
5142 out <<
" 1.0 1.0 1.0 1.0\n";
5152 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5157 for (j = 0; j <
Dim; j++)
5161 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
5163 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5169 for (j = 0; j < 8; j++)
5174 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
5176 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5178 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5183 for (j = 0; j < 4; j++)
5188 for ( ; i < ne; i++)
5191 for (j = 0; j < 4; j++)
5196 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
5202 int i, j, k, attr, nv, ne,
p;
5210 out <<
"areamesh2\n\n";
5214 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5219 attr =
boundary[i]->GetAttribute();
5222 for (j = 0; j < v.
Size(); j++)
5224 out << v[j] + 1 <<
" ";
5234 for (j = 0; j < v.
Size(); j++)
5236 out << v[j] + 1 <<
" ";
5241 for (p = 1; p <
NRanks; p++)
5243 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5244 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5246 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
5247 for (i = 0; i < ne; i++)
5250 for (j = 0; j < 2; j++)
5252 out <<
" " << k+ints[i*2+j]+1;
5261 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5267 out << 1 <<
" " << 3 <<
" ";
5268 for (j = 0; j < v.
Size(); j++)
5270 out << v[j] + 1 <<
" ";
5275 for (p = 1; p <
NRanks; p++)
5277 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5278 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5280 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
5281 for (i = 0; i < ne; i++)
5283 out << p+1 <<
" " << 3;
5284 for (j = 0; j < 3; j++)
5286 out <<
" " << k+ints[i*3+j]+1;
5295 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5299 for (j = 0; j <
Dim; j++)
5305 for (p = 1; p <
NRanks; p++)
5307 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5309 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
5310 for (i = 0; i < nv; i++)
5312 for (j = 0; j <
Dim; j++)
5314 out <<
" " << vert[Dim*i+j];
5324 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5327 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5332 for (j = 0; j < 2; j++)
5337 for ( ; i < ne; i++)
5340 for (j = 0; j < 2; j++)
5345 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
5348 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5355 for (j = 0; j < 3; j++)
5360 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
5363 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5367 for (j = 0; j <
Dim; j++)
5371 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
5389 MPI_Allreduce(p_min.
GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN,
MyComm);
5390 MPI_Allreduce(p_max.
GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX,
MyComm);
5394 double &gk_min,
double &gk_max)
5396 double h_min, h_max, kappa_min, kappa_max;
5400 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
5401 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
5402 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
5403 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
5410 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
5414 out <<
"Parallel Mesh Stats:" <<
'\n';
5420 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
5426 kappa_min = kappa_max =
kappa;
5430 if (h < h_min) { h_min = h; }
5431 if (h > h_max) { h_max = h; }
5432 if (kappa < kappa_min) { kappa_min =
kappa; }
5433 if (kappa > kappa_max) { kappa_max =
kappa; }
5437 double gh_min, gh_max, gk_min, gk_max;
5438 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
5439 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
5440 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
5441 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
5446 long mindata[5], maxdata[5], sumdata[5];
5465 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
5466 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
5467 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
5473 << setw(12) <<
"minimum"
5474 << setw(12) <<
"average"
5475 << setw(12) <<
"maximum"
5476 << setw(12) <<
"total" <<
'\n';
5478 << setw(12) << mindata[0]
5479 << setw(12) << sumdata[0]/
NRanks
5480 << setw(12) << maxdata[0]
5481 << setw(12) << sumdata[0] <<
'\n';
5483 << setw(12) << mindata[1]
5484 << setw(12) << sumdata[1]/
NRanks
5485 << setw(12) << maxdata[1]
5486 << setw(12) << sumdata[1] <<
'\n';
5490 << setw(12) << mindata[2]
5491 << setw(12) << sumdata[2]/
NRanks
5492 << setw(12) << maxdata[2]
5493 << setw(12) << sumdata[2] <<
'\n';
5496 << setw(12) << mindata[3]
5497 << setw(12) << sumdata[3]/
NRanks
5498 << setw(12) << maxdata[3]
5499 << setw(12) << sumdata[3] <<
'\n';
5500 out <<
" neighbors "
5501 << setw(12) << mindata[4]
5502 << setw(12) << sumdata[4]/
NRanks
5503 << setw(12) << maxdata[4] <<
'\n';
5506 << setw(12) <<
"minimum"
5507 << setw(12) <<
"maximum" <<
'\n';
5509 << setw(12) << gh_min
5510 << setw(12) << gh_max <<
'\n';
5512 << setw(12) << gk_min
5513 << setw(12) << gk_max <<
'\n';
5520 long local = value, global;
5521 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
5544 Printer(out,
"mfem_serial_mesh_end");
5552 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5563 out <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
5564 for (
int i = 0; i < nv; i++)
5573 out <<
"\nshared_edges " << ne <<
'\n';
5574 for (
int i = 0; i < ne; i++)
5577 out << v[0] <<
' ' << v[1] <<
'\n';
5586 out <<
"\nshared_faces " << nt+nq <<
'\n';
5587 for (
int i = 0; i < nt; i++)
5591 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5594 for (
int i = 0; i < nq; i++)
5598 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5605 out <<
"\nmfem_mesh_end" << endl;
5610 bool high_order_output,
5611 int compression_level,
5614 int pad_digits_rank = 6;
5617 std::string::size_type pos = pathname.find_last_of(
'/');
5619 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
5623 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
5624 std::ofstream
out(pvtu_name);
5627 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
5629 out <<
"<?xml version=\"1.0\"?>\n";
5630 out <<
"<VTKFile type=\"PUnstructuredGrid\"";
5631 out <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
5632 out <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
5634 out <<
"<PPoints>\n";
5635 out <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
5636 out <<
" Name=\"Points\" NumberOfComponents=\"3\""
5637 <<
" format=\"" << data_format <<
"\"/>\n";
5638 out <<
"</PPoints>\n";
5640 out <<
"<PCells>\n";
5641 out <<
"\t<PDataArray type=\"Int32\" ";
5642 out <<
" Name=\"connectivity\" NumberOfComponents=\"1\""
5643 <<
" format=\"" << data_format <<
"\"/>\n";
5644 out <<
"\t<PDataArray type=\"Int32\" ";
5645 out <<
" Name=\"offsets\" NumberOfComponents=\"1\""
5646 <<
" format=\"" << data_format <<
"\"/>\n";
5647 out <<
"\t<PDataArray type=\"UInt8\" ";
5648 out <<
" Name=\"types\" NumberOfComponents=\"1\""
5649 <<
" format=\"" << data_format <<
"\"/>\n";
5650 out <<
"</PCells>\n";
5652 out <<
"<PCellData>\n";
5653 out <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute"
5654 <<
"\" NumberOfComponents=\"1\""
5655 <<
" format=\"" << data_format <<
"\"/>\n";
5656 out <<
"</PCellData>\n";
5658 for (
int ii=0; ii<
NRanks; ii++)
5660 std::string piece = fname +
".proc"
5662 out <<
"<Piece Source=\"" << piece <<
"\"/>\n";
5665 out <<
"</PUnstructuredGrid>\n";
5666 out <<
"</VTKFile>\n";
5670 std::string vtu_fname = pathname +
"/" + fname +
".proc"
5672 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
5679 const int npts = point_mat.
Width();
5680 if (npts == 0) {
return 0; }
5682 const bool no_warn =
false;
5689 Array<int> my_point_rank(npts), glob_point_rank(npts);
5690 for (
int k = 0; k < npts; k++)
5692 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
5695 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
5696 MPI_INT, MPI_MIN,
MyComm);
5699 for (
int k = 0; k < npts; k++)
5701 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
5705 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
5708 if (warn && pts_found != npts &&
MyRank == 0)
5710 MFEM_WARNING((npts-pts_found) <<
" points were not found");
5715 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &
out)
5718 for (
int d = 1; d < space_dim; d++)
5726 stringstream out_name;
5727 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
5728 <<
".shared_entities";
5729 ofstream
out(out_name.str().c_str());
5737 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5748 out <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
5749 for (
int i = 0; i < nv; i++)
5761 out <<
"\nshared_edges " << ne <<
'\n';
5762 for (
int i = 0; i < ne; i++)