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]];
1520 if (orig_mesh.
GetNodes() !=
nullptr)
1530 const int meshgen_save =
meshgen;
1560 int max_attr = attr.
Size() ? attr.
Max() : 1 ;
1561 int glb_max_attr = -1;
1562 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1566 bool *attr_marker =
new bool[glb_max_attr];
1567 bool *glb_attr_marker =
new bool[glb_max_attr];
1568 for (
int i = 0; i < glb_max_attr; i++)
1570 attr_marker[i] =
false;
1572 for (
int i = 0; i < attr.
Size(); i++)
1574 attr_marker[attr[i] - 1] =
true;
1576 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1577 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
1578 delete [] attr_marker;
1583 for (
int i = 0; i < glb_max_attr; i++)
1585 if (glb_attr_marker[i])
1590 delete [] glb_attr_marker;
1598 if (bdr_attrs_changed)
1603 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1607 if (elem_attrs_changed)
1612 MFEM_WARNING(
"Non-positive element attributes found!");
1620 int maxNumOfBdrElements;
1621 MPI_Allreduce(
const_cast<int*
>(&
NumOfBdrElements), &maxNumOfBdrElements, 1,
1622 MPI_INT, MPI_MAX,
MyComm);
1623 return (maxNumOfBdrElements > 0);
1631 o = (v[0] < v[1]) ? (+1) : (-1);
1640 "Expecting a triangular face.");
1651 "Expecting a quadrilateral face.");
1661 gr_sedge.
GetI()[0] = 0;
1670 gr_sedge.
GetJ()[k] =k;
1685 gr_svert.
GetI()[0] = 0;
1694 gr_svert.
GetJ()[k] = k;
1709 gr_squad.
GetI()[0] = 0;
1718 gr_squad.
GetJ()[k] = k;
1733 gr_stria.
GetI()[0] = 0;
1742 gr_stria.
GetJ()[k] = k;
1768 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1771 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1773 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1776 if (n == 0) {
continue; }
1778 for (
int j = 0; j < n; j++)
1780 sedge_ord_map[j].one = sedge_ord[k+j];
1781 sedge_ord_map[j].two = j;
1784 for (
int j = 0; j < n; j++)
1787 const int *v =
shared_edges[sedge_from]->GetVertices();
1788 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1790 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1791 for (
int j = 0; j < n; j++)
1795 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1809 ilen_len[j].one = order[j];
1810 ilen_len[j].two =
GetLength(i, it.Column());
1817 for (
int i = 1; i < order.
Size(); i++)
1819 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1833 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1845 elements[i]->MarkEdge(v_to_v, order);
1853 boundary[i]->MarkEdge(v_to_v, order);
1872 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1889 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1890 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1892 if (bit == 8*
sizeof(
unsigned))
1898 const face_t &
f = face_stack.
Last();
1899 int mid = v_to_v.
FindId(
f.one,
f.two);
1909 face_stack.
Append(face_t(
f.three,
f.one, mid));
1910 face_t &r = face_stack[face_stack.
Size()-2];
1911 r = face_t(r.two, r.three, mid);
1923 bool need_refinement = 0;
1924 face_stack.
Append(face_t(v[0], v[1], v[2]));
1925 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1927 if (bit == 8*
sizeof(
unsigned))
1929 code = codes[pos++];
1933 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1935 const face_t &
f = face_stack.
Last();
1936 int mid = v_to_v.
FindId(
f.one,
f.two);
1939 mid = v_to_v.
GetId(
f.one,
f.two);
1940 int ind[2] = {
f.one,
f.two };
1943 need_refinement = 1;
1946 face_stack.
Append(face_t(
f.three,
f.one, mid));
1947 face_t &r = face_stack[face_stack.
Size()-2];
1948 r = face_t(r.two, r.three, mid);
1950 return need_refinement;
1956 if (HYPRE_AssumedPartitionCheck())
1959 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_BIG_INT, MPI_SUM,
MyComm);
1960 for (
int i = 0; i < N; i++)
1963 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1964 (*offsets[i])[1] = temp[i];
1967 for (
int i = 0; i < N; i++)
1969 (*offsets[i])[2] = temp[i];
1971 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1972 "overflow in offsets");
1978 MPI_Allgather(loc_sizes, N, HYPRE_MPI_BIG_INT, temp.
GetData(), N,
1979 HYPRE_MPI_BIG_INT,
MyComm);
1980 for (
int i = 0; i < N; i++)
1985 for (
int j = 0; j <
NRanks; j++)
1987 offs[j+1] = offs[j] + temp[i+N*j];
1991 "overflow in offsets");
2023 int det_order =
Dim*mesh_poly_deg-1;
2028 auto detgf = std::make_unique<ParGridFunction>(fespace_det);
2029 detgf->MakeOwner(fec_det);
2038 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
2086 *new_nodes = *
Nodes;
2117 bool del_tables =
false;
2144 gr_sface =
new Table;
2179 if (del_tables) {
delete gr_sface; }
2190 int num_face_nbrs = 0;
2193 if (gr_sface->
RowSize(g-1) > 0)
2201 if (num_face_nbrs == 0)
2211 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
2213 if (gr_sface->
RowSize(g-1) > 0)
2218 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
2220 rank_group[counter].two = g;
2227 for (
int fn = 0; fn < num_face_nbrs; fn++)
2233 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2234 MPI_Request *send_requests = requests;
2235 MPI_Request *recv_requests = requests + num_face_nbrs;
2236 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2238 int *nbr_data =
new int[6*num_face_nbrs];
2239 int *nbr_send_data = nbr_data;
2240 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
2249 Table send_face_nbr_elemdata, send_face_nbr_facedata;
2253 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
2254 send_face_nbr_facedata.
MakeI(num_face_nbrs);
2255 for (
int fn = 0; fn < num_face_nbrs; fn++)
2258 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2259 int *sface = gr_sface->
GetRow(nbr_group-1);
2260 for (
int i = 0; i < num_sfaces; i++)
2262 int lface = s2l_face[sface[i]];
2264 if (el_marker[el] != fn)
2269 const int nv =
elements[el]->GetNVertices();
2270 const int *v =
elements[el]->GetVertices();
2271 for (
int j = 0; j < nv; j++)
2272 if (vertex_marker[v[j]] != fn)
2274 vertex_marker[v[j]] = fn;
2278 const int nf =
elements[el]->GetNFaces();
2287 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
2292 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2293 &send_requests[fn]);
2294 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2295 &recv_requests[fn]);
2299 send_face_nbr_elemdata.
MakeJ();
2300 send_face_nbr_facedata.
MakeJ();
2304 for (
int fn = 0; fn < num_face_nbrs; fn++)
2307 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2308 int *sface = gr_sface->
GetRow(nbr_group-1);
2309 for (
int i = 0; i < num_sfaces; i++)
2311 const int sf = sface[i];
2312 int lface = s2l_face[sf];
2314 if (el_marker[el] != fn)
2319 const int nv =
elements[el]->GetNVertices();
2320 const int *v =
elements[el]->GetVertices();
2321 for (
int j = 0; j < nv; j++)
2322 if (vertex_marker[v[j]] != fn)
2324 vertex_marker[v[j]] = fn;
2335 const int nf =
elements[el]->GetNFaces();
2346 const int *lf_v =
faces[lface]->GetVertices();
2366 for (
int fn = 0; fn < num_face_nbrs; fn++)
2372 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
2373 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
2374 int *facedata = send_face_nbr_facedata.
GetRow(fn);
2376 for (
int i = 0; i < num_verts; i++)
2378 vertex_marker[verts[i]] = i;
2381 for (
int el = 0; el < num_elems; el++)
2383 const int nv =
elements[elems[el]]->GetNVertices();
2386 for (
int j = 0; j < nv; j++)
2388 elemdata[j] = vertex_marker[elemdata[j]];
2390 elemdata += nv + nf;
2392 el_marker[elems[el]] = el;
2395 for (
int i = 0; i < num_sfaces; i++)
2397 facedata[2*i] = el_marker[facedata[2*i]];
2401 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2404 Table recv_face_nbr_elemdata;
2409 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2412 for (
int fn = 0; fn < num_face_nbrs; fn++)
2420 recv_face_nbr_elemdata.
MakeJ();
2422 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2425 for (
int fn = 0; fn < num_face_nbrs; fn++)
2430 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2431 send_face_nbr_elemdata.
RowSize(fn),
2432 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2434 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2435 recv_face_nbr_elemdata.
RowSize(fn),
2436 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2445 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2447 if (fn == MPI_UNDEFINED)
2455 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2457 for (
int i = 0; i < num_elems; i++)
2463 for (
int j = 0; j < nv; j++)
2465 recv_elemdata[j] += vert_off;
2468 recv_elemdata += nv;
2473 for (
int j = 0; j < nf; j++)
2475 fn_ori[j] = recv_elemdata[j];
2477 recv_elemdata += nf;
2484 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2487 recv_face_nbr_facedata.
SetSize(
2489 for (
int fn = 0; fn < num_face_nbrs; fn++)
2494 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2495 send_face_nbr_facedata.
RowSize(fn),
2496 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2499 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2500 send_face_nbr_facedata.
RowSize(fn),
2501 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2508 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2510 if (fn == MPI_UNDEFINED)
2517 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2518 int *sface = gr_sface->
GetRow(nbr_group-1);
2520 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2522 for (
int i = 0; i < num_sfaces; i++)
2524 const int sf = sface[i];
2525 int lface = s2l_face[sf];
2527 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2528 int info = facedata[2*i+1];
2536 int nbr_ori = info%64, nbr_v[4];
2537 const int *lf_v =
faces[lface]->GetVertices();
2544 for (
int j = 0; j < 3; j++)
2546 nbr_v[perm[j]] = sf_v[j];
2556 for (
int j = 0; j < 4; j++)
2558 nbr_v[perm[j]] = sf_v[j];
2564 info = 64*(info/64) + nbr_ori;
2570 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2587 else if (
Nodes == NULL)
2597 if (!num_face_nbrs) {
return; }
2599 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2600 MPI_Request *send_requests = requests;
2601 MPI_Request *recv_requests = requests + num_face_nbrs;
2602 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2606 for (
int i = 0; i < send_vertices.
Size(); i++)
2612 for (
int fn = 0; fn < num_face_nbrs; fn++)
2627 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2628 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2636 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2651 for (
int j = 0; j < 4; j++)
2654 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2660 for (
int j = 0; j < 2; j++)
2663 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2665 for (
int j = 2; j < 5; j++)
2668 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2674 for (
int j = 0; j < 1; j++)
2677 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2679 for (
int j = 1; j < 5; j++)
2682 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2690 for (
int j = 0; j < 6; j++)
2693 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2698 MFEM_ABORT(
"Unexpected type of Element.");
2707 const std::unique_ptr<STable3D> &faces,
2708 const std::unique_ptr<STable3D> &shared_faces,
2709 int elem,
int start,
int end,
const int fverts[][N])
2711 for (
int i = start; i < end; ++i)
2714 const auto fv = fverts[i];
2716 const Vert3 elem_fv(elem_vertices[fv[0]], elem_vertices[fv[1]],
2717 elem_vertices[fv[2]]);
2720 const int lf =
faces->Index(elem_fv.
v[0], elem_fv.
v[1], elem_fv.
v[2]);
2724 const int sf = lf < 0 ? shared_faces->Index(elem_fv.
v[0], elem_fv.
v[1],
2729 const int face_to_add = lf < 0 ? (sf >= 0 ? sf +
NumOfFaces : -1) : lf;
2731 MFEM_ASSERT(sf >= 0 ||
2732 lf >= 0,
"Face must be from a local or a face neighbor element");
2749 auto add_quad_faces = [&
faces, &shared_faces, &v,
this]
2750 (
int elem,
int start,
int end,
const int fverts[][4])
2752 for (
int i = start; i < end; ++i)
2754 const int *
const fv = fverts[i];
2758 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2759 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2760 if (max < v[fv[3]]) { k = 3; }
2762 int v0 = -1, v1 = -1, v2 = -1;
2766 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2769 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2772 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2775 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2778 int lf =
faces->Index(v0, v1, v2);
2781 lf = shared_faces->Index(v0, v1, v2);
2819 MFEM_ABORT(
"Unexpected type of Element.");
2831 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2846 int el_nbr = i -
GetNE();
2853 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2854 "face_nbr_el_to_face not generated correctly.");
2863 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2864 "face_nbr_el_ori not generated correctly.");
2899 for (
int i = 0; i < s2l_face->
Size(); i++)
2914 for (
int i = 0; i < s2l_face->
Size(); i++)
2916 int lface = (*s2l_face)[i];
2917 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2946 const bool fill2 = mask & 10;
2984 MFEM_VERIFY(face_info.
Elem2Inf >= 0,
"The face must be shared.");
3002 FElTr.
Elem1 = &ElTr1;
3009 Elem2NbrNo = -1 - face_info.
Elem2No;
3016 FElTr.
Elem2 = &ElTr2;
3053 if (is_ghost || fill2)
3076 mfem::out <<
"\nInternal error: face id = " << FaceNo
3077 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
3079 MFEM_ABORT(
"internal error");
3088 MFEM_ASSERT(FaceNo >=
GetNumFaces(),
"Not a ghost face.");
3112 "Mesh requires nodal Finite Element.");
3123 FElTr.
SetFE(face_el);
3153 for (
int j = 0; j < nv; j++)
3173 for (
int j = 0; j < n; j++)
3183 MFEM_ABORT(
"Nodes are not ParGridFunction!");
3206 MFEM_ASSERT(
Dim > 1,
"");
3225 MFEM_ASSERT(
Dim > 1,
"");
3228 return sface < csize
3230 : shared.
slaves[sface - csize].index;
3243void Rotate3Indirect(
int &
a,
int &
b,
int &c,
3246 if (order[
a] < order[
b])
3248 if (order[
a] > order[c])
3255 if (order[
b] < order[c])
3276 Table *old_elem_vert = NULL;
3299 svert_comm.
Bcast(svert_master_index);
3312 for (
int i = 0; i <
vertices.Size(); i++)
3314 int s = lvert_svert[i];
3317 glob_vert_order[i] =
3318 (std::int64_t(svert_master_rank[s]) << 32) + svert_master_index[s];
3322 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
3334 int *v =
elements[i]->GetVertices();
3336 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3338 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
3340 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
3354 int *v =
boundary[i]->GetVertices();
3356 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3360 const bool check_consistency =
true;
3361 if (check_consistency)
3368 for (
int i = 0; i < stria_flag.
Size(); i++)
3371 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
3373 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
3377 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
3382 stria_comm.
Bcast(stria_master_flag);
3383 for (
int i = 0; i < stria_flag.
Size(); i++)
3386 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
3387 "inconsistent vertex ordering found, shared triangle "
3389 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
3390 <<
"local flag: " << stria_flag[i]
3391 <<
", master flag: " << stria_master_flag[i]);
3400 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3416 delete old_elem_vert;
3429 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3438 int uniform_refinement = 0;
3442 uniform_refinement = 1;
3453 for (
int i = 0; i < marked_el.
Size(); i++)
3459 for (
int i = 0; i < marked_el.
Size(); i++)
3468 for (
int i = 0; i < marked_el.
Size(); i++)
3485 int need_refinement;
3486 int max_faces_in_group = 0;
3492 face_splittings[i].
Reserve(faces_in_group);
3493 if (faces_in_group > max_faces_in_group)
3495 max_faces_in_group = faces_in_group;
3501 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3504#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3505 int ref_loops_all = 0, ref_loops_par = 0;
3509 need_refinement = 0;
3512 if (
elements[i]->NeedRefinement(v_to_v))
3514 need_refinement = 1;
3518#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3522 if (uniform_refinement)
3529 if (need_refinement == 0)
3531#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3535 const int tag = 293;
3544 if (faces_in_group == 0) {
continue; }
3546 face_splittings[i].
SetSize(0);
3547 for (
int j = 0; j < faces_in_group; j++)
3550 face_splittings[i]);
3554 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3555 MPI_UNSIGNED, neighbor, tag,
MyComm,
3556 &requests[req_count++]);
3564 if (faces_in_group == 0) {
continue; }
3568 MPI_Probe(neighbor, tag,
MyComm, &status);
3570 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3572 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3575 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3582 int nr = need_refinement;
3583 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3585 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3588 while (need_refinement == 1);
3590#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3592 int i = ref_loops_all;
3593 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3596 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3597 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3605 delete [] face_splittings;
3610 need_refinement = 0;
3613 if (
boundary[i]->NeedRefinement(v_to_v))
3615 need_refinement = 1;
3620 while (need_refinement == 1);
3625 " (NumOfBdrElements != boundary.Size())");
3652 int uniform_refinement = 0;
3656 uniform_refinement = 1;
3665 int *edge1 =
new int[nedges];
3666 int *edge2 =
new int[nedges];
3667 int *middle =
new int[nedges];
3669 for (
int i = 0; i < nedges; i++)
3671 edge1[i] = edge2[i] = middle[i] = -1;
3676 int *v =
elements[i]->GetVertices();
3677 for (
int j = 0; j < 3; j++)
3679 int ind = v_to_v(v[j], v[(j+1)%3]);
3680 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3685 for (
int i = 0; i < marked_el.
Size(); i++)
3691 int need_refinement;
3692 int edges_in_group, max_edges_in_group = 0;
3694 int **edge_splittings =
new int*[
GetNGroups()-1];
3698 edge_splittings[i] =
new int[edges_in_group];
3699 if (edges_in_group > max_edges_in_group)
3701 max_edges_in_group = edges_in_group;
3704 int neighbor, *iBuf =
new int[max_edges_in_group];
3708 MPI_Request request;
3713#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3714 int ref_loops_all = 0, ref_loops_par = 0;
3718 need_refinement = 0;
3719 for (
int i = 0; i < nedges; i++)
3721 if (middle[i] != -1 && edge1[i] != -1)
3723 need_refinement = 1;
3727#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3731 if (uniform_refinement)
3738 if (need_refinement == 0)
3740#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3749 edges_in_group = group_edges.
Size();
3751 if (edges_in_group != 0)
3753 for (
int j = 0; j < edges_in_group; j++)
3755 edge_splittings[i][j] =
3768 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3769 neighbor, 0,
MyComm, &request);
3777 edges_in_group = group_edges.
Size();
3778 if (edges_in_group != 0)
3789 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3790 MPI_ANY_TAG,
MyComm, &status);
3792 for (
int j = 0; j < edges_in_group; j++)
3794 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3797 int ii = v_to_v(v[0], v[1]);
3798#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3799 if (middle[ii] != -1)
3801 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3805 need_refinement = 1;
3817 int nr = need_refinement;
3818 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3821 while (need_refinement == 1);
3823#ifdef MFEM_DEBUG_PARMESH_LOCALREF
3825 int i = ref_loops_all;
3826 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3829 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3830 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3838 delete [] edge_splittings[i];
3840 delete [] edge_splittings;
3845 int v1[2], v2[2],
bisect, temp;
3847 for (
int i = 0; i < temp; i++)
3849 int *v =
boundary[i]->GetVertices();
3850 bisect = v_to_v(v[0], v[1]);
3851 if (middle[
bisect] != -1)
3856 v1[0] = v[0]; v1[1] = middle[
bisect];
3857 v2[0] = middle[
bisect]; v2[1] = v[1];
3864 mfem_error(
"Only bisection of segment is implemented for bdr"
3897 for (
int j = 0; j < marked_el.
Size(); j++)
3899 int i = marked_el[j];
3902 int new_v = cnv + j, new_e = cne + j;
3911 static real_t seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3913 UseExternalData(seg_children, 1, 2, 3);
3930 std::set<int> &conflicts)
const
3932 MFEM_VERIFY(
pncmesh,
"AnisotropicConflict should be called only for NCMesh");
3941 MFEM_ABORT(
"NURBS meshes are not supported. Please project the "
3942 "NURBS to Nodes first with SetCurvature().");
3947 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3948 "(you need to initialize the ParMesh from a nonconforming "
3995 real_t threshold,
int nc_limit,
int op)
3997 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3998 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3999 "Project the NURBS to Nodes first.");
4012 for (
int i = 0; i < dt.
Size(); i++)
4014 if (nc_limit > 0 && !level_ok[i]) {
continue; }
4019 if (error < threshold) { derefs.
Append(i); }
4023 if (!glob_size) {
return false; }
4070 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
4078 != NULL,
"internal error");
4112 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
4122 int *I_group_svert, *J_group_svert;
4123 int *I_group_sedge, *J_group_sedge;
4128 I_group_svert[0] = I_group_svert[1] = 0;
4129 I_group_sedge[0] = I_group_sedge[1] = 0;
4136 for (
int group = 0; group <
GetNGroups()-1; group++)
4146 const int ind = middle[v_to_v(v[0], v[1])];
4152 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4159 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4160 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4163 J = J_group_svert+I_group_svert[group];
4164 for (
int i = 0; i < group_verts.
Size(); i++)
4166 J[i] = group_verts[i];
4168 J = J_group_sedge+I_group_sedge[group];
4169 for (
int i = 0; i < group_edges.
Size(); i++)
4171 J[i] = group_edges[i];
4185 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
4187 Array<int> group_verts, group_edges, group_trias;
4206 I_group_svert[0] = 0;
4207 I_group_sedge[0] = 0;
4208 I_group_stria[0] = 0;
4210 for (
int group = 0; group <
GetNGroups()-1; group++)
4221 int ind = v_to_v.
FindId(v[0], v[1]);
4222 if (ind == -1) {
continue; }
4225 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4235 ind = v_to_v.
FindId(v[0], ind);
4243 ind = v_to_v.
FindId(v[0], v[1]);
4264 while (sedge_stack.
Size() > 0);
4271 int ind = v_to_v.
FindId(v[0], v[1]);
4272 if (ind == -1) {
continue; }
4275 const int edge_attr = 1;
4284 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
4285 ind = v_to_v.
FindId(v[0], v[1]);
4293 ind = v_to_v.
FindId(v[0], v[1]);
4311 v = sface_stack[sface_stack.
Size()-2].v;
4313 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
4316 while (sface_stack.
Size() > 0);
4322 ind = v_to_v.
FindId(v[0], v[1]);
4343 while (sedge_stack.
Size() > 0);
4346 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4347 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4348 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4350 J_group_svert.
Append(group_verts);
4351 J_group_sedge.
Append(group_edges);
4352 J_group_stria.
Append(group_trias);
4369 int *I_group_svert, *J_group_svert;
4370 int *I_group_sedge, *J_group_sedge;
4375 I_group_svert[0] = 0;
4376 I_group_sedge[0] = 0;
4383 for (
int group = 0; group <
GetNGroups()-1; group++)
4397 const int attr =
shared_edges[sedges[i]]->GetAttribute();
4403 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
4404 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
4406 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
4407 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4423 Array<int> group_verts, group_edges, group_trias, group_quads;
4425 int *I_group_svert, *J_group_svert;
4426 int *I_group_sedge, *J_group_sedge;
4427 int *I_group_stria, *J_group_stria;
4428 int *I_group_squad, *J_group_squad;
4435 I_group_svert[0] = 0;
4436 I_group_sedge[0] = 0;
4437 I_group_stria[0] = 0;
4438 I_group_squad[0] = 0;
4450 const int oface = old_nv + old_nedges;
4452 for (
int group = 0; group <
GetNGroups()-1; group++)
4464 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4468 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4478 const int stria = group_trias[i];
4481 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4482 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4483 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4484 const int edge_attr = 1;
4499 v[1] = m[0]; v[2] = m[2];
4500 group_trias.
Append(nst+0);
4501 group_trias.
Append(nst+1);
4502 group_trias.
Append(nst+2);
4510 const int squad = group_quads[i];
4512 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4514 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4518 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4519 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4520 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4521 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4522 const int edge_attr = 1;
4539 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4540 group_quads.
Append(nsq+0);
4541 group_quads.
Append(nsq+1);
4542 group_quads.
Append(nsq+2);
4546 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4547 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4548 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4549 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4551 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4552 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4553 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4554 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4573 const bool update_nodes =
false;
4598 auto faces_tbl = std::unique_ptr<STable3D>(
GetFacesTable());
4603 const bool update_nodes =
false;
4612 f2qf.
Size() ? &f2qf : NULL);
4621 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4629 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4637 mfem::out <<
"\nRefineNURBSWithKVFactors : Not supported yet!\n";
4643 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4649 os <<
"NETGEN_Neutral_Format\n";
4654 for (j = 0; j <
Dim; j++)
4668 for (j = 0; j < nv; j++)
4670 os <<
" " << ind[j]+1;
4683 for (j = 0; j < nv; j++)
4685 os <<
" " << ind[j]+1;
4696 for (j = 0; j < 3; j++)
4698 os <<
' ' << ind[j]+1;
4712 <<
" 0 0 0 0 0 0 0\n"
4713 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4715 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4716 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4717 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4723 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4731 os << i+1 <<
" " <<
elements[i]->GetAttribute();
4732 for (j = 0; j < nv; j++)
4734 os <<
" " << ind[j]+1;
4745 for (j = 0; j < nv; j++)
4747 os <<
" " << ind[j]+1;
4749 os <<
" 1.0 1.0 1.0 1.0\n";
4760 for (j = 0; j < 4; j++)
4762 os <<
' ' << ind[j]+1;
4764 os <<
" 1.0 1.0 1.0 1.0\n";
4773 os <<
"areamesh2\n\n";
4780 attr =
boundary[i]->GetAttribute();
4783 for (j = 0; j < v.
Size(); j++)
4785 os << v[j] + 1 <<
" ";
4795 for (j = 0; j < v.
Size(); j++)
4797 os << v[j] + 1 <<
" ";
4806 attr =
elements[i]->GetAttribute();
4822 for (j = 0; j < v.
Size(); j++)
4824 os << v[j] + 1 <<
" ";
4833 for (j = 0; j <
Dim; j++)
4858 int shared_bdr_attr;
4861 int interface_bdr_attr = 0;
4884 s2l_face = &nc_shared_faces;
4891 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4896 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4902 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4926 os << (!set_names ?
"MFEM mesh v1.0\n" :
"MFEM mesh v1.3\n");
4928 if (!comments.empty()) { os <<
'\n' << comments <<
'\n'; }
4932 "\n#\n# MFEM Geometry Types (see fem/geom.hpp):\n#\n"
4937 "# TETRAHEDRON = 4\n"
4942 os <<
"\ndimension\n" <<
Dim
4951 os <<
"\nattribute_sets\n";
4958 num_bdr_elems += s2l_face->
Size();
4963 num_bdr_elems += (
Dim == 3 ? 2 : 1) * interface_faces.
Size();
4965 os <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4979 shared_bdr_attr =
MyRank + 1;
4981 for (
int i = 0; i < s2l_face->
Size(); i++)
4984 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4994 for (
int i = 0; i < interface_faces.
Size(); i++)
4996 const int f = interface_faces[i];
4997 const int *fv =
faces[
f]->GetVertices();
5000 Segment seg(fv, interface_bdr_attr);
5008 int v0[3] = { fv[0], fv[1], fv[2] };
5009 int v1[3] = { fv[0], fv[2], fv[1] };
5010 Triangle t0(v0, interface_bdr_attr);
5011 Triangle t1(v1, interface_bdr_attr);
5017 int v0[4] = { fv[0], fv[1], fv[2], fv[3] };
5018 int v1[4] = { fv[0], fv[3], fv[2], fv[1] };
5026 MFEM_ABORT(
"unsupported 3D face geometry type '"
5028 <<
"' while printing interface boundaries.");
5036 os <<
"\nbdr_attribute_sets\n";
5063 os <<
"\nmfem_mesh_end" << endl;
5069 ostringstream fname_with_suffix;
5070 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
5071 ofstream ofs(fname_with_suffix.str().c_str());
5072 ofs.precision(precision);
5076#ifdef MFEM_USE_ADIOS2
5090 for (
int i = 0; i < nv; i++)
5104 for (
int f = 0;
f < nf;
f++)
5109 if (e1 < 0) {
continue; }
5110 const int a1 =
elements[e1]->GetAttribute();
5123 "invalid face-neighbor index");
5127 if (a1 != a2) { interface.
Append(
f); }
5133 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1];
5140 int interface_bdr_attr = 0;
5144 os <<
"MFEM mesh v1.0\n";
5146 if (!comments.empty()) { os <<
'\n' << comments <<
'\n'; }
5150 "\n#\n# MFEM Geometry Types (see fem/geom.hpp):\n#\n"
5155 "# TETRAHEDRON = 4\n"
5160 os <<
"\ndimension\n" <<
Dim;
5164 MPI_Reduce(&loc_ne, &glob_ne, 1, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
5167 MFEM_VERIFY(
static_cast<int>(glob_ne) == glob_ne,
5168 "integer overflow detected!");
5169 os <<
"\n\nelements\n" << glob_ne <<
'\n';
5176 <<
' ' <<
elements[i]->GetGeometryType();
5180 for (j = 0; j < nv; j++)
5189 MPI_Recv(nv_ne, 2, MPI_INT,
p, 444,
MyComm, &status);
5195 MPI_Recv(&ints[0], ne, MPI_INT,
p, 445,
MyComm, &status);
5197 MFEM_VERIFY(
static_cast<int>(vc + nv) == (vc + nv),
5198 "integer overflow detected!");
5199 for (i = 0; i < ne; )
5208 for (j = 0; j < k; j++)
5210 os <<
' ' << vc + ints[i++];
5223 ne += 2 +
elements[i]->GetNVertices();
5226 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
5232 dump_element_with_attr(
elements[i], ints);
5234 MFEM_ASSERT(ints.
Size() == ne,
"");
5237 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
5251 interface_bdr_attr = max_bdr_attr + 1;
5263 ne += list.
conforming.Size() + list.masters.Size() + list.slaves.Size();
5270 ne += (
Dim == 3 ? 2 : 1) * interface_faces.
Size();
5280 dump_element_with_attr(
boundary[i], ints); ne++;
5285 constexpr int shared_attribute = 1;
5291 ints.
Append(shared_attribute);
5308 ints.
Append(shared_attribute);
5315 ints.
Append(shared_attribute);
5323 MFEM_ABORT(
"invalid dimension: " <<
Dim);
5330 for (i = 0; i < list.conforming.Size(); i++)
5332 int index = list.conforming[i].index;
5335 dump_element_with_attr(
faces[
index], ints); ne++;
5338 for (i = 0; i < list.masters.Size(); i++)
5340 int index = list.masters[i].index;
5343 dump_element_with_attr(
faces[
index], ints); ne++;
5346 for (i = 0; i < list.slaves.Size(); i++)
5348 int index = list.slaves[i].index;
5351 dump_element_with_attr(
faces[
index], ints); ne++;
5357 for (i = 0; i < interface_faces.
Size(); i++)
5359 const int f = interface_faces[i];
5360 const int *fv =
faces[
f]->GetVertices();
5363 Segment seg(fv, interface_bdr_attr);
5364 dump_element_with_attr(&seg, ints); ne++;
5371 int v0[3] = { fv[0], fv[1], fv[2] };
5372 int v1[3] = { fv[0], fv[2], fv[1] };
5373 Triangle t0(v0, interface_bdr_attr);
5374 Triangle t1(v1, interface_bdr_attr);
5375 dump_element_with_attr(&t0, ints); ne++;
5376 dump_element_with_attr(&t1, ints); ne++;
5380 int v0[4] = { fv[0], fv[1], fv[2], fv[3] };
5381 int v1[4] = { fv[0], fv[3], fv[2], fv[1] };
5384 dump_element_with_attr(&q0, ints); ne++;
5385 dump_element_with_attr(&q1, ints); ne++;
5389 MFEM_ABORT(
"unsupported 3D face geometry type '"
5391 <<
"' while printing interface boundaries.");
5397 long long loc_nb = ne, glob_nb = 0;
5398 MPI_Reduce(&loc_nb, &glob_nb, 1, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
5401 MFEM_VERIFY(
static_cast<int>(glob_nb) == glob_nb,
5402 "integer overflow detected!");
5403 os <<
"\nboundary\n" << glob_nb <<
'\n';
5409 MPI_Recv(nv_ne, 2, MPI_INT,
p, 446,
MyComm, &status);
5421 for (i = 0; i < ne; )
5430 for (j = 0; j < k; j++)
5432 os <<
' ' << vc + ints[i++];
5443 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
5452 MPI_Reduce(
const_cast<int*
>(&
NumOfVertices), &nv, 1, MPI_INT, MPI_SUM, 0,
5456 os <<
"\nvertices\n" << nv <<
'\n';
5474 MPI_Recv(&nv, 1, MPI_INT,
p, 448,
MyComm, &status);
5481 for (i = 0; i < nv; i++)
5534 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
5546 serialmesh.
Printer(os,
"", comments);
5555 MFEM_ABORT(
"Nonconforming meshes and NURBS meshes are not yet supported.");
5564 MFEM_VERIFY(
int(ne_glob_l) == ne_glob_l,
5565 "overflow in the number of elements!");
5566 int ne_glob = (save_rank ==
MyRank) ?
int(ne_glob_l) : 0;
5569 long long nvertices_glob_l = 0;
5570 MPI_Reduce(&nvertices, &nvertices_glob_l, 1, MPI_LONG_LONG, MPI_SUM,
5572 int nvertices_glob = int(nvertices_glob_l);
5573 MFEM_VERIFY(nvertices_glob == nvertices_glob_l,
5574 "overflow in the number of vertices!");
5577 long long nbe_glob_l = 0;
5578 MPI_Reduce(&nbe, &nbe_glob_l, 1, MPI_LONG_LONG, MPI_SUM, save_rank,
MyComm);
5579 int nbe_glob = int(nbe_glob_l);
5580 MFEM_VERIFY(nbe_glob == nbe_glob_l,
5581 "overflow in the number of boundary elements!");
5598 const int attr =
elements[e]->GetAttribute();
5599 const int geom_type =
elements[e]->GetGeometryType();
5601 for (
int j = 0; j < dofs.
Size(); j++)
5613 if (
p == save_rank) {
continue; }
5614 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 444,
MyComm, &status);
5618 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 445,
MyComm, &status);
5620 for (
int i = 0; i < n_send_recv; )
5622 int attr = ints[i++];
5623 int geom_type = ints[i++];
5636 n_send_recv += 2 +
elements[e]->GetNVertices();
5638 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 444,
MyComm);
5643 const int attr =
elements[e]->GetAttribute();
5644 const int geom_type =
elements[e]->GetGeometryType();
5648 for (
int j = 0; j < dofs.
Size(); j++)
5655 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 445,
MyComm);
5664 const int attr =
boundary[e]->GetAttribute();
5665 const int geom_type =
boundary[e]->GetGeometryType();
5667 for (
int j = 0; j < dofs.
Size(); j++)
5679 if (
p == save_rank) {
continue; }
5680 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 446,
MyComm, &status);
5684 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 447,
MyComm, &status);
5686 for (
int i = 0; i < n_send_recv; )
5688 int attr = ints[i++];
5689 int geom_type = ints[i++];
5704 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 446,
MyComm);
5709 const int attr =
boundary[e]->GetAttribute();
5710 const int geom_type =
boundary[e]->GetGeometryType();
5714 for (
int j = 0; j < dofs.
Size(); j++)
5721 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 447,
MyComm);
5727 for (
int v = 0; v < nvertices_glob; v++)
5748 serialmesh.
GetNodes()->MakeOwner(fec_serial);
5764 serialmesh.
GetNodes()->SetSubVector(dofs, nodeloc);
5770 for (
int i = 0; i < ints.
Size(); i++)
5776 vdata_serial[d] = vdata[d];
5784 if (
p == save_rank) {
continue; }
5785 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 448,
MyComm, &status);
5792 for (
int i = 0; i < n_send_recv; )
5797 serialmesh.
GetNodes()->SetSubVector(dofs, &vert[i]);
5803 for (
int j = 0; j < ints_serial.
Size(); j++)
5808 vdata_serial[d] = vert[i++];
5831 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448,
MyComm);
5839 for (
int j = 0; j < nodeloc.
Size(); j++)
5847 for (
int i = 0; i < ints.
Size(); i++)
5880 ofs.precision(precision);
5887 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
5890 int i, j, k, nv, ne,
p;
5898 os <<
"NETGEN_Neutral_Format\n";
5901 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5905 for (j = 0; j <
Dim; j++)
5913 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5917 for (i = 0; i < nv; i++)
5919 for (j = 0; j <
Dim; j++)
5921 os <<
" " << vert[
Dim*i+j];
5929 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5936 for (j = 0; j < nv; j++)
5938 os <<
" " << ind[j]+1;
5945 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5946 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5948 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5949 for (i = 0; i < ne; i++)
5952 for (j = 0; j < 4; j++)
5954 os <<
" " << k+ints[i*4+j]+1;
5962 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5970 for (j = 0; j < nv; j++)
5972 os <<
" " << ind[j]+1;
5983 for (j = 0; j < 3; j++)
5985 os <<
' ' << ind[j]+1;
5993 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5994 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5996 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
5997 for (i = 0; i < ne; i++)
6000 for (j = 0; j < 3; j++)
6002 os <<
' ' << k+ints[i*3+j]+1;
6012 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6016 for (j = 0; j <
Dim; j++)
6024 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6031 for (j = 0; j < 4; j++)
6039 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6042 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6047 for (j = 0; j < 3; j++)
6052 for ( ; i < ne; i++)
6055 for (j = 0; j < 3; j++)
6060 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
6066 int i, j, k, nv, ne,
p;
6072 int TG_nv, TG_ne, TG_nbe;
6079 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6082 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
6083 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
6084 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
6085 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
6086 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
6093 <<
" " <<
vertices[i](2) <<
" 0.0\n";
6097 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6101 for (i = 0; i < nv; i++)
6103 os << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
6104 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
6114 os << i+1 <<
" " << 1;
6115 for (j = 0; j < nv; j++)
6117 os <<
" " << ind[j]+1;
6124 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6125 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6127 MPI_Recv(&ints[0], 8*ne, MPI_INT,
p, 447,
MyComm, &status);
6128 for (i = 0; i < ne; i++)
6130 os << i+1 <<
" " <<
p+1;
6131 for (j = 0; j < 8; j++)
6133 os <<
" " << k+ints[i*8+j]+1;
6148 for (j = 0; j < nv; j++)
6150 os <<
" " << ind[j]+1;
6152 os <<
" 1.0 1.0 1.0 1.0\n";
6162 for (j = 0; j < 4; j++)
6164 os <<
' ' << ind[j]+1;
6166 os <<
" 1.0 1.0 1.0 1.0\n";
6171 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6172 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6174 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
6175 for (i = 0; i < ne; i++)
6178 for (j = 0; j < 4; j++)
6180 os <<
" " << k+ints[i*4+j]+1;
6182 os <<
" 1.0 1.0 1.0 1.0\n";
6192 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6197 for (j = 0; j <
Dim; j++)
6210 for (j = 0; j < 8; j++)
6219 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6224 for (j = 0; j < 4; j++)
6229 for ( ; i < ne; i++)
6232 for (j = 0; j < 4; j++)
6237 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
6243 int i, j, k, attr, nv, ne,
p;
6251 os <<
"areamesh2\n\n";
6255 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6260 attr =
boundary[i]->GetAttribute();
6263 for (j = 0; j < v.
Size(); j++)
6265 os << v[j] + 1 <<
" ";
6275 for (j = 0; j < v.
Size(); j++)
6277 os << v[j] + 1 <<
" ";
6284 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6285 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6287 MPI_Recv(&ints[0], 2*ne, MPI_INT,
p, 447,
MyComm, &status);
6288 for (i = 0; i < ne; i++)
6291 for (j = 0; j < 2; j++)
6293 os <<
" " << k+ints[i*2+j]+1;
6302 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6308 os << 1 <<
" " << 3 <<
" ";
6309 for (j = 0; j < v.
Size(); j++)
6311 os << v[j] + 1 <<
" ";
6318 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6319 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6321 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
6322 for (i = 0; i < ne; i++)
6324 os <<
p+1 <<
" " << 3;
6325 for (j = 0; j < 3; j++)
6327 os <<
" " << k+ints[i*3+j]+1;
6336 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6340 for (j = 0; j <
Dim; j++)
6348 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6352 for (i = 0; i < nv; i++)
6354 for (j = 0; j <
Dim; j++)
6356 os <<
" " << vert[
Dim*i+j];
6366 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6369 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6374 for (j = 0; j < 2; j++)
6379 for ( ; i < ne; i++)
6382 for (j = 0; j < 2; j++)
6387 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
6390 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6397 for (j = 0; j < 3; j++)
6405 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6409 for (j = 0; j <
Dim; j++)
6442 real_t h_min, h_max, kappa_min, kappa_max;
6460 real_t h_min, h_max, kappa_min, kappa_max, h,
kappa;
6464 os <<
"Parallel Mesh Stats:" <<
'\n';
6476 kappa_min = kappa_max =
kappa;
6480 if (h < h_min) { h_min = h; }
6481 if (h > h_max) { h_max = h; }
6482 if (
kappa < kappa_min) { kappa_min =
kappa; }
6483 if (
kappa > kappa_max) { kappa_max =
kappa; }
6487 real_t gh_min, gh_max, gk_min, gk_max;
6500 long long mindata[5], maxdata[5], sumdata[5];
6519 MPI_Reduce(ldata, mindata, 5, MPI_LONG_LONG, MPI_MIN, 0,
MyComm);
6520 MPI_Reduce(ldata, sumdata, 5, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
6521 MPI_Reduce(ldata, maxdata, 5, MPI_LONG_LONG, MPI_MAX, 0,
MyComm);
6527 << setw(12) <<
"minimum"
6528 << setw(12) <<
"average"
6529 << setw(12) <<
"maximum"
6530 << setw(12) <<
"total" <<
'\n';
6532 << setw(12) << mindata[0]
6533 << setw(12) << sumdata[0]/
NRanks
6534 << setw(12) << maxdata[0]
6535 << setw(12) << sumdata[0] <<
'\n';
6537 << setw(12) << mindata[1]
6538 << setw(12) << sumdata[1]/
NRanks
6539 << setw(12) << maxdata[1]
6540 << setw(12) << sumdata[1] <<
'\n';
6544 << setw(12) << mindata[2]
6545 << setw(12) << sumdata[2]/
NRanks
6546 << setw(12) << maxdata[2]
6547 << setw(12) << sumdata[2] <<
'\n';
6550 << setw(12) << mindata[3]
6551 << setw(12) << sumdata[3]/
NRanks
6552 << setw(12) << maxdata[3]
6553 << setw(12) << sumdata[3] <<
'\n';
6555 << setw(12) << mindata[4]
6556 << setw(12) << sumdata[4]/
NRanks
6557 << setw(12) << maxdata[4] <<
'\n';
6560 << setw(12) <<
"minimum"
6561 << setw(12) <<
"maximum" <<
'\n';
6563 << setw(12) << gh_min
6564 << setw(12) << gh_max <<
'\n';
6566 << setw(12) << gk_min
6567 << setw(12) << gk_max <<
'\n';
6574 long long local = value, global;
6575 MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM,
MyComm);
6584 Print(os, comments);
6598 Printer(os,
"mfem_serial_mesh_end", comments);
6606 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6612 os <<
"\n# group 0 has no shared entities\n";
6618 os <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
6619 for (
int i = 0; i < nv; i++)
6628 os <<
"\nshared_edges " << ne <<
'\n';
6629 for (
int i = 0; i < ne; i++)
6632 os << v[0] <<
' ' << v[1] <<
'\n';
6641 os <<
"\nshared_faces " << nt+nq <<
'\n';
6642 for (
int i = 0; i < nt; i++)
6646 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6649 for (
int i = 0; i < nq; i++)
6653 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6660 os <<
"\nmfem_mesh_end" << endl;
6665 bool high_order_output,
6666 int compression_level,
6669 int pad_digits_rank = 6;
6672 std::string::size_type pos = pathname.find_last_of(
'/');
6674 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
6678 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
6679 std::ofstream os(pvtu_name);
6682 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
6684 os <<
"<?xml version=\"1.0\"?>\n";
6685 os <<
"<VTKFile type=\"PUnstructuredGrid\"";
6686 os <<
" version =\"2.2\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
6687 os <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
6689 os <<
"<PPoints>\n";
6690 os <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
6691 os <<
" Name=\"Points\" NumberOfComponents=\"3\""
6692 <<
" format=\"" << data_format <<
"\"/>\n";
6693 os <<
"</PPoints>\n";
6696 os <<
"\t<PDataArray type=\"Int32\" ";
6697 os <<
" Name=\"connectivity\" NumberOfComponents=\"1\""
6698 <<
" format=\"" << data_format <<
"\"/>\n";
6699 os <<
"\t<PDataArray type=\"Int32\" ";
6700 os <<
" Name=\"offsets\" NumberOfComponents=\"1\""
6701 <<
" format=\"" << data_format <<
"\"/>\n";
6702 os <<
"\t<PDataArray type=\"UInt8\" ";
6703 os <<
" Name=\"types\" NumberOfComponents=\"1\""
6704 <<
" format=\"" << data_format <<
"\"/>\n";
6705 os <<
"</PCells>\n";
6707 os <<
"<PCellData>\n";
6708 os <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute"
6709 <<
"\" NumberOfComponents=\"1\""
6710 <<
" format=\"" << data_format <<
"\"/>\n";
6711 os <<
"</PCellData>\n";
6713 for (
int ii=0; ii<
NRanks; ii++)
6715 std::string piece = fname +
".proc"
6717 os <<
"<Piece Source=\"" << piece <<
"\"/>\n";
6720 os <<
"</PUnstructuredGrid>\n";
6721 os <<
"</VTKFile>\n";
6725 std::string vtu_fname = pathname +
"/" + fname +
".proc"
6727 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level,
6735 const int npts = point_mat.
Width();
6736 if (npts == 0) {
return 0; }
6738 const bool no_warn =
false;
6745 Array<int> my_point_rank(npts), glob_point_rank(npts);
6746 for (
int k = 0; k < npts; k++)
6748 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
6751 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
6752 MPI_INT, MPI_MIN,
MyComm);
6755 for (
int k = 0; k < npts; k++)
6757 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
6761 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
6764 if (warn && pts_found != npts &&
MyRank == 0)
6766 MFEM_WARNING((npts-pts_found) <<
" points were not found");
6771static void PrintVertex(
const Vertex &v,
int space_dim, ostream &os)
6774 for (
int d = 1; d < space_dim; d++)
6782 stringstream out_name;
6783 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
6784 <<
".shared_entities";
6785 ofstream os(out_name.str().c_str());
6793 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6804 os <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
6805 for (
int i = 0; i < nv; i++)
6817 os <<
"\nshared_edges " << ne <<
'\n';
6818 for (
int i = 0; i < ne; i++)
6834 os <<
"\nshared_faces " << nt+nq <<
'\n';
6835 for (
int i = 0; i < nt; i++)
6840 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6843 for (
int j = 0; j < 3; j++)
6846 (j < 2) ? os <<
" | " : os <<
'\n';
6849 for (
int i = 0; i < nq; i++)
6854 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6857 for (
int j = 0; j < 4; j++)
6860 (j < 3) ? os <<
" | " : os <<
'\n';
6876 for (
int i=0; i<
GetNV(); ++i)
6901 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6929 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6942 for (
int i=0; i<
GetNE(); ++i)
6959 MFEM_VERIFY(bdr_marker.
Size() >= max_bdr_attr,
6960 "bdr_marker must be at least bdr_attriburtes.Max() in length");
6965 Array<bool> interior_bdr(max_bdr_attr); interior_bdr =
false;
6966 Array<bool> exterior_bdr(max_bdr_attr); exterior_bdr =
false;
6970 for (
int be = 0; be <
boundary.Size(); be++)
6972 const int bea =
boundary[be]->GetAttribute();
6974 if (bdr_marker[bea-1] != 0)
6978 if (ext_face_marker[
f] > 0)
6980 exterior_bdr[bea-1] =
true;
6984 interior_bdr[bea-1] =
true;
6993 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
6995 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
6999 for (
int b = 0;
b < max_bdr_attr;
b++)
7001 if (bdr_marker[
b] != 0 && glb_interior_bdr[
b])
7003 if (!excl || !glb_exterior_bdr[
b])
7015 MFEM_VERIFY(bdr_marker.
Size() >= max_bdr_attr,
7016 "bdr_marker must be at least bdr_attriburtes.Max() in length");
7021 Array<bool> interior_bdr(max_bdr_attr); interior_bdr =
false;
7022 Array<bool> exterior_bdr(max_bdr_attr); exterior_bdr =
false;
7026 for (
int be = 0; be <
boundary.Size(); be++)
7028 const int bea =
boundary[be]->GetAttribute();
7032 if (ext_face_marker[
f] > 0)
7034 exterior_bdr[bea-1] =
true;
7038 interior_bdr[bea-1] =
true;
7046 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
7048 MFEM_MPI_CXX_BOOL, MPI_LOR,
MyComm);
7052 for (
int b = 0;
b < max_bdr_attr;
b++)
7054 if (bdr_marker[
b] == 0 && glb_exterior_bdr[
b])
7056 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.
virtual int GetMaxElementOrder() const
Return the maximum polynomial order over all elements.
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 char * Name[NumGeom]
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 the "id" of the item whose parents are p1, p2, this "id" corresponding to the index of the item i...
int FindId(int p1, int p2) const
Find the "id" of an item whose parents are p1, p2. Return -1 if it does not 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
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.
void MakeHigherOrderSimplicial_(const Mesh &orig_mesh, const Array< int > &parent_elements)
Helper function for constructing higher order nodes from a mesh transformed into simplices....
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
Array< int > MakeSimplicial_(const Mesh &orig_mesh, int *vglobal)
Internal helper user in MakeSimplicial (and ParMesh::MakeSimplicial). Optional return is used in asse...
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
Print the mesh to the given stream using the default MFEM mesh format.
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
Return the indices of the elements sharing face Face.
void Printer(std::ostream &os=mfem::out, std::string section_delimiter="", const std::string &comments="") const
If NURBS mesh, write NURBS format. If NCMesh, write mfem v1.1 format. If section_delimiter is empty,...
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)
virtual void SetAttributes(bool elem_attrs_changed=true, bool bdr_face_attrs_changed=true)
Determine the sets of unique attribute values in domain if elem_attrs_changed and boundary elements i...
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()
void UpdateJacobianDeterminantGF(GridFunction &detgf) const
Update Jacobian determinant values in a given gridfunction.
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.
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-provided DofTransformation object.
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-provided 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 NURBSUniformRefinement(int rf=2, real_t tol=1.0e-12) override
Refine NURBS mesh, with an optional refinement factor.
void SetAttributes(bool elem_attrs_changed=true, bool bdr_attrs_changed=true) override
Determine the sets of unique attribute values in domain if elem_attrs_changed and boundary elements i...
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.
void FindInterface(Array< int > &interface) const
bool AnisotropicConflict(const Array< Refinement > &refinements, std::set< int > &conflicts) const
Return true if the input array of refinements to be performed would result in conflicting anisotropic...
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 GetGhostFaceTransformation(int FaceNo, FaceElementTransformations &FElTr) const
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...
bool FaceIsTrueInterior(int FaceNo) const
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
long glob_offset_sequence
int GetLocalElementNum(long long global_element_num) const
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.
void PrintVTU(std::string pathname, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr_elements=false) override
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.
void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1, int pyrtype=1) override
Set the curvature of the mesh nodes using the given polynomial degree.
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().
std::unique_ptr< ParGridFunction > GetJacobianDeterminantGF() const
Create a ParGridFunction representing the Jacobian determinant. Parallel counterpart of Mesh::GetJaco...
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 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
Write the mesh to the stream 'out' on Process 0 in a form suitable for visualization.
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
void RefineNURBSWithKVFactors(int rf, const std::string &kvf) 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 AnisotropicConflict(const Array< Refinement > &refinements, std::set< int > &conflicts)
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.
Data type quadrilateral element.
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.
Table stores the connectivity of elements of TYPE I to elements of TYPE II. For example,...
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 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
Returns the number of connections in the table.
void AddColumnsInRow(int r, int ncol)
void AddAColumnInRow(int r)
void SetDims(int rows, int nnz)
Set the rows and the number of all connections for the table.
Data type tetrahedron element.
int GetRefinementFlag() const
void GetMarkedFace(const int face, int *fv) const
Data type triangle element.
void MarkEdge(DenseMatrix &pmat)
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
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 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)
MFEM_HOST_DEVICE int FlipIndexSign(int i)
Signed indices i -> -1 - i are used as a convention to encode orientation.
void Swap(T &a, T &b)
Swap objects of type T. The operation is performed using the most specialized swap function from the ...
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 T & AsConst(const T &a)
Utility function similar to std::as_const in c++17.
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