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"
28 ParMesh::ParMesh(
const ParMesh &pmesh,
bool copy_nodes)
30 group_svert(pmesh.group_svert),
31 group_sedge(pmesh.group_sedge),
32 group_sface(pmesh.group_sface),
61 MFEM_VERIFY(pmesh.
pncmesh == NULL,
62 "copying non-conforming meshes is not implemented");
67 if (pmesh.
Nodes && copy_nodes)
77 Nodes->MakeOwner(fec_copy);
78 *Nodes = *pmesh.
Nodes;
100 int* partition =
new int[mesh.
GetNE()];
101 for (
int i = 0; i < mesh.
GetNE(); i++)
140 partitioning = partitioning_;
152 int vert_counter, element_counter, bdrelem_counter;
155 vert_global_local = -1;
159 for (i = 0; i < mesh.
GetNE(); i++)
160 if (partitioning[i] ==
MyRank)
164 for (j = 0; j < vert.
Size(); j++)
165 if (vert_global_local[vert[j]] < 0)
167 vert_global_local[vert[j]] = vert_counter++;
176 for (i = vert_counter = 0; i < vert_global_local.
Size(); i++)
177 if (vert_global_local[i] >= 0)
179 vert_global_local[i] = vert_counter++;
183 for (i = 0; i < vert_global_local.Size(); i++)
184 if (vert_global_local[i] >= 0)
192 for (i = 0; i < mesh.
GetNE(); i++)
193 if (partitioning[i] ==
MyRank)
196 int *v =
elements[element_counter]->GetVertices();
197 int nv =
elements[element_counter]->GetNVertices();
198 for (j = 0; j < nv; j++)
200 v[j] = vert_global_local[v[j]];
205 Table *edge_element = NULL;
209 activeBdrElem =
false;
215 for (i = 0; i < mesh.
GetNBE(); i++)
217 int face, o, el1, el2;
220 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
225 activeBdrElem[i] =
true;
232 for (i = 0; i < mesh.
GetNBE(); i++)
234 int face, o, el1, el2;
237 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] ==
MyRank)
240 int *v =
boundary[bdrelem_counter]->GetVertices();
241 int nv =
boundary[bdrelem_counter]->GetNVertices();
242 for (j = 0; j < nv; j++)
244 v[j] = vert_global_local[v[j]];
252 edge_element =
new Table;
256 for (i = 0; i < mesh.
GetNBE(); i++)
259 int el1 = edge_element->
GetRow(edge)[0];
260 if (partitioning[el1] ==
MyRank)
265 activeBdrElem[i] =
true;
272 for (i = 0; i < mesh.
GetNBE(); i++)
275 int el1 = edge_element->
GetRow(edge)[0];
276 if (partitioning[el1] ==
MyRank)
279 int *v =
boundary[bdrelem_counter]->GetVertices();
280 int nv =
boundary[bdrelem_counter]->GetNVertices();
281 for (j = 0; j < nv; j++)
283 v[j] = vert_global_local[v[j]];
292 for (i = 0; i < mesh.
GetNBE(); i++)
294 int vert = mesh.
boundary[i]->GetVertices()[0];
297 if (partitioning[el1] ==
MyRank)
305 for (i = 0; i < mesh.
GetNBE(); i++)
307 int vert = mesh.
boundary[i]->GetVertices()[0];
310 if (partitioning[el1] ==
MyRank)
313 int *v =
boundary[bdrelem_counter]->GetVertices();
314 v[0] = vert_global_local[v[0]];
359 cerr <<
"ParMesh::ParMesh (proc " <<
MyRank <<
") : "
360 "(Dim < 3 && mesh.GetNFaces() != 0) is true!" << endl;
365 int sface_counter = 0;
367 for (i = 0; i < face_group.Size(); i++)
374 el[0] = partitioning[el[0]];
375 el[1] = partitioning[el[1]];
380 face_group[i] = groups.
Insert(group) - 1;
387 int sedge_counter = 0;
390 edge_element =
new Table;
400 for (i = 0; i < edge_element->
Size(); i++)
402 int me = 0, others = 0;
403 for (j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
405 edge_element->
GetJ()[j] = partitioning[edge_element->
GetJ()[j]];
424 edge_element->
GetRow(i)[0] = -1;
429 int svert_counter = 0;
432 for (i = 0; i < vert_element->
Size(); i++)
434 int me = 0, others = 0;
435 for (j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
437 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
452 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
456 vert_element->
GetI()[i] = -1;
463 for (i = 0; i < face_group.Size(); i++)
465 if (face_group[i] >= 0)
474 for (i = 0; i < face_group.Size(); i++)
476 if (face_group[i] >= 0)
487 for (i = 0; i < edge_element->
Size(); i++)
489 if (edge_element->
GetRow(i)[0] >= 0)
498 for (i = 0; i < edge_element->
Size(); i++)
500 if (edge_element->
GetRow(i)[0] >= 0)
511 for (i = 0; i < vert_element->
Size(); i++)
513 if (vert_element->
GetI()[i] >= 0)
522 for (i = 0; i < vert_element->
Size(); i++)
524 if (vert_element->
GetI()[i] >= 0)
539 for (i = 0; i < face_group.Size(); i++)
541 if (face_group[i] >= 0)
546 for (j = 0; j < nv; j++)
548 v[j] = vert_global_local[v[j]];
553 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
567 if (
MyRank == partitioning[gl_el2])
569 std::swap(v[0], v[1]);
576 (*faces_tbl)(v[0], v[1], v[2], v[3]);
595 for (i = 0; i < edge_element->
Size(); i++)
597 if (edge_element->
GetRow(i)[0] >= 0)
602 new Segment(vert_global_local[vert[0]],
603 vert_global_local[vert[1]], 1);
606 v_to_v(vert_global_local[vert[0]],
607 vert_global_local[vert[1]])) < 0)
609 cerr <<
"\n\n\n" <<
MyRank <<
": ParMesh::ParMesh: "
610 <<
"ERROR in v_to_v\n\n" << endl;
625 for (i = 0; i < vert_element->
Size(); i++)
627 if (vert_element->
GetI()[i] >= 0)
629 svert_lvert[svert_counter++] = vert_global_local[i];
652 for (i = 0; i < mesh.
GetNE(); i++)
653 if (partitioning[i] ==
MyRank)
656 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
657 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
663 if (partitioning_ == NULL)
665 delete [] partitioning;
673 : MyComm(pncmesh.MyComm)
674 , NRanks(pncmesh.NRanks)
675 , MyRank(pncmesh.MyRank)
701 Loader(input, gen_edges,
"mfem_serial_mesh_end");
707 MFEM_VERIFY(ident ==
"communication_groups",
708 "input stream is not a parallel MFEM mesh");
718 input >> ident >> num_sverts;
727 input >> ident >> num_sedges;
743 input >> ident >> num_sfaces;
758 int svert_counter = 0, sedge_counter = 0, sface_counter = 0;
765 cerr <<
"ParMesh::ParMesh : expecting group " << gr
766 <<
", read group " << g << endl;
772 input >> ident >> nv;
775 "incorrect number of total_shared_vertices");
777 for ( ; svert_counter < nv; svert_counter++)
786 input >> ident >> ne;
789 "incorrect number of total_shared_edges");
791 for ( ; sedge_counter < ne; sedge_counter++)
794 input >> v[0] >> v[1];
796 sedge_ledge[sedge_counter] = (*v_to_v)(v[0], v[1]);
802 input >> ident >> nf;
805 "incorrect number of total_shared_faces");
807 for ( ; sface_counter < nf; sface_counter++)
816 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
820 (*faces_tbl)(v[0], v[1], v[2], v[3]);
829 const bool refine =
true;
830 const bool fix_orientation =
false;
841 :
Mesh(orig_mesh, ref_factor, ref_type),
842 MyComm(orig_mesh->GetComm()),
843 NRanks(orig_mesh->GetNRanks()),
844 MyRank(orig_mesh->GetMyRank()),
845 gtopo(orig_mesh->gtopo),
846 have_face_nbr_data(false),
872 for (
int fi = 0; fi < orig_nf; fi++)
874 const int orig_l_face = orig_mesh->
sface_lface[orig_sf[fi]];
905 for (
int j = 0; j < orig_n_verts; j++)
912 const int orig_n_edges = orig_mesh->
GroupNEdges(gr);
916 for (
int e = 0; e < orig_n_edges; e++)
921 for (
int j = 2; j < rdofs.
Size(); j++)
925 const int *c2h_map = rfec.
GetDofMap(geom);
930 for (
int k = 0; k < nvert; k++)
933 v[k] = rdofs[c2h_map[cid]];
942 for (
int f = 0; f < orig_nf; f++)
944 const int orig_l_face = orig_mesh->
sface_lface[orig_sf[f]];
954 for (
int j = rdofs.
Size()-num_int_verts; j < rdofs.
Size(); j++)
958 const int *c2h_map = rfec.
GetDofMap(geom);
964 for (
int k = 0; k < 2; k++)
966 v[k] = rdofs[c2h_map[RG.
RefEdges[j+k]]];
975 for (
int k = 0; k < nvert; k++)
978 v[k] = rdofs[c2h_map[cid]];
996 const int l_edge = v_to_v(v[0], v[1]);
997 MFEM_ASSERT(l_edge >= 0,
"invalid shared edge");
1013 l_face = (*faces_tbl)(v[0], v[1], v[2]);
1016 l_face = (*faces_tbl)(v[0], v[1], v[2], v[3]);
1019 MFEM_ABORT(
"invalid face geometry");
1022 MFEM_ASSERT(l_face >= 0,
"invalid shared face");
1034 o = (v[0] < v[1]) ? (+1) : (-1);
1065 gr_sedge.
GetI()[0] = 0;
1084 sedge_comm.
Bcast<
int>(sedge_ord, 1);
1086 for (
int k = 0, gr = 1; gr <
GetNGroups(); gr++)
1089 if (n == 0) {
continue; }
1090 sedge_ord_map.SetSize(n);
1091 for (
int j = 0; j < n; j++)
1093 sedge_ord_map[j].one = sedge_ord[k+j];
1094 sedge_ord_map[j].two = j;
1096 SortPairs<int, int>(sedge_ord_map, n);
1097 for (
int j = 0; j < n; j++)
1102 std::sort(&sedge_ord[k], &sedge_ord[k] + n);
1103 for (
int j = 0; j < n; j++)
1120 ilen_len[j].one = order[j];
1121 ilen_len[j].two =
GetLength(i, it.Column());
1125 SortPairs<int, double>(ilen_len, order.
Size());
1128 for (
int i = 1; i < order.
Size(); i++)
1130 d_max = std::max(d_max, ilen_len[i-1].two-ilen_len[i].two);
1135 cout <<
"proc. " <<
MyRank <<
'/' <<
NRanks <<
": d_max = " << d_max
1140 MPI_Reduce(&d_max, &glob_d_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
1143 cout <<
"glob_d_max = " << glob_d_max << endl;
1155 elements[i]->MarkEdge(v_to_v, order);
1163 boundary[i]->MarkEdge(v_to_v, order);
1185 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1206 int number_of_splittings = 0;
1209 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
1211 number_of_splittings++;
1212 if ((m = v_to_v(v[1], v[2])) != -1 && middle[m] != -1)
1215 number_of_splittings++;
1217 if ((m = v_to_v(v[2], v[0])) != -1 && middle[m] != -1)
1219 number_of_splittings++;
1222 switch (number_of_splittings)
1227 number_of_splittings++;
1231 number_of_splittings++;
1236 return number_of_splittings;
1242 if (HYPRE_AssumedPartitionCheck())
1245 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_INT, MPI_SUM,
MyComm);
1246 for (
int i = 0; i < N; i++)
1249 (*offsets[i])[0] = temp[i] - loc_sizes[i];
1250 (*offsets[i])[1] = temp[i];
1253 for (
int i = 0; i < N; i++)
1255 (*offsets[i])[2] = temp[i];
1257 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
1258 "overflow in offsets");
1264 MPI_Allgather(loc_sizes, N, HYPRE_MPI_INT, temp.
GetData(), N,
1266 for (
int i = 0; i < N; i++)
1271 for (
int j = 0; j <
NRanks; j++)
1273 offs[j+1] = offs[j] + temp[i+N*j];
1277 "overflow in offsets");
1299 for (
int j = 0; j < nv; j++)
1318 for (
int j = 0; j < n; j++)
1320 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
1328 MFEM_ABORT(
"Nodes are not ParGridFunction!");
1389 int num_face_nbrs = 0;
1391 if (gr_sface->
RowSize(g-1) > 0)
1398 if (num_face_nbrs == 0)
1408 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
1409 if (gr_sface->
RowSize(g-1) > 0)
1413 mfem_error(
"ParMesh::ExchangeFaceNbrData() : "
1414 "group size is not 2!");
1417 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
1419 rank_group[counter].two = g;
1423 SortPairs<int, int>(rank_group, rank_group.
Size());
1425 for (
int fn = 0; fn < num_face_nbrs; fn++)
1431 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1432 MPI_Request *send_requests = requests;
1433 MPI_Request *recv_requests = requests + num_face_nbrs;
1434 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1436 int *nbr_data =
new int[6*num_face_nbrs];
1437 int *nbr_send_data = nbr_data;
1438 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
1445 Table send_face_nbr_elemdata, send_face_nbr_facedata;
1449 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
1450 send_face_nbr_facedata.
MakeI(num_face_nbrs);
1451 for (
int fn = 0; fn < num_face_nbrs; fn++)
1454 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1455 int *sface = gr_sface->
GetRow(nbr_group-1);
1456 for (
int i = 0; i < num_sfaces; i++)
1458 int lface = s2l_face[sface[i]];
1460 if (el_marker[el] != fn)
1465 const int nv =
elements[el]->GetNVertices();
1466 const int *v =
elements[el]->GetVertices();
1467 for (
int j = 0; j < nv; j++)
1468 if (vertex_marker[v[j]] != fn)
1470 vertex_marker[v[j]] = fn;
1481 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
1486 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1487 &send_requests[fn]);
1488 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1489 &recv_requests[fn]);
1493 send_face_nbr_elemdata.
MakeJ();
1494 send_face_nbr_facedata.
MakeJ();
1497 for (
int fn = 0; fn < num_face_nbrs; fn++)
1500 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1501 int *sface = gr_sface->
GetRow(nbr_group-1);
1502 for (
int i = 0; i < num_sfaces; i++)
1504 int lface = s2l_face[sface[i]];
1506 if (el_marker[el] != fn)
1511 const int nv =
elements[el]->GetNVertices();
1512 const int *v =
elements[el]->GetVertices();
1513 for (
int j = 0; j < nv; j++)
1514 if (vertex_marker[v[j]] != fn)
1516 vertex_marker[v[j]] = fn;
1532 const int *sf_v =
shared_faces[sface[i]]->GetVertices();
1553 for (
int fn = 0; fn < num_face_nbrs; fn++)
1559 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
1560 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
1561 int *facedata = send_face_nbr_facedata.
GetRow(fn);
1563 for (
int i = 0; i < num_verts; i++)
1565 vertex_marker[verts[i]] = i;
1568 for (
int el = 0; el < num_elems; el++)
1570 const int nv =
elements[el]->GetNVertices();
1572 for (
int j = 0; j < nv; j++)
1574 elemdata[j] = vertex_marker[elemdata[j]];
1578 el_marker[elems[el]] = el;
1581 for (
int i = 0; i < num_sfaces; i++)
1583 facedata[2*i] = el_marker[facedata[2*i]];
1587 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1590 Table recv_face_nbr_elemdata;
1595 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
1598 for (
int fn = 0; fn < num_face_nbrs; fn++)
1606 recv_face_nbr_elemdata.
MakeJ();
1608 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1611 for (
int fn = 0; fn < num_face_nbrs; fn++)
1616 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
1617 send_face_nbr_elemdata.
RowSize(fn),
1618 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1620 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
1621 recv_face_nbr_elemdata.
RowSize(fn),
1622 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1630 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1632 if (fn == MPI_UNDEFINED)
1640 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
1642 for (
int i = 0; i < num_elems; i++)
1648 for (
int j = 0; j < nv; j++)
1650 recv_elemdata[j] += vert_off;
1653 recv_elemdata += nv;
1658 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1661 recv_face_nbr_facedata.
SetSize(
1663 for (
int fn = 0; fn < num_face_nbrs; fn++)
1668 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
1669 send_face_nbr_facedata.
RowSize(fn),
1670 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1673 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
1674 send_face_nbr_facedata.
RowSize(fn),
1675 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1682 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1684 if (fn == MPI_UNDEFINED)
1691 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1692 int *sface = gr_sface->
GetRow(nbr_group-1);
1694 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
1696 for (
int i = 0; i < num_sfaces; i++)
1698 int lface = s2l_face[sface[i]];
1700 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
1701 int info = facedata[2*i+1];
1709 int nbr_ori = info%64, nbr_v[4];
1711 const int *sf_v =
shared_faces[sface[i]]->GetVertices();
1717 for (
int j = 0; j < 3; j++)
1719 nbr_v[perm[j]] = sf_v[j];
1728 for (
int j = 0; j < 4; j++)
1730 nbr_v[perm[j]] = sf_v[j];
1736 info = 64*(info/64) + nbr_ori;
1742 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1763 else if (
Nodes == NULL)
1773 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1774 MPI_Request *send_requests = requests;
1775 MPI_Request *recv_requests = requests + num_face_nbrs;
1776 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1780 for (
int i = 0; i < send_vertices.Size(); i++)
1786 for (
int fn = 0; fn < num_face_nbrs; fn++)
1793 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
1798 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
1801 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1802 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1810 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
1821 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
1863 for (
int i = 0; i < s2l_face->
Size(); i++)
1878 for (
int i = 0; i < s2l_face->
Size(); i++)
1880 int lface = (*s2l_face)[i];
1881 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
1905 #if 0 // TODO: handle the case of non-interpolatory Nodes
1932 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
1981 if (is_ghost || fill2)
1990 std::swap(pm(0,0), pm(0,1));
1991 std::swap(pm(1,0), pm(1,1));
2018 MFEM_ASSERT(
Dim > 1,
"");
2037 MFEM_ASSERT(
Dim > 1,
"");
2040 return sface < csize
2042 : shared.
slaves[sface - csize].index;
2096 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
2105 int uniform_refinement = 0;
2109 uniform_refinement = 1;
2124 for (i = 0; i < marked_el.
Size(); i++)
2126 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2130 for (i = 0; i < marked_el.
Size(); i++)
2132 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2135 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2139 for (i = 0; i < marked_el.
Size(); i++)
2141 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2144 Bisection(j, v_to_v, NULL, NULL, middle);
2146 Bisection(j, v_to_v, NULL, NULL, middle);
2148 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2150 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
2156 int need_refinement;
2157 int refined_edge[5][3] =
2165 int faces_in_group, max_faces_in_group = 0;
2167 int **face_splittings =
new int*[
GetNGroups()-1];
2171 face_splittings[i] =
new int[faces_in_group];
2172 if (faces_in_group > max_faces_in_group)
2174 max_faces_in_group = faces_in_group;
2177 int neighbor, *iBuf =
new int[max_faces_in_group];
2181 MPI_Request request;
2184 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2185 int ref_loops_all = 0, ref_loops_par = 0;
2189 need_refinement = 0;
2192 if (
elements[i]->NeedRefinement(v_to_v, middle))
2194 need_refinement = 1;
2195 Bisection(i, v_to_v, NULL, NULL, middle);
2198 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2202 if (uniform_refinement)
2209 if (need_refinement == 0)
2211 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2215 const int tag = 293;
2221 faces_in_group = group_faces.
Size();
2223 if (faces_in_group == 0) {
continue; }
2225 for (j = 0; j < faces_in_group; j++)
2227 face_splittings[i][j] =
2233 MPI_Isend(face_splittings[i], faces_in_group, MPI_INT,
2234 neighbor, tag,
MyComm, &request);
2241 faces_in_group = group_faces.
Size();
2242 if (faces_in_group == 0) {
continue; }
2246 MPI_Recv(iBuf, faces_in_group, MPI_INT, neighbor,
2249 for (j = 0; j < faces_in_group; j++)
2251 if (iBuf[j] == face_splittings[i][j]) {
continue; }
2254 for (
int k = 0; k < 3; k++)
2256 if (refined_edge[iBuf[j]][k] != 1 ||
2257 refined_edge[face_splittings[i][j]][k] != 0)
2260 int ind[2] = { v[k], v[(k+1)%3] };
2261 int ii = v_to_v(ind[0], ind[1]);
2262 if (middle[ii] == -1)
2264 need_refinement = 1;
2273 i = need_refinement;
2274 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2277 while (need_refinement == 1);
2279 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2281 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2284 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2285 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2293 delete [] face_splittings[i];
2295 delete [] face_splittings;
2301 need_refinement = 0;
2304 if (
boundary[i]->NeedRefinement(v_to_v, middle))
2306 need_refinement = 1;
2311 while (need_refinement == 1);
2315 " (NumOfBdrElements != boundary.Size())");
2326 int refinement_edges[2], type, flag;
2351 int uniform_refinement = 0;
2355 uniform_refinement = 1;
2364 int *edge1 =
new int[nedges];
2365 int *edge2 =
new int[nedges];
2366 int *middle =
new int[nedges];
2368 for (i = 0; i < nedges; i++)
2370 edge1[i] = edge2[i] = middle[i] = -1;
2375 int *v =
elements[i]->GetVertices();
2376 for (j = 0; j < 3; j++)
2378 int ind = v_to_v(v[j], v[(j+1)%3]);
2379 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
2384 for (i = 0; i < marked_el.
Size(); i++)
2390 int need_refinement;
2391 int edges_in_group, max_edges_in_group = 0;
2393 int **edge_splittings =
new int*[
GetNGroups()-1];
2397 edge_splittings[i] =
new int[edges_in_group];
2398 if (edges_in_group > max_edges_in_group)
2400 max_edges_in_group = edges_in_group;
2403 int neighbor, *iBuf =
new int[max_edges_in_group];
2407 MPI_Request request;
2412 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2413 int ref_loops_all = 0, ref_loops_par = 0;
2417 need_refinement = 0;
2418 for (i = 0; i < nedges; i++)
2419 if (middle[i] != -1 && edge1[i] != -1)
2421 need_refinement = 1;
2424 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2428 if (uniform_refinement)
2435 if (need_refinement == 0)
2437 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2446 edges_in_group = group_edges.
Size();
2448 if (edges_in_group != 0)
2450 for (j = 0; j < edges_in_group; j++)
2451 edge_splittings[i][j] =
2463 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
2464 neighbor, 0,
MyComm, &request);
2472 edges_in_group = group_edges.
Size();
2473 if (edges_in_group != 0)
2484 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
2485 MPI_ANY_TAG,
MyComm, &status);
2487 for (j = 0; j < edges_in_group; j++)
2488 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
2491 int ii = v_to_v(v[0], v[1]);
2492 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2493 if (middle[ii] != -1)
2494 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
2497 need_refinement = 1;
2499 for (
int c = 0; c < 2; c++)
2508 i = need_refinement;
2509 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2512 while (need_refinement == 1);
2514 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2516 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2519 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2520 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2527 delete [] edge_splittings[i];
2529 delete [] edge_splittings;
2534 int v1[2], v2[2], bisect, temp;
2536 for (i = 0; i < temp; i++)
2538 int *v =
boundary[i]->GetVertices();
2539 bisect = v_to_v(v[0], v[1]);
2540 if (middle[bisect] != -1)
2545 v1[0] = v[0]; v1[1] = middle[bisect];
2546 v2[0] = middle[bisect]; v2[1] = v[1];
2552 mfem_error(
"Only bisection of segment is implemented for bdr"
2582 for (j = 0; j < marked_el.
Size(); j++)
2587 int new_v = cnv + j, new_e = cne + j;
2596 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
2618 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
2619 "supported. Project the NURBS to Nodes first.");
2624 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
2625 "(you need to initialize the ParMesh from a nonconforming "
2649 Swap(*pmesh2,
false);
2666 double threshold,
int nc_limit,
int op)
2679 for (
int i = 0; i < dt.
Size(); i++)
2681 if (nc_limit > 0 && !level_ok[i]) {
continue; }
2683 const int* fine = dt.
GetRow(i);
2687 for (
int j = 0; j < size; j++)
2689 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
2691 double err_fine = elem_error[fine[j]];
2694 case 0: error = std::min(error, err_fine);
break;
2695 case 1: error += err_fine;
break;
2696 case 2: error = std::max(error, err_fine);
break;
2700 if (error < threshold) { derefs.
Append(i); }
2717 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
2731 Swap(*pmesh2,
false);
2748 int i, attr, newv[3], ind, f_ind, *v;
2751 Array<int> group_verts, group_edges, group_faces;
2759 int *I_group_svert, *J_group_svert;
2760 int *I_group_sedge, *J_group_sedge;
2761 int *I_group_sface, *J_group_sface;
2771 I_group_sface = NULL;
2774 I_group_svert[0] = I_group_svert[1] = 0;
2775 I_group_sedge[0] = I_group_sedge[1] = 0;
2778 I_group_sface[0] = I_group_sface[1] = 0;
2795 J_group_sface = NULL;
2799 J_group_svert = J_group_sedge = J_group_sface = NULL;
2802 for (group = 0; group <
GetNGroups()-1; group++)
2813 ind = middle[v_to_v(v[0], v[1])];
2830 ind = middle[v_to_v(v[0], v[1])];
2838 f_ind = group_faces.
Size();
2841 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2846 ind = middle[v_to_v(v[0], v[1])];
2855 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2861 ind = middle[v_to_v(v[0], v[1])];
2870 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2876 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
2877 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
2880 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
2884 J = J_group_svert+I_group_svert[group];
2885 for (i = 0; i < group_verts.
Size(); i++)
2887 J[i] = group_verts[i];
2889 J = J_group_sedge+I_group_sedge[group];
2890 for (i = 0; i < group_edges.
Size(); i++)
2892 J[i] = group_edges[i];
2896 J = J_group_sface+I_group_sface[group];
2897 for (i = 0; i < group_faces.
Size(); i++)
2899 J[i] = group_faces[i];
2949 int i, attr, ind, *v;
2954 int *I_group_svert, *J_group_svert;
2955 int *I_group_sedge, *J_group_sedge;
2960 I_group_svert[0] = I_group_svert[1] = 0;
2961 I_group_sedge[0] = I_group_sedge[1] = 0;
2968 for (group = 0; group <
GetNGroups()-1; group++)
2988 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
2989 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
2992 J = J_group_svert+I_group_svert[group];
2993 for (i = 0; i < sverts.
Size(); i++)
2997 J = J_group_sedge+I_group_sedge[group];
2998 for (i = 0; i < sedges.
Size(); i++)
3041 int i, attr, newv[4], ind, m[5];
3045 Array<int> group_verts, group_edges, group_faces;
3047 int *I_group_svert, *J_group_svert;
3048 int *I_group_sedge, *J_group_sedge;
3049 int *I_group_sface, *J_group_sface;
3056 I_group_svert[0] = I_group_svert[1] = 0;
3057 I_group_sedge[0] = I_group_sedge[1] = 0;
3058 I_group_sface[0] = I_group_sface[1] = 0;
3064 I_group_svert[0] = 0;
3065 I_group_sedge[0] = 0;
3066 I_group_sface[0] = 0;
3077 for (group = 0; group <
GetNGroups()-1; group++)
3088 ind = oedge + v_to_v(v[0], v[1]);
3095 newv[0] = v[0]; newv[1] = ind;
3103 m[0] = oface+(*faces_tbl)(v[0], v[1], v[2], v[3]);
3108 m[1] = oedge + v_to_v(v[0], v[1]);
3109 m[2] = oedge + v_to_v(v[1], v[2]);
3110 m[3] = oedge + v_to_v(v[2], v[3]);
3111 m[4] = oedge + v_to_v(v[3], v[0]);
3121 newv[0] = v[0]; newv[1] = m[1]; newv[2] = m[0]; newv[3] = m[4];
3131 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
3132 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
3133 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
3136 J = J_group_svert+I_group_svert[group];
3137 for (i = 0; i < group_verts.
Size(); i++)
3139 J[i] = group_verts[i];
3141 J = J_group_sedge+I_group_sedge[group];
3142 for (i = 0; i < group_edges.
Size(); i++)
3144 J[i] = group_edges[i];
3146 J = J_group_sface+I_group_sface[group];
3147 for (i = 0; i < group_faces.
Size(); i++)
3149 J[i] = group_faces[i];
3167 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
3183 cout <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
3189 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
3195 out <<
"NETGEN_Neutral_Format\n";
3200 for (j = 0; j <
Dim; j++)
3213 out <<
elements[i]->GetAttribute();
3214 for (j = 0; j < nv; j++)
3216 out <<
" " << ind[j]+1;
3228 out <<
boundary[i]->GetAttribute();
3229 for (j = 0; j < nv; j++)
3231 out <<
" " << ind[j]+1;
3241 for (j = 0; j < nv; j++)
3243 out <<
" " << ind[j]+1;
3256 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3258 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3259 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3260 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
3265 <<
" " <<
vertices[i](2) <<
" 0.0\n";
3272 out << i+1 <<
" " <<
elements[i]->GetAttribute();
3273 for (j = 0; j < nv; j++)
3275 out <<
" " << ind[j]+1;
3285 out <<
boundary[i]->GetAttribute();
3286 for (j = 0; j < nv; j++)
3288 out <<
" " << ind[j]+1;
3290 out <<
" 1.0 1.0 1.0 1.0\n";
3299 for (j = 0; j < nv; j++)
3301 out <<
" " << ind[j]+1;
3303 out <<
" 1.0 1.0 1.0 1.0\n";
3312 out <<
"areamesh2\n\n";
3319 attr =
boundary[i]->GetAttribute();
3322 for (j = 0; j < v.
Size(); j++)
3324 out << v[j] + 1 <<
" ";
3334 for (j = 0; j < v.
Size(); j++)
3336 out << v[j] + 1 <<
" ";
3345 attr =
elements[i]->GetAttribute();
3361 for (j = 0; j < v.
Size(); j++)
3363 out << v[j] + 1 <<
" ";
3372 for (j = 0; j <
Dim; j++)
3397 bool print_shared =
true;
3398 int i, j, shared_bdr_attr;
3415 s2l_face = &nc_shared_faces;
3422 for (
unsigned i = 0; i < sfaces.
conforming.size(); i++)
3425 if (index < nfaces) { nc_shared_faces.
Append(index); }
3427 for (
unsigned i = 0; i < sfaces.
masters.size(); i++)
3430 int index = sfaces.
masters[i].index;
3431 if (index < nfaces) { nc_shared_faces.
Append(index); }
3433 for (
unsigned i = 0; i < sfaces.
slaves.size(); i++)
3435 int index = sfaces.
slaves[i].index;
3436 if (index < nfaces) { nc_shared_faces.
Append(index); }
3441 out <<
"MFEM mesh v1.0\n";
3445 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
3450 "# TETRAHEDRON = 4\n"
3454 out <<
"\ndimension\n" <<
Dim
3462 if (print_shared &&
Dim > 1)
3464 num_bdr_elems += s2l_face->
Size();
3466 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
3472 if (print_shared &&
Dim > 1)
3480 shared_bdr_attr =
MyRank + 1;
3482 for (i = 0; i < s2l_face->
Size(); i++)
3485 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
3517 for (
int i = 0; i < nv; i++)
3525 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
3533 out <<
"MFEM mesh v1.0\n";
3537 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
3542 "# TETRAHEDRON = 4\n"
3546 out <<
"\ndimension\n" <<
Dim;
3550 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3553 out <<
"\n\nelements\n" << ne <<
'\n';
3557 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
3561 for (j = 0; j < nv; j++)
3568 for (p = 1; p <
NRanks; p++)
3570 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
3574 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
3576 for (i = 0; i < ne; )
3579 out << p+1 <<
' ' << ints[i];
3582 for (j = 0; j < k; j++)
3584 out <<
' ' << vc + ints[i++];
3597 ne += 1 +
elements[i]->GetNVertices();
3600 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
3608 MFEM_ASSERT(ints.
Size() == ne,
"");
3611 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
3634 dump_element(
boundary[i], ints); ne++;
3639 for (i = 0; i < shared.
Size(); i++)
3641 dump_element(shared[i], ints); ne++;
3648 for (i = 0; i < (int) list.
conforming.size(); i++)
3651 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3653 for (i = 0; i < (int) list.
masters.size(); i++)
3655 int index = list.
masters[i].index;
3656 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3658 for (i = 0; i < (int) list.
slaves.size(); i++)
3660 int index = list.
slaves[i].index;
3661 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3665 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3668 out <<
"\nboundary\n" << k <<
'\n';
3670 for (p = 0; p <
NRanks; p++)
3674 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
3678 MPI_Recv(ints.
GetData(), ne, MPI_INT, p, 447,
MyComm, &status);
3686 for (i = 0; i < ne; )
3689 out << p+1 <<
' ' << ints[i];
3692 for (j = 0; j < k; j++)
3694 out <<
' ' << vc + ints[i++];
3705 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
3716 out <<
"\nvertices\n" << nv <<
'\n';
3732 for (p = 1; p <
NRanks; p++)
3734 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
3738 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
3740 for (i = 0; i < nv; i++)
3745 out <<
' ' << vert[i*spaceDim+j];
3760 vert[i*spaceDim+j] =
vertices[i](j);
3765 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
3792 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
3800 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
3803 int i, j, k, nv, ne, p;
3811 out <<
"NETGEN_Neutral_Format\n";
3814 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3818 for (j = 0; j <
Dim; j++)
3824 for (p = 1; p <
NRanks; p++)
3826 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3828 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
3829 for (i = 0; i < nv; i++)
3831 for (j = 0; j <
Dim; j++)
3833 out <<
" " << vert[Dim*i+j];
3841 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3848 for (j = 0; j < nv; j++)
3850 out <<
" " << ind[j]+1;
3855 for (p = 1; p <
NRanks; p++)
3857 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3858 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3860 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
3861 for (i = 0; i < ne; i++)
3864 for (j = 0; j < 4; j++)
3866 out <<
" " << k+ints[i*4+j]+1;
3874 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3882 for (j = 0; j < nv; j++)
3884 out <<
" " << ind[j]+1;
3894 for (j = 0; j < nv; j++)
3896 out <<
" " << ind[j]+1;
3901 for (p = 1; p <
NRanks; p++)
3903 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3904 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3906 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
3907 for (i = 0; i < ne; i++)
3910 for (j = 0; j < 3; j++)
3912 out <<
" " << k+ints[i*3+j]+1;
3922 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3926 for (j = 0; j <
Dim; j++)
3930 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3934 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3935 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3941 for (j = 0; j < 4; j++)
3946 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
3949 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3950 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3952 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
3957 for (j = 0; j < 3; j++)
3962 for ( ; i < ne; i++)
3965 for (j = 0; j < 3; j++)
3970 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
3976 int i, j, k, nv, ne, p;
3982 int TG_nv, TG_ne, TG_nbe;
3989 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3992 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
3993 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3994 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3995 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3996 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
4002 <<
" " <<
vertices[i](2) <<
" 0.0\n";
4003 for (p = 1; p <
NRanks; p++)
4005 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4007 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4008 for (i = 0; i < nv; i++)
4009 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
4010 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
4019 out << i+1 <<
" " << 1;
4020 for (j = 0; j < nv; j++)
4022 out <<
" " << ind[j]+1;
4027 for (p = 1; p <
NRanks; p++)
4029 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4030 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4032 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
4033 for (i = 0; i < ne; i++)
4035 out << i+1 <<
" " << p+1;
4036 for (j = 0; j < 8; j++)
4038 out <<
" " << k+ints[i*8+j]+1;
4053 for (j = 0; j < nv; j++)
4055 out <<
" " << ind[j]+1;
4057 out <<
" 1.0 1.0 1.0 1.0\n";
4065 for (j = 0; j < nv; j++)
4067 out <<
" " << ind[j]+1;
4069 out <<
" 1.0 1.0 1.0 1.0\n";
4072 for (p = 1; p <
NRanks; p++)
4074 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4075 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4077 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
4078 for (i = 0; i < ne; i++)
4081 for (j = 0; j < 4; j++)
4083 out <<
" " << k+ints[i*4+j]+1;
4085 out <<
" 1.0 1.0 1.0 1.0\n";
4095 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4100 for (j = 0; j <
Dim; j++)
4104 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
4106 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4112 for (j = 0; j < 8; j++)
4117 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
4119 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
4121 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4126 for (j = 0; j < 4; j++)
4131 for ( ; i < ne; i++)
4134 for (j = 0; j < 4; j++)
4139 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
4145 int i, j, k, attr, nv, ne, p;
4154 out <<
"areamesh2\n\n";
4158 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4163 attr =
boundary[i]->GetAttribute();
4166 for (j = 0; j < v.
Size(); j++)
4168 out << v[j] + 1 <<
" ";
4178 for (j = 0; j < v.
Size(); j++)
4180 out << v[j] + 1 <<
" ";
4185 for (p = 1; p <
NRanks; p++)
4187 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4188 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4190 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
4191 for (i = 0; i < ne; i++)
4194 for (j = 0; j < 2; j++)
4196 out <<
" " << k+ints[i*2+j]+1;
4205 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4209 attr =
elements[i]->GetAttribute();
4211 out << 1 <<
" " << 3 <<
" ";
4212 for (j = 0; j < v.
Size(); j++)
4214 out << v[j] + 1 <<
" ";
4219 for (p = 1; p <
NRanks; p++)
4221 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4222 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
4224 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
4225 for (i = 0; i < ne; i++)
4227 out << p+1 <<
" " << 3;
4228 for (j = 0; j < 3; j++)
4230 out <<
" " << k+ints[i*3+j]+1;
4239 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4243 for (j = 0; j <
Dim; j++)
4249 for (p = 1; p <
NRanks; p++)
4251 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
4253 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
4254 for (i = 0; i < nv; i++)
4256 for (j = 0; j <
Dim; j++)
4258 out <<
" " << vert[Dim*i+j];
4268 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4271 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
4276 for (j = 0; j < 2; j++)
4281 for ( ; i < ne; i++)
4284 for (j = 0; j < 2; j++)
4289 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
4292 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4299 for (j = 0; j < 3; j++)
4304 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
4307 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
4311 for (j = 0; j <
Dim; j++)
4315 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
4325 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
4329 out <<
"Parallel Mesh Stats:" <<
'\n';
4335 h = pow(fabs(J.
Det()), 1.0/
double(
Dim));
4340 kappa_min = kappa_max =
kappa;
4344 if (h < h_min) { h_min = h; }
4345 if (h > h_max) { h_max = h; }
4346 if (kappa < kappa_min) { kappa_min =
kappa; }
4347 if (kappa > kappa_max) { kappa_max =
kappa; }
4351 double gh_min, gh_max, gk_min, gk_max;
4352 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
4353 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
4354 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
4355 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
4358 long mindata[5], maxdata[5], sumdata[5];
4374 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
4375 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
4376 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
4382 << setw(12) <<
"minimum"
4383 << setw(12) <<
"average"
4384 << setw(12) <<
"maximum"
4385 << setw(12) <<
"total" <<
'\n';
4387 << setw(12) << mindata[0]
4388 << setw(12) << sumdata[0]/
NRanks
4389 << setw(12) << maxdata[0]
4390 << setw(12) << sumdata[0] <<
'\n';
4392 << setw(12) << mindata[1]
4393 << setw(12) << sumdata[1]/
NRanks
4394 << setw(12) << maxdata[1]
4395 << setw(12) << sumdata[1] <<
'\n';
4398 << setw(12) << mindata[2]
4399 << setw(12) << sumdata[2]/
NRanks
4400 << setw(12) << maxdata[2]
4401 << setw(12) << sumdata[2] <<
'\n';
4403 << setw(12) << mindata[3]
4404 << setw(12) << sumdata[3]/
NRanks
4405 << setw(12) << maxdata[3]
4406 << setw(12) << sumdata[3] <<
'\n';
4407 out <<
" neighbors "
4408 << setw(12) << mindata[4]
4409 << setw(12) << sumdata[4]/
NRanks
4410 << setw(12) << maxdata[4] <<
'\n';
4413 << setw(12) <<
"minimum"
4414 << setw(12) <<
"maximum" <<
'\n';
4416 << setw(12) << gh_min
4417 << setw(12) << gh_max <<
'\n';
4419 << setw(12) << gk_min
4420 << setw(12) << gk_max <<
'\n';
4427 long local = value, global;
4428 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
4444 Printer(out,
"mfem_serial_mesh_end");
4452 out <<
"total_shared_edges " <<
shared_edges.Size() <<
'\n';
4456 out <<
"total_shared_faces " <<
shared_faces.Size() <<
'\n';
4463 out <<
"\n#group " << gr <<
"\nshared_vertices " << nv <<
'\n';
4464 for (
int i = 0; i < nv; i++)
4473 out <<
"\nshared_edges " << ne <<
'\n';
4474 for (
int i = 0; i < ne; i++)
4477 out << v[0] <<
' ' << v[1] <<
'\n';
4484 out <<
"\nshared_faces " << nf <<
'\n';
4485 for (
int i = 0; i < nf; i++)
4493 out <<
"\nmfem_mesh_end" << endl;
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
int GetNFaceNeighbors() const
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 SaveAsOne(std::ostream &out=std::cout)
Merge the local grid functions.
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.
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.
int GetFaceGeometryType(int Face) const
Array< Element * > face_nbr_elements
double Det() const
Calculates the determinant of the matrix (for 2x2 or 3x3 matrices)
Lists all edges/faces in the nonconforming mesh.
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 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.
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
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 GetElementVertices(int i, Array< int > &dofs) const
Returns the indices of the dofs of element i.
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)
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).
void GetFaceNbrElementVDofs(int i, Array< int > &vdofs) const
void ExchangeFaceNbrData()
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
void PrintAsOne(std::ostream &out=std::cout)
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
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)
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 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 partition when the serial mesh is being split initially.
const int * GetDofMap(int GeomType) const
Get the Cartesian to local H1 dof map.
const IntegrationRule & GetNodes() const
int Insert(IntegerSet &s)
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.
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.
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 PrintInfo(std::ostream &out=std::cout)
Print various parallel mesh stats.
virtual void QuadUniformRefinement()
Refine quadrilateral mesh.
virtual void HexUniformRefinement()
Refine hexahedral mesh.
void Printer(std::ostream &out=std::cout, std::string section_delimiter="") const
void Swap(Mesh &other, bool non_geometry=false)
Array< Element * > elements
double GetLength(int i, int j) const
Return the length of the segment from node i to node j.
void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
virtual void PrintXG(std::ostream &out=std::cout) const
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.
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.
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.
void PrintAsOneXG(std::ostream &out=std::cout)
Old mesh format (Netgen/Truegrid) version of 'PrintAsOne'.
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
Table * GetFaceToAllElementTable() const
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()
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
void Bcast(T *data, int layout)
Broadcast within each group where the master is the root. The data layout can be: ...
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)
int GroupNEdges(int group)
void GreenRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
ParFiniteElementSpace * ParFESpace() const
virtual void NURBSUniformRefinement()
Refine NURBS mesh.
virtual void Print(std::ostream &out=std::cout) const