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"
29 ParMesh::ParMesh(
const ParMesh &pmesh,
bool copy_nodes)
31 group_svert(pmesh.group_svert),
32 group_sedge(pmesh.group_sedge),
33 group_sface(pmesh.group_sface),
62 MFEM_VERIFY(pmesh.
pncmesh == NULL,
63 "copying non-conforming meshes is not implemented");
68 if (pmesh.
Nodes && copy_nodes)
78 Nodes->MakeOwner(fec_copy);
79 *Nodes = *pmesh.
Nodes;
101 int* partition =
new int[mesh.
GetNE()];
102 for (
int i = 0; i < mesh.
GetNE(); i++)
141 partitioning = partitioning_;
153 int vert_counter, element_counter, bdrelem_counter;
156 vert_global_local = -1;
160 for (i = 0; i < mesh.
GetNE(); i++)
161 if (partitioning[i] ==
MyRank)
165 for (j = 0; j < vert.
Size(); j++)
166 if (vert_global_local[vert[j]] < 0)
168 vert_global_local[vert[j]] = vert_counter++;
177 for (i = vert_counter = 0; i < vert_global_local.
Size(); i++)
178 if (vert_global_local[i] >= 0)
180 vert_global_local[i] = vert_counter++;
184 for (i = 0; i < vert_global_local.Size(); i++)
185 if (vert_global_local[i] >= 0)
194 for (i = 0; i < mesh.
GetNE(); i++)
195 if (partitioning[i] ==
MyRank)
198 int *v =
elements[element_counter]->GetVertices();
199 int nv =
elements[element_counter]->GetNVertices();
200 for (j = 0; j < nv; j++)
202 v[j] = vert_global_local[v[j]];
207 Table *edge_element = NULL;
211 activeBdrElem =
false;
217 for (i = 0; i < mesh.
GetNBE(); i++)
219 int face, o, el1, el2;
222 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
227 activeBdrElem[i] =
true;
234 for (i = 0; i < mesh.
GetNBE(); i++)
236 int face, o, el1, el2;
239 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
242 int *v =
boundary[bdrelem_counter]->GetVertices();
243 int nv =
boundary[bdrelem_counter]->GetNVertices();
244 for (j = 0; j < nv; j++)
246 v[j] = vert_global_local[v[j]];
254 edge_element =
new Table;
258 for (i = 0; i < mesh.
GetNBE(); i++)
261 int el1 = edge_element->
GetRow(edge)[0];
262 if (partitioning[el1] ==
MyRank)
267 activeBdrElem[i] =
true;
274 for (i = 0; i < mesh.
GetNBE(); i++)
277 int el1 = edge_element->
GetRow(edge)[0];
278 if (partitioning[el1] ==
MyRank)
281 int *v =
boundary[bdrelem_counter]->GetVertices();
282 int nv =
boundary[bdrelem_counter]->GetNVertices();
283 for (j = 0; j < nv; j++)
285 v[j] = vert_global_local[v[j]];
294 for (i = 0; i < mesh.
GetNBE(); i++)
296 int vert = mesh.
boundary[i]->GetVertices()[0];
299 if (partitioning[el1] ==
MyRank)
307 for (i = 0; i < mesh.
GetNBE(); i++)
309 int vert = mesh.
boundary[i]->GetVertices()[0];
312 if (partitioning[el1] ==
MyRank)
315 int *v =
boundary[bdrelem_counter]->GetVertices();
316 v[0] = vert_global_local[v[0]];
362 "(Dim < 3 && mesh.GetNFaces() != 0) is true!" << endl;
367 int sface_counter = 0;
369 for (i = 0; i < face_group.Size(); i++)
376 el[0] = partitioning[el[0]];
377 el[1] = partitioning[el[1]];
382 face_group[i] = groups.
Insert(group) - 1;
389 int sedge_counter = 0;
392 edge_element =
new Table;
402 for (i = 0; i < edge_element->
Size(); i++)
404 int me = 0, others = 0;
405 for (j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
407 edge_element->
GetJ()[j] = partitioning[edge_element->
GetJ()[j]];
426 edge_element->
GetRow(i)[0] = -1;
431 int svert_counter = 0;
434 for (i = 0; i < vert_element->
Size(); i++)
436 int me = 0, others = 0;
437 for (j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
439 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
454 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
458 vert_element->
GetI()[i] = -1;
465 for (i = 0; i < face_group.Size(); i++)
467 if (face_group[i] >= 0)
476 for (i = 0; i < face_group.Size(); i++)
478 if (face_group[i] >= 0)
489 for (i = 0; i < edge_element->
Size(); i++)
491 if (edge_element->
GetRow(i)[0] >= 0)
500 for (i = 0; i < edge_element->
Size(); i++)
502 if (edge_element->
GetRow(i)[0] >= 0)
513 for (i = 0; i < vert_element->
Size(); i++)
515 if (vert_element->
GetI()[i] >= 0)
524 for (i = 0; i < vert_element->
Size(); i++)
526 if (vert_element->
GetI()[i] >= 0)
541 for (i = 0; i < face_group.Size(); i++)
543 if (face_group[i] >= 0)
548 for (j = 0; j < nv; j++)
550 v[j] = vert_global_local[v[j]];
555 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
569 if (
MyRank == partitioning[gl_el2])
571 std::swap(v[0], v[1]);
578 (*faces_tbl)(v[0], v[1], v[2], v[3]);
597 for (i = 0; i < edge_element->
Size(); i++)
599 if (edge_element->
GetRow(i)[0] >= 0)
604 new Segment(vert_global_local[vert[0]],
605 vert_global_local[vert[1]], 1);
608 v_to_v(vert_global_local[vert[0]],
609 vert_global_local[vert[1]])) < 0)
612 <<
"ERROR in v_to_v\n\n" << endl;
627 for (i = 0; i < vert_element->
Size(); i++)
629 if (vert_element->
GetI()[i] >= 0)
631 svert_lvert[svert_counter++] = vert_global_local[i];
654 for (i = 0; i < mesh.
GetNE(); i++)
655 if (partitioning[i] ==
MyRank)
658 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
659 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
665 if (partitioning_ == NULL)
667 delete [] partitioning;
675 : MyComm(pncmesh.MyComm)
676 , NRanks(pncmesh.NRanks)
677 , MyRank(pncmesh.MyRank)
703 Loader(input, gen_edges,
"mfem_serial_mesh_end");
709 MFEM_VERIFY(ident ==
"communication_groups",
710 "input stream is not a parallel MFEM mesh");
720 input >> ident >> num_sverts;
729 input >> ident >> num_sedges;
745 input >> ident >> num_sfaces;
760 int svert_counter = 0, sedge_counter = 0, sface_counter = 0;
767 mfem::err <<
"ParMesh::ParMesh : expecting group " << gr
768 <<
", read group " << g << endl;
774 input >> ident >> nv;
777 "incorrect number of total_shared_vertices");
779 for ( ; svert_counter < nv; svert_counter++)
788 input >> ident >> ne;
791 "incorrect number of total_shared_edges");
793 for ( ; sedge_counter < ne; sedge_counter++)
796 input >> v[0] >> v[1];
798 sedge_ledge[sedge_counter] = (*v_to_v)(v[0], v[1]);
804 input >> ident >> nf;
807 "incorrect number of total_shared_faces");
809 for ( ; sface_counter < nf; sface_counter++)
818 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
822 (*faces_tbl)(v[0], v[1], v[2], v[3]);
831 const bool refine =
true;
832 const bool fix_orientation =
false;
843 :
Mesh(orig_mesh, ref_factor, ref_type),
844 MyComm(orig_mesh->GetComm()),
845 NRanks(orig_mesh->GetNRanks()),
846 MyRank(orig_mesh->GetMyRank()),
847 gtopo(orig_mesh->gtopo),
848 have_face_nbr_data(false),
874 for (
int fi = 0; fi < orig_nf; fi++)
876 const int orig_l_face = orig_mesh->
sface_lface[orig_sf[fi]];
907 for (
int j = 0; j < orig_n_verts; j++)
914 const int orig_n_edges = orig_mesh->
GroupNEdges(gr);
918 for (
int e = 0; e < orig_n_edges; e++)
923 for (
int j = 2; j < rdofs.
Size(); j++)
927 const int *c2h_map = rfec.
GetDofMap(geom);
932 for (
int k = 0; k < nvert; k++)
935 v[k] = rdofs[c2h_map[cid]];
944 for (
int f = 0; f < orig_nf; f++)
946 const int orig_l_face = orig_mesh->
sface_lface[orig_sf[f]];
956 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
960 const int *c2h_map = rfec.
GetDofMap(geom);
966 for (
int k = 0; k < 2; k++)
968 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
977 for (
int k = 0; k < nvert; k++)
980 v[k] = rdofs[c2h_map[cid]];
998 const int l_edge = v_to_v(v[0], v[1]);
999 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
1015 l_face = (*faces_tbl)(v[0], v[1], v[2]);
1018 l_face = (*faces_tbl)(v[0], v[1], v[2], v[3]);
1021 MFEM_ABORT(
"invalid face geometry");
1024 MFEM_ASSERT(l_face >= 0,
"invalid shared face");
1036 o = (v[0] < v[1]) ? (+1) : (-1);
1067 gr_sedge.
GetI()[0] = 0;
1086 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1088 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1091 if (n == 0) {
continue; }
1092 sedge_ord_map.SetSize(n);
1093 for (
int j = 0; j < n; j++)
1095 sedge_ord_map[j].one = sedge_ord[k+j];
1096 sedge_ord_map[j].two = j;
1098 SortPairs<int, int>(sedge_ord_map, n);
1099 for (
int j = 0; j < n; j++)
1104 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1105 for (
int j = 0; j < n; j++)
1122 ilen_len[j].one = order[j];
1123 ilen_len[j].two =
GetLength(i, it.Column());
1127 SortPairs<int, double>(ilen_len, order.
Size());
1130 for (
int i = 1; i < order.
Size(); i++)
1132 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1142 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1145 mfem::out <<
"glob_d_max = " << glob_d_max << endl;
1157 elements[i]->MarkEdge(v_to_v, order);
1165 boundary[i]->MarkEdge(v_to_v, order);
1187 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1208 int number_of_splittings = 0;
1211 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1213 number_of_splittings++;
1214 if ((m = v_to_v(v[1], v[2])) != -1 && middle[m] != -1)
1217 number_of_splittings++;
1219 if ((m = v_to_v(v[2], v[0])) != -1 && middle[m] != -1)
1221 number_of_splittings++;
1224 switch (number_of_splittings)
1229 number_of_splittings++;
1233 number_of_splittings++;
1238 return number_of_splittings;
1244 if (HYPRE_AssumedPartitionCheck())
1247 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_INT, MPI_SUM,
MyComm);
1248 for (
int i = 0; i < N; i++)
1251 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1252 (*offsets[i])[1] = temp[i];
1255 for (
int i = 0; i < N; i++)
1257 (*offsets[i])[2] = temp[i];
1259 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1260 "overflow in offsets");
1266 MPI_Allgather(loc_sizes, N, HYPRE_MPI_INT, temp.
GetData(), N,
1268 for (
int i = 0; i < N; i++)
1273 for (
int j = 0; j <
NRanks; j++)
1275 offs[j+1] = offs[j] + temp[i+N*j];
1279 "overflow in offsets");
1301 for (
int j = 0; j < nv; j++)
1320 for (
int j = 0; j < n; j++)
1322 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
1330 MFEM_ABORT(
"Nodes are not ParGridFunction!");
1392 int num_face_nbrs = 0;
1394 if (gr_sface->
RowSize(g-1) > 0)
1401 if (num_face_nbrs == 0)
1411 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
1412 if (gr_sface->
RowSize(g-1) > 0)
1416 mfem_error(
"ParMesh::ExchangeFaceNbrData() : "
1417 "group size is not 2!");
1420 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
1422 rank_group[counter].two = g;
1426 SortPairs<int, int>(rank_group, rank_group.
Size());
1428 for (
int fn = 0; fn < num_face_nbrs; fn++)
1434 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1435 MPI_Request *send_requests = requests;
1436 MPI_Request *recv_requests = requests + num_face_nbrs;
1437 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1439 int *nbr_data =
new int[6*num_face_nbrs];
1440 int *nbr_send_data = nbr_data;
1441 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
1448 Table send_face_nbr_elemdata, send_face_nbr_facedata;
1452 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
1453 send_face_nbr_facedata.
MakeI(num_face_nbrs);
1454 for (
int fn = 0; fn < num_face_nbrs; fn++)
1457 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1458 int *sface = gr_sface->
GetRow(nbr_group-1);
1459 for (
int i = 0; i < num_sfaces; i++)
1461 int lface = s2l_face[sface[i]];
1463 if (el_marker[el] != fn)
1468 const int nv =
elements[el]->GetNVertices();
1469 const int *v =
elements[el]->GetVertices();
1470 for (
int j = 0; j < nv; j++)
1471 if (vertex_marker[v[j]] != fn)
1473 vertex_marker[v[j]] = fn;
1484 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
1489 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1490 &send_requests[fn]);
1491 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1492 &recv_requests[fn]);
1496 send_face_nbr_elemdata.
MakeJ();
1497 send_face_nbr_facedata.
MakeJ();
1500 for (
int fn = 0; fn < num_face_nbrs; fn++)
1503 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1504 int *sface = gr_sface->
GetRow(nbr_group-1);
1505 for (
int i = 0; i < num_sfaces; i++)
1507 int lface = s2l_face[sface[i]];
1509 if (el_marker[el] != fn)
1514 const int nv =
elements[el]->GetNVertices();
1515 const int *v =
elements[el]->GetVertices();
1516 for (
int j = 0; j < nv; j++)
1517 if (vertex_marker[v[j]] != fn)
1519 vertex_marker[v[j]] = fn;
1535 const int *sf_v =
shared_faces[sface[i]]->GetVertices();
1556 for (
int fn = 0; fn < num_face_nbrs; fn++)
1562 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
1563 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
1564 int *facedata = send_face_nbr_facedata.
GetRow(fn);
1566 for (
int i = 0; i < num_verts; i++)
1568 vertex_marker[verts[i]] = i;
1571 for (
int el = 0; el < num_elems; el++)
1573 const int nv =
elements[el]->GetNVertices();
1575 for (
int j = 0; j < nv; j++)
1577 elemdata[j] = vertex_marker[elemdata[j]];
1581 el_marker[elems[el]] = el;
1584 for (
int i = 0; i < num_sfaces; i++)
1586 facedata[2*i] = el_marker[facedata[2*i]];
1590 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1593 Table recv_face_nbr_elemdata;
1598 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
1601 for (
int fn = 0; fn < num_face_nbrs; fn++)
1609 recv_face_nbr_elemdata.
MakeJ();
1611 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1614 for (
int fn = 0; fn < num_face_nbrs; fn++)
1619 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
1620 send_face_nbr_elemdata.
RowSize(fn),
1621 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1623 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
1624 recv_face_nbr_elemdata.
RowSize(fn),
1625 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1633 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1635 if (fn == MPI_UNDEFINED)
1643 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
1645 for (
int i = 0; i < num_elems; i++)
1651 for (
int j = 0; j < nv; j++)
1653 recv_elemdata[j] += vert_off;
1656 recv_elemdata += nv;
1661 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1664 recv_face_nbr_facedata.
SetSize(
1666 for (
int fn = 0; fn < num_face_nbrs; fn++)
1671 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
1672 send_face_nbr_facedata.
RowSize(fn),
1673 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1676 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
1677 send_face_nbr_facedata.
RowSize(fn),
1678 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1685 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1687 if (fn == MPI_UNDEFINED)
1694 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1695 int *sface = gr_sface->
GetRow(nbr_group-1);
1697 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
1699 for (
int i = 0; i < num_sfaces; i++)
1701 int lface = s2l_face[sface[i]];
1703 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
1704 int info = facedata[2*i+1];
1712 int nbr_ori = info%64, nbr_v[4];
1714 const int *sf_v =
shared_faces[sface[i]]->GetVertices();
1720 for (
int j = 0; j < 3; j++)
1722 nbr_v[perm[j]] = sf_v[j];
1731 for (
int j = 0; j < 4; j++)
1733 nbr_v[perm[j]] = sf_v[j];
1739 info = 64*(info/64) + nbr_ori;
1745 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1766 else if (
Nodes == NULL)
1776 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1777 MPI_Request *send_requests = requests;
1778 MPI_Request *recv_requests = requests + num_face_nbrs;
1779 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1783 for (
int i = 0; i < send_vertices.Size(); i++)
1789 for (
int fn = 0; fn < num_face_nbrs; fn++)
1796 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
1801 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
1804 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1805 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1813 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
1824 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
1866 for (
int i = 0; i < s2l_face->
Size(); i++)
1881 for (
int i = 0; i < s2l_face->
Size(); i++)
1883 int lface = (*s2l_face)[i];
1884 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
1908 #if 0 // TODO: handle the case of non-interpolatory Nodes
1936 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
1985 if (is_ghost || fill2)
1994 std::swap(pm(0,0), pm(0,1));
1995 std::swap(pm(1,0), pm(1,1));
2022 MFEM_ASSERT(
Dim > 1,
"");
2041 MFEM_ASSERT(
Dim > 1,
"");
2044 return sface < csize
2046 : shared.
slaves[sface - csize].index;
2100 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
2109 int uniform_refinement = 0;
2113 uniform_refinement = 1;
2128 for (i = 0; i < marked_el.
Size(); i++)
2130 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2134 for (i = 0; i < marked_el.
Size(); i++)
2136 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2139 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2143 for (i = 0; i < marked_el.
Size(); i++)
2145 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2148 Bisection(j, v_to_v, NULL, NULL, middle);
2150 Bisection(j, v_to_v, NULL, NULL, middle);
2152 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2154 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2160 int need_refinement;
2161 int refined_edge[5][3] =
2169 int faces_in_group, max_faces_in_group = 0;
2171 int **face_splittings =
new int*[
GetNGroups()-1];
2175 face_splittings[i] =
new int[faces_in_group];
2176 if (faces_in_group > max_faces_in_group)
2178 max_faces_in_group = faces_in_group;
2181 int neighbor, *iBuf =
new int[max_faces_in_group];
2185 MPI_Request request;
2188 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2189 int ref_loops_all = 0, ref_loops_par = 0;
2193 need_refinement = 0;
2196 if (
elements[i]->NeedRefinement(v_to_v, middle))
2198 need_refinement = 1;
2199 Bisection(i, v_to_v, NULL, NULL, middle);
2202 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2206 if (uniform_refinement)
2213 if (need_refinement == 0)
2215 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2219 const int tag = 293;
2225 faces_in_group = group_faces.
Size();
2227 if (faces_in_group == 0) {
continue; }
2229 for (j = 0; j < faces_in_group; j++)
2231 face_splittings[i][j] =
2237 MPI_Isend(face_splittings[i], faces_in_group, MPI_INT,
2238 neighbor, tag,
MyComm, &request);
2245 faces_in_group = group_faces.
Size();
2246 if (faces_in_group == 0) {
continue; }
2250 MPI_Recv(iBuf, faces_in_group, MPI_INT, neighbor,
2253 for (j = 0; j < faces_in_group; j++)
2255 if (iBuf[j] == face_splittings[i][j]) {
continue; }
2258 for (
int k = 0; k < 3; k++)
2260 if (refined_edge[iBuf[j]][k] != 1 ||
2261 refined_edge[face_splittings[i][j]][k] != 0)
2264 int ind[2] = { v[k], v[(k+1)%3] };
2265 int ii = v_to_v(ind[0], ind[1]);
2266 if (middle[ii] == -1)
2268 need_refinement = 1;
2277 i = need_refinement;
2278 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2281 while (need_refinement == 1);
2283 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2285 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2288 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2289 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2297 delete [] face_splittings[i];
2299 delete [] face_splittings;
2305 need_refinement = 0;
2308 if (
boundary[i]->NeedRefinement(v_to_v, middle))
2310 need_refinement = 1;
2315 while (need_refinement == 1);
2319 " (NumOfBdrElements != boundary.Size())");
2330 int refinement_edges[2], type, flag;
2355 int uniform_refinement = 0;
2359 uniform_refinement = 1;
2368 int *edge1 =
new int[nedges];
2369 int *edge2 =
new int[nedges];
2370 int *middle =
new int[nedges];
2372 for (i = 0; i < nedges; i++)
2374 edge1[i] = edge2[i] = middle[i] = -1;
2379 int *v =
elements[i]->GetVertices();
2380 for (j = 0; j < 3; j++)
2382 int ind = v_to_v(v[j], v[(j+1)%3]);
2383 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
2388 for (i = 0; i < marked_el.
Size(); i++)
2394 int need_refinement;
2395 int edges_in_group, max_edges_in_group = 0;
2397 int **edge_splittings =
new int*[
GetNGroups()-1];
2401 edge_splittings[i] =
new int[edges_in_group];
2402 if (edges_in_group > max_edges_in_group)
2404 max_edges_in_group = edges_in_group;
2407 int neighbor, *iBuf =
new int[max_edges_in_group];
2411 MPI_Request request;
2416 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2417 int ref_loops_all = 0, ref_loops_par = 0;
2421 need_refinement = 0;
2422 for (i = 0; i < nedges; i++)
2423 if (middle[i] != -1 && edge1[i] != -1)
2425 need_refinement = 1;
2428 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2432 if (uniform_refinement)
2439 if (need_refinement == 0)
2441 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2450 edges_in_group = group_edges.
Size();
2452 if (edges_in_group != 0)
2454 for (j = 0; j < edges_in_group; j++)
2455 edge_splittings[i][j] =
2467 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
2468 neighbor, 0,
MyComm, &request);
2476 edges_in_group = group_edges.
Size();
2477 if (edges_in_group != 0)
2488 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
2489 MPI_ANY_TAG,
MyComm, &status);
2491 for (j = 0; j < edges_in_group; j++)
2492 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
2495 int ii = v_to_v(v[0], v[1]);
2496 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2497 if (middle[ii] != -1)
2498 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
2501 need_refinement = 1;
2503 for (
int c = 0; c < 2; c++)
2512 i = need_refinement;
2513 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2516 while (need_refinement == 1);
2518 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2520 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2523 mfem::out <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2524 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2531 delete [] edge_splittings[i];
2533 delete [] edge_splittings;
2538 int v1[2], v2[2], bisect, temp;
2540 for (i = 0; i < temp; i++)
2542 int *v =
boundary[i]->GetVertices();
2543 bisect = v_to_v(v[0], v[1]);
2544 if (middle[bisect] != -1)
2549 v1[0] = v[0]; v1[1] = middle[bisect];
2550 v2[0] = middle[bisect]; v2[1] = v[1];
2556 mfem_error(
"Only bisection of segment is implemented for bdr"
2586 for (j = 0; j < marked_el.
Size(); j++)
2591 int new_v = cnv + j, new_e = cne + j;
2600 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
2622 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
2623 "supported. Project the NURBS to Nodes first.");
2628 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
2629 "(you need to initialize the ParMesh from a nonconforming "
2653 Swap(*pmesh2,
false);
2670 double threshold,
int nc_limit,
int op)
2683 for (
int i = 0; i < dt.
Size(); i++)
2685 if (nc_limit > 0 && !level_ok[i]) {
continue; }
2687 const int* fine = dt.
GetRow(i);
2691 for (
int j = 0; j < size; j++)
2693 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
2695 double err_fine = elem_error[fine[j]];
2698 case 0: error = std::min(error, err_fine);
break;
2699 case 1: error += err_fine;
break;
2700 case 2: error = std::max(error, err_fine);
break;
2704 if (error < threshold) { derefs.
Append(i); }
2721 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
2735 Swap(*pmesh2,
false);
2752 int i, attr, newv[3], ind, f_ind, *v;
2755 Array<int> group_verts, group_edges, group_faces;
2763 int *I_group_svert, *J_group_svert;
2764 int *I_group_sedge, *J_group_sedge;
2765 int *I_group_sface, *J_group_sface;
2775 I_group_sface = NULL;
2778 I_group_svert[0] = I_group_svert[1] = 0;
2779 I_group_sedge[0] = I_group_sedge[1] = 0;
2782 I_group_sface[0] = I_group_sface[1] = 0;
2799 J_group_sface = NULL;
2803 J_group_svert = J_group_sedge = J_group_sface = NULL;
2806 for (group = 0; group <
GetNGroups()-1; group++)
2817 ind = middle[v_to_v(v[0], v[1])];
2834 ind = middle[v_to_v(v[0], v[1])];
2842 f_ind = group_faces.
Size();
2845 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2850 ind = middle[v_to_v(v[0], v[1])];
2859 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2865 ind = middle[v_to_v(v[0], v[1])];
2874 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2880 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
2881 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
2884 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
2888 J = J_group_svert+I_group_svert[group];
2889 for (i = 0; i < group_verts.
Size(); i++)
2891 J[i] = group_verts[i];
2893 J = J_group_sedge+I_group_sedge[group];
2894 for (i = 0; i < group_edges.
Size(); i++)
2896 J[i] = group_edges[i];
2900 J = J_group_sface+I_group_sface[group];
2901 for (i = 0; i < group_faces.
Size(); i++)
2903 J[i] = group_faces[i];
2953 int i, attr, ind, *v;
2958 int *I_group_svert, *J_group_svert;
2959 int *I_group_sedge, *J_group_sedge;
2964 I_group_svert[0] = I_group_svert[1] = 0;
2965 I_group_sedge[0] = I_group_sedge[1] = 0;
2972 for (group = 0; group <
GetNGroups()-1; group++)
2992 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
2993 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
2996 J = J_group_svert+I_group_svert[group];
2997 for (i = 0; i < sverts.
Size(); i++)
3001 J = J_group_sedge+I_group_sedge[group];
3002 for (i = 0; i < sedges.
Size(); i++)
3045 int i, attr, newv[4], ind, m[5];
3049 Array<int> group_verts, group_edges, group_faces;
3051 int *I_group_svert, *J_group_svert;
3052 int *I_group_sedge, *J_group_sedge;
3053 int *I_group_sface, *J_group_sface;
3060 I_group_svert[0] = I_group_svert[1] = 0;
3061 I_group_sedge[0] = I_group_sedge[1] = 0;
3062 I_group_sface[0] = I_group_sface[1] = 0;
3068 I_group_svert[0] = 0;
3069 I_group_sedge[0] = 0;
3070 I_group_sface[0] = 0;
3081 for (group = 0; group <
GetNGroups()-1; group++)
3092 ind = oedge + v_to_v(v[0], v[1]);
3099 newv[0] = v[0]; newv[1] = ind;
3107 m[0] = oface+(*faces_tbl)(v[0], v[1], v[2], v[3]);
3112 m[1] = oedge + v_to_v(v[0], v[1]);
3113 m[2] = oedge + v_to_v(v[1], v[2]);
3114 m[3] = oedge + v_to_v(v[2], v[3]);
3115 m[4] = oedge + v_to_v(v[3], v[0]);
3125 newv[0] = v[0]; newv[1] = m[1]; newv[2] = m[0]; newv[3] = m[4];
3135 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3136 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3137 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
3140 J = J_group_svert+I_group_svert[group];
3141 for (i = 0; i < group_verts.
Size(); i++)
3143 J[i] = group_verts[i];
3145 J = J_group_sedge+I_group_sedge[group];
3146 for (i = 0; i < group_edges.
Size(); i++)
3148 J[i] = group_edges[i];
3150 J = J_group_sface+I_group_sface[group];
3151 for (i = 0; i < group_faces.
Size(); i++)
3153 J[i] = group_faces[i];
3171 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
3187 mfem::out <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
3193 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
3199 out <<
"NETGEN_Neutral_Format\n";
3204 for (j = 0; j <
Dim; j++)
3217 out <<
elements[i]->GetAttribute();
3218 for (j = 0; j < nv; j++)
3220 out <<
" " << ind[j]+1;
3232 out <<
boundary[i]->GetAttribute();
3233 for (j = 0; j < nv; j++)
3235 out <<
" " << ind[j]+1;
3245 for (j = 0; j < nv; j++)
3247 out <<
" " << ind[j]+1;
3260 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3262 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3263 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3264 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
3269 <<
" " <<
vertices[i](2) <<
" 0.0\n";
3276 out << i+1 <<
" " <<
elements[i]->GetAttribute();
3277 for (j = 0; j < nv; j++)
3279 out <<
" " << ind[j]+1;
3289 out <<
boundary[i]->GetAttribute();
3290 for (j = 0; j < nv; j++)
3292 out <<
" " << ind[j]+1;
3294 out <<
" 1.0 1.0 1.0 1.0\n";
3303 for (j = 0; j < nv; j++)
3305 out <<
" " << ind[j]+1;
3307 out <<
" 1.0 1.0 1.0 1.0\n";
3316 out <<
"areamesh2\n\n";
3323 attr =
boundary[i]->GetAttribute();
3326 for (j = 0; j < v.
Size(); j++)
3328 out << v[j] + 1 <<
" ";
3338 for (j = 0; j < v.
Size(); j++)
3340 out << v[j] + 1 <<
" ";
3349 attr =
elements[i]->GetAttribute();
3365 for (j = 0; j < v.
Size(); j++)
3367 out << v[j] + 1 <<
" ";
3376 for (j = 0; j <
Dim; j++)
3401 bool print_shared =
true;
3402 int i, j, shared_bdr_attr;
3419 s2l_face = &nc_shared_faces;
3426 for (
unsigned i = 0; i < sfaces.
conforming.size(); i++)
3429 if (index < nfaces) { nc_shared_faces.
Append(index); }
3431 for (
unsigned i = 0; i < sfaces.
masters.size(); i++)
3434 int index = sfaces.
masters[i].index;
3435 if (index < nfaces) { nc_shared_faces.
Append(index); }
3437 for (
unsigned i = 0; i < sfaces.
slaves.size(); i++)
3439 int index = sfaces.
slaves[i].index;
3440 if (index < nfaces) { nc_shared_faces.
Append(index); }
3445 out <<
"MFEM mesh v1.0\n";
3449 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
3454 "# TETRAHEDRON = 4\n"
3458 out <<
"\ndimension\n" <<
Dim
3466 if (print_shared &&
Dim > 1)
3468 num_bdr_elems += s2l_face->
Size();
3470 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
3476 if (print_shared &&
Dim > 1)
3484 shared_bdr_attr =
MyRank + 1;
3486 for (i = 0; i < s2l_face->
Size(); i++)
3489 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
3521 for (
int i = 0; i < nv; i++)
3529 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
3537 out <<
"MFEM mesh v1.0\n";
3541 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
3546 "# TETRAHEDRON = 4\n"
3550 out <<
"\ndimension\n" <<
Dim;
3554 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3557 out <<
"\n\nelements\n" << ne <<
'\n';
3561 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
3565 for (j = 0; j < nv; j++)
3572 for (p = 1; p <
NRanks; p++)
3574 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
3578 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
3580 for (i = 0; i < ne; )
3583 out << p+1 <<
' ' << ints[i];
3586 for (j = 0; j < k; j++)
3588 out <<
' ' << vc + ints[i++];
3601 ne += 1 +
elements[i]->GetNVertices();
3604 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
3612 MFEM_ASSERT(ints.
Size() == ne,
"");
3615 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
3638 dump_element(
boundary[i], ints); ne++;
3643 for (i = 0; i < shared.
Size(); i++)
3645 dump_element(shared[i], ints); ne++;
3652 for (i = 0; i < (int) list.
conforming.size(); i++)
3655 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3657 for (i = 0; i < (int) list.
masters.size(); i++)
3659 int index = list.
masters[i].index;
3660 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3662 for (i = 0; i < (int) list.
slaves.size(); i++)
3664 int index = list.
slaves[i].index;
3665 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3669 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3672 out <<
"\nboundary\n" << k <<
'\n';
3674 for (p = 0; p <
NRanks; p++)
3678 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
3682 MPI_Recv(ints.
GetData(), ne, MPI_INT, p, 447,
MyComm, &status);
3690 for (i = 0; i < ne; )
3693 out << p+1 <<
' ' << ints[i];
3696 for (j = 0; j < k; j++)
3698 out <<
' ' << vc + ints[i++];
3709 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
3720 out <<
"\nvertices\n" << nv <<
'\n';
3736 for (p = 1; p <
NRanks; p++)
3738 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
3742 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
3744 for (i = 0; i < nv; i++)
3749 out <<
' ' << vert[i*spaceDim+j];
3764 vert[i*spaceDim+j] =
vertices[i](j);
3769 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
3796 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
3804 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
3807 int i, j, k, nv, ne, p;
3815 out <<
"NETGEN_Neutral_Format\n";
3818 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3822 for (j = 0; j <
Dim; j++)
3828 for (p = 1; p <
NRanks; p++)
3830 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3832 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
3833 for (i = 0; i < nv; i++)
3835 for (j = 0; j <
Dim; j++)
3837 out <<
" " << vert[Dim*i+j];
3845 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3852 for (j = 0; j < nv; j++)
3854 out <<
" " << ind[j]+1;
3859 for (p = 1; p <
NRanks; p++)
3861 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3862 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3864 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
3865 for (i = 0; i < ne; i++)
3868 for (j = 0; j < 4; j++)
3870 out <<
" " << k+ints[i*4+j]+1;
3878 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3886 for (j = 0; j < nv; j++)
3888 out <<
" " << ind[j]+1;
3898 for (j = 0; j < nv; j++)
3900 out <<
" " << ind[j]+1;
3905 for (p = 1; p <
NRanks; p++)
3907 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3908 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3910 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
3911 for (i = 0; i < ne; i++)
3914 for (j = 0; j < 3; j++)
3916 out <<
" " << k+ints[i*3+j]+1;
3926 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3930 for (j = 0; j <
Dim; j++)
3934 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3938 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3939 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3945 for (j = 0; j < 4; j++)
3950 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
3953 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3954 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3956 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
3961 for (j = 0; j < 3; j++)
3966 for ( ; i < ne; i++)
3969 for (j = 0; j < 3; j++)
3974 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
3980 int i, j, k, nv, ne, p;
3986 int TG_nv, TG_ne, TG_nbe;
3993 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3996 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
3997 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3998 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3999 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
4000 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4006 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4007 for (p = 1; p <
NRanks; p++)
4009 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4011 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4012 for (i = 0; i < nv; i++)
4013 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
4014 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
4023 out << i+1 <<
" " << 1;
4024 for (j = 0; j < nv; j++)
4026 out <<
" " << ind[j]+1;
4031 for (p = 1; p <
NRanks; p++)
4033 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4034 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4036 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
4037 for (i = 0; i < ne; i++)
4039 out << i+1 <<
" " << p+1;
4040 for (j = 0; j < 8; j++)
4042 out <<
" " << k+ints[i*8+j]+1;
4057 for (j = 0; j < nv; j++)
4059 out <<
" " << ind[j]+1;
4061 out <<
" 1.0 1.0 1.0 1.0\n";
4069 for (j = 0; j < nv; j++)
4071 out <<
" " << ind[j]+1;
4073 out <<
" 1.0 1.0 1.0 1.0\n";
4076 for (p = 1; p <
NRanks; p++)
4078 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4079 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4081 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4082 for (i = 0; i < ne; i++)
4085 for (j = 0; j < 4; j++)
4087 out <<
" " << k+ints[i*4+j]+1;
4089 out <<
" 1.0 1.0 1.0 1.0\n";
4099 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4104 for (j = 0; j <
Dim; j++)
4108 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
4110 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4116 for (j = 0; j < 8; j++)
4121 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
4123 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4125 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4130 for (j = 0; j < 4; j++)
4135 for ( ; i < ne; i++)
4138 for (j = 0; j < 4; j++)
4143 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
4149 int i, j, k, attr, nv, ne, p;
4158 out <<
"areamesh2\n\n";
4162 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4167 attr =
boundary[i]->GetAttribute();
4170 for (j = 0; j < v.
Size(); j++)
4172 out << v[j] + 1 <<
" ";
4182 for (j = 0; j < v.
Size(); j++)
4184 out << v[j] + 1 <<
" ";
4189 for (p = 1; p <
NRanks; p++)
4191 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4192 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4194 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
4195 for (i = 0; i < ne; i++)
4198 for (j = 0; j < 2; j++)
4200 out <<
" " << k+ints[i*2+j]+1;
4209 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4213 attr =
elements[i]->GetAttribute();
4215 out << 1 <<
" " << 3 <<
" ";
4216 for (j = 0; j < v.
Size(); j++)
4218 out << v[j] + 1 <<
" ";
4223 for (p = 1; p <
NRanks; p++)
4225 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4226 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4228 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4229 for (i = 0; i < ne; i++)
4231 out << p+1 <<
" " << 3;
4232 for (j = 0; j < 3; j++)
4234 out <<
" " << k+ints[i*3+j]+1;
4243 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4247 for (j = 0; j <
Dim; j++)
4253 for (p = 1; p <
NRanks; p++)
4255 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4257 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4258 for (i = 0; i < nv; i++)
4260 for (j = 0; j <
Dim; j++)
4262 out <<
" " << vert[Dim*i+j];
4272 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4275 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4280 for (j = 0; j < 2; j++)
4285 for ( ; i < ne; i++)
4288 for (j = 0; j < 2; j++)
4293 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
4296 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4303 for (j = 0; j < 3; j++)
4308 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
4311 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4315 for (j = 0; j <
Dim; j++)
4319 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4337 MPI_Allreduce(p_min.
GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN,
MyComm);
4338 MPI_Allreduce(p_max.
GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX,
MyComm);
4342 double &gk_min,
double &gk_max)
4344 double h_min, h_max, kappa_min, kappa_max;
4348 MPI_Allreduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
4349 MPI_Allreduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
4350 MPI_Allreduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN,
MyComm);
4351 MPI_Allreduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX,
MyComm);
4358 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
4362 out <<
"Parallel Mesh Stats:" <<
'\n';
4368 h = pow(fabs(J.
Det()), 1.0/
double(
Dim));
4373 kappa_min = kappa_max =
kappa;
4377 if (h < h_min) { h_min = h; }
4378 if (h > h_max) { h_max = h; }
4379 if (kappa < kappa_min) { kappa_min =
kappa; }
4380 if (kappa > kappa_max) { kappa_max =
kappa; }
4384 double gh_min, gh_max, gk_min, gk_max;
4385 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
4386 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
4387 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
4388 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
4391 long mindata[5], maxdata[5], sumdata[5];
4407 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
4408 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
4409 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
4415 << setw(12) <<
"minimum"
4416 << setw(12) <<
"average"
4417 << setw(12) <<
"maximum"
4418 << setw(12) <<
"total" <<
'\n';
4420 << setw(12) << mindata[0]
4421 << setw(12) << sumdata[0]/
NRanks
4422 << setw(12) << maxdata[0]
4423 << setw(12) << sumdata[0] <<
'\n';
4425 << setw(12) << mindata[1]
4426 << setw(12) << sumdata[1]/
NRanks
4427 << setw(12) << maxdata[1]
4428 << setw(12) << sumdata[1] <<
'\n';
4431 << setw(12) << mindata[2]
4432 << setw(12) << sumdata[2]/
NRanks
4433 << setw(12) << maxdata[2]
4434 << setw(12) << sumdata[2] <<
'\n';
4436 << setw(12) << mindata[3]
4437 << setw(12) << sumdata[3]/
NRanks
4438 << setw(12) << maxdata[3]
4439 << setw(12) << sumdata[3] <<
'\n';
4440 out <<
" neighbors "
4441 << setw(12) << mindata[4]
4442 << setw(12) << sumdata[4]/
NRanks
4443 << setw(12) << maxdata[4] <<
'\n';
4446 << setw(12) <<
"minimum"
4447 << setw(12) <<
"maximum" <<
'\n';
4449 << setw(12) << gh_min
4450 << setw(12) << gh_max <<
'\n';
4452 << setw(12) << gk_min
4453 << setw(12) << gk_max <<
'\n';
4460 long local = value, global;
4461 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
4477 Printer(out,
"mfem_serial_mesh_end");
4485 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
4489 out <<
"total_shared_faces " <<
shared_faces.Size() <<
'\n';
4496 out <<
"\n#group " << gr <<
"\nshared_vertices " << nv <<
'\n';
4497 for (
int i = 0; i < nv; i++)
4506 out <<
"\nshared_edges " << ne <<
'\n';
4507 for (
int i = 0; i < ne; i++)
4510 out << v[0] <<
' ' << v[1] <<
'\n';
4517 out <<
"\nshared_faces " << nf <<
'\n';
4518 for (
int i = 0; i < nf; i++)
4526 out <<
"\nmfem_mesh_end" << endl;
4533 const int npts = point_mat.
Width();
4534 if (npts == 0) {
return 0; }
4536 const bool no_warn =
false;
4543 Array<int> my_point_rank(npts), glob_point_rank(npts);
4544 for (
int k = 0; k < npts; k++)
4546 my_point_rank[k] = (elem_id[k] == -1) ?
NRanks :
MyRank;
4549 MPI_Allreduce(my_point_rank.GetData(), glob_point_rank.
GetData(), npts,
4550 MPI_INT, MPI_MIN,
MyComm);
4553 for (
int k = 0; k < npts; k++)
4555 if (glob_point_rank[k] ==
NRanks) { elem_id[k] = -1; }
4559 if (glob_point_rank[k] !=
MyRank) { elem_id[k] = -2; }
4562 if (warn && pts_found != npts &&
MyRank == 0)
4564 MFEM_WARNING((npts-pts_found) <<
" points were not found");
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
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 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 UseExternalData(double *ext_data, int i, int j, int k)
void FreeElement(Element *E)
void DerefineMesh(const Array< int > &derefinements)
Derefine elements once a list of derefinements is known.
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.
virtual Element * Duplicate(Mesh *m) const =0
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
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.
void GetFaceElements(int Face, int *Elem1, int *Elem2)
Array< Element * > boundary
int * GeneratePartitioning(int nparts, int part_method=1)
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)
int GetFaceGeometryType(int Face) const
Array< Element * > face_nbr_elements
Lists all edges/faces in the nonconforming mesh.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void GetLocalFaceTransformation(int face_type, int elem_type, IsoparametricTransformation &Transf, int inf)
Used in GetFaceElementTransformations (...)
int GetGroupSize(int g) const
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
void SetDims(int rows, int nnz)
const int * GetGroup(int g) const
void Copy(Array ©) const
Create a copy of the current array.
RefinedGeometry * Refine(int Geom, int Times, int ETimes=1)
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.
ElementTransformation * GetGhostFaceTransformation(FaceElementTransformations *FETr, int face_type, int face_geom)
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
const FiniteElement * GetTraceElement(int i, int geom_type) const
Return the trace element from element 'i' to the given 'geom_type'.
int GetBdrElementEdgeIndex(int i) const
void GetCharacteristics(double &h_min, double &h_max, double &kappa_min, double &kappa_max)
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.
virtual void OnMeshUpdated(Mesh *mesh)
Abstract parallel finite element space.
Array< int > face_nbr_vertices_offset
std::vector< MeshId > conforming
Array< int > face_nbr_group
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
Data type quadrilateral element.
void GetVertices(Vector &vert_coord) const
int GetFaceElementType(int Face) const
virtual void MarkTetMeshForRefinement(DSTable &v_to_v)
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)
int GetGeometryType() const
void DeleteAll()
Delete whole array.
void AddConnections(int r, const int *c, int nc)
void InitRefinementTransforms()
IsoparametricTransformation FaceTransformation
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
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()
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.
void GetElementJacobian(int i, DenseMatrix &J)
void Rebalance()
Load balance the mesh. NC meshes only.
void GetVertexDofs(int i, Array< int > &dofs) const
bool Nonconforming() const
Communicator performing operations within groups defined by a GroupTopology with arbitrary-size data ...
const FiniteElement * GetFaceNbrFE(int i) const
void GetSharedFaceDofs(int group, int fi, Array< int > &dofs) 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 PrintAsOne(std::ostream &out=mfem::out)
void Finalize()
Allocate internal buffers after the GroupLDofTable is defined.
void GetFaceTransformation(int i, IsoparametricTransformation *FTr)
void CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
std::vector< Master > masters
static const int NumVerts[NumGeom]
static FiniteElement * GetTransformationFEforElementType(int)
void AddConnection(int r, int c)
STable3D * GetElementToFaceTable(int ret_ftbl=0)
FaceElementTransformations * GetSharedFaceTransformations(int sf, bool fill2=true)
static void Rotate3(int &, int &, int &)
int MeshGenerator()
Get the mesh generator/type.
Table send_face_nbr_vertices
int GetFaceSplittings(Element *face, const DSTable &v_to_v, int *middle)
Return a number(0-4) identifying how the given face has been split.
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 int * GetDofMap(int GeomType) const
Get the Cartesian to local H1 dof map.
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 Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
GeometryRefiner GlobGeometryRefiner
Array< Element * > shared_faces
int GetAttribute() const
Return element's attribute.
int GetElementToEdgeTable(Table &, Array< int > &)
Data type triangle element.
int GetElementType(int i) const
Returns the type of element i.
const Element * GetElement(int i) const
int GroupNVertices(int group)
virtual void QuadUniformRefinement()
Refine quadrilateral mesh.
IsoparametricTransformation Transformation2
int Size() const
Returns the number of TYPE I elements.
int GetVDim() const
Returns vector dimension.
FiniteElementSpace * FESpace()
virtual void ReorientTetMesh()
virtual void HexUniformRefinement()
Refine a hexahedral mesh.
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 Save(std::ostream &out) const
Save the data in a stream.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void RefineGroups(const DSTable &v_to_v, int *middle)
Update the groups after tet 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
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 mfem_error(const char *msg)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
virtual long ReduceInt(int value) const
Utility function: sum integers from all processors (Allreduce).
bool IsSlaveFace(const FaceInfo &fi) const
virtual void QuadUniformRefinement()
Refine quadrilateral mesh.
virtual void HexUniformRefinement()
Refine hexahedral mesh.
void Swap(Mesh &other, bool non_geometry=false)
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).
int GetElementBaseGeometry(int i=0) const
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name...
void GetFaceNbrElementTransformation(int i, IsoparametricTransformation *ElTr)
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual const char * Name() const
virtual void Refine(const Array< Refinement > &refinements)
Element * ReadElementWithoutAttr(std::istream &)
void GroupFace(int group, int i, int &face, int &o)
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
void ExchangeFaceNbrNodes()
void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
static const int Orient[NumOrient][NumVert]
void SetIJ(int *newI, int *newJ, int newsize=-1)
Table group_svert
Shared objects in each group.
int GroupNFaces(int group)
virtual int DofForGeometry(int GeomType) const
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.
STable3D * GetFacesTable()
NCMesh * ncmesh
Optional non-conforming mesh extension.
static void PrintElementWithoutAttr(const Element *, std::ostream &)
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.
int GetNEdges() const
Return the number of edges.
virtual void PrintXG(std::ostream &out=mfem::out) const
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 NCList & GetSharedList(int type)
Helper to get shared vertices/edges/faces ('type' == 0/1/2 resp.).
const FiniteElementCollection * FEColl() const
void GetNodes(Vector &node_coord) const
int GetFaceBaseGeometry(int i) const
void AverageVertices(int *indexes, int n, int result)
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".
bool IsGhost(int type, int index) const
Returns true if the specified vertex/edge/face is a ghost.
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 ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
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 *)
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 GenerateNCFaceInfo()
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
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.
virtual int GetType() const =0
Returns element's type.
void UpdateNodes()
Update the nodes of a curved mesh after refinement.
Defines the position of a fine element within a coarse element.
void GetFaceNeighbors(ParMesh &pmesh)
void Bcast(T *ldata, int layout)
Broadcast within each group where the master is the root.
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.