12 #include "../config/config.hpp"
17 #include "../fem/fem.hpp"
18 #include "../general/sets.hpp"
19 #include "../general/sort_pairs.hpp"
26 ParMesh::ParMesh(MPI_Comm comm,
Mesh &mesh,
int *partitioning_,
35 MPI_Comm_size(MyComm, &NRanks);
36 MPI_Comm_rank(MyComm, &MyRank);
42 partitioning = partitioning_;
51 int vert_counter, element_counter, bdrelem_counter;
54 vert_global_local = -1;
58 for (i = 0; i < mesh.
GetNE(); i++)
59 if (partitioning[i] == MyRank)
63 for (j = 0; j < vert.
Size(); j++)
64 if (vert_global_local[vert[j]] < 0)
65 vert_global_local[vert[j]] = vert_counter++;
73 for (i = vert_counter = 0; i < vert_global_local.
Size(); i++)
74 if (vert_global_local[i] >= 0)
75 vert_global_local[i] = vert_counter++;
78 for (i = 0; i < vert_global_local.Size(); i++)
79 if (vert_global_local[i] >= 0)
85 for (i = 0; i < mesh.
GetNE(); i++)
86 if (partitioning[i] == MyRank)
89 int *v =
elements[element_counter]->GetVertices();
90 int nv =
elements[element_counter]->GetNVertices();
91 for (j = 0; j < nv; j++)
92 v[j] = vert_global_local[v[j]];
96 Table *edge_element = NULL;
100 activeBdrElem =
false;
106 for (i = 0; i < mesh.
GetNBE(); i++)
108 int face, o, el1, el2;
111 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] == MyRank)
115 activeBdrElem[i] =
true;
121 for (i = 0; i < mesh.
GetNBE(); i++)
123 int face, o, el1, el2;
126 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] == MyRank)
129 int *v =
boundary[bdrelem_counter]->GetVertices();
130 int nv =
boundary[bdrelem_counter]->GetNVertices();
131 for (j = 0; j < nv; j++)
132 v[j] = vert_global_local[v[j]];
139 edge_element =
new Table;
143 for (i = 0; i < mesh.
GetNBE(); i++)
146 int el1 = edge_element->
GetRow(edge)[0];
147 if (partitioning[el1] == MyRank)
151 activeBdrElem[i] =
true;
157 for (i = 0; i < mesh.
GetNBE(); i++)
160 int el1 = edge_element->
GetRow(edge)[0];
161 if (partitioning[el1] == MyRank)
164 int *v =
boundary[bdrelem_counter]->GetVertices();
165 int nv =
boundary[bdrelem_counter]->GetNVertices();
166 for (j = 0; j < nv; j++)
167 v[j] = vert_global_local[v[j]];
175 for (i = 0; i < mesh.
GetNBE(); i++)
177 int vert = mesh.
boundary[i]->GetVertices()[0];
180 if (partitioning[el1] == MyRank)
188 for (i = 0; i < mesh.
GetNBE(); i++)
190 int vert = mesh.
boundary[i]->GetVertices()[0];
193 if (partitioning[el1] == MyRank)
196 int *v =
boundary[bdrelem_counter]->GetVertices();
197 v[0] = vert_global_local[v[0]];
238 cerr <<
"ParMesh::ParMesh (proc " << MyRank <<
") : "
239 "(Dim < 3 && mesh.GetNFaces() != 0) is true!" << endl;
244 int sface_counter = 0;
246 for (i = 0; i < face_group.Size(); i++)
253 el[0] = partitioning[el[0]];
254 el[1] = partitioning[el[1]];
255 if ((el[0] == MyRank && el[1] != MyRank) ||
256 (el[0] != MyRank && el[1] == MyRank))
259 face_group[i] = groups.
Insert(group) - 1;
266 int sedge_counter = 0;
269 edge_element =
new Table;
275 for (i = 0; i < edge_element->
Size(); i++)
277 int me = 0, others = 0;
278 for (j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
280 edge_element->
GetJ()[j] = partitioning[edge_element->
GetJ()[j]];
281 if (edge_element->
GetJ()[j] == MyRank)
294 edge_element->
GetRow(i)[0] = -1;
298 int svert_counter = 0;
301 for (i = 0; i < vert_element->
Size(); i++)
303 int me = 0, others = 0;
304 for (j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
306 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
307 if (vert_element->
GetJ()[j] == MyRank)
317 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
320 vert_element->
GetI()[i] = -1;
326 for (i = 0; i < face_group.Size(); i++)
327 if (face_group[i] >= 0)
333 for (i = 0; i < face_group.Size(); i++)
334 if (face_group[i] >= 0)
342 for (i = 0; i < edge_element->
Size(); i++)
343 if (edge_element->
GetRow(i)[0] >= 0)
349 for (i = 0; i < edge_element->
Size(); i++)
350 if (edge_element->
GetRow(i)[0] >= 0)
359 for (i = 0; i < vert_element->
Size(); i++)
360 if (vert_element->
GetI()[i] >= 0)
366 for (i = 0; i < vert_element->
Size(); i++)
367 if (vert_element->
GetI()[i] >= 0)
374 shared_faces.SetSize(sface_counter);
375 sface_lface. SetSize(sface_counter);
380 for (i = 0; i < face_group.Size(); i++)
381 if (face_group[i] >= 0)
384 int *v = shared_faces[sface_counter]->GetVertices();
385 int nv = shared_faces[sface_counter]->GetNVertices();
386 for (j = 0; j < nv; j++)
387 v[j] = vert_global_local[v[j]];
388 switch (shared_faces[sface_counter]->GetType())
391 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
396 int lface = sface_lface[sface_counter];
399 int re[2], type, flag, *tv;
407 case 1: v[0] = tv[1]; v[1] = tv[2]; v[2] = tv[3];
break;
408 case 4: v[0] = tv[3]; v[1] = tv[1]; v[2] = tv[2];
break;
409 case 5: v[0] = tv[2]; v[1] = tv[3]; v[2] = tv[1];
break;
415 case 2: v[0] = tv[2]; v[1] = tv[0]; v[2] = tv[3];
break;
416 case 3: v[0] = tv[0]; v[1] = tv[3]; v[2] = tv[2];
break;
417 case 5: v[0] = tv[3]; v[1] = tv[2]; v[2] = tv[0];
break;
421 v[0] = tv[0]; v[1] = tv[1]; v[2] = tv[3];
424 v[0] = tv[1]; v[1] = tv[0]; v[2] = tv[2];
432 if (MyRank == partitioning[gl_el2])
434 const int t = v[0]; v[0] = v[1]; v[1] = t;
440 sface_lface[sface_counter] =
441 (*faces_tbl)(v[0], v[1], v[2], v[3]);
451 shared_edges.SetSize(sedge_counter);
452 sedge_ledge. SetSize(sedge_counter);
459 for (i = 0; i < edge_element->
Size(); i++)
460 if (edge_element->
GetRow(i)[0] >= 0)
464 shared_edges[sedge_counter] =
465 new Segment(vert_global_local[vert[0]],
466 vert_global_local[vert[1]], 1);
468 if ((sedge_ledge[sedge_counter] =
469 v_to_v(vert_global_local[vert[0]],
470 vert_global_local[vert[1]])) < 0)
472 cerr <<
"\n\n\n" << MyRank <<
": ParMesh::ParMesh: "
473 <<
"ERROR in v_to_v\n\n" << endl;
484 svert_lvert.
SetSize(svert_counter);
487 for (i = 0; i < vert_element->
Size(); i++)
488 if (vert_element->
GetI()[i] >= 0)
489 svert_lvert[svert_counter++] = vert_global_local[i];
510 for (i = 0; i < mesh.
GetNE(); i++)
511 if (partitioning[i] == MyRank)
514 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
515 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
521 if (partitioning_ == NULL)
522 delete [] partitioning;
529 int sedge = group_sedge.
GetJ()[group_sedge.
GetI()[group-1]+i];
530 edge = sedge_ledge[sedge];
531 int *v = shared_edges[sedge]->GetVertices();
532 o = (v[0] < v[1]) ? (+1) : (-1);
537 int sface = group_sface.
GetJ()[group_sface.
GetI()[group-1]+i];
538 face = sface_lface[sface];
552 int ParMesh::GetEdgeSplittings(
Element *edge,
const DSTable &v_to_v,
557 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
570 int ParMesh::GetFaceSplittings(Element *face,
const DSTable &v_to_v,
574 int number_of_splittings = 0;
575 int *v = face->GetVertices();
577 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
579 number_of_splittings++;
580 if ((m = v_to_v(v[1], v[2])) != -1 && middle[m] != -1)
583 number_of_splittings++;
585 if ((m = v_to_v(v[2], v[0])) != -1 && middle[m] != -1)
586 number_of_splittings++;
588 switch (number_of_splittings)
592 number_of_splittings++;
595 number_of_splittings++;
600 return number_of_splittings;
603 void ParMesh::GetFaceNbrElementTransformation(
604 int i, IsoparametricTransformation *ElTr)
606 DenseMatrix &pointmat = ElTr->GetPointMat();
609 ElTr->Attribute = elem->GetAttribute();
614 const int nv = elem->GetNVertices();
615 const int *v = elem->GetVertices();
619 for (
int j = 0; j < nv; j++)
627 ParGridFunction *pNodes =
dynamic_cast<ParGridFunction *
>(
Nodes);
630 pNodes->ParFESpace()->GetFaceNbrElementVDofs(i, vdofs);
632 pointmat.SetSize(spaceDim, n);
634 for (
int j = 0; j < n; j++)
635 pointmat(k,j) = (pNodes->FaceNbrData())(vdofs[n*k+j]);
637 ElTr->SetFE(pNodes->ParFESpace()->GetFaceNbrFE(i));
640 mfem_error(
"ParMesh::GetFaceNbrElementTransformation : "
641 "Nodes are not ParGridFunction!");
645 void ParMesh::DeleteFaceNbrData()
671 gr_sface = &group_svert;
672 s2l_face = svert_lvert;
676 gr_sface = &group_sedge;
677 s2l_face = sedge_ledge;
681 gr_sface = &group_sface;
682 s2l_face = sface_lface;
685 int num_face_nbrs = 0;
687 if (gr_sface->
RowSize(g-1) > 0)
692 if (num_face_nbrs == 0)
702 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
703 if (gr_sface->
RowSize(g-1) > 0)
707 mfem_error(
"ParMesh::ExchangeFaceNbrData() : "
708 "group size is not 2!");
711 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
713 rank_group[counter].two = g;
719 for (
int fn = 0; fn < num_face_nbrs; fn++)
723 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
724 MPI_Request *send_requests = requests;
725 MPI_Request *recv_requests = requests + num_face_nbrs;
726 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
728 int *nbr_data =
new int[6*num_face_nbrs];
729 int *nbr_send_data = nbr_data;
730 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
737 Table send_face_nbr_elemdata, send_face_nbr_facedata;
741 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
742 send_face_nbr_facedata.
MakeI(num_face_nbrs);
743 for (
int fn = 0; fn < num_face_nbrs; fn++)
746 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
747 int *sface = gr_sface->
GetRow(nbr_group-1);
748 for (
int i = 0; i < num_sfaces; i++)
750 int lface = s2l_face[sface[i]];
752 if (el_marker[el] != fn)
757 const int nv =
elements[el]->GetNVertices();
758 const int *v =
elements[el]->GetVertices();
759 for (
int j = 0; j < nv; j++)
760 if (vertex_marker[v[j]] != fn)
762 vertex_marker[v[j]] = fn;
773 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
778 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag, MyComm,
780 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag, MyComm,
785 send_face_nbr_elemdata.
MakeJ();
786 send_face_nbr_facedata.
MakeJ();
789 for (
int fn = 0; fn < num_face_nbrs; fn++)
792 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
793 int *sface = gr_sface->
GetRow(nbr_group-1);
794 for (
int i = 0; i < num_sfaces; i++)
796 int lface = s2l_face[sface[i]];
798 if (el_marker[el] != fn)
803 const int nv =
elements[el]->GetNVertices();
804 const int *v =
elements[el]->GetVertices();
805 for (
int j = 0; j < nv; j++)
806 if (vertex_marker[v[j]] != fn)
808 vertex_marker[v[j]] = fn;
824 const int *sf_v = shared_faces[sface[i]]->GetVertices();
841 for (
int fn = 0; fn < num_face_nbrs; fn++)
847 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
848 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
849 int *facedata = send_face_nbr_facedata.
GetRow(fn);
851 for (
int i = 0; i < num_verts; i++)
852 vertex_marker[verts[i]] = i;
854 for (
int el = 0; el < num_elems; el++)
856 const int nv =
elements[el]->GetNVertices();
858 for (
int j = 0; j < nv; j++)
859 elemdata[j] = vertex_marker[elemdata[j]];
862 el_marker[elems[el]] = el;
865 for (
int i = 0; i < num_sfaces; i++)
866 facedata[2*i] = el_marker[facedata[2*i]];
869 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
872 Table recv_face_nbr_elemdata;
877 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
880 for (
int fn = 0; fn < num_face_nbrs; fn++)
888 recv_face_nbr_elemdata.
MakeJ();
890 MPI_Waitall(num_face_nbrs, send_requests, statuses);
893 for (
int fn = 0; fn < num_face_nbrs; fn++)
898 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
899 send_face_nbr_elemdata.
RowSize(fn),
900 MPI_INT, nbr_rank, tag, MyComm, &send_requests[fn]);
902 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
903 recv_face_nbr_elemdata.
RowSize(fn),
904 MPI_INT, nbr_rank, tag, MyComm, &recv_requests[fn]);
912 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
914 if (fn == MPI_UNDEFINED)
920 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
922 for (
int i = 0; i < num_elems; i++)
928 for (
int j = 0; j < nv; j++)
929 recv_elemdata[j] += vert_off;
936 MPI_Waitall(num_face_nbrs, send_requests, statuses);
939 recv_face_nbr_facedata.
SetSize(
941 for (
int fn = 0; fn < num_face_nbrs; fn++)
946 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
947 send_face_nbr_facedata.
RowSize(fn),
948 MPI_INT, nbr_rank, tag, MyComm, &send_requests[fn]);
951 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
952 send_face_nbr_facedata.
RowSize(fn),
953 MPI_INT, nbr_rank, tag, MyComm, &recv_requests[fn]);
960 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
962 if (fn == MPI_UNDEFINED)
967 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
968 int *sface = gr_sface->
GetRow(nbr_group-1);
970 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
972 for (
int i = 0; i < num_sfaces; i++)
974 int lface = s2l_face[sface[i]];
976 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
977 int info = facedata[2*i+1];
985 int nbr_ori = info%64, nbr_v[4];
987 const int *sf_v = shared_faces[sface[i]]->GetVertices();
993 for (
int j = 0; j < 3; j++)
994 nbr_v[perm[j]] = sf_v[j];
1002 for (
int j = 0; j < 4; j++)
1003 nbr_v[perm[j]] = sf_v[j];
1008 info = 64*(info/64) + nbr_ori;
1014 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1035 else if (
Nodes == NULL)
1039 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1040 MPI_Request *send_requests = requests;
1041 MPI_Request *recv_requests = requests + num_face_nbrs;
1042 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1046 for (
int i = 0; i < send_vertices.Size(); i++)
1050 for (
int fn = 0; fn < num_face_nbrs; fn++)
1057 MPI_DOUBLE, nbr_rank, tag, MyComm, &send_requests[fn]);
1062 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
1065 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1066 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1077 mfem_error(
"ParMesh::ExchangeFaceNbrNodes() : "
1078 "Nodes are not ParGridFunction!");
1086 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
1096 s2l_face = &svert_lvert;
1098 s2l_face = &sedge_ledge;
1100 s2l_face = &sface_lface;
1113 for (
int i = 0; i < s2l_face->
Size(); i++)
1124 for (
int i = 0; i < s2l_face->
Size(); i++)
1126 int lface = (*s2l_face)[i];
1127 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
1141 FaceNo = svert_lvert[sf];
1143 FaceNo = sedge_ledge[sf];
1145 FaceNo = sface_lface[sf];
1194 return svert_lvert.
Size();
1196 return sedge_ledge.
Size();
1197 return sface_lface.
Size();
1214 for (
int i = 0; i < shared_edges.Size(); i++)
1216 v = shared_edges[i]->GetVertices();
1217 sedge_ledge[i] = v_to_v(v[0], v[1]);
1229 for (
int i = 0; i < shared_faces.Size(); i++)
1232 v = shared_faces[i]->GetVertices();
1236 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2]);
1253 DeleteFaceNbrData();
1266 int uniform_refinement = 0;
1270 uniform_refinement = 1;
1285 for (i = 0; i < marked_el.
Size(); i++)
1286 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1289 for (i = 0; i < marked_el.
Size(); i++)
1291 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1294 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1298 for (i = 0; i < marked_el.
Size(); i++)
1300 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1303 Bisection(j, v_to_v, NULL, NULL, middle);
1305 Bisection(j, v_to_v, NULL, NULL, middle);
1307 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1309 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1321 int need_refinement;
1322 int refined_edge[5][3] = {{0, 0, 0},
1327 int faces_in_group, max_faces_in_group = 0;
1329 int **face_splittings =
new int*[
GetNGroups()-1];
1333 face_splittings[i] =
new int[faces_in_group];
1334 if (faces_in_group > max_faces_in_group)
1335 max_faces_in_group = faces_in_group;
1337 int neighbor, *iBuf =
new int[max_faces_in_group];
1342 MPI_Request request;
1346 int ref_loops_all = 0, ref_loops_par = 0;
1350 need_refinement = 0;
1353 if (
elements[i]->NeedRefinement(v_to_v, middle))
1355 need_refinement = 1;
1356 Bisection(i, v_to_v, NULL, NULL, middle);
1363 if (uniform_refinement)
1368 if (need_refinement == 0)
1378 group_sface.
GetRow(i, group_faces);
1379 faces_in_group = group_faces.
Size();
1381 if (faces_in_group != 0)
1383 for (j = 0; j < faces_in_group; j++)
1384 face_splittings[i][j] =
1385 GetFaceSplittings(shared_faces[group_faces[j]], v_to_v,
1392 MPI_Isend(face_splittings[i], faces_in_group, MPI_INT,
1393 neighbor, 0, MyComm, &request);
1400 group_sface.
GetRow(i, group_faces);
1401 faces_in_group = group_faces.
Size();
1402 if (faces_in_group != 0)
1409 MPI_Recv(iBuf, faces_in_group, MPI_INT, neighbor,
1410 MPI_ANY_TAG, MyComm, &status);
1412 for (j = 0; j < faces_in_group; j++)
1413 if (iBuf[j] != face_splittings[i][j])
1415 int *v = shared_faces[group_faces[j]]->GetVertices();
1416 for (
int k = 0; k < 3; k++)
1417 if (refined_edge[iBuf[j]][k] == 1 &&
1418 refined_edge[face_splittings[i][j]][k] == 0)
1420 int ii = v_to_v(v[k], v[(k+1)%3]);
1421 if (middle[ii] == -1)
1423 need_refinement = 1;
1425 for (
int c = 0; c < 3; c++)
1435 i = need_refinement;
1436 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR, MyComm);
1439 while (need_refinement == 1);
1443 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0, MyComm);
1446 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
1447 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
1454 delete [] face_splittings[i];
1455 delete [] face_splittings;
1461 need_refinement = 0;
1463 if (
boundary[i]->NeedRefinement(v_to_v, middle))
1465 need_refinement = 1;
1469 while (need_refinement == 1);
1473 " (NumOfBdrElements != boundary.Size())");
1494 int refinement_edges[2], type, flag;
1500 ((
Tetrahedron *) El)->ParseRefinementFlag(refinement_edges,
1503 ((
Tetrahedron *) El)->CreateRefinementFlag(refinement_edges,
1548 int uniform_refinement = 0;
1552 uniform_refinement = 1;
1561 int *edge1 =
new int[nedges];
1562 int *edge2 =
new int[nedges];
1563 int *middle =
new int[nedges];
1565 for (i = 0; i < nedges; i++)
1566 edge1[i] = edge2[i] = middle[i] = -1;
1570 int *v =
elements[i]->GetVertices();
1571 for (j = 0; j < 3; j++)
1573 int ind = v_to_v(v[j], v[(j+1)%3]);
1574 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
1579 for (i = 0; i < marked_el.
Size(); i++)
1589 int need_refinement;
1590 int edges_in_group, max_edges_in_group = 0;
1592 int **edge_splittings =
new int*[
GetNGroups()-1];
1596 edge_splittings[i] =
new int[edges_in_group];
1597 if (edges_in_group > max_edges_in_group)
1598 max_edges_in_group = edges_in_group;
1600 int neighbor, *iBuf =
new int[max_edges_in_group];
1604 MPI_Request request;
1610 int ref_loops_all = 0, ref_loops_par = 0;
1614 need_refinement = 0;
1615 for (i = 0; i < nedges; i++)
1616 if (middle[i] != -1 && edge1[i] != -1)
1618 need_refinement = 1;
1625 if (uniform_refinement)
1630 if (need_refinement == 0)
1640 group_sedge.
GetRow(i, group_edges);
1641 edges_in_group = group_edges.
Size();
1643 if (edges_in_group != 0)
1645 for (j = 0; j < edges_in_group; j++)
1646 edge_splittings[i][j] =
1647 GetEdgeSplittings(shared_edges[group_edges[j]], v_to_v,
1654 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
1655 neighbor, 0, MyComm, &request);
1662 group_sedge.
GetRow(i, group_edges);
1663 edges_in_group = group_edges.
Size();
1664 if (edges_in_group != 0)
1671 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
1672 MPI_ANY_TAG, MyComm, &status);
1674 for (j = 0; j < edges_in_group; j++)
1675 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
1677 int *v = shared_edges[group_edges[j]]->GetVertices();
1678 int ii = v_to_v(v[0], v[1]);
1680 if (middle[ii] != -1)
1681 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
1684 need_refinement = 1;
1686 for (
int c = 0; c < 2; c++)
1693 i = need_refinement;
1694 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR, MyComm);
1697 while (need_refinement == 1);
1701 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0, MyComm);
1704 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
1705 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
1711 delete [] edge_splittings[i];
1712 delete [] edge_splittings;
1717 int v1[2], v2[2], bisect, temp;
1719 for (i = 0; i < temp; i++)
1721 int *v =
boundary[i]->GetVertices();
1722 bisect = v_to_v(v[0], v[1]);
1723 if (middle[bisect] != -1)
1727 v1[0] = v[0]; v1[1] = middle[bisect];
1728 v2[0] = middle[bisect]; v2[1] = v[1];
1733 #ifdef MFEM_USE_MEMALLOC
1752 mfem_error(
"Only bisection of segment is implemented for bdr"
1806 for (j = 0; j < marked_el.
Size(); j++)
1811 int new_v = cnv + j, new_e = cne + j;
1816 #ifdef MFEM_USE_MEMALLOC
1858 int i, attr, newv[3], ind, f_ind, *v;
1861 Array<int> group_verts, group_edges, group_faces;
1869 int *I_group_svert, *J_group_svert;
1870 int *I_group_sedge, *J_group_sedge;
1871 int *I_group_sface, *J_group_sface;
1878 I_group_sface = NULL;
1880 I_group_svert[0] = I_group_svert[1] = 0;
1881 I_group_sedge[0] = I_group_sedge[1] = 0;
1883 I_group_sface[0] = I_group_sface[1] = 0;
1899 J_group_sface = NULL;
1903 J_group_svert = J_group_sedge = J_group_sface = NULL;
1906 for (group = 0; group <
GetNGroups()-1; group++)
1909 group_svert.
GetRow(group, group_verts);
1910 group_sedge.
GetRow(group, group_edges);
1911 group_sface.
GetRow(group, group_faces);
1914 for (i = 0; i < group_sedge.
RowSize(group); i++)
1916 v = shared_edges[group_edges[i]]->GetVertices();
1917 ind = middle[v_to_v(v[0], v[1])];
1923 attr = shared_edges[group_edges[i]]->GetAttribute();
1924 shared_edges.Append(
new Segment(v[1], ind, attr));
1931 for (i = 0; i < group_sface.
RowSize(group); i++)
1933 v = shared_faces[group_faces[i]]->GetVertices();
1934 ind = middle[v_to_v(v[0], v[1])];
1937 attr = shared_faces[group_faces[i]]->GetAttribute();
1939 shared_edges.Append(
new Segment(v[2], ind, attr));
1942 f_ind = group_faces.
Size();
1943 shared_faces.Append(
new Triangle(v[1], v[2], ind, attr));
1945 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
1946 shared_faces[group_faces[i]]->SetVertices(newv);
1950 ind = middle[v_to_v(v[0], v[1])];
1954 shared_edges.Append(
new Segment(v[2], ind, attr));
1957 shared_faces.Append(
new Triangle(v[1], v[2], ind, attr));
1959 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
1960 shared_faces[group_faces[i]]->SetVertices(newv);
1964 v = shared_faces[group_faces[f_ind]]->GetVertices();
1965 ind = middle[v_to_v(v[0], v[1])];
1969 shared_edges.Append(
new Segment(v[2], ind, attr));
1972 shared_faces.Append(
new Triangle(v[1], v[2], ind, attr));
1974 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
1975 shared_faces[group_faces[f_ind]]->SetVertices(newv);
1980 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
1981 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
1983 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
1986 J = J_group_svert+I_group_svert[group];
1987 for (i = 0; i < group_verts.
Size(); i++)
1988 J[i] = group_verts[i];
1989 J = J_group_sedge+I_group_sedge[group];
1990 for (i = 0; i < group_edges.
Size(); i++)
1991 J[i] = group_edges[i];
1994 J = J_group_sface+I_group_sface[group];
1995 for (i = 0; i < group_faces.
Size(); i++)
1996 J[i] = group_faces[i];
2004 for (i = 0; i < shared_edges.Size(); i++)
2006 v = shared_edges[i]->GetVertices();
2007 sedge_ledge[i] = new_v_to_v(v[0], v[1]);
2013 for (i = 0; i < shared_faces.Size(); i++)
2015 v = shared_faces[i]->GetVertices();
2016 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2]);
2021 group_svert.
SetIJ(I_group_svert, J_group_svert);
2022 group_sedge.
SetIJ(I_group_sedge, J_group_sedge);
2024 group_sface.
SetIJ(I_group_sface, J_group_sface);
2027 void ParMesh::QuadUniformRefinement()
2030 DeleteFaceNbrData();
2047 int i, attr, ind, *v;
2050 Array<int> sverts, sedges;
2052 int *I_group_svert, *J_group_svert;
2053 int *I_group_sedge, *J_group_sedge;
2058 I_group_svert[0] = I_group_svert[1] = 0;
2059 I_group_sedge[0] = I_group_sedge[1] = 0;
2066 for (group = 0; group <
GetNGroups()-1; group++)
2069 group_svert.
GetRow(group, sverts);
2070 group_sedge.
GetRow(group, sedges);
2073 for (i = 0; i < group_sedge.
RowSize(group); i++)
2075 v = shared_edges[sedges[i]]->GetVertices();
2076 ind = oedge + sedge_ledge[sedges[i]];
2080 attr = shared_edges[sedges[i]]->GetAttribute();
2081 shared_edges.Append(
new Segment(v[1], ind, attr));
2082 sedges.Append(sedge_ledge.
Append(-1)-1);
2086 I_group_svert[group+1] = I_group_svert[group] + sverts.Size();
2087 I_group_sedge[group+1] = I_group_sedge[group] + sedges.Size();
2090 J = J_group_svert+I_group_svert[group];
2091 for (i = 0; i < sverts.Size(); i++)
2093 J = J_group_sedge+I_group_sedge[group];
2094 for (i = 0; i < sedges.Size(); i++)
2101 for (i = 0; i < shared_edges.Size(); i++)
2103 v = shared_edges[i]->GetVertices();
2104 sedge_ledge[i] = v_to_v(v[0], v[1]);
2107 group_svert.
SetIJ(I_group_svert, J_group_svert);
2108 group_sedge.
SetIJ(I_group_sedge, J_group_sedge);
2118 void ParMesh::HexUniformRefinement()
2121 DeleteFaceNbrData();
2136 GridFunction *nodes =
Nodes;
2144 int i, attr, newv[4], ind, m[5];
2148 Array<int> group_verts, group_edges, group_faces;
2150 int *I_group_svert, *J_group_svert;
2151 int *I_group_sedge, *J_group_sedge;
2152 int *I_group_sface, *J_group_sface;
2158 I_group_svert[0] = I_group_svert[1] = 0;
2159 I_group_sedge[0] = I_group_sedge[1] = 0;
2160 I_group_sface[0] = I_group_sface[1] = 0;
2170 for (group = 0; group <
GetNGroups()-1; group++)
2173 group_svert.
GetRow(group, group_verts);
2174 group_sedge.
GetRow(group, group_edges);
2175 group_sface.
GetRow(group, group_faces);
2178 for (i = 0; i < group_sedge.
RowSize(group); i++)
2180 shared_edges[group_edges[i]]->GetVertices(v);
2181 ind = oedge + v_to_v(v[0], v[1]);
2183 group_verts.Append(svert_lvert.
Append(ind)-1);
2185 attr = shared_edges[group_edges[i]]->GetAttribute();
2186 shared_edges.Append(
new Segment(v[1], ind, attr));
2187 group_edges.Append(sedge_ledge.
Append(-1)-1);
2188 newv[0] = v[0]; newv[1] = ind;
2189 shared_edges[group_edges[i]]->SetVertices(newv);
2193 for (i = 0; i < group_sface.
RowSize(group); i++)
2195 shared_faces[group_faces[i]]->GetVertices(v);
2196 m[0] = oface+(*faces_tbl)(v[0], v[1], v[2], v[3]);
2198 group_verts.Append(svert_lvert.
Append(m[0])-1);
2200 attr = shared_faces[group_faces[i]]->GetAttribute();
2201 m[1] = oedge + v_to_v(v[0], v[1]);
2202 m[2] = oedge + v_to_v(v[1], v[2]);
2203 m[3] = oedge + v_to_v(v[2], v[3]);
2204 m[4] = oedge + v_to_v(v[3], v[0]);
2205 shared_edges.Append(
new Segment(m[1], m[0], attr));
2206 group_edges.Append(sedge_ledge.
Append(-1)-1);
2207 shared_edges.Append(
new Segment(m[2], m[0], attr));
2208 group_edges.Append(sedge_ledge.
Append(-1)-1);
2209 shared_edges.Append(
new Segment(m[3], m[0], attr));
2210 group_edges.Append(sedge_ledge.
Append(-1)-1);
2211 shared_edges.Append(
new Segment(m[4], m[0], attr));
2212 group_edges.Append(sedge_ledge.
Append(-1)-1);
2214 newv[0] = v[0]; newv[1] = m[1]; newv[2] = m[0]; newv[3] = m[4];
2215 shared_faces[group_faces[i]]->SetVertices(newv);
2216 shared_faces.Append(
new Quadrilateral(m[1],v[1],m[2],m[0],attr));
2217 group_faces.Append(sface_lface.
Append(-1)-1);
2218 shared_faces.Append(
new Quadrilateral(m[0],m[2],v[2],m[3],attr));
2219 group_faces.Append(sface_lface.
Append(-1)-1);
2220 shared_faces.Append(
new Quadrilateral(m[4],m[0],m[3],v[3],attr));
2221 group_faces.Append(sface_lface.
Append(-1)-1);
2224 I_group_svert[group+1] = I_group_svert[group] + group_verts.Size();
2225 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.Size();
2226 I_group_sface[group+1] = I_group_sface[group] + group_faces.Size();
2229 J = J_group_svert+I_group_svert[group];
2230 for (i = 0; i < group_verts.Size(); i++)
2231 J[i] = group_verts[i];
2232 J = J_group_sedge+I_group_sedge[group];
2233 for (i = 0; i < group_edges.Size(); i++)
2234 J[i] = group_edges[i];
2235 J = J_group_sface+I_group_sface[group];
2236 for (i = 0; i < group_faces.Size(); i++)
2237 J[i] = group_faces[i];
2243 for (i = 0; i < shared_edges.Size(); i++)
2245 shared_edges[i]->GetVertices(v);
2246 sedge_ledge[i] = new_v_to_v(v[0], v[1]);
2251 for (i = 0; i < shared_faces.Size(); i++)
2253 shared_faces[i]->GetVertices(v);
2254 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
2258 group_svert.
SetIJ(I_group_svert, J_group_svert);
2259 group_sedge.
SetIJ(I_group_sedge, J_group_sedge);
2260 group_sface.
SetIJ(I_group_sface, J_group_sface);
2270 void ParMesh::NURBSUniformRefinement()
2273 cout <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
2278 MFEM_ASSERT(
Dim == spaceDim,
"2D manifolds not supported");
2284 out <<
"NETGEN_Neutral_Format\n";
2289 for (j = 0; j <
Dim; j++)
2300 out <<
elements[i]->GetAttribute();
2301 for (j = 0; j < nv; j++)
2302 out <<
" " << ind[j]+1;
2313 out <<
boundary[i]->GetAttribute();
2314 for (j = 0; j < nv; j++)
2315 out <<
" " << ind[j]+1;
2319 for (i = 0; i < shared_faces.Size(); i++)
2321 nv = shared_faces[i]->GetNVertices();
2322 ind = shared_faces[i]->GetVertices();
2323 out << shared_faces[i]->GetAttribute();
2324 for (j = 0; j < nv; j++)
2325 out <<
" " << ind[j]+1;
2337 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
2339 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
2340 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
2341 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
2346 <<
" " <<
vertices[i](2) <<
" 0.0\n";
2353 out << i+1 <<
" " <<
elements[i]->GetAttribute();
2354 for (j = 0; j < nv; j++)
2355 out <<
" " << ind[j]+1;
2364 out <<
boundary[i]->GetAttribute();
2365 for (j = 0; j < nv; j++)
2366 out <<
" " << ind[j]+1;
2367 out <<
" 1.0 1.0 1.0 1.0\n";
2371 for (i = 0; i < shared_faces.Size(); i++)
2373 nv = shared_faces[i]->GetNVertices();
2374 ind = shared_faces[i]->GetVertices();
2375 out << shared_faces[i]->GetAttribute();
2376 for (j = 0; j < nv; j++)
2377 out <<
" " << ind[j]+1;
2378 out <<
" 1.0 1.0 1.0 1.0\n";
2387 out <<
"areamesh2\n\n";
2394 attr =
boundary[i]->GetAttribute();
2397 for (j = 0; j < v.
Size(); j++)
2398 out << v[j] + 1 <<
" ";
2402 for (i = 0; i < shared_edges.Size(); i++)
2404 attr = shared_edges[i]->GetAttribute();
2405 shared_edges[i]->GetVertices(v);
2407 for (j = 0; j < v.
Size(); j++)
2408 out << v[j] + 1 <<
" ";
2416 attr =
elements[i]->GetAttribute();
2428 for (j = 0; j < v.
Size(); j++)
2429 out << v[j] + 1 <<
" ";
2437 for (j = 0; j <
Dim; j++)
2446 bool print_shared =
true;
2447 int i, j, shared_bdr_attr;
2449 ((
Dim == 2) ? sedge_ledge : sface_lface));
2457 out <<
"MFEM mesh v1.0\n";
2461 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
2466 "# TETRAHEDRON = 4\n"
2470 out <<
"\ndimension\n" <<
Dim
2476 if (print_shared &&
Dim > 1)
2477 num_bdr_elems += s2l_face.
Size();
2478 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
2482 if (print_shared &&
Dim > 1)
2487 shared_bdr_attr = MyRank + 1;
2488 for (i = 0; i < s2l_face.
Size(); i++)
2491 faces[s2l_face[i]]->SetAttribute(shared_bdr_attr);
2498 out << spaceDim <<
'\n';
2516 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
2524 out <<
"MFEM mesh v1.0\n";
2528 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
2533 "# TETRAHEDRON = 4\n"
2537 out <<
"\ndimension\n" <<
Dim;
2541 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
2544 out <<
"\n\nelements\n" << ne <<
'\n';
2548 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
2552 for (j = 0; j < nv; j++)
2557 for (p = 1; p < NRanks; p++)
2559 MPI_Recv(nv_ne, 2, MPI_INT, p, 444, MyComm, &status);
2561 MPI_Recv(&ints[0], ne, MPI_INT, p, 445, MyComm, &status);
2562 for (i = 0; i < ne; )
2565 out << p+1 <<
' ' << ints[i];
2568 for (j = 0; j < k; j++)
2569 out <<
' ' << vc + ints[i++];
2580 ne += 1 +
elements[i]->GetNVertices();
2582 MPI_Send(nv_ne, 2, MPI_INT, 0, 444, MyComm);
2586 ints[j++] =
elements[i]->GetGeometryType();
2589 for (k = 0; k < nv; k++)
2592 MPI_Send(&ints[0], ne, MPI_INT, 0, 445, MyComm);
2597 (
Dim == 2) ? shared_edges : shared_faces;
2599 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
2602 out <<
"\nboundary\n" << ne <<
'\n';
2607 out << 1 <<
' ' <<
boundary[i]->GetGeometryType();
2611 for (j = 0; j < nv; j++)
2616 for (i = 0; i < shared_boundary.
Size(); i++)
2619 out << 1 <<
' ' << shared_boundary[i]->GetGeometryType();
2621 nv = shared_boundary[i]->GetNVertices();
2622 v = shared_boundary[i]->GetVertices();
2623 for (j = 0; j < nv; j++)
2628 for (p = 1; p < NRanks; p++)
2630 MPI_Recv(nv_ne, 2, MPI_INT, p, 446, MyComm, &status);
2632 MPI_Recv(&ints[0], ne, MPI_INT, p, 447, MyComm, &status);
2633 for (i = 0; i < ne; )
2636 out << p+1 <<
' ' << ints[i];
2639 for (j = 0; j < k; j++)
2640 out <<
' ' << vc + ints[i++];
2652 ne += 1 +
boundary[i]->GetNVertices();
2653 for (i = 0; i < shared_boundary.
Size(); i++)
2654 ne += 1 + shared_boundary[i]->GetNVertices();
2656 MPI_Send(nv_ne, 2, MPI_INT, 0, 446, MyComm);
2661 ints[j++] =
boundary[i]->GetGeometryType();
2664 for (k = 0; k < nv; k++)
2668 for (i = 0; i < shared_boundary.
Size(); i++)
2670 ints[j++] = shared_boundary[i]->GetGeometryType();
2671 nv = shared_boundary[i]->GetNVertices();
2672 v = shared_boundary[i]->GetVertices();
2673 for (k = 0; k < nv; k++)
2676 MPI_Send(&ints[0], ne, MPI_INT, 0, 447, MyComm);
2680 MPI_Reduce(&
NumOfVertices, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
2682 out <<
"\nvertices\n" << nv <<
'\n';
2687 out << spaceDim <<
'\n';
2695 for (p = 1; p < NRanks; p++)
2697 MPI_Recv(&nv, 1, MPI_INT, p, 448, MyComm, &status);
2699 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449, MyComm, &status);
2700 for (i = 0; i < nv; i++)
2704 out <<
' ' << vert[i*spaceDim+j];
2715 vert[i*spaceDim+j] =
vertices[i](j);
2716 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449, MyComm);
2739 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
2746 MFEM_ASSERT(
Dim == spaceDim,
"2D Manifolds not supported.");
2749 int i, j, k, nv, ne, p;
2757 out <<
"NETGEN_Neutral_Format\n";
2760 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
2764 for (j = 0; j <
Dim; j++)
2768 for (p = 1; p < NRanks; p++)
2770 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
2772 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445, MyComm, &status);
2773 for (i = 0; i < nv; i++)
2775 for (j = 0; j <
Dim; j++)
2776 out <<
" " << vert[Dim*i+j];
2783 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
2790 for (j = 0; j < nv; j++)
2791 out <<
" " << ind[j]+1;
2795 for (p = 1; p < NRanks; p++)
2797 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
2798 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
2800 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447, MyComm, &status);
2801 for (i = 0; i < ne; i++)
2804 for (j = 0; j < 4; j++)
2805 out <<
" " << k+ints[i*4+j]+1;
2812 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
2820 for (j = 0; j < nv; j++)
2821 out <<
" " << ind[j]+1;
2825 for (i = 0; i < shared_faces.Size(); i++)
2827 nv = shared_faces[i]->GetNVertices();
2828 ind = shared_faces[i]->GetVertices();
2830 for (j = 0; j < nv; j++)
2831 out <<
" " << ind[j]+1;
2835 for (p = 1; p < NRanks; p++)
2837 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
2838 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
2840 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447, MyComm, &status);
2841 for (i = 0; i < ne; i++)
2844 for (j = 0; j < 3; j++)
2845 out <<
" " << k+ints[i*3+j]+1;
2854 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
2858 for (j = 0; j <
Dim; j++)
2860 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
2864 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
2865 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
2871 for (j = 0; j < 4; j++)
2874 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447, MyComm);
2877 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
2878 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
2880 MPI_Send(&ne, 1, MPI_INT, 0, 446, MyComm);
2885 for (j = 0; j < 3; j++)
2888 for ( ; i < ne; i++)
2891 for (j = 0; j < 3; j++)
2894 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447, MyComm);
2900 int i, j, k, nv, ne, p;
2906 int TG_nv, TG_ne, TG_nbe;
2910 MPI_Reduce(&
NumOfVertices, &TG_nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
2911 MPI_Reduce(&
NumOfElements, &TG_ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
2913 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0, MyComm);
2916 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
2917 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
2918 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
2919 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
2920 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
2926 <<
" " <<
vertices[i](2) <<
" 0.0\n";
2927 for (p = 1; p < NRanks; p++)
2929 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
2931 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445, MyComm, &status);
2932 for (i = 0; i < nv; i++)
2933 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
2934 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
2943 out << i+1 <<
" " << 1;
2944 for (j = 0; j < nv; j++)
2945 out <<
" " << ind[j]+1;
2949 for (p = 1; p < NRanks; p++)
2951 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
2952 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
2954 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447, MyComm, &status);
2955 for (i = 0; i < ne; i++)
2957 out << i+1 <<
" " << p+1;
2958 for (j = 0; j < 8; j++)
2959 out <<
" " << k+ints[i*8+j]+1;
2973 for (j = 0; j < nv; j++)
2974 out <<
" " << ind[j]+1;
2975 out <<
" 1.0 1.0 1.0 1.0\n";
2978 for (i = 0; i < shared_faces.Size(); i++)
2980 nv = shared_faces[i]->GetNVertices();
2981 ind = shared_faces[i]->GetVertices();
2983 for (j = 0; j < nv; j++)
2984 out <<
" " << ind[j]+1;
2985 out <<
" 1.0 1.0 1.0 1.0\n";
2988 for (p = 1; p < NRanks; p++)
2990 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
2991 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
2993 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447, MyComm, &status);
2994 for (i = 0; i < ne; i++)
2997 for (j = 0; j < 4; j++)
2998 out <<
" " << k+ints[i*4+j]+1;
2999 out <<
" 1.0 1.0 1.0 1.0\n";
3006 MPI_Reduce(&
NumOfVertices, &TG_nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3007 MPI_Reduce(&
NumOfElements, &TG_ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3009 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0, MyComm);
3014 for (j = 0; j <
Dim; j++)
3016 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445, MyComm);
3018 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
3024 for (j = 0; j < 8; j++)
3027 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447, MyComm);
3029 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
3031 MPI_Send(&ne, 1, MPI_INT, 0, 446, MyComm);
3036 for (j = 0; j < 4; j++)
3039 for ( ; i < ne; i++)
3042 for (j = 0; j < 4; j++)
3045 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447, MyComm);
3051 int i, j, k, attr, nv, ne, p;
3060 out <<
"areamesh2\n\n";
3064 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3069 attr =
boundary[i]->GetAttribute();
3072 for (j = 0; j < v.
Size(); j++)
3073 out << v[j] + 1 <<
" ";
3077 for (i = 0; i < shared_edges.Size(); i++)
3079 attr = shared_edges[i]->GetAttribute();
3080 shared_edges[i]->GetVertices(v);
3082 for (j = 0; j < v.
Size(); j++)
3083 out << v[j] + 1 <<
" ";
3087 for (p = 1; p < NRanks; p++)
3089 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3090 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3092 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447, MyComm, &status);
3093 for (i = 0; i < ne; i++)
3096 for (j = 0; j < 2; j++)
3097 out <<
" " << k+ints[i*2+j]+1;
3105 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3109 attr =
elements[i]->GetAttribute();
3111 out << 1 <<
" " << 3 <<
" ";
3112 for (j = 0; j < v.
Size(); j++)
3113 out << v[j] + 1 <<
" ";
3117 for (p = 1; p < NRanks; p++)
3119 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3120 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3122 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447, MyComm, &status);
3123 for (i = 0; i < ne; i++)
3125 out << p+1 <<
" " << 3;
3126 for (j = 0; j < 3; j++)
3127 out <<
" " << k+ints[i*3+j]+1;
3135 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3139 for (j = 0; j <
Dim; j++)
3143 for (p = 1; p < NRanks; p++)
3145 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3147 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445, MyComm, &status);
3148 for (i = 0; i < nv; i++)
3150 for (j = 0; j <
Dim; j++)
3151 out <<
" " << vert[Dim*i+j];
3160 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3163 MPI_Send(&ne, 1, MPI_INT, 0, 446, MyComm);
3168 for (j = 0; j < 2; j++)
3171 for ( ; i < ne; i++)
3174 for (j = 0; j < 2; j++)
3177 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447, MyComm);
3180 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3187 for (j = 0; j < 3; j++)
3190 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447, MyComm);
3193 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3197 for (j = 0; j <
Dim; j++)
3199 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3209 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
3212 out <<
"Parallel Mesh Stats:" << endl;
3217 h = pow(fabs(J.
Det()), 1.0/
double(
Dim));
3222 kappa_min = kappa_max =
kappa;
3226 if (h < h_min) h_min = h;
3227 if (h > h_max) h_max = h;
3228 if (kappa < kappa_min) kappa_min =
kappa;
3229 if (kappa > kappa_max) kappa_max =
kappa;
3233 double gh_min, gh_max, gk_min, gk_max;
3234 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0, MyComm);
3235 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0, MyComm);
3236 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0, MyComm);
3237 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0, MyComm);
3240 int mindata[5], maxdata[5], sumdata[5];
3251 ldata[0] -= group_svert.
RowSize(gr-1);
3252 ldata[1] -= group_sedge.
RowSize(gr-1);
3253 ldata[2] -= group_sface.
RowSize(gr-1);
3256 MPI_Reduce(ldata, mindata, 5, MPI_INT, MPI_MIN, 0, MyComm);
3257 MPI_Reduce(ldata, sumdata, 5, MPI_INT, MPI_SUM, 0, MyComm);
3258 MPI_Reduce(ldata, maxdata, 5, MPI_INT, MPI_MAX, 0, MyComm);
3264 << setw(12) <<
"minimum"
3265 << setw(12) <<
"average"
3266 << setw(12) <<
"maximum"
3267 << setw(12) <<
"total" <<
'\n';
3269 << setw(12) << mindata[0]
3270 << setw(12) << sumdata[0]/NRanks
3271 << setw(12) << maxdata[0]
3272 << setw(12) << sumdata[0] <<
'\n';
3274 << setw(12) << mindata[1]
3275 << setw(12) << sumdata[1]/NRanks
3276 << setw(12) << maxdata[1]
3277 << setw(12) << sumdata[1] <<
'\n';
3280 << setw(12) << mindata[2]
3281 << setw(12) << sumdata[2]/NRanks
3282 << setw(12) << maxdata[2]
3283 << setw(12) << sumdata[2] <<
'\n';
3285 << setw(12) << mindata[3]
3286 << setw(12) << sumdata[3]/NRanks
3287 << setw(12) << maxdata[3]
3288 << setw(12) << sumdata[3] <<
'\n';
3289 out <<
" neighbors "
3290 << setw(12) << mindata[4]
3291 << setw(12) << sumdata[4]/NRanks
3292 << setw(12) << maxdata[4] <<
'\n';
3295 << setw(12) <<
"minimum"
3296 << setw(12) <<
"maximum" <<
'\n';
3298 << setw(12) << gh_min
3299 << setw(12) << gh_max <<
'\n';
3301 << setw(12) << gk_min
3302 << setw(12) << gk_max <<
'\n';
3310 DeleteFaceNbrData();
3312 for (i = 0; i < shared_faces.Size(); i++)
3314 for (i = 0; i < shared_edges.Size(); i++)
int GetNPoints() const
Returns the number of the points in the integration rule.
int GetNFaceNeighbors() const
void Create(ListOfIntegerSets &groups, int mpitag)
void SetState(int s)
Change the mesh state to NORMAL, TWO_LEVEL_COARSE, TWO_LEVEL_FINE.
int Size() const
Logical size of the array.
void Recreate(const int n, const int *p)
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 FreeElement(Element *E)
void ExchangeFaceNbrData()
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 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)
virtual void ReorientTetMesh()
See the remarks for the serial version in mesh.hpp.
int GetNBE() const
Returns number of boundary elements.
void GetLocalPtToSegTransformation(IsoparametricTransformation &, int)
Used in GetFaceElementTransformations (...)
Array< Element * > face_nbr_elements
double Det() const
Calculates the determinant of the matrix (for 2x2 or 3x3 matrices)
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)
int GetElementBaseGeometry(int i) const
const int * GetGroup(int g) const
void Copy(Array ©) const
Create a copy of the current array.
virtual void LocalRefinement(const Array< int > &marked_el, int type=3)
Refine the marked elements.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
int GetBdrElementEdgeIndex(int i) const
int GetNE() const
Returns number of elements.
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.
Abstract parallel finite element space.
Array< int > face_nbr_vertices_offset
void DeleteCoarseTables()
Array< int > face_nbr_group
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
void GetVertices(Vector &vert_coord) const
void CheckBdrElementOrientation(bool fix_it=true)
Check the orientation of the boundary elements.
FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
int Size_of_connections() const
const IntegrationRule * GetVertices(int GeomType)
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)
Array< FaceInfo > fc_faces_info
bool IAmMaster(int g) const
Element * NewElement(int geom)
FaceElementTransformations FaceElemTr
template void SortPairs< int, int >(Pair< int, int > *, int)
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)
Array< int > face_nbr_elements_offset
static const int quad_orientations[8][4]
int Append(const T &el)
Append element to array, resize if necessary.
int GetNumNeighbors() const
void GetLocalSegToTriTransformation(IsoparametricTransformation &loc, int i)
static FiniteElement * GetTransformationFEforElementType(int)
void AddConnection(int r, int c)
STable3D * GetElementToFaceTable(int ret_ftbl=0)
static void Rotate3(int &, int &, int &)
int MeshGenerator()
Truegrid or NetGen?
Table send_face_nbr_vertices
void CheckElementOrientation(bool fix_it=true)
Check the orientation of the elements.
int Insert(IntegerSet &s)
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
int GetAttribute() const
Return element's attribute.
int GetElementToEdgeTable(Table &, Array< int > &)
int GetElementType(int i) const
Returns the type of element i.
Data type triangle element.
const Element * GetElement(int i) const
void GetLocalQuadToHexTransformation(IsoparametricTransformation &loc, int i)
Used in GetFaceElementTransformations (...)
IsoparametricTransformation Transformation2
int Size() const
Returns the number of TYPE I elements.
FiniteElementSpace * FESpace()
virtual void ReorientTetMesh()
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.
void Swap(Array< T > &, Array< T > &)
Array< int > bdr_attributes
void UseTwoLevelState(int use)
void SetCoarseElem(Element *ce)
void RefineGroups(const DSTable &v_to_v, int *middle)
Update the groups after tet refinement.
Array< Vertex > face_nbr_vertices
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)
void GetElementVDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
MemAlloc< BisectedElement, 1024 > BEMemory
void PrintInfo(std::ostream &out=std::cout)
Print various parallel mesh stats.
virtual void QuadUniformRefinement()
Refine quadrilateral mesh.
virtual void HexUniformRefinement()
Refine hexahedral mesh.
Array< Element * > elements
virtual void PrintXG(std::ostream &out=std::cout) const
Array< int > fc_be_to_edge
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
void GetLocalTriToTetTransformation(IsoparametricTransformation &loc, int i)
Used in GetFaceElementTransformations (...)
NURBSExtension * NURBSext
void GroupFace(int group, int i, int &face, int &o)
void GetLocalSegToQuadTransformation(IsoparametricTransformation &loc, int i)
void ExchangeFaceNbrNodes()
void SetIJ(int *newI, int *newJ, int newsize=-1)
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.
Array< FaceInfo > faces_info
virtual int GetNVertices() const =0
void SetAttribute(const int attr)
Set element's attribute.
STable3D * GetFacesTable()
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.
void GetNodes(Vector &node_coord) const
void AverageVertices(int *indexes, int n, int result)
int NumberOfEntries() const
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
void PrintAsOneXG(std::ostream &out=std::cout)
Old mesh format (Netgen/Truegrid) version of 'PrintAsOne'.
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
Class for parallel grid function.
Table send_face_nbr_elements
Table * GetFaceToAllElementTable() const
FaceElementTransformations * GetSharedFaceTransformations(int)
void Bisection(int i, const DSTable &, int *, int *, int *)
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.
Table * GetVertexToElementTable()
The returned Table must be destroyed by the caller.
const Element * GetBdrElement(int i) const
virtual int GetType() const =0
Returns element's type.
void UpdateNodes()
Update the nodes of a curved mesh after refinement.
int GroupNEdges(int group)
void GreenRefinement(int i, const DSTable &v_to_v, int *edge1, int *edge2, int *middle)
static const int tri_orientations[6][3]
virtual void Print(std::ostream &out=std::cout) const