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),
78 if (pmesh.
Nodes && copy_nodes)
97 int *partitioning = NULL;
108 partitioning = partitioning_;
113 partitioning =
new int[mesh.
GetNE()];
114 for (
int i = 0; i < mesh.
GetNE(); i++)
144 partitioning = partitioning_;
158 Table *edge_element = NULL;
161 activeBdrElem, edge_element);
199 int nsedges =
FindSharedEdges(mesh, partitioning, edge_element, groups);
206 int ngroups = groups.
Size()-1, nstris, nsquads;
213 face_group, vert_global_local);
232 "invalid NURBS mesh");
252 Nodes->MakeOwner(nfec);
258 int element_counter = 0;
259 for (
int i = 0; i < mesh.
GetNE(); i++)
261 if (partitioning[i] ==
MyRank)
264 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
265 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
272 if (partitioning != partitioning_)
274 delete [] partitioning;
282 const int* partitioning,
286 vert_global_local = -1;
288 int vert_counter = 0;
289 for (
int i = 0; i < mesh.
GetNE(); i++)
291 if (partitioning[i] ==
MyRank)
295 for (
int j = 0; j < vert.
Size(); j++)
297 if (vert_global_local[vert[j]] < 0)
299 vert_global_local[vert[j]] = vert_counter++;
307 for (
int i = 0; i < vert_global_local.
Size(); i++)
309 if (vert_global_local[i] >= 0)
311 vert_global_local[i] = vert_counter++;
317 for (
int i = 0; i < vert_global_local.
Size(); i++)
319 if (vert_global_local[i] >= 0)
333 for (
int i = 0; i < mesh.
GetNE(); i++)
335 if (partitioning[i] ==
MyRank) { nelems++; }
343 int element_counter = 0;
344 for (
int i = 0; i < mesh.
GetNE(); i++)
346 if (partitioning[i] ==
MyRank)
349 int *v =
elements[element_counter]->GetVertices();
350 int nv =
elements[element_counter]->GetNVertices();
351 for (
int j = 0; j < nv; j++)
353 v[j] = vert_global_local[v[j]];
359 return element_counter;
365 Table*& edge_element)
372 activeBdrElem =
false;
377 for (
int i = 0; i < mesh.
GetNBE(); i++)
379 int face, o, el1, el2;
382 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
387 activeBdrElem[i] =
true;
392 int bdrelem_counter = 0;
394 for (
int i = 0; i < mesh.
GetNBE(); i++)
396 int face, o, el1, el2;
399 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
402 int *v =
boundary[bdrelem_counter]->GetVertices();
403 int nv =
boundary[bdrelem_counter]->GetNVertices();
404 for (
int j = 0; j < nv; j++)
406 v[j] = vert_global_local[v[j]];
414 edge_element =
new Table;
417 for (
int i = 0; i < mesh.
GetNBE(); i++)
420 int el1 = edge_element->
GetRow(edge)[0];
421 if (partitioning[el1] ==
MyRank)
426 activeBdrElem[i] =
true;
431 int bdrelem_counter = 0;
433 for (
int i = 0; i < mesh.
GetNBE(); i++)
436 int el1 = edge_element->
GetRow(edge)[0];
437 if (partitioning[el1] ==
MyRank)
440 int *v =
boundary[bdrelem_counter]->GetVertices();
441 int nv =
boundary[bdrelem_counter]->GetNVertices();
442 for (
int j = 0; j < nv; j++)
444 v[j] = vert_global_local[v[j]];
452 for (
int i = 0; i < mesh.
GetNBE(); i++)
454 int vert = mesh.
boundary[i]->GetVertices()[0];
457 if (partitioning[el1] ==
MyRank)
463 int bdrelem_counter = 0;
465 for (
int i = 0; i < mesh.
GetNBE(); i++)
467 int vert = mesh.
boundary[i]->GetVertices()[0];
470 if (partitioning[el1] ==
MyRank)
473 int *v =
boundary[bdrelem_counter]->GetVertices();
474 v[0] = vert_global_local[v[0]];
491 for (
int i = 0; i < face_group.
Size(); i++)
498 el[0] = partitioning[el[0]];
499 el[1] = partitioning[el[1]];
504 face_group[i] = groups.
Insert(group) - 1;
511 Table*& edge_element,
517 int sedge_counter = 0;
520 edge_element =
new Table;
531 for (
int i = 0; i < edge_element->
Size(); i++)
533 int me = 0, others = 0;
534 for (
int j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
536 int k = edge_element->
GetJ()[j];
537 int rank = partitioning[k];
538 edge_element->
GetJ()[j] = rank;
557 edge_element->
GetRow(i)[0] = -1;
561 return sedge_counter;
570 int svert_counter = 0;
571 for (
int i = 0; i < vert_element->
Size(); i++)
573 int me = 0, others = 0;
574 for (
int j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
576 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
591 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
595 vert_element->
GetI()[i] = -1;
598 return svert_counter;
603 int &nstria,
int &nsquad)
609 for (
int i = 0; i < face_group.
Size(); i++)
611 if (face_group[i] >= 0)
628 for (
int i = 0; i < face_group.
Size(); i++)
630 if (face_group[i] >= 0)
651 for (
int i = 0; i < edge_element.
Size(); i++)
653 if (edge_element.
GetRow(i)[0] >= 0)
661 int sedge_counter = 0;
662 for (
int i = 0; i < edge_element.
Size(); i++)
664 if (edge_element.
GetRow(i)[0] >= 0)
677 for (
int i = 0; i < vert_element.
Size(); i++)
679 if (vert_element.
GetI()[i] >= 0)
687 int svert_counter = 0;
688 for (
int i = 0; i < vert_element.
Size(); i++)
690 if (vert_element.
GetI()[i] >= 0)
700 const Mesh& mesh,
int *partitioning,
709 if (
Dim < 3) {
return; }
711 int stria_counter = 0;
712 int squad_counter = 0;
713 for (
int i = 0; i < face_group.
Size(); i++)
715 if (face_group[i] < 0) {
continue; }
725 for (
int j = 0; j < 3; j++)
727 v[j] = vert_global_local[v[j]];
729 const int lface = (*faces_tbl)(v[0], v[1], v[2]);
745 if (
MyRank == partitioning[gl_el2])
747 std::swap(v[0], v[1]);
759 for (
int j = 0; j < 4; j++)
761 v[j] = vert_global_local[v[j]];
764 (*faces_tbl)(v[0], v[1], v[2], v[3]);
770 MFEM_ABORT(
"unknown face type: " << face->
GetType());
778 const Table* edge_element)
790 int sedge_counter = 0;
791 for (
int i = 0; i < edge_element->
Size(); i++)
793 if (edge_element->
GetRow(i)[0] >= 0)
799 new Segment(vert_global_local[vert[0]],
800 vert_global_local[vert[1]], 1);
802 sedge_ledge[sedge_counter] = v_to_v(vert_global_local[vert[0]],
803 vert_global_local[vert[1]]);
805 MFEM_VERIFY(
sedge_ledge[sedge_counter] >= 0,
"Error in v_to_v.");
820 int svert_counter = 0;
821 for (
int i = 0; i < vert_element->
Size(); i++)
823 if (vert_element->
GetI()[i] >= 0)
825 svert_lvert[svert_counter++] = vert_global_local[i];
833 : MyComm(pncmesh.MyComm)
834 , NRanks(pncmesh.NRanks)
835 , MyRank(pncmesh.MyRank)
847 MPI_Allreduce(&loc_meshgen, &
meshgen, 1, MPI_INT, MPI_BOR,
MyComm);
861 const int l_edge = v_to_v(v[0], v[1]);
862 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
873 for (
int st = 0; st < nst; st++)
881 sface_lface[nst+sq] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
900 const int gen_edges = 1;
905 Loader(input, gen_edges,
"mfem_serial_mesh_end");
913 MFEM_VERIFY(ident ==
"communication_groups",
914 "input stream is not a parallel MFEM mesh");
922 input >> ident >> num_sverts;
931 input >> ident >> num_sedges;
945 input >> ident >> num_sface;
958 int svert_counter = 0, sedge_counter = 0;
968 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
969 <<
", read group " << g << endl;
976 input >> ident >> nv;
979 "incorrect number of total_shared_vertices");
981 for ( ; svert_counter < nv; svert_counter++)
990 input >> ident >> ne;
993 "incorrect number of total_shared_edges");
995 for ( ; sedge_counter < ne; sedge_counter++)
998 input >> v[0] >> v[1];
1005 input >> ident >> nf;
1006 for (
int i = 0; i < nf; i++)
1015 for (
int i = 0; i < 3; i++) { input >> v[i]; }
1020 for (
int i = 0; i < 4; i++) { input >> v[i]; }
1023 MFEM_ABORT(
"invalid shared face geometry: " << geom);
1034 "incorrect number of total_shared_faces");
1050 const bool fix_orientation =
false;
1061 :
Mesh(orig_mesh, ref_factor, ref_type),
1062 MyComm(orig_mesh->GetComm()),
1063 NRanks(orig_mesh->GetNRanks()),
1064 MyRank(orig_mesh->GetMyRank()),
1065 gtopo(orig_mesh->gtopo),
1066 have_face_nbr_data(false),
1145 for (
int j = 0; j < orig_n_verts; j++)
1152 const int orig_n_edges = orig_mesh->
GroupNEdges(gr);
1153 if (orig_n_edges > 0)
1158 const int *c2h_map = rfec.
GetDofMap(geom);
1160 for (
int e = 0; e < orig_n_edges; e++)
1165 for (
int j = 2; j < rdofs.
Size(); j++)
1173 for (
int k = 0; k < nvert; k++)
1176 v[k] = rdofs[c2h_map[cid]];
1192 const int *c2h_map = rfec.
GetDofMap(geom);
1194 for (
int f = 0; f < orig_nt; f++)
1199 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1208 for (
int k = 0; k < 2; k++)
1210 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1219 for (
int k = 0; k < nvert; k++)
1222 v[k] = rdofs[c2h_map[cid]];
1236 const int *c2h_map = rfec.
GetDofMap(geom);
1238 for (
int f = 0; f < orig_nq; f++)
1243 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
1252 for (
int k = 0; k < 2; k++)
1254 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
1263 for (
int k = 0; k < nvert; k++)
1266 v[k] = rdofs[c2h_map[cid]];
1283 const int meshgen_save =
meshgen;
1298 int max_attr = attr.
Max();
1299 int glb_max_attr = -1;
1300 MPI_Allreduce(&max_attr, &glb_max_attr, 1, MPI_INT, MPI_MAX,
MyComm);
1304 bool * attr_marker =
new bool[glb_max_attr];
1305 bool * glb_attr_marker =
new bool[glb_max_attr];
1306 for (
int i=0; i<glb_max_attr; i++)
1308 attr_marker[i] =
false;
1310 for (
int i=0; i<attr.
Size(); i++)
1312 attr_marker[attr[i] - 1] =
true;
1314 MPI_Allreduce(attr_marker, glb_attr_marker, glb_max_attr,
1315 MPI_C_BOOL, MPI_LOR,
MyComm);
1316 delete [] attr_marker;
1320 glb_attr.
SetSize(glb_max_attr);
1321 glb_attr = glb_max_attr;
1323 for (
int i=0; i<glb_max_attr; i++)
1325 if (glb_attr_marker[i])
1327 glb_attr[o++] = i + 1;
1330 delete [] glb_attr_marker;
1334 glb_attr.
Copy(attr);
1345 MFEM_WARNING(
"Non-positive boundary element attributes found!");
1351 MFEM_WARNING(
"Non-positive element attributes found!");
1360 o = (v[0] < v[1]) ? (+1) : (-1);
1369 "Expecting a triangular face.");
1380 "Expecting a quadrilateral face.");
1396 gr_sedge.
GetI()[0] = 0;
1415 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1418 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1420 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1423 if (n == 0) {
continue; }
1424 sedge_ord_map.SetSize(n);
1425 for (
int j = 0; j < n; j++)
1427 sedge_ord_map[j].one = sedge_ord[k+j];
1428 sedge_ord_map[j].two = j;
1430 SortPairs<int, int>(sedge_ord_map, n);
1431 for (
int j = 0; j < n; j++)
1434 const int *v =
shared_edges[sedge_from]->GetVertices();
1435 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1437 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1438 for (
int j = 0; j < n; j++)
1442 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1456 ilen_len[j].one = order[j];
1457 ilen_len[j].two =
GetLength(i, it.Column());
1461 SortPairs<int, double>(ilen_len, order.
Size());
1464 for (
int i = 1; i < order.
Size(); i++)
1466 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1476 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1479 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1491 elements[i]->MarkEdge(v_to_v, order);
1499 boundary[i]->MarkEdge(v_to_v, order);
1518 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1535 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1536 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1538 if (bit == 8*
sizeof(
unsigned))
1544 const face_t &f = face_stack.
Last();
1545 int mid = v_to_v.
FindId(f.one, f.two);
1555 face_stack.
Append(face_t(f.three, f.one, mid));
1556 face_t &r = face_stack[face_stack.
Size()-2];
1557 r = face_t(r.two, r.three, mid);
1569 bool need_refinement = 0;
1570 face_stack.
Append(face_t(v[0], v[1], v[2]));
1571 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1573 if (bit == 8*
sizeof(
unsigned))
1575 code = codes[pos++];
1579 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1581 const face_t &f = face_stack.
Last();
1582 int mid = v_to_v.
FindId(f.one, f.two);
1585 mid = v_to_v.
GetId(f.one, f.two);
1586 int ind[2] = { f.one, f.two };
1589 need_refinement = 1;
1592 face_stack.
Append(face_t(f.three, f.one, mid));
1593 face_t &r = face_stack[face_stack.
Size()-2];
1594 r = face_t(r.two, r.three, mid);
1596 return need_refinement;
1602 if (HYPRE_AssumedPartitionCheck())
1605 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_INT, MPI_SUM,
MyComm);
1606 for (
int i = 0; i < N; i++)
1609 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1610 (*offsets[i])[1] = temp[i];
1613 for (
int i = 0; i < N; i++)
1615 (*offsets[i])[2] = temp[i];
1617 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1618 "overflow in offsets");
1624 MPI_Allgather(loc_sizes, N, HYPRE_MPI_INT, temp.
GetData(), N,
1626 for (
int i = 0; i < N; i++)
1631 for (
int j = 0; j <
NRanks; j++)
1633 offs[j+1] = offs[j] + temp[i+N*j];
1637 "overflow in offsets");
1659 for (
int j = 0; j < nv; j++)
1678 for (
int j = 0; j < n; j++)
1680 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
1688 MFEM_ABORT(
"Nodes are not ParGridFunction!");
1717 space_dim = (space_dim == -1) ?
spaceDim : space_dim;
1754 bool del_tables =
false;
1781 gr_sface =
new Table;
1811 if (del_tables) {
delete gr_sface; }
1822 int num_face_nbrs = 0;
1825 if (gr_sface->
RowSize(g-1) > 0)
1833 if (num_face_nbrs == 0)
1843 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
1845 if (gr_sface->
RowSize(g-1) > 0)
1850 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
1852 rank_group[counter].two = g;
1857 SortPairs<int, int>(rank_group, rank_group.
Size());
1859 for (
int fn = 0; fn < num_face_nbrs; fn++)
1865 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1866 MPI_Request *send_requests = requests;
1867 MPI_Request *recv_requests = requests + num_face_nbrs;
1868 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1870 int *nbr_data =
new int[6*num_face_nbrs];
1871 int *nbr_send_data = nbr_data;
1872 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
1879 Table send_face_nbr_elemdata, send_face_nbr_facedata;
1883 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
1884 send_face_nbr_facedata.
MakeI(num_face_nbrs);
1885 for (
int fn = 0; fn < num_face_nbrs; fn++)
1888 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1889 int *sface = gr_sface->
GetRow(nbr_group-1);
1890 for (
int i = 0; i < num_sfaces; i++)
1892 int lface = s2l_face[sface[i]];
1894 if (el_marker[el] != fn)
1899 const int nv =
elements[el]->GetNVertices();
1900 const int *v =
elements[el]->GetVertices();
1901 for (
int j = 0; j < nv; j++)
1902 if (vertex_marker[v[j]] != fn)
1904 vertex_marker[v[j]] = fn;
1915 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
1920 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1921 &send_requests[fn]);
1922 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1923 &recv_requests[fn]);
1927 send_face_nbr_elemdata.
MakeJ();
1928 send_face_nbr_facedata.
MakeJ();
1932 for (
int fn = 0; fn < num_face_nbrs; fn++)
1935 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1936 int *sface = gr_sface->
GetRow(nbr_group-1);
1937 for (
int i = 0; i < num_sfaces; i++)
1939 const int sf = sface[i];
1940 int lface = s2l_face[sf];
1942 if (el_marker[el] != fn)
1947 const int nv =
elements[el]->GetNVertices();
1948 const int *v =
elements[el]->GetVertices();
1949 for (
int j = 0; j < nv; j++)
1950 if (vertex_marker[v[j]] != fn)
1952 vertex_marker[v[j]] = fn;
1967 const int *lf_v =
faces[lface]->GetVertices();
1987 for (
int fn = 0; fn < num_face_nbrs; fn++)
1993 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
1994 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
1995 int *facedata = send_face_nbr_facedata.
GetRow(fn);
1997 for (
int i = 0; i < num_verts; i++)
1999 vertex_marker[verts[i]] = i;
2002 for (
int el = 0; el < num_elems; el++)
2004 const int nv =
elements[elems[el]]->GetNVertices();
2006 for (
int j = 0; j < nv; j++)
2008 elemdata[j] = vertex_marker[elemdata[j]];
2012 el_marker[elems[el]] = el;
2015 for (
int i = 0; i < num_sfaces; i++)
2017 facedata[2*i] = el_marker[facedata[2*i]];
2021 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2024 Table recv_face_nbr_elemdata;
2029 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
2032 for (
int fn = 0; fn < num_face_nbrs; fn++)
2040 recv_face_nbr_elemdata.
MakeJ();
2042 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2045 for (
int fn = 0; fn < num_face_nbrs; fn++)
2050 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
2051 send_face_nbr_elemdata.
RowSize(fn),
2052 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2054 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
2055 recv_face_nbr_elemdata.
RowSize(fn),
2056 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2064 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2066 if (fn == MPI_UNDEFINED)
2074 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
2076 for (
int i = 0; i < num_elems; i++)
2082 for (
int j = 0; j < nv; j++)
2084 recv_elemdata[j] += vert_off;
2087 recv_elemdata += nv;
2092 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2095 recv_face_nbr_facedata.
SetSize(
2097 for (
int fn = 0; fn < num_face_nbrs; fn++)
2102 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2103 send_face_nbr_facedata.
RowSize(fn),
2104 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2107 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2108 send_face_nbr_facedata.
RowSize(fn),
2109 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2116 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2118 if (fn == MPI_UNDEFINED)
2125 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2126 int *sface = gr_sface->
GetRow(nbr_group-1);
2128 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2130 for (
int i = 0; i < num_sfaces; i++)
2132 const int sf = sface[i];
2133 int lface = s2l_face[sf];
2135 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2136 int info = facedata[2*i+1];
2144 int nbr_ori = info%64, nbr_v[4];
2145 const int *lf_v =
faces[lface]->GetVertices();
2152 for (
int j = 0; j < 3; j++)
2154 nbr_v[perm[j]] = sf_v[j];
2164 for (
int j = 0; j < 4; j++)
2166 nbr_v[perm[j]] = sf_v[j];
2172 info = 64*(info/64) + nbr_ori;
2178 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2195 else if (
Nodes == NULL)
2205 if (!num_face_nbrs) {
return; }
2207 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2208 MPI_Request *send_requests = requests;
2209 MPI_Request *recv_requests = requests + num_face_nbrs;
2210 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2214 for (
int i = 0; i < send_vertices.Size(); i++)
2220 for (
int fn = 0; fn < num_face_nbrs; fn++)
2227 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
2232 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
2235 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2236 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2244 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2255 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2297 for (
int i = 0; i < s2l_face->
Size(); i++)
2312 for (
int i = 0; i < s2l_face->
Size(); i++)
2314 int lface = (*s2l_face)[i];
2315 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2340 #if 0 // TODO: handle the case of non-interpolatory Nodes
2368 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
2417 if (is_ghost || fill2)
2426 std::swap(pm(0,0), pm(0,1));
2427 std::swap(pm(1,0), pm(1,1));
2454 MFEM_ASSERT(
Dim > 1,
"");
2473 MFEM_ASSERT(
Dim > 1,
"");
2476 return sface < csize
2478 : shared.
slaves[sface - csize].index;
2485 void Rotate3Indirect(
int &
a,
int &
b,
int &c,
2488 if (order[a] < order[b])
2490 if (order[a] > order[c])
2497 if (order[b] < order[c])
2518 Table *old_elem_vert = NULL;
2532 gr_svert.
GetI()[0] = 0;
2557 svert_comm.
Bcast(svert_master_index);
2571 for (
int i = 0; i <
vertices.Size(); i++)
2573 int s = lvert_svert[i];
2576 glob_vert_order[i] =
2577 (std::int64_t(svert_master_rank[s]) << 32) + svert_master_index[s];
2581 glob_vert_order[i] = (std::int64_t(
MyRank) << 32) + i;
2593 int *v =
elements[i]->GetVertices();
2595 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2597 if (glob_vert_order[v[0]] < glob_vert_order[v[3]])
2599 Rotate3Indirect(v[1], v[2], v[3], glob_vert_order);
2613 int *v =
boundary[i]->GetVertices();
2615 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2619 const bool check_consistency =
true;
2620 if (check_consistency)
2629 gr_stria.
GetI()[0] = 0;
2641 for (
int i = 0; i < stria_flag.Size(); i++)
2644 if (glob_vert_order[v[0]] < glob_vert_order[v[1]])
2646 stria_flag[i] = (glob_vert_order[v[0]] < glob_vert_order[v[2]]) ? 0 : 2;
2650 stria_flag[i] = (glob_vert_order[v[1]] < glob_vert_order[v[2]]) ? 1 : 2;
2655 stria_comm.
Bcast(stria_master_flag);
2656 for (
int i = 0; i < stria_flag.Size(); i++)
2659 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
2660 "inconsistent vertex ordering found, shared triangle "
2662 << v[0] <<
", " << v[1] <<
", " << v[2] <<
"), "
2663 <<
"local flag: " << stria_flag[i]
2664 <<
", master flag: " << stria_master_flag[i]);
2673 Rotate3Indirect(v[0], v[1], v[2], glob_vert_order);
2689 delete old_elem_vert;
2702 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
2711 int uniform_refinement = 0;
2715 uniform_refinement = 1;
2726 for (
int i = 0; i < marked_el.
Size(); i++)
2732 for (
int i = 0; i < marked_el.
Size(); i++)
2741 for (
int i = 0; i < marked_el.
Size(); i++)
2758 int need_refinement;
2759 int max_faces_in_group = 0;
2765 face_splittings[i].
Reserve(faces_in_group);
2766 if (faces_in_group > max_faces_in_group)
2768 max_faces_in_group = faces_in_group;
2774 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
2777 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2778 int ref_loops_all = 0, ref_loops_par = 0;
2782 need_refinement = 0;
2785 if (
elements[i]->NeedRefinement(v_to_v))
2787 need_refinement = 1;
2791 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2795 if (uniform_refinement)
2802 if (need_refinement == 0)
2804 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2808 const int tag = 293;
2817 if (faces_in_group == 0) {
continue; }
2819 face_splittings[i].
SetSize(0);
2820 for (
int j = 0; j < faces_in_group; j++)
2823 face_splittings[i]);
2827 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
2828 MPI_UNSIGNED, neighbor, tag,
MyComm,
2829 &requests[req_count++]);
2837 if (faces_in_group == 0) {
continue; }
2841 MPI_Probe(neighbor, tag,
MyComm, &status);
2843 MPI_Get_count(&status, MPI_UNSIGNED, &count);
2845 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
2848 for (
int j = 0, pos = 0; j < faces_in_group; j++)
2855 int nr = need_refinement;
2856 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2858 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
2861 while (need_refinement == 1);
2863 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2865 int i = ref_loops_all;
2866 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2869 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2870 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2878 delete [] face_splittings;
2883 need_refinement = 0;
2886 if (
boundary[i]->NeedRefinement(v_to_v))
2888 need_refinement = 1;
2893 while (need_refinement == 1);
2898 " (NumOfBdrElements != boundary.Size())");
2925 int uniform_refinement = 0;
2929 uniform_refinement = 1;
2938 int *edge1 =
new int[nedges];
2939 int *edge2 =
new int[nedges];
2940 int *middle =
new int[nedges];
2942 for (
int i = 0; i < nedges; i++)
2944 edge1[i] = edge2[i] = middle[i] = -1;
2949 int *v =
elements[i]->GetVertices();
2950 for (
int j = 0; j < 3; j++)
2952 int ind = v_to_v(v[j], v[(j+1)%3]);
2953 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
2958 for (
int i = 0; i < marked_el.
Size(); i++)
2964 int need_refinement;
2965 int edges_in_group, max_edges_in_group = 0;
2967 int **edge_splittings =
new int*[
GetNGroups()-1];
2971 edge_splittings[i] =
new int[edges_in_group];
2972 if (edges_in_group > max_edges_in_group)
2974 max_edges_in_group = edges_in_group;
2977 int neighbor, *iBuf =
new int[max_edges_in_group];
2981 MPI_Request request;
2986 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2987 int ref_loops_all = 0, ref_loops_par = 0;
2991 need_refinement = 0;
2992 for (
int i = 0; i < nedges; i++)
2994 if (middle[i] != -1 && edge1[i] != -1)
2996 need_refinement = 1;
3000 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3004 if (uniform_refinement)
3011 if (need_refinement == 0)
3013 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3022 edges_in_group = group_edges.
Size();
3024 if (edges_in_group != 0)
3026 for (
int j = 0; j < edges_in_group; j++)
3028 edge_splittings[i][j] =
3041 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
3042 neighbor, 0,
MyComm, &request);
3050 edges_in_group = group_edges.
Size();
3051 if (edges_in_group != 0)
3062 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
3063 MPI_ANY_TAG,
MyComm, &status);
3065 for (
int j = 0; j < edges_in_group; j++)
3067 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
3070 int ii = v_to_v(v[0], v[1]);
3071 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3072 if (middle[ii] != -1)
3074 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
3078 need_refinement = 1;
3080 for (
int c = 0; c < 2; c++)
3090 int nr = need_refinement;
3091 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
3094 while (need_refinement == 1);
3096 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
3098 int i = ref_loops_all;
3099 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
3102 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
3103 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
3111 delete [] edge_splittings[i];
3113 delete [] edge_splittings;
3118 int v1[2], v2[2], bisect, temp;
3120 for (
int i = 0; i < temp; i++)
3122 int *v =
boundary[i]->GetVertices();
3123 bisect = v_to_v(v[0], v[1]);
3124 if (middle[bisect] != -1)
3129 v1[0] = v[0]; v1[1] = middle[bisect];
3130 v2[0] = middle[bisect]; v2[1] = v[1];
3137 mfem_error(
"Only bisection of segment is implemented for bdr"
3170 for (
int j = 0; j < marked_el.
Size(); j++)
3172 int i = marked_el[j];
3175 int new_v = cnv + j, new_e = cne + j;
3184 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
3186 UseExternalData(seg_children, 1, 2, 3);
3207 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
3208 "supported. Project the NURBS to Nodes first.");
3213 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
3214 "(you need to initialize the ParMesh from a nonconforming "
3240 Swap(*pmesh2,
false);
3255 double threshold,
int nc_limit,
int op)
3257 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3258 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3259 "Project the NURBS to Nodes first.");
3272 for (
int i = 0; i < dt.
Size(); i++)
3274 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3279 if (error < threshold) { derefs.
Append(i); }
3283 if (!glob_size) {
return false; }
3296 Swap(*mesh2,
false);
3326 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
3336 *new_nodes = *
Nodes;
3357 Swap(*pmesh2,
false);
3374 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
3384 int *I_group_svert, *J_group_svert;
3385 int *I_group_sedge, *J_group_sedge;
3390 I_group_svert[0] = I_group_svert[1] = 0;
3391 I_group_sedge[0] = I_group_sedge[1] = 0;
3398 for (
int group = 0; group <
GetNGroups()-1; group++)
3408 const int ind = middle[v_to_v(v[0], v[1])];
3414 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3421 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3422 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3425 J = J_group_svert+I_group_svert[group];
3426 for (
int i = 0; i < group_verts.
Size(); i++)
3428 J[i] = group_verts[i];
3430 J = J_group_sedge+I_group_sedge[group];
3431 for (
int i = 0; i < group_edges.
Size(); i++)
3433 J[i] = group_edges[i];
3447 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
3449 Array<int> group_verts, group_edges, group_trias;
3468 I_group_svert[0] = 0;
3469 I_group_sedge[0] = 0;
3470 I_group_stria[0] = 0;
3472 for (
int group = 0; group <
GetNGroups()-1; group++)
3483 int ind = v_to_v.
FindId(v[0], v[1]);
3484 if (ind == -1) {
continue; }
3487 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3497 ind = v_to_v.
FindId(v[0], ind);
3505 ind = v_to_v.
FindId(v[0], v[1]);
3526 while (sedge_stack.
Size() > 0);
3533 int ind = v_to_v.
FindId(v[0], v[1]);
3534 if (ind == -1) {
continue; }
3537 const int edge_attr = 1;
3546 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
3547 ind = v_to_v.
FindId(v[0], v[1]);
3555 ind = v_to_v.
FindId(v[0], v[1]);
3573 v = sface_stack[sface_stack.
Size()-2].v;
3575 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
3578 while (sface_stack.
Size() > 0);
3584 ind = v_to_v.
FindId(v[0], v[1]);
3605 while (sedge_stack.
Size() > 0);
3608 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3609 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3610 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3612 J_group_svert.
Append(group_verts);
3613 J_group_sedge.
Append(group_edges);
3614 J_group_stria.
Append(group_trias);
3631 int *I_group_svert, *J_group_svert;
3632 int *I_group_sedge, *J_group_sedge;
3637 I_group_svert[0] = 0;
3638 I_group_sedge[0] = 0;
3645 for (
int group = 0; group <
GetNGroups()-1; group++)
3659 const int attr =
shared_edges[sedges[i]]->GetAttribute();
3665 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
3666 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
3668 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
3669 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3685 Array<int> group_verts, group_edges, group_trias, group_quads;
3687 int *I_group_svert, *J_group_svert;
3688 int *I_group_sedge, *J_group_sedge;
3689 int *I_group_stria, *J_group_stria;
3690 int *I_group_squad, *J_group_squad;
3697 I_group_svert[0] = 0;
3698 I_group_sedge[0] = 0;
3699 I_group_stria[0] = 0;
3700 I_group_squad[0] = 0;
3712 const int oface = old_nv + old_nedges;
3714 for (
int group = 0; group <
GetNGroups()-1; group++)
3726 const int ind = old_nv + old_v_to_v(v[0], v[1]);
3730 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3740 const int stria = group_trias[i];
3743 m[0] = old_nv + old_v_to_v(v[0], v[1]);
3744 m[1] = old_nv + old_v_to_v(v[1], v[2]);
3745 m[2] = old_nv + old_v_to_v(v[2], v[0]);
3746 const int edge_attr = 1;
3761 v[1] = m[0]; v[2] = m[2];
3762 group_trias.
Append(nst+0);
3763 group_trias.
Append(nst+1);
3764 group_trias.
Append(nst+2);
3772 const int squad = group_quads[i];
3774 const int olf = old_faces(v[0], v[1], v[2], v[3]);
3776 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
3780 m[1] = old_nv + old_v_to_v(v[0], v[1]);
3781 m[2] = old_nv + old_v_to_v(v[1], v[2]);
3782 m[3] = old_nv + old_v_to_v(v[2], v[3]);
3783 m[4] = old_nv + old_v_to_v(v[3], v[0]);
3784 const int edge_attr = 1;
3801 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
3802 group_quads.
Append(nsq+0);
3803 group_quads.
Append(nsq+1);
3804 group_quads.
Append(nsq+2);
3808 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3809 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3810 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3811 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
3813 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
3814 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3815 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
3816 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
3835 const bool update_nodes =
false;
3865 const bool update_nodes =
false;
3874 f2qf.
Size() ? &f2qf : NULL);
3884 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
3890 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
3896 out <<
"NETGEN_Neutral_Format\n";
3901 for (j = 0; j <
Dim; j++)
3914 out <<
elements[i]->GetAttribute();
3915 for (j = 0; j < nv; j++)
3917 out <<
" " << ind[j]+1;
3929 out <<
boundary[i]->GetAttribute();
3930 for (j = 0; j < nv; j++)
3932 out <<
" " << ind[j]+1;
3943 for (j = 0; j < 3; j++)
3945 out <<
' ' << ind[j]+1;
3959 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3961 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3962 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3963 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
3969 <<
" " <<
vertices[i](2) <<
" 0.0\n";
3977 out << i+1 <<
" " <<
elements[i]->GetAttribute();
3978 for (j = 0; j < nv; j++)
3980 out <<
" " << ind[j]+1;
3990 out <<
boundary[i]->GetAttribute();
3991 for (j = 0; j < nv; j++)
3993 out <<
" " << ind[j]+1;
3995 out <<
" 1.0 1.0 1.0 1.0\n";
4006 for (j = 0; j < 4; j++)
4008 out <<
' ' << ind[j]+1;
4010 out <<
" 1.0 1.0 1.0 1.0\n";
4019 out <<
"areamesh2\n\n";
4026 attr =
boundary[i]->GetAttribute();
4029 for (j = 0; j < v.
Size(); j++)
4031 out << v[j] + 1 <<
" ";
4041 for (j = 0; j < v.
Size(); j++)
4043 out << v[j] + 1 <<
" ";
4052 attr =
elements[i]->GetAttribute();
4068 for (j = 0; j < v.
Size(); j++)
4070 out << v[j] + 1 <<
" ";
4079 for (j = 0; j <
Dim; j++)
4104 bool print_shared =
true;
4105 int i, j, shared_bdr_attr;
4122 s2l_face = &nc_shared_faces;
4129 for (
unsigned i = 0; i < sfaces.
conforming.size(); i++)
4132 if (index < nfaces) { nc_shared_faces.
Append(index); }
4134 for (
unsigned i = 0; i < sfaces.
masters.size(); i++)
4138 if (index < nfaces) { nc_shared_faces.
Append(index); }
4140 for (
unsigned i = 0; i < sfaces.
slaves.size(); i++)
4143 if (index < nfaces) { nc_shared_faces.
Append(index); }
4148 out <<
"MFEM mesh v1.0\n";
4152 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4157 "# TETRAHEDRON = 4\n"
4162 out <<
"\ndimension\n" <<
Dim
4170 if (print_shared &&
Dim > 1)
4172 num_bdr_elems += s2l_face->
Size();
4174 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
4180 if (print_shared &&
Dim > 1)
4188 shared_bdr_attr =
MyRank + 1;
4190 for (i = 0; i < s2l_face->
Size(); i++)
4193 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
4225 for (
int i = 0; i < nv; i++)
4233 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4241 out <<
"MFEM mesh v1.0\n";
4245 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4250 "# TETRAHEDRON = 4\n"
4255 out <<
"\ndimension\n" <<
Dim;
4259 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4262 out <<
"\n\nelements\n" << ne <<
'\n';
4266 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
4270 for (j = 0; j < nv; j++)
4277 for (p = 1; p <
NRanks; p++)
4279 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
4283 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
4285 for (i = 0; i < ne; )
4288 out << p+1 <<
' ' << ints[i];
4291 for (j = 0; j < k; j++)
4293 out <<
' ' << vc + ints[i++];
4306 ne += 1 +
elements[i]->GetNVertices();
4309 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
4317 MFEM_ASSERT(ints.
Size() == ne,
"");
4320 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
4345 dump_element(
boundary[i], ints); ne++;
4383 MFEM_ABORT(
"invalid dimension: " <<
Dim);
4390 for (i = 0; i < (int) list.
conforming.size(); i++)
4393 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4395 for (i = 0; i < (int) list.
masters.size(); i++)
4398 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4400 for (i = 0; i < (int) list.
slaves.size(); i++)
4403 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4407 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4410 out <<
"\nboundary\n" << k <<
'\n';
4412 for (p = 0; p <
NRanks; p++)
4416 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
4420 MPI_Recv(ints.
GetData(), ne, MPI_INT, p, 447,
MyComm, &status);
4428 for (i = 0; i < ne; )
4431 out << p+1 <<
' ' << ints[i];
4434 for (j = 0; j < k; j++)
4436 out <<
' ' << vc + ints[i++];
4447 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
4458 out <<
"\nvertices\n" << nv <<
'\n';
4474 for (p = 1; p <
NRanks; p++)
4476 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
4480 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
4482 for (i = 0; i < nv; i++)
4487 out <<
' ' << vert[i*spaceDim+j];
4502 vert[i*spaceDim+j] =
vertices[i](j);
4507 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
4534 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
4542 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
4545 int i, j, k, nv, ne, p;
4553 out <<
"NETGEN_Neutral_Format\n";
4556 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4560 for (j = 0; j <
Dim; j++)
4566 for (p = 1; p <
NRanks; p++)
4568 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4570 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4571 for (i = 0; i < nv; i++)
4573 for (j = 0; j <
Dim; j++)
4575 out <<
" " << vert[Dim*i+j];
4583 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4590 for (j = 0; j < nv; j++)
4592 out <<
" " << ind[j]+1;
4597 for (p = 1; p <
NRanks; p++)
4599 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4600 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4602 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4603 for (i = 0; i < ne; i++)
4606 for (j = 0; j < 4; j++)
4608 out <<
" " << k+ints[i*4+j]+1;
4616 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4624 for (j = 0; j < nv; j++)
4626 out <<
" " << ind[j]+1;
4637 for (j = 0; j < 3; j++)
4639 out <<
' ' << ind[j]+1;
4645 for (p = 1; p <
NRanks; p++)
4647 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4648 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4650 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4651 for (i = 0; i < ne; i++)
4654 for (j = 0; j < 3; j++)
4656 out <<
' ' << k+ints[i*3+j]+1;
4666 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4670 for (j = 0; j <
Dim; j++)
4674 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4678 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4679 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4685 for (j = 0; j < 4; j++)
4690 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
4693 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4694 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4696 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4701 for (j = 0; j < 3; j++)
4706 for ( ; i < ne; i++)
4709 for (j = 0; j < 3; j++)
4714 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
4720 int i, j, k, nv, ne, p;
4726 int TG_nv, TG_ne, TG_nbe;
4733 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4736 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
4737 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4738 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4739 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4740 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4747 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4749 for (p = 1; p <
NRanks; p++)
4751 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4753 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4754 for (i = 0; i < nv; i++)
4756 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
4757 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
4767 out << i+1 <<
" " << 1;
4768 for (j = 0; j < nv; j++)
4770 out <<
" " << ind[j]+1;
4775 for (p = 1; p <
NRanks; p++)
4777 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4778 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4780 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
4781 for (i = 0; i < ne; i++)
4783 out << i+1 <<
" " << p+1;
4784 for (j = 0; j < 8; j++)
4786 out <<
" " << k+ints[i*8+j]+1;
4801 for (j = 0; j < nv; j++)
4803 out <<
" " << ind[j]+1;
4805 out <<
" 1.0 1.0 1.0 1.0\n";
4815 for (j = 0; j < 4; j++)
4817 out <<
' ' << ind[j]+1;
4819 out <<
" 1.0 1.0 1.0 1.0\n";
4822 for (p = 1; p <
NRanks; p++)
4824 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4825 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4827 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4828 for (i = 0; i < ne; i++)
4831 for (j = 0; j < 4; j++)
4833 out <<
" " << k+ints[i*4+j]+1;
4835 out <<
" 1.0 1.0 1.0 1.0\n";
4845 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4850 for (j = 0; j <
Dim; j++)
4854 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
4856 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4862 for (j = 0; j < 8; j++)
4867 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
4869 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4871 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4876 for (j = 0; j < 4; j++)
4881 for ( ; i < ne; i++)
4884 for (j = 0; j < 4; j++)
4889 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
4895 int i, j, k, attr, nv, ne, p;
4903 out <<
"areamesh2\n\n";
4907 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4912 attr =
boundary[i]->GetAttribute();
4915 for (j = 0; j < v.
Size(); j++)
4917 out << v[j] + 1 <<
" ";
4927 for (j = 0; j < v.
Size(); j++)
4929 out << v[j] + 1 <<
" ";
4934 for (p = 1; p <
NRanks; p++)
4936 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4937 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4939 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
4940 for (i = 0; i < ne; i++)
4943 for (j = 0; j < 2; j++)
4945 out <<
" " << k+ints[i*2+j]+1;
4954 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4960 out << 1 <<
" " << 3 <<
" ";
4961 for (j = 0; j < v.
Size(); j++)
4963 out << v[j] + 1 <<
" ";
4968 for (p = 1; p <
NRanks; p++)
4970 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4971 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4973 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4974 for (i = 0; i < ne; i++)
4976 out << p+1 <<
" " << 3;
4977 for (j = 0; j < 3; j++)
4979 out <<
" " << k+ints[i*3+j]+1;
4988 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4992 for (j = 0; j <
Dim; j++)
4998 for (p = 1; p <
NRanks; p++)
5000 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
5002 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
5003 for (i = 0; i < nv; i++)
5005 for (j = 0; j <
Dim; j++)
5007 out <<
" " << vert[Dim*i+j];
5017 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5020 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
5025 for (j = 0; j < 2; j++)
5030 for ( ; i < ne; i++)
5033 for (j = 0; j < 2; j++)
5038 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
5041 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5048 for (j = 0; j < 3; j++)
5053 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
5056 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
5060 for (j = 0; j <
Dim; j++)
5064 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
5082 MPI_Allreduce(p_min.
GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN,
MyComm);
5083 MPI_Allreduce(p_max.
GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX,
MyComm);
5087 double &gk_min,
double &gk_max)
5089 double h_min, h_max, kappa_min, kappa_max;
5093 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
5094 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
5095 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
5096 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
5103 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
5107 out <<
"Parallel Mesh Stats:" <<
'\n';
5113 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
5119 kappa_min = kappa_max =
kappa;
5123 if (h < h_min) { h_min = h; }
5124 if (h > h_max) { h_max = h; }
5125 if (kappa < kappa_min) { kappa_min =
kappa; }
5126 if (kappa > kappa_max) { kappa_max =
kappa; }
5130 double gh_min, gh_max, gk_min, gk_max;
5131 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
5132 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
5133 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
5134 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
5139 long mindata[5], maxdata[5], sumdata[5];
5158 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
5159 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
5160 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
5166 << setw(12) <<
"minimum"
5167 << setw(12) <<
"average"
5168 << setw(12) <<
"maximum"
5169 << setw(12) <<
"total" <<
'\n';
5171 << setw(12) << mindata[0]
5172 << setw(12) << sumdata[0]/
NRanks
5173 << setw(12) << maxdata[0]
5174 << setw(12) << sumdata[0] <<
'\n';
5176 << setw(12) << mindata[1]
5177 << setw(12) << sumdata[1]/
NRanks
5178 << setw(12) << maxdata[1]
5179 << setw(12) << sumdata[1] <<
'\n';
5183 << setw(12) << mindata[2]
5184 << setw(12) << sumdata[2]/
NRanks
5185 << setw(12) << maxdata[2]
5186 << setw(12) << sumdata[2] <<
'\n';
5189 << setw(12) << mindata[3]
5190 << setw(12) << sumdata[3]/
NRanks
5191 << setw(12) << maxdata[3]
5192 << setw(12) << sumdata[3] <<
'\n';
5193 out <<
" neighbors "
5194 << setw(12) << mindata[4]
5195 << setw(12) << sumdata[4]/
NRanks
5196 << setw(12) << maxdata[4] <<
'\n';
5199 << setw(12) <<
"minimum"
5200 << setw(12) <<
"maximum" <<
'\n';
5202 << setw(12) << gh_min
5203 << setw(12) << gh_max <<
'\n';
5205 << setw(12) << gk_min
5206 << setw(12) << gk_max <<
'\n';
5213 long local = value, global;
5214 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
5230 Printer(out,
"mfem_serial_mesh_end");
5238 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5249 out <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
5250 for (
int i = 0; i < nv; i++)
5259 out <<
"\nshared_edges " << ne <<
'\n';
5260 for (
int i = 0; i < ne; i++)
5263 out << v[0] <<
' ' << v[1] <<
'\n';
5272 out <<
"\nshared_faces " << nt+nq <<
'\n';
5273 for (
int i = 0; i < nt; i++)
5277 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5280 for (
int i = 0; i < nq; i++)
5284 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5291 out <<
"\nmfem_mesh_end" << endl;
5298 const int npts = point_mat.
Width();
5299 if (npts == 0) {
return 0; }
5301 const bool no_warn =
false;
5308 Array<int> my_point_rank(npts), glob_point_rank(npts);
5309 for (
int k = 0; k < npts; k++)
5311 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
5314 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
5315 MPI_INT, MPI_MIN,
MyComm);
5318 for (
int k = 0; k < npts; k++)
5320 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
5324 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
5327 if (warn && pts_found != npts &&
MyRank == 0)
5329 MFEM_WARNING((npts-pts_found) <<
" points were not found");
5334 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &
out)
5337 for (
int d = 1; d < space_dim; d++)
5345 stringstream out_name;
5346 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
5347 <<
".shared_entities";
5348 ofstream
out(out_name.str().c_str());
5356 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5367 out <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
5368 for (
int i = 0; i < nv; i++)
5380 out <<
"\nshared_edges " << ne <<
'\n';
5381 for (
int i = 0; i < ne; i++)
5397 out <<
"\nshared_faces " << nt+nq <<
'\n';
5398 for (
int i = 0; i < nt; i++)
5403 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5406 for (
int j = 0; j < 3; j++)
5409 (j < 2) ? out <<
" | " : out <<
'\n';
5412 for (
int i = 0; i < nq; i++)
5417 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5420 for (
int j = 0; j < 4; j++)
5423 (j < 3) ? out <<
" | " : out <<
'\n';
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
Geometry::Type GetGeometryType() const
int GetGroupMasterRank(int g) const
int GetNFaceNeighbors() const
void PrintAsOneXG(std::ostream &out=mfem::out)
Old mesh format (Netgen/Truegrid) version of 'PrintAsOne'.
void Create(ListOfIntegerSets &groups, int mpitag)
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
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)
void Recreate(const int n, const int *p)
Class for an integration rule - an Array of IntegrationPoint.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
void Bcast(T *ldata, int layout) const
Broadcast within each group where the master is the root.
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
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
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
Element::Type GetBdrElementType(int i) const
Returns the type of boundary element i.
void Copy(Array ©) const
Create a copy of the current array.
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)
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.
Array< Vert3 > shared_trias
virtual int DofForGeometry(Geometry::Type GeomType) const
Array< int > face_nbr_vertices_offset
std::vector< MeshId > conforming
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)
void DeleteAll()
Delete whole array.
void AddConnections(int r, const int *c, int nc)
void InitRefinementTransforms()
IsoparametricTransformation FaceTransformation
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
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
int FindSharedEdges(const Mesh &mesh, const int *partition, Table *&edge_element, ListOfIntegerSets &groups)
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)
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)
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 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
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
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.
std::vector< Master > masters
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
int Insert(IntegerSet &s)
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
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. 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()
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.
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
std::vector< Slave > slaves
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 ApplyLocalSlaveTransformation(IsoparametricTransformation &transf, const FaceInfo &fi)
static void PrintElement(const Element *, std::ostream &)
int GetNeighborRank(int i) const
void AddAColumnInRow(int r)
GridFunction * GetNodes()
Return a pointer to the internal node GridFunction (may be NULL).
void SetSize(int nsize)
Change 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.
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)
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.
Table group_svert
Shared objects in each group.
bool DecodeFaceSplittings(HashTable< Hashed2 > &v_to_v, const int *v, const Array< unsigned > &codes, int &pos)
ElementTransformation * GetGhostFaceTransformation(FaceElementTransformations *FETr, Element::Type face_type, Geometry::Type face_geom)
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.
void GetVectorValues(ElementTransformation &T, const IntegrationRule &ir, DenseMatrix &vals) const
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.
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.
void Printer(std::ostream &out=mfem::out, std::string section_delimiter="") const
ParFiniteElementSpace * ParFESpace() const
virtual void NURBSUniformRefinement()
Refine NURBS mesh.