12 #include "../config/config.hpp"
17 #include "../fem/fem.hpp"
18 #include "../general/sets.hpp"
19 #include "../general/sort_pairs.hpp"
26 ParMesh::ParMesh(
const ParMesh &pmesh,
bool copy_nodes)
28 group_svert(pmesh.group_svert),
29 group_sedge(pmesh.group_sedge),
30 group_sface(pmesh.group_sface),
59 MFEM_VERIFY(pmesh.
pncmesh == NULL,
60 "copying non-conforming meshes is not implemented");
65 if (pmesh.
Nodes && copy_nodes)
75 Nodes->MakeOwner(fec_copy);
76 *Nodes = *pmesh.
Nodes;
98 int* partition =
new int[mesh.
GetNE()];
99 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++)
464 if (face_group[i] >= 0)
472 for (i = 0; i < face_group.Size(); i++)
473 if (face_group[i] >= 0)
483 for (i = 0; i < edge_element->
Size(); i++)
484 if (edge_element->
GetRow(i)[0] >= 0)
492 for (i = 0; i < edge_element->
Size(); i++)
493 if (edge_element->
GetRow(i)[0] >= 0)
502 for (i = 0; i < vert_element->
Size(); i++)
503 if (vert_element->
GetI()[i] >= 0)
511 for (i = 0; i < vert_element->
Size(); i++)
512 if (vert_element->
GetI()[i] >= 0)
525 for (i = 0; i < face_group.Size(); i++)
526 if (face_group[i] >= 0)
531 for (j = 0; j < nv; j++)
533 v[j] = vert_global_local[v[j]];
538 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
546 int re[2], type, flag, *tv;
554 case 1: v[0] = tv[1]; v[1] = tv[2]; v[2] = tv[3];
556 case 4: v[0] = tv[3]; v[1] = tv[1]; v[2] = tv[2];
558 case 5: v[0] = tv[2]; v[1] = tv[3]; v[2] = tv[1];
565 case 2: v[0] = tv[2]; v[1] = tv[0]; v[2] = tv[3];
567 case 3: v[0] = tv[0]; v[1] = tv[3]; v[2] = tv[2];
569 case 5: v[0] = tv[3]; v[1] = tv[2]; v[2] = tv[0];
574 v[0] = tv[0]; v[1] = tv[1]; v[2] = tv[3];
577 v[0] = tv[1]; v[1] = tv[0]; v[2] = tv[2];
585 if (
MyRank == partitioning[gl_el2])
587 const int t = v[0]; v[0] = v[1]; v[1] = t;
594 (*faces_tbl)(v[0], v[1], v[2], v[3]);
612 for (i = 0; i < edge_element->
Size(); i++)
613 if (edge_element->
GetRow(i)[0] >= 0)
618 new Segment(vert_global_local[vert[0]],
619 vert_global_local[vert[1]], 1);
622 v_to_v(vert_global_local[vert[0]],
623 vert_global_local[vert[1]])) < 0)
625 cerr <<
"\n\n\n" <<
MyRank <<
": ParMesh::ParMesh: "
626 <<
"ERROR in v_to_v\n\n" << endl;
640 for (i = 0; i < vert_element->
Size(); i++)
641 if (vert_element->
GetI()[i] >= 0)
643 svert_lvert[svert_counter++] = vert_global_local[i];
665 for (i = 0; i < mesh.
GetNE(); i++)
666 if (partitioning[i] ==
MyRank)
669 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
670 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
676 if (partitioning_ == NULL)
678 delete [] partitioning;
685 : MyComm(pncmesh.MyComm)
686 , NRanks(pncmesh.NRanks)
687 , MyRank(pncmesh.MyRank)
702 o = (v[0] < v[1]) ? (+1) : (-1);
727 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
748 int number_of_splittings = 0;
751 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
753 number_of_splittings++;
754 if ((m = v_to_v(v[1], v[2])) != -1 && middle[m] != -1)
757 number_of_splittings++;
759 if ((m = v_to_v(v[2], v[0])) != -1 && middle[m] != -1)
761 number_of_splittings++;
764 switch (number_of_splittings)
769 number_of_splittings++;
773 number_of_splittings++;
778 return number_of_splittings;
784 if (HYPRE_AssumedPartitionCheck())
787 MPI_Scan(loc_sizes, temp.
GetData(), N, HYPRE_MPI_INT, MPI_SUM,
MyComm);
788 for (
int i = 0; i < N; i++)
791 (*offsets[i])[0] = temp[i] - loc_sizes[i];
792 (*offsets[i])[1] = temp[i];
795 for (
int i = 0; i < N; i++)
797 (*offsets[i])[2] = temp[i];
799 MFEM_VERIFY((*offsets[i])[0] >= 0 && (*offsets[i])[1] >= 0,
800 "overflow in offsets");
806 MPI_Allgather(loc_sizes, N, HYPRE_MPI_INT, temp.
GetData(), N,
808 for (
int i = 0; i < N; i++)
813 for (
int j = 0; j <
NRanks; j++)
815 offs[j+1] = offs[j] + temp[i+N*j];
819 "overflow in offsets");
841 for (
int j = 0; j < nv; j++)
860 for (
int j = 0; j < n; j++)
862 pointmat(k,j) = (pNodes->
FaceNbrData())(vdofs[n*k+j]);
870 MFEM_ABORT(
"Nodes are not ParGridFunction!");
931 int num_face_nbrs = 0;
933 if (gr_sface->
RowSize(g-1) > 0)
940 if (num_face_nbrs == 0)
950 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
951 if (gr_sface->
RowSize(g-1) > 0)
955 mfem_error(
"ParMesh::ExchangeFaceNbrData() : "
956 "group size is not 2!");
959 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
961 rank_group[counter].two = g;
965 SortPairs<int, int>(rank_group, rank_group.
Size());
967 for (
int fn = 0; fn < num_face_nbrs; fn++)
973 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
974 MPI_Request *send_requests = requests;
975 MPI_Request *recv_requests = requests + num_face_nbrs;
976 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
978 int *nbr_data =
new int[6*num_face_nbrs];
979 int *nbr_send_data = nbr_data;
980 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
987 Table send_face_nbr_elemdata, send_face_nbr_facedata;
991 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
992 send_face_nbr_facedata.
MakeI(num_face_nbrs);
993 for (
int fn = 0; fn < num_face_nbrs; fn++)
996 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
997 int *sface = gr_sface->
GetRow(nbr_group-1);
998 for (
int i = 0; i < num_sfaces; i++)
1000 int lface = s2l_face[sface[i]];
1002 if (el_marker[el] != fn)
1007 const int nv =
elements[el]->GetNVertices();
1008 const int *v =
elements[el]->GetVertices();
1009 for (
int j = 0; j < nv; j++)
1010 if (vertex_marker[v[j]] != fn)
1012 vertex_marker[v[j]] = fn;
1023 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
1028 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1029 &send_requests[fn]);
1030 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag,
MyComm,
1031 &recv_requests[fn]);
1035 send_face_nbr_elemdata.
MakeJ();
1036 send_face_nbr_facedata.
MakeJ();
1039 for (
int fn = 0; fn < num_face_nbrs; fn++)
1042 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1043 int *sface = gr_sface->
GetRow(nbr_group-1);
1044 for (
int i = 0; i < num_sfaces; i++)
1046 int lface = s2l_face[sface[i]];
1048 if (el_marker[el] != fn)
1053 const int nv =
elements[el]->GetNVertices();
1054 const int *v =
elements[el]->GetVertices();
1055 for (
int j = 0; j < nv; j++)
1056 if (vertex_marker[v[j]] != fn)
1058 vertex_marker[v[j]] = fn;
1074 const int *sf_v =
shared_faces[sface[i]]->GetVertices();
1095 for (
int fn = 0; fn < num_face_nbrs; fn++)
1101 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
1102 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
1103 int *facedata = send_face_nbr_facedata.
GetRow(fn);
1105 for (
int i = 0; i < num_verts; i++)
1107 vertex_marker[verts[i]] = i;
1110 for (
int el = 0; el < num_elems; el++)
1112 const int nv =
elements[el]->GetNVertices();
1114 for (
int j = 0; j < nv; j++)
1116 elemdata[j] = vertex_marker[elemdata[j]];
1120 el_marker[elems[el]] = el;
1123 for (
int i = 0; i < num_sfaces; i++)
1125 facedata[2*i] = el_marker[facedata[2*i]];
1129 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1132 Table recv_face_nbr_elemdata;
1137 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
1140 for (
int fn = 0; fn < num_face_nbrs; fn++)
1148 recv_face_nbr_elemdata.
MakeJ();
1150 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1153 for (
int fn = 0; fn < num_face_nbrs; fn++)
1158 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
1159 send_face_nbr_elemdata.
RowSize(fn),
1160 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1162 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
1163 recv_face_nbr_elemdata.
RowSize(fn),
1164 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1172 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1174 if (fn == MPI_UNDEFINED)
1182 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
1184 for (
int i = 0; i < num_elems; i++)
1190 for (
int j = 0; j < nv; j++)
1192 recv_elemdata[j] += vert_off;
1195 recv_elemdata += nv;
1200 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1203 recv_face_nbr_facedata.
SetSize(
1205 for (
int fn = 0; fn < num_face_nbrs; fn++)
1210 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
1211 send_face_nbr_facedata.
RowSize(fn),
1212 MPI_INT, nbr_rank, tag,
MyComm, &send_requests[fn]);
1215 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
1216 send_face_nbr_facedata.
RowSize(fn),
1217 MPI_INT, nbr_rank, tag,
MyComm, &recv_requests[fn]);
1224 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1226 if (fn == MPI_UNDEFINED)
1233 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1234 int *sface = gr_sface->
GetRow(nbr_group-1);
1236 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
1238 for (
int i = 0; i < num_sfaces; i++)
1240 int lface = s2l_face[sface[i]];
1242 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
1243 int info = facedata[2*i+1];
1251 int nbr_ori = info%64, nbr_v[4];
1253 const int *sf_v =
shared_faces[sface[i]]->GetVertices();
1259 for (
int j = 0; j < 3; j++)
1261 nbr_v[perm[j]] = sf_v[j];
1270 for (
int j = 0; j < 4; j++)
1272 nbr_v[perm[j]] = sf_v[j];
1278 info = 64*(info/64) + nbr_ori;
1284 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1305 else if (
Nodes == NULL)
1315 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1316 MPI_Request *send_requests = requests;
1317 MPI_Request *recv_requests = requests + num_face_nbrs;
1318 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1322 for (
int i = 0; i < send_vertices.Size(); i++)
1328 for (
int fn = 0; fn < num_face_nbrs; fn++)
1335 MPI_DOUBLE, nbr_rank, tag,
MyComm, &send_requests[fn]);
1340 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
1343 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1344 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1352 MFEM_VERIFY(pNodes != NULL,
"Nodes are not ParGridFunction!");
1363 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
1405 for (
int i = 0; i < s2l_face->
Size(); i++)
1420 for (
int i = 0; i < s2l_face->
Size(); i++)
1422 int lface = (*s2l_face)[i];
1423 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
1447 #if 0 // TODO: handle the case of non-interpolatory Nodes
1474 int local_face = is_ghost ? nc_info->
MasterFace : FaceNo;
1523 if (is_ghost || fill2)
1532 std::swap(pm(0,0), pm(0,1));
1533 std::swap(pm(1,0), pm(1,1));
1560 MFEM_ASSERT(
Dim > 1,
"");
1579 MFEM_ASSERT(
Dim > 1,
"");
1582 return sface < csize
1584 : shared.
slaves[sface - csize].index;
1638 MFEM_ABORT(
"Local and nonconforming refinements cannot be mixed.");
1647 int uniform_refinement = 0;
1651 uniform_refinement = 1;
1666 for (i = 0; i < marked_el.
Size(); i++)
1668 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1672 for (i = 0; i < marked_el.
Size(); i++)
1674 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1677 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1681 for (i = 0; i < marked_el.
Size(); i++)
1683 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1686 Bisection(j, v_to_v, NULL, NULL, middle);
1688 Bisection(j, v_to_v, NULL, NULL, middle);
1690 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1692 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1698 int need_refinement;
1699 int refined_edge[5][3] =
1707 int faces_in_group, max_faces_in_group = 0;
1709 int **face_splittings =
new int*[
GetNGroups()-1];
1713 face_splittings[i] =
new int[faces_in_group];
1714 if (faces_in_group > max_faces_in_group)
1716 max_faces_in_group = faces_in_group;
1719 int neighbor, *iBuf =
new int[max_faces_in_group];
1723 MPI_Request request;
1726 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1727 int ref_loops_all = 0, ref_loops_par = 0;
1731 need_refinement = 0;
1734 if (
elements[i]->NeedRefinement(v_to_v, middle))
1736 need_refinement = 1;
1737 Bisection(i, v_to_v, NULL, NULL, middle);
1740 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1744 if (uniform_refinement)
1751 if (need_refinement == 0)
1753 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1757 const int tag = 293;
1763 faces_in_group = group_faces.
Size();
1765 if (faces_in_group == 0) {
continue; }
1767 for (j = 0; j < faces_in_group; j++)
1769 face_splittings[i][j] =
1775 MPI_Isend(face_splittings[i], faces_in_group, MPI_INT,
1776 neighbor, tag,
MyComm, &request);
1783 faces_in_group = group_faces.
Size();
1784 if (faces_in_group == 0) {
continue; }
1788 MPI_Recv(iBuf, faces_in_group, MPI_INT, neighbor,
1791 for (j = 0; j < faces_in_group; j++)
1793 if (iBuf[j] == face_splittings[i][j]) {
continue; }
1796 for (
int k = 0; k < 3; k++)
1798 if (refined_edge[iBuf[j]][k] != 1 ||
1799 refined_edge[face_splittings[i][j]][k] != 0)
1802 int ind[2] = { v[k], v[(k+1)%3] };
1803 int ii = v_to_v(ind[0], ind[1]);
1804 if (middle[ii] == -1)
1806 need_refinement = 1;
1815 i = need_refinement;
1816 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
1819 while (need_refinement == 1);
1821 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1823 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
1826 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
1827 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
1835 delete [] face_splittings[i];
1837 delete [] face_splittings;
1843 need_refinement = 0;
1846 if (
boundary[i]->NeedRefinement(v_to_v, middle))
1848 need_refinement = 1;
1853 while (need_refinement == 1);
1857 " (NumOfBdrElements != boundary.Size())");
1868 int refinement_edges[2], type, flag;
1893 int uniform_refinement = 0;
1897 uniform_refinement = 1;
1906 int *edge1 =
new int[nedges];
1907 int *edge2 =
new int[nedges];
1908 int *middle =
new int[nedges];
1910 for (i = 0; i < nedges; i++)
1912 edge1[i] = edge2[i] = middle[i] = -1;
1917 int *v =
elements[i]->GetVertices();
1918 for (j = 0; j < 3; j++)
1920 int ind = v_to_v(v[j], v[(j+1)%3]);
1921 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
1926 for (i = 0; i < marked_el.
Size(); i++)
1932 int need_refinement;
1933 int edges_in_group, max_edges_in_group = 0;
1935 int **edge_splittings =
new int*[
GetNGroups()-1];
1939 edge_splittings[i] =
new int[edges_in_group];
1940 if (edges_in_group > max_edges_in_group)
1942 max_edges_in_group = edges_in_group;
1945 int neighbor, *iBuf =
new int[max_edges_in_group];
1949 MPI_Request request;
1954 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1955 int ref_loops_all = 0, ref_loops_par = 0;
1959 need_refinement = 0;
1960 for (i = 0; i < nedges; i++)
1961 if (middle[i] != -1 && edge1[i] != -1)
1963 need_refinement = 1;
1966 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1970 if (uniform_refinement)
1977 if (need_refinement == 0)
1979 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
1988 edges_in_group = group_edges.
Size();
1990 if (edges_in_group != 0)
1992 for (j = 0; j < edges_in_group; j++)
1993 edge_splittings[i][j] =
2005 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
2006 neighbor, 0,
MyComm, &request);
2014 edges_in_group = group_edges.
Size();
2015 if (edges_in_group != 0)
2026 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
2027 MPI_ANY_TAG,
MyComm, &status);
2029 for (j = 0; j < edges_in_group; j++)
2030 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
2033 int ii = v_to_v(v[0], v[1]);
2034 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2035 if (middle[ii] != -1)
2036 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
2039 need_refinement = 1;
2041 for (
int c = 0; c < 2; c++)
2050 i = need_refinement;
2051 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR,
MyComm);
2054 while (need_refinement == 1);
2056 #ifdef MFEM_DEBUG_PARMESH_LOCALREF
2058 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0,
MyComm);
2061 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
2062 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
2069 delete [] edge_splittings[i];
2071 delete [] edge_splittings;
2076 int v1[2], v2[2], bisect, temp;
2078 for (i = 0; i < temp; i++)
2080 int *v =
boundary[i]->GetVertices();
2081 bisect = v_to_v(v[0], v[1]);
2082 if (middle[bisect] != -1)
2087 v1[0] = v[0]; v1[1] = middle[bisect];
2088 v2[0] = middle[bisect]; v2[1] = v[1];
2094 mfem_error(
"Only bisection of segment is implemented for bdr"
2124 for (j = 0; j < marked_el.
Size(); j++)
2129 int new_v = cnv + j, new_e = cne + j;
2138 static double seg_children[3*2] = { 0.0,1.0, 0.0,0.5, 0.5,1.0 };
2160 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
2161 "supported. Project the NURBS to Nodes first.");
2166 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
2167 "(you need to initialize the ParMesh from a nonconforming "
2191 Swap(*pmesh2,
false);
2208 double threshold,
int nc_limit,
int op)
2221 for (
int i = 0; i < dt.
Size(); i++)
2223 if (nc_limit > 0 && !level_ok[i]) {
continue; }
2225 const int* fine = dt.
GetRow(i);
2229 for (
int j = 0; j < size; j++)
2231 MFEM_VERIFY(fine[j] < elem_error.
Size(),
"");
2233 double err_fine = elem_error[fine[j]];
2236 case 0: error = std::min(error, err_fine);
break;
2237 case 1: error += err_fine;
break;
2238 case 2: error = std::max(error, err_fine);
break;
2242 if (error < threshold) { derefs.
Append(i); }
2259 MFEM_ABORT(
"Load balancing is currently not supported for conforming"
2273 Swap(*pmesh2,
false);
2290 int i, attr, newv[3], ind, f_ind, *v;
2293 Array<int> group_verts, group_edges, group_faces;
2301 int *I_group_svert, *J_group_svert;
2302 int *I_group_sedge, *J_group_sedge;
2303 int *I_group_sface, *J_group_sface;
2313 I_group_sface = NULL;
2316 I_group_svert[0] = I_group_svert[1] = 0;
2317 I_group_sedge[0] = I_group_sedge[1] = 0;
2320 I_group_sface[0] = I_group_sface[1] = 0;
2337 J_group_sface = NULL;
2341 J_group_svert = J_group_sedge = J_group_sface = NULL;
2344 for (group = 0; group <
GetNGroups()-1; group++)
2355 ind = middle[v_to_v(v[0], v[1])];
2372 ind = middle[v_to_v(v[0], v[1])];
2380 f_ind = group_faces.
Size();
2383 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2388 ind = middle[v_to_v(v[0], v[1])];
2397 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2403 ind = middle[v_to_v(v[0], v[1])];
2412 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2418 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
2419 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
2422 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
2426 J = J_group_svert+I_group_svert[group];
2427 for (i = 0; i < group_verts.
Size(); i++)
2429 J[i] = group_verts[i];
2431 J = J_group_sedge+I_group_sedge[group];
2432 for (i = 0; i < group_edges.
Size(); i++)
2434 J[i] = group_edges[i];
2438 J = J_group_sface+I_group_sface[group];
2439 for (i = 0; i < group_faces.
Size(); i++)
2441 J[i] = group_faces[i];
2491 int i, attr, ind, *v;
2496 int *I_group_svert, *J_group_svert;
2497 int *I_group_sedge, *J_group_sedge;
2502 I_group_svert[0] = I_group_svert[1] = 0;
2503 I_group_sedge[0] = I_group_sedge[1] = 0;
2510 for (group = 0; group <
GetNGroups()-1; group++)
2530 I_group_svert[group+1] = I_group_svert[group] + sverts.
Size();
2531 I_group_sedge[group+1] = I_group_sedge[group] + sedges.
Size();
2534 J = J_group_svert+I_group_svert[group];
2535 for (i = 0; i < sverts.
Size(); i++)
2539 J = J_group_sedge+I_group_sedge[group];
2540 for (i = 0; i < sedges.
Size(); i++)
2583 int i, attr, newv[4], ind, m[5];
2587 Array<int> group_verts, group_edges, group_faces;
2589 int *I_group_svert, *J_group_svert;
2590 int *I_group_sedge, *J_group_sedge;
2591 int *I_group_sface, *J_group_sface;
2597 I_group_svert[0] = I_group_svert[1] = 0;
2598 I_group_sedge[0] = I_group_sedge[1] = 0;
2599 I_group_sface[0] = I_group_sface[1] = 0;
2609 for (group = 0; group <
GetNGroups()-1; group++)
2620 ind = oedge + v_to_v(v[0], v[1]);
2627 newv[0] = v[0]; newv[1] = ind;
2635 m[0] = oface+(*faces_tbl)(v[0], v[1], v[2], v[3]);
2640 m[1] = oedge + v_to_v(v[0], v[1]);
2641 m[2] = oedge + v_to_v(v[1], v[2]);
2642 m[3] = oedge + v_to_v(v[2], v[3]);
2643 m[4] = oedge + v_to_v(v[3], v[0]);
2653 newv[0] = v[0]; newv[1] = m[1]; newv[2] = m[0]; newv[3] = m[4];
2663 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
2664 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
2665 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
2668 J = J_group_svert+I_group_svert[group];
2669 for (i = 0; i < group_verts.
Size(); i++)
2671 J[i] = group_verts[i];
2673 J = J_group_sedge+I_group_sedge[group];
2674 for (i = 0; i < group_edges.
Size(); i++)
2676 J[i] = group_edges[i];
2678 J = J_group_sface+I_group_sface[group];
2679 for (i = 0; i < group_faces.
Size(); i++)
2681 J[i] = group_faces[i];
2699 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
2715 cout <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
2721 MFEM_ASSERT(
Dim ==
spaceDim,
"2D manifolds not supported");
2727 out <<
"NETGEN_Neutral_Format\n";
2732 for (j = 0; j <
Dim; j++)
2745 out <<
elements[i]->GetAttribute();
2746 for (j = 0; j < nv; j++)
2748 out <<
" " << ind[j]+1;
2760 out <<
boundary[i]->GetAttribute();
2761 for (j = 0; j < nv; j++)
2763 out <<
" " << ind[j]+1;
2773 for (j = 0; j < nv; j++)
2775 out <<
" " << ind[j]+1;
2788 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
2790 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
2791 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
2792 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
2797 <<
" " <<
vertices[i](2) <<
" 0.0\n";
2804 out << i+1 <<
" " <<
elements[i]->GetAttribute();
2805 for (j = 0; j < nv; j++)
2807 out <<
" " << ind[j]+1;
2817 out <<
boundary[i]->GetAttribute();
2818 for (j = 0; j < nv; j++)
2820 out <<
" " << ind[j]+1;
2822 out <<
" 1.0 1.0 1.0 1.0\n";
2831 for (j = 0; j < nv; j++)
2833 out <<
" " << ind[j]+1;
2835 out <<
" 1.0 1.0 1.0 1.0\n";
2844 out <<
"areamesh2\n\n";
2851 attr =
boundary[i]->GetAttribute();
2854 for (j = 0; j < v.
Size(); j++)
2856 out << v[j] + 1 <<
" ";
2866 for (j = 0; j < v.
Size(); j++)
2868 out << v[j] + 1 <<
" ";
2877 attr =
elements[i]->GetAttribute();
2893 for (j = 0; j < v.
Size(); j++)
2895 out << v[j] + 1 <<
" ";
2904 for (j = 0; j <
Dim; j++)
2929 bool print_shared =
true;
2930 int i, j, shared_bdr_attr;
2941 s2l_face = &nc_shared_faces;
2948 for (
unsigned i = 0; i < sfaces.
conforming.size(); i++)
2951 if (index < nfaces) { nc_shared_faces.
Append(index); }
2953 for (
unsigned i = 0; i < sfaces.
masters.size(); i++)
2956 int index = sfaces.
masters[i].index;
2957 if (index < nfaces) { nc_shared_faces.
Append(index); }
2959 for (
unsigned i = 0; i < sfaces.
slaves.size(); i++)
2961 int index = sfaces.
slaves[i].index;
2962 if (index < nfaces) { nc_shared_faces.
Append(index); }
2973 out <<
"MFEM mesh v1.0\n";
2977 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
2982 "# TETRAHEDRON = 4\n"
2986 out <<
"\ndimension\n" <<
Dim
2994 if (print_shared &&
Dim > 1)
2996 num_bdr_elems += s2l_face->
Size();
2998 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
3004 if (print_shared &&
Dim > 1)
3012 shared_bdr_attr =
MyRank + 1;
3014 for (i = 0; i < s2l_face->
Size(); i++)
3017 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
3049 for (
int i = 0; i < nv; i++)
3057 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
3065 out <<
"MFEM mesh v1.0\n";
3069 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
3074 "# TETRAHEDRON = 4\n"
3078 out <<
"\ndimension\n" <<
Dim;
3082 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3085 out <<
"\n\nelements\n" << ne <<
'\n';
3089 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
3093 for (j = 0; j < nv; j++)
3100 for (p = 1; p <
NRanks; p++)
3102 MPI_Recv(nv_ne, 2, MPI_INT, p, 444,
MyComm, &status);
3106 MPI_Recv(&ints[0], ne, MPI_INT, p, 445,
MyComm, &status);
3108 for (i = 0; i < ne; )
3111 out << p+1 <<
' ' << ints[i];
3114 for (j = 0; j < k; j++)
3116 out <<
' ' << vc + ints[i++];
3129 ne += 1 +
elements[i]->GetNVertices();
3132 MPI_Send(nv_ne, 2, MPI_INT, 0, 444,
MyComm);
3140 MFEM_ASSERT(ints.
Size() == ne,
"");
3143 MPI_Send(&ints[0], ne, MPI_INT, 0, 445,
MyComm);
3166 dump_element(
boundary[i], ints); ne++;
3171 for (i = 0; i < shared.
Size(); i++)
3173 dump_element(shared[i], ints); ne++;
3180 for (i = 0; i < (int) list.
conforming.size(); i++)
3183 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3185 for (i = 0; i < (int) list.
masters.size(); i++)
3187 int index = list.
masters[i].index;
3188 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3190 for (i = 0; i < (int) list.
slaves.size(); i++)
3192 int index = list.
slaves[i].index;
3193 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3197 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3200 out <<
"\nboundary\n" << k <<
'\n';
3202 for (p = 0; p <
NRanks; p++)
3206 MPI_Recv(nv_ne, 2, MPI_INT, p, 446,
MyComm, &status);
3210 MPI_Recv(ints.
GetData(), ne, MPI_INT, p, 447,
MyComm, &status);
3218 for (i = 0; i < ne; )
3221 out << p+1 <<
' ' << ints[i];
3224 for (j = 0; j < k; j++)
3226 out <<
' ' << vc + ints[i++];
3237 MPI_Send(nv_ne, 2, MPI_INT, 0, 446,
MyComm);
3248 out <<
"\nvertices\n" << nv <<
'\n';
3264 for (p = 1; p <
NRanks; p++)
3266 MPI_Recv(&nv, 1, MPI_INT, p, 448,
MyComm, &status);
3270 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449,
MyComm, &status);
3272 for (i = 0; i < nv; i++)
3277 out <<
' ' << vert[i*spaceDim+j];
3292 vert[i*spaceDim+j] =
vertices[i](j);
3297 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449,
MyComm);
3324 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
3332 MFEM_ASSERT(
Dim ==
spaceDim,
"2D Manifolds not supported.");
3335 int i, j, k, nv, ne, p;
3343 out <<
"NETGEN_Neutral_Format\n";
3346 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3350 for (j = 0; j <
Dim; j++)
3356 for (p = 1; p <
NRanks; p++)
3358 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3360 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
3361 for (i = 0; i < nv; i++)
3363 for (j = 0; j <
Dim; j++)
3365 out <<
" " << vert[Dim*i+j];
3373 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3380 for (j = 0; j < nv; j++)
3382 out <<
" " << ind[j]+1;
3387 for (p = 1; p <
NRanks; p++)
3389 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3390 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3392 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
3393 for (i = 0; i < ne; i++)
3396 for (j = 0; j < 4; j++)
3398 out <<
" " << k+ints[i*4+j]+1;
3406 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3414 for (j = 0; j < nv; j++)
3416 out <<
" " << ind[j]+1;
3426 for (j = 0; j < nv; j++)
3428 out <<
" " << ind[j]+1;
3433 for (p = 1; p <
NRanks; p++)
3435 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3436 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3438 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
3439 for (i = 0; i < ne; i++)
3442 for (j = 0; j < 3; j++)
3444 out <<
" " << k+ints[i*3+j]+1;
3454 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3458 for (j = 0; j <
Dim; j++)
3462 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3466 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3467 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3473 for (j = 0; j < 4; j++)
3478 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447,
MyComm);
3481 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3482 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3484 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
3489 for (j = 0; j < 3; j++)
3494 for ( ; i < ne; i++)
3497 for (j = 0; j < 3; j++)
3502 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447,
MyComm);
3508 int i, j, k, nv, ne, p;
3514 int TG_nv, TG_ne, TG_nbe;
3521 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3524 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
3525 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3526 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3527 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3528 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
3534 <<
" " <<
vertices[i](2) <<
" 0.0\n";
3535 for (p = 1; p <
NRanks; p++)
3537 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3539 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
3540 for (i = 0; i < nv; i++)
3541 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
3542 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
3551 out << i+1 <<
" " << 1;
3552 for (j = 0; j < nv; j++)
3554 out <<
" " << ind[j]+1;
3559 for (p = 1; p <
NRanks; p++)
3561 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3562 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3564 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447,
MyComm, &status);
3565 for (i = 0; i < ne; i++)
3567 out << i+1 <<
" " << p+1;
3568 for (j = 0; j < 8; j++)
3570 out <<
" " << k+ints[i*8+j]+1;
3585 for (j = 0; j < nv; j++)
3587 out <<
" " << ind[j]+1;
3589 out <<
" 1.0 1.0 1.0 1.0\n";
3597 for (j = 0; j < nv; j++)
3599 out <<
" " << ind[j]+1;
3601 out <<
" 1.0 1.0 1.0 1.0\n";
3604 for (p = 1; p <
NRanks; p++)
3606 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3607 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3609 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447,
MyComm, &status);
3610 for (i = 0; i < ne; i++)
3613 for (j = 0; j < 4; j++)
3615 out <<
" " << k+ints[i*4+j]+1;
3617 out <<
" 1.0 1.0 1.0 1.0\n";
3627 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3632 for (j = 0; j <
Dim; j++)
3636 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445,
MyComm);
3638 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3644 for (j = 0; j < 8; j++)
3649 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447,
MyComm);
3651 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444,
MyComm);
3653 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
3658 for (j = 0; j < 4; j++)
3663 for ( ; i < ne; i++)
3666 for (j = 0; j < 4; j++)
3671 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447,
MyComm);
3677 int i, j, k, attr, nv, ne, p;
3686 out <<
"areamesh2\n\n";
3690 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3695 attr =
boundary[i]->GetAttribute();
3698 for (j = 0; j < v.
Size(); j++)
3700 out << v[j] + 1 <<
" ";
3710 for (j = 0; j < v.
Size(); j++)
3712 out << v[j] + 1 <<
" ";
3717 for (p = 1; p <
NRanks; p++)
3719 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3720 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3722 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447,
MyComm, &status);
3723 for (i = 0; i < ne; i++)
3726 for (j = 0; j < 2; j++)
3728 out <<
" " << k+ints[i*2+j]+1;
3737 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3741 attr =
elements[i]->GetAttribute();
3743 out << 1 <<
" " << 3 <<
" ";
3744 for (j = 0; j < v.
Size(); j++)
3746 out << v[j] + 1 <<
" ";
3751 for (p = 1; p <
NRanks; p++)
3753 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3754 MPI_Recv(&ne, 1, MPI_INT, p, 446,
MyComm, &status);
3756 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447,
MyComm, &status);
3757 for (i = 0; i < ne; i++)
3759 out << p+1 <<
" " << 3;
3760 for (j = 0; j < 3; j++)
3762 out <<
" " << k+ints[i*3+j]+1;
3771 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3775 for (j = 0; j <
Dim; j++)
3781 for (p = 1; p <
NRanks; p++)
3783 MPI_Recv(&nv, 1, MPI_INT, p, 444,
MyComm, &status);
3785 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445,
MyComm, &status);
3786 for (i = 0; i < nv; i++)
3788 for (j = 0; j <
Dim; j++)
3790 out <<
" " << vert[Dim*i+j];
3800 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3803 MPI_Send(&ne, 1, MPI_INT, 0, 446,
MyComm);
3808 for (j = 0; j < 2; j++)
3813 for ( ; i < ne; i++)
3816 for (j = 0; j < 2; j++)
3821 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447,
MyComm);
3824 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3831 for (j = 0; j < 3; j++)
3836 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447,
MyComm);
3839 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
3843 for (j = 0; j <
Dim; j++)
3847 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3857 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
3861 out <<
"Parallel Mesh Stats:" <<
'\n';
3867 h = pow(fabs(J.
Det()), 1.0/
double(
Dim));
3872 kappa_min = kappa_max =
kappa;
3876 if (h < h_min) { h_min = h; }
3877 if (h > h_max) { h_max = h; }
3878 if (kappa < kappa_min) { kappa_min =
kappa; }
3879 if (kappa > kappa_max) { kappa_max =
kappa; }
3883 double gh_min, gh_max, gk_min, gk_max;
3884 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
3885 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
3886 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0,
MyComm);
3887 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0,
MyComm);
3890 long mindata[5], maxdata[5], sumdata[5];
3906 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0,
MyComm);
3907 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0,
MyComm);
3908 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0,
MyComm);
3914 << setw(12) <<
"minimum"
3915 << setw(12) <<
"average"
3916 << setw(12) <<
"maximum"
3917 << setw(12) <<
"total" <<
'\n';
3919 << setw(12) << mindata[0]
3920 << setw(12) << sumdata[0]/
NRanks
3921 << setw(12) << maxdata[0]
3922 << setw(12) << sumdata[0] <<
'\n';
3924 << setw(12) << mindata[1]
3925 << setw(12) << sumdata[1]/
NRanks
3926 << setw(12) << maxdata[1]
3927 << setw(12) << sumdata[1] <<
'\n';
3930 << setw(12) << mindata[2]
3931 << setw(12) << sumdata[2]/
NRanks
3932 << setw(12) << maxdata[2]
3933 << setw(12) << sumdata[2] <<
'\n';
3935 << setw(12) << mindata[3]
3936 << setw(12) << sumdata[3]/
NRanks
3937 << setw(12) << maxdata[3]
3938 << setw(12) << sumdata[3] <<
'\n';
3939 out <<
" neighbors "
3940 << setw(12) << mindata[4]
3941 << setw(12) << sumdata[4]/
NRanks
3942 << setw(12) << maxdata[4] <<
'\n';
3945 << setw(12) <<
"minimum"
3946 << setw(12) <<
"maximum" <<
'\n';
3948 << setw(12) << gh_min
3949 << setw(12) << gh_max <<
'\n';
3951 << setw(12) << gk_min
3952 << setw(12) << gk_max <<
'\n';
3959 long local = value, global;
3960 MPI_Allreduce(&local, &global, 1, MPI_LONG, MPI_SUM,
MyComm);
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)
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 Recreate(const int n, const int *p)
Class for integration rule.
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)
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.
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
void CheckBdrElementOrientation(bool fix_it=true)
Check the orientation of the boundary elements.
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)
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.
Element * NewElement(int geom)
FaceElementTransformations FaceElemTr
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.
bool Nonconforming() const
const FiniteElement * GetFaceNbrFE(int i) const
Array< int > face_nbr_elements_offset
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 GetFaceTransformation(int i, IsoparametricTransformation *FTr)
void CreateRefinementFlag(int refinement_edges[2], int type, int flag=0)
std::vector< Master > masters
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 &)
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.
int InitialPartition(int index) const
Helper to get the partition when the serial mesh is being split initially.
void CheckElementOrientation(bool fix_it=true)
Check the orientation of the elements.
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.
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
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.
void GetBdrElementFace(int i, int *, int *) const
Return the index and the orientation of the face of bdr element i. (3D)
virtual void Print(std::ostream &out=std::cout) const
Print the mesh to the given stream using the default MFEM mesh format.
Array< int > bdr_attributes
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 degrees of freedom in the FE space.
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.
void SetSubVector(const Array< int > &dofs, const Vector &elemvect)
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 Swap(Mesh &other, bool non_geometry=false)
Array< Element * > elements
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)
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
void GetFaceNbrElementTransformation(int i, IsoparametricTransformation *ElTr)
NURBSExtension * NURBSext
virtual const char * Name() const
virtual void Refine(const Array< Refinement > &refinements)
void GroupFace(int group, int i, int &face, int &o)
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
void ExchangeFaceNbrNodes()
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)
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()
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 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
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'.
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 *)
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.
Table * GetVertexToElementTable()
The returned Table must be destroyed by the caller.
const Element * GetBdrElement(int i) const
static const int Orient[NumOrient][NumVert]
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