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)
3375 gr_stria.
GetI()[0] = 0;
3387 for (
int i = 0; i < stria_flag.Size(); i++)
3390 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
3392 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
3396 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
3401 stria_comm.
Bcast(stria_master_flag);
3402 for (
int i = 0; i < stria_flag.Size(); i++)
3405 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
3406 "inconsistent vertex ordering found, shared triangle " 3408 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), " 3409 <<
"local flag: " << stria_flag[i]
3410 <<
", master flag: " << stria_master_flag[i]);
3419 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3435 delete old_elem_vert;
3448 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3457 int uniform_refinement = 0;
3461 uniform_refinement = 1;
3472 for (
int i = 0; i < marked_el.
Size(); i++)
3478 for (
int i = 0; i < marked_el.
Size(); i++)
3487 for (
int i = 0; i < marked_el.
Size(); i++)
3504 int need_refinement;
3505 int max_faces_in_group = 0;
3511 face_splittings[i].
Reserve(faces_in_group);
3512 if (faces_in_group > max_faces_in_group)
3514 max_faces_in_group = faces_in_group;
3520 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3523 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3524 int ref_loops_all = 0, ref_loops_par = 0;
3528 need_refinement = 0;
3531 if (
elements[i]->NeedRefinement(v_to_v))
3533 need_refinement = 1;
3537 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3541 if (uniform_refinement)
3548 if (need_refinement == 0)
3550 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3554 const int tag = 293;
3563 if (faces_in_group == 0) {
continue; }
3565 face_splittings[i].
SetSize(0);
3566 for (
int j = 0; j < faces_in_group; j++)
3569 face_splittings[i]);
3573 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3574 MPI_UNSIGNED, neighbor, tag,
MyComm,
3575 &requests[req_count++]);
3583 if (faces_in_group == 0) {
continue; }
3587 MPI_Probe(neighbor, tag,
MyComm, &status);
3589 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3591 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3594 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3601 int nr = need_refinement;
3602 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3604 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3607 while (need_refinement == 1);
3609 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3611 int i = ref_loops_all;
3612 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3615 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = " 3616 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3624 delete [] face_splittings;
3629 need_refinement = 0;
3632 if (
boundary[i]->NeedRefinement(v_to_v))
3634 need_refinement = 1;
3639 while (need_refinement == 1);
3644 " (NumOfBdrElements != boundary.Size())");
3671 int uniform_refinement = 0;
3675 uniform_refinement = 1;
3684 int *edge1 =
new int[nedges];
3685 int *edge2 =
new int[nedges];
3686 int *middle =
new int[nedges];
3688 for (
int i = 0; i < nedges; i++)
3690 edge1[i] = edge2[i] = middle[i] = -1;
3695 int *v =
elements[i]->GetVertices();
3696 for (
int j = 0; j < 3; j++)
3698 int ind = v_to_v(v[j], v[(j+1)%3]);
3699 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3704 for (
int i = 0; i < marked_el.
Size(); i++)
3710 int need_refinement;
3711 int edges_in_group, max_edges_in_group = 0;
3713 int **edge_splittings =
new int*[
GetNGroups()-1];
3717 edge_splittings[i] =
new int[edges_in_group];
3718 if (edges_in_group > max_edges_in_group)
3720 max_edges_in_group = edges_in_group;
3723 int neighbor, *iBuf =
new int[max_edges_in_group];
3727 MPI_Request request;
3732 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3733 int ref_loops_all = 0, ref_loops_par = 0;
3737 need_refinement = 0;
3738 for (
int i = 0; i < nedges; i++)
3740 if (middle[i] != -1 && edge1[i] != -1)
3742 need_refinement = 1;
3746 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3750 if (uniform_refinement)
3757 if (need_refinement == 0)
3759 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3768 edges_in_group = group_edges.
Size();
3770 if (edges_in_group != 0)
3772 for (
int j = 0; j < edges_in_group; j++)
3774 edge_splittings[i][j] =
3787 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3788 neighbor, 0,
MyComm, &request);
3796 edges_in_group = group_edges.
Size();
3797 if (edges_in_group != 0)
3808 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3809 MPI_ANY_TAG,
MyComm, &status);
3811 for (
int j = 0; j < edges_in_group; j++)
3813 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3816 int ii = v_to_v(v[0], v[1]);
3817 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3818 if (middle[ii] != -1)
3820 mfem_error(
"ParMesh::LocalRefinement (triangles) : " 3824 need_refinement = 1;
3826 for (
int c = 0; c < 2; c++)
3836 int nr = need_refinement;
3837 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3840 while (need_refinement == 1);
3842 #ifdef MFEM_DEBUG_PARMESH_LOCALREF 3844 int i = ref_loops_all;
3845 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3848 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = " 3849 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3857 delete [] edge_splittings[i];
3859 delete [] edge_splittings;
3864 int v1[2], v2[2], bisect, temp;
3866 for (
int i = 0; i < temp; i++)
3868 int *v =
boundary[i]->GetVertices();
3869 bisect = v_to_v(v[0], v[1]);
3870 if (middle[bisect] != -1)
3875 v1[0] = v[0]; v1[1] = middle[bisect];
3876 v2[0] = middle[bisect]; v2[1] = v[1];
3883 mfem_error(
"Only bisection of segment is implemented for bdr" 3916 for (
int j = 0; j < marked_el.
Size(); j++)
3918 int i = marked_el[j];
3921 int new_v = cnv + j, new_e = cne + j;
3930 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3932 UseExternalData(seg_children, 1, 2, 3);
3953 MFEM_ABORT(
"NURBS meshes are not supported. Please project the " 3954 "NURBS to Nodes first with SetCurvature().");
3959 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh " 3960 "(you need to initialize the ParMesh from a nonconforming " 4001 double threshold,
int nc_limit,
int op)
4003 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
4004 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. " 4005 "Project the NURBS to Nodes first.");
4018 for (
int i = 0; i < dt.
Size(); i++)
4020 if (nc_limit > 0 && !level_ok[i]) {
continue; }
4025 if (error < threshold) { derefs.
Append(i); }
4029 if (!glob_size) {
return false; }
4072 MFEM_ABORT(
"Load balancing is currently not supported for conforming" 4079 MFEM_VERIFY(dynamic_cast<ParFiniteElementSpace*>(
Nodes->
FESpace())
4080 != NULL,
"internal error");
4110 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
4120 int *I_group_svert, *J_group_svert;
4121 int *I_group_sedge, *J_group_sedge;
4126 I_group_svert[0] = I_group_svert[1] = 0;
4127 I_group_sedge[0] = I_group_sedge[1] = 0;
4134 for (
int group = 0; group <
GetNGroups()-1; group++)
4144 const int ind = middle[v_to_v(v[0], v[1])];
4150 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4157 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4158 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4161 J = J_group_svert+I_group_svert[group];
4162 for (
int i = 0; i < group_verts.
Size(); i++)
4164 J[i] = group_verts[i];
4166 J = J_group_sedge+I_group_sedge[group];
4167 for (
int i = 0; i < group_edges.
Size(); i++)
4169 J[i] = group_edges[i];
4183 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
4185 Array<int> group_verts, group_edges, group_trias;
4204 I_group_svert[0] = 0;
4205 I_group_sedge[0] = 0;
4206 I_group_stria[0] = 0;
4208 for (
int group = 0; group <
GetNGroups()-1; group++)
4219 int ind = v_to_v.
FindId(v[0], v[1]);
4220 if (ind == -1) {
continue; }
4223 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4233 ind = v_to_v.
FindId(v[0], ind);
4241 ind = v_to_v.
FindId(v[0], v[1]);
4262 while (sedge_stack.
Size() > 0);
4269 int ind = v_to_v.
FindId(v[0], v[1]);
4270 if (ind == -1) {
continue; }
4273 const int edge_attr = 1;
4282 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
4283 ind = v_to_v.
FindId(v[0], v[1]);
4291 ind = v_to_v.
FindId(v[0], v[1]);
4309 v = sface_stack[sface_stack.
Size()-2].v;
4311 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
4314 while (sface_stack.
Size() > 0);
4320 ind = v_to_v.
FindId(v[0], v[1]);
4341 while (sedge_stack.
Size() > 0);
4344 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4345 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4346 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4348 J_group_svert.
Append(group_verts);
4349 J_group_sedge.
Append(group_edges);
4350 J_group_stria.
Append(group_trias);
4367 int *I_group_svert, *J_group_svert;
4368 int *I_group_sedge, *J_group_sedge;
4373 I_group_svert[0] = 0;
4374 I_group_sedge[0] = 0;
4381 for (
int group = 0; group <
GetNGroups()-1; group++)
4395 const int attr =
shared_edges[sedges[i]]->GetAttribute();
4401 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
4402 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
4404 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
4405 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4421 Array<int> group_verts, group_edges, group_trias, group_quads;
4423 int *I_group_svert, *J_group_svert;
4424 int *I_group_sedge, *J_group_sedge;
4425 int *I_group_stria, *J_group_stria;
4426 int *I_group_squad, *J_group_squad;
4433 I_group_svert[0] = 0;
4434 I_group_sedge[0] = 0;
4435 I_group_stria[0] = 0;
4436 I_group_squad[0] = 0;
4448 const int oface = old_nv + old_nedges;
4450 for (
int group = 0; group <
GetNGroups()-1; group++)
4462 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4466 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4476 const int stria = group_trias[i];
4479 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4480 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4481 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4482 const int edge_attr = 1;
4497 v[1] = m[0]; v[2] = m[2];
4498 group_trias.
Append(nst+0);
4499 group_trias.
Append(nst+1);
4500 group_trias.
Append(nst+2);
4508 const int squad = group_quads[i];
4510 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4512 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4516 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4517 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4518 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4519 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4520 const int edge_attr = 1;
4537 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4538 group_quads.
Append(nsq+0);
4539 group_quads.
Append(nsq+1);
4540 group_quads.
Append(nsq+2);
4544 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4545 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4546 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4547 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4549 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4550 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4551 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4552 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4571 const bool update_nodes =
false;
4601 const bool update_nodes =
false;
4610 f2qf.
Size() ? &f2qf : NULL);
4620 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4626 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4632 os <<
"NETGEN_Neutral_Format\n";
4637 for (j = 0; j <
Dim; j++)
4651 for (j = 0; j < nv; j++)
4653 os <<
" " << ind[j]+1;
4666 for (j = 0; j < nv; j++)
4668 os <<
" " << ind[j]+1;
4679 for (j = 0; j < 3; j++)
4681 os <<
' ' << ind[j]+1;
4695 <<
" 0 0 0 0 0 0 0\n" 4696 <<
"0 0 0 1 0 0 0 0 0 0 0\n" 4698 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n" 4699 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n" 4700 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4706 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4714 os << i+1 <<
" " <<
elements[i]->GetAttribute();
4715 for (j = 0; j < nv; j++)
4717 os <<
" " << ind[j]+1;
4728 for (j = 0; j < nv; j++)
4730 os <<
" " << ind[j]+1;
4732 os <<
" 1.0 1.0 1.0 1.0\n";
4743 for (j = 0; j < 4; j++)
4745 os <<
' ' << ind[j]+1;
4747 os <<
" 1.0 1.0 1.0 1.0\n";
4756 os <<
"areamesh2\n\n";
4763 attr =
boundary[i]->GetAttribute();
4766 for (j = 0; j < v.
Size(); j++)
4768 os << v[j] + 1 <<
" ";
4778 for (j = 0; j < v.
Size(); j++)
4780 os << v[j] + 1 <<
" ";
4789 attr =
elements[i]->GetAttribute();
4805 for (j = 0; j < v.
Size(); j++)
4807 os << v[j] + 1 <<
" ";
4816 for (j = 0; j <
Dim; j++)
4841 int shared_bdr_attr;
4858 s2l_face = &nc_shared_faces;
4865 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4870 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4876 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4884 os <<
"MFEM mesh v1.0\n";
4888 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n" 4893 "# TETRAHEDRON = 4\n" 4898 os <<
"\ndimension\n" <<
Dim 4908 num_bdr_elems += s2l_face->
Size();
4910 os <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4924 shared_bdr_attr =
MyRank + 1;
4926 for (
int i = 0; i < s2l_face->
Size(); i++)
4929 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4957 ostringstream fname_with_suffix;
4958 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
4959 ofstream ofs(fname_with_suffix.str().c_str());
4960 ofs.precision(precision);
4964 #ifdef MFEM_USE_ADIOS2 4977 for (
int i = 0; i < nv; i++)
4985 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4993 os <<
"MFEM mesh v1.0\n";
4997 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n" 5002 "# TETRAHEDRON = 4\n" 5007 os <<
"\ndimension\n" <<
Dim;
5011 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5014 os <<
"\n\nelements\n" << ne <<
'\n';
5018 os << 1 <<
' ' <<
elements[i]->GetGeometryType();
5022 for (j = 0; j < nv; j++)
5031 MPI_Recv(nv_ne, 2, MPI_INT,
p, 444,
MyComm, &status);
5035 MPI_Recv(&ints[0], ne, MPI_INT,
p, 445,
MyComm, &status);
5037 for (i = 0; i < ne; )
5040 os <<
p+1 <<
' ' << ints[i];
5043 for (j = 0; j < k; j++)
5045 os <<
' ' << vc + ints[i++];
5058 ne += 1 +
elements[i]->GetNVertices();
5061 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
5069 MFEM_ASSERT(ints.
Size() == ne,
"");
5072 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
5097 dump_element(
boundary[i], ints); ne++;
5135 MFEM_ABORT(
"invalid dimension: " <<
Dim);
5147 for (i = 0; i < list.
masters.Size(); i++)
5152 for (i = 0; i < list.
slaves.Size(); i++)
5159 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5162 os <<
"\nboundary\n" << k <<
'\n';
5168 MPI_Recv(nv_ne, 2, MPI_INT,
p, 446,
MyComm, &status);
5180 for (i = 0; i < ne; )
5183 os <<
p+1 <<
' ' << ints[i];
5186 for (j = 0; j < k; j++)
5188 os <<
' ' << vc + ints[i++];
5199 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
5210 os <<
"\nvertices\n" << nv <<
'\n';
5228 MPI_Recv(&nv, 1, MPI_INT,
p, 448,
MyComm, &status);
5234 for (i = 0; i < nv; i++)
5286 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
5307 MFEM_ABORT(
"Nonconforming meshes and NURBS meshes are not yet supported.");
5316 MFEM_VERIFY(
int(ne_glob_l) == ne_glob_l,
5317 "overflow in the number of elements!");
5318 int ne_glob = (save_rank ==
MyRank) ?
int(ne_glob_l) : 0;
5321 long long nvertices_glob_l = 0;
5322 MPI_Reduce(&nvertices, &nvertices_glob_l, 1, MPI_LONG_LONG, MPI_SUM,
5324 int nvertices_glob = int(nvertices_glob_l);
5325 MFEM_VERIFY(nvertices_glob == nvertices_glob_l,
5326 "overflow in the number of vertices!");
5329 long long nbe_glob_l = 0;
5330 MPI_Reduce(&nbe, &nbe_glob_l, 1, MPI_LONG_LONG, MPI_SUM, save_rank,
MyComm);
5331 int nbe_glob = int(nbe_glob_l);
5332 MFEM_VERIFY(nbe_glob == nbe_glob_l,
5333 "overflow in the number of boundary elements!");
5350 const int attr =
elements[e]->GetAttribute();
5351 const int geom_type =
elements[e]->GetGeometryType();
5353 for (
int j = 0; j < dofs.
Size(); j++)
5365 if (
p == save_rank) {
continue; }
5366 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 444,
MyComm, &status);
5370 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 445,
MyComm, &status);
5372 for (
int i = 0; i < n_send_recv; )
5374 int attr = ints[i++];
5375 int geom_type = ints[i++];
5388 n_send_recv += 2 +
elements[e]->GetNVertices();
5390 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 444,
MyComm);
5395 const int attr =
elements[e]->GetAttribute();
5396 const int geom_type =
elements[e]->GetGeometryType();;
5400 for (
int j = 0; j < dofs.
Size(); j++)
5407 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 445,
MyComm);
5416 const int attr =
boundary[e]->GetAttribute();
5417 const int geom_type =
boundary[e]->GetGeometryType();
5419 for (
int j = 0; j < dofs.
Size(); j++)
5431 if (
p == save_rank) {
continue; }
5432 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 446,
MyComm, &status);
5436 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 447,
MyComm, &status);
5438 for (
int i = 0; i < n_send_recv; )
5440 int attr = ints[i++];
5441 int geom_type = ints[i++];
5456 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 446,
MyComm);
5461 const int attr =
boundary[e]->GetAttribute();
5462 const int geom_type =
boundary[e]->GetGeometryType();
5466 for (
int j = 0; j < dofs.
Size(); j++)
5473 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 447,
MyComm);
5479 for (
int v = 0; v < nvertices_glob; v++)
5500 serialmesh.
GetNodes()->MakeOwner(fec_serial);
5516 serialmesh.
GetNodes()->SetSubVector(dofs, nodeloc);
5522 for (
int i = 0; i < ints.
Size(); i++)
5524 const double *vdata =
GetVertex(ints[i]);
5525 double *vdata_serial = serialmesh.
GetVertex(ints_serial[i]);
5528 vdata_serial[d] = vdata[d];
5536 if (
p == save_rank) {
continue; }
5537 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 448,
MyComm, &status);
5541 MPI_Recv(&vert[0], n_send_recv, MPI_DOUBLE,
p, 449,
MyComm, &status);
5543 for (
int i = 0; i < n_send_recv; )
5548 serialmesh.
GetNodes()->SetSubVector(dofs, &vert[i]);
5554 for (
int j = 0; j < ints_serial.
Size(); j++)
5556 double *vdata_serial = serialmesh.
GetVertex(ints_serial[j]);
5559 vdata_serial[d] = vert[i++];
5582 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448,
MyComm);
5590 for (
int j = 0; j < nodeloc.
Size(); j++)
5598 for (
int i = 0; i < ints.
Size(); i++)
5600 const double *vdata =
GetVertex(ints[i]);
5610 MPI_Send(&vert[0], n_send_recv, MPI_DOUBLE, save_rank, 449,
MyComm);
5624 ofs.precision(precision);
5631 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
5634 int i, j, k, nv, ne,
p;
5642 os <<
"NETGEN_Neutral_Format\n";
5645 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5649 for (j = 0; j <
Dim; j++)
5657 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5659 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE,
p, 445,
MyComm, &status);
5660 for (i = 0; i < nv; i++)
5662 for (j = 0; j <
Dim; j++)
5664 os <<
" " << vert[
Dim*i+j];
5672 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5679 for (j = 0; j < nv; j++)
5681 os <<
" " << ind[j]+1;
5688 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5689 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5691 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5692 for (i = 0; i < ne; i++)
5695 for (j = 0; j < 4; j++)
5697 os <<
" " << k+ints[i*4+j]+1;
5705 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5713 for (j = 0; j < nv; j++)
5715 os <<
" " << ind[j]+1;
5726 for (j = 0; j < 3; j++)
5728 os <<
' ' << ind[j]+1;
5736 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5737 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5739 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
5740 for (i = 0; i < ne; i++)
5743 for (j = 0; j < 3; j++)
5745 os <<
' ' << k+ints[i*3+j]+1;
5755 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5759 for (j = 0; j <
Dim; j++)
5767 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5774 for (j = 0; j < 4; j++)
5782 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5785 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5790 for (j = 0; j < 3; j++)
5795 for ( ; i < ne; i++)
5798 for (j = 0; j < 3; j++)
5803 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
5809 int i, j, k, nv, ne,
p;
5815 int TG_nv, TG_ne, TG_nbe;
5822 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5825 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n" 5826 <<
"0 0 0 1 0 0 0 0 0 0 0\n" 5827 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n" 5828 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n" 5829 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
5836 <<
" " <<
vertices[i](2) <<
" 0.0\n";
5840 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5842 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE,
p, 445,
MyComm, &status);
5843 for (i = 0; i < nv; i++)
5845 os << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
5846 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
5856 os << i+1 <<
" " << 1;
5857 for (j = 0; j < nv; j++)
5859 os <<
" " << ind[j]+1;
5866 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5867 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5869 MPI_Recv(&ints[0], 8*ne, MPI_INT,
p, 447,
MyComm, &status);
5870 for (i = 0; i < ne; i++)
5872 os << i+1 <<
" " <<
p+1;
5873 for (j = 0; j < 8; j++)
5875 os <<
" " << k+ints[i*8+j]+1;
5890 for (j = 0; j < nv; j++)
5892 os <<
" " << ind[j]+1;
5894 os <<
" 1.0 1.0 1.0 1.0\n";
5904 for (j = 0; j < 4; j++)
5906 os <<
' ' << ind[j]+1;
5908 os <<
" 1.0 1.0 1.0 1.0\n";
5913 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
5914 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
5916 MPI_Recv(&ints[0], 4*ne, MPI_INT,
p, 447,
MyComm, &status);
5917 for (i = 0; i < ne; i++)
5920 for (j = 0; j < 4; j++)
5922 os <<
" " << k+ints[i*4+j]+1;
5924 os <<
" 1.0 1.0 1.0 1.0\n";
5934 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5939 for (j = 0; j <
Dim; j++)
5951 for (j = 0; j < 8; j++)
5960 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5965 for (j = 0; j < 4; j++)
5970 for ( ; i < ne; i++)
5973 for (j = 0; j < 4; j++)
5978 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
5984 int i, j, k, attr, nv, ne,
p;
5992 os <<
"areamesh2\n\n";
5996 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6001 attr =
boundary[i]->GetAttribute();
6004 for (j = 0; j < v.
Size(); j++)
6006 os << v[j] + 1 <<
" ";
6016 for (j = 0; j < v.
Size(); j++)
6018 os << v[j] + 1 <<
" ";
6025 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6026 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6028 MPI_Recv(&ints[0], 2*ne, MPI_INT,
p, 447,
MyComm, &status);
6029 for (i = 0; i < ne; i++)
6032 for (j = 0; j < 2; j++)
6034 os <<
" " << k+ints[i*2+j]+1;
6043 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6049 os << 1 <<
" " << 3 <<
" ";
6050 for (j = 0; j < v.
Size(); j++)
6052 os << v[j] + 1 <<
" ";
6059 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6060 MPI_Recv(&ne, 1, MPI_INT,
p, 446,
MyComm, &status);
6062 MPI_Recv(&ints[0], 3*ne, MPI_INT,
p, 447,
MyComm, &status);
6063 for (i = 0; i < ne; i++)
6065 os <<
p+1 <<
" " << 3;
6066 for (j = 0; j < 3; j++)
6068 os <<
" " << k+ints[i*3+j]+1;
6077 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6081 for (j = 0; j <
Dim; j++)
6089 MPI_Recv(&nv, 1, MPI_INT,
p, 444,
MyComm, &status);
6091 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE,
p, 445,
MyComm, &status);
6092 for (i = 0; i < nv; i++)
6094 for (j = 0; j <
Dim; j++)
6096 os <<
" " << vert[
Dim*i+j];
6106 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6109 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6114 for (j = 0; j < 2; j++)
6119 for ( ; i < ne; i++)
6122 for (j = 0; j < 2; j++)
6127 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
6130 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6137 for (j = 0; j < 3; j++)
6145 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6149 for (j = 0; j <
Dim; j++)
6171 MPI_Allreduce(p_min.
GetData(), gp_min.
GetData(), sdim, MPI_DOUBLE,
6173 MPI_Allreduce(p_max.
GetData(), gp_max.
GetData(), sdim, MPI_DOUBLE,
6178 double &gk_min,
double &gk_max)
6180 double h_min, h_max, kappa_min, kappa_max;
6184 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
6185 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
6186 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
6187 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
6194 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
6198 os <<
"Parallel Mesh Stats:" <<
'\n';
6204 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
6210 kappa_min = kappa_max =
kappa;
6214 if (h < h_min) { h_min = h; }
6215 if (h > h_max) { h_max = h; }
6216 if (
kappa < kappa_min) { kappa_min =
kappa; }
6217 if (
kappa > kappa_max) { kappa_max =
kappa; }
6221 double gh_min, gh_max, gk_min, gk_max;
6222 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
6223 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
6224 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
6225 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
6230 long long mindata[5], maxdata[5], sumdata[5];
6249 MPI_Reduce(ldata, mindata, 5, MPI_LONG_LONG, MPI_MIN, 0,
MyComm);
6250 MPI_Reduce(ldata, sumdata, 5, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
6251 MPI_Reduce(ldata, maxdata, 5, MPI_LONG_LONG, MPI_MAX, 0,
MyComm);
6257 << setw(12) <<
"minimum" 6258 << setw(12) <<
"average" 6259 << setw(12) <<
"maximum" 6260 << setw(12) <<
"total" <<
'\n';
6262 << setw(12) << mindata[0]
6263 << setw(12) << sumdata[0]/
NRanks 6264 << setw(12) << maxdata[0]
6265 << setw(12) << sumdata[0] <<
'\n';
6267 << setw(12) << mindata[1]
6268 << setw(12) << sumdata[1]/
NRanks 6269 << setw(12) << maxdata[1]
6270 << setw(12) << sumdata[1] <<
'\n';
6274 << setw(12) << mindata[2]
6275 << setw(12) << sumdata[2]/
NRanks 6276 << setw(12) << maxdata[2]
6277 << setw(12) << sumdata[2] <<
'\n';
6280 << setw(12) << mindata[3]
6281 << setw(12) << sumdata[3]/
NRanks 6282 << setw(12) << maxdata[3]
6283 << setw(12) << sumdata[3] <<
'\n';
6285 << setw(12) << mindata[4]
6286 << setw(12) << sumdata[4]/
NRanks 6287 << setw(12) << maxdata[4] <<
'\n';
6290 << setw(12) <<
"minimum" 6291 << setw(12) <<
"maximum" <<
'\n';
6293 << setw(12) << gh_min
6294 << setw(12) << gh_max <<
'\n';
6296 << setw(12) << gk_min
6297 << setw(12) << gk_max <<
'\n';
6304 long long local = value, global;
6305 MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM,
MyComm);
6328 Printer(os,
"mfem_serial_mesh_end");
6336 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6347 os <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
6348 for (
int i = 0; i < nv; i++)
6357 os <<
"\nshared_edges " << ne <<
'\n';
6358 for (
int i = 0; i < ne; i++)
6361 os << v[0] <<
' ' << v[1] <<
'\n';
6370 os <<
"\nshared_faces " << nt+nq <<
'\n';
6371 for (
int i = 0; i < nt; i++)
6375 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6378 for (
int i = 0; i < nq; i++)
6382 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6389 os <<
"\nmfem_mesh_end" << endl;
6394 bool high_order_output,
6395 int compression_level,
6398 int pad_digits_rank = 6;
6401 std::string::size_type pos = pathname.find_last_of(
'/');
6403 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
6407 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
6408 std::ofstream os(pvtu_name);
6411 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
6413 os <<
"<?xml version=\"1.0\"?>\n";
6414 os <<
"<VTKFile type=\"PUnstructuredGrid\"";
6415 os <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
6416 os <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
6418 os <<
"<PPoints>\n";
6419 os <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
6420 os <<
" Name=\"Points\" NumberOfComponents=\"3\"" 6421 <<
" format=\"" << data_format <<
"\"/>\n";
6422 os <<
"</PPoints>\n";
6425 os <<
"\t<PDataArray type=\"Int32\" ";
6426 os <<
" Name=\"connectivity\" NumberOfComponents=\"1\"" 6427 <<
" format=\"" << data_format <<
"\"/>\n";
6428 os <<
"\t<PDataArray type=\"Int32\" ";
6429 os <<
" Name=\"offsets\" NumberOfComponents=\"1\"" 6430 <<
" format=\"" << data_format <<
"\"/>\n";
6431 os <<
"\t<PDataArray type=\"UInt8\" ";
6432 os <<
" Name=\"types\" NumberOfComponents=\"1\"" 6433 <<
" format=\"" << data_format <<
"\"/>\n";
6434 os <<
"</PCells>\n";
6436 os <<
"<PCellData>\n";
6437 os <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute" 6438 <<
"\" NumberOfComponents=\"1\"" 6439 <<
" format=\"" << data_format <<
"\"/>\n";
6440 os <<
"</PCellData>\n";
6442 for (
int ii=0; ii<
NRanks; ii++)
6444 std::string piece = fname +
".proc" 6446 os <<
"<Piece Source=\"" << piece <<
"\"/>\n";
6449 os <<
"</PUnstructuredGrid>\n";
6450 os <<
"</VTKFile>\n";
6454 std::string vtu_fname = pathname +
"/" + fname +
".proc" 6456 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
6463 const int npts = point_mat.
Width();
6464 if (npts == 0) {
return 0; }
6466 const bool no_warn =
false;
6473 Array<int> my_point_rank(npts), glob_point_rank(npts);
6474 for (
int k = 0; k < npts; k++)
6476 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
6479 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
6480 MPI_INT, MPI_MIN,
MyComm);
6483 for (
int k = 0; k < npts; k++)
6485 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
6489 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
6492 if (warn && pts_found != npts &&
MyRank == 0)
6494 MFEM_WARNING((npts-pts_found) <<
" points were not found");
6499 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &os)
6502 for (
int d = 1; d < space_dim; d++)
6510 stringstream out_name;
6511 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank 6512 <<
".shared_entities";
6513 ofstream os(out_name.str().c_str());
6521 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6532 os <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
6533 for (
int i = 0; i < nv; i++)
6545 os <<
"\nshared_edges " << ne <<
'\n';
6546 for (
int i = 0; i < ne; i++)
6562 os <<
"\nshared_faces " << nt+nq <<
'\n';
6563 for (
int i = 0; i < nt; i++)
6568 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6571 for (
int j = 0; j < 3; j++)
6574 (j < 2) ? os <<
" | " : os <<
'\n';
6577 for (
int i = 0; i < nq; i++)
6582 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6585 for (
int j = 0; j < 4; j++)
6588 (j < 3) ? os <<
" | " : os <<
'\n';
6604 for (
int i=0; i<
GetNV(); ++i)
6629 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6657 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6670 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 PrintSharedEntities(const char *fname_prefix) const
Debugging method.
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 * 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)
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 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
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...
virtual void Derefine(const Array< int > &derefs)
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
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.
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)
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 GetElementJacobian(int i, DenseMatrix &J)
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 f(const Vector &xvec)
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()
Array< Element * > shared_edges
virtual void SetAttributes()
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 ...
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 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)
The parameter elem should be allocated using the NewElement() method.
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 indexes of degrees of freedom in array dofs for i'th element.
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 SaveAsOne(const char *fname, int precision=16) const
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
void GenerateOffsets(int N, HYPRE_BigInt loc_sizes[], Array< HYPRE_BigInt > *offsets[]) const
int SpaceDimension() const
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.
virtual void Refine(const Array< Refinement > &refinements)
Element::Type GetElementType(int i) const
Returns the type of element i.
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.
virtual void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level)
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
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.
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()
void Save(const char *fname, int precision=16) const override
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 void LimitNCLevel(int max_nc_level)
Parallel version of NCMesh::LimitNCLevel.
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 must be destroyed 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]