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++)
163 partitioning = partitioning_;
177 Table *edge_element = NULL;
180 activeBdrElem, edge_element);
235 int nsedges =
FindSharedEdges(mesh, partitioning, edge_element, groups);
242 int ngroups = groups.
Size()-1, nstris, nsquads;
249 face_group, vert_global_local);
265 "invalid NURBS mesh");
291 int element_counter = 0;
292 for (
int i = 0; i < mesh.
GetNE(); i++)
294 if (partitioning[i] ==
MyRank)
297 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
298 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
309 if (partitioning != partitioning_)
311 delete [] partitioning;
319 const int* partitioning,
323 vert_global_local = -1;
325 int vert_counter = 0;
326 for (
int i = 0; i < mesh.
GetNE(); i++)
328 if (partitioning[i] ==
MyRank)
332 for (
int j = 0; j < vert.
Size(); j++)
334 if (vert_global_local[vert[j]] < 0)
336 vert_global_local[vert[j]] = vert_counter++;
344 for (
int i = 0; i < vert_global_local.
Size(); i++)
346 if (vert_global_local[i] >= 0)
348 vert_global_local[i] = vert_counter++;
354 for (
int i = 0; i < vert_global_local.
Size(); i++)
356 if (vert_global_local[i] >= 0)
369 const int nelems = std::count_if(partitioning,
370 partitioning + mesh.
GetNE(), [
this](
int i) { return i == MyRank;});
377 int element_counter = 0;
378 for (
int i = 0; i < mesh.
GetNE(); i++)
380 if (partitioning[i] ==
MyRank)
384 int nv =
elements[element_counter]->GetNVertices();
385 for (
int j = 0; j < nv; j++)
387 v[j] = vert_global_local[v[j]];
393 return element_counter;
399 Table*& edge_element)
405 activeBdrElem =
false;
410 for (
int i = 0; i < mesh.
GetNBE(); i++)
412 int face, o, el1, el2;
415 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
420 activeBdrElem[i] =
true;
425 int bdrelem_counter = 0;
427 for (
int i = 0; i < mesh.
GetNBE(); i++)
429 int face, o, el1, el2;
432 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
436 int nv =
boundary[bdrelem_counter]->GetNVertices();
437 for (
int j = 0; j < nv; j++)
439 v[j] = vert_global_local[v[j]];
447 edge_element =
new Table;
450 for (
int i = 0; i < mesh.
GetNBE(); i++)
453 int el1 = edge_element->
GetRow(edge)[0];
454 if (partitioning[el1] ==
MyRank)
459 activeBdrElem[i] =
true;
464 int bdrelem_counter = 0;
466 for (
int i = 0; i < mesh.
GetNBE(); i++)
469 int el1 = edge_element->
GetRow(edge)[0];
470 if (partitioning[el1] ==
MyRank)
474 int nv =
boundary[bdrelem_counter]->GetNVertices();
475 for (
int j = 0; j < nv; j++)
477 v[j] = vert_global_local[v[j]];
485 for (
int i = 0; i < mesh.
GetNBE(); i++)
487 int vert = mesh.
boundary[i]->GetVertices()[0];
490 if (partitioning[el1] ==
MyRank)
496 int bdrelem_counter = 0;
498 for (
int i = 0; i < mesh.
GetNBE(); i++)
500 int vert = mesh.
boundary[i]->GetVertices()[0];
503 if (partitioning[el1] ==
MyRank)
507 v[0] = vert_global_local[v[0]];
524 for (
int i = 0; i < face_group.
Size(); i++)
531 el[0] = partitioning[el[0]];
532 el[1] = partitioning[el[1]];
537 face_group[i] = groups.
Insert(group) - 1;
544 Table*& edge_element,
550 int sedge_counter = 0;
553 edge_element =
new Table;
564 for (
int i = 0; i < edge_element->
Size(); i++)
566 int me = 0, others = 0;
567 for (
int j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
569 int k = edge_element->
GetJ()[j];
570 int rank = partitioning[k];
571 edge_element->
GetJ()[j] = rank;
590 edge_element->
GetRow(i)[0] = -1;
594 return sedge_counter;
603 int svert_counter = 0;
604 for (
int i = 0; i < vert_element->
Size(); i++)
606 int me = 0, others = 0;
607 for (
int j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
609 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
624 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
628 vert_element->
GetI()[i] = -1;
631 return svert_counter;
636 int &nstria,
int &nsquad)
642 for (
int i = 0; i < face_group.
Size(); i++)
644 if (face_group[i] >= 0)
661 for (
int i = 0; i < face_group.
Size(); i++)
663 if (face_group[i] >= 0)
684 for (
int i = 0; i < edge_element.
Size(); i++)
686 if (edge_element.
GetRow(i)[0] >= 0)
694 int sedge_counter = 0;
695 for (
int i = 0; i < edge_element.
Size(); i++)
697 if (edge_element.
GetRow(i)[0] >= 0)
710 for (
int i = 0; i < vert_element.
Size(); i++)
712 if (vert_element.
GetI()[i] >= 0)
720 int svert_counter = 0;
721 for (
int i = 0; i < vert_element.
Size(); i++)
723 if (vert_element.
GetI()[i] >= 0)
733 const Mesh& mesh,
int *partitioning,
742 if (
Dim < 3) {
return; }
744 int stria_counter = 0;
745 int squad_counter = 0;
746 for (
int i = 0; i < face_group.
Size(); i++)
748 if (face_group[i] < 0) {
continue; }
758 for (
int j = 0; j < 3; j++)
760 v[j] = vert_global_local[v[j]];
762 const int lface = (*faces_tbl)(v[0], v[1], v[2]);
778 if (
MyRank == partitioning[gl_el2])
780 std::swap(v[0], v[1]);
792 for (
int j = 0; j < 4; j++)
794 v[j] = vert_global_local[v[j]];
797 (*faces_tbl)(v[0], v[1], v[2], v[3]);
803 MFEM_ABORT(
"unknown face type: " << face->
GetType());
811 const Table* edge_element)
823 int sedge_counter = 0;
824 for (
int i = 0; i < edge_element->
Size(); i++)
826 if (edge_element->
GetRow(i)[0] >= 0)
832 new Segment(vert_global_local[vert[0]],
833 vert_global_local[vert[1]], 1);
835 sedge_ledge[sedge_counter] = v_to_v(vert_global_local[vert[0]],
836 vert_global_local[vert[1]]);
838 MFEM_VERIFY(
sedge_ledge[sedge_counter] >= 0,
"Error in v_to_v.");
853 int svert_counter = 0;
854 for (
int i = 0; i < vert_element->
Size(); i++)
856 if (vert_element->
GetI()[i] >= 0)
858 svert_lvert[svert_counter++] = vert_global_local[i];
866 : MyComm(pncmesh.MyComm)
867 , NRanks(pncmesh.NRanks)
868 , MyRank(pncmesh.MyRank)
869 , glob_elem_offset(-1)
870 , glob_offset_sequence(-1)
895 MPI_Allreduce(&loc_meshgen, &
meshgen, 1, MPI_INT, MPI_BOR,
MyComm);
909 const int l_edge = v_to_v(v[0], v[1]);
910 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
921 for (
int st = 0; st < nst; st++)
935 bool fix_orientation)
936 : glob_elem_offset(-1)
937 , glob_offset_sequence(-1)
947 Load(input, generate_edges, refine, fix_orientation);
951 bool fix_orientation)
958 Loader(input, generate_edges,
"mfem_serial_mesh_end");
970 MFEM_ASSERT(
pncmesh,
"internal error");
993 MFEM_VERIFY(ident ==
"communication_groups",
994 "input stream is not a parallel MFEM mesh");
1002 input >> ident >> num_sverts;
1003 MFEM_VERIFY(ident ==
"total_shared_vertices",
"invalid mesh file");
1012 input >> ident >> num_sedges;
1013 MFEM_VERIFY(ident ==
"total_shared_edges",
"invalid mesh file");
1027 input >> ident >> num_sface;
1028 MFEM_VERIFY(ident ==
"total_shared_faces",
"invalid mesh file");
1041 int svert_counter = 0, sedge_counter = 0;
1048 input >> ident >> g;
1051 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
1052 <<
", read group " << g << endl;
1058 input >> ident >> nv;
1059 MFEM_VERIFY(ident ==
"shared_vertices",
"invalid mesh file");
1060 nv += svert_counter;
1062 "incorrect number of total_shared_vertices");
1064 for ( ; svert_counter < nv; svert_counter++)
1073 input >> ident >> ne;
1074 MFEM_VERIFY(ident ==
"shared_edges",
"invalid mesh file");
1075 ne += sedge_counter;
1077 "incorrect number of total_shared_edges");
1079 for ( ; sedge_counter < ne; sedge_counter++)
1082 input >> v[0] >> v[1];
1089 input >> ident >> nf;
1090 for (
int i = 0; i < nf; i++)
1099 for (
int ii = 0; ii < 3; ii++) { input >> v[ii]; }
1104 for (
int ii = 0; ii < 4; ii++) { input >> v[ii]; }
1107 MFEM_ABORT(
"invalid shared face geometry: " << geom);
1118 "incorrect number of total_shared_faces");
1153 ref_factors = ref_factor;
1232 for (
int j = 0; j < orig_n_verts; j++)
1239 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1240 if (orig_n_edges > 0)
1245 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1247 for (
int e = 0; e < orig_n_edges; e++)
1252 for (
int j = 2; j < rdofs.
Size(); j++)
1260 for (
int k = 0; k < nvert; k++)
1263 v[k] = rdofs[c2h_map[cid]];
1279 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1281 for (
int f = 0;
f < orig_nt;
f++)
1286 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1295 for (
int k = 0; k < 2; k++)
1297 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1306 for (
int k = 0; k < nvert; k++)
1309 v[k] = rdofs[c2h_map[cid]];
1323 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1325 for (
int f = 0;
f < orig_nq;
f++)
1330 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1339 for (
int k = 0; k < 2; k++)
1341 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1350 for (
int k = 0; k < nvert; k++)
1353 v[k] = rdofs[c2h_map[cid]];
1400 for (
int iv=0; iv<orig_mesh.
GetNV(); ++iv)
1411 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1437 constexpr int ntris = 2, nv_tri = 3, nv_quad = 4;
1440 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1444 for (
int j = 0; j < orig_n_verts; j++)
1451 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1452 for (
int e = 0; e < orig_n_edges; e++)
1464 for (
int e = 0; e < orig_nt; e++)
1471 for (
int iv=0; iv<nv_tri; ++iv) { v2[iv] = v[iv]; }
1478 static const int trimap[12] =
1484 static const int diagmap[4] = { 0, 2, 1, 3 };
1485 for (
int f = 0;
f < orig_nq; ++
f)
1492 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
1493 int iv_min = std::min_element(vg, vg+nv_quad) - vg;
1494 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
1498 v_diag[0] = v[diagmap[0 + isplit*2]];
1499 v_diag[1] = v[diagmap[1 + isplit*2]];
1502 for (
int itri=0; itri<ntris; ++itri)
1506 for (
int iv=0; iv<nv_tri; ++iv)
1508 v2[iv] = v[trimap[itri + isplit*2 + iv*ntris*2]];
1526 const int meshgen_save =
meshgen;
1556 int max_attr = attr.
Size() ? attr.
Max() : 1 ;
1557 int glb_max_attr = -1;
1558 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1562 bool *attr_marker =
new bool[glb_max_attr];
1563 bool *glb_attr_marker =
new bool[glb_max_attr];
1564 for (
int i = 0; i < glb_max_attr; i++)
1566 attr_marker[i] =
false;
1568 for (
int i = 0; i < attr.
Size(); i++)
1570 attr_marker[attr[i] - 1] =
true;
1572 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1573 MPI_C_BOOL, MPI_LOR,
MyComm);
1574 delete [] attr_marker;
1579 for (
int i = 0; i < glb_max_attr; i++)
1581 if (glb_attr_marker[i])
1586 delete [] glb_attr_marker;
1597 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1603 MFEM_WARNING(
"Non-positive element attributes found!");
1610 int maxNumOfBdrElements;
1612 MPI_INT, MPI_MAX,
MyComm);
1613 return (maxNumOfBdrElements > 0);
1621 o = (v[0] < v[1]) ? (+1) : (-1);
1630 "Expecting a triangular face.");
1641 "Expecting a quadrilateral face.");
1651 gr_sedge.
GetI()[0] = 0;
1660 gr_sedge.
GetJ()[k] =k;
1675 gr_svert.
GetI()[0] = 0;
1684 gr_svert.
GetJ()[k] = k;
1699 gr_squad.
GetI()[0] = 0;
1708 gr_squad.
GetJ()[k] = k;
1723 gr_stria.
GetI()[0] = 0;
1732 gr_stria.
GetJ()[k] = k;
1758 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1761 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1763 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1766 if (n == 0) {
continue; }
1768 for (
int j = 0; j < n; j++)
1770 sedge_ord_map[j].one = sedge_ord[k+j];
1771 sedge_ord_map[j].two = j;
1774 for (
int j = 0; j < n; j++)
1777 const int *v =
shared_edges[sedge_from]->GetVertices();
1778 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1780 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1781 for (
int j = 0; j < n; j++)
1785 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1799 ilen_len[j].one = order[j];
1800 ilen_len[j].two =
GetLength(i, it.Column());
1807 for (
int i = 1; i < order.
Size(); i++)
1809 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1823 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1835 elements[i]->MarkEdge(v_to_v, order);
1843 boundary[i]->MarkEdge(v_to_v, order);
1862 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1879 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1880 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1882 if (bit == 8*
sizeof(
unsigned))
1888 const face_t &
f = face_stack.
Last();
1889 int mid = v_to_v.
FindId(
f.one,
f.two);
1899 face_stack.
Append(face_t(
f.three,
f.one, mid));
1900 face_t &r = face_stack[face_stack.
Size()-2];
1901 r = face_t(r.two, r.three, mid);
1913 bool need_refinement = 0;
1914 face_stack.
Append(face_t(v[0], v[1], v[2]));
1915 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1917 if (bit == 8*
sizeof(
unsigned))
1919 code = codes[pos++];
1923 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1925 const face_t &
f = face_stack.
Last();
1926 int mid = v_to_v.
FindId(
f.one,
f.two);
1929 mid = v_to_v.
GetId(
f.one,
f.two);
1930 int ind[2] = {
f.one,
f.two };
1933 need_refinement = 1;
1936 face_stack.
Append(face_t(
f.three,
f.one, mid));
1937 face_t &r = face_stack[face_stack.
Size()-2];
1938 r = face_t(r.two, r.three, mid);
1940 return need_refinement;
1946 if (HYPRE_AssumedPartitionCheck())
1949 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_BIG_INT, MPI_SUM,
MyComm);
1950 for (
int i = 0; i < N; i++)
1953 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1954 (*offsets[i])[1] = temp[i];
1957 for (
int i = 0; i < N; i++)
1959 (*offsets[i])[2] = temp[i];
1961 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1962 "overflow in offsets");
1968 MPI_Allgather(loc_sizes, N, HYPRE_MPI_BIG_INT, temp.
GetData(), N,
1969 HYPRE_MPI_BIG_INT,
MyComm);
1970 for (
int i = 0; i < N; i++)
1975 for (
int j = 0; j <
NRanks; j++)
1977 offs[j+1] = offs[j] + temp[i+N*j];
1981 "overflow in offsets");
2010 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
2057 *new_nodes = *
Nodes;
2088 bool del_tables =
false;
2115 gr_sface =
new Table;
2150 if (del_tables) {
delete gr_sface; }
2161 int num_face_nbrs = 0;
2164 if (gr_sface->
RowSize(g-1) > 0)
2172 if (num_face_nbrs == 0)
2182 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
2184 if (gr_sface->
RowSize(g-1) > 0)
2189 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
2191 rank_group[counter].two = g;
2198 for (
int fn = 0; fn < num_face_nbrs; fn++)
2204 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2205 MPI_Request *send_requests = requests;
2206 MPI_Request *recv_requests = requests + num_face_nbrs;
2207 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2209 int *nbr_data =
new int[6*num_face_nbrs];
2210 int *nbr_send_data = nbr_data;
2211 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
2220 Table send_face_nbr_elemdata, send_face_nbr_facedata;
2224 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
2225 send_face_nbr_facedata.
MakeI(num_face_nbrs);
2226 for (
int fn = 0; fn < num_face_nbrs; fn++)
2229 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2230 int *sface = gr_sface->
GetRow(nbr_group-1);
2231 for (
int i = 0; i < num_sfaces; i++)
2233 int lface = s2l_face[sface[i]];
2235 if (el_marker[el] != fn)
2240 const int nv =
elements[el]->GetNVertices();
2241 const int *v =
elements[el]->GetVertices();
2242 for (
int j = 0; j < nv; j++)
2243 if (vertex_marker[v[j]] != fn)
2245 vertex_marker[v[j]] = fn;
2249 const int nf =
elements[el]->GetNFaces();
2258 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
2263 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2264 &send_requests[fn]);
2265 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2266 &recv_requests[fn]);
2270 send_face_nbr_elemdata.
MakeJ();
2271 send_face_nbr_facedata.
MakeJ();
2275 for (
int fn = 0; fn < num_face_nbrs; fn++)
2278 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2279 int *sface = gr_sface->
GetRow(nbr_group-1);
2280 for (
int i = 0; i < num_sfaces; i++)
2282 const int sf = sface[i];
2283 int lface = s2l_face[sf];
2285 if (el_marker[el] != fn)
2290 const int nv =
elements[el]->GetNVertices();
2291 const int *v =
elements[el]->GetVertices();
2292 for (
int j = 0; j < nv; j++)
2293 if (vertex_marker[v[j]] != fn)
2295 vertex_marker[v[j]] = fn;
2306 const int nf =
elements[el]->GetNFaces();
2317 const int *lf_v =
faces[lface]->GetVertices();
2337 for (
int fn = 0; fn < num_face_nbrs; fn++)
2343 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
2344 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
2345 int *facedata = send_face_nbr_facedata.
GetRow(fn);
2347 for (
int i = 0; i < num_verts; i++)
2349 vertex_marker[verts[i]] = i;
2352 for (
int el = 0; el < num_elems; el++)
2354 const int nv =
elements[elems[el]]->GetNVertices();
2357 for (
int j = 0; j < nv; j++)
2359 elemdata[j] = vertex_marker[elemdata[j]];
2361 elemdata += nv + nf;
2363 el_marker[elems[el]] = el;
2366 for (
int i = 0; i < num_sfaces; i++)
2368 facedata[2*i] = el_marker[facedata[2*i]];
2372 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2375 Table recv_face_nbr_elemdata;
2380 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2383 for (
int fn = 0; fn < num_face_nbrs; fn++)
2391 recv_face_nbr_elemdata.
MakeJ();
2393 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2396 for (
int fn = 0; fn < num_face_nbrs; fn++)
2401 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2402 send_face_nbr_elemdata.
RowSize(fn),
2403 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2405 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2406 recv_face_nbr_elemdata.
RowSize(fn),
2407 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2416 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2418 if (fn == MPI_UNDEFINED)
2426 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2428 for (
int i = 0; i < num_elems; i++)
2434 for (
int j = 0; j < nv; j++)
2436 recv_elemdata[j] += vert_off;
2439 recv_elemdata += nv;
2444 for (
int j = 0; j < nf; j++)
2446 fn_ori[j] = recv_elemdata[j];
2448 recv_elemdata += nf;
2455 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2458 recv_face_nbr_facedata.
SetSize(
2460 for (
int fn = 0; fn < num_face_nbrs; fn++)
2465 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2466 send_face_nbr_facedata.
RowSize(fn),
2467 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2470 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2471 send_face_nbr_facedata.
RowSize(fn),
2472 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2479 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2481 if (fn == MPI_UNDEFINED)
2488 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2489 int *sface = gr_sface->
GetRow(nbr_group-1);
2491 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2493 for (
int i = 0; i < num_sfaces; i++)
2495 const int sf = sface[i];
2496 int lface = s2l_face[sf];
2498 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2499 int info = facedata[2*i+1];
2507 int nbr_ori = info%64, nbr_v[4];
2508 const int *lf_v =
faces[lface]->GetVertices();
2515 for (
int j = 0; j < 3; j++)
2517 nbr_v[perm[j]] = sf_v[j];
2527 for (
int j = 0; j < 4; j++)
2529 nbr_v[perm[j]] = sf_v[j];
2535 info = 64*(info/64) + nbr_ori;
2541 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2558 else if (
Nodes == NULL)
2568 if (!num_face_nbrs) {
return; }
2570 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2571 MPI_Request *send_requests = requests;
2572 MPI_Request *recv_requests = requests + num_face_nbrs;
2573 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2577 for (
int i = 0; i < send_vertices.
Size(); i++)
2583 for (
int fn = 0; fn < num_face_nbrs; fn++)
2598 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2599 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2607 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2622 for (
int j = 0; j < 4; j++)
2625 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2631 for (
int j = 0; j < 2; j++)
2634 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2636 for (
int j = 2; j < 5; j++)
2639 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2645 for (
int j = 0; j < 1; j++)
2648 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2650 for (
int j = 1; j < 5; j++)
2653 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2661 for (
int j = 0; j < 6; j++)
2664 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2669 MFEM_ABORT(
"Unexpected type of Element.");
2678 const std::unique_ptr<STable3D> &faces,
2679 const std::unique_ptr<STable3D> &shared_faces,
2680 int elem,
int start,
int end,
const int fverts[][N])
2682 for (
int i = start; i < end; ++i)
2685 const auto fv = fverts[i];
2687 const Vert3 elem_fv(elem_vertices[fv[0]], elem_vertices[fv[1]],
2688 elem_vertices[fv[2]]);
2691 const int lf =
faces->Index(elem_fv.
v[0], elem_fv.
v[1], elem_fv.
v[2]);
2695 const int sf = lf < 0 ? shared_faces->Index(elem_fv.
v[0], elem_fv.
v[1],
2700 const int face_to_add = lf < 0 ? (sf >= 0 ? sf +
NumOfFaces : -1) : lf;
2702 MFEM_ASSERT(sf >= 0 ||
2703 lf >= 0,
"Face must be from a local or a face neighbor element");
2720 auto add_quad_faces = [&
faces, &shared_faces, &v,
this]
2721 (
int elem,
int start,
int end,
const int fverts[][4])
2723 for (
int i = start; i < end; ++i)
2725 const int *
const fv = fverts[i];
2729 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2730 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2731 if (max < v[fv[3]]) { k = 3; }
2733 int v0 = -1, v1 = -1, v2 = -1;
2737 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2740 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2743 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2746 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2749 int lf =
faces->Index(v0, v1, v2);
2752 lf = shared_faces->Index(v0, v1, v2);
2790 MFEM_ABORT(
"Unexpected type of Element.");
2802 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2817 int el_nbr = i -
GetNE();
2824 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2825 "face_nbr_el_to_face not generated correctly.");
2834 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2835 "face_nbr_el_ori not generated correctly.");
2870 for (
int i = 0; i < s2l_face->
Size(); i++)
2885 for (
int i = 0; i < s2l_face->
Size(); i++)
2887 int lface = (*s2l_face)[i];
2888 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2917 const bool fill2 = mask & 10;
2955 MFEM_VERIFY(face_info.
Elem2Inf >= 0,
"The face must be shared.");
2973 FElTr.
Elem1 = &ElTr1;
2980 Elem2NbrNo = -1 - face_info.
Elem2No;
2987 FElTr.
Elem2 = &ElTr2;
3024 if (is_ghost || fill2)
3047 mfem::out <<
"\nInternal error: face id = " << FaceNo
3048 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
3050 MFEM_ABORT(
"internal error");
3073 "Mesh requires nodal Finite Element.");
3084 FElTr.
SetFE(face_el);
3114 for (
int j = 0; j < nv; j++)
3133 for (
int j = 0; j < n; j++)
3135 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
3143 MFEM_ABORT(
"Nodes are not ParGridFunction!");
3166 MFEM_ASSERT(
Dim > 1,
"");
3185 MFEM_ASSERT(
Dim > 1,
"");
3188 return sface < csize
3190 : shared.
slaves[sface - csize].index;
3203void Rotate3Indirect(
int &
a,
int &
b,
int &c,
3206 if (order[
a] < order[
b])
3208 if (order[
a] > order[c])
3215 if (order[
b] < order[c])
3236 Table *old_elem_vert = NULL;
3259 svert_comm.
Bcast(svert_master_index);
3272 for (
int i = 0; i <
vertices.Size(); i++)
3274 int s = lvert_svert[i];
3277 glob_vert_order[i] =
3278 (std::int64_t(svert_master_rank[
s]) << 32) + svert_master_index[
s];
3282 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
3294 int *v =
elements[i]->GetVertices();
3296 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3298 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
3300 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
3314 int *v =
boundary[i]->GetVertices();
3316 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3320 const bool check_consistency =
true;
3321 if (check_consistency)
3328 for (
int i = 0; i < stria_flag.
Size(); i++)
3331 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
3333 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
3337 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
3342 stria_comm.
Bcast(stria_master_flag);
3343 for (
int i = 0; i < stria_flag.
Size(); i++)
3346 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
3347 "inconsistent vertex ordering found, shared triangle "
3349 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
3350 <<
"local flag: " << stria_flag[i]
3351 <<
", master flag: " << stria_master_flag[i]);
3360 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3376 delete old_elem_vert;
3389 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3398 int uniform_refinement = 0;
3402 uniform_refinement = 1;
3413 for (
int i = 0; i < marked_el.
Size(); i++)
3419 for (
int i = 0; i < marked_el.
Size(); i++)
3428 for (
int i = 0; i < marked_el.
Size(); i++)
3445 int need_refinement;
3446 int max_faces_in_group = 0;
3452 face_splittings[i].
Reserve(faces_in_group);
3453 if (faces_in_group > max_faces_in_group)
3455 max_faces_in_group = faces_in_group;
3461 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3464#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3465 int ref_loops_all = 0, ref_loops_par = 0;
3469 need_refinement = 0;
3472 if (
elements[i]->NeedRefinement(v_to_v))
3474 need_refinement = 1;
3478#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3482 if (uniform_refinement)
3489 if (need_refinement == 0)
3491#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3495 const int tag = 293;
3504 if (faces_in_group == 0) {
continue; }
3506 face_splittings[i].
SetSize(0);
3507 for (
int j = 0; j < faces_in_group; j++)
3510 face_splittings[i]);
3514 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3515 MPI_UNSIGNED, neighbor, tag,
MyComm,
3516 &requests[req_count++]);
3524 if (faces_in_group == 0) {
continue; }
3528 MPI_Probe(neighbor, tag,
MyComm, &status);
3530 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3532 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3535 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3542 int nr = need_refinement;
3543 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3545 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3548 while (need_refinement == 1);
3550#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3552 int i = ref_loops_all;
3553 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3556 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3557 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3565 delete [] face_splittings;
3570 need_refinement = 0;
3573 if (
boundary[i]->NeedRefinement(v_to_v))
3575 need_refinement = 1;
3580 while (need_refinement == 1);
3585 " (NumOfBdrElements != boundary.Size())");
3612 int uniform_refinement = 0;
3616 uniform_refinement = 1;
3625 int *edge1 =
new int[nedges];
3626 int *edge2 =
new int[nedges];
3627 int *middle =
new int[nedges];
3629 for (
int i = 0; i < nedges; i++)
3631 edge1[i] = edge2[i] = middle[i] = -1;
3636 int *v =
elements[i]->GetVertices();
3637 for (
int j = 0; j < 3; j++)
3639 int ind = v_to_v(v[j], v[(j+1)%3]);
3640 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3645 for (
int i = 0; i < marked_el.
Size(); i++)
3651 int need_refinement;
3652 int edges_in_group, max_edges_in_group = 0;
3654 int **edge_splittings =
new int*[
GetNGroups()-1];
3658 edge_splittings[i] =
new int[edges_in_group];
3659 if (edges_in_group > max_edges_in_group)
3661 max_edges_in_group = edges_in_group;
3664 int neighbor, *iBuf =
new int[max_edges_in_group];
3668 MPI_Request request;
3673#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3674 int ref_loops_all = 0, ref_loops_par = 0;
3678 need_refinement = 0;
3679 for (
int i = 0; i < nedges; i++)
3681 if (middle[i] != -1 && edge1[i] != -1)
3683 need_refinement = 1;
3687#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3691 if (uniform_refinement)
3698 if (need_refinement == 0)
3700#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3709 edges_in_group = group_edges.
Size();
3711 if (edges_in_group != 0)
3713 for (
int j = 0; j < edges_in_group; j++)
3715 edge_splittings[i][j] =
3728 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3729 neighbor, 0,
MyComm, &request);
3737 edges_in_group = group_edges.
Size();
3738 if (edges_in_group != 0)
3749 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3750 MPI_ANY_TAG,
MyComm, &status);
3752 for (
int j = 0; j < edges_in_group; j++)
3754 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3757 int ii = v_to_v(v[0], v[1]);
3758#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3759 if (middle[ii] != -1)
3761 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3765 need_refinement = 1;
3767 for (
int c = 0; c < 2; c++)
3777 int nr = need_refinement;
3778 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3781 while (need_refinement == 1);
3783#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3785 int i = ref_loops_all;
3786 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3789 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3790 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3798 delete [] edge_splittings[i];
3800 delete [] edge_splittings;
3805 int v1[2], v2[2], bisect, temp;
3807 for (
int i = 0; i < temp; i++)
3809 int *v =
boundary[i]->GetVertices();
3810 bisect = v_to_v(v[0], v[1]);
3811 if (middle[bisect] != -1)
3816 v1[0] = v[0]; v1[1] = middle[bisect];
3817 v2[0] = middle[bisect]; v2[1] = v[1];
3824 mfem_error(
"Only bisection of segment is implemented for bdr"
3857 for (
int j = 0; j < marked_el.
Size(); j++)
3859 int i = marked_el[j];
3862 int new_v = cnv + j, new_e = cne + j;
3871 static real_t seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3873 UseExternalData(seg_children, 1, 2, 3);
3894 MFEM_ABORT(
"NURBS meshes are not supported. Please project the "
3895 "NURBS to Nodes first with SetCurvature().");
3900 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3901 "(you need to initialize the ParMesh from a nonconforming "
3948 real_t threshold,
int nc_limit,
int op)
3950 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3951 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3952 "Project the NURBS to Nodes first.");
3965 for (
int i = 0; i < dt.
Size(); i++)
3967 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3972 if (error < threshold) { derefs.
Append(i); }
3976 if (!glob_size) {
return false; }
4023 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
4031 != NULL,
"internal error");
4065 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
4075 int *I_group_svert, *J_group_svert;
4076 int *I_group_sedge, *J_group_sedge;
4081 I_group_svert[0] = I_group_svert[1] = 0;
4082 I_group_sedge[0] = I_group_sedge[1] = 0;
4089 for (
int group = 0; group <
GetNGroups()-1; group++)
4099 const int ind = middle[v_to_v(v[0], v[1])];
4105 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4112 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4113 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4116 J = J_group_svert+I_group_svert[group];
4117 for (
int i = 0; i < group_verts.
Size(); i++)
4119 J[i] = group_verts[i];
4121 J = J_group_sedge+I_group_sedge[group];
4122 for (
int i = 0; i < group_edges.
Size(); i++)
4124 J[i] = group_edges[i];
4138 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
4140 Array<int> group_verts, group_edges, group_trias;
4159 I_group_svert[0] = 0;
4160 I_group_sedge[0] = 0;
4161 I_group_stria[0] = 0;
4163 for (
int group = 0; group <
GetNGroups()-1; group++)
4174 int ind = v_to_v.
FindId(v[0], v[1]);
4175 if (ind == -1) {
continue; }
4178 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4188 ind = v_to_v.
FindId(v[0], ind);
4196 ind = v_to_v.
FindId(v[0], v[1]);
4217 while (sedge_stack.
Size() > 0);
4224 int ind = v_to_v.
FindId(v[0], v[1]);
4225 if (ind == -1) {
continue; }
4228 const int edge_attr = 1;
4237 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
4238 ind = v_to_v.
FindId(v[0], v[1]);
4246 ind = v_to_v.
FindId(v[0], v[1]);
4264 v = sface_stack[sface_stack.
Size()-2].v;
4266 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
4269 while (sface_stack.
Size() > 0);
4275 ind = v_to_v.
FindId(v[0], v[1]);
4296 while (sedge_stack.
Size() > 0);
4299 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4300 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4301 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4303 J_group_svert.
Append(group_verts);
4304 J_group_sedge.
Append(group_edges);
4305 J_group_stria.
Append(group_trias);
4322 int *I_group_svert, *J_group_svert;
4323 int *I_group_sedge, *J_group_sedge;
4328 I_group_svert[0] = 0;
4329 I_group_sedge[0] = 0;
4336 for (
int group = 0; group <
GetNGroups()-1; group++)
4350 const int attr =
shared_edges[sedges[i]]->GetAttribute();
4356 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
4357 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
4359 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
4360 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4376 Array<int> group_verts, group_edges, group_trias, group_quads;
4378 int *I_group_svert, *J_group_svert;
4379 int *I_group_sedge, *J_group_sedge;
4380 int *I_group_stria, *J_group_stria;
4381 int *I_group_squad, *J_group_squad;
4388 I_group_svert[0] = 0;
4389 I_group_sedge[0] = 0;
4390 I_group_stria[0] = 0;
4391 I_group_squad[0] = 0;
4403 const int oface = old_nv + old_nedges;
4405 for (
int group = 0; group <
GetNGroups()-1; group++)
4417 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4421 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4431 const int stria = group_trias[i];
4434 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4435 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4436 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4437 const int edge_attr = 1;
4452 v[1] = m[0]; v[2] = m[2];
4453 group_trias.
Append(nst+0);
4454 group_trias.
Append(nst+1);
4455 group_trias.
Append(nst+2);
4463 const int squad = group_quads[i];
4465 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4467 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4471 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4472 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4473 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4474 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4475 const int edge_attr = 1;
4492 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4493 group_quads.
Append(nsq+0);
4494 group_quads.
Append(nsq+1);
4495 group_quads.
Append(nsq+2);
4499 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4500 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4501 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4502 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4504 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4505 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4506 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4507 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4526 const bool update_nodes =
false;
4551 auto faces_tbl = std::unique_ptr<STable3D>(
GetFacesTable());
4556 const bool update_nodes =
false;
4565 f2qf.
Size() ? &f2qf : NULL);
4574 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4582 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4588 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4594 os <<
"NETGEN_Neutral_Format\n";
4599 for (j = 0; j <
Dim; j++)
4613 for (j = 0; j < nv; j++)
4615 os <<
" " << ind[j]+1;
4628 for (j = 0; j < nv; j++)
4630 os <<
" " << ind[j]+1;
4641 for (j = 0; j < 3; j++)
4643 os <<
' ' << ind[j]+1;
4657 <<
" 0 0 0 0 0 0 0\n"
4658 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4660 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4661 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4662 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4668 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4676 os << i+1 <<
" " <<
elements[i]->GetAttribute();
4677 for (j = 0; j < nv; j++)
4679 os <<
" " << ind[j]+1;
4690 for (j = 0; j < nv; j++)
4692 os <<
" " << ind[j]+1;
4694 os <<
" 1.0 1.0 1.0 1.0\n";
4705 for (j = 0; j < 4; j++)
4707 os <<
' ' << ind[j]+1;
4709 os <<
" 1.0 1.0 1.0 1.0\n";
4718 os <<
"areamesh2\n\n";
4725 attr =
boundary[i]->GetAttribute();
4728 for (j = 0; j < v.
Size(); j++)
4730 os << v[j] + 1 <<
" ";
4740 for (j = 0; j < v.
Size(); j++)
4742 os << v[j] + 1 <<
" ";
4751 attr =
elements[i]->GetAttribute();
4767 for (j = 0; j < v.
Size(); j++)
4769 os << v[j] + 1 <<
" ";
4778 for (j = 0; j <
Dim; j++)
4803 int shared_bdr_attr;
4820 s2l_face = &nc_shared_faces;
4827 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4832 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4838 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4849 os << (!set_names ?
"MFEM mesh v1.0\n" :
"MFEM mesh v1.3\n");
4851 if (!comments.empty()) { os <<
'\n' << comments <<
'\n'; }
4855 "\n#\n# MFEM Geometry Types (see fem/geom.hpp):\n#\n"
4860 "# TETRAHEDRON = 4\n"
4865 os <<
"\ndimension\n" <<
Dim
4874 os <<
"\nattribute_sets\n";
4881 num_bdr_elems += s2l_face->
Size();
4883 os <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4897 shared_bdr_attr =
MyRank + 1;
4899 for (
int i = 0; i < s2l_face->
Size(); i++)
4902 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4909 os <<
"\nbdr_attribute_sets\n";
4936 os <<
"\nmfem_mesh_end" << endl;
4942 ostringstream fname_with_suffix;
4943 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
4944 ofstream ofs(fname_with_suffix.str().c_str());
4945 ofs.precision(precision);
4949#ifdef MFEM_USE_ADIOS2
4962 for (
int i = 0; i < nv; i++)
4970 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4978 os <<
"MFEM mesh v1.0\n";
4980 if (!comments.empty()) { os <<
'\n' << comments <<
'\n'; }
4984 "\n#\n# MFEM Geometry Types (see fem/geom.hpp):\n#\n"
4989 "# TETRAHEDRON = 4\n"
4994 os <<
"\ndimension\n" <<
Dim;
4998 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5001 os <<
"\n\nelements\n" << ne <<
'\n';
5005 os << 1 <<
' ' <<
elements[i]->GetGeometryType();
5009 for (j = 0; j < nv; j++)
5018 MPI_Recv(nv_ne, 2, MPI_INT,
p, 444,
MyComm, &status);
5022 MPI_Recv(&ints[0], ne, MPI_INT,
p, 445,
MyComm, &status);
5024 for (i = 0; i < ne; )
5027 os <<
p+1 <<
' ' << ints[i];
5030 for (j = 0; j < k; j++)
5032 os <<
' ' << vc + ints[i++];
5045 ne += 1 +
elements[i]->GetNVertices();
5048 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
5056 MFEM_ASSERT(ints.
Size() == ne,
"");
5059 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
5072 ne += list.
conforming.Size() + list.masters.Size() + list.slaves.Size();
5084 dump_element(
boundary[i], ints); ne++;
5122 MFEM_ABORT(
"invalid dimension: " <<
Dim);
5129 for (i = 0; i < list.conforming.Size(); i++)
5131 int index = list.conforming[i].index;
5134 for (i = 0; i < list.masters.Size(); i++)
5136 int index = list.masters[i].index;
5139 for (i = 0; i < list.slaves.Size(); i++)
5141 int index = list.slaves[i].index;
5146 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5149 os <<
"\nboundary\n" << k <<
'\n';
5155 MPI_Recv(nv_ne, 2, MPI_INT,
p, 446,
MyComm, &status);
5167 for (i = 0; i < ne; )
5170 os <<
p+1 <<
' ' << ints[i];
5173 for (j = 0; j < k; j++)
5175 os <<
' ' << vc + ints[i++];
5186 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
5197 os <<
"\nvertices\n" << nv <<
'\n';
5215 MPI_Recv(&nv, 1, MPI_INT,
p, 448,
MyComm, &status);
5222 for (i = 0; i < nv; i++)
5275 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
5287 serialmesh.
Printer(os,
"", comments);
5296 MFEM_ABORT(
"Nonconforming meshes and NURBS meshes are not yet supported.");
5305 MFEM_VERIFY(
int(ne_glob_l) == ne_glob_l,
5306 "overflow in the number of elements!");
5307 int ne_glob = (save_rank ==
MyRank) ?
int(ne_glob_l) : 0;
5310 long long nvertices_glob_l = 0;
5311 MPI_Reduce(&nvertices, &nvertices_glob_l, 1, MPI_LONG_LONG, MPI_SUM,
5313 int nvertices_glob = int(nvertices_glob_l);
5314 MFEM_VERIFY(nvertices_glob == nvertices_glob_l,
5315 "overflow in the number of vertices!");
5318 long long nbe_glob_l = 0;
5319 MPI_Reduce(&nbe, &nbe_glob_l, 1, MPI_LONG_LONG, MPI_SUM, save_rank,
MyComm);
5320 int nbe_glob = int(nbe_glob_l);
5321 MFEM_VERIFY(nbe_glob == nbe_glob_l,
5322 "overflow in the number of boundary elements!");
5339 const int attr =
elements[e]->GetAttribute();
5340 const int geom_type =
elements[e]->GetGeometryType();
5342 for (
int j = 0; j < dofs.
Size(); j++)
5354 if (
p == save_rank) {
continue; }
5355 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 444,
MyComm, &status);
5359 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 445,
MyComm, &status);
5361 for (
int i = 0; i < n_send_recv; )
5363 int attr = ints[i++];
5364 int geom_type = ints[i++];
5377 n_send_recv += 2 +
elements[e]->GetNVertices();
5379 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 444,
MyComm);
5384 const int attr =
elements[e]->GetAttribute();
5385 const int geom_type =
elements[e]->GetGeometryType();
5389 for (
int j = 0; j < dofs.
Size(); j++)
5396 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 445,
MyComm);
5405 const int attr =
boundary[e]->GetAttribute();
5406 const int geom_type =
boundary[e]->GetGeometryType();
5408 for (
int j = 0; j < dofs.
Size(); j++)
5420 if (
p == save_rank) {
continue; }
5421 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 446,
MyComm, &status);
5425 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 447,
MyComm, &status);
5427 for (
int i = 0; i < n_send_recv; )
5429 int attr = ints[i++];
5430 int geom_type = ints[i++];
5445 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 446,
MyComm);
5450 const int attr =
boundary[e]->GetAttribute();
5451 const int geom_type =
boundary[e]->GetGeometryType();
5455 for (
int j = 0; j < dofs.
Size(); j++)
5462 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 447,
MyComm);
5468 for (
int v = 0; v < nvertices_glob; v++)
5489 serialmesh.
GetNodes()->MakeOwner(fec_serial);
5505 serialmesh.
GetNodes()->SetSubVector(dofs, nodeloc);
5511 for (
int i = 0; i < ints.
Size(); i++)
5517 vdata_serial[d] = vdata[d];
5525 if (
p == save_rank) {
continue; }
5526 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 448,
MyComm, &status);
5533 for (
int i = 0; i < n_send_recv; )
5538 serialmesh.
GetNodes()->SetSubVector(dofs, &vert[i]);
5544 for (
int j = 0; j < ints_serial.
Size(); j++)
5549 vdata_serial[d] = vert[i++];
5572 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448,
MyComm);
5580 for (
int j = 0; j < nodeloc.
Size(); j++)
5588 for (
int i = 0; i < ints.
Size(); i++)
5615 ofs.precision(precision);
5622 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
5625 int i, j, k, nv, ne,
p;
5633 os <<
"NETGEN_Neutral_Format\n";
5636 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5640 for (j = 0; j <
Dim; j++)
5648 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5652 for (i = 0; i < nv; i++)
5654 for (j = 0; j <
Dim; j++)
5656 os <<
" " << vert[
Dim*i+j];
5664 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5671 for (j = 0; j < nv; j++)
5673 os <<
" " << ind[j]+1;
5680 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5681 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5683 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5684 for (i = 0; i < ne; i++)
5687 for (j = 0; j < 4; j++)
5689 os <<
" " << k+ints[i*4+j]+1;
5697 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5705 for (j = 0; j < nv; j++)
5707 os <<
" " << ind[j]+1;
5718 for (j = 0; j < 3; j++)
5720 os <<
' ' << ind[j]+1;
5728 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5729 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5731 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
5732 for (i = 0; i < ne; i++)
5735 for (j = 0; j < 3; j++)
5737 os <<
' ' << k+ints[i*3+j]+1;
5747 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5751 for (j = 0; j <
Dim; j++)
5759 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5766 for (j = 0; j < 4; j++)
5774 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5777 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5782 for (j = 0; j < 3; j++)
5787 for ( ; i < ne; i++)
5790 for (j = 0; j < 3; j++)
5795 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
5801 int i, j, k, nv, ne,
p;
5807 int TG_nv, TG_ne, TG_nbe;
5814 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5817 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
5818 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
5819 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
5820 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
5821 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
5828 <<
" " <<
vertices[i](2) <<
" 0.0\n";
5832 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5836 for (i = 0; i < nv; i++)
5838 os << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
5839 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
5849 os << i+1 <<
" " << 1;
5850 for (j = 0; j < nv; j++)
5852 os <<
" " << ind[j]+1;
5859 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5860 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5862 MPI_Recv(&ints[0], 8*ne, MPI_INT,
p, 447,
MyComm, &status);
5863 for (i = 0; i < ne; i++)
5865 os << i+1 <<
" " <<
p+1;
5866 for (j = 0; j < 8; j++)
5868 os <<
" " << k+ints[i*8+j]+1;
5883 for (j = 0; j < nv; j++)
5885 os <<
" " << ind[j]+1;
5887 os <<
" 1.0 1.0 1.0 1.0\n";
5897 for (j = 0; j < 4; j++)
5899 os <<
' ' << ind[j]+1;
5901 os <<
" 1.0 1.0 1.0 1.0\n";
5906 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5907 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5909 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5910 for (i = 0; i < ne; i++)
5913 for (j = 0; j < 4; j++)
5915 os <<
" " << k+ints[i*4+j]+1;
5917 os <<
" 1.0 1.0 1.0 1.0\n";
5927 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5932 for (j = 0; j <
Dim; j++)
5945 for (j = 0; j < 8; j++)
5954 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5959 for (j = 0; j < 4; j++)
5964 for ( ; i < ne; i++)
5967 for (j = 0; j < 4; j++)
5972 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
5978 int i, j, k, attr, nv, ne,
p;
5986 os <<
"areamesh2\n\n";
5990 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5995 attr =
boundary[i]->GetAttribute();
5998 for (j = 0; j < v.
Size(); j++)
6000 os << v[j] + 1 <<
" ";
6010 for (j = 0; j < v.
Size(); j++)
6012 os << v[j] + 1 <<
" ";
6019 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6020 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6022 MPI_Recv(&ints[0], 2*ne, MPI_INT,
p, 447,
MyComm, &status);
6023 for (i = 0; i < ne; i++)
6026 for (j = 0; j < 2; j++)
6028 os <<
" " << k+ints[i*2+j]+1;
6037 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6043 os << 1 <<
" " << 3 <<
" ";
6044 for (j = 0; j < v.
Size(); j++)
6046 os << v[j] + 1 <<
" ";
6053 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6054 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6056 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
6057 for (i = 0; i < ne; i++)
6059 os <<
p+1 <<
" " << 3;
6060 for (j = 0; j < 3; j++)
6062 os <<
" " << k+ints[i*3+j]+1;
6071 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6075 for (j = 0; j <
Dim; j++)
6083 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6087 for (i = 0; i < nv; i++)
6089 for (j = 0; j <
Dim; j++)
6091 os <<
" " << vert[
Dim*i+j];
6101 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6104 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6109 for (j = 0; j < 2; j++)
6114 for ( ; i < ne; i++)
6117 for (j = 0; j < 2; j++)
6122 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
6125 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6132 for (j = 0; j < 3; j++)
6140 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6144 for (j = 0; j <
Dim; j++)
6177 real_t h_min, h_max, kappa_min, kappa_max;
6195 real_t h_min, h_max, kappa_min, kappa_max, h,
kappa;
6199 os <<
"Parallel Mesh Stats:" <<
'\n';
6211 kappa_min = kappa_max =
kappa;
6215 if (h < h_min) { h_min = h; }
6216 if (h > h_max) { h_max = h; }
6217 if (
kappa < kappa_min) { kappa_min =
kappa; }
6218 if (
kappa > kappa_max) { kappa_max =
kappa; }
6222 real_t gh_min, gh_max, gk_min, gk_max;
6235 long long mindata[5], maxdata[5], sumdata[5];
6254 MPI_Reduce(ldata, mindata, 5, MPI_LONG_LONG, MPI_MIN, 0,
MyComm);
6255 MPI_Reduce(ldata, sumdata, 5, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
6256 MPI_Reduce(ldata, maxdata, 5, MPI_LONG_LONG, MPI_MAX, 0,
MyComm);
6262 << setw(12) <<
"minimum"
6263 << setw(12) <<
"average"
6264 << setw(12) <<
"maximum"
6265 << setw(12) <<
"total" <<
'\n';
6267 << setw(12) << mindata[0]
6268 << setw(12) << sumdata[0]/
NRanks
6269 << setw(12) << maxdata[0]
6270 << setw(12) << sumdata[0] <<
'\n';
6272 << setw(12) << mindata[1]
6273 << setw(12) << sumdata[1]/
NRanks
6274 << setw(12) << maxdata[1]
6275 << setw(12) << sumdata[1] <<
'\n';
6279 << setw(12) << mindata[2]
6280 << setw(12) << sumdata[2]/
NRanks
6281 << setw(12) << maxdata[2]
6282 << setw(12) << sumdata[2] <<
'\n';
6285 << setw(12) << mindata[3]
6286 << setw(12) << sumdata[3]/
NRanks
6287 << setw(12) << maxdata[3]
6288 << setw(12) << sumdata[3] <<
'\n';
6290 << setw(12) << mindata[4]
6291 << setw(12) << sumdata[4]/
NRanks
6292 << setw(12) << maxdata[4] <<
'\n';
6295 << setw(12) <<
"minimum"
6296 << setw(12) <<
"maximum" <<
'\n';
6298 << setw(12) << gh_min
6299 << setw(12) << gh_max <<
'\n';
6301 << setw(12) << gk_min
6302 << setw(12) << gk_max <<
'\n';
6309 long long local = value, global;
6310 MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM,
MyComm);
6319 Print(os, comments);
6333 Printer(os,
"mfem_serial_mesh_end", comments);
6341 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6347 os <<
"\n# group 0 has no shared entities\n";
6353 os <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
6354 for (
int i = 0; i < nv; i++)
6363 os <<
"\nshared_edges " << ne <<
'\n';
6364 for (
int i = 0; i < ne; i++)
6367 os << v[0] <<
' ' << v[1] <<
'\n';
6376 os <<
"\nshared_faces " << nt+nq <<
'\n';
6377 for (
int i = 0; i < nt; i++)
6381 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6384 for (
int i = 0; i < nq; i++)
6388 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6395 os <<
"\nmfem_mesh_end" << endl;
6400 bool high_order_output,
6401 int compression_level,
6404 int pad_digits_rank = 6;
6407 std::string::size_type pos = pathname.find_last_of(
'/');
6409 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
6413 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
6414 std::ofstream os(pvtu_name);
6417 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
6419 os <<
"<?xml version=\"1.0\"?>\n";
6420 os <<
"<VTKFile type=\"PUnstructuredGrid\"";
6421 os <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
6422 os <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
6424 os <<
"<PPoints>\n";
6425 os <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
6426 os <<
" Name=\"Points\" NumberOfComponents=\"3\""
6427 <<
" format=\"" << data_format <<
"\"/>\n";
6428 os <<
"</PPoints>\n";
6431 os <<
"\t<PDataArray type=\"Int32\" ";
6432 os <<
" Name=\"connectivity\" NumberOfComponents=\"1\""
6433 <<
" format=\"" << data_format <<
"\"/>\n";
6434 os <<
"\t<PDataArray type=\"Int32\" ";
6435 os <<
" Name=\"offsets\" NumberOfComponents=\"1\""
6436 <<
" format=\"" << data_format <<
"\"/>\n";
6437 os <<
"\t<PDataArray type=\"UInt8\" ";
6438 os <<
" Name=\"types\" NumberOfComponents=\"1\""
6439 <<
" format=\"" << data_format <<
"\"/>\n";
6440 os <<
"</PCells>\n";
6442 os <<
"<PCellData>\n";
6443 os <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute"
6444 <<
"\" NumberOfComponents=\"1\""
6445 <<
" format=\"" << data_format <<
"\"/>\n";
6446 os <<
"</PCellData>\n";
6448 for (
int ii=0; ii<
NRanks; ii++)
6450 std::string piece = fname +
".proc"
6452 os <<
"<Piece Source=\"" << piece <<
"\"/>\n";
6455 os <<
"</PUnstructuredGrid>\n";
6456 os <<
"</VTKFile>\n";
6460 std::string vtu_fname = pathname +
"/" + fname +
".proc"
6462 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
6469 const int npts = point_mat.
Width();
6470 if (npts == 0) {
return 0; }
6472 const bool no_warn =
false;
6479 Array<int> my_point_rank(npts), glob_point_rank(npts);
6480 for (
int k = 0; k < npts; k++)
6482 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
6485 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
6486 MPI_INT, MPI_MIN,
MyComm);
6489 for (
int k = 0; k < npts; k++)
6491 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
6495 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
6498 if (warn && pts_found != npts &&
MyRank == 0)
6500 MFEM_WARNING((npts-pts_found) <<
" points were not found");
6505static void PrintVertex(
const Vertex &v,
int space_dim, ostream &os)
6508 for (
int d = 1; d < space_dim; d++)
6516 stringstream out_name;
6517 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
6518 <<
".shared_entities";
6519 ofstream os(out_name.str().c_str());
6527 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6538 os <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
6539 for (
int i = 0; i < nv; i++)
6551 os <<
"\nshared_edges " << ne <<
'\n';
6552 for (
int i = 0; i < ne; i++)
6568 os <<
"\nshared_faces " << nt+nq <<
'\n';
6569 for (
int i = 0; i < nt; i++)
6574 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6577 for (
int j = 0; j < 3; j++)
6580 (j < 2) ? os <<
" | " : os <<
'\n';
6583 for (
int i = 0; i < nq; i++)
6588 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6591 for (
int j = 0; j < 4; j++)
6594 (j < 3) ? os <<
" | " : os <<
'\n';
6610 for (
int i=0; i<
GetNV(); ++i)
6635 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6663 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6676 for (
int i=0; i<
GetNE(); ++i)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void LoseData()
NULL-ifies the data.
int Size() const
Return the logical size of the array.
void DeleteAll()
Delete the whole array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
T * GetData()
Returns the data.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
void CopyTo(U *dest)
STL-like copyTo dest from begin to end.
void DeleteLast()
Delete the last entry of the array.
T & Last()
Return the last element in the array.
bool SetsExist() const
Return true if any named sets are currently defined.
void Print(std::ostream &out=mfem::out, int width=-1) const
Print the contents of the container to an output stream.
void Copy(AttributeSets ©) const
Create a copy of the internal data to the provided copy.
@ GaussLobatto
Closed type.
int NumberOfEntries() const
static int create_directory(const std::string &dir_name, const Mesh *mesh, int myid)
Data type dense matrix using column-major storage.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
real_t CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
Abstract data type element.
virtual MFEM_DEPRECATED int GetNFaces(int &nFaceVertices) const =0
Geometry::Type GetGeometryType() const
virtual Element * Duplicate(Mesh *m) const =0
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
void SetAttribute(const int attr)
Set element's attribute.
virtual Type GetType() const =0
Returns element's type.
Type
Constants for the classes derived from Element.
int GetAttribute() const
Return element's attribute.
virtual int GetNVertices() const =0
virtual void SetVertices(const Array< int > &v)=0
Set the indices defining the vertices.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name.
virtual const char * Name() const
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void GetVertexDofs(int i, Array< int > &dofs) const
Returns the indices of the degrees of freedom for the specified vertices.
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 ...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Ordering::Type GetOrdering() const
Return the ordering method.
int GetEdgeDofs(int edge, Array< int > &dofs, int variant=0) const
Returns the indices of the degrees of freedom for the specified edge, including the DOFs for the vert...
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
const FiniteElementCollection * FEColl() const
int GetVDim() const
Returns vector dimension.
Abstract class for all finite elements.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
virtual void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
RefinedGeometry * Refine(Geometry::Type Geom, int Times, int ETimes=1)
static const int NumVerts[NumGeom]
const IntegrationRule * GetVertices(int GeomType) const
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType.
FiniteElementCollection * OwnFEC()
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec and fes.
virtual void GetElementDofValues(int el, Vector &dof_vals) const
FiniteElementSpace * FESpace()
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Communicator performing operations within groups defined by a GroupTopology with arbitrary-size data ...
Table & GroupLDofTable()
Fill-in the returned Table reference to initialize the GroupCommunicator then call Finalize().
void Bcast(T *ldata, int layout) const
Broadcast within each group where the master is the root.
void Finalize()
Allocate internal buffers after the GroupLDofTable is defined.
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
bool IAmMaster(int g) const
Return true if I am master for group 'g'.
void Swap(GroupTopology &other)
Swap the internal data with another GroupTopology object.
void Save(std::ostream &out) const
Save the data in a stream.
const int * GetGroup(int g) const
Return a pointer to a list of neighbors for a given group. Neighbor 0 is the local processor.
int GetGroupSize(int g) const
Get the number of processors in a group.
void Load(std::istream &in)
Load the data from a stream.
int GetGroupMasterRank(int g) const
Return the rank of the group master for group 'g'.
void Create(ListOfIntegerSets &groups, int mpitag)
Set up the group topology given the list of sets of shared entities.
int GetNumNeighbors() const
Return the number of neighbors including the local processor.
Arbitrary order H1-conforming (continuous) finite elements.
int DofForGeometry(Geometry::Type GeomType) const override
const int * GetDofMap(Geometry::Type GeomType) const
Get the Cartesian to local H1 dof map.
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn't exist.
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
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.
int GetNPoints() const
Returns the number of the points in the integration rule.
Arbitrary order "L2-conforming" discontinuous finite elements.
int Size()
Return the number of integer sets in the list.
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...
Class used by MFEM to store pointers to host and/or device memory.
int CheckElementOrientation(bool fix_it=true)
Check (and optionally attempt to fix) the orientation of the elements.
void GetEdgeOrdering(const DSTable &v_to_v, Array< int > &order)
void GetLocalFaceTransformation(int face_type, int elem_type, IsoparametricTransformation &Transf, int info) const
A helper method that constructs a transformation from the reference space of a face to the reference ...
void SetVerticesFromNodes(const GridFunction *nodes)
Helper to set vertex coordinates given a high-order curvature function.
int GetElementToEdgeTable(Table &)
Element * NewElement(int geom)
IsoparametricTransformation Transformation2
int GetNEdges() const
Return the number of edges.
void GetBdrElementFace(int i, int *f, int *o) const
static void PrintElement(const Element *el, std::ostream &os)
Array< FaceInfo > faces_info
CoarseFineTransformations CoarseFineTr
void GetElementJacobian(int i, DenseMatrix &J, const IntegrationPoint *ip=NULL)
int AddBdrElement(Element *elem)
virtual FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void RedRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
NURBSExtension * NURBSext
Optional NURBS mesh extension.
static FiniteElement * GetTransformationFEforElementType(Element::Type)
Return FiniteElement for reference element of the specified type.
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
Element::Type GetElementType(int i) const
Returns the type of element i.
void BdrBisection(int i, const HashTable< Hashed2 > &)
Bisect a boundary triangle: boundary element with index i is bisected.
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
const Table & ElementToEdgeTable() const
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Geometry::Type GetFaceGeometry(int i) const
Return the Geometry::Type associated with face i.
int GetAttribute(int i) const
Return the attribute of element i.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
void UniformRefinement3D_base(Array< int > *f2qf=NULL, DSTable *v_to_v_p=NULL, bool update_nodes=true)
Array< NCFaceInfo > nc_faces_info
void MakeRefined_(Mesh &orig_mesh, const Array< int > &ref_factors, int ref_type)
Internal function used in Mesh::MakeRefined.
real_t GetLength(int i, int j) const
Return the length of the segment from node i to node j.
const FiniteElementSpace * GetNodalFESpace() const
void Loader(std::istream &input, int generate_edges=0, std::string parse_tag="")
void GenerateNCFaceInfo()
void ApplyLocalSlaveTransformation(FaceElementTransformations &FT, const FaceInfo &fi, bool is_ghost) const
real_t AggregateError(const Array< real_t > &elem_error, const int *fine, int nfine, int op)
Derefinement helper.
void DoNodeReorder(DSTable *old_v_to_v, Table *old_elem_vert)
bool Nonconforming() const
AttributeSets bdr_attribute_sets
Named sets of boundary element attributes.
int GetBdrElementFaceIndex(int be_idx) const
Return the local face (codimension-1) index for the given boundary element index.
void GetVertices(Vector &vert_coord) const
void InitFromNCMesh(const NCMesh &ncmesh)
Initialize vertices/elements/boundary/tables from a nonconforming mesh.
virtual int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type, does not count master nonconforming face...
const Element * GetElement(int i) const
Return pointer to the i'th element object.
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
int GetNFaces() const
Return the number of faces in a 3D mesh.
ElementTransformation * GetFaceTransformation(int FaceNo)
Returns a pointer to the transformation defining the given face element.
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
void PrepareNodeReorder(DSTable **old_v_to_v, Table **old_elem_vert)
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
int GetNE() const
Returns number of elements.
const Element * GetFace(int i) const
Return pointer to the i'th face element object.
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
int Dimension() const
Dimension of the reference space used within the elements.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
void GreenRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
void UpdateNodes()
Update the nodes of a curved mesh after the topological part of a Mesh::Operation,...
real_t GetElementSize(int i, int type=0)
Get the size of the i-th element relative to the perfect reference element.
int AddElement(Element *elem)
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
STable3D * GetElementToFaceTable(int ret_ftbl=0)
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
void Printer(std::ostream &os=mfem::out, std::string section_delimiter="", const std::string &comments="") const
IsoparametricTransformation Transformation
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
void GetCharacteristics(real_t &h_min, real_t &h_max, real_t &kappa_min, real_t &kappa_max, Vector *Vh=NULL, Vector *Vk=NULL)
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
void GetNodes(Vector &node_coord) const
AttributeSets attribute_sets
Named sets of element attributes.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
void PrintVTU(std::ostream &os, int ref=1, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr_elements=false)
Element::Type GetFaceElementType(int Face) const
int CheckBdrElementOrientation(bool fix_it=true)
Check the orientation of the boundary elements.
void AverageVertices(const int *indexes, int n, int result)
Averages the vertices with given indexes and saves the result in vertices[result].
void Swap(Mesh &other, bool non_geometry)
void Bisection(int i, const DSTable &, int *, int *, int *)
Bisect a triangle: element with index i is bisected.
void UniformRefinement2D_base(bool update_nodes=true)
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
int GetNBE() const
Returns number of boundary elements.
long long GetGlobalNE() const
Return the total (global) number of elements.
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
virtual int FindPoints(DenseMatrix &point_mat, Array< int > &elem_ids, Array< IntegrationPoint > &ips, bool warn=true, InverseElementTransformation *inv_trans=NULL)
Find the ids of the elements that contain the given points, and their corresponding reference coordin...
bool IsSlaveFace(const FaceInfo &fi) const
void FreeElement(Element *E)
Array< Element * > boundary
NCMesh * ncmesh
Optional nonconforming mesh extension.
void NewNodes(GridFunction &nodes, bool make_owner=false)
Replace the internal node GridFunction with the given GridFunction.
GridFunction * GetNodes()
Return a pointer to the internal node GridFunction (may be NULL).
STable3D * GetFacesTable()
void SetMeshGen()
Determine the mesh generator bitmask meshgen, see MeshGenerator().
FaceElementTransformations FaceElemTr
void GetVertexToVertexTable(DSTable &) const
Geometry::Type GetElementBaseGeometry(int i) const
Table * GetVertexToElementTable()
void InitRefinementTransforms()
int * GeneratePartitioning(int nparts, int part_method=1)
Array< Element * > elements
Array< int > attributes
A list of all unique element attributes used by the Mesh.
void MakeSimplicial_(const Mesh &orig_mesh, int *vglobal)
virtual void SetAttributes()
Determine the sets of unique attribute values in domain and boundary elements.
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void OnMeshUpdated(Mesh *mesh)
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
const Table & GetDerefinementTable()
Arbitrary order H(curl)-conforming Nedelec finite elements.
Class for standard nodal finite elements.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Abstract parallel finite element space.
void GetSharedTriangleDofs(int group, int fi, Array< int > &dofs) const
void GetSharedEdgeDofs(int group, int ei, Array< int > &dofs) const
int GetTrueVSize() const override
Return the number of local vector true dofs.
void GetFaceNbrElementVDofs(int i, Array< int > &vdofs, DofTransformation &doftrans) const
int GetFaceDofs(int i, Array< int > &dofs, int variant=0) const override
void GetSharedQuadrilateralDofs(int group, int fi, Array< int > &dofs) const
void GetElementDofs(int i, Array< int > &dofs, DofTransformation &doftrans) const override
The same as GetElementDofs(), but with a user-allocated DofTransformation object. doftrans must be al...
HYPRE_BigInt GetGlobalTDofNumber(int ldof) const
Returns the global tdof number of the given local degree of freedom.
const FiniteElement * GetFaceNbrFE(int i) const
void GetBdrElementDofs(int i, Array< int > &dofs, DofTransformation &doftrans) const override
The same as GetBdrElementDofs(), but with a user-allocated DofTransformation object....
Class for parallel grid function.
void ExchangeFaceNbrData()
ParFiniteElementSpace * ParFESpace() const
void SaveAsOne(const char *fname, int precision=16) const
Class for parallel meshes.
Mesh GetSerialMesh(int save_rank) const
void GetCharacteristics(real_t &h_min, real_t &h_max, real_t &kappa_min, real_t &kappa_max)
void NonconformingRefinement(const Array< Refinement > &refinements, int nc_limit=0) override
This function is not public anymore. Use GeneralRefinement instead.
int GroupNQuadrilaterals(int group) const
ElementTransformation * GetFaceNbrElementTransformation(int FaceNo)
Returns a pointer to the transformation defining the i-th face neighbor.
void GetFaceSplittings(const int *fv, const HashTable< Hashed2 > &v_to_v, Array< unsigned > &codes)
Append codes identifying how the given face has been split to codes.
Table send_face_nbr_elements
Array< int > face_nbr_vertices_offset
void BuildVertexGroup(int ngroups, const Table &vert_element)
void PrintVTU(std::string pathname, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr=false) override
void NURBSUniformRefinement(int rf=2, real_t tol=1.0e-12) override
Refine NURBS mesh, with an optional refinement factor.
void PrintXG(std::ostream &out=mfem::out) const override
Array< Element * > shared_edges
int GetEdgeSplittings(Element *edge, const DSTable &v_to_v, int *middle)
Return a number(0-1) identifying how the given edge has been split.
void RefineGroups(const DSTable &v_to_v, int *middle)
Update the groups after triangle refinement.
void ParPrint(std::ostream &out, const std::string &comments="") const
void GetSharedTriCommunicator(int ordering, GroupCommunicator &stria_comm) const
Get the shared face triangles GroupCommunicator.
bool NonconformingDerefinement(Array< real_t > &elem_error, real_t threshold, int nc_limit=0, int op=1) override
NC version of GeneralDerefinement.
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
void SaveAsOne(const std::string &fname, int precision=16) const
void ExchangeFaceNbrData()
void BuildEdgeGroup(int ngroups, const Table &edge_element)
Table group_svert
Shared objects in each group.
MFEM_DEPRECATED void ReorientTetMesh() override
See the remarks for the serial version in mesh.hpp.
int GroupVertex(int group, int i) const
void UniformRefinement2D() override
Refine a mixed 2D mesh uniformly.
void BuildSharedFaceElems(int ntri_faces, int nquad_faces, const Mesh &mesh, int *partitioning, const STable3D *faces_tbl, const Array< int > &face_group, const Array< int > &vert_global_local)
bool WantSkipSharedMaster(const NCMesh::Master &master) const
FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31) override
void BuildSharedVertMapping(int nvert, const Table *vert_element, const Array< int > &vert_global_local)
long long GetGlobalElementNum(int local_element_num) const
Map a local element number to a global element number.
Table * GetFaceToAllElementTable() const
void GetGlobalElementIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are supported.
void AddTriFaces(const Array< int > &v, const std::unique_ptr< STable3D > &faces, const std::unique_ptr< STable3D > &shared_faces, int elem, int start, int end, const int fverts[][N])
Helper function for adding triangle face neighbor element to face table entries. Have to use a templa...
void FindSharedFaces(const Mesh &mesh, const int *partition, Array< int > &face_group, ListOfIntegerSets &groups)
long long glob_elem_offset
void GetSharedEdgeCommunicator(int ordering, GroupCommunicator &sedge_comm) const
Get the shared edges GroupCommunicator.
void PrintInfo(std::ostream &out=mfem::out) override
Print various parallel mesh stats.
int GetNFbyType(FaceType type) const override
Returns the number of local faces according to the requested type, does not count master non-conformi...
void GetGlobalVertexIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
bool HasBoundaryElements() const override
Checks if any rank in the mesh has boundary elements.
void LocalRefinement(const Array< int > &marked_el, int type=3) override
This function is not public anymore. Use GeneralRefinement instead.
void GetFaceNbrElementFaces(int i, Array< int > &faces, Array< int > &orientation) const
void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1) override
Set the curvature of the mesh nodes using the given polynomial degree.
long glob_offset_sequence
int GetLocalElementNum(long long global_element_num) const
void SetAttributes() override
Determine the sets of unique attribute values in domain and boundary elements.
int FindPoints(DenseMatrix &point_mat, Array< int > &elem_ids, Array< IntegrationPoint > &ips, bool warn=true, InverseElementTransformation *inv_trans=NULL) override
Find the ids of the elements that contain the given points, and their corresponding reference coordin...
void GetSharedQuadCommunicator(int ordering, GroupCommunicator &squad_comm) const
Get the shared face quadrilaterals GroupCommunicator.
void BuildFaceNbrElementToFaceTable()
void MakeRefined_(ParMesh &orig_mesh, int ref_factor, int ref_type)
Internal function used in ParMesh::MakeRefined (and related constructor)
void GetGlobalFaceIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
Array< Vertex > face_nbr_vertices
void UniformRefineGroups2D(int old_nv)
void GetGlobalEdgeIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
void ExchangeFaceNbrNodes()
void SetNodalFESpace(FiniteElementSpace *nfes) override
void UniformRefinement3D() override
Refine a mixed 3D mesh uniformly.
long long ReduceInt(int value) const override
Utility function: sum integers from all processors (Allreduce).
Table send_face_nbr_vertices
ParMesh()
Default constructor. Create an empty ParMesh.
int BuildLocalElements(const Mesh &global_mesh, const int *partitioning, const Array< int > &vert_global_local)
Fills out partitioned Mesh::elements.
bool DecodeFaceSplittings(HashTable< Hashed2 > &v_to_v, const int *v, const Array< unsigned > &codes, int &pos)
static ParMesh MakeSimplicial(ParMesh &orig_mesh)
Array< Vert4 > shared_quads
void LoadSharedEntities(std::istream &input)
void Finalize(bool refine=false, bool fix_orientation=false) override
Finalize the construction of a general Mesh.
void BuildFaceGroup(int ngroups, const Mesh &mesh, const Array< int > &face_group, int &nstria, int &nsquad)
void BuildSharedEdgeElems(int nedges, Mesh &mesh, const Array< int > &vert_global_local, const Table *edge_element)
Array< int > svert_lvert
Shared to local index mapping.
Array< Element * > face_nbr_elements
FaceElementTransformations * GetSharedFaceTransformationsByLocalIndex(int FaceNo, bool fill2=true)
Get the FaceElementTransformations for the given shared face (edge 2D) using the face index FaceNo....
void PrintSharedEntities(const std::string &fname_prefix) const
Debugging method.
int GroupNTriangles(int group) const
void GetSharedVertexCommunicator(int ordering, GroupCommunicator &svert_comm) const
Get the shared vertices GroupCommunicator.
int GetSharedFace(int sface) const
Return the local face index for the given shared face.
void EnsureParNodes()
If the mesh is curved, make sure 'Nodes' is ParGridFunction.
int GroupNEdges(int group) const
void GenerateOffsets(int N, HYPRE_BigInt loc_sizes[], Array< HYPRE_BigInt > *offsets[]) const
void MarkTetMeshForRefinement(const DSTable &v_to_v) override
Array< int > face_nbr_group
Array< int > face_nbr_elements_offset
ParMesh & operator=(ParMesh &&mesh)
Move assignment operator.
void Load(std::istream &input, int generate_edges=0, int refine=1, bool fix_orientation=true) override
Parallel version of Mesh::Load().
int GetNFaceNeighbors() const
void UniformRefineGroups3D(int old_nv, int old_nedges, const DSTable &old_v_to_v, const STable3D &old_faces, Array< int > *f2qf)
void GetGhostFaceTransformation(FaceElementTransformations &FElTr, Element::Type face_type, Geometry::Type face_geom) const
void RebalanceImpl(const Array< int > *partition)
int FindSharedEdges(const Mesh &mesh, const int *partition, Table *&edge_element, ListOfIntegerSets &groups)
void PrintAsOneXG(std::ostream &out=mfem::out)
Old mesh format (Netgen/Truegrid) version of 'PrintAsOne'.
std::unique_ptr< Table > face_nbr_el_to_face
Array< Vert3 > shared_trias
void GroupQuadrilateral(int group, int i, int &face, int &o) const
void Save(const std::string &fname, int precision=16) const override
void DistributeAttributes(Array< int > &attr)
Ensure that bdr_attributes and attributes agree across processors.
STable3D * GetSharedFacesTable()
static ParMesh MakeRefined(ParMesh &orig_mesh, int ref_factor, int ref_type)
Create a uniformly refined (by any factor) version of orig_mesh.
real_t GetFaceNbrElementSize(int i, int type=0)
std::unique_ptr< Table > face_nbr_el_ori
orientations for each face (from nbr processor)
int GetFaceNbrRank(int fn) const
int FindSharedVertices(const int *partition, Table *vertex_element, ListOfIntegerSets &groups)
void GroupTriangle(int group, int i, int &face, int &o) const
FaceElementTransformations * GetSharedFaceTransformations(int sf, bool fill2=true)
Get the FaceElementTransformations for the given shared face (edge 2D) using the shared face index sf...
void PrintAsSerial(std::ostream &out=mfem::out, const std::string &comments="") const
int BuildLocalBoundary(const Mesh &global_mesh, const int *partitioning, const Array< int > &vert_global_local, Array< bool > &activeBdrElem, Table *&edge_element)
Fills out partitioned Mesh::boundary.
int BuildLocalVertices(const Mesh &global_mesh, const int *partitioning, Array< int > &vert_global_local)
Fills out partitioned Mesh::vertices.
void ComputeGlobalElementOffset() const
void GetBoundingBox(Vector &p_min, Vector &p_max, int ref=2)
void PrintAsOne(std::ostream &out=mfem::out, const std::string &comments="") const
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
void Swap(ParMesh &other)
void GroupEdge(int group, int i, int &edge, int &o) const
int GroupNVertices(int group) const
A parallel extension of the NCMesh class.
bool IsGhost(int entity, int index) const
Return true if the specified vertex/edge/face is a ghost.
void GetFaceNeighbors(class ParMesh &pmesh)
void LimitNCLevel(int max_nc_level) override
Parallel version of NCMesh::LimitNCLevel.
void Refine(const Array< Refinement > &refinements) override
void GetConformingSharedStructures(class ParMesh &pmesh)
void Derefine(const Array< int > &derefs) override
void Rebalance(const Array< int > *custom_partition=NULL)
void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level) override
const NCList & GetSharedList(int entity)
Helper to get shared vertices/edges/faces ('entity' == 0/1/2 resp.).
const NCList & GetSharedEdges()
const NCList & GetSharedFaces()
int InitialPartition(int index) const
Helper to get the partitioning when the serial mesh gets split initially.
void SynchronizeDerefinementData(Array< Type > &elem_data, const Table &deref_table)
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Symmetric 3D Table stored as an array of rows each of which has a stack of column,...
int Push(int r, int c, int f)
Check to see if this entry is in the table and add it to the table if it is not there....
int Push4(int r, int c, int f, int t)
Check to see if this entry is in the table and add it to the table if it is not there....
Data type line segment element.
void GetVertices(Array< int > &v) const override
Get the indices defining the vertices.
void AddConnections(int r, const int *c, int nc)
void SetSize(int dim, int connections_per_row)
Set the size and the number of connections for the table.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
void AddConnection(int r, int c)
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
void SetIJ(int *newI, int *newJ, int newsize=-1)
Replace the I and J arrays with the given newI and newJ arrays.
int Size() const
Returns the number of TYPE I elements.
int Size_of_connections() const
void AddColumnsInRow(int r, int ncol)
void AddAColumnInRow(int r)
void SetDims(int rows, int nnz)
Data type tetrahedron element.
int GetRefinementFlag() const
void GetMarkedFace(const int face, int *fv) const
void MarkEdge(DenseMatrix &pmat)
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
int index(int i, int j, int nx, int ny)
void Swap(Array< T > &, Array< T > &)
void mfem_error(const char *msg)
GeometryRefiner GlobGeometryRefiner
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
void ShiftRight(int &a, int &b, int &c)
std::string to_padded_string(int i, int digits)
Convert an integer to a 0-padded string with the given number of digits.
VTKFormat
Data array format for VTK and VTU files.
@ ASCII
Data arrays will be written in ASCII format.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
const char * VTKByteOrder()
Determine the byte order and return either "BigEndian" or "LittleEndian".
void SortPairs(Pair< A, B > *pairs, int size)
Sort an array of Pairs with respect to the first element.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
real_t p(const Vector &x, real_t t)
Defines the position of a fine element within a coarse element.
static const int FaceVert[NumFaces][MaxFaceVert]
static const int FaceVert[NumFaces][MaxFaceVert]
static const int FaceVert[NumFaces][MaxFaceVert]
static const int Orient[NumOrient][NumVert]
static const int FaceVert[NumFaces][MaxFaceVert]
static const int Orient[NumOrient][NumVert]
Helper struct to convert a C++ type to an MPI type.
This structure stores the low level information necessary to interpret the configuration of elements ...
int slaves_end
slave faces
Lists all edges/faces in the nonconforming mesh.
Array< MeshId > conforming
All MeshIds corresponding to conformal faces.
Array< Slave > slaves
All MeshIds corresponding to slave faces.
Array< Master > masters
All MeshIds corresponding to master faces.