12 #include "../config/config.hpp" 17 #include "../fem/fem.hpp" 18 #include "../general/sets.hpp" 19 #include "../general/sort_pairs.hpp" 20 #include "../general/text.hpp" 21 #include "../general/globals.hpp" 31 ParMesh::ParMesh(
const ParMesh &pmesh,
bool copy_nodes)
33 group_svert(pmesh.group_svert),
34 group_sedge(pmesh.group_sedge),
35 group_stria(pmesh.group_stria),
36 group_squad(pmesh.group_squad),
37 face_nbr_el_to_face(NULL),
39 glob_offset_sequence(-1),
81 if (pmesh.
Nodes && copy_nodes)
109 : face_nbr_el_to_face(NULL)
110 , glob_elem_offset(-1)
111 , glob_offset_sequence(-1)
114 int *partitioning = NULL;
125 partitioning = partitioning_;
130 partitioning =
new int[mesh.
GetNE()];
131 for (
int i = 0; i < mesh.
GetNE(); i++)
161 partitioning = partitioning_;
175 Table *edge_element = NULL;
178 activeBdrElem, edge_element);
216 int nsedges =
FindSharedEdges(mesh, partitioning, edge_element, groups);
223 int ngroups = groups.
Size()-1, nstris, nsquads;
230 face_group, vert_global_local);
249 "invalid NURBS mesh");
275 int element_counter = 0;
276 for (
int i = 0; i < mesh.
GetNE(); i++)
278 if (partitioning[i] ==
MyRank)
281 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
282 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
293 if (partitioning != partitioning_)
295 delete [] partitioning;
303 const int* partitioning,
307 vert_global_local = -1;
309 int vert_counter = 0;
310 for (
int i = 0; i < mesh.
GetNE(); i++)
312 if (partitioning[i] ==
MyRank)
316 for (
int j = 0; j < vert.
Size(); j++)
318 if (vert_global_local[vert[j]] < 0)
320 vert_global_local[vert[j]] = vert_counter++;
328 for (
int i = 0; i < vert_global_local.
Size(); i++)
330 if (vert_global_local[i] >= 0)
332 vert_global_local[i] = vert_counter++;
338 for (
int i = 0; i < vert_global_local.
Size(); i++)
340 if (vert_global_local[i] >= 0)
354 for (
int i = 0; i < mesh.
GetNE(); i++)
356 if (partitioning[i] ==
MyRank) { nelems++; }
364 int element_counter = 0;
365 for (
int i = 0; i < mesh.
GetNE(); i++)
367 if (partitioning[i] ==
MyRank)
370 int *v =
elements[element_counter]->GetVertices();
371 int nv =
elements[element_counter]->GetNVertices();
372 for (
int j = 0; j < nv; j++)
374 v[j] = vert_global_local[v[j]];
380 return element_counter;
386 Table*& edge_element)
393 activeBdrElem =
false;
398 for (
int i = 0; i < mesh.
GetNBE(); i++)
400 int face, o, el1, el2;
403 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
408 activeBdrElem[i] =
true;
413 int bdrelem_counter = 0;
415 for (
int i = 0; i < mesh.
GetNBE(); i++)
417 int face, o, el1, el2;
420 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
423 int *v =
boundary[bdrelem_counter]->GetVertices();
424 int nv =
boundary[bdrelem_counter]->GetNVertices();
425 for (
int j = 0; j < nv; j++)
427 v[j] = vert_global_local[v[j]];
435 edge_element =
new Table;
438 for (
int i = 0; i < mesh.
GetNBE(); i++)
441 int el1 = edge_element->
GetRow(edge)[0];
442 if (partitioning[el1] ==
MyRank)
447 activeBdrElem[i] =
true;
452 int bdrelem_counter = 0;
454 for (
int i = 0; i < mesh.
GetNBE(); i++)
457 int el1 = edge_element->
GetRow(edge)[0];
458 if (partitioning[el1] ==
MyRank)
461 int *v =
boundary[bdrelem_counter]->GetVertices();
462 int nv =
boundary[bdrelem_counter]->GetNVertices();
463 for (
int j = 0; j < nv; j++)
465 v[j] = vert_global_local[v[j]];
473 for (
int i = 0; i < mesh.
GetNBE(); i++)
475 int vert = mesh.
boundary[i]->GetVertices()[0];
478 if (partitioning[el1] ==
MyRank)
484 int bdrelem_counter = 0;
486 for (
int i = 0; i < mesh.
GetNBE(); i++)
488 int vert = mesh.
boundary[i]->GetVertices()[0];
491 if (partitioning[el1] ==
MyRank)
494 int *v =
boundary[bdrelem_counter]->GetVertices();
495 v[0] = vert_global_local[v[0]];
512 for (
int i = 0; i < face_group.
Size(); i++)
519 el[0] = partitioning[el[0]];
520 el[1] = partitioning[el[1]];
525 face_group[i] = groups.
Insert(group) - 1;
532 Table*& edge_element,
538 int sedge_counter = 0;
541 edge_element =
new Table;
552 for (
int i = 0; i < edge_element->
Size(); i++)
554 int me = 0, others = 0;
555 for (
int j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
557 int k = edge_element->
GetJ()[j];
558 int rank = partitioning[k];
559 edge_element->
GetJ()[j] = rank;
578 edge_element->
GetRow(i)[0] = -1;
582 return sedge_counter;
591 int svert_counter = 0;
592 for (
int i = 0; i < vert_element->
Size(); i++)
594 int me = 0, others = 0;
595 for (
int j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
597 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
612 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
616 vert_element->
GetI()[i] = -1;
619 return svert_counter;
624 int &nstria,
int &nsquad)
630 for (
int i = 0; i < face_group.
Size(); i++)
632 if (face_group[i] >= 0)
649 for (
int i = 0; i < face_group.
Size(); i++)
651 if (face_group[i] >= 0)
672 for (
int i = 0; i < edge_element.
Size(); i++)
674 if (edge_element.
GetRow(i)[0] >= 0)
682 int sedge_counter = 0;
683 for (
int i = 0; i < edge_element.
Size(); i++)
685 if (edge_element.
GetRow(i)[0] >= 0)
698 for (
int i = 0; i < vert_element.
Size(); i++)
700 if (vert_element.
GetI()[i] >= 0)
708 int svert_counter = 0;
709 for (
int i = 0; i < vert_element.
Size(); i++)
711 if (vert_element.
GetI()[i] >= 0)
721 const Mesh& mesh,
int *partitioning,
730 if (
Dim < 3) {
return; }
732 int stria_counter = 0;
733 int squad_counter = 0;
734 for (
int i = 0; i < face_group.
Size(); i++)
736 if (face_group[i] < 0) {
continue; }
746 for (
int j = 0; j < 3; j++)
748 v[j] = vert_global_local[v[j]];
750 const int lface = (*faces_tbl)(v[0], v[1], v[2]);
766 if (
MyRank == partitioning[gl_el2])
768 std::swap(v[0], v[1]);
780 for (
int j = 0; j < 4; j++)
782 v[j] = vert_global_local[v[j]];
785 (*faces_tbl)(v[0], v[1], v[2], v[3]);
791 MFEM_ABORT(
"unknown face type: " << face->
GetType());
799 const Table* edge_element)
811 int sedge_counter = 0;
812 for (
int i = 0; i < edge_element->
Size(); i++)
814 if (edge_element->
GetRow(i)[0] >= 0)
820 new Segment(vert_global_local[vert[0]],
821 vert_global_local[vert[1]], 1);
823 sedge_ledge[sedge_counter] = v_to_v(vert_global_local[vert[0]],
824 vert_global_local[vert[1]]);
826 MFEM_VERIFY(
sedge_ledge[sedge_counter] >= 0,
"Error in v_to_v.");
841 int svert_counter = 0;
842 for (
int i = 0; i < vert_element->
Size(); i++)
844 if (vert_element->
GetI()[i] >= 0)
846 svert_lvert[svert_counter++] = vert_global_local[i];
854 : MyComm(pncmesh.MyComm)
855 , NRanks(pncmesh.NRanks)
856 , MyRank(pncmesh.MyRank)
857 , face_nbr_el_to_face(NULL)
858 , glob_elem_offset(-1)
859 , glob_offset_sequence(-1)
884 MPI_Allreduce(&loc_meshgen, &
meshgen, 1, MPI_INT, MPI_BOR,
MyComm);
898 const int l_edge = v_to_v(v[0], v[1]);
899 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
910 for (
int st = 0; st < nst; st++)
925 : face_nbr_el_to_face(NULL)
926 , glob_elem_offset(-1)
927 , glob_offset_sequence(-1)
937 const int gen_edges = 1;
939 Load(input, gen_edges, refine,
true);
943 bool fix_orientation)
950 Loader(input, generate_edges,
"mfem_serial_mesh_end");
962 MFEM_ASSERT(
pncmesh,
"internal error");
985 MFEM_VERIFY(ident ==
"communication_groups",
986 "input stream is not a parallel MFEM mesh");
994 input >> ident >> num_sverts;
995 MFEM_VERIFY(ident ==
"total_shared_vertices",
"invalid mesh file");
1004 input >> ident >> num_sedges;
1005 MFEM_VERIFY(ident ==
"total_shared_edges",
"invalid mesh file");
1019 input >> ident >> num_sface;
1020 MFEM_VERIFY(ident ==
"total_shared_faces",
"invalid mesh file");
1033 int svert_counter = 0, sedge_counter = 0;
1040 input >> ident >> g;
1043 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
1044 <<
", read group " << g << endl;
1050 input >> ident >> nv;
1051 MFEM_VERIFY(ident ==
"shared_vertices",
"invalid mesh file");
1052 nv += svert_counter;
1054 "incorrect number of total_shared_vertices");
1056 for ( ; svert_counter < nv; svert_counter++)
1065 input >> ident >> ne;
1066 MFEM_VERIFY(ident ==
"shared_edges",
"invalid mesh file");
1067 ne += sedge_counter;
1069 "incorrect number of total_shared_edges");
1071 for ( ; sedge_counter < ne; sedge_counter++)
1074 input >> v[0] >> v[1];
1081 input >> ident >> nf;
1082 for (
int i = 0; i < nf; i++)
1091 for (
int ii = 0; ii < 3; ii++) { input >> v[ii]; }
1096 for (
int ii = 0; ii < 4; ii++) { input >> v[ii]; }
1099 MFEM_ABORT(
"invalid shared face geometry: " << geom);
1110 "incorrect number of total_shared_faces");
1145 ref_factors = ref_factor;
1224 for (
int j = 0; j < orig_n_verts; j++)
1231 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1232 if (orig_n_edges > 0)
1237 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1239 for (
int e = 0; e < orig_n_edges; e++)
1244 for (
int j = 2; j < rdofs.
Size(); j++)
1252 for (
int k = 0; k < nvert; k++)
1255 v[k] = rdofs[c2h_map[cid]];
1271 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1273 for (
int f = 0;
f < orig_nt;
f++)
1278 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1287 for (
int k = 0; k < 2; k++)
1289 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1298 for (
int k = 0; k < nvert; k++)
1301 v[k] = rdofs[c2h_map[cid]];
1315 const int *c2h_map = rfec.
GetDofMap(geom, ref_factor);
1317 for (
int f = 0;
f < orig_nq;
f++)
1322 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1331 for (
int k = 0; k < 2; k++)
1333 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1342 for (
int k = 0; k < nvert; k++)
1345 v[k] = rdofs[c2h_map[cid]];
1392 for (
int iv=0; iv<orig_mesh.
GetNV(); ++iv)
1394 vglobal[iv] = fes.GetGlobalTDofNumber(iv);
1403 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1429 constexpr
int ntris = 2, nv_tri = 3, nv_quad = 4;
1432 for (
int gr = 1; gr < mesh.
GetNGroups(); gr++)
1436 for (
int j = 0; j < orig_n_verts; j++)
1438 fes.GetVertexDofs(orig_mesh.
GroupVertex(gr, j), dofs);
1443 const int orig_n_edges = orig_mesh.
GroupNEdges(gr);
1444 for (
int e = 0; e < orig_n_edges; e++)
1456 for (
int e = 0; e < orig_nt; e++)
1463 for (
int iv=0; iv<nv_tri; ++iv) { v2[iv] = v[iv]; }
1470 static const int trimap[12] =
1476 static const int diagmap[4] = { 0, 2, 1, 3 };
1477 for (
int f = 0;
f < orig_nq; ++
f)
1484 for (
int iv=0; iv<nv_quad; ++iv) { vg[iv] = vglobal[v[iv]]; }
1485 int iv_min = std::min_element(vg, vg+nv_quad) - vg;
1486 int isplit = (iv_min == 0 || iv_min == 2) ? 0 : 1;
1490 v_diag[0] = v[diagmap[0 + isplit*2]];
1491 v_diag[1] = v[diagmap[1 + isplit*2]];
1494 for (
int itri=0; itri<ntris; ++itri)
1498 for (
int iv=0; iv<nv_tri; ++iv)
1500 v2[iv] = v[trimap[itri + isplit*2 + iv*ntris*2]];
1518 const int meshgen_save =
meshgen;
1547 int max_attr = attr.
Size() ? attr.
Max() : 1 ;
1548 int glb_max_attr = -1;
1549 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1553 bool *attr_marker =
new bool[glb_max_attr];
1554 bool *glb_attr_marker =
new bool[glb_max_attr];
1555 for (
int i = 0; i < glb_max_attr; i++)
1557 attr_marker[i] =
false;
1559 for (
int i = 0; i < attr.
Size(); i++)
1561 attr_marker[attr[i] - 1] =
true;
1563 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1564 MPI_C_BOOL, MPI_LOR,
MyComm);
1565 delete [] attr_marker;
1570 for (
int i = 0; i < glb_max_attr; i++)
1572 if (glb_attr_marker[i])
1577 delete [] glb_attr_marker;
1588 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1594 MFEM_WARNING(
"Non-positive element attributes found!");
1601 int maxNumOfBdrElements;
1603 MPI_INT, MPI_MAX,
MyComm);
1604 return (maxNumOfBdrElements > 0);
1612 o = (v[0] < v[1]) ? (+1) : (-1);
1621 "Expecting a triangular face.");
1632 "Expecting a quadrilateral face.");
1642 gr_sedge.
GetI()[0] = 0;
1651 gr_sedge.
GetJ()[k] =k;
1666 gr_svert.
GetI()[0] = 0;
1675 gr_svert.
GetJ()[k] = k;
1690 gr_squad.
GetI()[0] = 0;
1699 gr_squad.
GetJ()[k] = k;
1714 gr_stria.
GetI()[0] = 0;
1723 gr_stria.
GetJ()[k] = k;
1749 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1752 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1754 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1757 if (n == 0) {
continue; }
1758 sedge_ord_map.SetSize(n);
1759 for (
int j = 0; j < n; j++)
1761 sedge_ord_map[j].one = sedge_ord[k+j];
1762 sedge_ord_map[j].two = j;
1764 SortPairs<int, int>(sedge_ord_map, n);
1765 for (
int j = 0; j < n; j++)
1768 const int *v =
shared_edges[sedge_from]->GetVertices();
1769 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1771 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1772 for (
int j = 0; j < n; j++)
1776 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1790 ilen_len[j].one = order[j];
1791 ilen_len[j].two =
GetLength(i, it.Column());
1795 SortPairs<int, double>(ilen_len, order.
Size());
1798 for (
int i = 1; i < order.
Size(); i++)
1800 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1810 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1813 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1825 elements[i]->MarkEdge(v_to_v, order);
1833 boundary[i]->MarkEdge(v_to_v, order);
1852 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1869 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1870 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1872 if (bit == 8*
sizeof(
unsigned))
1878 const face_t &
f = face_stack.
Last();
1879 int mid = v_to_v.
FindId(
f.one,
f.two);
1889 face_stack.
Append(face_t(
f.three,
f.one, mid));
1890 face_t &r = face_stack[face_stack.
Size()-2];
1891 r = face_t(r.two, r.three, mid);
1903 bool need_refinement = 0;
1904 face_stack.
Append(face_t(v[0], v[1], v[2]));
1905 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1907 if (bit == 8*
sizeof(
unsigned))
1909 code = codes[pos++];
1913 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1915 const face_t &
f = face_stack.
Last();
1916 int mid = v_to_v.
FindId(
f.one,
f.two);
1919 mid = v_to_v.
GetId(
f.one,
f.two);
1920 int ind[2] = {
f.one,
f.two };
1923 need_refinement = 1;
1926 face_stack.
Append(face_t(
f.three,
f.one, mid));
1927 face_t &r = face_stack[face_stack.
Size()-2];
1928 r = face_t(r.two, r.three, mid);
1930 return need_refinement;
1936 if (HYPRE_AssumedPartitionCheck())
1939 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_BIG_INT, MPI_SUM,
MyComm);
1940 for (
int i = 0; i < N; i++)
1943 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1944 (*offsets[i])[1] = temp[i];
1947 for (
int i = 0; i < N; i++)
1949 (*offsets[i])[2] = temp[i];
1951 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1952 "overflow in offsets");
1958 MPI_Allgather(loc_sizes, N, HYPRE_MPI_BIG_INT, temp.
GetData(), N,
1959 HYPRE_MPI_BIG_INT,
MyComm);
1960 for (
int i = 0; i < N; i++)
1965 for (
int j = 0; j <
NRanks; j++)
1967 offs[j+1] = offs[j] + temp[i+N*j];
1971 "overflow in offsets");
1996 for (
int j = 0; j < nv; j++)
2015 for (
int j = 0; j < n; j++)
2017 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
2025 MFEM_ABORT(
"Nodes are not ParGridFunction!");
2058 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
2103 *new_nodes = *
Nodes;
2136 bool del_tables =
false;
2163 gr_sface =
new Table;
2198 if (del_tables) {
delete gr_sface; }
2209 int num_face_nbrs = 0;
2212 if (gr_sface->
RowSize(g-1) > 0)
2220 if (num_face_nbrs == 0)
2230 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
2232 if (gr_sface->
RowSize(g-1) > 0)
2237 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
2239 rank_group[counter].two = g;
2244 SortPairs<int, int>(rank_group, rank_group.
Size());
2246 for (
int fn = 0; fn < num_face_nbrs; fn++)
2252 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2253 MPI_Request *send_requests = requests;
2254 MPI_Request *recv_requests = requests + num_face_nbrs;
2255 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2257 int *nbr_data =
new int[6*num_face_nbrs];
2258 int *nbr_send_data = nbr_data;
2259 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
2268 Table send_face_nbr_elemdata, send_face_nbr_facedata;
2272 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
2273 send_face_nbr_facedata.
MakeI(num_face_nbrs);
2274 for (
int fn = 0; fn < num_face_nbrs; fn++)
2277 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2278 int *sface = gr_sface->
GetRow(nbr_group-1);
2279 for (
int i = 0; i < num_sfaces; i++)
2281 int lface = s2l_face[sface[i]];
2283 if (el_marker[el] != fn)
2288 const int nv =
elements[el]->GetNVertices();
2289 const int *v =
elements[el]->GetVertices();
2290 for (
int j = 0; j < nv; j++)
2291 if (vertex_marker[v[j]] != fn)
2293 vertex_marker[v[j]] = fn;
2297 const int nf =
elements[el]->GetNFaces();
2306 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
2311 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2312 &send_requests[fn]);
2313 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
2314 &recv_requests[fn]);
2318 send_face_nbr_elemdata.
MakeJ();
2319 send_face_nbr_facedata.
MakeJ();
2323 for (
int fn = 0; fn < num_face_nbrs; fn++)
2326 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2327 int *sface = gr_sface->
GetRow(nbr_group-1);
2328 for (
int i = 0; i < num_sfaces; i++)
2330 const int sf = sface[i];
2331 int lface = s2l_face[sf];
2333 if (el_marker[el] != fn)
2338 const int nv =
elements[el]->GetNVertices();
2339 const int *v =
elements[el]->GetVertices();
2340 for (
int j = 0; j < nv; j++)
2341 if (vertex_marker[v[j]] != fn)
2343 vertex_marker[v[j]] = fn;
2354 const int nf =
elements[el]->GetNFaces();
2365 const int *lf_v =
faces[lface]->GetVertices();
2385 for (
int fn = 0; fn < num_face_nbrs; fn++)
2391 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
2392 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
2393 int *facedata = send_face_nbr_facedata.
GetRow(fn);
2395 for (
int i = 0; i < num_verts; i++)
2397 vertex_marker[verts[i]] = i;
2400 for (
int el = 0; el < num_elems; el++)
2402 const int nv =
elements[elems[el]]->GetNVertices();
2405 for (
int j = 0; j < nv; j++)
2407 elemdata[j] = vertex_marker[elemdata[j]];
2409 elemdata += nv + nf;
2411 el_marker[elems[el]] = el;
2414 for (
int i = 0; i < num_sfaces; i++)
2416 facedata[2*i] = el_marker[facedata[2*i]];
2420 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2423 Table recv_face_nbr_elemdata;
2428 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2431 for (
int fn = 0; fn < num_face_nbrs; fn++)
2439 recv_face_nbr_elemdata.
MakeJ();
2441 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2444 for (
int fn = 0; fn < num_face_nbrs; fn++)
2449 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2450 send_face_nbr_elemdata.
RowSize(fn),
2451 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2453 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2454 recv_face_nbr_elemdata.
RowSize(fn),
2455 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2465 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2467 if (fn == MPI_UNDEFINED)
2475 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2477 for (
int i = 0; i < num_elems; i++)
2483 for (
int j = 0; j < nv; j++)
2485 recv_elemdata[j] += vert_off;
2488 recv_elemdata += nv;
2493 for (
int j = 0; j < nf; j++)
2495 fn_ori[j] = recv_elemdata[j];
2497 recv_elemdata += nf;
2504 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2507 recv_face_nbr_facedata.
SetSize(
2509 for (
int fn = 0; fn < num_face_nbrs; fn++)
2514 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2515 send_face_nbr_facedata.
RowSize(fn),
2516 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2519 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2520 send_face_nbr_facedata.
RowSize(fn),
2521 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2528 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2530 if (fn == MPI_UNDEFINED)
2537 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2538 int *sface = gr_sface->
GetRow(nbr_group-1);
2540 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2542 for (
int i = 0; i < num_sfaces; i++)
2544 const int sf = sface[i];
2545 int lface = s2l_face[sf];
2547 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2548 int info = facedata[2*i+1];
2556 int nbr_ori = info%64, nbr_v[4];
2557 const int *lf_v =
faces[lface]->GetVertices();
2564 for (
int j = 0; j < 3; j++)
2566 nbr_v[perm[j]] = sf_v[j];
2576 for (
int j = 0; j < 4; j++)
2578 nbr_v[perm[j]] = sf_v[j];
2584 info = 64*(info/64) + nbr_ori;
2590 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2607 else if (
Nodes == NULL)
2617 if (!num_face_nbrs) {
return; }
2619 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2620 MPI_Request *send_requests = requests;
2621 MPI_Request *recv_requests = requests + num_face_nbrs;
2622 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2626 for (
int i = 0; i < send_vertices.Size(); i++)
2632 for (
int fn = 0; fn < num_face_nbrs; fn++)
2639 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
2644 MPI_DOUBLE, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2647 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2648 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2656 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2671 for (
int j = 0; j < 4; j++)
2674 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2680 for (
int j = 0; j < 2; j++)
2683 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2685 for (
int j = 2; j < 5; j++)
2688 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2694 for (
int j = 0; j < 1; j++)
2697 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2699 for (
int j = 1; j < 5; j++)
2702 sfaces_tbl->
Push(v[fv[0]], v[fv[1]], v[fv[2]]);
2710 for (
int j = 0; j < 6; j++)
2713 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2718 MFEM_ABORT(
"Unexpected type of Element.");
2742 for (
int j = 0; j < 4; j++)
2745 int lf = faces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2748 lf = sfaces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2760 for (
int j = 0; j < 2; j++)
2763 int lf = faces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2766 lf = sfaces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2774 for (
int j = 2; j < 5; j++)
2780 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2781 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2782 if (max < v[fv[3]]) { k = 3; }
2784 int v0 = -1, v1 = -1, v2 = -1;
2788 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2791 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2794 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2797 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2800 int lf = faces_tbl->
Index(v0, v1, v2);
2803 lf = sfaces_tbl->
Index(v0, v1, v2);
2815 for (
int j = 0; j < 1; j++)
2821 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2822 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2823 if (max < v[fv[3]]) { k = 3; }
2825 int v0 = -1, v1 = -1, v2 = -1;
2829 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2832 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2835 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2838 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2841 int lf = faces_tbl->
Index(v0, v1, v2);
2844 lf = sfaces_tbl->
Index(v0, v1, v2);
2852 for (
int j = 1; j < 5; j++)
2855 int lf = faces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2858 lf = sfaces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2872 for (
int j = 0; j < 6; j++)
2878 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2879 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2880 if (max < v[fv[3]]) { k = 3; }
2882 int v0 = -1, v1 = -1, v2 = -1;
2886 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2889 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2892 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2895 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2898 int lf = faces_tbl->
Index(v0, v1, v2);
2901 lf = sfaces_tbl->
Index(v0, v1, v2);
2912 MFEM_ABORT(
"Unexpected type of Element.");
2932 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2947 int el_nbr = i -
GetNE();
2954 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : " 2955 "face_nbr_el_to_face not generated.");
2969 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : " 2970 "face_nbr_el_to_face not generated.");
3005 for (
int i = 0; i < s2l_face->
Size(); i++)
3020 for (
int i = 0; i < s2l_face->
Size(); i++)
3022 int lface = (*s2l_face)[i];
3023 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
3048 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
3049 "Mesh requires nodal Finite Element.");
3051 #if 0 // TODO: handle the case of non-interpolatory Nodes 3060 FETr->
SetFE(face_el);
3074 const bool fill2 = mask & 10;
3091 MFEM_VERIFY(face_info.
Elem2Inf >= 0,
"The face must be shared.");
3104 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
3118 Elem2NbrNo = -1 - face_info.
Elem2No;
3162 if (is_ghost || fill2)
3185 mfem::out <<
"\nInternal error: face id = " << FaceNo
3186 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
3188 MFEM_ABORT(
"internal error");
3209 MFEM_ASSERT(
Dim > 1,
"");
3228 MFEM_ASSERT(
Dim > 1,
"");
3231 return sface < csize
3233 : shared.
slaves[sface - csize].index;
3246 void Rotate3Indirect(
int &
a,
int &
b,
int &c,
3249 if (order[
a] < order[
b])
3251 if (order[
a] > order[c])
3258 if (order[
b] < order[c])
3279 Table *old_elem_vert = NULL;
3303 svert_comm.
Bcast(svert_master_index);
3317 for (
int i = 0; i <
vertices.Size(); i++)
3319 int s = lvert_svert[i];
3322 glob_vert_order[i] =
3323 (std::int64_t(svert_master_rank[
s]) << 32) + svert_master_index[
s];
3327 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
3339 int *v =
elements[i]->GetVertices();
3341 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3343 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
3345 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
3359 int *v =
boundary[i]->GetVertices();
3361 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3365 const bool check_consistency =
true;
3366 if (check_consistency)
3373 for (
int i = 0; i < stria_flag.Size(); i++)
3376 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
3378 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
3382 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
3387 stria_comm.
Bcast(stria_master_flag);
3388 for (
int i = 0; i < stria_flag.Size(); i++)
3391 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
3392 "inconsistent vertex ordering found, shared triangle " 3394 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), " 3395 <<
"local flag: " << stria_flag[i]
3396 <<
", master flag: " << stria_master_flag[i]);
3405 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3421 delete old_elem_vert;
3434 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3443 int uniform_refinement = 0;
3447 uniform_refinement = 1;
3458 for (
int i = 0; i < marked_el.
Size(); i++)
3464 for (
int i = 0; i < marked_el.
Size(); i++)
3473 for (
int i = 0; i < marked_el.
Size(); i++)
3490 int need_refinement;
3491 int max_faces_in_group = 0;
3497 face_splittings[i].
Reserve(faces_in_group);
3498 if (faces_in_group > max_faces_in_group)
3500 max_faces_in_group = faces_in_group;
3506 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3509 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3510 int ref_loops_all = 0, ref_loops_par = 0;
3514 need_refinement = 0;
3517 if (
elements[i]->NeedRefinement(v_to_v))
3519 need_refinement = 1;
3523 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3527 if (uniform_refinement)
3534 if (need_refinement == 0)
3536 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3540 const int tag = 293;
3549 if (faces_in_group == 0) {
continue; }
3551 face_splittings[i].
SetSize(0);
3552 for (
int j = 0; j < faces_in_group; j++)
3555 face_splittings[i]);
3559 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3560 MPI_UNSIGNED, neighbor, tag,
MyComm,
3561 &requests[req_count++]);
3569 if (faces_in_group == 0) {
continue; }
3573 MPI_Probe(neighbor, tag,
MyComm, &status);
3575 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3577 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3580 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3587 int nr = need_refinement;
3588 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3590 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3593 while (need_refinement == 1);
3595 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3597 int i = ref_loops_all;
3598 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3601 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = " 3602 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3610 delete [] face_splittings;
3615 need_refinement = 0;
3618 if (
boundary[i]->NeedRefinement(v_to_v))
3620 need_refinement = 1;
3625 while (need_refinement == 1);
3630 " (NumOfBdrElements != boundary.Size())");
3657 int uniform_refinement = 0;
3661 uniform_refinement = 1;
3670 int *edge1 =
new int[nedges];
3671 int *edge2 =
new int[nedges];
3672 int *middle =
new int[nedges];
3674 for (
int i = 0; i < nedges; i++)
3676 edge1[i] = edge2[i] = middle[i] = -1;
3681 int *v =
elements[i]->GetVertices();
3682 for (
int j = 0; j < 3; j++)
3684 int ind = v_to_v(v[j], v[(j+1)%3]);
3685 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3690 for (
int i = 0; i < marked_el.
Size(); i++)
3696 int need_refinement;
3697 int edges_in_group, max_edges_in_group = 0;
3699 int **edge_splittings =
new int*[
GetNGroups()-1];
3703 edge_splittings[i] =
new int[edges_in_group];
3704 if (edges_in_group > max_edges_in_group)
3706 max_edges_in_group = edges_in_group;
3709 int neighbor, *iBuf =
new int[max_edges_in_group];
3713 MPI_Request request;
3718 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3719 int ref_loops_all = 0, ref_loops_par = 0;
3723 need_refinement = 0;
3724 for (
int i = 0; i < nedges; i++)
3726 if (middle[i] != -1 && edge1[i] != -1)
3728 need_refinement = 1;
3732 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3736 if (uniform_refinement)
3743 if (need_refinement == 0)
3745 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3754 edges_in_group = group_edges.
Size();
3756 if (edges_in_group != 0)
3758 for (
int j = 0; j < edges_in_group; j++)
3760 edge_splittings[i][j] =
3773 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3774 neighbor, 0,
MyComm, &request);
3782 edges_in_group = group_edges.
Size();
3783 if (edges_in_group != 0)
3794 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3795 MPI_ANY_TAG,
MyComm, &status);
3797 for (
int j = 0; j < edges_in_group; j++)
3799 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3802 int ii = v_to_v(v[0], v[1]);
3803 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3804 if (middle[ii] != -1)
3806 mfem_error(
"ParMesh::LocalRefinement (triangles) : " 3810 need_refinement = 1;
3812 for (
int c = 0; c < 2; c++)
3822 int nr = need_refinement;
3823 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3826 while (need_refinement == 1);
3828 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3830 int i = ref_loops_all;
3831 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3834 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = " 3835 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3843 delete [] edge_splittings[i];
3845 delete [] edge_splittings;
3850 int v1[2], v2[2], bisect, temp;
3852 for (
int i = 0; i < temp; i++)
3854 int *v =
boundary[i]->GetVertices();
3855 bisect = v_to_v(v[0], v[1]);
3856 if (middle[bisect] != -1)
3861 v1[0] = v[0]; v1[1] = middle[bisect];
3862 v2[0] = middle[bisect]; v2[1] = v[1];
3869 mfem_error(
"Only bisection of segment is implemented for bdr" 3902 for (
int j = 0; j < marked_el.
Size(); j++)
3904 int i = marked_el[j];
3907 int new_v = cnv + j, new_e = cne + j;
3916 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3918 UseExternalData(seg_children, 1, 2, 3);
3939 MFEM_ABORT(
"NURBS meshes are not supported. Please project the " 3940 "NURBS to Nodes first with SetCurvature().");
3945 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh " 3946 "(you need to initialize the ParMesh from a nonconforming " 3987 double threshold,
int nc_limit,
int op)
3989 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3990 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. " 3991 "Project the NURBS to Nodes first.");
4004 for (
int i = 0; i < dt.
Size(); i++)
4006 if (nc_limit > 0 && !level_ok[i]) {
continue; }
4011 if (error < threshold) { derefs.
Append(i); }
4015 if (!glob_size) {
return false; }
4058 MFEM_ABORT(
"Load balancing is currently not supported for conforming" 4065 MFEM_VERIFY(dynamic_cast<ParFiniteElementSpace*>(
Nodes->
FESpace())
4066 != NULL,
"internal error");
4096 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
4106 int *I_group_svert, *J_group_svert;
4107 int *I_group_sedge, *J_group_sedge;
4112 I_group_svert[0] = I_group_svert[1] = 0;
4113 I_group_sedge[0] = I_group_sedge[1] = 0;
4120 for (
int group = 0; group <
GetNGroups()-1; group++)
4130 const int ind = middle[v_to_v(v[0], v[1])];
4136 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4143 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4144 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4147 J = J_group_svert+I_group_svert[group];
4148 for (
int i = 0; i < group_verts.
Size(); i++)
4150 J[i] = group_verts[i];
4152 J = J_group_sedge+I_group_sedge[group];
4153 for (
int i = 0; i < group_edges.
Size(); i++)
4155 J[i] = group_edges[i];
4169 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
4171 Array<int> group_verts, group_edges, group_trias;
4190 I_group_svert[0] = 0;
4191 I_group_sedge[0] = 0;
4192 I_group_stria[0] = 0;
4194 for (
int group = 0; group <
GetNGroups()-1; group++)
4205 int ind = v_to_v.
FindId(v[0], v[1]);
4206 if (ind == -1) {
continue; }
4209 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4219 ind = v_to_v.
FindId(v[0], ind);
4227 ind = v_to_v.
FindId(v[0], v[1]);
4248 while (sedge_stack.
Size() > 0);
4255 int ind = v_to_v.
FindId(v[0], v[1]);
4256 if (ind == -1) {
continue; }
4259 const int edge_attr = 1;
4268 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
4269 ind = v_to_v.
FindId(v[0], v[1]);
4277 ind = v_to_v.
FindId(v[0], v[1]);
4295 v = sface_stack[sface_stack.
Size()-2].v;
4297 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
4300 while (sface_stack.
Size() > 0);
4306 ind = v_to_v.
FindId(v[0], v[1]);
4327 while (sedge_stack.
Size() > 0);
4330 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4331 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4332 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4334 J_group_svert.
Append(group_verts);
4335 J_group_sedge.
Append(group_edges);
4336 J_group_stria.
Append(group_trias);
4353 int *I_group_svert, *J_group_svert;
4354 int *I_group_sedge, *J_group_sedge;
4359 I_group_svert[0] = 0;
4360 I_group_sedge[0] = 0;
4367 for (
int group = 0; group <
GetNGroups()-1; group++)
4381 const int attr =
shared_edges[sedges[i]]->GetAttribute();
4387 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
4388 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
4390 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
4391 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4407 Array<int> group_verts, group_edges, group_trias, group_quads;
4409 int *I_group_svert, *J_group_svert;
4410 int *I_group_sedge, *J_group_sedge;
4411 int *I_group_stria, *J_group_stria;
4412 int *I_group_squad, *J_group_squad;
4419 I_group_svert[0] = 0;
4420 I_group_sedge[0] = 0;
4421 I_group_stria[0] = 0;
4422 I_group_squad[0] = 0;
4434 const int oface = old_nv + old_nedges;
4436 for (
int group = 0; group <
GetNGroups()-1; group++)
4448 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4452 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4462 const int stria = group_trias[i];
4465 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4466 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4467 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4468 const int edge_attr = 1;
4483 v[1] = m[0]; v[2] = m[2];
4484 group_trias.
Append(nst+0);
4485 group_trias.
Append(nst+1);
4486 group_trias.
Append(nst+2);
4494 const int squad = group_quads[i];
4496 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4498 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4502 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4503 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4504 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4505 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4506 const int edge_attr = 1;
4523 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4524 group_quads.
Append(nsq+0);
4525 group_quads.
Append(nsq+1);
4526 group_quads.
Append(nsq+2);
4530 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4531 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4532 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4533 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4535 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4536 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4537 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4538 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4557 const bool update_nodes =
false;
4587 const bool update_nodes =
false;
4596 f2qf.
Size() ? &f2qf : NULL);
4606 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4612 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4618 os <<
"NETGEN_Neutral_Format\n";
4623 for (j = 0; j <
Dim; j++)
4637 for (j = 0; j < nv; j++)
4639 os <<
" " << ind[j]+1;
4652 for (j = 0; j < nv; j++)
4654 os <<
" " << ind[j]+1;
4665 for (j = 0; j < 3; j++)
4667 os <<
' ' << ind[j]+1;
4681 <<
" 0 0 0 0 0 0 0\n" 4682 <<
"0 0 0 1 0 0 0 0 0 0 0\n" 4684 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n" 4685 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n" 4686 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4692 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4700 os << i+1 <<
" " <<
elements[i]->GetAttribute();
4701 for (j = 0; j < nv; j++)
4703 os <<
" " << ind[j]+1;
4714 for (j = 0; j < nv; j++)
4716 os <<
" " << ind[j]+1;
4718 os <<
" 1.0 1.0 1.0 1.0\n";
4729 for (j = 0; j < 4; j++)
4731 os <<
' ' << ind[j]+1;
4733 os <<
" 1.0 1.0 1.0 1.0\n";
4742 os <<
"areamesh2\n\n";
4749 attr =
boundary[i]->GetAttribute();
4752 for (j = 0; j < v.
Size(); j++)
4754 os << v[j] + 1 <<
" ";
4764 for (j = 0; j < v.
Size(); j++)
4766 os << v[j] + 1 <<
" ";
4775 attr =
elements[i]->GetAttribute();
4791 for (j = 0; j < v.
Size(); j++)
4793 os << v[j] + 1 <<
" ";
4802 for (j = 0; j <
Dim; j++)
4827 int shared_bdr_attr;
4844 s2l_face = &nc_shared_faces;
4851 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4856 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4862 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4870 os <<
"MFEM mesh v1.0\n";
4874 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n" 4879 "# TETRAHEDRON = 4\n" 4884 os <<
"\ndimension\n" <<
Dim 4894 num_bdr_elems += s2l_face->
Size();
4896 os <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4910 shared_bdr_attr =
MyRank + 1;
4912 for (
int i = 0; i < s2l_face->
Size(); i++)
4915 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4943 ostringstream fname_with_suffix;
4944 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
4945 ofstream ofs(fname_with_suffix.str().c_str());
4946 ofs.precision(precision);
4950 #ifdef MFEM_USE_ADIOS2 4963 for (
int i = 0; i < nv; i++)
4971 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4979 os <<
"MFEM mesh v1.0\n";
4983 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n" 4988 "# TETRAHEDRON = 4\n" 4993 os <<
"\ndimension\n" <<
Dim;
4997 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5000 os <<
"\n\nelements\n" << ne <<
'\n';
5004 os << 1 <<
' ' <<
elements[i]->GetGeometryType();
5008 for (j = 0; j < nv; j++)
5017 MPI_Recv(nv_ne, 2, MPI_INT,
p, 444,
MyComm, &status);
5021 MPI_Recv(&ints[0], ne, MPI_INT,
p, 445,
MyComm, &status);
5023 for (i = 0; i < ne; )
5026 os <<
p+1 <<
' ' << ints[i];
5029 for (j = 0; j < k; j++)
5031 os <<
' ' << vc + ints[i++];
5044 ne += 1 +
elements[i]->GetNVertices();
5047 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
5055 MFEM_ASSERT(ints.
Size() == ne,
"");
5058 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
5083 dump_element(
boundary[i], ints); ne++;
5121 MFEM_ABORT(
"invalid dimension: " <<
Dim);
5133 for (i = 0; i < list.
masters.Size(); i++)
5138 for (i = 0; i < list.
slaves.Size(); i++)
5145 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5148 os <<
"\nboundary\n" << k <<
'\n';
5154 MPI_Recv(nv_ne, 2, MPI_INT,
p, 446,
MyComm, &status);
5166 for (i = 0; i < ne; )
5169 os <<
p+1 <<
' ' << ints[i];
5172 for (j = 0; j < k; j++)
5174 os <<
' ' << vc + ints[i++];
5185 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
5196 os <<
"\nvertices\n" << nv <<
'\n';
5214 MPI_Recv(&nv, 1, MPI_INT,
p, 448,
MyComm, &status);
5220 for (i = 0; i < nv; i++)
5272 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
5293 MFEM_ABORT(
"Nonconforming meshes and NURBS meshes are not yet supported.");
5302 MFEM_VERIFY(
int(ne_glob_l) == ne_glob_l,
5303 "overflow in the number of elements!");
5304 int ne_glob = (save_rank ==
MyRank) ?
int(ne_glob_l) : 0;
5307 long long nvertices_glob_l = 0;
5308 MPI_Reduce(&nvertices, &nvertices_glob_l, 1, MPI_LONG_LONG, MPI_SUM,
5310 int nvertices_glob = int(nvertices_glob_l);
5311 MFEM_VERIFY(nvertices_glob == nvertices_glob_l,
5312 "overflow in the number of vertices!");
5315 long long nbe_glob_l = 0;
5316 MPI_Reduce(&nbe, &nbe_glob_l, 1, MPI_LONG_LONG, MPI_SUM, save_rank,
MyComm);
5317 int nbe_glob = int(nbe_glob_l);
5318 MFEM_VERIFY(nbe_glob == nbe_glob_l,
5319 "overflow in the number of boundary elements!");
5336 const int attr =
elements[e]->GetAttribute();
5337 const int geom_type =
elements[e]->GetGeometryType();
5339 for (
int j = 0; j < dofs.
Size(); j++)
5351 if (
p == save_rank) {
continue; }
5352 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 444,
MyComm, &status);
5356 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 445,
MyComm, &status);
5358 for (
int i = 0; i < n_send_recv; )
5360 int attr = ints[i++];
5361 int geom_type = ints[i++];
5374 n_send_recv += 2 +
elements[e]->GetNVertices();
5376 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 444,
MyComm);
5381 const int attr =
elements[e]->GetAttribute();
5382 const int geom_type =
elements[e]->GetGeometryType();;
5386 for (
int j = 0; j < dofs.
Size(); j++)
5393 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 445,
MyComm);
5402 const int attr =
boundary[e]->GetAttribute();
5403 const int geom_type =
boundary[e]->GetGeometryType();
5405 for (
int j = 0; j < dofs.
Size(); j++)
5417 if (
p == save_rank) {
continue; }
5418 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 446,
MyComm, &status);
5422 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 447,
MyComm, &status);
5424 for (
int i = 0; i < n_send_recv; )
5426 int attr = ints[i++];
5427 int geom_type = ints[i++];
5442 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 446,
MyComm);
5447 const int attr =
boundary[e]->GetAttribute();
5448 const int geom_type =
boundary[e]->GetGeometryType();
5452 for (
int j = 0; j < dofs.
Size(); j++)
5459 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 447,
MyComm);
5465 for (
int v = 0; v < nvertices_glob; v++)
5486 serialmesh.
GetNodes()->MakeOwner(fec_serial);
5502 serialmesh.
GetNodes()->SetSubVector(dofs, nodeloc);
5508 for (
int i = 0; i < ints.
Size(); i++)
5510 const double *vdata =
GetVertex(ints[i]);
5511 double *vdata_serial = serialmesh.
GetVertex(ints_serial[i]);
5514 vdata_serial[d] = vdata[d];
5522 if (
p == save_rank) {
continue; }
5523 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 448,
MyComm, &status);
5527 MPI_Recv(&vert[0], n_send_recv, MPI_DOUBLE,
p, 449,
MyComm, &status);
5529 for (
int i = 0; i < n_send_recv; )
5534 serialmesh.
GetNodes()->SetSubVector(dofs, &vert[i]);
5540 for (
int j = 0; j < ints_serial.
Size(); j++)
5542 double *vdata_serial = serialmesh.
GetVertex(ints_serial[j]);
5545 vdata_serial[d] = vert[i++];
5568 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448,
MyComm);
5576 for (
int j = 0; j < nodeloc.
Size(); j++)
5584 for (
int i = 0; i < ints.
Size(); i++)
5586 const double *vdata =
GetVertex(ints[i]);
5596 MPI_Send(&vert[0], n_send_recv, MPI_DOUBLE, save_rank, 449,
MyComm);
5610 ofs.precision(precision);
5617 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
5620 int i, j, k, nv, ne,
p;
5628 os <<
"NETGEN_Neutral_Format\n";
5631 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5635 for (j = 0; j <
Dim; j++)
5643 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5645 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE,
p, 445,
MyComm, &status);
5646 for (i = 0; i < nv; i++)
5648 for (j = 0; j <
Dim; j++)
5650 os <<
" " << vert[
Dim*i+j];
5658 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5665 for (j = 0; j < nv; j++)
5667 os <<
" " << ind[j]+1;
5674 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5675 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5677 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5678 for (i = 0; i < ne; i++)
5681 for (j = 0; j < 4; j++)
5683 os <<
" " << k+ints[i*4+j]+1;
5691 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5699 for (j = 0; j < nv; j++)
5701 os <<
" " << ind[j]+1;
5712 for (j = 0; j < 3; j++)
5714 os <<
' ' << ind[j]+1;
5722 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5723 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5725 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
5726 for (i = 0; i < ne; i++)
5729 for (j = 0; j < 3; j++)
5731 os <<
' ' << k+ints[i*3+j]+1;
5741 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5745 for (j = 0; j <
Dim; j++)
5753 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5760 for (j = 0; j < 4; j++)
5768 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5771 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5776 for (j = 0; j < 3; j++)
5781 for ( ; i < ne; i++)
5784 for (j = 0; j < 3; j++)
5789 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
5795 int i, j, k, nv, ne,
p;
5801 int TG_nv, TG_ne, TG_nbe;
5808 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5811 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n" 5812 <<
"0 0 0 1 0 0 0 0 0 0 0\n" 5813 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n" 5814 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n" 5815 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
5822 <<
" " <<
vertices[i](2) <<
" 0.0\n";
5826 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5828 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE,
p, 445,
MyComm, &status);
5829 for (i = 0; i < nv; i++)
5831 os << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
5832 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
5842 os << i+1 <<
" " << 1;
5843 for (j = 0; j < nv; j++)
5845 os <<
" " << ind[j]+1;
5852 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5853 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5855 MPI_Recv(&ints[0], 8*ne, MPI_INT,
p, 447,
MyComm, &status);
5856 for (i = 0; i < ne; i++)
5858 os << i+1 <<
" " <<
p+1;
5859 for (j = 0; j < 8; j++)
5861 os <<
" " << k+ints[i*8+j]+1;
5876 for (j = 0; j < nv; j++)
5878 os <<
" " << ind[j]+1;
5880 os <<
" 1.0 1.0 1.0 1.0\n";
5890 for (j = 0; j < 4; j++)
5892 os <<
' ' << ind[j]+1;
5894 os <<
" 1.0 1.0 1.0 1.0\n";
5899 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5900 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5902 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5903 for (i = 0; i < ne; i++)
5906 for (j = 0; j < 4; j++)
5908 os <<
" " << k+ints[i*4+j]+1;
5910 os <<
" 1.0 1.0 1.0 1.0\n";
5920 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5925 for (j = 0; j <
Dim; j++)
5937 for (j = 0; j < 8; j++)
5946 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5951 for (j = 0; j < 4; j++)
5956 for ( ; i < ne; i++)
5959 for (j = 0; j < 4; j++)
5964 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
5970 int i, j, k, attr, nv, ne,
p;
5978 os <<
"areamesh2\n\n";
5982 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5987 attr =
boundary[i]->GetAttribute();
5990 for (j = 0; j < v.
Size(); j++)
5992 os << v[j] + 1 <<
" ";
6002 for (j = 0; j < v.
Size(); j++)
6004 os << v[j] + 1 <<
" ";
6011 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6012 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6014 MPI_Recv(&ints[0], 2*ne, MPI_INT,
p, 447,
MyComm, &status);
6015 for (i = 0; i < ne; i++)
6018 for (j = 0; j < 2; j++)
6020 os <<
" " << k+ints[i*2+j]+1;
6029 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6035 os << 1 <<
" " << 3 <<
" ";
6036 for (j = 0; j < v.
Size(); j++)
6038 os << v[j] + 1 <<
" ";
6045 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6046 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6048 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
6049 for (i = 0; i < ne; i++)
6051 os <<
p+1 <<
" " << 3;
6052 for (j = 0; j < 3; j++)
6054 os <<
" " << k+ints[i*3+j]+1;
6063 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6067 for (j = 0; j <
Dim; j++)
6075 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6077 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE,
p, 445,
MyComm, &status);
6078 for (i = 0; i < nv; i++)
6080 for (j = 0; j <
Dim; j++)
6082 os <<
" " << vert[
Dim*i+j];
6092 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6095 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6100 for (j = 0; j < 2; j++)
6105 for ( ; i < ne; i++)
6108 for (j = 0; j < 2; j++)
6113 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
6116 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6123 for (j = 0; j < 3; j++)
6131 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6135 for (j = 0; j <
Dim; j++)
6157 MPI_Allreduce(p_min.
GetData(), gp_min.
GetData(), sdim, MPI_DOUBLE,
6159 MPI_Allreduce(p_max.
GetData(), gp_max.
GetData(), sdim, MPI_DOUBLE,
6164 double &gk_min,
double &gk_max)
6166 double h_min, h_max, kappa_min, kappa_max;
6170 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
6171 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
6172 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
6173 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
6180 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
6184 os <<
"Parallel Mesh Stats:" <<
'\n';
6190 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
6196 kappa_min = kappa_max =
kappa;
6200 if (h < h_min) { h_min = h; }
6201 if (h > h_max) { h_max = h; }
6202 if (
kappa < kappa_min) { kappa_min =
kappa; }
6203 if (
kappa > kappa_max) { kappa_max =
kappa; }
6207 double gh_min, gh_max, gk_min, gk_max;
6208 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
6209 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
6210 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
6211 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
6216 long long mindata[5], maxdata[5], sumdata[5];
6235 MPI_Reduce(ldata, mindata, 5, MPI_LONG_LONG, MPI_MIN, 0,
MyComm);
6236 MPI_Reduce(ldata, sumdata, 5, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
6237 MPI_Reduce(ldata, maxdata, 5, MPI_LONG_LONG, MPI_MAX, 0,
MyComm);
6243 << setw(12) <<
"minimum" 6244 << setw(12) <<
"average" 6245 << setw(12) <<
"maximum" 6246 << setw(12) <<
"total" <<
'\n';
6248 << setw(12) << mindata[0]
6249 << setw(12) << sumdata[0]/
NRanks 6250 << setw(12) << maxdata[0]
6251 << setw(12) << sumdata[0] <<
'\n';
6253 << setw(12) << mindata[1]
6254 << setw(12) << sumdata[1]/
NRanks 6255 << setw(12) << maxdata[1]
6256 << setw(12) << sumdata[1] <<
'\n';
6260 << setw(12) << mindata[2]
6261 << setw(12) << sumdata[2]/
NRanks 6262 << setw(12) << maxdata[2]
6263 << setw(12) << sumdata[2] <<
'\n';
6266 << setw(12) << mindata[3]
6267 << setw(12) << sumdata[3]/
NRanks 6268 << setw(12) << maxdata[3]
6269 << setw(12) << sumdata[3] <<
'\n';
6271 << setw(12) << mindata[4]
6272 << setw(12) << sumdata[4]/
NRanks 6273 << setw(12) << maxdata[4] <<
'\n';
6276 << setw(12) <<
"minimum" 6277 << setw(12) <<
"maximum" <<
'\n';
6279 << setw(12) << gh_min
6280 << setw(12) << gh_max <<
'\n';
6282 << setw(12) << gk_min
6283 << setw(12) << gk_max <<
'\n';
6290 long long local = value, global;
6291 MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM,
MyComm);
6314 Printer(os,
"mfem_serial_mesh_end");
6322 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6333 os <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
6334 for (
int i = 0; i < nv; i++)
6343 os <<
"\nshared_edges " << ne <<
'\n';
6344 for (
int i = 0; i < ne; i++)
6347 os << v[0] <<
' ' << v[1] <<
'\n';
6356 os <<
"\nshared_faces " << nt+nq <<
'\n';
6357 for (
int i = 0; i < nt; i++)
6361 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6364 for (
int i = 0; i < nq; i++)
6368 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6375 os <<
"\nmfem_mesh_end" << endl;
6380 bool high_order_output,
6381 int compression_level,
6384 int pad_digits_rank = 6;
6387 std::string::size_type pos = pathname.find_last_of(
'/');
6389 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
6393 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
6394 std::ofstream os(pvtu_name);
6397 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
6399 os <<
"<?xml version=\"1.0\"?>\n";
6400 os <<
"<VTKFile type=\"PUnstructuredGrid\"";
6401 os <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
6402 os <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
6404 os <<
"<PPoints>\n";
6405 os <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
6406 os <<
" Name=\"Points\" NumberOfComponents=\"3\"" 6407 <<
" format=\"" << data_format <<
"\"/>\n";
6408 os <<
"</PPoints>\n";
6411 os <<
"\t<PDataArray type=\"Int32\" ";
6412 os <<
" Name=\"connectivity\" NumberOfComponents=\"1\"" 6413 <<
" format=\"" << data_format <<
"\"/>\n";
6414 os <<
"\t<PDataArray type=\"Int32\" ";
6415 os <<
" Name=\"offsets\" NumberOfComponents=\"1\"" 6416 <<
" format=\"" << data_format <<
"\"/>\n";
6417 os <<
"\t<PDataArray type=\"UInt8\" ";
6418 os <<
" Name=\"types\" NumberOfComponents=\"1\"" 6419 <<
" format=\"" << data_format <<
"\"/>\n";
6420 os <<
"</PCells>\n";
6422 os <<
"<PCellData>\n";
6423 os <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute" 6424 <<
"\" NumberOfComponents=\"1\"" 6425 <<
" format=\"" << data_format <<
"\"/>\n";
6426 os <<
"</PCellData>\n";
6428 for (
int ii=0; ii<
NRanks; ii++)
6430 std::string piece = fname +
".proc" 6432 os <<
"<Piece Source=\"" << piece <<
"\"/>\n";
6435 os <<
"</PUnstructuredGrid>\n";
6436 os <<
"</VTKFile>\n";
6440 std::string vtu_fname = pathname +
"/" + fname +
".proc" 6442 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
6449 const int npts = point_mat.
Width();
6450 if (npts == 0) {
return 0; }
6452 const bool no_warn =
false;
6459 Array<int> my_point_rank(npts), glob_point_rank(npts);
6460 for (
int k = 0; k < npts; k++)
6462 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
6465 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
6466 MPI_INT, MPI_MIN,
MyComm);
6469 for (
int k = 0; k < npts; k++)
6471 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
6475 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
6478 if (warn && pts_found != npts &&
MyRank == 0)
6480 MFEM_WARNING((npts-pts_found) <<
" points were not found");
6485 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &os)
6488 for (
int d = 1; d < space_dim; d++)
6496 stringstream out_name;
6497 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank 6498 <<
".shared_entities";
6499 ofstream os(out_name.str().c_str());
6507 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6518 os <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
6519 for (
int i = 0; i < nv; i++)
6531 os <<
"\nshared_edges " << ne <<
'\n';
6532 for (
int i = 0; i < ne; i++)
6548 os <<
"\nshared_faces " << nt+nq <<
'\n';
6549 for (
int i = 0; i < nt; i++)
6554 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6557 for (
int j = 0; j < 3; j++)
6560 (j < 2) ? os <<
" | " : os <<
'\n';
6563 for (
int i = 0; i < nq; i++)
6568 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6571 for (
int j = 0; j < 4; j++)
6574 (j < 3) ? os <<
" | " : os <<
'\n';
6590 for (
int i=0; i<
GetNV(); ++i)
6615 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6643 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6656 for (
int i=0; i<
GetNE(); ++i)
Abstract class for all finite elements.
void UniformRefinement3D() override
Refine a mixed 3D mesh uniformly.
void PrintAsOneXG(std::ostream &out=mfem::out)
Old mesh format (Netgen/Truegrid) version of 'PrintAsOne'.
void Create(ListOfIntegerSets &groups, int mpitag)
Set up the group topology given the list of sets of shared entities.
void Loader(std::istream &input, int generate_edges=0, std::string parse_tag="")
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
void GetSharedQuadrilateralDofs(int group, int fi, Array< int > &dofs) const
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
void GetConformingSharedStructures(class ParMesh &pmesh)
int GetGroupMasterRank(int g) const
Return the rank of the group master for group 'g'.
int GetNPoints() const
Returns the number of the points in the integration rule.
void Recreate(const int n, const int *p)
Create an integer set from C-array 'p' of 'n' integers. Overwrites any existing set data...
void GetGhostFaceTransformation(FaceElementTransformations *FETr, Element::Type face_type, Geometry::Type face_geom)
Class for an integration rule - an Array of IntegrationPoint.
const FiniteElementSpace * GetNodalFESpace() const
void GetSharedVertexCommunicator(int ordering, GroupCommunicator &svert_comm) const
Get the shared vertices GroupCommunicator.
void LoadSharedEntities(std::istream &input)
long glob_offset_sequence
void UniformRefineGroups2D(int old_nv)
void FreeElement(Element *E)
FaceElementTransformations * GetSharedFaceTransformationsByLocalIndex(int FaceNo, bool fill2=true)
void ExchangeFaceNbrData()
int CheckElementOrientation(bool fix_it=true)
Check (and optionally attempt to fix) the orientation of the elements.
void SetSize(int dim, int connections_per_row)
Set the size and the number of connections for the table.
ParMesh & operator=(ParMesh &&mesh)
Move assignment operator.
void GetSharedQuadCommunicator(int ordering, GroupCommunicator &squad_comm) const
Get the shared face quadrilaterals GroupCommunicator.
void MakeRefined_(ParMesh &orig_mesh, int ref_factor, int ref_type)
Internal function used in ParMesh::MakeRefined (and related constructor)
virtual Element * Duplicate(Mesh *m) const =0
int FindSharedVertices(const int *partition, Table *vertex_element, ListOfIntegerSets &groups)
void AddColumnsInRow(int r, int ncol)
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void UniformRefinement3D_base(Array< int > *f2qf=NULL, DSTable *v_to_v_p=NULL, bool update_nodes=true)
void PrintInfo(std::ostream &out=mfem::out) override
Print various parallel mesh stats.
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
const FiniteElement * GetFaceNbrFE(int i) const
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
Geometry::Type GetElementBaseGeometry(int i) const
int GetBdrElementEdgeIndex(int i) const
static ParMesh MakeRefined(ParMesh &orig_mesh, int ref_factor, int ref_type)
Create a uniformly refined (by any factor) version of orig_mesh.
void GetSharedTriCommunicator(int ordering, GroupCommunicator &stria_comm) const
Get the shared face triangles GroupCommunicator.
Array< Element * > boundary
int Dimension() const
Dimension of the reference space used within the elements.
int * GeneratePartitioning(int nparts, int part_method=1)
int BuildLocalVertices(const Mesh &global_mesh, const int *partitioning, Array< int > &vert_global_local)
Fills out partitioned Mesh::vertices.
void UniformRefinement2D() override
Refine a mixed 2D mesh uniformly.
void SaveAsOne(const char *fname, int precision=16) const
CoarseFineTransformations CoarseFineTr
void Bcast(T *ldata, int layout) const
Broadcast within each group where the master is the root.
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
void SetSize(int s)
Resize the vector to size s.
IsoparametricTransformation Transformation
void GetCharacteristics(double &h_min, double &h_max, double &kappa_min, double &kappa_max, Vector *Vh=NULL, Vector *Vk=NULL)
Array< Element * > face_nbr_elements
static FiniteElement * GetTransformationFEforElementType(Element::Type)
Return FiniteElement for reference element of the specified type.
void NewNodes(GridFunction &nodes, bool make_owner=false)
Replace the internal node GridFunction with the given GridFunction.
void GetFaceNeighbors(class ParMesh &pmesh)
Lists all edges/faces in the nonconforming mesh.
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
Geometry::Type GetFaceGeometry(int i) const
Return the Geometry::Type associated with face i.
void ShiftRight(int &a, int &b, int &c)
void SetDims(int rows, int nnz)
static const int FaceVert[NumFaces][MaxFaceVert]
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void BuildSharedFaceElems(int ntri_faces, int nquad_faces, const Mesh &mesh, int *partitioning, const STable3D *faces_tbl, const Array< int > &face_group, const Array< int > &vert_global_local)
void GetVertexToVertexTable(DSTable &) const
int GetAttribute() const
Return element's attribute.
T * GetData()
Returns the data.
bool Nonconforming() const
static const int FaceVert[NumFaces][MaxFaceVert]
int Size() const
Returns the size of the vector.
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. Returns the number assigned to the table entry.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Data type dense matrix using column-major storage.
bool IsSlaveFace(const FaceInfo &fi) const
void ApplyLocalSlaveTransformation(FaceElementTransformations &FT, const FaceInfo &fi, bool is_ghost)
void GetElementJacobian(int i, DenseMatrix &J, const IntegrationPoint *ip=NULL)
void GetCharacteristics(double &h_min, double &h_max, double &kappa_min, double &kappa_max)
void AverageVertices(const int *indexes, int n, int result)
Averages the vertices with given indexes and saves the result in vertices[result].
void SynchronizeDerefinementData(Array< Type > &elem_data, const Table &deref_table)
void NonconformingRefinement(const Array< Refinement > &refinements, int nc_limit=0) override
This function is not public anymore. Use GeneralRefinement instead.
double CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
void EnsureParNodes()
If the mesh is curved, make sure 'Nodes' is ParGridFunction.
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
virtual void SetVertices(const int *ind)
Set the indices the element according to the input.
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
int GetNEdges() const
Return the number of edges.
void UniformRefineGroups3D(int old_nv, int old_nedges, const DSTable &old_v_to_v, const STable3D &old_faces, Array< int > *f2qf)
const Element * GetElement(int i) const
Return pointer to the i'th element object.
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...
Abstract parallel finite element space.
Array< Vert3 > shared_trias
Array< int > face_nbr_vertices_offset
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec and fes.
void SetMeshGen()
Determine the mesh generator bitmask meshgen, see MeshGenerator().
Array< int > face_nbr_group
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
bool NonconformingDerefinement(Array< double > &elem_error, double threshold, int nc_limit=0, int op=1) override
NC version of GeneralDerefinement.
Data arrays will be written in ASCII format.
void RebalanceImpl(const Array< int > *partition)
void GroupEdge(int group, int i, int &edge, int &o) const
void MarkTetMeshForRefinement(DSTable &v_to_v) override
void BuildFaceGroup(int ngroups, const Mesh &mesh, const Array< int > &face_group, int &nstria, int &nsquad)
void Swap(GroupTopology &other)
Swap the internal data with another GroupTopology object.
void GetVertexDofs(int i, Array< int > &dofs) const
Returns the indices of the degrees of freedom for the specified vertices.
virtual FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
const NCList & GetSharedEdges()
int GetNBE() const
Returns number of boundary elements.
STable3D * GetSharedFacesTable()
void RedRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
void Save(std::ostream &out) const
Save the data in a stream.
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
bool HasBoundaryElements() const override
Checks if any rank in the mesh has boundary elements.
void DeleteAll()
Delete the whole array.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
void AddConnections(int r, const int *c, int nc)
void InitRefinementTransforms()
const NCList & GetSharedList(int entity)
Helper to get shared vertices/edges/faces ('entity' == 0/1/2 resp.).
void UniformRefinement2D_base(bool update_nodes=true)
Array< NCFaceInfo > nc_faces_info
void OnMeshUpdated(Mesh *mesh)
A parallel extension of the NCMesh class.
void Derefine(const Array< int > &derefs) override
Element * NewElement(int geom)
FaceElementTransformations FaceElemTr
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
void SetVerticesFromNodes(const GridFunction *nodes)
Helper to set vertex coordinates given a high-order curvature function.
void CopyTo(U *dest)
STL-like copyTo dest from begin to end.
int FindSharedEdges(const Mesh &mesh, const int *partition, Table *&edge_element, ListOfIntegerSets &groups)
std::function< double(const Vector &)> f(double mass_coeff)
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 GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void MakeRefined_(Mesh &orig_mesh, const Array< int > ref_factors, int ref_type)
Internal function used in Mesh::MakeRefined.
void ExchangeFaceNbrData()
void BuildSharedVertMapping(int nvert, const Table *vert_element, const Array< int > &vert_global_local)
int GetAttribute(int i) const
Return the attribute of element i.
DofTransformation * GetFaceNbrElementVDofs(int i, Array< int > &vdofs) const
void NURBSUniformRefinement() override
Refine NURBS mesh.
void MarkEdge(DenseMatrix &pmat)
int AddVertex(double x, double y=0.0, double z=0.0)
void GetGlobalEdgeIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
void GetBdrElementFace(int i, int *f, int *o) const
Return the index and the orientation of the face of bdr element i. (3D)
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.
Communicator performing operations within groups defined by a GroupTopology with arbitrary-size data ...
void ParPrint(std::ostream &out) const
Save the mesh in a parallel mesh format.
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
long long GetGlobalNE() const
Return the total (global) number of elements.
Array< int > face_nbr_elements_offset
void GetEdgeOrdering(DSTable &v_to_v, Array< int > &order)
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
GeometryRefiner GlobGeometryRefiner
void Finalize(bool refine=false, bool fix_orientation=false) override
Finalize the construction of a general Mesh.
double GetElementSize(ElementTransformation *T, int type=0)
Geometry::Type GetGeometryType() const
Symmetric 3D Table stored as an array of rows each of which has a stack of column, floor, number nodes. The number of the node is assigned by counting the nodes from zero as they are pushed into the table. Diagonals of any kind are not allowed so the row, column and floor must all be different for each node. Only one node is stored for all 6 symmetric entries that are indexable by unique triplets of row, column, and floor.
void GetBoundingBox(Vector &p_min, Vector &p_max, int ref=2)
void GetVertices(Vector &vert_coord) const
const Table & GetDerefinementTable()
void SaveAsOne(const std::string &fname, int precision=16) const
Array< Element * > shared_edges
virtual void SetAttributes()
Determine the sets of unique attribute values in domain and boundary elements.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
const FiniteElementCollection * FEColl() const
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
std::string to_padded_string(int i, int digits)
Convert an integer to a 0-padded string with the given number of digits.
void BuildSharedEdgeElems(int nedges, Mesh &mesh, const Array< int > &vert_global_local, const Table *edge_element)
void Finalize()
Allocate internal buffers after the GroupLDofTable is defined.
void GetFaceTransformation(int i, IsoparametricTransformation *FTr)
int GroupNVertices(int group) const
FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31) override
static const int NumVerts[NumGeom]
int GroupVertex(int group, int i) const
void AddConnection(int r, int c)
STable3D * GetElementToFaceTable(int ret_ftbl=0)
FaceElementTransformations * GetSharedFaceTransformations(int sf, bool fill2=true)
void LoseData()
NULL-ifies the data.
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
Table send_face_nbr_vertices
Type
Constants for the classes derived from Element.
This structure stores the low level information necessary to interpret the configuration of elements ...
void Refine(const Array< Refinement > &refinements) override
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
VTKFormat
Data array format for VTK and VTU files.
virtual const char * Name() const
void GetGlobalVertexIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
int Insert(IntegerSet &s)
Check to see if set 's' is in the list. If not append it to the end of the list. Returns the index of...
virtual int DofForGeometry(Geometry::Type GeomType) const
void Save(const std::string &fname, int precision=16) const override
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void PrintVTU(std::string pathname, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr=false) override
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
int GetNFaceNeighbors() const
int AddElement(Element *elem)
static int create_directory(const std::string &dir_name, const Mesh *mesh, int myid)
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 GetElementToEdgeTable(Table &, Array< int > &)
virtual MFEM_DEPRECATED int GetNFaces(int &nFaceVertices) const =0
void GetSharedEdgeCommunicator(int ordering, GroupCommunicator &sedge_comm) const
Get the shared edges GroupCommunicator.
int GetNFbyType(FaceType type) const override
Returns the number of local faces according to the requested type, does not count master non-conformi...
RefinedGeometry * Refine(Geometry::Type Geom, int Times, int ETimes=1)
void GetLocalFaceTransformation(int face_type, int elem_type, IsoparametricTransformation &Transf, int info)
A helper method that constructs a transformation from the reference space of a face to the reference ...
IsoparametricTransformation Transformation2
Table * face_nbr_el_to_face
void GetSharedTriangleDofs(int group, int fi, Array< int > &dofs) const
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
FiniteElementCollection * OwnFEC()
long long ReduceInt(int value) const override
Utility function: sum integers from all processors (Allreduce).
FiniteElementSpace * FESpace()
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
int GetSharedFace(int sface) const
Return the local face index for the given shared face.
int Size()
Return the number of integer sets in the list.
STable3D * GetFaceNbrElementToFaceTable(int ret_ftbl=0)
void GetGlobalElementIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are supported.
Array< Vert4 > shared_quads
void Rebalance(const Array< int > *custom_partition=NULL)
int GroupNTriangles(int group) const
int slaves_end
slave faces
Data type tetrahedron element.
double * GetData() const
Return a pointer to the beginning of the Vector data.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
void PrintXG(std::ostream &out=mfem::out) const override
int GetVDim() const
Returns vector dimension.
virtual DofTransformation * GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
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)
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 ...
int CheckBdrElementOrientation(bool fix_it=true)
Check the orientation of the boundary elements.
virtual void GetElementDofValues(int el, Vector &dof_vals) const
virtual int GetFaceDofs(int i, Array< int > &dofs, int variant=0) const
void Swap(Array< T > &, Array< T > &)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
const Table & ElementToEdgeTable() const
double p(const Vector &x, double t)
void FindSharedFaces(const Mesh &mesh, const int *partition, Array< int > &face_group, ListOfIntegerSets &groups)
void LocalRefinement(const Array< int > &marked_el, int type=3) override
This function is not public anymore. Use GeneralRefinement instead.
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
void RefineGroups(const DSTable &v_to_v, int *middle)
Update the groups after triangle refinement.
Array< Vertex > face_nbr_vertices
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
static void PrintElement(const Element *, std::ostream &)
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
bool IsGhost(int entity, int index) const
Return true if the specified vertex/edge/face is a ghost.
void Swap(ParMesh &other)
ParFiniteElementSpace * ParFESpace() const
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
void AddAColumnInRow(int r)
GridFunction * GetNodes()
Return a pointer to the internal node GridFunction (may be NULL).
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void PrepareNodeReorder(DSTable **old_v_to_v, Table **old_elem_vert)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
long long glob_elem_offset
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...
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. The entry is addressed by the three smallest values of (r,c,f,t). Returns the number assigned to the table entry.
Table * GetFaceToAllElementTable() const
int Index(int r, int c, int f) const
void DeleteLast()
Delete the last entry of the array.
void PrintAsOne(std::ostream &out=mfem::out) const
bool WantSkipSharedMaster(const NCMesh::Master &master) const
int GetDof() const
Returns the number of degrees of freedom in the finite element.
ParMesh()
Default constructor. Create an empty ParMesh.
Table & GroupLDofTable()
Fill-in the returned Table reference to initialize the GroupCommunicator then call Finalize()...
Array< Element * > elements
void SetAttributes() override
Determine the sets of unique attribute values in domain and boundary elements.
void GenerateOffsets(int N, HYPRE_BigInt loc_sizes[], Array< HYPRE_BigInt > *offsets[]) const
int SpaceDimension() const
Dimension of the physical space containing the mesh.
static const int FaceVert[NumFaces][MaxFaceVert]
void BuildVertexGroup(int ngroups, const Table &vert_element)
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name...
void GetFaceNbrElementTransformation(int i, IsoparametricTransformation *ElTr)
int GetNE() const
Returns number of elements.
virtual int GetTrueVSize() const
Return the number of local vector true dofs.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetLocalElementNum(long long global_element_num) const
void GetFaceNbrElementFaces(int i, Array< int > &fcs, Array< int > &cor) const
void DistributeAttributes(Array< int > &attr)
Ensure that bdr_attributes and attributes agree across processors.
Element::Type GetElementType(int i) const
Returns the type of element i.
void PrintSharedEntities(const std::string &fname_prefix) const
Debugging method.
void Swap(Mesh &other, bool non_geometry)
void BuildEdgeGroup(int ngroups, const Table &edge_element)
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.
int GetGroupSize(int g) const
Get the number of processors in a group.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
virtual int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type, does not count master nonconforming face...
int Size() const
Returns the number of TYPE I elements.
void ExchangeFaceNbrNodes()
Ordering::Type GetOrdering() const
Return the ordering method.
const Element * GetFace(int i) const
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
static const int Orient[NumOrient][NumVert]
int BuildLocalElements(const Mesh &global_mesh, const int *partitioning, const Array< int > &vert_global_local)
Fills out partitioned Mesh::elements.
void SetIJ(int *newI, int *newJ, int newsize=-1)
Replace the I and J arrays with the given newI and newJ arrays.
const char * VTKByteOrder()
Determine the byte order and return either "BigEndian" or "LittleEndian".
Table group_svert
Shared objects in each group.
void PrintAsSerial(std::ostream &out=mfem::out) const
void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1) override
Set the curvature of the mesh nodes using the given polynomial degree.
bool DecodeFaceSplittings(HashTable< Hashed2 > &v_to_v, const int *v, const Array< unsigned > &codes, int &pos)
Array< MeshId > conforming
Element::Type GetFaceElementType(int Face) const
double GetFaceNbrElementSize(int i, int type=0)
int index(int i, int j, int nx, int ny)
int NumberOfEntries() const
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
void MakeSimplicial_(const Mesh &orig_mesh, int *vglobal)
long long GetGlobalElementNum(int local_element_num) const
Map a local element number to a global element number.
Array< FaceInfo > faces_info
virtual int GetNVertices() const =0
void SetAttribute(const int attr)
Set element's attribute.
STable3D * GetFacesTable()
int Size_of_connections() const
void GetSharedEdgeDofs(int group, int ei, Array< int > &dofs) const
NCMesh * ncmesh
Optional nonconforming mesh extension.
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
int AddBdrElement(Element *elem)
int Size() const
Return the logical size of the array.
T & Last()
Return the last element in the array.
void GetGlobalFaceIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
int GetEdgeSplittings(Element *edge, const DSTable &v_to_v, int *middle)
Return a number(0-1) identifying how the given edge has been split.
const int * GetDofMap(Geometry::Type GeomType) const
Get the Cartesian to local H1 dof map.
double AggregateError(const Array< double > &elem_error, const int *fine, int nfine, int op)
Derefinement helper.
void GetMarkedFace(const int face, int *fv)
int InitialPartition(int index) const
Helper to get the partitioning when the serial mesh gets split initially.
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...
Arbitrary order H(curl)-conforming Nedelec finite elements.
int GetFaceNbrRank(int fn) const
int GetNFaces() const
Return the number of faces in a 3D mesh.
virtual void Print(std::ostream &os=mfem::out) const
int GroupNEdges(int group) const
static ParMesh MakeSimplicial(ParMesh &orig_mesh)
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
void SetNodalFESpace(FiniteElementSpace *nfes) override
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn't exist.
Arbitrary order H1-conforming (continuous) finite elements.
Array< int > svert_lvert
Shared to local index mapping.
const NCList & GetSharedFaces()
int GroupNQuadrilaterals(int group) const
void GetNodes(Vector &node_coord) const
void Printer(std::ostream &out=mfem::out, std::string section_delimiter="") const
void Print(std::ostream &out=mfem::out) const override
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
void DoNodeReorder(DSTable *old_v_to_v, Table *old_elem_vert)
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Class for parallel grid function.
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
void GroupQuadrilateral(int group, int i, int &face, int &o) const
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Table send_face_nbr_elements
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
void InitFromNCMesh(const NCMesh &ncmesh)
Initialize vertices/elements/boundary/tables from a nonconforming mesh.
void Bisection(int i, const DSTable &, int *, int *, int *)
Bisect a triangle: element with index i is bisected.
Mesh GetSerialMesh(int save_rank) const
void Load(std::istream &input, int generate_edges=0, int refine=1, bool fix_orientation=true) override
Parallel version of Mesh::Load().
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
void GroupTriangle(int group, int i, int &face, int &o) const
HYPRE_BigInt GetGlobalTDofNumber(int ldof) const
Returns the global tdof number of the given local degree of freedom.
Class for parallel meshes.
Abstract data type element.
void LimitNCLevel(int max_nc_level) override
Parallel version of NCMesh::LimitNCLevel.
void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level) override
Data type line segment element.
void BdrBisection(int i, const HashTable< Hashed2 > &)
Bisect a boundary triangle: boundary element with index i is bisected.
void ComputeGlobalElementOffset() const
void GenerateNCFaceInfo()
virtual Type GetType() const =0
Returns element's type.
double GetLength(int i, int j) const
Return the length of the segment from node i to node j.
virtual DofTransformation * GetBdrElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom for i'th boundary element.
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Table * GetVertexToElementTable()
The returned Table should be deleted by the caller.
static const int Orient[NumOrient][NumVert]
void Load(std::istream &in)
Load the data from a stream.
void UpdateNodes()
Update the nodes of a curved mesh after the topological part of a Mesh::Operation, such as refinement, has been performed.
Defines the position of a fine element within a coarse element.
bool IAmMaster(int g) const
Return true if I am master for group 'g'.
MFEM_DEPRECATED void ReorientTetMesh() override
See the remarks for the serial version in mesh.hpp.
void GreenRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
int GetNumNeighbors() const
Return the number of neighbors including the local processor.
Arbitrary order "L2-conforming" discontinuous finite elements.
static const int FaceVert[NumFaces][MaxFaceVert]