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)
121 partitioning.
MakeRef(
const_cast<int *
>(partitioning_), mesh.
GetNE(),
132 for (
int i = 0; i < mesh.
GetNE(); i++)
171 mesh.
GetNE(), mt,
true);
181 Table *edge_element = NULL;
184 activeBdrElem, edge_element);
239 int nsedges =
FindSharedEdges(mesh, partitioning, edge_element, groups);
246 int ngroups = groups.
Size()-1, nstris, nsquads;
253 face_group, vert_global_local);
269 "invalid NURBS mesh");
295 int element_counter = 0;
296 for (
int i = 0; i < mesh.
GetNE(); i++)
298 if (partitioning[i] ==
MyRank)
301 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
302 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
318 const int* partitioning,
322 vert_global_local = -1;
324 int vert_counter = 0;
325 for (
int i = 0; i < mesh.
GetNE(); i++)
327 if (partitioning[i] ==
MyRank)
331 for (
int j = 0; j < vert.
Size(); j++)
333 if (vert_global_local[vert[j]] < 0)
335 vert_global_local[vert[j]] = vert_counter++;
343 for (
int i = 0; i < vert_global_local.
Size(); i++)
345 if (vert_global_local[i] >= 0)
347 vert_global_local[i] = vert_counter++;
353 for (
int i = 0; i < vert_global_local.
Size(); i++)
355 if (vert_global_local[i] >= 0)
368 const int nelems = std::count_if(partitioning,
369 partitioning + mesh.
GetNE(), [
this](
int i) { return i == MyRank;});
376 int element_counter = 0;
377 for (
int i = 0; i < mesh.
GetNE(); i++)
379 if (partitioning[i] ==
MyRank)
383 int nv =
elements[element_counter]->GetNVertices();
384 for (
int j = 0; j < nv; j++)
386 v[j] = vert_global_local[v[j]];
392 return element_counter;
398 Table*& edge_element)
404 activeBdrElem =
false;
409 for (
int i = 0; i < mesh.
GetNBE(); i++)
411 int face, o, el1, el2;
414 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
419 activeBdrElem[i] =
true;
424 int bdrelem_counter = 0;
426 for (
int i = 0; i < mesh.
GetNBE(); i++)
428 int face, o, el1, el2;
431 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
435 int nv =
boundary[bdrelem_counter]->GetNVertices();
436 for (
int j = 0; j < nv; j++)
438 v[j] = vert_global_local[v[j]];
446 edge_element =
new Table;
449 for (
int i = 0; i < mesh.
GetNBE(); i++)
452 int el1 = edge_element->
GetRow(edge)[0];
453 if (partitioning[el1] ==
MyRank)
458 activeBdrElem[i] =
true;
463 int bdrelem_counter = 0;
465 for (
int i = 0; i < mesh.
GetNBE(); i++)
468 int el1 = edge_element->
GetRow(edge)[0];
469 if (partitioning[el1] ==
MyRank)
473 int nv =
boundary[bdrelem_counter]->GetNVertices();
474 for (
int j = 0; j < nv; j++)
476 v[j] = vert_global_local[v[j]];
484 for (
int i = 0; i < mesh.
GetNBE(); i++)
486 int vert = mesh.
boundary[i]->GetVertices()[0];
489 if (partitioning[el1] ==
MyRank)
495 int bdrelem_counter = 0;
497 for (
int i = 0; i < mesh.
GetNBE(); i++)
499 int vert = mesh.
boundary[i]->GetVertices()[0];
502 if (partitioning[el1] ==
MyRank)
506 v[0] = vert_global_local[v[0]];
523 for (
int i = 0; i < face_group.
Size(); i++)
530 el[0] = partitioning[el[0]];
531 el[1] = partitioning[el[1]];
536 face_group[i] = groups.
Insert(group) - 1;
543 Table*& edge_element,
549 int sedge_counter = 0;
552 edge_element =
new Table;
563 for (
int i = 0; i < edge_element->
Size(); i++)
565 int me = 0, others = 0;
566 for (
int j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
568 int k = edge_element->
GetJ()[j];
569 int rank = partitioning[k];
570 edge_element->
GetJ()[j] = rank;
589 edge_element->
GetRow(i)[0] = -1;
593 return sedge_counter;
602 int svert_counter = 0;
603 for (
int i = 0; i < vert_element->
Size(); i++)
605 int me = 0, others = 0;
606 for (
int j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
608 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
623 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
627 vert_element->
GetI()[i] = -1;
630 return svert_counter;
635 int &nstria,
int &nsquad)
641 for (
int i = 0; i < face_group.
Size(); i++)
643 if (face_group[i] >= 0)
660 for (
int i = 0; i < face_group.
Size(); i++)
662 if (face_group[i] >= 0)
683 for (
int i = 0; i < edge_element.
Size(); i++)
685 if (edge_element.
GetRow(i)[0] >= 0)
693 int sedge_counter = 0;
694 for (
int i = 0; i < edge_element.
Size(); i++)
696 if (edge_element.
GetRow(i)[0] >= 0)
709 for (
int i = 0; i < vert_element.
Size(); i++)
711 if (vert_element.
GetI()[i] >= 0)
719 int svert_counter = 0;
720 for (
int i = 0; i < vert_element.
Size(); i++)
722 if (vert_element.
GetI()[i] >= 0)
732 const Mesh& mesh,
const int *partitioning,
741 if (
Dim < 3) {
return; }
743 int stria_counter = 0;
744 int squad_counter = 0;
745 for (
int i = 0; i < face_group.
Size(); i++)
747 if (face_group[i] < 0) {
continue; }
757 for (
int j = 0; j < 3; j++)
759 v[j] = vert_global_local[v[j]];
761 const int lface = (*faces_tbl)(v[0], v[1], v[2]);
777 if (
MyRank == partitioning[gl_el2])
779 std::swap(v[0], v[1]);
791 for (
int j = 0; j < 4; j++)
793 v[j] = vert_global_local[v[j]];
796 (*faces_tbl)(v[0], v[1], v[2], v[3]);
802 MFEM_ABORT(
"unknown face type: " << face->
GetType());
810 const Table* edge_element)
822 int sedge_counter = 0;
823 for (
int i = 0; i < edge_element->
Size(); i++)
825 if (edge_element->
GetRow(i)[0] >= 0)
831 new Segment(vert_global_local[vert[0]],
832 vert_global_local[vert[1]], 1);
834 sedge_ledge[sedge_counter] = v_to_v(vert_global_local[vert[0]],
835 vert_global_local[vert[1]]);
837 MFEM_VERIFY(
sedge_ledge[sedge_counter] >= 0,
"Error in v_to_v.");
852 int svert_counter = 0;
853 for (
int i = 0; i < vert_element->
Size(); i++)
855 if (vert_element->
GetI()[i] >= 0)
857 svert_lvert[svert_counter++] = vert_global_local[i];
865 : MyComm(pncmesh.MyComm)
866 , NRanks(pncmesh.NRanks)
867 , MyRank(pncmesh.MyRank)
868 , glob_elem_offset(-1)
869 , glob_offset_sequence(-1)
894 MPI_Allreduce(&loc_meshgen, &
meshgen, 1, MPI_INT, MPI_BOR,
MyComm);
908 const int l_edge = v_to_v(v[0], v[1]);
909 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
920 for (
int st = 0; st < nst; st++)
934 bool fix_orientation)
935 : glob_elem_offset(-1)
936 , glob_offset_sequence(-1)
946 Load(input, generate_edges, refine, fix_orientation);
950 bool fix_orientation)
957 Loader(input, generate_edges,
"mfem_serial_mesh_end");
969 MFEM_ASSERT(
pncmesh,
"internal error");
992 MFEM_VERIFY(ident ==
"communication_groups",
993 "input stream is not a parallel MFEM mesh");
1001 input >> ident >> num_sverts;
1002 MFEM_VERIFY(ident ==
"total_shared_vertices",
"invalid mesh file");
1011 input >> ident >> num_sedges;
1012 MFEM_VERIFY(ident ==
"total_shared_edges",
"invalid mesh file");
1026 input >> ident >> num_sface;
1027 MFEM_VERIFY(ident ==
"total_shared_faces",
"invalid mesh file");
1040 int svert_counter = 0, sedge_counter = 0;
1047 input >> ident >> g;
1050 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
1051 <<
", read group " << g << endl;
1057 input >> ident >> nv;
1058 MFEM_VERIFY(ident ==
"shared_vertices",
"invalid mesh file");
1059 nv += svert_counter;
1061 "incorrect number of total_shared_vertices");
1063 for ( ; svert_counter < nv; svert_counter++)
1072 input >> ident >> ne;
1073 MFEM_VERIFY(ident ==
"shared_edges",
"invalid mesh file");
1074 ne += sedge_counter;
1076 "incorrect number of total_shared_edges");
1078 for ( ; sedge_counter < ne; sedge_counter++)
1081 input >> v[0] >> v[1];
1088 input >> ident >> nf;
1089 for (
int i = 0; i < nf; i++)
1098 for (
int ii = 0; ii < 3; ii++) { input >> v[ii]; }
1103 for (
int ii = 0; ii < 4; ii++) { input >> v[ii]; }
1106 MFEM_ABORT(
"invalid shared face geometry: " << geom);
1117 "incorrect number of total_shared_faces");
1152 ref_factors = ref_factor;
1231 for (
int j = 0; j < orig_n_verts; j++)
1238 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1239 if (orig_n_edges > 0)
1244 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1246 for (
int e = 0; e < orig_n_edges; e++)
1251 for (
int j = 2; j < rdofs.
Size(); j++)
1259 for (
int k = 0; k < nvert; k++)
1262 v[k] = rdofs[c2h_map[cid]];
1278 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1280 for (
int f = 0;
f < orig_nt;
f++)
1285 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1294 for (
int k = 0; k < 2; k++)
1296 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1305 for (
int k = 0; k < nvert; k++)
1308 v[k] = rdofs[c2h_map[cid]];
1322 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1324 for (
int f = 0;
f < orig_nq;
f++)
1329 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1338 for (
int k = 0; k < 2; k++)
1340 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1349 for (
int k = 0; k < nvert; k++)
1352 v[k] = rdofs[c2h_map[cid]];
1399 for (
int iv=0; iv<orig_mesh.
GetNV(); ++iv)
1410 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1436 constexpr int ntris = 2, nv_tri = 3, nv_quad = 4;
1439 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1443 for (
int j = 0; j < orig_n_verts; j++)
1450 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1451 for (
int e = 0; e < orig_n_edges; e++)
1463 for (
int e = 0; e < orig_nt; e++)
1470 for (
int iv=0; iv<nv_tri; ++iv) { v2[iv] = v[iv]; }
1477 static const int trimap[12] =
1483 static const int diagmap[4] = { 0, 2, 1, 3 };
1484 for (
int f = 0;
f < orig_nq; ++
f)
1491 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
1492 int iv_min = std::min_element(vg, vg+nv_quad) - vg;
1493 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
1497 v_diag[0] = v[diagmap[0 + isplit*2]];
1498 v_diag[1] = v[diagmap[1 + isplit*2]];
1501 for (
int itri=0; itri<ntris; ++itri)
1505 for (
int iv=0; iv<nv_tri; ++iv)
1507 v2[iv] = v[trimap[itri + isplit*2 + iv*ntris*2]];
1525 const int meshgen_save =
meshgen;
1555 int max_attr = attr.
Size() ? attr.
Max() : 1 ;
1556 int glb_max_attr = -1;
1557 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1561 bool *attr_marker =
new bool[glb_max_attr];
1562 bool *glb_attr_marker =
new bool[glb_max_attr];
1563 for (
int i = 0; i < glb_max_attr; i++)
1565 attr_marker[i] =
false;
1567 for (
int i = 0; i < attr.
Size(); i++)
1569 attr_marker[attr[i] - 1] =
true;
1571 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1572 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
1573 delete [] attr_marker;
1578 for (
int i = 0; i < glb_max_attr; i++)
1580 if (glb_attr_marker[i])
1585 delete [] glb_attr_marker;
1596 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1602 MFEM_WARNING(
"Non-positive element attributes found!");
1609 int maxNumOfBdrElements;
1611 MPI_INT, MPI_MAX,
MyComm);
1612 return (maxNumOfBdrElements > 0);
1620 o = (v[0] < v[1]) ? (+1) : (-1);
1629 "Expecting a triangular face.");
1640 "Expecting a quadrilateral face.");
1650 gr_sedge.
GetI()[0] = 0;
1659 gr_sedge.
GetJ()[k] =k;
1674 gr_svert.
GetI()[0] = 0;
1683 gr_svert.
GetJ()[k] = k;
1698 gr_squad.
GetI()[0] = 0;
1707 gr_squad.
GetJ()[k] = k;
1722 gr_stria.
GetI()[0] = 0;
1731 gr_stria.
GetJ()[k] = k;
1757 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1760 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1762 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1765 if (n == 0) {
continue; }
1767 for (
int j = 0; j < n; j++)
1769 sedge_ord_map[j].one = sedge_ord[k+j];
1770 sedge_ord_map[j].two = j;
1773 for (
int j = 0; j < n; j++)
1776 const int *v =
shared_edges[sedge_from]->GetVertices();
1777 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1779 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1780 for (
int j = 0; j < n; j++)
1784 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1798 ilen_len[j].one = order[j];
1799 ilen_len[j].two =
GetLength(i, it.Column());
1806 for (
int i = 1; i < order.
Size(); i++)
1808 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1822 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1834 elements[i]->MarkEdge(v_to_v, order);
1842 boundary[i]->MarkEdge(v_to_v, order);
1861 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1878 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1879 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1881 if (bit == 8*
sizeof(
unsigned))
1887 const face_t &
f = face_stack.
Last();
1888 int mid = v_to_v.
FindId(
f.one,
f.two);
1898 face_stack.
Append(face_t(
f.three,
f.one, mid));
1899 face_t &r = face_stack[face_stack.
Size()-2];
1900 r = face_t(r.two, r.three, mid);
1912 bool need_refinement = 0;
1913 face_stack.
Append(face_t(v[0], v[1], v[2]));
1914 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1916 if (bit == 8*
sizeof(
unsigned))
1918 code = codes[pos++];
1922 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1924 const face_t &
f = face_stack.
Last();
1925 int mid = v_to_v.
FindId(
f.one,
f.two);
1928 mid = v_to_v.
GetId(
f.one,
f.two);
1929 int ind[2] = {
f.one,
f.two };
1932 need_refinement = 1;
1935 face_stack.
Append(face_t(
f.three,
f.one, mid));
1936 face_t &r = face_stack[face_stack.
Size()-2];
1937 r = face_t(r.two, r.three, mid);
1939 return need_refinement;
1945 if (HYPRE_AssumedPartitionCheck())
1948 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_BIG_INT, MPI_SUM,
MyComm);
1949 for (
int i = 0; i < N; i++)
1952 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1953 (*offsets[i])[1] = temp[i];
1956 for (
int i = 0; i < N; i++)
1958 (*offsets[i])[2] = temp[i];
1960 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1961 "overflow in offsets");
1967 MPI_Allgather(loc_sizes, N, HYPRE_MPI_BIG_INT, temp.
GetData(), N,
1968 HYPRE_MPI_BIG_INT,
MyComm);
1969 for (
int i = 0; i < N; i++)
1974 for (
int j = 0; j <
NRanks; j++)
1976 offs[j+1] = offs[j] + temp[i+N*j];
1980 "overflow in offsets");
2009 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
2056 *new_nodes = *
Nodes;
2087 bool del_tables =
false;
2114 gr_sface =
new Table;
2149 if (del_tables) {
delete gr_sface; }
2160 int num_face_nbrs = 0;
2163 if (gr_sface->
RowSize(g-1) > 0)
2171 if (num_face_nbrs == 0)
2181 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
2183 if (gr_sface->
RowSize(g-1) > 0)
2188 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
2190 rank_group[counter].two = g;
2197 for (
int fn = 0; fn < num_face_nbrs; fn++)
2203 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2204 MPI_Request *send_requests = requests;
2205 MPI_Request *recv_requests = requests + num_face_nbrs;
2206 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2208 int *nbr_data =
new int[6*num_face_nbrs];
2209 int *nbr_send_data = nbr_data;
2210 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
2219 Table send_face_nbr_elemdata, send_face_nbr_facedata;
2223 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
2224 send_face_nbr_facedata.
MakeI(num_face_nbrs);
2225 for (
int fn = 0; fn < num_face_nbrs; fn++)
2228 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2229 int *sface = gr_sface->
GetRow(nbr_group-1);
2230 for (
int i = 0; i < num_sfaces; i++)
2232 int lface = s2l_face[sface[i]];
2234 if (el_marker[el] != fn)
2239 const int nv =
elements[el]->GetNVertices();
2240 const int *v =
elements[el]->GetVertices();
2241 for (
int j = 0; j < nv; j++)
2242 if (vertex_marker[v[j]] != fn)
2244 vertex_marker[v[j]] = fn;
2248 const int nf =
elements[el]->GetNFaces();
2257 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
2262 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2263 &send_requests[fn]);
2264 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2265 &recv_requests[fn]);
2269 send_face_nbr_elemdata.
MakeJ();
2270 send_face_nbr_facedata.
MakeJ();
2274 for (
int fn = 0; fn < num_face_nbrs; fn++)
2277 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2278 int *sface = gr_sface->
GetRow(nbr_group-1);
2279 for (
int i = 0; i < num_sfaces; i++)
2281 const int sf = sface[i];
2282 int lface = s2l_face[sf];
2284 if (el_marker[el] != fn)
2289 const int nv =
elements[el]->GetNVertices();
2290 const int *v =
elements[el]->GetVertices();
2291 for (
int j = 0; j < nv; j++)
2292 if (vertex_marker[v[j]] != fn)
2294 vertex_marker[v[j]] = fn;
2305 const int nf =
elements[el]->GetNFaces();
2316 const int *lf_v =
faces[lface]->GetVertices();
2336 for (
int fn = 0; fn < num_face_nbrs; fn++)
2342 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
2343 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
2344 int *facedata = send_face_nbr_facedata.
GetRow(fn);
2346 for (
int i = 0; i < num_verts; i++)
2348 vertex_marker[verts[i]] = i;
2351 for (
int el = 0; el < num_elems; el++)
2353 const int nv =
elements[elems[el]]->GetNVertices();
2356 for (
int j = 0; j < nv; j++)
2358 elemdata[j] = vertex_marker[elemdata[j]];
2360 elemdata += nv + nf;
2362 el_marker[elems[el]] = el;
2365 for (
int i = 0; i < num_sfaces; i++)
2367 facedata[2*i] = el_marker[facedata[2*i]];
2371 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2374 Table recv_face_nbr_elemdata;
2379 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2382 for (
int fn = 0; fn < num_face_nbrs; fn++)
2390 recv_face_nbr_elemdata.
MakeJ();
2392 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2395 for (
int fn = 0; fn < num_face_nbrs; fn++)
2400 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2401 send_face_nbr_elemdata.
RowSize(fn),
2402 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2404 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2405 recv_face_nbr_elemdata.
RowSize(fn),
2406 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2415 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2417 if (fn == MPI_UNDEFINED)
2425 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2427 for (
int i = 0; i < num_elems; i++)
2433 for (
int j = 0; j < nv; j++)
2435 recv_elemdata[j] += vert_off;
2438 recv_elemdata += nv;
2443 for (
int j = 0; j < nf; j++)
2445 fn_ori[j] = recv_elemdata[j];
2447 recv_elemdata += nf;
2454 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2457 recv_face_nbr_facedata.
SetSize(
2459 for (
int fn = 0; fn < num_face_nbrs; fn++)
2464 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2465 send_face_nbr_facedata.
RowSize(fn),
2466 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2469 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2470 send_face_nbr_facedata.
RowSize(fn),
2471 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2478 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2480 if (fn == MPI_UNDEFINED)
2487 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2488 int *sface = gr_sface->
GetRow(nbr_group-1);
2490 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2492 for (
int i = 0; i < num_sfaces; i++)
2494 const int sf = sface[i];
2495 int lface = s2l_face[sf];
2497 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2498 int info = facedata[2*i+1];
2506 int nbr_ori = info%64, nbr_v[4];
2507 const int *lf_v =
faces[lface]->GetVertices();
2514 for (
int j = 0; j < 3; j++)
2516 nbr_v[perm[j]] = sf_v[j];
2526 for (
int j = 0; j < 4; j++)
2528 nbr_v[perm[j]] = sf_v[j];
2534 info = 64*(info/64) + nbr_ori;
2540 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2557 else if (
Nodes == NULL)
2567 if (!num_face_nbrs) {
return; }
2569 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2570 MPI_Request *send_requests = requests;
2571 MPI_Request *recv_requests = requests + num_face_nbrs;
2572 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2576 for (
int i = 0; i < send_vertices.
Size(); i++)
2582 for (
int fn = 0; fn < num_face_nbrs; fn++)
2597 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2598 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2606 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2621 for (
int j = 0; j < 4; j++)
2624 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2630 for (
int j = 0; j < 2; j++)
2633 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2635 for (
int j = 2; j < 5; j++)
2638 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2644 for (
int j = 0; j < 1; j++)
2647 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2649 for (
int j = 1; j < 5; j++)
2652 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2660 for (
int j = 0; j < 6; j++)
2663 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2668 MFEM_ABORT(
"Unexpected type of Element.");
2677 const std::unique_ptr<STable3D> &faces,
2678 const std::unique_ptr<STable3D> &shared_faces,
2679 int elem,
int start,
int end,
const int fverts[][N])
2681 for (
int i = start; i < end; ++i)
2684 const auto fv = fverts[i];
2686 const Vert3 elem_fv(elem_vertices[fv[0]], elem_vertices[fv[1]],
2687 elem_vertices[fv[2]]);
2690 const int lf =
faces->Index(elem_fv.
v[0], elem_fv.
v[1], elem_fv.
v[2]);
2694 const int sf = lf < 0 ? shared_faces->Index(elem_fv.
v[0], elem_fv.
v[1],
2699 const int face_to_add = lf < 0 ? (sf >= 0 ? sf +
NumOfFaces : -1) : lf;
2701 MFEM_ASSERT(sf >= 0 ||
2702 lf >= 0,
"Face must be from a local or a face neighbor element");
2719 auto add_quad_faces = [&
faces, &shared_faces, &v,
this]
2720 (
int elem,
int start,
int end,
const int fverts[][4])
2722 for (
int i = start; i < end; ++i)
2724 const int *
const fv = fverts[i];
2728 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2729 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2730 if (max < v[fv[3]]) { k = 3; }
2732 int v0 = -1, v1 = -1, v2 = -1;
2736 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2739 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2742 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2745 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2748 int lf =
faces->Index(v0, v1, v2);
2751 lf = shared_faces->Index(v0, v1, v2);
2789 MFEM_ABORT(
"Unexpected type of Element.");
2801 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2816 int el_nbr = i -
GetNE();
2823 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2824 "face_nbr_el_to_face not generated correctly.");
2833 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2834 "face_nbr_el_ori not generated correctly.");
2869 for (
int i = 0; i < s2l_face->
Size(); i++)
2884 for (
int i = 0; i < s2l_face->
Size(); i++)
2886 int lface = (*s2l_face)[i];
2887 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2916 const bool fill2 = mask & 10;
2954 MFEM_VERIFY(face_info.
Elem2Inf >= 0,
"The face must be shared.");
2972 FElTr.
Elem1 = &ElTr1;
2979 Elem2NbrNo = -1 - face_info.
Elem2No;
2986 FElTr.
Elem2 = &ElTr2;
3023 if (is_ghost || fill2)
3046 mfem::out <<
"\nInternal error: face id = " << FaceNo
3047 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
3049 MFEM_ABORT(
"internal error");
3072 "Mesh requires nodal Finite Element.");
3083 FElTr.
SetFE(face_el);
3113 for (
int j = 0; j < nv; j++)
3132 for (
int j = 0; j < n; j++)
3134 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
3142 MFEM_ABORT(
"Nodes are not ParGridFunction!");
3165 MFEM_ASSERT(
Dim > 1,
"");
3184 MFEM_ASSERT(
Dim > 1,
"");
3187 return sface < csize
3189 : shared.
slaves[sface - csize].index;
3202void Rotate3Indirect(
int &
a,
int &
b,
int &c,
3205 if (order[
a] < order[
b])
3207 if (order[
a] > order[c])
3214 if (order[
b] < order[c])
3235 Table *old_elem_vert = NULL;
3258 svert_comm.
Bcast(svert_master_index);
3271 for (
int i = 0; i <
vertices.Size(); i++)
3273 int s = lvert_svert[i];
3276 glob_vert_order[i] =
3277 (std::int64_t(svert_master_rank[s]) << 32) + svert_master_index[s];
3281 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
3293 int *v =
elements[i]->GetVertices();
3295 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3297 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
3299 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
3313 int *v =
boundary[i]->GetVertices();
3315 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3319 const bool check_consistency =
true;
3320 if (check_consistency)
3327 for (
int i = 0; i < stria_flag.
Size(); i++)
3330 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
3332 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
3336 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
3341 stria_comm.
Bcast(stria_master_flag);
3342 for (
int i = 0; i < stria_flag.
Size(); i++)
3345 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
3346 "inconsistent vertex ordering found, shared triangle "
3348 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
3349 <<
"local flag: " << stria_flag[i]
3350 <<
", master flag: " << stria_master_flag[i]);
3359 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3375 delete old_elem_vert;
3388 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3397 int uniform_refinement = 0;
3401 uniform_refinement = 1;
3412 for (
int i = 0; i < marked_el.
Size(); i++)
3418 for (
int i = 0; i < marked_el.
Size(); i++)
3427 for (
int i = 0; i < marked_el.
Size(); i++)
3444 int need_refinement;
3445 int max_faces_in_group = 0;
3451 face_splittings[i].
Reserve(faces_in_group);
3452 if (faces_in_group > max_faces_in_group)
3454 max_faces_in_group = faces_in_group;
3460 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3463#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3464 int ref_loops_all = 0, ref_loops_par = 0;
3468 need_refinement = 0;
3471 if (
elements[i]->NeedRefinement(v_to_v))
3473 need_refinement = 1;
3477#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3481 if (uniform_refinement)
3488 if (need_refinement == 0)
3490#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3494 const int tag = 293;
3503 if (faces_in_group == 0) {
continue; }
3505 face_splittings[i].
SetSize(0);
3506 for (
int j = 0; j < faces_in_group; j++)
3509 face_splittings[i]);
3513 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3514 MPI_UNSIGNED, neighbor, tag,
MyComm,
3515 &requests[req_count++]);
3523 if (faces_in_group == 0) {
continue; }
3527 MPI_Probe(neighbor, tag,
MyComm, &status);
3529 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3531 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3534 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3541 int nr = need_refinement;
3542 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3544 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3547 while (need_refinement == 1);
3549#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3551 int i = ref_loops_all;
3552 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3555 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3556 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3564 delete [] face_splittings;
3569 need_refinement = 0;
3572 if (
boundary[i]->NeedRefinement(v_to_v))
3574 need_refinement = 1;
3579 while (need_refinement == 1);
3584 " (NumOfBdrElements != boundary.Size())");
3611 int uniform_refinement = 0;
3615 uniform_refinement = 1;
3624 int *edge1 =
new int[nedges];
3625 int *edge2 =
new int[nedges];
3626 int *middle =
new int[nedges];
3628 for (
int i = 0; i < nedges; i++)
3630 edge1[i] = edge2[i] = middle[i] = -1;
3635 int *v =
elements[i]->GetVertices();
3636 for (
int j = 0; j < 3; j++)
3638 int ind = v_to_v(v[j], v[(j+1)%3]);
3639 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3644 for (
int i = 0; i < marked_el.
Size(); i++)
3650 int need_refinement;
3651 int edges_in_group, max_edges_in_group = 0;
3653 int **edge_splittings =
new int*[
GetNGroups()-1];
3657 edge_splittings[i] =
new int[edges_in_group];
3658 if (edges_in_group > max_edges_in_group)
3660 max_edges_in_group = edges_in_group;
3663 int neighbor, *iBuf =
new int[max_edges_in_group];
3667 MPI_Request request;
3672#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3673 int ref_loops_all = 0, ref_loops_par = 0;
3677 need_refinement = 0;
3678 for (
int i = 0; i < nedges; i++)
3680 if (middle[i] != -1 && edge1[i] != -1)
3682 need_refinement = 1;
3686#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3690 if (uniform_refinement)
3697 if (need_refinement == 0)
3699#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3708 edges_in_group = group_edges.
Size();
3710 if (edges_in_group != 0)
3712 for (
int j = 0; j < edges_in_group; j++)
3714 edge_splittings[i][j] =
3727 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3728 neighbor, 0,
MyComm, &request);
3736 edges_in_group = group_edges.
Size();
3737 if (edges_in_group != 0)
3748 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3749 MPI_ANY_TAG,
MyComm, &status);
3751 for (
int j = 0; j < edges_in_group; j++)
3753 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3756 int ii = v_to_v(v[0], v[1]);
3757#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3758 if (middle[ii] != -1)
3760 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3764 need_refinement = 1;
3776 int nr = need_refinement;
3777 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3780 while (need_refinement == 1);
3782#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3784 int i = ref_loops_all;
3785 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3788 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3789 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3797 delete [] edge_splittings[i];
3799 delete [] edge_splittings;
3804 int v1[2], v2[2],
bisect, temp;
3806 for (
int i = 0; i < temp; i++)
3808 int *v =
boundary[i]->GetVertices();
3809 bisect = v_to_v(v[0], v[1]);
3810 if (middle[
bisect] != -1)
3815 v1[0] = v[0]; v1[1] = middle[
bisect];
3816 v2[0] = middle[
bisect]; v2[1] = v[1];
3823 mfem_error(
"Only bisection of segment is implemented for bdr"
3856 for (
int j = 0; j < marked_el.
Size(); j++)
3858 int i = marked_el[j];
3861 int new_v = cnv + j, new_e = cne + j;
3870 static real_t seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3872 UseExternalData(seg_children, 1, 2, 3);
3893 MFEM_ABORT(
"NURBS meshes are not supported. Please project the "
3894 "NURBS to Nodes first with SetCurvature().");
3899 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3900 "(you need to initialize the ParMesh from a nonconforming "
3947 real_t threshold,
int nc_limit,
int op)
3949 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3950 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3951 "Project the NURBS to Nodes first.");
3964 for (
int i = 0; i < dt.
Size(); i++)
3966 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3971 if (error < threshold) { derefs.
Append(i); }
3975 if (!glob_size) {
return false; }
4022 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
4030 != NULL,
"internal error");
4064 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
4074 int *I_group_svert, *J_group_svert;
4075 int *I_group_sedge, *J_group_sedge;
4080 I_group_svert[0] = I_group_svert[1] = 0;
4081 I_group_sedge[0] = I_group_sedge[1] = 0;
4088 for (
int group = 0; group <
GetNGroups()-1; group++)
4098 const int ind = middle[v_to_v(v[0], v[1])];
4104 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4111 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4112 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4115 J = J_group_svert+I_group_svert[group];
4116 for (
int i = 0; i < group_verts.
Size(); i++)
4118 J[i] = group_verts[i];
4120 J = J_group_sedge+I_group_sedge[group];
4121 for (
int i = 0; i < group_edges.
Size(); i++)
4123 J[i] = group_edges[i];
4137 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
4139 Array<int> group_verts, group_edges, group_trias;
4158 I_group_svert[0] = 0;
4159 I_group_sedge[0] = 0;
4160 I_group_stria[0] = 0;
4162 for (
int group = 0; group <
GetNGroups()-1; group++)
4173 int ind = v_to_v.
FindId(v[0], v[1]);
4174 if (ind == -1) {
continue; }
4177 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4187 ind = v_to_v.
FindId(v[0], ind);
4195 ind = v_to_v.
FindId(v[0], v[1]);
4216 while (sedge_stack.
Size() > 0);
4223 int ind = v_to_v.
FindId(v[0], v[1]);
4224 if (ind == -1) {
continue; }
4227 const int edge_attr = 1;
4236 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
4237 ind = v_to_v.
FindId(v[0], v[1]);
4245 ind = v_to_v.
FindId(v[0], v[1]);
4263 v = sface_stack[sface_stack.
Size()-2].v;
4265 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
4268 while (sface_stack.
Size() > 0);
4274 ind = v_to_v.
FindId(v[0], v[1]);
4295 while (sedge_stack.
Size() > 0);
4298 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4299 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4300 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4302 J_group_svert.
Append(group_verts);
4303 J_group_sedge.
Append(group_edges);
4304 J_group_stria.
Append(group_trias);
4321 int *I_group_svert, *J_group_svert;
4322 int *I_group_sedge, *J_group_sedge;
4327 I_group_svert[0] = 0;
4328 I_group_sedge[0] = 0;
4335 for (
int group = 0; group <
GetNGroups()-1; group++)
4349 const int attr =
shared_edges[sedges[i]]->GetAttribute();
4355 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
4356 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
4358 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
4359 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4375 Array<int> group_verts, group_edges, group_trias, group_quads;
4377 int *I_group_svert, *J_group_svert;
4378 int *I_group_sedge, *J_group_sedge;
4379 int *I_group_stria, *J_group_stria;
4380 int *I_group_squad, *J_group_squad;
4387 I_group_svert[0] = 0;
4388 I_group_sedge[0] = 0;
4389 I_group_stria[0] = 0;
4390 I_group_squad[0] = 0;
4402 const int oface = old_nv + old_nedges;
4404 for (
int group = 0; group <
GetNGroups()-1; group++)
4416 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4420 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4430 const int stria = group_trias[i];
4433 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4434 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4435 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4436 const int edge_attr = 1;
4451 v[1] = m[0]; v[2] = m[2];
4452 group_trias.
Append(nst+0);
4453 group_trias.
Append(nst+1);
4454 group_trias.
Append(nst+2);
4462 const int squad = group_quads[i];
4464 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4466 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4470 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4471 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4472 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4473 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4474 const int edge_attr = 1;
4491 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4492 group_quads.
Append(nsq+0);
4493 group_quads.
Append(nsq+1);
4494 group_quads.
Append(nsq+2);
4498 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4499 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4500 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4501 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4503 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4504 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4505 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4506 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4525 const bool update_nodes =
false;
4550 auto faces_tbl = std::unique_ptr<STable3D>(
GetFacesTable());
4555 const bool update_nodes =
false;
4564 f2qf.
Size() ? &f2qf : NULL);
4573 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4581 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4587 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4593 os <<
"NETGEN_Neutral_Format\n";
4598 for (j = 0; j <
Dim; j++)
4612 for (j = 0; j < nv; j++)
4614 os <<
" " << ind[j]+1;
4627 for (j = 0; j < nv; j++)
4629 os <<
" " << ind[j]+1;
4640 for (j = 0; j < 3; j++)
4642 os <<
' ' << ind[j]+1;
4656 <<
" 0 0 0 0 0 0 0\n"
4657 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4659 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4660 <<
"0.0 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 0\n";
4667 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4675 os << i+1 <<
" " <<
elements[i]->GetAttribute();
4676 for (j = 0; j < nv; j++)
4678 os <<
" " << ind[j]+1;
4689 for (j = 0; j < nv; j++)
4691 os <<
" " << ind[j]+1;
4693 os <<
" 1.0 1.0 1.0 1.0\n";
4704 for (j = 0; j < 4; j++)
4706 os <<
' ' << ind[j]+1;
4708 os <<
" 1.0 1.0 1.0 1.0\n";
4717 os <<
"areamesh2\n\n";
4724 attr =
boundary[i]->GetAttribute();
4727 for (j = 0; j < v.
Size(); j++)
4729 os << v[j] + 1 <<
" ";
4739 for (j = 0; j < v.
Size(); j++)
4741 os << v[j] + 1 <<
" ";
4750 attr =
elements[i]->GetAttribute();
4766 for (j = 0; j < v.
Size(); j++)
4768 os << v[j] + 1 <<
" ";
4777 for (j = 0; j <
Dim; j++)
4802 int shared_bdr_attr;
4819 s2l_face = &nc_shared_faces;
4826 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4831 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4837 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4848 os << (!set_names ?
"MFEM mesh v1.0\n" :
"MFEM mesh v1.3\n");
4850 if (!comments.empty()) { os <<
'\n' << comments <<
'\n'; }
4854 "\n#\n# MFEM Geometry Types (see fem/geom.hpp):\n#\n"
4859 "# TETRAHEDRON = 4\n"
4864 os <<
"\ndimension\n" <<
Dim
4873 os <<
"\nattribute_sets\n";
4880 num_bdr_elems += s2l_face->
Size();
4882 os <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4896 shared_bdr_attr =
MyRank + 1;
4898 for (
int i = 0; i < s2l_face->
Size(); i++)
4901 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4908 os <<
"\nbdr_attribute_sets\n";
4935 os <<
"\nmfem_mesh_end" << endl;
4941 ostringstream fname_with_suffix;
4942 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
4943 ofstream ofs(fname_with_suffix.str().c_str());
4944 ofs.precision(precision);
4948#ifdef MFEM_USE_ADIOS2
4961 for (
int i = 0; i < nv; i++)
4969 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4977 os <<
"MFEM mesh v1.0\n";
4979 if (!comments.empty()) { os <<
'\n' << comments <<
'\n'; }
4983 "\n#\n# MFEM Geometry Types (see fem/geom.hpp):\n#\n"
4988 "# TETRAHEDRON = 4\n"
4993 os <<
"\ndimension\n" <<
Dim;
4997 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5000 os <<
"\n\nelements\n" << ne <<
'\n';
5004 os << 1 <<
' ' <<
elements[i]->GetGeometryType();
5008 for (j = 0; j < nv; j++)
5017 MPI_Recv(nv_ne, 2, MPI_INT,
p, 444,
MyComm, &status);
5021 MPI_Recv(&ints[0], ne, MPI_INT,
p, 445,
MyComm, &status);
5023 for (i = 0; i < ne; )
5026 os <<
p+1 <<
' ' << ints[i];
5029 for (j = 0; j < k; j++)
5031 os <<
' ' << vc + ints[i++];
5044 ne += 1 +
elements[i]->GetNVertices();
5047 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
5055 MFEM_ASSERT(ints.
Size() == ne,
"");
5058 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
5071 ne += list.
conforming.Size() + list.masters.Size() + list.slaves.Size();
5083 dump_element(
boundary[i], ints); ne++;
5121 MFEM_ABORT(
"invalid dimension: " <<
Dim);
5128 for (i = 0; i < list.conforming.Size(); i++)
5130 int index = list.conforming[i].index;
5133 for (i = 0; i < list.masters.Size(); i++)
5135 int index = list.masters[i].index;
5138 for (i = 0; i < list.slaves.Size(); i++)
5140 int index = list.slaves[i].index;
5145 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5148 os <<
"\nboundary\n" << k <<
'\n';
5154 MPI_Recv(nv_ne, 2, MPI_INT,
p, 446,
MyComm, &status);
5166 for (i = 0; i < ne; )
5169 os <<
p+1 <<
' ' << ints[i];
5172 for (j = 0; j < k; j++)
5174 os <<
' ' << vc + ints[i++];
5185 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
5196 os <<
"\nvertices\n" << nv <<
'\n';
5214 MPI_Recv(&nv, 1, MPI_INT,
p, 448,
MyComm, &status);
5221 for (i = 0; i < nv; i++)
5274 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
5286 serialmesh.
Printer(os,
"", comments);
5295 MFEM_ABORT(
"Nonconforming meshes and NURBS meshes are not yet supported.");
5304 MFEM_VERIFY(
int(ne_glob_l) == ne_glob_l,
5305 "overflow in the number of elements!");
5306 int ne_glob = (save_rank ==
MyRank) ?
int(ne_glob_l) : 0;
5309 long long nvertices_glob_l = 0;
5310 MPI_Reduce(&nvertices, &nvertices_glob_l, 1, MPI_LONG_LONG, MPI_SUM,
5312 int nvertices_glob = int(nvertices_glob_l);
5313 MFEM_VERIFY(nvertices_glob == nvertices_glob_l,
5314 "overflow in the number of vertices!");
5317 long long nbe_glob_l = 0;
5318 MPI_Reduce(&nbe, &nbe_glob_l, 1, MPI_LONG_LONG, MPI_SUM, save_rank,
MyComm);
5319 int nbe_glob = int(nbe_glob_l);
5320 MFEM_VERIFY(nbe_glob == nbe_glob_l,
5321 "overflow in the number of boundary elements!");
5338 const int attr =
elements[e]->GetAttribute();
5339 const int geom_type =
elements[e]->GetGeometryType();
5341 for (
int j = 0; j < dofs.
Size(); j++)
5353 if (
p == save_rank) {
continue; }
5354 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 444,
MyComm, &status);
5358 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 445,
MyComm, &status);
5360 for (
int i = 0; i < n_send_recv; )
5362 int attr = ints[i++];
5363 int geom_type = ints[i++];
5376 n_send_recv += 2 +
elements[e]->GetNVertices();
5378 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 444,
MyComm);
5383 const int attr =
elements[e]->GetAttribute();
5384 const int geom_type =
elements[e]->GetGeometryType();
5388 for (
int j = 0; j < dofs.
Size(); j++)
5395 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 445,
MyComm);
5404 const int attr =
boundary[e]->GetAttribute();
5405 const int geom_type =
boundary[e]->GetGeometryType();
5407 for (
int j = 0; j < dofs.
Size(); j++)
5419 if (
p == save_rank) {
continue; }
5420 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 446,
MyComm, &status);
5424 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 447,
MyComm, &status);
5426 for (
int i = 0; i < n_send_recv; )
5428 int attr = ints[i++];
5429 int geom_type = ints[i++];
5444 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 446,
MyComm);
5449 const int attr =
boundary[e]->GetAttribute();
5450 const int geom_type =
boundary[e]->GetGeometryType();
5454 for (
int j = 0; j < dofs.
Size(); j++)
5461 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 447,
MyComm);
5467 for (
int v = 0; v < nvertices_glob; v++)
5488 serialmesh.
GetNodes()->MakeOwner(fec_serial);
5504 serialmesh.
GetNodes()->SetSubVector(dofs, nodeloc);
5510 for (
int i = 0; i < ints.
Size(); i++)
5516 vdata_serial[d] = vdata[d];
5524 if (
p == save_rank) {
continue; }
5525 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 448,
MyComm, &status);
5532 for (
int i = 0; i < n_send_recv; )
5537 serialmesh.
GetNodes()->SetSubVector(dofs, &vert[i]);
5543 for (
int j = 0; j < ints_serial.
Size(); j++)
5548 vdata_serial[d] = vert[i++];
5571 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448,
MyComm);
5579 for (
int j = 0; j < nodeloc.
Size(); j++)
5587 for (
int i = 0; i < ints.
Size(); i++)
5614 ofs.precision(precision);
5621 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
5624 int i, j, k, nv, ne,
p;
5632 os <<
"NETGEN_Neutral_Format\n";
5635 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5639 for (j = 0; j <
Dim; j++)
5647 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5651 for (i = 0; i < nv; i++)
5653 for (j = 0; j <
Dim; j++)
5655 os <<
" " << vert[
Dim*i+j];
5663 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5670 for (j = 0; j < nv; j++)
5672 os <<
" " << ind[j]+1;
5679 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5680 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5682 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5683 for (i = 0; i < ne; i++)
5686 for (j = 0; j < 4; j++)
5688 os <<
" " << k+ints[i*4+j]+1;
5696 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5704 for (j = 0; j < nv; j++)
5706 os <<
" " << ind[j]+1;
5717 for (j = 0; j < 3; j++)
5719 os <<
' ' << ind[j]+1;
5727 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5728 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5730 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
5731 for (i = 0; i < ne; i++)
5734 for (j = 0; j < 3; j++)
5736 os <<
' ' << k+ints[i*3+j]+1;
5746 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5750 for (j = 0; j <
Dim; j++)
5758 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5765 for (j = 0; j < 4; j++)
5773 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5776 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5781 for (j = 0; j < 3; j++)
5786 for ( ; i < ne; i++)
5789 for (j = 0; j < 3; j++)
5794 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
5800 int i, j, k, nv, ne,
p;
5806 int TG_nv, TG_ne, TG_nbe;
5813 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5816 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
5817 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
5818 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
5819 <<
"0.0 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 0\n";
5827 <<
" " <<
vertices[i](2) <<
" 0.0\n";
5831 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5835 for (i = 0; i < nv; i++)
5837 os << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
5838 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
5848 os << i+1 <<
" " << 1;
5849 for (j = 0; j < nv; j++)
5851 os <<
" " << ind[j]+1;
5858 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5859 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5861 MPI_Recv(&ints[0], 8*ne, MPI_INT,
p, 447,
MyComm, &status);
5862 for (i = 0; i < ne; i++)
5864 os << i+1 <<
" " <<
p+1;
5865 for (j = 0; j < 8; j++)
5867 os <<
" " << k+ints[i*8+j]+1;
5882 for (j = 0; j < nv; j++)
5884 os <<
" " << ind[j]+1;
5886 os <<
" 1.0 1.0 1.0 1.0\n";
5896 for (j = 0; j < 4; j++)
5898 os <<
' ' << ind[j]+1;
5900 os <<
" 1.0 1.0 1.0 1.0\n";
5905 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5906 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5908 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5909 for (i = 0; i < ne; i++)
5912 for (j = 0; j < 4; j++)
5914 os <<
" " << k+ints[i*4+j]+1;
5916 os <<
" 1.0 1.0 1.0 1.0\n";
5926 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5931 for (j = 0; j <
Dim; j++)
5944 for (j = 0; j < 8; j++)
5953 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5958 for (j = 0; j < 4; j++)
5963 for ( ; i < ne; i++)
5966 for (j = 0; j < 4; j++)
5971 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
5977 int i, j, k, attr, nv, ne,
p;
5985 os <<
"areamesh2\n\n";
5989 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5994 attr =
boundary[i]->GetAttribute();
5997 for (j = 0; j < v.
Size(); j++)
5999 os << v[j] + 1 <<
" ";
6009 for (j = 0; j < v.
Size(); j++)
6011 os << v[j] + 1 <<
" ";
6018 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6019 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6021 MPI_Recv(&ints[0], 2*ne, MPI_INT,
p, 447,
MyComm, &status);
6022 for (i = 0; i < ne; i++)
6025 for (j = 0; j < 2; j++)
6027 os <<
" " << k+ints[i*2+j]+1;
6036 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6042 os << 1 <<
" " << 3 <<
" ";
6043 for (j = 0; j < v.
Size(); j++)
6045 os << v[j] + 1 <<
" ";
6052 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6053 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6055 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
6056 for (i = 0; i < ne; i++)
6058 os <<
p+1 <<
" " << 3;
6059 for (j = 0; j < 3; j++)
6061 os <<
" " << k+ints[i*3+j]+1;
6070 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6074 for (j = 0; j <
Dim; j++)
6082 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6086 for (i = 0; i < nv; i++)
6088 for (j = 0; j <
Dim; j++)
6090 os <<
" " << vert[
Dim*i+j];
6100 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6103 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6108 for (j = 0; j < 2; j++)
6113 for ( ; i < ne; i++)
6116 for (j = 0; j < 2; j++)
6121 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
6124 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6131 for (j = 0; j < 3; j++)
6139 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6143 for (j = 0; j <
Dim; j++)
6176 real_t h_min, h_max, kappa_min, kappa_max;
6194 real_t h_min, h_max, kappa_min, kappa_max, h,
kappa;
6198 os <<
"Parallel Mesh Stats:" <<
'\n';
6210 kappa_min = kappa_max =
kappa;
6214 if (h < h_min) { h_min = h; }
6215 if (h > h_max) { h_max = h; }
6216 if (
kappa < kappa_min) { kappa_min =
kappa; }
6217 if (
kappa > kappa_max) { kappa_max =
kappa; }
6221 real_t gh_min, gh_max, gk_min, gk_max;
6234 long long mindata[5], maxdata[5], sumdata[5];
6253 MPI_Reduce(ldata, mindata, 5, MPI_LONG_LONG, MPI_MIN, 0,
MyComm);
6254 MPI_Reduce(ldata, sumdata, 5, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
6255 MPI_Reduce(ldata, maxdata, 5, MPI_LONG_LONG, MPI_MAX, 0,
MyComm);
6261 << setw(12) <<
"minimum"
6262 << setw(12) <<
"average"
6263 << setw(12) <<
"maximum"
6264 << setw(12) <<
"total" <<
'\n';
6266 << setw(12) << mindata[0]
6267 << setw(12) << sumdata[0]/
NRanks
6268 << setw(12) << maxdata[0]
6269 << setw(12) << sumdata[0] <<
'\n';
6271 << setw(12) << mindata[1]
6272 << setw(12) << sumdata[1]/
NRanks
6273 << setw(12) << maxdata[1]
6274 << setw(12) << sumdata[1] <<
'\n';
6278 << setw(12) << mindata[2]
6279 << setw(12) << sumdata[2]/
NRanks
6280 << setw(12) << maxdata[2]
6281 << setw(12) << sumdata[2] <<
'\n';
6284 << setw(12) << mindata[3]
6285 << setw(12) << sumdata[3]/
NRanks
6286 << setw(12) << maxdata[3]
6287 << setw(12) << sumdata[3] <<
'\n';
6289 << setw(12) << mindata[4]
6290 << setw(12) << sumdata[4]/
NRanks
6291 << setw(12) << maxdata[4] <<
'\n';
6294 << setw(12) <<
"minimum"
6295 << setw(12) <<
"maximum" <<
'\n';
6297 << setw(12) << gh_min
6298 << setw(12) << gh_max <<
'\n';
6300 << setw(12) << gk_min
6301 << setw(12) << gk_max <<
'\n';
6308 long long local = value, global;
6309 MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM,
MyComm);
6318 Print(os, comments);
6332 Printer(os,
"mfem_serial_mesh_end", comments);
6340 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6346 os <<
"\n# group 0 has no shared entities\n";
6352 os <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
6353 for (
int i = 0; i < nv; i++)
6362 os <<
"\nshared_edges " << ne <<
'\n';
6363 for (
int i = 0; i < ne; i++)
6366 os << v[0] <<
' ' << v[1] <<
'\n';
6375 os <<
"\nshared_faces " << nt+nq <<
'\n';
6376 for (
int i = 0; i < nt; i++)
6380 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6383 for (
int i = 0; i < nq; i++)
6387 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6394 os <<
"\nmfem_mesh_end" << endl;
6399 bool high_order_output,
6400 int compression_level,
6403 int pad_digits_rank = 6;
6406 std::string::size_type pos = pathname.find_last_of(
'/');
6408 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
6412 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
6413 std::ofstream os(pvtu_name);
6416 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
6418 os <<
"<?xml version=\"1.0\"?>\n";
6419 os <<
"<VTKFile type=\"PUnstructuredGrid\"";
6420 os <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
6421 os <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
6423 os <<
"<PPoints>\n";
6424 os <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
6425 os <<
" Name=\"Points\" NumberOfComponents=\"3\""
6426 <<
" format=\"" << data_format <<
"\"/>\n";
6427 os <<
"</PPoints>\n";
6430 os <<
"\t<PDataArray type=\"Int32\" ";
6431 os <<
" Name=\"connectivity\" NumberOfComponents=\"1\""
6432 <<
" format=\"" << data_format <<
"\"/>\n";
6433 os <<
"\t<PDataArray type=\"Int32\" ";
6434 os <<
" Name=\"offsets\" NumberOfComponents=\"1\""
6435 <<
" format=\"" << data_format <<
"\"/>\n";
6436 os <<
"\t<PDataArray type=\"UInt8\" ";
6437 os <<
" Name=\"types\" NumberOfComponents=\"1\""
6438 <<
" format=\"" << data_format <<
"\"/>\n";
6439 os <<
"</PCells>\n";
6441 os <<
"<PCellData>\n";
6442 os <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute"
6443 <<
"\" NumberOfComponents=\"1\""
6444 <<
" format=\"" << data_format <<
"\"/>\n";
6445 os <<
"</PCellData>\n";
6447 for (
int ii=0; ii<
NRanks; ii++)
6449 std::string piece = fname +
".proc"
6451 os <<
"<Piece Source=\"" << piece <<
"\"/>\n";
6454 os <<
"</PUnstructuredGrid>\n";
6455 os <<
"</VTKFile>\n";
6459 std::string vtu_fname = pathname +
"/" + fname +
".proc"
6461 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
6468 const int npts = point_mat.
Width();
6469 if (npts == 0) {
return 0; }
6471 const bool no_warn =
false;
6478 Array<int> my_point_rank(npts), glob_point_rank(npts);
6479 for (
int k = 0; k < npts; k++)
6481 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
6484 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
6485 MPI_INT, MPI_MIN,
MyComm);
6488 for (
int k = 0; k < npts; k++)
6490 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
6494 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
6497 if (warn && pts_found != npts &&
MyRank == 0)
6499 MFEM_WARNING((npts-pts_found) <<
" points were not found");
6504static void PrintVertex(
const Vertex &v,
int space_dim, ostream &os)
6507 for (
int d = 1; d < space_dim; d++)
6515 stringstream out_name;
6516 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
6517 <<
".shared_entities";
6518 ofstream os(out_name.str().c_str());
6526 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6537 os <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
6538 for (
int i = 0; i < nv; i++)
6550 os <<
"\nshared_edges " << ne <<
'\n';
6551 for (
int i = 0; i < ne; i++)
6567 os <<
"\nshared_faces " << nt+nq <<
'\n';
6568 for (
int i = 0; i < nt; i++)
6573 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6576 for (
int j = 0; j < 3; j++)
6579 (j < 2) ? os <<
" | " : os <<
'\n';
6582 for (
int i = 0; i < nq; i++)
6587 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6590 for (
int j = 0; j < 4; j++)
6593 (j < 3) ? os <<
" | " : os <<
'\n';
6609 for (
int i=0; i<
GetNV(); ++i)
6634 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6662 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6675 for (
int i=0; i<
GetNE(); ++i)
6692 MFEM_VERIFY(bdr_marker.
Size() >= max_bdr_attr,
6693 "bdr_marker must be at least bdr_attriburtes.Max() in length");
6698 Array<bool> interior_bdr(max_bdr_attr); interior_bdr =
false;
6699 Array<bool> exterior_bdr(max_bdr_attr); exterior_bdr =
false;
6703 for (
int be = 0; be <
boundary.Size(); be++)
6705 const int bea =
boundary[be]->GetAttribute();
6707 if (bdr_marker[bea-1] != 0)
6711 if (ext_face_marker[
f] > 0)
6713 exterior_bdr[bea-1] =
true;
6717 interior_bdr[bea-1] =
true;
6726 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
6728 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
6732 for (
int b = 0;
b < max_bdr_attr;
b++)
6734 if (bdr_marker[
b] != 0 && glb_interior_bdr[
b])
6736 if (!excl || !glb_exterior_bdr[
b])
6748 MFEM_VERIFY(bdr_marker.
Size() >= max_bdr_attr,
6749 "bdr_marker must be at least bdr_attriburtes.Max() in length");
6754 Array<bool> interior_bdr(max_bdr_attr); interior_bdr =
false;
6755 Array<bool> exterior_bdr(max_bdr_attr); exterior_bdr =
false;
6759 for (
int be = 0; be <
boundary.Size(); be++)
6761 const int bea =
boundary[be]->GetAttribute();
6765 if (ext_face_marker[
f] > 0)
6767 exterior_bdr[bea-1] =
true;
6771 interior_bdr[bea-1] =
true;
6779 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
6781 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
6785 for (
int b = 0;
b < max_bdr_attr;
b++)
6787 if (bdr_marker[
b] == 0 && glb_exterior_bdr[
b])
6789 if (!excl || !glb_interior_bdr[
b])
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 MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
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 the vector dimension of the finite element space.
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_owned 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 Insert(const 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...
int Size() const
Return the number of integer sets in the list.
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.
virtual void GetExteriorFaceMarker(Array< int > &face_marker) const
Populate a marker array identifying exterior faces.
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
bool Conforming() const
Return a bool indicating whether this mesh is conforming.
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
Return a bool indicating whether this mesh is nonconforming.
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.
const FiniteElement * GetFaceNbrFE(int i, int ndofs=0) const
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.
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
Accessors for entities within a shared group structure.
void UniformRefinement2D() override
Refine a mixed 2D mesh uniformly.
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.
void MarkExternalBoundaries(Array< int > &bdr_marker, bool excl=true) const override
Mark boundary attributes of external boundaries.
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.
void GetExteriorFaceMarker(Array< int > &face_marker) const override
Populate a marker array identifying exterior faces.
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 BuildSharedFaceElems(int ntri_faces, int nquad_faces, const Mesh &mesh, const int *partitioning, const STable3D *faces_tbl, const Array< int > &face_group, const Array< int > &vert_global_local)
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)
void UnmarkInternalBoundaries(Array< int > &bdr_marker, bool excl=true) const override
Unmark boundary attributes of internal boundaries.
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)
Parallel version of NURBSExtension.
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...
double bisect(ElementTransformation &Tr, Coefficient *LvlSet)
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.
MemoryType
Memory types supported by MFEM.
@ HOST
Host memory; using new[] and delete[].
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.
std::array< int, NCMesh::MaxFaceNodes > nodes