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;
1300 o = (v[0] < v[1]) ? (+1) : (-1);
1309 "Expecting a triangular face.");
1320 "Expecting a quadrilateral face.");
1336 gr_sedge.
GetI()[0] = 0;
1355 sedge_ord[k] = order[v_to_v(v[0], v[1])];
1358 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1360 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1363 if (n == 0) {
continue; }
1364 sedge_ord_map.SetSize(n);
1365 for (
int j = 0; j < n; j++)
1367 sedge_ord_map[j].one = sedge_ord[k+j];
1368 sedge_ord_map[j].two = j;
1370 SortPairs<int, int>(sedge_ord_map, n);
1371 for (
int j = 0; j < n; j++)
1374 const int *v =
shared_edges[sedge_from]->GetVertices();
1375 sedge_ord[k+j] = order[v_to_v(v[0], v[1])];
1377 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1378 for (
int j = 0; j < n; j++)
1382 order[v_to_v(v[0], v[1])] = sedge_ord[k+j];
1396 ilen_len[j].one = order[j];
1397 ilen_len[j].two =
GetLength(i, it.Column());
1401 SortPairs<int, double>(ilen_len, order.
Size());
1404 for (
int i = 1; i < order.
Size(); i++)
1406 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1416 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1419 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1431 elements[i]->MarkEdge(v_to_v, order);
1439 boundary[i]->MarkEdge(v_to_v, order);
1458 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1475 face_stack.
Append(face_t(fv[0], fv[1], fv[2]));
1476 for (
unsigned bit = 0; face_stack.
Size() > 0; bit++)
1478 if (bit == 8*
sizeof(
unsigned))
1484 const face_t &f = face_stack.
Last();
1485 int mid = v_to_v.
FindId(f.one, f.two);
1495 face_stack.
Append(face_t(f.three, f.one, mid));
1496 face_t &r = face_stack[face_stack.
Size()-2];
1497 r = face_t(r.two, r.three, mid);
1509 bool need_refinement = 0;
1510 face_stack.
Append(face_t(v[0], v[1], v[2]));
1511 for (
unsigned bit = 0, code = codes[pos++]; face_stack.
Size() > 0; bit++)
1513 if (bit == 8*
sizeof(
unsigned))
1515 code = codes[pos++];
1519 if ((code & (1 << bit)) == 0) { face_stack.
DeleteLast();
continue; }
1521 const face_t &f = face_stack.
Last();
1522 int mid = v_to_v.
FindId(f.one, f.two);
1525 mid = v_to_v.
GetId(f.one, f.two);
1526 int ind[2] = { f.one, f.two };
1529 need_refinement = 1;
1532 face_stack.
Append(face_t(f.three, f.one, mid));
1533 face_t &r = face_stack[face_stack.
Size()-2];
1534 r = face_t(r.two, r.three, mid);
1536 return need_refinement;
1542 if (HYPRE_AssumedPartitionCheck())
1545 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_INT, MPI_SUM,
MyComm);
1546 for (
int i = 0; i < N; i++)
1549 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1550 (*offsets[i])[1] = temp[i];
1553 for (
int i = 0; i < N; i++)
1555 (*offsets[i])[2] = temp[i];
1557 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1558 "overflow in offsets");
1564 MPI_Allgather(loc_sizes, N, HYPRE_MPI_INT, temp.
GetData(), N,
1566 for (
int i = 0; i < N; i++)
1571 for (
int j = 0; j <
NRanks; j++)
1573 offs[j+1] = offs[j] + temp[i+N*j];
1577 "overflow in offsets");
1599 for (
int j = 0; j < nv; j++)
1618 for (
int j = 0; j < n; j++)
1620 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
1628 MFEM_ABORT(
"Nodes are not ParGridFunction!");
1674 bool del_tables =
false;
1701 gr_sface =
new Table;
1731 if (del_tables) {
delete gr_sface; }
1742 int num_face_nbrs = 0;
1745 if (gr_sface->
RowSize(g-1) > 0)
1753 if (num_face_nbrs == 0)
1763 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
1765 if (gr_sface->
RowSize(g-1) > 0)
1770 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
1772 rank_group[counter].two = g;
1777 SortPairs<int, int>(rank_group, rank_group.
Size());
1779 for (
int fn = 0; fn < num_face_nbrs; fn++)
1785 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1786 MPI_Request *send_requests = requests;
1787 MPI_Request *recv_requests = requests + num_face_nbrs;
1788 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1790 int *nbr_data =
new int[6*num_face_nbrs];
1791 int *nbr_send_data = nbr_data;
1792 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
1799 Table send_face_nbr_elemdata, send_face_nbr_facedata;
1803 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
1804 send_face_nbr_facedata.
MakeI(num_face_nbrs);
1805 for (
int fn = 0; fn < num_face_nbrs; fn++)
1808 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1809 int *sface = gr_sface->
GetRow(nbr_group-1);
1810 for (
int i = 0; i < num_sfaces; i++)
1812 int lface = s2l_face[sface[i]];
1814 if (el_marker[el] != fn)
1819 const int nv =
elements[el]->GetNVertices();
1820 const int *v =
elements[el]->GetVertices();
1821 for (
int j = 0; j < nv; j++)
1822 if (vertex_marker[v[j]] != fn)
1824 vertex_marker[v[j]] = fn;
1835 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
1840 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1841 &send_requests[fn]);
1842 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1843 &recv_requests[fn]);
1847 send_face_nbr_elemdata.
MakeJ();
1848 send_face_nbr_facedata.
MakeJ();
1852 for (
int fn = 0; fn < num_face_nbrs; fn++)
1855 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1856 int *sface = gr_sface->
GetRow(nbr_group-1);
1857 for (
int i = 0; i < num_sfaces; i++)
1859 const int sf = sface[i];
1860 int lface = s2l_face[sf];
1862 if (el_marker[el] != fn)
1867 const int nv =
elements[el]->GetNVertices();
1868 const int *v =
elements[el]->GetVertices();
1869 for (
int j = 0; j < nv; j++)
1870 if (vertex_marker[v[j]] != fn)
1872 vertex_marker[v[j]] = fn;
1887 const int *lf_v =
faces[lface]->GetVertices();
1907 for (
int fn = 0; fn < num_face_nbrs; fn++)
1913 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
1914 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
1915 int *facedata = send_face_nbr_facedata.
GetRow(fn);
1917 for (
int i = 0; i < num_verts; i++)
1919 vertex_marker[verts[i]] = i;
1922 for (
int el = 0; el < num_elems; el++)
1924 const int nv =
elements[elems[el]]->GetNVertices();
1926 for (
int j = 0; j < nv; j++)
1928 elemdata[j] = vertex_marker[elemdata[j]];
1932 el_marker[elems[el]] = el;
1935 for (
int i = 0; i < num_sfaces; i++)
1937 facedata[2*i] = el_marker[facedata[2*i]];
1941 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1944 Table recv_face_nbr_elemdata;
1949 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
1952 for (
int fn = 0; fn < num_face_nbrs; fn++)
1960 recv_face_nbr_elemdata.
MakeJ();
1962 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1965 for (
int fn = 0; fn < num_face_nbrs; fn++)
1970 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
1971 send_face_nbr_elemdata.
RowSize(fn),
1972 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1974 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
1975 recv_face_nbr_elemdata.
RowSize(fn),
1976 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1984 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1986 if (fn == MPI_UNDEFINED)
1994 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
1996 for (
int i = 0; i < num_elems; i++)
2002 for (
int j = 0; j < nv; j++)
2004 recv_elemdata[j] += vert_off;
2007 recv_elemdata += nv;
2012 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2015 recv_face_nbr_facedata.
SetSize(
2017 for (
int fn = 0; fn < num_face_nbrs; fn++)
2022 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
2023 send_face_nbr_facedata.
RowSize(fn),
2024 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
2027 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
2028 send_face_nbr_facedata.
RowSize(fn),
2029 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
2036 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
2038 if (fn == MPI_UNDEFINED)
2045 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
2046 int *sface = gr_sface->
GetRow(nbr_group-1);
2048 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
2050 for (
int i = 0; i < num_sfaces; i++)
2052 const int sf = sface[i];
2053 int lface = s2l_face[sf];
2055 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
2056 int info = facedata[2*i+1];
2064 int nbr_ori = info%64, nbr_v[4];
2065 const int *lf_v =
faces[lface]->GetVertices();
2072 for (
int j = 0; j < 3; j++)
2074 nbr_v[perm[j]] = sf_v[j];
2084 for (
int j = 0; j < 4; j++)
2086 nbr_v[perm[j]] = sf_v[j];
2092 info = 64*(info/64) + nbr_ori;
2098 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2115 else if (
Nodes == NULL)
2125 if (!num_face_nbrs) {
return; }
2127 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
2128 MPI_Request *send_requests = requests;
2129 MPI_Request *recv_requests = requests + num_face_nbrs;
2130 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
2134 for (
int i = 0; i < send_vertices.Size(); i++)
2140 for (
int fn = 0; fn < num_face_nbrs; fn++)
2147 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
2152 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
2155 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
2156 MPI_Waitall(num_face_nbrs, send_requests, statuses);
2164 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
2175 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
2217 for (
int i = 0; i < s2l_face->
Size(); i++)
2232 for (
int i = 0; i < s2l_face->
Size(); i++)
2234 int lface = (*s2l_face)[i];
2235 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
2260 #if 0 // TODO: handle the case of non-interpolatory Nodes
2288 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
2337 if (is_ghost || fill2)
2346 std::swap(pm(0,0), pm(0,1));
2347 std::swap(pm(1,0), pm(1,1));
2374 MFEM_ASSERT(
Dim > 1,
"");
2393 MFEM_ASSERT(
Dim > 1,
"");
2396 return sface < csize
2398 : shared.
slaves[sface - csize].index;
2411 const bool check_consistency =
true;
2412 if (check_consistency)
2421 gr_stria.
GetI()[0] = 0;
2433 for (
int i = 0; i < stria_flag.Size(); i++)
2438 stria_flag[i] = (v[0] < v[2]) ? 0 : 2;
2442 stria_flag[i] = (v[1] < v[2]) ? 1 : 2;
2446 stria_comm.
Bcast(stria_master_flag);
2447 for (
int i = 0; i < stria_flag.Size(); i++)
2449 MFEM_VERIFY(stria_flag[i] == stria_master_flag[i],
2450 "inconsistent vertex ordering found");
2475 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
2484 int uniform_refinement = 0;
2488 uniform_refinement = 1;
2499 for (
int i = 0; i < marked_el.
Size(); i++)
2505 for (
int i = 0; i < marked_el.
Size(); i++)
2514 for (
int i = 0; i < marked_el.
Size(); i++)
2531 int need_refinement;
2532 int max_faces_in_group = 0;
2538 face_splittings[i].
Reserve(faces_in_group);
2539 if (faces_in_group > max_faces_in_group)
2541 max_faces_in_group = faces_in_group;
2547 MPI_Request *requests =
new MPI_Request[
GetNGroups()-1];
2550 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2551 int ref_loops_all = 0, ref_loops_par = 0;
2555 need_refinement = 0;
2558 if (
elements[i]->NeedRefinement(v_to_v))
2560 need_refinement = 1;
2564 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2568 if (uniform_refinement)
2575 if (need_refinement == 0)
2577 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2581 const int tag = 293;
2590 if (faces_in_group == 0) {
continue; }
2592 face_splittings[i].
SetSize(0);
2593 for (
int j = 0; j < faces_in_group; j++)
2596 face_splittings[i]);
2600 MPI_Isend(face_splittings[i], face_splittings[i].Size(),
2601 MPI_UNSIGNED, neighbor, tag,
MyComm,
2602 &requests[req_count++]);
2610 if (faces_in_group == 0) {
continue; }
2614 MPI_Probe(neighbor, tag,
MyComm, &status);
2616 MPI_Get_count(&status, MPI_UNSIGNED, &count);
2618 MPI_Recv(iBuf, count, MPI_UNSIGNED, neighbor, tag,
MyComm,
2621 for (
int j = 0, pos = 0; j < faces_in_group; j++)
2628 int nr = need_refinement;
2629 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2631 MPI_Waitall(req_count, requests, MPI_STATUSES_IGNORE);
2634 while (need_refinement == 1);
2636 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2638 int i = ref_loops_all;
2639 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2642 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2643 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2651 delete [] face_splittings;
2656 need_refinement = 0;
2659 if (
boundary[i]->NeedRefinement(v_to_v))
2661 need_refinement = 1;
2666 while (need_refinement == 1);
2671 " (NumOfBdrElements != boundary.Size())");
2698 int uniform_refinement = 0;
2702 uniform_refinement = 1;
2711 int *edge1 =
new int[nedges];
2712 int *edge2 =
new int[nedges];
2713 int *middle =
new int[nedges];
2715 for (
int i = 0; i < nedges; i++)
2717 edge1[i] = edge2[i] = middle[i] = -1;
2722 int *v =
elements[i]->GetVertices();
2723 for (
int j = 0; j < 3; j++)
2725 int ind = v_to_v(v[j], v[(j+1)%3]);
2726 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
2731 for (
int i = 0; i < marked_el.
Size(); i++)
2737 int need_refinement;
2738 int edges_in_group, max_edges_in_group = 0;
2740 int **edge_splittings =
new int*[
GetNGroups()-1];
2744 edge_splittings[i] =
new int[edges_in_group];
2745 if (edges_in_group > max_edges_in_group)
2747 max_edges_in_group = edges_in_group;
2750 int neighbor, *iBuf =
new int[max_edges_in_group];
2754 MPI_Request request;
2759 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2760 int ref_loops_all = 0, ref_loops_par = 0;
2764 need_refinement = 0;
2765 for (
int i = 0; i < nedges; i++)
2767 if (middle[i] != -1 && edge1[i] != -1)
2769 need_refinement = 1;
2773 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2777 if (uniform_refinement)
2784 if (need_refinement == 0)
2786 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2795 edges_in_group = group_edges.
Size();
2797 if (edges_in_group != 0)
2799 for (
int j = 0; j < edges_in_group; j++)
2801 edge_splittings[i][j] =
2814 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
2815 neighbor, 0,
MyComm, &request);
2823 edges_in_group = group_edges.
Size();
2824 if (edges_in_group != 0)
2835 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
2836 MPI_ANY_TAG,
MyComm, &status);
2838 for (
int j = 0; j < edges_in_group; j++)
2840 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
2843 int ii = v_to_v(v[0], v[1]);
2844 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2845 if (middle[ii] != -1)
2847 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
2851 need_refinement = 1;
2853 for (
int c = 0; c < 2; c++)
2863 int nr = need_refinement;
2864 MPI_Allreduce(&nr, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2867 while (need_refinement == 1);
2869 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2871 int i = ref_loops_all;
2872 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2875 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2876 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2884 delete [] edge_splittings[i];
2886 delete [] edge_splittings;
2891 int v1[2], v2[2], bisect, temp;
2893 for (
int i = 0; i < temp; i++)
2895 int *v =
boundary[i]->GetVertices();
2896 bisect = v_to_v(v[0], v[1]);
2897 if (middle[bisect] != -1)
2902 v1[0] = v[0]; v1[1] = middle[bisect];
2903 v2[0] = middle[bisect]; v2[1] = v[1];
2910 mfem_error(
"Only bisection of segment is implemented for bdr"
2943 for (
int j = 0; j < marked_el.
Size(); j++)
2945 int i = marked_el[j];
2948 int new_v = cnv + j, new_e = cne + j;
2957 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
2959 UseExternalData(seg_children, 1, 2, 3);
2980 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
2981 "supported. Project the NURBS to Nodes first.");
2986 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
2987 "(you need to initialize the ParMesh from a nonconforming "
3013 Swap(*pmesh2,
false);
3028 double threshold,
int nc_limit,
int op)
3030 MFEM_VERIFY(
pncmesh,
"Only supported for non-conforming meshes.");
3031 MFEM_VERIFY(!
NURBSext,
"Derefinement of NURBS meshes is not supported. "
3032 "Project the NURBS to Nodes first.");
3045 for (
int i = 0; i < dt.
Size(); i++)
3047 if (nc_limit > 0 && !level_ok[i]) {
continue; }
3052 if (error < threshold) { derefs.
Append(i); }
3056 if (!glob_size) {
return false; }
3066 Swap(*mesh2,
false);
3089 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
3099 *new_nodes = *
Nodes;
3120 Swap(*pmesh2,
false);
3137 MFEM_ASSERT(
Dim == 2 &&
meshgen == 1,
"internal error");
3147 int *I_group_svert, *J_group_svert;
3148 int *I_group_sedge, *J_group_sedge;
3153 I_group_svert[0] = I_group_svert[1] = 0;
3154 I_group_sedge[0] = I_group_sedge[1] = 0;
3161 for (
int group = 0; group <
GetNGroups()-1; group++)
3171 const int ind = middle[v_to_v(v[0], v[1])];
3177 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3184 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3185 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3188 J = J_group_svert+I_group_svert[group];
3189 for (
int i = 0; i < group_verts.
Size(); i++)
3191 J[i] = group_verts[i];
3193 J = J_group_sedge+I_group_sedge[group];
3194 for (
int i = 0; i < group_edges.
Size(); i++)
3196 J[i] = group_edges[i];
3210 MFEM_ASSERT(
Dim == 3 &&
meshgen == 1,
"internal error");
3212 Array<int> group_verts, group_edges, group_trias;
3231 I_group_svert[0] = 0;
3232 I_group_sedge[0] = 0;
3233 I_group_stria[0] = 0;
3235 for (
int group = 0; group <
GetNGroups()-1; group++)
3246 int ind = v_to_v.
FindId(v[0], v[1]);
3247 if (ind == -1) {
continue; }
3250 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3260 ind = v_to_v.
FindId(v[0], ind);
3268 ind = v_to_v.
FindId(v[0], v[1]);
3289 while (sedge_stack.
Size() > 0);
3296 int ind = v_to_v.
FindId(v[0], v[1]);
3297 if (ind == -1) {
continue; }
3300 const int edge_attr = 1;
3309 v[1] = v[0]; v[0] = v[2]; v[2] = ind;
3310 ind = v_to_v.
FindId(v[0], v[1]);
3318 ind = v_to_v.
FindId(v[0], v[1]);
3336 v = sface_stack[sface_stack.
Size()-2].v;
3338 v[0] = v[1]; v[1] = v[2]; v[2] = ind;
3341 while (sface_stack.
Size() > 0);
3347 ind = v_to_v.
FindId(v[0], v[1]);
3368 while (sedge_stack.
Size() > 0);
3371 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3372 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3373 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3375 J_group_svert.
Append(group_verts);
3376 J_group_sedge.
Append(group_edges);
3377 J_group_stria.
Append(group_trias);
3394 int *I_group_svert, *J_group_svert;
3395 int *I_group_sedge, *J_group_sedge;
3400 I_group_svert[0] = 0;
3401 I_group_sedge[0] = 0;
3408 for (
int group = 0; group <
GetNGroups()-1; group++)
3422 const int attr =
shared_edges[sedges[i]]->GetAttribute();
3428 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
3429 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
3431 sverts.
CopyTo(J_group_svert + I_group_svert[group]);
3432 sedges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3448 Array<int> group_verts, group_edges, group_trias, group_quads;
3450 int *I_group_svert, *J_group_svert;
3451 int *I_group_sedge, *J_group_sedge;
3452 int *I_group_stria, *J_group_stria;
3453 int *I_group_squad, *J_group_squad;
3460 I_group_svert[0] = 0;
3461 I_group_sedge[0] = 0;
3462 I_group_stria[0] = 0;
3463 I_group_squad[0] = 0;
3475 const int oface = old_nv + old_nedges;
3477 for (
int group = 0; group <
GetNGroups()-1; group++)
3489 const int ind = old_nv + old_v_to_v(v[0], v[1]);
3493 const int attr =
shared_edges[group_edges[i]]->GetAttribute();
3503 const int stria = group_trias[i];
3506 m[0] = old_nv + old_v_to_v(v[0], v[1]);
3507 m[1] = old_nv + old_v_to_v(v[1], v[2]);
3508 m[2] = old_nv + old_v_to_v(v[2], v[0]);
3509 const int edge_attr = 1;
3524 v[1] = m[0]; v[2] = m[2];
3525 group_trias.
Append(nst+0);
3526 group_trias.
Append(nst+1);
3527 group_trias.
Append(nst+2);
3535 const int squad = group_quads[i];
3537 const int olf = old_faces(v[0], v[1], v[2], v[3]);
3539 m[0] = oface + (f2qf ? (*f2qf)[olf] : olf);
3543 m[1] = old_nv + old_v_to_v(v[0], v[1]);
3544 m[2] = old_nv + old_v_to_v(v[1], v[2]);
3545 m[3] = old_nv + old_v_to_v(v[2], v[3]);
3546 m[4] = old_nv + old_v_to_v(v[3], v[0]);
3547 const int edge_attr = 1;
3564 v[1] = m[1]; v[2] = m[0]; v[3] = m[4];
3565 group_quads.
Append(nsq+0);
3566 group_quads.
Append(nsq+1);
3567 group_quads.
Append(nsq+2);
3571 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3572 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3573 I_group_stria[group+1] = I_group_stria[group] + group_trias.
Size();
3574 I_group_squad[group+1] = I_group_squad[group] + group_quads.
Size();
3576 group_verts.
CopyTo(J_group_svert + I_group_svert[group]);
3577 group_edges.
CopyTo(J_group_sedge + I_group_sedge[group]);
3578 group_trias.
CopyTo(J_group_stria + I_group_stria[group]);
3579 group_quads.
CopyTo(J_group_squad + I_group_squad[group]);
3635 f2qf.
Size() ? &f2qf : NULL);
3645 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
3651 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
3657 out <<
"NETGEN_Neutral_Format\n";
3662 for (j = 0; j <
Dim; j++)
3675 out <<
elements[i]->GetAttribute();
3676 for (j = 0; j < nv; j++)
3678 out <<
" " << ind[j]+1;
3690 out <<
boundary[i]->GetAttribute();
3691 for (j = 0; j < nv; j++)
3693 out <<
" " << ind[j]+1;
3704 for (j = 0; j < 3; j++)
3706 out <<
' ' << ind[j]+1;
3720 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3722 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3723 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3724 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
3730 <<
" " <<
vertices[i](2) <<
" 0.0\n";
3738 out << i+1 <<
" " <<
elements[i]->GetAttribute();
3739 for (j = 0; j < nv; j++)
3741 out <<
" " << ind[j]+1;
3751 out <<
boundary[i]->GetAttribute();
3752 for (j = 0; j < nv; j++)
3754 out <<
" " << ind[j]+1;
3756 out <<
" 1.0 1.0 1.0 1.0\n";
3767 for (j = 0; j < 4; j++)
3769 out <<
' ' << ind[j]+1;
3771 out <<
" 1.0 1.0 1.0 1.0\n";
3780 out <<
"areamesh2\n\n";
3787 attr =
boundary[i]->GetAttribute();
3790 for (j = 0; j < v.
Size(); j++)
3792 out << v[j] + 1 <<
" ";
3802 for (j = 0; j < v.
Size(); j++)
3804 out << v[j] + 1 <<
" ";
3813 attr =
elements[i]->GetAttribute();
3829 for (j = 0; j < v.
Size(); j++)
3831 out << v[j] + 1 <<
" ";
3840 for (j = 0; j <
Dim; j++)
3865 bool print_shared =
true;
3866 int i, j, shared_bdr_attr;
3883 s2l_face = &nc_shared_faces;
3890 for (
unsigned i = 0; i < sfaces.
conforming.size(); i++)
3893 if (index < nfaces) { nc_shared_faces.
Append(index); }
3895 for (
unsigned i = 0; i < sfaces.
masters.size(); i++)
3898 int index = sfaces.
masters[i].index;
3899 if (index < nfaces) { nc_shared_faces.
Append(index); }
3901 for (
unsigned i = 0; i < sfaces.
slaves.size(); i++)
3903 int index = sfaces.
slaves[i].index;
3904 if (index < nfaces) { nc_shared_faces.
Append(index); }
3909 out <<
"MFEM mesh v1.0\n";
3913 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
3918 "# TETRAHEDRON = 4\n"
3923 out <<
"\ndimension\n" <<
Dim
3931 if (print_shared &&
Dim > 1)
3933 num_bdr_elems += s2l_face->
Size();
3935 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
3941 if (print_shared &&
Dim > 1)
3949 shared_bdr_attr =
MyRank + 1;
3951 for (i = 0; i < s2l_face->
Size(); i++)
3954 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
3986 for (
int i = 0; i < nv; i++)
3994 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
4002 out <<
"MFEM mesh v1.0\n";
4006 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
4011 "# TETRAHEDRON = 4\n"
4015 out <<
"\ndimension\n" <<
Dim;
4019 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4022 out <<
"\n\nelements\n" << ne <<
'\n';
4026 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
4030 for (j = 0; j < nv; j++)
4037 for (p = 1; p <
NRanks; p++)
4039 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
4043 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
4045 for (i = 0; i < ne; )
4048 out << p+1 <<
' ' << ints[i];
4051 for (j = 0; j < k; j++)
4053 out <<
' ' << vc + ints[i++];
4066 ne += 1 +
elements[i]->GetNVertices();
4069 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
4077 MFEM_ASSERT(ints.
Size() == ne,
"");
4080 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
4105 dump_element(
boundary[i], ints); ne++;
4134 MFEM_ABORT(
"invalid dimension: " <<
Dim);
4141 for (i = 0; i < (int) list.
conforming.size(); i++)
4144 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4146 for (i = 0; i < (int) list.
masters.size(); i++)
4148 int index = list.
masters[i].index;
4149 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4151 for (i = 0; i < (int) list.
slaves.size(); i++)
4153 int index = list.
slaves[i].index;
4154 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
4158 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4161 out <<
"\nboundary\n" << k <<
'\n';
4163 for (p = 0; p <
NRanks; p++)
4167 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
4171 MPI_Recv(ints.
GetData(), ne, MPI_INT, p, 447,
MyComm, &status);
4179 for (i = 0; i < ne; )
4182 out << p+1 <<
' ' << ints[i];
4185 for (j = 0; j < k; j++)
4187 out <<
' ' << vc + ints[i++];
4198 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
4209 out <<
"\nvertices\n" << nv <<
'\n';
4225 for (p = 1; p <
NRanks; p++)
4227 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
4231 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
4233 for (i = 0; i < nv; i++)
4238 out <<
' ' << vert[i*spaceDim+j];
4253 vert[i*spaceDim+j] =
vertices[i](j);
4258 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
4285 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
4293 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
4296 int i, j, k, nv, ne, p;
4304 out <<
"NETGEN_Neutral_Format\n";
4307 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4311 for (j = 0; j <
Dim; j++)
4317 for (p = 1; p <
NRanks; p++)
4319 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4321 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4322 for (i = 0; i < nv; i++)
4324 for (j = 0; j <
Dim; j++)
4326 out <<
" " << vert[Dim*i+j];
4334 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4341 for (j = 0; j < nv; j++)
4343 out <<
" " << ind[j]+1;
4348 for (p = 1; p <
NRanks; p++)
4350 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4351 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4353 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4354 for (i = 0; i < ne; i++)
4357 for (j = 0; j < 4; j++)
4359 out <<
" " << k+ints[i*4+j]+1;
4367 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4375 for (j = 0; j < nv; j++)
4377 out <<
" " << ind[j]+1;
4388 for (j = 0; j < 3; j++)
4390 out <<
' ' << ind[j]+1;
4396 for (p = 1; p <
NRanks; p++)
4398 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4399 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4401 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4402 for (i = 0; i < ne; i++)
4405 for (j = 0; j < 3; j++)
4407 out <<
' ' << k+ints[i*3+j]+1;
4417 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4421 for (j = 0; j <
Dim; j++)
4425 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4429 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4430 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4436 for (j = 0; j < 4; j++)
4441 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
4444 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4445 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4447 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4452 for (j = 0; j < 3; j++)
4457 for ( ; i < ne; i++)
4460 for (j = 0; j < 3; j++)
4465 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
4471 int i, j, k, nv, ne, p;
4477 int TG_nv, TG_ne, TG_nbe;
4484 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4487 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
4488 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
4489 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
4490 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4491 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4498 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4500 for (p = 1; p <
NRanks; p++)
4502 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4504 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4505 for (i = 0; i < nv; i++)
4507 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
4508 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
4518 out << i+1 <<
" " << 1;
4519 for (j = 0; j < nv; j++)
4521 out <<
" " << ind[j]+1;
4526 for (p = 1; p <
NRanks; p++)
4528 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4529 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4531 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
4532 for (i = 0; i < ne; i++)
4534 out << i+1 <<
" " << p+1;
4535 for (j = 0; j < 8; j++)
4537 out <<
" " << k+ints[i*8+j]+1;
4552 for (j = 0; j < nv; j++)
4554 out <<
" " << ind[j]+1;
4556 out <<
" 1.0 1.0 1.0 1.0\n";
4566 for (j = 0; j < 4; j++)
4568 out <<
' ' << ind[j]+1;
4570 out <<
" 1.0 1.0 1.0 1.0\n";
4573 for (p = 1; p <
NRanks; p++)
4575 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4576 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4578 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4579 for (i = 0; i < ne; i++)
4582 for (j = 0; j < 4; j++)
4584 out <<
" " << k+ints[i*4+j]+1;
4586 out <<
" 1.0 1.0 1.0 1.0\n";
4596 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4601 for (j = 0; j <
Dim; j++)
4605 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
4607 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4613 for (j = 0; j < 8; j++)
4618 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
4620 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4622 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4627 for (j = 0; j < 4; j++)
4632 for ( ; i < ne; i++)
4635 for (j = 0; j < 4; j++)
4640 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
4646 int i, j, k, attr, nv, ne, p;
4654 out <<
"areamesh2\n\n";
4658 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4663 attr =
boundary[i]->GetAttribute();
4666 for (j = 0; j < v.
Size(); j++)
4668 out << v[j] + 1 <<
" ";
4678 for (j = 0; j < v.
Size(); j++)
4680 out << v[j] + 1 <<
" ";
4685 for (p = 1; p <
NRanks; p++)
4687 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4688 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4690 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
4691 for (i = 0; i < ne; i++)
4694 for (j = 0; j < 2; j++)
4696 out <<
" " << k+ints[i*2+j]+1;
4705 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4711 out << 1 <<
" " << 3 <<
" ";
4712 for (j = 0; j < v.
Size(); j++)
4714 out << v[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++)
4727 out << p+1 <<
" " << 3;
4728 for (j = 0; j < 3; j++)
4730 out <<
" " << k+ints[i*3+j]+1;
4739 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4743 for (j = 0; j <
Dim; j++)
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 for (j = 0; j <
Dim; j++)
4758 out <<
" " << vert[Dim*i+j];
4768 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4771 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4776 for (j = 0; j < 2; j++)
4781 for ( ; i < ne; i++)
4784 for (j = 0; j < 2; j++)
4789 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
4792 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4799 for (j = 0; j < 3; j++)
4804 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
4807 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4811 for (j = 0; j <
Dim; j++)
4815 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4833 MPI_Allreduce(p_min.
GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN,
MyComm);
4834 MPI_Allreduce(p_max.
GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX,
MyComm);
4838 double &gk_min,
double &gk_max)
4840 double h_min, h_max, kappa_min, kappa_max;
4844 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
4845 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
4846 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
4847 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
4854 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
4858 out <<
"Parallel Mesh Stats:" <<
'\n';
4864 h = pow(fabs(J.
Weight()), 1.0/
double(
Dim));
4870 kappa_min = kappa_max =
kappa;
4874 if (h < h_min) { h_min = h; }
4875 if (h > h_max) { h_max = h; }
4876 if (kappa < kappa_min) { kappa_min =
kappa; }
4877 if (kappa > kappa_max) { kappa_max =
kappa; }
4881 double gh_min, gh_max, gk_min, gk_max;
4882 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
4883 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
4884 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
4885 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
4890 long mindata[5], maxdata[5], sumdata[5];
4909 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
4910 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
4911 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
4917 << setw(12) <<
"minimum"
4918 << setw(12) <<
"average"
4919 << setw(12) <<
"maximum"
4920 << setw(12) <<
"total" <<
'\n';
4922 << setw(12) << mindata[0]
4923 << setw(12) << sumdata[0]/
NRanks
4924 << setw(12) << maxdata[0]
4925 << setw(12) << sumdata[0] <<
'\n';
4927 << setw(12) << mindata[1]
4928 << setw(12) << sumdata[1]/
NRanks
4929 << setw(12) << maxdata[1]
4930 << setw(12) << sumdata[1] <<
'\n';
4934 << setw(12) << mindata[2]
4935 << setw(12) << sumdata[2]/
NRanks
4936 << setw(12) << maxdata[2]
4937 << setw(12) << sumdata[2] <<
'\n';
4940 << setw(12) << mindata[3]
4941 << setw(12) << sumdata[3]/
NRanks
4942 << setw(12) << maxdata[3]
4943 << setw(12) << sumdata[3] <<
'\n';
4944 out <<
" neighbors "
4945 << setw(12) << mindata[4]
4946 << setw(12) << sumdata[4]/
NRanks
4947 << setw(12) << maxdata[4] <<
'\n';
4950 << setw(12) <<
"minimum"
4951 << setw(12) <<
"maximum" <<
'\n';
4953 << setw(12) << gh_min
4954 << setw(12) << gh_max <<
'\n';
4956 << setw(12) << gk_min
4957 << setw(12) << gk_max <<
'\n';
4964 long local = value, global;
4965 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
4981 Printer(out,
"mfem_serial_mesh_end");
4989 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5000 out <<
"\n# group " << gr <<
"\nshared_vertices " << nv <<
'\n';
5001 for (
int i = 0; i < nv; i++)
5010 out <<
"\nshared_edges " << ne <<
'\n';
5011 for (
int i = 0; i < ne; i++)
5014 out << v[0] <<
' ' << v[1] <<
'\n';
5023 out <<
"\nshared_faces " << nt+nq <<
'\n';
5024 for (
int i = 0; i < nt; i++)
5028 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5031 for (
int i = 0; i < nq; i++)
5035 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5042 out <<
"\nmfem_mesh_end" << endl;
5049 const int npts = point_mat.
Width();
5050 if (npts == 0) {
return 0; }
5052 const bool no_warn =
false;
5059 Array<int> my_point_rank(npts), glob_point_rank(npts);
5060 for (
int k = 0; k < npts; k++)
5062 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
5065 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
5066 MPI_INT, MPI_MIN,
MyComm);
5069 for (
int k = 0; k < npts; k++)
5071 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
5075 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
5078 if (warn && pts_found != npts &&
MyRank == 0)
5080 MFEM_WARNING((npts-pts_found) <<
" points were not found");
5085 static void PrintVertex(
const Vertex &v,
int space_dim, ostream &
out)
5088 for (
int d = 1; d < space_dim; d++)
5096 stringstream out_name;
5097 out_name << fname_prefix <<
'_' << setw(5) << setfill(
'0') <<
MyRank
5098 <<
".shared_entities";
5099 ofstream
out(out_name.str().c_str());
5107 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
5118 out <<
"\n# group " << gr <<
"\n\nshared_vertices " << nv <<
'\n';
5119 for (
int i = 0; i < nv; i++)
5131 out <<
"\nshared_edges " << ne <<
'\n';
5132 for (
int i = 0; i < ne; i++)
5148 out <<
"\nshared_faces " << nt+nq <<
'\n';
5149 for (
int i = 0; i < nt; i++)
5154 for (
int j = 0; j < 3; j++) { out <<
' ' << v[j]; }
5157 for (
int j = 0; j < 3; j++)
5160 (j < 2) ? out <<
" | " : out <<
'\n';
5163 for (
int i = 0; i < nq; i++)
5168 for (
int j = 0; j < 4; j++) { out <<
' ' << v[j]; }
5171 for (
int j = 0; j < 4; j++)
5174 (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 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.
Class for grid function - Vector with associated FE space.
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()
virtual void Update(bool want_transform=true)
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.
void UniformRefinement3D_base(Array< int > *f2qf=NULL, DSTable *v_to_v_p=NULL)
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 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.
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 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 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
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
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)
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 Rebalance()
Load balance the mesh. NC meshes only.
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
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.
static void Rotate3(int &, int &, int &)
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
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()
virtual void ReorientTetMesh()
Array< Vert4 > shared_quads
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)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
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.
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
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
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 UniformRefinement2D()
Refine a mixed 2D mesh uniformly.
virtual void UniformRefinement3D()
Refine a mixed 3D mesh uniformly.
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.
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)
void Printer(std::ostream &out=mfem::out, std::string section_delimiter="") const
ParFiniteElementSpace * ParFESpace() const
virtual void NURBSUniformRefinement()
Refine NURBS mesh.