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");
269 Nodes->MakeOwner(nfec);
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]]);
2696 for (
int j = 0; j < 6; j++)
2699 sfaces_tbl->
Push4(v[fv[0]], v[fv[1]], v[fv[2]], v[fv[3]]);
2704 MFEM_ABORT(
"Unexpected type of Element.");
2728 for (
int j = 0; j < 4; j++)
2731 int lf = faces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2734 lf = sfaces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2746 for (
int j = 0; j < 2; j++)
2749 int lf = faces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2752 lf = sfaces_tbl->
Index(v[fv[0]], v[fv[1]], v[fv[2]]);
2760 for (
int j = 2; j < 5; j++)
2766 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2767 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2768 if (max < v[fv[3]]) { k = 3; }
2770 int v0 = -1, v1 = -1, v2 = -1;
2774 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2777 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2780 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2783 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2786 int lf = faces_tbl->
Index(v0, v1, v2);
2789 lf = sfaces_tbl->
Index(v0, v1, v2);
2803 for (
int j = 0; j < 6; j++)
2809 if (max < v[fv[1]]) { max = v[fv[1]], k = 1; }
2810 if (max < v[fv[2]]) { max = v[fv[2]], k = 2; }
2811 if (max < v[fv[3]]) { k = 3; }
2813 int v0 = -1, v1 = -1, v2 = -1;
2817 v0 = v[fv[1]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2820 v0 = v[fv[0]]; v1 = v[fv[2]]; v2 = v[fv[3]];
2823 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[3]];
2826 v0 = v[fv[0]]; v1 = v[fv[1]]; v2 = v[fv[2]];
2829 int lf = faces_tbl->
Index(v0, v1, v2);
2832 lf = sfaces_tbl->
Index(v0, v1, v2);
2843 MFEM_ABORT(
"Unexpected type of Element.");
2863 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2878 int el_nbr = i -
GetNE();
2885 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2886 "face_nbr_el_to_face not generated.");
2900 MFEM_ABORT(
"ParMesh::GetFaceNbrElementFaces(...) : "
2901 "face_nbr_el_to_face not generated.");
2936 for (
int i = 0; i < s2l_face->
Size(); i++)
2951 for (
int i = 0; i < s2l_face->
Size(); i++)
2953 int lface = (*s2l_face)[i];
2954 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2979 MFEM_VERIFY(dynamic_cast<const NodalFiniteElement*>(face_el),
2980 "Mesh requires nodal Finite Element.");
2982 #if 0 // TODO: handle the case of non-interpolatory Nodes
2991 FETr->
SetFE(face_el);
3005 const bool fill2 = mask & 10;
3022 MFEM_VERIFY(face_info.
Elem2Inf >= 0,
"The face must be shared.");
3035 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
3049 Elem2NbrNo = -1 - face_info.
Elem2No;
3093 if (is_ghost || fill2)
3116 mfem::out <<
"\nInternal error: face id = " << FaceNo
3117 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
3119 MFEM_ABORT(
"internal error");
3140 MFEM_ASSERT(
Dim > 1,
"");
3159 MFEM_ASSERT(
Dim > 1,
"");
3162 return sface < csize
3164 : shared.
slaves[sface - csize].index;
3177 void Rotate3Indirect(
int &
a,
int &
b,
int &c,
3180 if (order[a] < order[b])
3182 if (order[a] > order[c])
3189 if (order[b] < order[c])
3210 Table *old_elem_vert = NULL;
3234 svert_comm.
Bcast(svert_master_index);
3248 for (
int i = 0; i <
vertices.Size(); i++)
3250 int s = lvert_svert[i];
3253 glob_vert_order[i] =
3254 (std::int64_t(svert_master_rank[s]) << 32) + svert_master_index[s];
3258 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
3270 int *v =
elements[i]->GetVertices();
3272 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3274 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
3276 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
3290 int *v =
boundary[i]->GetVertices();
3292 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3296 const bool check_consistency =
true;
3297 if (check_consistency)
3306 gr_stria.
GetI()[0] = 0;
3318 for (
int i = 0; i < stria_flag.Size(); i++)
3321 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
3323 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
3327 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
3332 stria_comm.
Bcast(stria_master_flag);
3333 for (
int i = 0; i < stria_flag.Size(); i++)
3336 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
3337 "inconsistent vertex ordering found, shared triangle "
3339 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
3340 <<
"local flag: " << stria_flag[i]
3341 <<
", master flag: " << stria_master_flag[i]);
3350 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
3366 delete old_elem_vert;
3379 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
3388 int uniform_refinement = 0;
3392 uniform_refinement = 1;
3403 for (
int i = 0; i < marked_el.
Size(); i++)
3409 for (
int i = 0; i < marked_el.
Size(); i++)
3418 for (
int i = 0; i < marked_el.
Size(); i++)
3435 int need_refinement;
3436 int max_faces_in_group = 0;
3442 face_splittings[i].
Reserve(faces_in_group);
3443 if (faces_in_group > max_faces_in_group)
3445 max_faces_in_group = faces_in_group;
3451 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
3454 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3455 int ref_loops_all = 0, ref_loops_par = 0;
3459 need_refinement = 0;
3462 if (
elements[i]->NeedRefinement(v_to_v))
3464 need_refinement = 1;
3468 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3472 if (uniform_refinement)
3479 if (need_refinement == 0)
3481 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3485 const int tag = 293;
3494 if (faces_in_group == 0) {
continue; }
3496 face_splittings[i].
SetSize(0);
3497 for (
int j = 0; j < faces_in_group; j++)
3500 face_splittings[i]);
3504 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
3505 MPI_UNSIGNED, neighbor, tag,
MyComm,
3506 &requests[req_count++]);
3514 if (faces_in_group == 0) {
continue; }
3518 MPI_Probe(neighbor, tag,
MyComm, &status);
3520 MPI_Get_count(&status, MPI_UNSIGNED, &count);
3522 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
3525 for (
int j = 0, pos = 0; j < faces_in_group; j++)
3532 int nr = need_refinement;
3533 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3535 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
3538 while (need_refinement == 1);
3540 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3542 int i = ref_loops_all;
3543 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3546 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3547 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3555 delete [] face_splittings;
3560 need_refinement = 0;
3563 if (
boundary[i]->NeedRefinement(v_to_v))
3565 need_refinement = 1;
3570 while (need_refinement == 1);
3575 " (NumOfBdrElements != boundary.Size())");
3602 int uniform_refinement = 0;
3606 uniform_refinement = 1;
3615 int *edge1 =
new int[nedges];
3616 int *edge2 =
new int[nedges];
3617 int *middle =
new int[nedges];
3619 for (
int i = 0; i < nedges; i++)
3621 edge1[i] = edge2[i] = middle[i] = -1;
3626 int *v =
elements[i]->GetVertices();
3627 for (
int j = 0; j < 3; j++)
3629 int ind = v_to_v(v[j], v[(j+1)%3]);
3630 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3635 for (
int i = 0; i < marked_el.
Size(); i++)
3641 int need_refinement;
3642 int edges_in_group, max_edges_in_group = 0;
3644 int **edge_splittings =
new int*[
GetNGroups()-1];
3648 edge_splittings[i] =
new int[edges_in_group];
3649 if (edges_in_group > max_edges_in_group)
3651 max_edges_in_group = edges_in_group;
3654 int neighbor, *iBuf =
new int[max_edges_in_group];
3658 MPI_Request request;
3663 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3664 int ref_loops_all = 0, ref_loops_par = 0;
3668 need_refinement = 0;
3669 for (
int i = 0; i < nedges; i++)
3671 if (middle[i] != -1 && edge1[i] != -1)
3673 need_refinement = 1;
3677 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3681 if (uniform_refinement)
3688 if (need_refinement == 0)
3690 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3699 edges_in_group = group_edges.
Size();
3701 if (edges_in_group != 0)
3703 for (
int j = 0; j < edges_in_group; j++)
3705 edge_splittings[i][j] =
3718 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3719 neighbor, 0,
MyComm, &request);
3727 edges_in_group = group_edges.
Size();
3728 if (edges_in_group != 0)
3739 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3740 MPI_ANY_TAG,
MyComm, &status);
3742 for (
int j = 0; j < edges_in_group; j++)
3744 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3747 int ii = v_to_v(v[0], v[1]);
3748 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3749 if (middle[ii] != -1)
3751 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3755 need_refinement = 1;
3757 for (
int c = 0; c < 2; c++)
3767 int nr = need_refinement;
3768 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3771 while (need_refinement == 1);
3773 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3775 int i = ref_loops_all;
3776 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3779 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3780 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3788 delete [] edge_splittings[i];
3790 delete [] edge_splittings;
3795 int v1[2], v2[2], bisect, temp;
3797 for (
int i = 0; i < temp; i++)
3799 int *v =
boundary[i]->GetVertices();
3800 bisect = v_to_v(v[0], v[1]);
3801 if (middle[bisect] != -1)
3806 v1[0] = v[0]; v1[1] = middle[bisect];
3807 v2[0] = middle[bisect]; v2[1] = v[1];
3814 mfem_error(
"Only bisection of segment is implemented for bdr"
3847 for (
int j = 0; j < marked_el.
Size(); j++)
3849 int i = marked_el[j];
3852 int new_v = cnv + j, new_e = cne + j;
3861 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3863 UseExternalData(seg_children, 1, 2, 3);
3884 MFEM_ABORT(
"NURBS meshes are not supported. Please project the "
3885 "NURBS to Nodes first with SetCurvature().");
3890 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3891 "(you need to initialize the ParMesh from a nonconforming "
3932 double threshold,
int nc_limit,
int op)
3934 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3935 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3936 "Project the NURBS to Nodes first.");
3949 for (
int i = 0; i < dt.
Size(); i++)
3951 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3956 if (error < threshold) { derefs.
Append(i); }
3960 if (!glob_size) {
return false; }
4003 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
4010 MFEM_VERIFY(dynamic_cast<ParFiniteElementSpace*>(
Nodes->
FESpace())
4011 != NULL,
"internal error");
4041 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
4051 int *I_group_svert, *J_group_svert;
4052 int *I_group_sedge, *J_group_sedge;
4057 I_group_svert[0] = I_group_svert[1] = 0;
4058 I_group_sedge[0] = I_group_sedge[1] = 0;
4065 for (
int group = 0; group <
GetNGroups()-1; group++)
4075 const int ind = middle[v_to_v(v[0], v[1])];
4081 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4088 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4089 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4092 J = J_group_svert+I_group_svert[group];
4093 for (
int i = 0; i < group_verts.
Size(); i++)
4095 J[i] = group_verts[i];
4097 J = J_group_sedge+I_group_sedge[group];
4098 for (
int i = 0; i < group_edges.
Size(); i++)
4100 J[i] = group_edges[i];
4114 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
4116 Array<int> group_verts, group_edges, group_trias;
4135 I_group_svert[0] = 0;
4136 I_group_sedge[0] = 0;
4137 I_group_stria[0] = 0;
4139 for (
int group = 0; group <
GetNGroups()-1; group++)
4150 int ind = v_to_v.
FindId(v[0], v[1]);
4151 if (ind == -1) {
continue; }
4154 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4164 ind = v_to_v.
FindId(v[0], ind);
4172 ind = v_to_v.
FindId(v[0], v[1]);
4193 while (sedge_stack.
Size() > 0);
4200 int ind = v_to_v.
FindId(v[0], v[1]);
4201 if (ind == -1) {
continue; }
4204 const int edge_attr = 1;
4213 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
4214 ind = v_to_v.
FindId(v[0], v[1]);
4222 ind = v_to_v.
FindId(v[0], v[1]);
4240 v = sface_stack[sface_stack.
Size()-2].v;
4242 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
4245 while (sface_stack.
Size() > 0);
4251 ind = v_to_v.
FindId(v[0], v[1]);
4272 while (sedge_stack.
Size() > 0);
4275 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4276 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4277 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4279 J_group_svert.
Append(group_verts);
4280 J_group_sedge.
Append(group_edges);
4281 J_group_stria.
Append(group_trias);
4298 int *I_group_svert, *J_group_svert;
4299 int *I_group_sedge, *J_group_sedge;
4304 I_group_svert[0] = 0;
4305 I_group_sedge[0] = 0;
4312 for (
int group = 0; group <
GetNGroups()-1; group++)
4326 const int attr =
shared_edges[sedges[i]]->GetAttribute();
4332 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
4333 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
4335 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
4336 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4352 Array<int> group_verts, group_edges, group_trias, group_quads;
4354 int *I_group_svert, *J_group_svert;
4355 int *I_group_sedge, *J_group_sedge;
4356 int *I_group_stria, *J_group_stria;
4357 int *I_group_squad, *J_group_squad;
4364 I_group_svert[0] = 0;
4365 I_group_sedge[0] = 0;
4366 I_group_stria[0] = 0;
4367 I_group_squad[0] = 0;
4379 const int oface = old_nv + old_nedges;
4381 for (
int group = 0; group <
GetNGroups()-1; group++)
4393 const int ind = old_nv + old_v_to_v(v[0], v[1]);
4397 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
4407 const int stria = group_trias[i];
4410 m[0] = old_nv + old_v_to_v(v[0], v[1]);
4411 m[1] = old_nv + old_v_to_v(v[1], v[2]);
4412 m[2] = old_nv + old_v_to_v(v[2], v[0]);
4413 const int edge_attr = 1;
4428 v[1] = m[0]; v[2] = m[2];
4429 group_trias.
Append(nst+0);
4430 group_trias.
Append(nst+1);
4431 group_trias.
Append(nst+2);
4439 const int squad = group_quads[i];
4441 const int olf = old_faces(v[0], v[1], v[2], v[3]);
4443 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
4447 m[1] = old_nv + old_v_to_v(v[0], v[1]);
4448 m[2] = old_nv + old_v_to_v(v[1], v[2]);
4449 m[3] = old_nv + old_v_to_v(v[2], v[3]);
4450 m[4] = old_nv + old_v_to_v(v[3], v[0]);
4451 const int edge_attr = 1;
4468 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
4469 group_quads.
Append(nsq+0);
4470 group_quads.
Append(nsq+1);
4471 group_quads.
Append(nsq+2);
4475 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
4476 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
4477 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
4478 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
4480 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
4481 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
4482 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
4483 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
4502 const bool update_nodes =
false;
4532 const bool update_nodes =
false;
4541 f2qf.
Size() ? &f2qf : NULL);
4551 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
4557 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
4563 os <<
"NETGEN_Neutral_Format\n";
4568 for (j = 0; j <
Dim; j++)
4582 for (j = 0; j < nv; j++)
4584 os <<
" " << ind[j]+1;
4597 for (j = 0; j < nv; j++)
4599 os <<
" " << ind[j]+1;
4610 for (j = 0; j < 3; j++)
4612 os <<
' ' << ind[j]+1;
4626 <<
" 0 0 0 0 0 0 0\n"
4627 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4629 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4630 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4631 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4637 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4645 os << i+1 <<
" " <<
elements[i]->GetAttribute();
4646 for (j = 0; j < nv; j++)
4648 os <<
" " << ind[j]+1;
4659 for (j = 0; j < nv; j++)
4661 os <<
" " << ind[j]+1;
4663 os <<
" 1.0 1.0 1.0 1.0\n";
4674 for (j = 0; j < 4; j++)
4676 os <<
' ' << ind[j]+1;
4678 os <<
" 1.0 1.0 1.0 1.0\n";
4687 os <<
"areamesh2\n\n";
4694 attr =
boundary[i]->GetAttribute();
4697 for (j = 0; j < v.
Size(); j++)
4699 os << v[j] + 1 <<
" ";
4709 for (j = 0; j < v.
Size(); j++)
4711 os << v[j] + 1 <<
" ";
4720 attr =
elements[i]->GetAttribute();
4736 for (j = 0; j < v.
Size(); j++)
4738 os << v[j] + 1 <<
" ";
4747 for (j = 0; j <
Dim; j++)
4772 int shared_bdr_attr;
4789 s2l_face = &nc_shared_faces;
4796 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4799 if (index < nfaces) { nc_shared_faces.
Append(index); }
4801 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4805 if (index < nfaces) { nc_shared_faces.
Append(index); }
4807 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4810 if (index < nfaces) { nc_shared_faces.
Append(index); }
4815 os <<
"MFEM mesh v1.0\n";
4819 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4824 "# TETRAHEDRON = 4\n"
4829 os <<
"\ndimension\n" <<
Dim
4839 num_bdr_elems += s2l_face->
Size();
4841 os <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4855 shared_bdr_attr =
MyRank + 1;
4857 for (
int i = 0; i < s2l_face->
Size(); i++)
4860 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4888 ostringstream fname_with_suffix;
4889 fname_with_suffix << fname <<
"." << setfill(
'0') << setw(6) <<
MyRank;
4890 ofstream ofs(fname_with_suffix.str().c_str());
4891 ofs.precision(precision);
4895 #ifdef MFEM_USE_ADIOS2
4908 for (
int i = 0; i < nv; i++)
4916 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4924 os <<
"MFEM mesh v1.0\n";
4928 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4933 "# TETRAHEDRON = 4\n"
4938 os <<
"\ndimension\n" <<
Dim;
4942 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4945 os <<
"\n\nelements\n" << ne <<
'\n';
4949 os << 1 <<
' ' <<
elements[i]->GetGeometryType();
4953 for (j = 0; j < nv; j++)
4960 for (p = 1; p <
NRanks; p++)
4962 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
4966 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
4968 for (i = 0; i < ne; )
4971 os << p+1 <<
' ' << ints[i];
4974 for (j = 0; j < k; j++)
4976 os <<
' ' << vc + ints[i++];
4989 ne += 1 +
elements[i]->GetNVertices();
4992 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
5000 MFEM_ASSERT(ints.
Size() == ne,
"");
5003 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
5028 dump_element(
boundary[i], ints); ne++;
5066 MFEM_ABORT(
"invalid dimension: " <<
Dim);
5076 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
5078 for (i = 0; i < list.
masters.Size(); i++)
5081 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
5083 for (i = 0; i < list.
slaves.Size(); i++)
5086 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
5090 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5093 os <<
"\nboundary\n" << k <<
'\n';
5095 for (p = 0; p <
NRanks; p++)
5099 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
5111 for (i = 0; i < ne; )
5114 os << p+1 <<
' ' << ints[i];
5117 for (j = 0; j < k; j++)
5119 os <<
' ' << vc + ints[i++];
5130 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
5141 os <<
"\nvertices\n" << nv <<
'\n';
5157 for (p = 1; p <
NRanks; p++)
5159 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
5163 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
5165 for (i = 0; i < nv; i++)
5170 os <<
' ' << vert[i*spaceDim+j];
5185 vert[i*spaceDim+j] =
vertices[i](j);
5190 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
5217 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
5238 MFEM_ABORT(
"Nonconforming meshes and NURBS meshes are not yet supported.");
5247 MFEM_VERIFY(
int(ne_glob_l) == ne_glob_l,
5248 "overflow in the number of elements!");
5249 int ne_glob = (save_rank ==
MyRank) ?
int(ne_glob_l) : 0;
5252 long long nvertices_glob_l = 0;
5253 MPI_Reduce(&nvertices, &nvertices_glob_l, 1, MPI_LONG_LONG, MPI_SUM,
5255 int nvertices_glob = int(nvertices_glob_l);
5256 MFEM_VERIFY(nvertices_glob == nvertices_glob_l,
5257 "overflow in the number of vertices!");
5260 long long nbe_glob_l = 0;
5261 MPI_Reduce(&nbe, &nbe_glob_l, 1, MPI_LONG_LONG, MPI_SUM, save_rank,
MyComm);
5262 int nbe_glob = int(nbe_glob_l);
5263 MFEM_VERIFY(nbe_glob == nbe_glob_l,
5264 "overflow in the number of boundary elements!");
5281 const int attr =
elements[e]->GetAttribute();
5282 const int geom_type =
elements[e]->GetGeometryType();
5284 for (
int j = 0; j < dofs.
Size(); j++)
5296 if (
p == save_rank) {
continue; }
5297 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 444,
MyComm, &status);
5301 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 445,
MyComm, &status);
5303 for (
int i = 0; i < n_send_recv; )
5305 int attr = ints[i++];
5306 int geom_type = ints[i++];
5319 n_send_recv += 2 +
elements[e]->GetNVertices();
5321 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 444,
MyComm);
5326 const int attr =
elements[e]->GetAttribute();
5327 const int geom_type =
elements[e]->GetGeometryType();;
5331 for (
int j = 0; j < dofs.
Size(); j++)
5338 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 445,
MyComm);
5347 const int attr =
boundary[e]->GetAttribute();
5348 const int geom_type =
boundary[e]->GetGeometryType();
5350 for (
int j = 0; j < dofs.
Size(); j++)
5362 if (
p == save_rank) {
continue; }
5363 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 446,
MyComm, &status);
5367 MPI_Recv(&ints[0], n_send_recv, MPI_INT,
p, 447,
MyComm, &status);
5369 for (
int i = 0; i < n_send_recv; )
5371 int attr = ints[i++];
5372 int geom_type = ints[i++];
5387 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 446,
MyComm);
5392 const int attr =
boundary[e]->GetAttribute();
5393 const int geom_type =
boundary[e]->GetGeometryType();
5397 for (
int j = 0; j < dofs.
Size(); j++)
5404 MPI_Send(&ints[0], n_send_recv, MPI_INT, save_rank, 447,
MyComm);
5410 for (
int v = 0; v < nvertices_glob; v++)
5431 serialmesh.
GetNodes()->MakeOwner(fec_serial);
5447 serialmesh.
GetNodes()->SetSubVector(dofs, nodeloc);
5453 for (
int i = 0; i < ints.
Size(); i++)
5455 const double *vdata =
GetVertex(ints[i]);
5456 double *vdata_serial = serialmesh.
GetVertex(ints_serial[i]);
5459 vdata_serial[d] = vdata[d];
5467 if (
p == save_rank) {
continue; }
5468 MPI_Recv(&n_send_recv, 1, MPI_INT,
p, 448,
MyComm, &status);
5472 MPI_Recv(&vert[0], n_send_recv, MPI_DOUBLE,
p, 449,
MyComm, &status);
5474 for (
int i = 0; i < n_send_recv; )
5479 serialmesh.
GetNodes()->SetSubVector(dofs, &vert[i]);
5485 for (
int j = 0; j < ints_serial.
Size(); j++)
5487 double *vdata_serial = serialmesh.
GetVertex(ints_serial[j]);
5490 vdata_serial[d] = vert[i++];
5513 MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448,
MyComm);
5521 for (
int j = 0; j < nodeloc.
Size(); j++)
5529 for (
int i = 0; i < ints.
Size(); i++)
5531 const double *vdata =
GetVertex(ints[i]);
5541 MPI_Send(&vert[0], n_send_recv, MPI_DOUBLE, save_rank, 449,
MyComm);
5555 ofs.precision(precision);
5562 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
5565 int i, j, k, nv, ne,
p;
5573 os <<
"NETGEN_Neutral_Format\n";
5576 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5580 for (j = 0; j <
Dim; j++)
5586 for (p = 1; p <
NRanks; p++)
5588 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5590 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
5591 for (i = 0; i < nv; i++)
5593 for (j = 0; j <
Dim; j++)
5595 os <<
" " << vert[Dim*i+j];
5603 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5610 for (j = 0; j < nv; j++)
5612 os <<
" " << ind[j]+1;
5617 for (p = 1; p <
NRanks; p++)
5619 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5620 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5622 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
5623 for (i = 0; i < ne; i++)
5626 for (j = 0; j < 4; j++)
5628 os <<
" " << k+ints[i*4+j]+1;
5636 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5644 for (j = 0; j < nv; j++)
5646 os <<
" " << ind[j]+1;
5657 for (j = 0; j < 3; j++)
5659 os <<
' ' << ind[j]+1;
5665 for (p = 1; p <
NRanks; p++)
5667 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5668 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5670 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
5671 for (i = 0; i < ne; i++)
5674 for (j = 0; j < 3; j++)
5676 os <<
' ' << k+ints[i*3+j]+1;
5686 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5690 for (j = 0; j <
Dim; j++)
5694 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
5698 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5699 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5705 for (j = 0; j < 4; j++)
5710 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
5713 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5714 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5716 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5721 for (j = 0; j < 3; j++)
5726 for ( ; i < ne; i++)
5729 for (j = 0; j < 3; j++)
5734 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
5740 int i, j, k, nv, ne,
p;
5746 int TG_nv, TG_ne, TG_nbe;
5753 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5756 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
5757 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
5758 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
5759 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
5760 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
5767 <<
" " <<
vertices[i](2) <<
" 0.0\n";
5769 for (p = 1; p <
NRanks; p++)
5771 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5773 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
5774 for (i = 0; i < nv; i++)
5776 os << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
5777 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
5787 os << i+1 <<
" " << 1;
5788 for (j = 0; j < nv; j++)
5790 os <<
" " << ind[j]+1;
5795 for (p = 1; p <
NRanks; p++)
5797 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5798 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5800 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
5801 for (i = 0; i < ne; i++)
5803 os << i+1 <<
" " << p+1;
5804 for (j = 0; j < 8; j++)
5806 os <<
" " << k+ints[i*8+j]+1;
5821 for (j = 0; j < nv; j++)
5823 os <<
" " << ind[j]+1;
5825 os <<
" 1.0 1.0 1.0 1.0\n";
5835 for (j = 0; j < 4; j++)
5837 os <<
' ' << ind[j]+1;
5839 os <<
" 1.0 1.0 1.0 1.0\n";
5842 for (p = 1; p <
NRanks; p++)
5844 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5845 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5847 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
5848 for (i = 0; i < ne; i++)
5851 for (j = 0; j < 4; j++)
5853 os <<
" " << k+ints[i*4+j]+1;
5855 os <<
" 1.0 1.0 1.0 1.0\n";
5865 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5870 for (j = 0; j <
Dim; j++)
5874 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
5876 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5882 for (j = 0; j < 8; j++)
5887 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
5889 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
5891 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5896 for (j = 0; j < 4; j++)
5901 for ( ; i < ne; i++)
5904 for (j = 0; j < 4; j++)
5909 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
5915 int i, j, k, attr, nv, ne,
p;
5923 os <<
"areamesh2\n\n";
5927 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5932 attr =
boundary[i]->GetAttribute();
5935 for (j = 0; j < v.
Size(); j++)
5937 os << v[j] + 1 <<
" ";
5947 for (j = 0; j < v.
Size(); j++)
5949 os << v[j] + 1 <<
" ";
5954 for (p = 1; p <
NRanks; p++)
5956 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5957 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5959 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
5960 for (i = 0; i < ne; i++)
5963 for (j = 0; j < 2; j++)
5965 os <<
" " << k+ints[i*2+j]+1;
5974 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5980 os << 1 <<
" " << 3 <<
" ";
5981 for (j = 0; j < v.
Size(); j++)
5983 os << v[j] + 1 <<
" ";
5988 for (p = 1; p <
NRanks; p++)
5990 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5991 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5993 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
5994 for (i = 0; i < ne; i++)
5996 os << p+1 <<
" " << 3;
5997 for (j = 0; j < 3; j++)
5999 os <<
" " << k+ints[i*3+j]+1;
6008 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6012 for (j = 0; j <
Dim; j++)
6018 for (p = 1; p <
NRanks; p++)
6020 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
6022 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
6023 for (i = 0; i < nv; i++)
6025 for (j = 0; j <
Dim; j++)
6027 os <<
" " << vert[Dim*i+j];
6037 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6040 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
6045 for (j = 0; j < 2; j++)
6050 for ( ; i < ne; i++)
6053 for (j = 0; j < 2; j++)
6058 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
6061 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6068 for (j = 0; j < 3; j++)
6073 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
6076 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
6080 for (j = 0; j <
Dim; j++)
6084 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
6102 MPI_Allreduce(p_min.
GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN,
MyComm);
6103 MPI_Allreduce(p_max.
GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX,
MyComm);
6107 double &gk_min,
double &gk_max)
6109 double h_min, h_max, kappa_min, kappa_max;
6113 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
6114 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
6115 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
6116 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
6123 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
6127 os <<
"Parallel Mesh Stats:" <<
'\n';
6133 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
6139 kappa_min = kappa_max =
kappa;
6143 if (h < h_min) { h_min = h; }
6144 if (h > h_max) { h_max = h; }
6145 if (kappa < kappa_min) { kappa_min =
kappa; }
6146 if (kappa > kappa_max) { kappa_max =
kappa; }
6150 double gh_min, gh_max, gk_min, gk_max;
6151 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
6152 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
6153 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
6154 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
6159 long long mindata[5], maxdata[5], sumdata[5];
6178 MPI_Reduce(ldata, mindata, 5, MPI_LONG_LONG, MPI_MIN, 0,
MyComm);
6179 MPI_Reduce(ldata, sumdata, 5, MPI_LONG_LONG, MPI_SUM, 0,
MyComm);
6180 MPI_Reduce(ldata, maxdata, 5, MPI_LONG_LONG, MPI_MAX, 0,
MyComm);
6186 << setw(12) <<
"minimum"
6187 << setw(12) <<
"average"
6188 << setw(12) <<
"maximum"
6189 << setw(12) <<
"total" <<
'\n';
6191 << setw(12) << mindata[0]
6192 << setw(12) << sumdata[0]/
NRanks
6193 << setw(12) << maxdata[0]
6194 << setw(12) << sumdata[0] <<
'\n';
6196 << setw(12) << mindata[1]
6197 << setw(12) << sumdata[1]/
NRanks
6198 << setw(12) << maxdata[1]
6199 << setw(12) << sumdata[1] <<
'\n';
6203 << setw(12) << mindata[2]
6204 << setw(12) << sumdata[2]/
NRanks
6205 << setw(12) << maxdata[2]
6206 << setw(12) << sumdata[2] <<
'\n';
6209 << setw(12) << mindata[3]
6210 << setw(12) << sumdata[3]/
NRanks
6211 << setw(12) << maxdata[3]
6212 << setw(12) << sumdata[3] <<
'\n';
6214 << setw(12) << mindata[4]
6215 << setw(12) << sumdata[4]/
NRanks
6216 << setw(12) << maxdata[4] <<
'\n';
6219 << setw(12) <<
"minimum"
6220 << setw(12) <<
"maximum" <<
'\n';
6222 << setw(12) << gh_min
6223 << setw(12) << gh_max <<
'\n';
6225 << setw(12) << gk_min
6226 << setw(12) << gk_max <<
'\n';
6233 long long local = value, global;
6234 MPI_Allreduce(&local, &global, 1, MPI_LONG_LONG, MPI_SUM,
MyComm);
6257 Printer(os,
"mfem_serial_mesh_end");
6265 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6276 os <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
6277 for (
int i = 0; i < nv; i++)
6286 os <<
"\nshared_edges " << ne <<
'\n';
6287 for (
int i = 0; i < ne; i++)
6290 os << v[0] <<
' ' << v[1] <<
'\n';
6299 os <<
"\nshared_faces " << nt+nq <<
'\n';
6300 for (
int i = 0; i < nt; i++)
6304 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6307 for (
int i = 0; i < nq; i++)
6311 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6318 os <<
"\nmfem_mesh_end" << endl;
6323 bool high_order_output,
6324 int compression_level,
6327 int pad_digits_rank = 6;
6330 std::string::size_type pos = pathname.find_last_of(
'/');
6332 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
6336 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
6337 std::ofstream os(pvtu_name);
6340 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
6342 os <<
"<?xml version=\"1.0\"?>\n";
6343 os <<
"<VTKFile type=\"PUnstructuredGrid\"";
6344 os <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
6345 os <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
6347 os <<
"<PPoints>\n";
6348 os <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
6349 os <<
" Name=\"Points\" NumberOfComponents=\"3\""
6350 <<
" format=\"" << data_format <<
"\"/>\n";
6351 os <<
"</PPoints>\n";
6354 os <<
"\t<PDataArray type=\"Int32\" ";
6355 os <<
" Name=\"connectivity\" NumberOfComponents=\"1\""
6356 <<
" format=\"" << data_format <<
"\"/>\n";
6357 os <<
"\t<PDataArray type=\"Int32\" ";
6358 os <<
" Name=\"offsets\" NumberOfComponents=\"1\""
6359 <<
" format=\"" << data_format <<
"\"/>\n";
6360 os <<
"\t<PDataArray type=\"UInt8\" ";
6361 os <<
" Name=\"types\" NumberOfComponents=\"1\""
6362 <<
" format=\"" << data_format <<
"\"/>\n";
6363 os <<
"</PCells>\n";
6365 os <<
"<PCellData>\n";
6366 os <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute"
6367 <<
"\" NumberOfComponents=\"1\""
6368 <<
" format=\"" << data_format <<
"\"/>\n";
6369 os <<
"</PCellData>\n";
6371 for (
int ii=0; ii<
NRanks; ii++)
6373 std::string piece = fname +
".proc"
6375 os <<
"<Piece Source=\"" << piece <<
"\"/>\n";
6378 os <<
"</PUnstructuredGrid>\n";
6379 os <<
"</VTKFile>\n";
6383 std::string vtu_fname = pathname +
"/" + fname +
".proc"
6385 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
6392 const int npts = point_mat.
Width();
6393 if (npts == 0) {
return 0; }
6395 const bool no_warn =
false;
6402 Array<int> my_point_rank(npts), glob_point_rank(npts);
6403 for (
int k = 0; k < npts; k++)
6405 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
6408 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
6409 MPI_INT, MPI_MIN,
MyComm);
6412 for (
int k = 0; k < npts; k++)
6414 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
6418 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
6421 if (warn && pts_found != npts &&
MyRank == 0)
6423 MFEM_WARNING((npts-pts_found) <<
" points were not found");
6428 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &os)
6431 for (
int d = 1; d < space_dim; d++)
6439 stringstream out_name;
6440 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
6441 <<
".shared_entities";
6442 ofstream os(out_name.str().c_str());
6450 os <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
6461 os <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
6462 for (
int i = 0; i < nv; i++)
6474 os <<
"\nshared_edges " << ne <<
'\n';
6475 for (
int i = 0; i < ne; i++)
6491 os <<
"\nshared_faces " << nt+nq <<
'\n';
6492 for (
int i = 0; i < nt; i++)
6497 for (
int j = 0; j < 3; j++) { os <<
' ' << v[j]; }
6500 for (
int j = 0; j < 3; j++)
6503 (j < 2) ? os <<
" | " : os <<
'\n';
6506 for (
int i = 0; i < nq; i++)
6511 for (
int j = 0; j < 4; j++) { os <<
' ' << v[j]; }
6514 for (
int j = 0; j < 4; j++)
6517 (j < 3) ? os <<
" | " : os <<
'\n';
6533 for (
int i=0; i<
GetNV(); ++i)
6558 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6586 const int ldof = (dofs[0] >= 0) ? dofs[0] : -1 - dofs[0];
6599 for (
int i=0; i<
GetNE(); ++i)
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for all finite elements.
void UniformRefinement3D() override
Refine a mixed 3D mesh uniformly.
Geometry::Type GetGeometryType() const
int GetGroupMasterRank(int g) const
Return the rank of the group master for group 'g'.
int GetNFaceNeighbors() const
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="")
Ordering::Type GetOrdering() const
Return the ordering method.
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
int Size() const
Return the logical size of the array.
void GroupQuadrilateral(int group, int i, int &face, int &o) 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)
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.
void GetGlobalFaceIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void LoadSharedEntities(std::istream &input)
void Bcast(T *ldata, int layout) const
Broadcast within each group where the master is the root.
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 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
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
int FindSharedVertices(const int *partition, Table *vertex_element, ListOfIntegerSets &groups)
int GroupNVertices(int group) const
void AddColumnsInRow(int r, int ncol)
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.
int GroupNEdges(int group) const
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
virtual void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
int GroupNTriangles(int group) const
static ParMesh MakeRefined(ParMesh &orig_mesh, int ref_factor, int ref_type)
Create a uniformly refined (by any factor) version of orig_mesh.
Array< Element * > boundary
const FiniteElement * GetTraceElement(int i, Geometry::Type geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
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 GetBdrElementFace(int i, int *f, int *o) const
Return the index and the orientation of the face of bdr element i. (3D)
CoarseFineTransformations CoarseFineTr
void SetSize(int s)
Resize the vector to size s.
int GetNBE() const
Returns number of boundary elements.
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 GetSharedVertexCommunicator(int ordering, GroupCommunicator &svert_comm) const
Get the shared vertices GroupCommunicator.
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.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
int GetGroupSize(int g) const
Get the number of processors in a group.
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
Element::Type GetElementType(int i) const
Returns the type of element i.
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
void ShiftRight(int &a, int &b, int &c)
void SetDims(int rows, int nnz)
static const int FaceVert[NumFaces][MaxFaceVert]
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)
const int * GetGroup(int g) const
Return a pointer to a list of neighbors for a given group. Neighbor 0 is the local processor...
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
T * GetData()
Returns the data.
static const int FaceVert[NumFaces][MaxFaceVert]
virtual DofTransformation * GetBdrElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom for i'th boundary element.
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.
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
int GetLocalElementNum(long long global_element_num) const
void ApplyLocalSlaveTransformation(FaceElementTransformations &FT, const FaceInfo &fi, bool is_ghost)
int GetBdrElementEdgeIndex(int i) const
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].
int GetNE() const
Returns number of elements.
void SynchronizeDerefinementData(Array< Type > &elem_data, const Table &deref_table)
const Element * GetFace(int i) const
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...
void NonconformingRefinement(const Array< Refinement > &refinements, int nc_limit=0) override
This function is not public anymore. Use GeneralRefinement instead.
void EnsureParNodes()
If the mesh is curved, make sure 'Nodes' is ParGridFunction.
virtual void SetVertices(const int *ind)
Set the indices the element according to the input.
void UniformRefineGroups3D(int old_nv, int old_nedges, const DSTable &old_v_to_v, const STable3D &old_faces, Array< int > *f2qf)
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
virtual int DofForGeometry(Geometry::Type GeomType) const
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".
void GetVertices(Vector &vert_coord) const
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 MarkTetMeshForRefinement(DSTable &v_to_v) override
void BuildFaceGroup(int ngroups, const Mesh &mesh, const Array< int > &face_group, int &nstria, int &nsquad)
double * GetData() const
Return a pointer to the beginning of the Vector data.
void Swap(GroupTopology &other)
Swap the internal data with another GroupTopology object.
virtual FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
int Index(int r, int c, int f) const
Geometry::Type GetElementBaseGeometry(int i) const
int Size_of_connections() const
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
const NCList & GetSharedEdges()
STable3D * GetSharedFacesTable()
void GetVertexToVertexTable(DSTable &) const
void RedRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
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.
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
bool IAmMaster(int g) const
Return true if I am master for group 'g'.
bool WantSkipSharedMaster(const NCMesh::Master &master) const
void OnMeshUpdated(Mesh *mesh)
A parallel extension of the NCMesh class.
void GetSharedEdgeDofs(int group, int ei, Array< int > &dofs) const
Element * NewElement(int geom)
FaceElementTransformations FaceElemTr
Element::Type GetFaceElementType(int Face) 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.
virtual int GetTrueVSize() const
Return the number of local vector true dofs.
int FindSharedEdges(const Mesh &mesh, const int *partition, Table *&edge_element, ListOfIntegerSets &groups)
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
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)
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
virtual void GetElementDofValues(int el, Vector &dof_vals) const
void NURBSUniformRefinement() override
Refine NURBS mesh.
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
void GetElementJacobian(int i, DenseMatrix &J)
void GetVertexDofs(int i, Array< int > &dofs) const
void MarkEdge(DenseMatrix &pmat)
int AddVertex(double x, double y=0.0, double z=0.0)
const int * GetDofMap(Geometry::Type GeomType) const
Get the Cartesian to local H1 dof map.
bool Nonconforming() const
int BuildLocalBoundary(const Mesh &global_mesh, const int *partitioning, const Array< int > &vert_global_local, Array< bool > &activeBdrElem, Table *&edge_element)
Fills out partitioned Mesh::boundary.
Communicator performing operations within groups defined by a GroupTopology with arbitrary-size data ...
const FiniteElement * GetFaceNbrFE(int i) const
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
Array< int > face_nbr_elements_offset
void GetEdgeOrdering(DSTable &v_to_v, Array< int > &order)
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)
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)
const Table & GetDerefinementTable()
Mesh GetSerialMesh(int save_rank) const
Array< Element * > shared_edges
virtual void SetAttributes()
int Append(const T &el)
Append element 'el' to array, resize if necessary.
int GetSharedFace(int sface) const
Return the local face index for the given shared face.
int GetNumNeighbors() const
Return the number of neighbors including the local processor.
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)
Returns the transformation defining the given face element in a user-defined variable.
FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31) override
static const int NumVerts[NumGeom]
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.
Table send_face_nbr_vertices
Type
Constants for the classes derived from Element.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
int InitialPartition(int index) const
Helper to get the partitioning when the serial mesh gets split initially.
This structure stores the low level information necessary to interpret the configuration of elements ...
VTKFormat
Data array format for VTK and VTU files.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
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...
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 GetSharedQuadrilateralDofs(int group, int fi, Array< int > &dofs) 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)
GeometryRefiner GlobGeometryRefiner
int GetAttribute() const
Return element's attribute.
int GetElementToEdgeTable(Table &, Array< int > &)
virtual MFEM_DEPRECATED int GetNFaces(int &nFaceVertices) const =0
const Element * GetElement(int i) const
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 GetGlobalVertexIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
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 ...
void GetSharedTriangleDofs(int group, int fi, Array< int > &dofs) const
IsoparametricTransformation Transformation2
Table * face_nbr_el_to_face
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
FiniteElementCollection * OwnFEC()
int Size() const
Returns the number of TYPE I elements.
int GetVDim() const
Returns vector dimension.
long long ReduceInt(int value) const override
Utility function: sum integers from all processors (Allreduce).
FiniteElementSpace * FESpace()
int Size()
Return the number of integer sets in the list.
STable3D * GetFaceNbrElementToFaceTable(int ret_ftbl=0)
virtual DofTransformation * GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
Array< Vert4 > shared_quads
void Rebalance(const Array< int > *custom_partition=NULL)
int slaves_end
slave faces
Data type tetrahedron element.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
void PrintXG(std::ostream &out=mfem::out) const override
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)
int CheckBdrElementOrientation(bool fix_it=true)
Check the orientation of the boundary elements.
int SpaceDimension() const
int GroupNQuadrilaterals(int group) const
void Save(std::ostream &out) const
Save the data in a stream.
HYPRE_BigInt GetGlobalTDofNumber(int ldof) const
Returns the global tdof number of the given local degree of freedom.
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
void Swap(Array< T > &, Array< T > &)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
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.
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...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void GetSharedTriCommunicator(int ordering, GroupCommunicator &stria_comm) const
Get the shared face triangles GroupCommunicator.
static void PrintElement(const Element *, std::ostream &)
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
void Swap(ParMesh &other)
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 PrintSharedEntities(const char *fname_prefix) const
Debugging method.
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
long long glob_elem_offset
bool IsSlaveFace(const FaceInfo &fi) const
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.
void DeleteLast()
Delete the last entry of the array.
void GetFaceNbrElementFaces(int i, Array< int > &fcs, Array< int > &cor) const
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
double GetLength(int i, int j) const
Return the length of the segment from node i to node j.
static const int FaceVert[NumFaces][MaxFaceVert]
void GetSharedEdgeCommunicator(int ordering, GroupCommunicator &sedge_comm) const
Get the shared edges GroupCommunicator.
void BuildVertexGroup(int ngroups, const Table &vert_element)
void SaveAsOne(const char *fname, int precision=16) const
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name...
void GetFaceNbrElementTransformation(int i, IsoparametricTransformation *ElTr)
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual const char * Name() const
void DistributeAttributes(Array< int > &attr)
Ensure that bdr_attributes and attributes agree across processors.
long long GetGlobalElementNum(int local_element_num) const
Map a local element number to a global element number.
void GroupEdge(int group, int i, int &edge, int &o) const
virtual void Refine(const Array< Refinement > &refinements)
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.
void GetSharedQuadCommunicator(int ordering, GroupCommunicator &squad_comm) const
Get the shared face quadrilaterals GroupCommunicator.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
const FiniteElementSpace * GetNodalFESpace() const
void ComputeGlobalElementOffset() const
void ExchangeFaceNbrNodes()
virtual void Print(std::ostream &os=mfem::out) const
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
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.
virtual int GetFaceDofs(int i, Array< int > &dofs, int variant=0) const
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".
long long GetGlobalNE() const
Return the total (global) number of elements.
Table group_svert
Shared objects in each group.
void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1) override
bool DecodeFaceSplittings(HashTable< Hashed2 > &v_to_v, const int *v, const Array< unsigned > &codes, int &pos)
Array< MeshId > conforming
double GetFaceNbrElementSize(int i, int type=0)
void GroupTriangle(int group, int i, int &face, int &o) const
void GetGlobalElementIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are supported.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int index(int i, int j, int nx, int ny)
bool IsGhost(int entity, int index) const
Return true if the specified vertex/edge/face is a ghost.
double CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
void MakeSimplicial_(const Mesh &orig_mesh, int *vglobal)
Array< FaceInfo > faces_info
virtual int GetNVertices() const =0
void SetAttribute(const int attr)
Set element's attribute.
void GetGlobalEdgeIndices(Array< HYPRE_BigInt > &gi) const
AMR meshes are not supported.
STable3D * GetFacesTable()
NCMesh * ncmesh
Optional nonconforming mesh extension.
int GroupVertex(int group, int i) const
int AddBdrElement(Element *elem)
T & Last()
Return the last element in the array.
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.
Geometry::Type GetFaceGeometryType(int Face) const
int GetNEdges() const
Return the number of edges.
double AggregateError(const Array< double > &elem_error, const int *fine, int nfine, int op)
Derefinement helper.
void GetMarkedFace(const int face, int *fv)
int GetNFaces() const
Return the number of faces in a 3D mesh.
virtual int FindPoints(DenseMatrix &point_mat, Array< int > &elem_ids, Array< IntegrationPoint > &ips, bool warn=true, InverseElementTransformation *inv_trans=NULL)
Find the ids of the elements that contain the given points, and their corresponding reference coordin...
Arbitrary order H(curl)-conforming Nedelec finite elements.
const FiniteElementCollection * FEColl() const
void GetNodes(Vector &node_coord) const
virtual int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type, does not count master nonconforming face...
int NumberOfEntries() 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 PrintAsOne(std::ostream &out=mfem::out) const
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()
void SaveAsOne(const char *fname, int precision=16) 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)
Class for parallel grid function.
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Table send_face_nbr_elements
Table * GetFaceToAllElementTable() const
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
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.
void Load(std::istream &input, int generate_edges=0, int refine=1, bool fix_orientation=true) override
Parallel version of Mesh::Load().
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
void ParPrint(std::ostream &out) const
Save the mesh in a parallel mesh format.
Class for parallel meshes.
void PrintAsSerial(std::ostream &out=mfem::out) const
Abstract data type element.
int GetAttribute(int i) const
Return the attribute of element i.
int GetFaceNbrRank(int fn) const
const Table & ElementToEdgeTable() const
Data type line segment element.
void BdrBisection(int i, const HashTable< Hashed2 > &)
Bisect a boundary triangle: boundary element with index i is bisected.
void GenerateNCFaceInfo()
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
void Save(const char *fname, int precision=16) const override
void GenerateOffsets(int N, HYPRE_BigInt loc_sizes[], Array< HYPRE_BigInt > *offsets[]) const
virtual Type GetType() const =0
Returns element's type.
virtual void LimitNCLevel(int max_nc_level)
Parallel version of NCMesh::LimitNCLevel.
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.
const Element * GetBdrElement(int i) const
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 refinement.
Defines the position of a fine element within a coarse element.
MFEM_DEPRECATED void ReorientTetMesh() override
See the remarks for the serial version in mesh.hpp.
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
DofTransformation * GetFaceNbrElementVDofs(int i, Array< int > &vdofs) const
void GreenRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
Arbitrary order "L2-conforming" discontinuous finite elements.
void Printer(std::ostream &out=mfem::out, std::string section_delimiter="") const
ParFiniteElementSpace * ParFESpace() const