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),
38 glob_offset_sequence(-1),
80 if (pmesh.
Nodes && copy_nodes)
97 : glob_elem_offset(-1)
98 , glob_offset_sequence(-1)
101 int *partitioning = NULL;
112 partitioning = partitioning_;
117 partitioning =
new int[mesh.
GetNE()];
118 for (
int i = 0; i < mesh.
GetNE(); i++)
148 partitioning = partitioning_;
162 Table *edge_element = NULL;
165 activeBdrElem, edge_element);
203 int nsedges =
FindSharedEdges(mesh, partitioning, edge_element, groups);
210 int ngroups = groups.
Size()-1, nstris, nsquads;
217 face_group, vert_global_local);
236 "invalid NURBS mesh");
256 Nodes->MakeOwner(nfec);
262 int element_counter = 0;
263 for (
int i = 0; i < mesh.
GetNE(); i++)
265 if (partitioning[i] ==
MyRank)
268 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
269 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
276 if (partitioning != partitioning_)
278 delete [] partitioning;
286 const int* partitioning,
290 vert_global_local = -1;
292 int vert_counter = 0;
293 for (
int i = 0; i < mesh.
GetNE(); i++)
295 if (partitioning[i] ==
MyRank)
299 for (
int j = 0; j < vert.
Size(); j++)
301 if (vert_global_local[vert[j]] < 0)
303 vert_global_local[vert[j]] = vert_counter++;
311 for (
int i = 0; i < vert_global_local.
Size(); i++)
313 if (vert_global_local[i] >= 0)
315 vert_global_local[i] = vert_counter++;
321 for (
int i = 0; i < vert_global_local.
Size(); i++)
323 if (vert_global_local[i] >= 0)
337 for (
int i = 0; i < mesh.
GetNE(); i++)
339 if (partitioning[i] ==
MyRank) { nelems++; }
347 int element_counter = 0;
348 for (
int i = 0; i < mesh.
GetNE(); i++)
350 if (partitioning[i] ==
MyRank)
353 int *v =
elements[element_counter]->GetVertices();
354 int nv =
elements[element_counter]->GetNVertices();
355 for (
int j = 0; j < nv; j++)
357 v[j] = vert_global_local[v[j]];
363 return element_counter;
369 Table*& edge_element)
376 activeBdrElem =
false;
381 for (
int i = 0; i < mesh.
GetNBE(); i++)
383 int face, o, el1, el2;
386 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
391 activeBdrElem[i] =
true;
396 int bdrelem_counter = 0;
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)
406 int *v =
boundary[bdrelem_counter]->GetVertices();
407 int nv =
boundary[bdrelem_counter]->GetNVertices();
408 for (
int j = 0; j < nv; j++)
410 v[j] = vert_global_local[v[j]];
418 edge_element =
new Table;
421 for (
int i = 0; i < mesh.
GetNBE(); i++)
424 int el1 = edge_element->
GetRow(edge)[0];
425 if (partitioning[el1] ==
MyRank)
430 activeBdrElem[i] =
true;
435 int bdrelem_counter = 0;
437 for (
int i = 0; i < mesh.
GetNBE(); i++)
440 int el1 = edge_element->
GetRow(edge)[0];
441 if (partitioning[el1] ==
MyRank)
444 int *v =
boundary[bdrelem_counter]->GetVertices();
445 int nv =
boundary[bdrelem_counter]->GetNVertices();
446 for (
int j = 0; j < nv; j++)
448 v[j] = vert_global_local[v[j]];
456 for (
int i = 0; i < mesh.
GetNBE(); i++)
458 int vert = mesh.
boundary[i]->GetVertices()[0];
461 if (partitioning[el1] ==
MyRank)
467 int bdrelem_counter = 0;
469 for (
int i = 0; i < mesh.
GetNBE(); i++)
471 int vert = mesh.
boundary[i]->GetVertices()[0];
474 if (partitioning[el1] ==
MyRank)
477 int *v =
boundary[bdrelem_counter]->GetVertices();
478 v[0] = vert_global_local[v[0]];
495 for (
int i = 0; i < face_group.
Size(); i++)
502 el[0] = partitioning[el[0]];
503 el[1] = partitioning[el[1]];
508 face_group[i] = groups.
Insert(group) - 1;
515 Table*& edge_element,
521 int sedge_counter = 0;
524 edge_element =
new Table;
535 for (
int i = 0; i < edge_element->
Size(); i++)
537 int me = 0, others = 0;
538 for (
int j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
540 int k = edge_element->
GetJ()[j];
541 int rank = partitioning[k];
542 edge_element->
GetJ()[j] = rank;
561 edge_element->
GetRow(i)[0] = -1;
565 return sedge_counter;
574 int svert_counter = 0;
575 for (
int i = 0; i < vert_element->
Size(); i++)
577 int me = 0, others = 0;
578 for (
int j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
580 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
595 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
599 vert_element->
GetI()[i] = -1;
602 return svert_counter;
607 int &nstria,
int &nsquad)
613 for (
int i = 0; i < face_group.
Size(); i++)
615 if (face_group[i] >= 0)
632 for (
int i = 0; i < face_group.
Size(); i++)
634 if (face_group[i] >= 0)
655 for (
int i = 0; i < edge_element.
Size(); i++)
657 if (edge_element.
GetRow(i)[0] >= 0)
665 int sedge_counter = 0;
666 for (
int i = 0; i < edge_element.
Size(); i++)
668 if (edge_element.
GetRow(i)[0] >= 0)
681 for (
int i = 0; i < vert_element.
Size(); i++)
683 if (vert_element.
GetI()[i] >= 0)
691 int svert_counter = 0;
692 for (
int i = 0; i < vert_element.
Size(); i++)
694 if (vert_element.
GetI()[i] >= 0)
704 const Mesh& mesh,
int *partitioning,
713 if (
Dim < 3) {
return; }
715 int stria_counter = 0;
716 int squad_counter = 0;
717 for (
int i = 0; i < face_group.
Size(); i++)
719 if (face_group[i] < 0) {
continue; }
729 for (
int j = 0; j < 3; j++)
731 v[j] = vert_global_local[v[j]];
733 const int lface = (*faces_tbl)(v[0], v[1], v[2]);
749 if (
MyRank == partitioning[gl_el2])
751 std::swap(v[0], v[1]);
763 for (
int j = 0; j < 4; j++)
765 v[j] = vert_global_local[v[j]];
768 (*faces_tbl)(v[0], v[1], v[2], v[3]);
774 MFEM_ABORT(
"unknown face type: " << face->
GetType());
782 const Table* edge_element)
794 int sedge_counter = 0;
795 for (
int i = 0; i < edge_element->
Size(); i++)
797 if (edge_element->
GetRow(i)[0] >= 0)
803 new Segment(vert_global_local[vert[0]],
804 vert_global_local[vert[1]], 1);
806 sedge_ledge[sedge_counter] = v_to_v(vert_global_local[vert[0]],
807 vert_global_local[vert[1]]);
809 MFEM_VERIFY(
sedge_ledge[sedge_counter] >= 0,
"Error in v_to_v.");
824 int svert_counter = 0;
825 for (
int i = 0; i < vert_element->
Size(); i++)
827 if (vert_element->
GetI()[i] >= 0)
829 svert_lvert[svert_counter++] = vert_global_local[i];
837 : MyComm(pncmesh.MyComm)
838 , NRanks(pncmesh.NRanks)
839 , MyRank(pncmesh.MyRank)
840 , glob_elem_offset(-1)
841 , glob_offset_sequence(-1)
865 MPI_Allreduce(&loc_meshgen, &
meshgen, 1, MPI_INT, MPI_BOR,
MyComm);
879 const int l_edge = v_to_v(v[0], v[1]);
880 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
891 for (
int st = 0; st < nst; st++)
906 : glob_elem_offset(-1)
907 , glob_offset_sequence(-1)
920 const int gen_edges = 1;
925 Loader(input, gen_edges,
"mfem_serial_mesh_end");
933 MFEM_VERIFY(ident ==
"communication_groups",
934 "input stream is not a parallel MFEM mesh");
942 input >> ident >> num_sverts;
951 input >> ident >> num_sedges;
965 input >> ident >> num_sface;
978 int svert_counter = 0, sedge_counter = 0;
988 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
989 <<
", read group " << g << endl;
996 input >> ident >> nv;
999 "incorrect number of total_shared_vertices");
1001 for ( ; svert_counter < nv; svert_counter++)
1010 input >> ident >> ne;
1011 ne += sedge_counter;
1013 "incorrect number of total_shared_edges");
1015 for ( ; sedge_counter < ne; sedge_counter++)
1018 input >> v[0] >> v[1];
1025 input >> ident >> nf;
1026 for (
int i = 0; i < nf; i++)
1035 for (
int i = 0; i < 3; i++) { input >> v[i]; }
1040 for (
int i = 0; i < 4; i++) { input >> v[i]; }
1043 MFEM_ABORT(
"invalid shared face geometry: " << geom);
1054 "incorrect number of total_shared_faces");
1070 const bool fix_orientation =
false;
1081 :
Mesh(orig_mesh, ref_factor, ref_type),
1082 MyComm(orig_mesh->GetComm()),
1083 NRanks(orig_mesh->GetNRanks()),
1084 MyRank(orig_mesh->GetMyRank()),
1085 glob_elem_offset(-1),
1086 glob_offset_sequence(-1),
1087 gtopo(orig_mesh->gtopo),
1088 have_face_nbr_data(false),
1167 for (
int j = 0; j < orig_n_verts; j++)
1174 const int orig_n_edges = orig_mesh->
GroupNEdges(gr);
1175 if (orig_n_edges > 0)
1180 const int *c2h_map = rfec.
GetDofMap(geom);
1182 for (
int e = 0; e < orig_n_edges; e++)
1187 for (
int j = 2; j < rdofs.
Size(); j++)
1195 for (
int k = 0; k < nvert; k++)
1198 v[k] = rdofs[c2h_map[cid]];
1214 const int *c2h_map = rfec.
GetDofMap(geom);
1216 for (
int f = 0;
f < orig_nt;
f++)
1221 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1230 for (
int k = 0; k < 2; k++)
1232 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1241 for (
int k = 0; k < nvert; k++)
1244 v[k] = rdofs[c2h_map[cid]];
1258 const int *c2h_map = rfec.
GetDofMap(geom);
1260 for (
int f = 0;
f < orig_nq;
f++)
1265 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1274 for (
int k = 0; k < 2; k++)
1276 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1285 for (
int k = 0; k < nvert; k++)
1288 v[k] = rdofs[c2h_map[cid]];
1312 const int meshgen_save =
meshgen;
1341 int max_attr = attr.
Max();
1342 int glb_max_attr = -1;
1343 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1347 bool * attr_marker =
new bool[glb_max_attr];
1348 bool * glb_attr_marker =
new bool[glb_max_attr];
1349 for (
int i=0; i<glb_max_attr; i++)
1351 attr_marker[i] =
false;
1353 for (
int i=0; i<attr.
Size(); i++)
1355 attr_marker[attr[i] - 1] =
true;
1357 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1358 MPI_C_BOOL, MPI_LOR,
MyComm);
1359 delete [] attr_marker;
1363 glb_attr.
SetSize(glb_max_attr);
1364 glb_attr = glb_max_attr;
1366 for (
int i=0; i<glb_max_attr; i++)
1368 if (glb_attr_marker[i])
1370 glb_attr[o++] = i + 1;
1373 delete [] glb_attr_marker;
1377 glb_attr.
Copy(attr);
1388 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1394 MFEM_WARNING(
"Non-positive element attributes found!");
1403 o = (v[0] < v[1]) ? (+1) : (-1);
1412 "Expecting a triangular face.");
1423 "Expecting a quadrilateral face.");
1439 gr_sedge.
GetI()[0] = 0;
1458 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1461 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1463 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1466 if (n == 0) {
continue; }
1467 sedge_ord_map.SetSize(n);
1468 for (
int j = 0; j < n; j++)
1470 sedge_ord_map[j].one = sedge_ord[k+j];
1471 sedge_ord_map[j].two = j;
1473 SortPairs<int, int>(sedge_ord_map, n);
1474 for (
int j = 0; j < n; j++)
1477 const int *v =
shared_edges[sedge_from]->GetVertices();
1478 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1480 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1481 for (
int j = 0; j < n; j++)
1485 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1499 ilen_len[j].one = order[j];
1500 ilen_len[j].two =
GetLength(i, it.Column());
1504 SortPairs<int, double>(ilen_len, order.
Size());
1507 for (
int i = 1; i < order.
Size(); i++)
1509 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1519 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1522 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1534 elements[i]->MarkEdge(v_to_v, order);
1542 boundary[i]->MarkEdge(v_to_v, order);
1561 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1578 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1579 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1581 if (bit == 8*
sizeof(
unsigned))
1587 const face_t &
f = face_stack.
Last();
1588 int mid = v_to_v.
FindId(f.one, f.two);
1598 face_stack.
Append(face_t(f.three, f.one, mid));
1599 face_t &r = face_stack[face_stack.
Size()-2];
1600 r = face_t(r.two, r.three, mid);
1612 bool need_refinement = 0;
1613 face_stack.
Append(face_t(v[0], v[1], v[2]));
1614 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1616 if (bit == 8*
sizeof(
unsigned))
1618 code = codes[pos++];
1622 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1624 const face_t &
f = face_stack.
Last();
1625 int mid = v_to_v.
FindId(f.one, f.two);
1628 mid = v_to_v.
GetId(f.one, f.two);
1629 int ind[2] = { f.one, f.two };
1632 need_refinement = 1;
1635 face_stack.
Append(face_t(f.three, f.one, mid));
1636 face_t &r = face_stack[face_stack.
Size()-2];
1637 r = face_t(r.two, r.three, mid);
1639 return need_refinement;
1645 if (HYPRE_AssumedPartitionCheck())
1648 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_INT, MPI_SUM,
MyComm);
1649 for (
int i = 0; i < N; i++)
1652 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1653 (*offsets[i])[1] = temp[i];
1656 for (
int i = 0; i < N; i++)
1658 (*offsets[i])[2] = temp[i];
1660 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1661 "overflow in offsets");
1667 MPI_Allgather(loc_sizes, N, HYPRE_MPI_INT, temp.
GetData(), N,
1669 for (
int i = 0; i < N; i++)
1674 for (
int j = 0; j <
NRanks; j++)
1676 offs[j+1] = offs[j] + temp[i+N*j];
1680 "overflow in offsets");
1704 for (
int j = 0; j < nv; j++)
1723 for (
int j = 0; j < n; j++)
1725 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
1733 MFEM_ABORT(
"Nodes are not ParGridFunction!");
1761 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
1798 bool del_tables =
false;
1825 gr_sface =
new Table;
1855 if (del_tables) {
delete gr_sface; }
1866 int num_face_nbrs = 0;
1869 if (gr_sface->
RowSize(g-1) > 0)
1877 if (num_face_nbrs == 0)
1887 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
1889 if (gr_sface->
RowSize(g-1) > 0)
1894 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
1896 rank_group[counter].two = g;
1901 SortPairs<int, int>(rank_group, rank_group.
Size());
1903 for (
int fn = 0; fn < num_face_nbrs; fn++)
1909 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1910 MPI_Request *send_requests = requests;
1911 MPI_Request *recv_requests = requests + num_face_nbrs;
1912 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1914 int *nbr_data =
new int[6*num_face_nbrs];
1915 int *nbr_send_data = nbr_data;
1916 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
1923 Table send_face_nbr_elemdata, send_face_nbr_facedata;
1927 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
1928 send_face_nbr_facedata.
MakeI(num_face_nbrs);
1929 for (
int fn = 0; fn < num_face_nbrs; fn++)
1932 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1933 int *sface = gr_sface->
GetRow(nbr_group-1);
1934 for (
int i = 0; i < num_sfaces; i++)
1936 int lface = s2l_face[sface[i]];
1938 if (el_marker[el] != fn)
1943 const int nv =
elements[el]->GetNVertices();
1944 const int *v =
elements[el]->GetVertices();
1945 for (
int j = 0; j < nv; j++)
1946 if (vertex_marker[v[j]] != fn)
1948 vertex_marker[v[j]] = fn;
1959 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
1964 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1965 &send_requests[fn]);
1966 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1967 &recv_requests[fn]);
1971 send_face_nbr_elemdata.
MakeJ();
1972 send_face_nbr_facedata.
MakeJ();
1976 for (
int fn = 0; fn < num_face_nbrs; fn++)
1979 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1980 int *sface = gr_sface->
GetRow(nbr_group-1);
1981 for (
int i = 0; i < num_sfaces; i++)
1983 const int sf = sface[i];
1984 int lface = s2l_face[sf];
1986 if (el_marker[el] != fn)
1991 const int nv =
elements[el]->GetNVertices();
1992 const int *v =
elements[el]->GetVertices();
1993 for (
int j = 0; j < nv; j++)
1994 if (vertex_marker[v[j]] != fn)
1996 vertex_marker[v[j]] = fn;
2011 const int *lf_v =
faces[lface]->GetVertices();
2031 for (
int fn = 0; fn < num_face_nbrs; fn++)
2037 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
2038 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
2039 int *facedata = send_face_nbr_facedata.
GetRow(fn);
2041 for (
int i = 0; i < num_verts; i++)
2043 vertex_marker[verts[i]] = i;
2046 for (
int el = 0; el < num_elems; el++)
2048 const int nv =
elements[elems[el]]->GetNVertices();
2050 for (
int j = 0; j < nv; j++)
2052 elemdata[j] = vertex_marker[elemdata[j]];
2056 el_marker[elems[el]] = el;
2059 for (
int i = 0; i < num_sfaces; i++)
2061 facedata[2*i] = el_marker[facedata[2*i]];
2065 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2068 Table recv_face_nbr_elemdata;
2073 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2076 for (
int fn = 0; fn < num_face_nbrs; fn++)
2084 recv_face_nbr_elemdata.
MakeJ();
2086 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2089 for (
int fn = 0; fn < num_face_nbrs; fn++)
2094 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2095 send_face_nbr_elemdata.
RowSize(fn),
2096 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2098 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2099 recv_face_nbr_elemdata.
RowSize(fn),
2100 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2108 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2110 if (fn == MPI_UNDEFINED)
2118 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2120 for (
int i = 0; i < num_elems; i++)
2126 for (
int j = 0; j < nv; j++)
2128 recv_elemdata[j] += vert_off;
2131 recv_elemdata += nv;
2136 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2139 recv_face_nbr_facedata.
SetSize(
2141 for (
int fn = 0; fn < num_face_nbrs; fn++)
2146 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2147 send_face_nbr_facedata.
RowSize(fn),
2148 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2151 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2152 send_face_nbr_facedata.
RowSize(fn),
2153 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2160 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2162 if (fn == MPI_UNDEFINED)
2169 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2170 int *sface = gr_sface->
GetRow(nbr_group-1);
2172 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2174 for (
int i = 0; i < num_sfaces; i++)
2176 const int sf = sface[i];
2177 int lface = s2l_face[sf];
2179 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2180 int info = facedata[2*i+1];
2188 int nbr_ori = info%64, nbr_v[4];
2189 const int *lf_v =
faces[lface]->GetVertices();
2196 for (
int j = 0; j < 3; j++)
2198 nbr_v[perm[j]] = sf_v[j];
2208 for (
int j = 0; j < 4; j++)
2210 nbr_v[perm[j]] = sf_v[j];
2216 info = 64*(info/64) + nbr_ori;
2222 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2239 else if (
Nodes == NULL)
2249 if (!num_face_nbrs) {
return; }
2251 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2252 MPI_Request *send_requests = requests;
2253 MPI_Request *recv_requests = requests + num_face_nbrs;
2254 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2258 for (
int i = 0; i < send_vertices.Size(); i++)
2264 for (
int fn = 0; fn < num_face_nbrs; fn++)
2271 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
2276 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
2279 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2280 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2288 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2299 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2341 for (
int i = 0; i < s2l_face->
Size(); i++)
2356 for (
int i = 0; i < s2l_face->
Size(); i++)
2358 int lface = (*s2l_face)[i];
2359 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2385 #if 0 // TODO: handle the case of non-interpolatory Nodes
2394 FETr->
SetFE(face_el);
2416 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
2430 Elem2NbrNo = -1 - face_info.
Elem2No;
2474 if (is_ghost || fill2)
2497 mfem::out <<
"\nInternal error: face id = " << FaceNo
2498 <<
", dist = " << dist <<
", rank = " <<
MyRank <<
'\n';
2500 MFEM_ABORT(
"internal error");
2521 MFEM_ASSERT(
Dim > 1,
"");
2540 MFEM_ASSERT(
Dim > 1,
"");
2543 return sface < csize
2545 : shared.
slaves[sface - csize].index;
2552 void Rotate3Indirect(
int &
a,
int &
b,
int &c,
2555 if (order[a] < order[b])
2557 if (order[a] > order[c])
2564 if (order[b] < order[c])
2585 Table *old_elem_vert = NULL;
2599 gr_svert.
GetI()[0] = 0;
2624 svert_comm.
Bcast(svert_master_index);
2638 for (
int i = 0; i <
vertices.Size(); i++)
2640 int s = lvert_svert[i];
2643 glob_vert_order[i] =
2644 (std::int64_t(svert_master_rank[s]) << 32) + svert_master_index[s];
2648 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
2660 int *v =
elements[i]->GetVertices();
2662 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2664 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
2666 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
2680 int *v =
boundary[i]->GetVertices();
2682 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2686 const bool check_consistency =
true;
2687 if (check_consistency)
2696 gr_stria.
GetI()[0] = 0;
2708 for (
int i = 0; i < stria_flag.Size(); i++)
2711 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
2713 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
2717 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
2722 stria_comm.
Bcast(stria_master_flag);
2723 for (
int i = 0; i < stria_flag.Size(); i++)
2726 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
2727 "inconsistent vertex ordering found, shared triangle "
2729 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
2730 <<
"local flag: " << stria_flag[i]
2731 <<
", master flag: " << stria_master_flag[i]);
2740 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2756 delete old_elem_vert;
2769 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
2778 int uniform_refinement = 0;
2782 uniform_refinement = 1;
2793 for (
int i = 0; i < marked_el.
Size(); i++)
2799 for (
int i = 0; i < marked_el.
Size(); i++)
2808 for (
int i = 0; i < marked_el.
Size(); i++)
2825 int need_refinement;
2826 int max_faces_in_group = 0;
2832 face_splittings[i].
Reserve(faces_in_group);
2833 if (faces_in_group > max_faces_in_group)
2835 max_faces_in_group = faces_in_group;
2841 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
2844 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2845 int ref_loops_all = 0, ref_loops_par = 0;
2849 need_refinement = 0;
2852 if (
elements[i]->NeedRefinement(v_to_v))
2854 need_refinement = 1;
2858 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2862 if (uniform_refinement)
2869 if (need_refinement == 0)
2871 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2875 const int tag = 293;
2884 if (faces_in_group == 0) {
continue; }
2886 face_splittings[i].
SetSize(0);
2887 for (
int j = 0; j < faces_in_group; j++)
2890 face_splittings[i]);
2894 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
2895 MPI_UNSIGNED, neighbor, tag,
MyComm,
2896 &requests[req_count++]);
2904 if (faces_in_group == 0) {
continue; }
2908 MPI_Probe(neighbor, tag,
MyComm, &status);
2910 MPI_Get_count(&status, MPI_UNSIGNED, &count);
2912 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
2915 for (
int j = 0, pos = 0; j < faces_in_group; j++)
2922 int nr = need_refinement;
2923 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2925 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
2928 while (need_refinement == 1);
2930 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2932 int i = ref_loops_all;
2933 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2936 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2937 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2945 delete [] face_splittings;
2950 need_refinement = 0;
2953 if (
boundary[i]->NeedRefinement(v_to_v))
2955 need_refinement = 1;
2960 while (need_refinement == 1);
2965 " (NumOfBdrElements != boundary.Size())");
2992 int uniform_refinement = 0;
2996 uniform_refinement = 1;
3005 int *edge1 =
new int[nedges];
3006 int *edge2 =
new int[nedges];
3007 int *middle =
new int[nedges];
3009 for (
int i = 0; i < nedges; i++)
3011 edge1[i] = edge2[i] = middle[i] = -1;
3016 int *v =
elements[i]->GetVertices();
3017 for (
int j = 0; j < 3; j++)
3019 int ind = v_to_v(v[j], v[(j+1)%3]);
3020 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
3025 for (
int i = 0; i < marked_el.
Size(); i++)
3031 int need_refinement;
3032 int edges_in_group, max_edges_in_group = 0;
3034 int **edge_splittings =
new int*[
GetNGroups()-1];
3038 edge_splittings[i] =
new int[edges_in_group];
3039 if (edges_in_group > max_edges_in_group)
3041 max_edges_in_group = edges_in_group;
3044 int neighbor, *iBuf =
new int[max_edges_in_group];
3048 MPI_Request request;
3053 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3054 int ref_loops_all = 0, ref_loops_par = 0;
3058 need_refinement = 0;
3059 for (
int i = 0; i < nedges; i++)
3061 if (middle[i] != -1 && edge1[i] != -1)
3063 need_refinement = 1;
3067 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3071 if (uniform_refinement)
3078 if (need_refinement == 0)
3080 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3089 edges_in_group = group_edges.
Size();
3091 if (edges_in_group != 0)
3093 for (
int j = 0; j < edges_in_group; j++)
3095 edge_splittings[i][j] =
3108 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3109 neighbor, 0,
MyComm, &request);
3117 edges_in_group = group_edges.
Size();
3118 if (edges_in_group != 0)
3129 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3130 MPI_ANY_TAG,
MyComm, &status);
3132 for (
int j = 0; j < edges_in_group; j++)
3134 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3137 int ii = v_to_v(v[0], v[1]);
3138 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3139 if (middle[ii] != -1)
3141 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3145 need_refinement = 1;
3147 for (
int c = 0; c < 2; c++)
3157 int nr = need_refinement;
3158 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3161 while (need_refinement == 1);
3163 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3165 int i = ref_loops_all;
3166 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3169 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3170 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3178 delete [] edge_splittings[i];
3180 delete [] edge_splittings;
3185 int v1[2], v2[2], bisect, temp;
3187 for (
int i = 0; i < temp; i++)
3189 int *v =
boundary[i]->GetVertices();
3190 bisect = v_to_v(v[0], v[1]);
3191 if (middle[bisect] != -1)
3196 v1[0] = v[0]; v1[1] = middle[bisect];
3197 v2[0] = middle[bisect]; v2[1] = v[1];
3204 mfem_error(
"Only bisection of segment is implemented for bdr"
3237 for (
int j = 0; j < marked_el.
Size(); j++)
3239 int i = marked_el[j];
3242 int new_v = cnv + j, new_e = cne + j;
3251 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3253 UseExternalData(seg_children, 1, 2, 3);
3274 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
3275 "supported. Project the NURBS to Nodes first.");
3280 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3281 "(you need to initialize the ParMesh from a nonconforming "
3307 Swap(*pmesh2,
false);
3322 double threshold,
int nc_limit,
int op)
3324 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3325 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3326 "Project the NURBS to Nodes first.");
3339 for (
int i = 0; i < dt.
Size(); i++)
3341 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3346 if (error < threshold) { derefs.
Append(i); }
3350 if (!glob_size) {
return false; }
3363 Swap(*mesh2,
false);
3393 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
3403 *new_nodes = *
Nodes;
3424 Swap(*pmesh2,
false);
3441 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
3451 int *I_group_svert, *J_group_svert;
3452 int *I_group_sedge, *J_group_sedge;
3457 I_group_svert[0] = I_group_svert[1] = 0;
3458 I_group_sedge[0] = I_group_sedge[1] = 0;
3465 for (
int group = 0; group <
GetNGroups()-1; group++)
3475 const int ind = middle[v_to_v(v[0], v[1])];
3481 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3488 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3489 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3492 J = J_group_svert+I_group_svert[group];
3493 for (
int i = 0; i < group_verts.
Size(); i++)
3495 J[i] = group_verts[i];
3497 J = J_group_sedge+I_group_sedge[group];
3498 for (
int i = 0; i < group_edges.
Size(); i++)
3500 J[i] = group_edges[i];
3514 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
3516 Array<int> group_verts, group_edges, group_trias;
3535 I_group_svert[0] = 0;
3536 I_group_sedge[0] = 0;
3537 I_group_stria[0] = 0;
3539 for (
int group = 0; group <
GetNGroups()-1; group++)
3550 int ind = v_to_v.
FindId(v[0], v[1]);
3551 if (ind == -1) {
continue; }
3554 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3564 ind = v_to_v.
FindId(v[0], ind);
3572 ind = v_to_v.
FindId(v[0], v[1]);
3593 while (sedge_stack.
Size() > 0);
3600 int ind = v_to_v.
FindId(v[0], v[1]);
3601 if (ind == -1) {
continue; }
3604 const int edge_attr = 1;
3613 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
3614 ind = v_to_v.
FindId(v[0], v[1]);
3622 ind = v_to_v.
FindId(v[0], v[1]);
3640 v = sface_stack[sface_stack.
Size()-2].v;
3642 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
3645 while (sface_stack.
Size() > 0);
3651 ind = v_to_v.
FindId(v[0], v[1]);
3672 while (sedge_stack.
Size() > 0);
3675 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3676 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3677 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3679 J_group_svert.
Append(group_verts);
3680 J_group_sedge.
Append(group_edges);
3681 J_group_stria.
Append(group_trias);
3698 int *I_group_svert, *J_group_svert;
3699 int *I_group_sedge, *J_group_sedge;
3704 I_group_svert[0] = 0;
3705 I_group_sedge[0] = 0;
3712 for (
int group = 0; group <
GetNGroups()-1; group++)
3726 const int attr =
shared_edges[sedges[i]]->GetAttribute();
3732 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
3733 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
3735 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
3736 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3752 Array<int> group_verts, group_edges, group_trias, group_quads;
3754 int *I_group_svert, *J_group_svert;
3755 int *I_group_sedge, *J_group_sedge;
3756 int *I_group_stria, *J_group_stria;
3757 int *I_group_squad, *J_group_squad;
3764 I_group_svert[0] = 0;
3765 I_group_sedge[0] = 0;
3766 I_group_stria[0] = 0;
3767 I_group_squad[0] = 0;
3779 const int oface = old_nv + old_nedges;
3781 for (
int group = 0; group <
GetNGroups()-1; group++)
3793 const int ind = old_nv + old_v_to_v(v[0], v[1]);
3797 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3807 const int stria = group_trias[i];
3810 m[0] = old_nv + old_v_to_v(v[0], v[1]);
3811 m[1] = old_nv + old_v_to_v(v[1], v[2]);
3812 m[2] = old_nv + old_v_to_v(v[2], v[0]);
3813 const int edge_attr = 1;
3828 v[1] = m[0]; v[2] = m[2];
3829 group_trias.
Append(nst+0);
3830 group_trias.
Append(nst+1);
3831 group_trias.
Append(nst+2);
3839 const int squad = group_quads[i];
3841 const int olf = old_faces(v[0], v[1], v[2], v[3]);
3843 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
3847 m[1] = old_nv + old_v_to_v(v[0], v[1]);
3848 m[2] = old_nv + old_v_to_v(v[1], v[2]);
3849 m[3] = old_nv + old_v_to_v(v[2], v[3]);
3850 m[4] = old_nv + old_v_to_v(v[3], v[0]);
3851 const int edge_attr = 1;
3868 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
3869 group_quads.
Append(nsq+0);
3870 group_quads.
Append(nsq+1);
3871 group_quads.
Append(nsq+2);
3875 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3876 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3877 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3878 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
3880 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
3881 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3882 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
3883 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
3902 const bool update_nodes =
false;
3932 const bool update_nodes =
false;
3941 f2qf.
Size() ? &f2qf : NULL);
3951 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
3957 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
3963 out <<
"NETGEN_Neutral_Format\n";
3968 for (j = 0; j <
Dim; j++)
3981 out <<
elements[i]->GetAttribute();
3982 for (j = 0; j < nv; j++)
3984 out <<
" " << ind[j]+1;
3996 out <<
boundary[i]->GetAttribute();
3997 for (j = 0; j < nv; j++)
3999 out <<
" " << ind[j]+1;
4010 for (j = 0; j < 3; j++)
4012 out <<
' ' << ind[j]+1;
4026 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4028 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4029 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4030 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4036 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4044 out << i+1 <<
" " <<
elements[i]->GetAttribute();
4045 for (j = 0; j < nv; j++)
4047 out <<
" " << ind[j]+1;
4057 out <<
boundary[i]->GetAttribute();
4058 for (j = 0; j < nv; j++)
4060 out <<
" " << ind[j]+1;
4062 out <<
" 1.0 1.0 1.0 1.0\n";
4073 for (j = 0; j < 4; j++)
4075 out <<
' ' << ind[j]+1;
4077 out <<
" 1.0 1.0 1.0 1.0\n";
4086 out <<
"areamesh2\n\n";
4093 attr =
boundary[i]->GetAttribute();
4096 for (j = 0; j < v.
Size(); j++)
4098 out << v[j] + 1 <<
" ";
4108 for (j = 0; j < v.
Size(); j++)
4110 out << v[j] + 1 <<
" ";
4119 attr =
elements[i]->GetAttribute();
4135 for (j = 0; j < v.
Size(); j++)
4137 out << v[j] + 1 <<
" ";
4146 for (j = 0; j <
Dim; j++)
4171 bool print_shared =
true;
4172 int i, j, shared_bdr_attr;
4189 s2l_face = &nc_shared_faces;
4196 for (
int i = 0; i < sfaces.
conforming.Size(); i++)
4199 if (index < nfaces) { nc_shared_faces.
Append(index); }
4201 for (
int i = 0; i < sfaces.
masters.Size(); i++)
4205 if (index < nfaces) { nc_shared_faces.
Append(index); }
4207 for (
int i = 0; i < sfaces.
slaves.Size(); i++)
4210 if (index < nfaces) { nc_shared_faces.
Append(index); }
4215 out <<
"MFEM mesh v1.0\n";
4219 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4224 "# TETRAHEDRON = 4\n"
4229 out <<
"\ndimension\n" <<
Dim
4237 if (print_shared &&
Dim > 1)
4239 num_bdr_elems += s2l_face->
Size();
4241 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4247 if (print_shared &&
Dim > 1)
4255 shared_bdr_attr =
MyRank + 1;
4257 for (i = 0; i < s2l_face->
Size(); i++)
4260 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4286 #ifdef MFEM_USE_ADIOS2
4299 for (
int i = 0; i < nv; i++)
4307 int i, j, k,
p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4315 out <<
"MFEM mesh v1.0\n";
4319 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4324 "# TETRAHEDRON = 4\n"
4329 out <<
"\ndimension\n" <<
Dim;
4333 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4336 out <<
"\n\nelements\n" << ne <<
'\n';
4340 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
4344 for (j = 0; j < nv; j++)
4351 for (p = 1; p <
NRanks; p++)
4353 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
4357 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
4359 for (i = 0; i < ne; )
4362 out << p+1 <<
' ' << ints[i];
4365 for (j = 0; j < k; j++)
4367 out <<
' ' << vc + ints[i++];
4380 ne += 1 +
elements[i]->GetNVertices();
4383 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
4391 MFEM_ASSERT(ints.
Size() == ne,
"");
4394 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
4419 dump_element(
boundary[i], ints); ne++;
4457 MFEM_ABORT(
"invalid dimension: " <<
Dim);
4467 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4469 for (i = 0; i < list.
masters.Size(); i++)
4472 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4474 for (i = 0; i < list.
slaves.Size(); i++)
4477 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4481 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4484 out <<
"\nboundary\n" << k <<
'\n';
4486 for (p = 0; p <
NRanks; p++)
4490 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
4502 for (i = 0; i < ne; )
4505 out << p+1 <<
' ' << ints[i];
4508 for (j = 0; j < k; j++)
4510 out <<
' ' << vc + ints[i++];
4521 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
4532 out <<
"\nvertices\n" << nv <<
'\n';
4548 for (p = 1; p <
NRanks; p++)
4550 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
4554 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
4556 for (i = 0; i < nv; i++)
4561 out <<
' ' << vert[i*spaceDim+j];
4576 vert[i*spaceDim+j] =
vertices[i](j);
4581 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
4608 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
4616 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
4619 int i, j, k, nv, ne,
p;
4627 out <<
"NETGEN_Neutral_Format\n";
4630 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4634 for (j = 0; j <
Dim; j++)
4640 for (p = 1; p <
NRanks; p++)
4642 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4644 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4645 for (i = 0; i < nv; i++)
4647 for (j = 0; j <
Dim; j++)
4649 out <<
" " << vert[Dim*i+j];
4657 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4664 for (j = 0; j < nv; j++)
4666 out <<
" " << ind[j]+1;
4671 for (p = 1; p <
NRanks; p++)
4673 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4674 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4676 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4677 for (i = 0; i < ne; i++)
4680 for (j = 0; j < 4; j++)
4682 out <<
" " << k+ints[i*4+j]+1;
4690 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4698 for (j = 0; j < nv; j++)
4700 out <<
" " << ind[j]+1;
4711 for (j = 0; j < 3; j++)
4713 out <<
' ' << ind[j]+1;
4719 for (p = 1; p <
NRanks; p++)
4721 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4722 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4724 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4725 for (i = 0; i < ne; i++)
4728 for (j = 0; j < 3; j++)
4730 out <<
' ' << k+ints[i*3+j]+1;
4740 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4744 for (j = 0; j <
Dim; j++)
4748 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4752 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4753 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4759 for (j = 0; j < 4; j++)
4764 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
4767 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4768 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4770 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4775 for (j = 0; j < 3; j++)
4780 for ( ; i < ne; i++)
4783 for (j = 0; j < 3; j++)
4788 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
4794 int i, j, k, nv, ne,
p;
4800 int TG_nv, TG_ne, TG_nbe;
4807 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4810 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
4811 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4812 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4813 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4814 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4821 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4823 for (p = 1; p <
NRanks; p++)
4825 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4827 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4828 for (i = 0; i < nv; i++)
4830 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
4831 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
4841 out << i+1 <<
" " << 1;
4842 for (j = 0; j < nv; j++)
4844 out <<
" " << ind[j]+1;
4849 for (p = 1; p <
NRanks; p++)
4851 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4852 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4854 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
4855 for (i = 0; i < ne; i++)
4857 out << i+1 <<
" " << p+1;
4858 for (j = 0; j < 8; j++)
4860 out <<
" " << k+ints[i*8+j]+1;
4875 for (j = 0; j < nv; j++)
4877 out <<
" " << ind[j]+1;
4879 out <<
" 1.0 1.0 1.0 1.0\n";
4889 for (j = 0; j < 4; j++)
4891 out <<
' ' << ind[j]+1;
4893 out <<
" 1.0 1.0 1.0 1.0\n";
4896 for (p = 1; p <
NRanks; p++)
4898 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4899 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4901 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4902 for (i = 0; i < ne; i++)
4905 for (j = 0; j < 4; j++)
4907 out <<
" " << k+ints[i*4+j]+1;
4909 out <<
" 1.0 1.0 1.0 1.0\n";
4919 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4924 for (j = 0; j <
Dim; j++)
4928 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
4930 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4936 for (j = 0; j < 8; j++)
4941 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
4943 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4945 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4950 for (j = 0; j < 4; j++)
4955 for ( ; i < ne; i++)
4958 for (j = 0; j < 4; j++)
4963 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
4969 int i, j, k, attr, nv, ne,
p;
4977 out <<
"areamesh2\n\n";
4981 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4986 attr =
boundary[i]->GetAttribute();
4989 for (j = 0; j < v.
Size(); j++)
4991 out << v[j] + 1 <<
" ";
5001 for (j = 0; j < v.
Size(); j++)
5003 out << v[j] + 1 <<
" ";
5008 for (p = 1; p <
NRanks; p++)
5010 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5011 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5013 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
5014 for (i = 0; i < ne; i++)
5017 for (j = 0; j < 2; j++)
5019 out <<
" " << k+ints[i*2+j]+1;
5028 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5034 out << 1 <<
" " << 3 <<
" ";
5035 for (j = 0; j < v.
Size(); j++)
5037 out << v[j] + 1 <<
" ";
5042 for (p = 1; p <
NRanks; p++)
5044 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5045 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
5047 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
5048 for (i = 0; i < ne; i++)
5050 out << p+1 <<
" " << 3;
5051 for (j = 0; j < 3; j++)
5053 out <<
" " << k+ints[i*3+j]+1;
5062 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5066 for (j = 0; j <
Dim; j++)
5072 for (p = 1; p <
NRanks; p++)
5074 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5076 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
5077 for (i = 0; i < nv; i++)
5079 for (j = 0; j <
Dim; j++)
5081 out <<
" " << vert[Dim*i+j];
5091 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5094 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5099 for (j = 0; j < 2; j++)
5104 for ( ; i < ne; i++)
5107 for (j = 0; j < 2; j++)
5112 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
5115 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5122 for (j = 0; j < 3; j++)
5127 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
5130 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5134 for (j = 0; j <
Dim; j++)
5138 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
5156 MPI_Allreduce(p_min.
GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN,
MyComm);
5157 MPI_Allreduce(p_max.
GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX,
MyComm);
5161 double &gk_min,
double &gk_max)
5163 double h_min, h_max, kappa_min, kappa_max;
5167 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
5168 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
5169 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
5170 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
5177 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
5181 out <<
"Parallel Mesh Stats:" <<
'\n';
5187 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
5193 kappa_min = kappa_max =
kappa;
5197 if (h < h_min) { h_min = h; }
5198 if (h > h_max) { h_max = h; }
5199 if (kappa < kappa_min) { kappa_min =
kappa; }
5200 if (kappa > kappa_max) { kappa_max =
kappa; }
5204 double gh_min, gh_max, gk_min, gk_max;
5205 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
5206 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
5207 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
5208 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
5213 long mindata[5], maxdata[5], sumdata[5];
5232 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
5233 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
5234 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
5240 << setw(12) <<
"minimum"
5241 << setw(12) <<
"average"
5242 << setw(12) <<
"maximum"
5243 << setw(12) <<
"total" <<
'\n';
5245 << setw(12) << mindata[0]
5246 << setw(12) << sumdata[0]/
NRanks
5247 << setw(12) << maxdata[0]
5248 << setw(12) << sumdata[0] <<
'\n';
5250 << setw(12) << mindata[1]
5251 << setw(12) << sumdata[1]/
NRanks
5252 << setw(12) << maxdata[1]
5253 << setw(12) << sumdata[1] <<
'\n';
5257 << setw(12) << mindata[2]
5258 << setw(12) << sumdata[2]/
NRanks
5259 << setw(12) << maxdata[2]
5260 << setw(12) << sumdata[2] <<
'\n';
5263 << setw(12) << mindata[3]
5264 << setw(12) << sumdata[3]/
NRanks
5265 << setw(12) << maxdata[3]
5266 << setw(12) << sumdata[3] <<
'\n';
5267 out <<
" neighbors "
5268 << setw(12) << mindata[4]
5269 << setw(12) << sumdata[4]/
NRanks
5270 << setw(12) << maxdata[4] <<
'\n';
5273 << setw(12) <<
"minimum"
5274 << setw(12) <<
"maximum" <<
'\n';
5276 << setw(12) << gh_min
5277 << setw(12) << gh_max <<
'\n';
5279 << setw(12) << gk_min
5280 << setw(12) << gk_max <<
'\n';
5287 long local = value, global;
5288 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
5304 Printer(out,
"mfem_serial_mesh_end");
5312 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5323 out <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
5324 for (
int i = 0; i < nv; i++)
5333 out <<
"\nshared_edges " << ne <<
'\n';
5334 for (
int i = 0; i < ne; i++)
5337 out << v[0] <<
' ' << v[1] <<
'\n';
5346 out <<
"\nshared_faces " << nt+nq <<
'\n';
5347 for (
int i = 0; i < nt; i++)
5351 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5354 for (
int i = 0; i < nq; i++)
5358 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5365 out <<
"\nmfem_mesh_end" << endl;
5370 bool high_order_output,
5371 int compression_level,
5374 int pad_digits_rank = 6;
5377 std::string::size_type pos = pathname.find_last_of(
'/');
5379 = (pos == std::string::npos) ? pathname : pathname.substr(pos+1);
5383 std::string pvtu_name = pathname +
"/" + fname +
".pvtu";
5384 std::ofstream
out(pvtu_name);
5387 std::string data_format = (format ==
VTKFormat::ASCII) ?
"ascii" :
"binary";
5389 out <<
"<?xml version=\"1.0\"?>\n";
5390 out <<
"<VTKFile type=\"PUnstructuredGrid\"";
5391 out <<
" version =\"0.1\" byte_order=\"" <<
VTKByteOrder() <<
"\">\n";
5392 out <<
"<PUnstructuredGrid GhostLevel=\"0\">\n";
5394 out <<
"<PPoints>\n";
5395 out <<
"\t<PDataArray type=\"" << data_type <<
"\" ";
5396 out <<
" Name=\"Points\" NumberOfComponents=\"3\""
5397 <<
" format=\"" << data_format <<
"\"/>\n";
5398 out <<
"</PPoints>\n";
5400 out <<
"<PCells>\n";
5401 out <<
"\t<PDataArray type=\"Int32\" ";
5402 out <<
" Name=\"connectivity\" NumberOfComponents=\"1\""
5403 <<
" format=\"" << data_format <<
"\"/>\n";
5404 out <<
"\t<PDataArray type=\"Int32\" ";
5405 out <<
" Name=\"offsets\" NumberOfComponents=\"1\""
5406 <<
" format=\"" << data_format <<
"\"/>\n";
5407 out <<
"\t<PDataArray type=\"UInt8\" ";
5408 out <<
" Name=\"types\" NumberOfComponents=\"1\""
5409 <<
" format=\"" << data_format <<
"\"/>\n";
5410 out <<
"</PCells>\n";
5412 out <<
"<PCellData>\n";
5413 out <<
"\t<PDataArray type=\"Int32\" Name=\"" <<
"attribute"
5414 <<
"\" NumberOfComponents=\"1\""
5415 <<
" format=\"" << data_format <<
"\"/>\n";
5416 out <<
"</PCellData>\n";
5418 for (
int ii=0; ii<
NRanks; ii++)
5420 std::string piece = fname +
".proc"
5422 out <<
"<Piece Source=\"" << piece <<
"\"/>\n";
5425 out <<
"</PUnstructuredGrid>\n";
5426 out <<
"</VTKFile>\n";
5430 std::string vtu_fname = pathname +
"/" + fname +
".proc"
5432 Mesh::PrintVTU(vtu_fname, format, high_order_output, compression_level, bdr);
5439 const int npts = point_mat.
Width();
5440 if (npts == 0) {
return 0; }
5442 const bool no_warn =
false;
5449 Array<int> my_point_rank(npts), glob_point_rank(npts);
5450 for (
int k = 0; k < npts; k++)
5452 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
5455 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
5456 MPI_INT, MPI_MIN,
MyComm);
5459 for (
int k = 0; k < npts; k++)
5461 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
5465 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
5468 if (warn && pts_found != npts &&
MyRank == 0)
5470 MFEM_WARNING((npts-pts_found) <<
" points were not found");
5475 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &
out)
5478 for (
int d = 1; d < space_dim; d++)
5486 stringstream out_name;
5487 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
5488 <<
".shared_entities";
5489 ofstream
out(out_name.str().c_str());
5497 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5508 out <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
5509 for (
int i = 0; i < nv; i++)
5521 out <<
"\nshared_edges " << ne <<
'\n';
5522 for (
int i = 0; i < ne; i++)
5538 out <<
"\nshared_faces " << nt+nq <<
'\n';
5539 for (
int i = 0; i < nt; i++)
5544 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5547 for (
int j = 0; j < 3; j++)
5550 (j < 2) ? out <<
" | " : out <<
'\n';
5553 for (
int i = 0; i < nq; i++)
5558 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5561 for (
int j = 0; j < 4; j++)
5564 (j < 3) ? out <<
" | " : out <<
'\n';
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for all finite elements.
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 SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
void GetConformingSharedStructures(class ParMesh &pmesh)
virtual void Print(std::ostream &out=mfem::out) const
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 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 Unique()
Removes duplicities from a sorted array. This requires operator== to be defined for T...
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)
void ExchangeFaceNbrData()
int CheckElementOrientation(bool fix_it=true)
Check the orientation of the elements.
void SetSize(int dim, int connections_per_row)
Set the size and the number of connections for the table.
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)
void AddColumnsInRow(int r, int ncol)
void UniformRefinement3D_base(Array< int > *f2qf=NULL, DSTable *v_to_v_p=NULL, bool update_nodes=true)
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.
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
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.
CoarseFineTransformations CoarseFineTr
virtual void ReorientTetMesh()
See the remarks for the serial version in mesh.hpp.
void SetSize(int s)
Resize the vector to size s.
int GetNBE() const
Returns number of boundary elements.
IsoparametricTransformation Transformation
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
void GetCharacteristics(double &h_min, double &h_max, double &kappa_min, double &kappa_max, Vector *Vh=NULL, Vector *Vk=NULL)
void MakeOwner(FiniteElementCollection *_fec)
Make the GridFunction the owner of fec and fes.
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.
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)
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.
void SaveAsOne(std::ostream &out=mfem::out)
Merge the local grid functions.
virtual void LocalRefinement(const Array< int > &marked_el, int type=3)
This function is not public anymore. Use GeneralRefinement instead.
Data type dense matrix using column-major storage.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
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
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)
virtual void OnMeshUpdated(Mesh *mesh)
virtual void Derefine(const Array< int > &derefs)
Abstract parallel finite element space.
void PrintVTU(std::ostream &out, int ref=1, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr_elements=false)
Array< Vert3 > shared_trias
virtual int DofForGeometry(Geometry::Type GeomType) const
Array< int > face_nbr_vertices_offset
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
virtual void SetAttributes()
void RebalanceImpl(const Array< int > *partition)
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.
virtual void MarkTetMeshForRefinement(DSTable &v_to_v)
int GroupNQuadrilaterals(int group)
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()
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.
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 GroupTriangle(int group, int i, int &face, int &o)
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
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 CopyTo(U *dest)
STL-like copyTo dest from begin to end.
int FindSharedEdges(const Mesh &mesh, const int *partition, Table *&edge_element, ListOfIntegerSets &groups)
long GetGlobalElementNum(int local_element_num) const
Map a local element number to a global element number.
int GroupVertex(int group, int i)
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
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...
void GetFaceNbrElementVDofs(int i, Array< int > &vdofs) const
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 GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
virtual void UniformRefinement2D()
Refine a mixed 2D mesh uniformly.
void GetElementJacobian(int i, DenseMatrix &J)
int GetLocalElementNum(long global_element_num) const
void GetVertexDofs(int i, Array< int > &dofs) const
void MarkEdge(DenseMatrix &pmat)
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
Array< int > face_nbr_elements_offset
void GetEdgeOrdering(DSTable &v_to_v, Array< int > &order)
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()
Array< Element * > shared_edges
virtual void SetAttributes()
int Append(const T &el)
Append element 'el' to array, resize if necessary.
virtual void NonconformingRefinement(const Array< Refinement > &refinements, int nc_limit=0)
This function is not public anymore. Use GeneralRefinement instead.
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 PrintAsOne(std::ostream &out=mfem::out)
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.
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.
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...
virtual void Print(std::ostream &out=mfem::out) const
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void GetSharedQuadrilateralDofs(int group, int fi, Array< int > &dofs) const
static int create_directory(const std::string &dir_name, const Mesh *mesh, int myid)
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
GeometryRefiner GlobGeometryRefiner
int GetAttribute() const
Return element's attribute.
int GetElementToEdgeTable(Table &, Array< int > &)
const Element * GetElement(int i) const
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
int GroupNVertices(int group)
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 ...
void GetSharedTriangleDofs(int group, int fi, Array< int > &dofs) const
IsoparametricTransformation Transformation2
FiniteElementCollection * OwnFEC()
int Size() const
Returns the number of TYPE I elements.
int GetVDim() const
Returns vector dimension.
FiniteElementSpace * FESpace()
int Size()
Return the number of integer sets in the list.
Array< Vert4 > shared_quads
void Rebalance(const Array< int > *custom_partition=NULL)
int slaves_end
slave faces
Data type tetrahedron element.
int CheckBdrElementOrientation(bool fix_it=true)
Check the orientation of the boundary elements.
int SpaceDimension() const
void GetBdrElementFace(int i, int *, int *) const
Return the index and the orientation of the face of bdr element i. (3D)
void GroupQuadrilateral(int group, int i, int &face, int &o)
void Save(std::ostream &out) const
Save the data in a stream.
int GroupNTriangles(int group)
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
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 RefineGroups(const DSTable &v_to_v, int *middle)
Update the groups after triangle refinement.
virtual bool NonconformingDerefinement(Array< double > &elem_error, double threshold, int nc_limit=0, int op=1)
NC version of GeneralDerefinement.
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...
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 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.
virtual long ReduceInt(int value) const
Utility function: sum integers from all processors (Allreduce).
bool IsSlaveFace(const FaceInfo &fi) const
void DeleteLast()
Delete the last entry of the array.
Table & GroupLDofTable()
Fill-in the returned Table reference to initialize the GroupCommunicator then call Finalize()...
Array< Element * > elements
double GetLength(int i, int j) const
Return the length of the segment from node i to node j.
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)
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.
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 GetElementTransformation(int i, IsoparametricTransformation *ElTr)
const FiniteElementSpace * GetNodalFESpace() const
void ComputeGlobalElementOffset() const
void ExchangeFaceNbrNodes()
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.
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()
Table group_svert
Shared objects in each group.
bool DecodeFaceSplittings(HashTable< Hashed2 > &v_to_v, const int *v, const Array< unsigned > &codes, int &pos)
Array< MeshId > conforming
virtual void UniformRefinement3D()
Refine a mixed 3D mesh uniformly.
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.
Array< FaceInfo > faces_info
virtual int GetNVertices() const =0
void SetAttribute(const int attr)
Set element's attribute.
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
STable3D * GetFacesTable()
NCMesh * ncmesh
Optional non-conforming mesh extension.
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.
virtual void PrintXG(std::ostream &out=mfem::out) const
double AggregateError(const Array< double > &elem_error, const int *fine, int nfine, int op)
Derefinement helper.
void GetMarkedFace(const int face, int *fv)
void GroupEdge(int group, int i, int &edge, int &o)
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...
const FiniteElementCollection * FEColl() const
void GetNodes(Vector &node_coord) const
void GenerateOffsets(int N, HYPRE_Int loc_sizes[], Array< HYPRE_Int > *offsets[]) const
int NumberOfEntries() const
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
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()
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 SetSize(int s)
Change the size of the DenseMatrix to s x s.
Table send_face_nbr_elements
virtual void PrintInfo(std::ostream &out=mfem::out)
Print various parallel mesh stats.
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.
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.
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.
virtual void PrintVTU(std::string pathname, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr=false)
void GenerateNCFaceInfo()
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
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.
int GroupNEdges(int group)
void GreenRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
Arbitrary order "L2-conforming" discontinuous finite elements.
double f(const Vector &p)
void Printer(std::ostream &out=mfem::out, std::string section_delimiter="") const
ParFiniteElementSpace * ParFESpace() const
virtual void NURBSUniformRefinement()
Refine NURBS mesh.