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),
33 MyComm = pmesh.MyComm;
34 NRanks = pmesh.NRanks;
35 MyRank = pmesh.MyRank;
38 shared_edges.SetSize(pmesh.shared_edges.Size());
39 for (
int i = 0; i < shared_edges.Size(); i++)
41 shared_edges[i] = pmesh.shared_edges[i]->Duplicate(
this);
45 shared_faces.SetSize(pmesh.shared_faces.Size());
46 for (
int i = 0; i < shared_faces.Size(); i++)
48 shared_faces[i] = pmesh.shared_faces[i]->Duplicate(
this);
52 pmesh.svert_lvert.
Copy(svert_lvert);
53 pmesh.sedge_ledge.
Copy(sedge_ledge);
54 pmesh.sface_lface.
Copy(sface_lface);
61 if (pmesh.
Nodes && copy_nodes)
71 Nodes->MakeOwner(fec_copy);
72 *Nodes = *pmesh.
Nodes;
77 ParMesh::ParMesh(MPI_Comm comm,
Mesh &mesh,
int *partitioning_,
86 MPI_Comm_size(MyComm, &NRanks);
87 MPI_Comm_rank(MyComm, &MyRank);
97 int* partition =
new int[mesh.
GetNE()];
98 for (
int i = 0; i < mesh.
GetNE(); i++)
133 partitioning = partitioning_;
145 int vert_counter, element_counter, bdrelem_counter;
148 vert_global_local = -1;
152 for (i = 0; i < mesh.
GetNE(); i++)
153 if (partitioning[i] == MyRank)
157 for (j = 0; j < vert.
Size(); j++)
158 if (vert_global_local[vert[j]] < 0)
160 vert_global_local[vert[j]] = vert_counter++;
169 for (i = vert_counter = 0; i < vert_global_local.
Size(); i++)
170 if (vert_global_local[i] >= 0)
172 vert_global_local[i] = vert_counter++;
176 for (i = 0; i < vert_global_local.Size(); i++)
177 if (vert_global_local[i] >= 0)
185 for (i = 0; i < mesh.
GetNE(); i++)
186 if (partitioning[i] == MyRank)
189 int *v =
elements[element_counter]->GetVertices();
190 int nv =
elements[element_counter]->GetNVertices();
191 for (j = 0; j < nv; j++)
193 v[j] = vert_global_local[v[j]];
198 Table *edge_element = NULL;
202 activeBdrElem =
false;
208 for (i = 0; i < mesh.
GetNBE(); i++)
210 int face, o, el1, el2;
213 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] == MyRank)
218 activeBdrElem[i] =
true;
225 for (i = 0; i < mesh.
GetNBE(); i++)
227 int face, o, el1, el2;
230 if (partitioning[(o % 2 == 0 || el2 < 0) ? el1 : el2] == MyRank)
233 int *v =
boundary[bdrelem_counter]->GetVertices();
234 int nv =
boundary[bdrelem_counter]->GetNVertices();
235 for (j = 0; j < nv; j++)
237 v[j] = vert_global_local[v[j]];
245 edge_element =
new Table;
249 for (i = 0; i < mesh.
GetNBE(); i++)
252 int el1 = edge_element->
GetRow(edge)[0];
253 if (partitioning[el1] == MyRank)
258 activeBdrElem[i] =
true;
265 for (i = 0; i < mesh.
GetNBE(); i++)
268 int el1 = edge_element->
GetRow(edge)[0];
269 if (partitioning[el1] == MyRank)
272 int *v =
boundary[bdrelem_counter]->GetVertices();
273 int nv =
boundary[bdrelem_counter]->GetNVertices();
274 for (j = 0; j < nv; j++)
276 v[j] = vert_global_local[v[j]];
285 for (i = 0; i < mesh.
GetNBE(); i++)
287 int vert = mesh.
boundary[i]->GetVertices()[0];
290 if (partitioning[el1] == MyRank)
298 for (i = 0; i < mesh.
GetNBE(); i++)
300 int vert = mesh.
boundary[i]->GetVertices()[0];
303 if (partitioning[el1] == MyRank)
306 int *v =
boundary[bdrelem_counter]->GetVertices();
307 v[0] = vert_global_local[v[0]];
354 cerr <<
"ParMesh::ParMesh (proc " << MyRank <<
") : "
355 "(Dim < 3 && mesh.GetNFaces() != 0) is true!" << endl;
360 int sface_counter = 0;
362 for (i = 0; i < face_group.Size(); i++)
369 el[0] = partitioning[el[0]];
370 el[1] = partitioning[el[1]];
371 if ((el[0] == MyRank && el[1] != MyRank) ||
372 (el[0] != MyRank && el[1] == MyRank))
375 face_group[i] = groups.
Insert(group) - 1;
382 int sedge_counter = 0;
385 edge_element =
new Table;
395 for (i = 0; i < edge_element->
Size(); i++)
397 int me = 0, others = 0;
398 for (j = edge_element->
GetI()[i]; j < edge_element->
GetI()[i+1]; j++)
400 edge_element->
GetJ()[j] = partitioning[edge_element->
GetJ()[j]];
401 if (edge_element->
GetJ()[j] == MyRank)
419 edge_element->
GetRow(i)[0] = -1;
424 int svert_counter = 0;
427 for (i = 0; i < vert_element->
Size(); i++)
429 int me = 0, others = 0;
430 for (j = vert_element->
GetI()[i]; j < vert_element->
GetI()[i+1]; j++)
432 vert_element->
GetJ()[j] = partitioning[vert_element->
GetJ()[j]];
433 if (vert_element->
GetJ()[j] == MyRank)
447 vert_element->
GetI()[i] = groups.
Insert(group) - 1;
451 vert_element->
GetI()[i] = -1;
458 for (i = 0; i < face_group.Size(); i++)
459 if (face_group[i] >= 0)
467 for (i = 0; i < face_group.Size(); i++)
468 if (face_group[i] >= 0)
478 for (i = 0; i < edge_element->
Size(); i++)
479 if (edge_element->
GetRow(i)[0] >= 0)
487 for (i = 0; i < edge_element->
Size(); i++)
488 if (edge_element->
GetRow(i)[0] >= 0)
497 for (i = 0; i < vert_element->
Size(); i++)
498 if (vert_element->
GetI()[i] >= 0)
506 for (i = 0; i < vert_element->
Size(); i++)
507 if (vert_element->
GetI()[i] >= 0)
514 shared_faces.SetSize(sface_counter);
515 sface_lface. SetSize(sface_counter);
520 for (i = 0; i < face_group.Size(); i++)
521 if (face_group[i] >= 0)
524 int *v = shared_faces[sface_counter]->GetVertices();
525 int nv = shared_faces[sface_counter]->GetNVertices();
526 for (j = 0; j < nv; j++)
528 v[j] = vert_global_local[v[j]];
530 switch (shared_faces[sface_counter]->GetType())
533 sface_lface[sface_counter] = (*faces_tbl)(v[0], v[1], v[2]);
538 int lface = sface_lface[sface_counter];
541 int re[2], type, flag, *tv;
549 case 1: v[0] = tv[1]; v[1] = tv[2]; v[2] = tv[3];
551 case 4: v[0] = tv[3]; v[1] = tv[1]; v[2] = tv[2];
553 case 5: v[0] = tv[2]; v[1] = tv[3]; v[2] = tv[1];
560 case 2: v[0] = tv[2]; v[1] = tv[0]; v[2] = tv[3];
562 case 3: v[0] = tv[0]; v[1] = tv[3]; v[2] = tv[2];
564 case 5: v[0] = tv[3]; v[1] = tv[2]; v[2] = tv[0];
569 v[0] = tv[0]; v[1] = tv[1]; v[2] = tv[3];
572 v[0] = tv[1]; v[1] = tv[0]; v[2] = tv[2];
580 if (MyRank == partitioning[gl_el2])
582 const int t = v[0]; v[0] = v[1]; v[1] = t;
588 sface_lface[sface_counter] =
589 (*faces_tbl)(v[0], v[1], v[2], v[3]);
599 shared_edges.SetSize(sedge_counter);
600 sedge_ledge. SetSize(sedge_counter);
607 for (i = 0; i < edge_element->
Size(); i++)
608 if (edge_element->
GetRow(i)[0] >= 0)
612 shared_edges[sedge_counter] =
613 new Segment(vert_global_local[vert[0]],
614 vert_global_local[vert[1]], 1);
616 if ((sedge_ledge[sedge_counter] =
617 v_to_v(vert_global_local[vert[0]],
618 vert_global_local[vert[1]])) < 0)
620 cerr <<
"\n\n\n" << MyRank <<
": ParMesh::ParMesh: "
621 <<
"ERROR in v_to_v\n\n" << endl;
632 svert_lvert.
SetSize(svert_counter);
635 for (i = 0; i < vert_element->
Size(); i++)
636 if (vert_element->
GetI()[i] >= 0)
638 svert_lvert[svert_counter++] = vert_global_local[i];
660 for (i = 0; i < mesh.
GetNE(); i++)
661 if (partitioning[i] == MyRank)
664 mesh.
GetNodes()->FESpace()->GetElementVDofs(i, gvdofs);
665 mesh.
GetNodes()->GetSubVector(gvdofs, lnodes);
671 if (partitioning_ == NULL)
673 delete [] partitioning;
679 ParMesh::ParMesh(
const ParNCMesh &pncmesh)
680 : MyComm(pncmesh.MyComm)
681 , NRanks(pncmesh.NRanks)
682 , MyRank(pncmesh.MyRank)
694 int sedge = group_sedge.
GetJ()[group_sedge.
GetI()[group-1]+i];
695 edge = sedge_ledge[sedge];
696 int *v = shared_edges[sedge]->GetVertices();
697 o = (v[0] < v[1]) ? (+1) : (-1);
702 int sface = group_sface.
GetJ()[group_sface.
GetI()[group-1]+i];
703 face = sface_lface[sface];
717 int ParMesh::GetEdgeSplittings(
Element *edge,
const DSTable &v_to_v,
722 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
739 int ParMesh::GetFaceSplittings(Element *face,
const DSTable &v_to_v,
743 int number_of_splittings = 0;
744 int *v = face->GetVertices();
746 if ((m = v_to_v(v[0], v[1])) != -1 && middle[m] != -1)
748 number_of_splittings++;
749 if ((m = v_to_v(v[1], v[2])) != -1 && middle[m] != -1)
752 number_of_splittings++;
754 if ((m = v_to_v(v[2], v[0])) != -1 && middle[m] != -1)
756 number_of_splittings++;
759 switch (number_of_splittings)
764 number_of_splittings++;
768 number_of_splittings++;
773 return number_of_splittings;
776 void ParMesh::GetFaceNbrElementTransformation(
777 int i, IsoparametricTransformation *ElTr)
779 DenseMatrix &pointmat = ElTr->GetPointMat();
782 ElTr->Attribute = elem->GetAttribute();
787 const int nv = elem->GetNVertices();
788 const int *v = elem->GetVertices();
792 for (
int j = 0; j < nv; j++)
802 ParGridFunction *pNodes =
dynamic_cast<ParGridFunction *
>(
Nodes);
805 pNodes->ParFESpace()->GetFaceNbrElementVDofs(i, vdofs);
807 pointmat.SetSize(spaceDim, n);
809 for (
int j = 0; j < n; j++)
811 pointmat(k,j) = (pNodes->FaceNbrData())(vdofs[n*k+j]);
814 ElTr->SetFE(pNodes->ParFESpace()->GetFaceNbrFE(i));
817 mfem_error(
"ParMesh::GetFaceNbrElementTransformation : "
818 "Nodes are not ParGridFunction!");
822 void ParMesh::DeleteFaceNbrData()
854 gr_sface = &group_svert;
855 s2l_face = svert_lvert;
859 gr_sface = &group_sedge;
860 s2l_face = sedge_ledge;
864 gr_sface = &group_sface;
865 s2l_face = sface_lface;
868 int num_face_nbrs = 0;
870 if (gr_sface->
RowSize(g-1) > 0)
877 if (num_face_nbrs == 0)
887 for (
int g = 1, counter = 0; g <
GetNGroups(); g++)
888 if (gr_sface->
RowSize(g-1) > 0)
892 mfem_error(
"ParMesh::ExchangeFaceNbrData() : "
893 "group size is not 2!");
896 int lproc = (nbs[0]) ? nbs[0] : nbs[1];
898 rank_group[counter].two = g;
904 for (
int fn = 0; fn < num_face_nbrs; fn++)
910 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
911 MPI_Request *send_requests = requests;
912 MPI_Request *recv_requests = requests + num_face_nbrs;
913 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
915 int *nbr_data =
new int[6*num_face_nbrs];
916 int *nbr_send_data = nbr_data;
917 int *nbr_recv_data = nbr_data + 3*num_face_nbrs;
924 Table send_face_nbr_elemdata, send_face_nbr_facedata;
928 send_face_nbr_elemdata.
MakeI(num_face_nbrs);
929 send_face_nbr_facedata.
MakeI(num_face_nbrs);
930 for (
int fn = 0; fn < num_face_nbrs; fn++)
933 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
934 int *sface = gr_sface->
GetRow(nbr_group-1);
935 for (
int i = 0; i < num_sfaces; i++)
937 int lface = s2l_face[sface[i]];
939 if (el_marker[el] != fn)
944 const int nv =
elements[el]->GetNVertices();
945 const int *v =
elements[el]->GetVertices();
946 for (
int j = 0; j < nv; j++)
947 if (vertex_marker[v[j]] != fn)
949 vertex_marker[v[j]] = fn;
960 nbr_send_data[3*fn+2] = send_face_nbr_elemdata.
GetI()[fn];
965 MPI_Isend(&nbr_send_data[3*fn], 3, MPI_INT, nbr_rank, tag, MyComm,
967 MPI_Irecv(&nbr_recv_data[3*fn], 3, MPI_INT, nbr_rank, tag, MyComm,
972 send_face_nbr_elemdata.
MakeJ();
973 send_face_nbr_facedata.
MakeJ();
976 for (
int fn = 0; fn < num_face_nbrs; fn++)
979 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
980 int *sface = gr_sface->
GetRow(nbr_group-1);
981 for (
int i = 0; i < num_sfaces; i++)
983 int lface = s2l_face[sface[i]];
985 if (el_marker[el] != fn)
990 const int nv =
elements[el]->GetNVertices();
991 const int *v =
elements[el]->GetVertices();
992 for (
int j = 0; j < nv; j++)
993 if (vertex_marker[v[j]] != fn)
995 vertex_marker[v[j]] = fn;
1011 const int *sf_v = shared_faces[sface[i]]->GetVertices();
1032 for (
int fn = 0; fn < num_face_nbrs; fn++)
1038 int *elemdata = send_face_nbr_elemdata.
GetRow(fn);
1039 int num_sfaces = send_face_nbr_facedata.
RowSize(fn)/2;
1040 int *facedata = send_face_nbr_facedata.
GetRow(fn);
1042 for (
int i = 0; i < num_verts; i++)
1044 vertex_marker[verts[i]] = i;
1047 for (
int el = 0; el < num_elems; el++)
1049 const int nv =
elements[el]->GetNVertices();
1051 for (
int j = 0; j < nv; j++)
1053 elemdata[j] = vertex_marker[elemdata[j]];
1057 el_marker[elems[el]] = el;
1060 for (
int i = 0; i < num_sfaces; i++)
1062 facedata[2*i] = el_marker[facedata[2*i]];
1066 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1069 Table recv_face_nbr_elemdata;
1074 recv_face_nbr_elemdata.
MakeI(num_face_nbrs);
1077 for (
int fn = 0; fn < num_face_nbrs; fn++)
1085 recv_face_nbr_elemdata.
MakeJ();
1087 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1090 for (
int fn = 0; fn < num_face_nbrs; fn++)
1095 MPI_Isend(send_face_nbr_elemdata.
GetRow(fn),
1096 send_face_nbr_elemdata.
RowSize(fn),
1097 MPI_INT, nbr_rank, tag, MyComm, &send_requests[fn]);
1099 MPI_Irecv(recv_face_nbr_elemdata.
GetRow(fn),
1100 recv_face_nbr_elemdata.
RowSize(fn),
1101 MPI_INT, nbr_rank, tag, MyComm, &recv_requests[fn]);
1109 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1111 if (fn == MPI_UNDEFINED)
1119 int *recv_elemdata = recv_face_nbr_elemdata.
GetRow(fn);
1121 for (
int i = 0; i < num_elems; i++)
1127 for (
int j = 0; j < nv; j++)
1129 recv_elemdata[j] += vert_off;
1132 recv_elemdata += nv;
1137 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1140 recv_face_nbr_facedata.
SetSize(
1142 for (
int fn = 0; fn < num_face_nbrs; fn++)
1147 MPI_Isend(send_face_nbr_facedata.
GetRow(fn),
1148 send_face_nbr_facedata.
RowSize(fn),
1149 MPI_INT, nbr_rank, tag, MyComm, &send_requests[fn]);
1152 MPI_Irecv(&recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]],
1153 send_face_nbr_facedata.
RowSize(fn),
1154 MPI_INT, nbr_rank, tag, MyComm, &recv_requests[fn]);
1161 MPI_Waitany(num_face_nbrs, recv_requests, &fn, statuses);
1163 if (fn == MPI_UNDEFINED)
1170 int num_sfaces = gr_sface->
RowSize(nbr_group-1);
1171 int *sface = gr_sface->
GetRow(nbr_group-1);
1173 &recv_face_nbr_facedata[send_face_nbr_facedata.
GetI()[fn]];
1175 for (
int i = 0; i < num_sfaces; i++)
1177 int lface = s2l_face[sface[i]];
1179 face_info.
Elem2No = -1 - (facedata[2*i] + elem_off);
1180 int info = facedata[2*i+1];
1188 int nbr_ori = info%64, nbr_v[4];
1190 const int *sf_v = shared_faces[sface[i]]->GetVertices();
1196 for (
int j = 0; j < 3; j++)
1198 nbr_v[perm[j]] = sf_v[j];
1207 for (
int j = 0; j < 4; j++)
1209 nbr_v[perm[j]] = sf_v[j];
1215 info = 64*(info/64) + nbr_ori;
1221 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1242 else if (
Nodes == NULL)
1246 MPI_Request *requests =
new MPI_Request[2*num_face_nbrs];
1247 MPI_Request *send_requests = requests;
1248 MPI_Request *recv_requests = requests + num_face_nbrs;
1249 MPI_Status *statuses =
new MPI_Status[num_face_nbrs];
1253 for (
int i = 0; i < send_vertices.Size(); i++)
1259 for (
int fn = 0; fn < num_face_nbrs; fn++)
1266 MPI_DOUBLE, nbr_rank, tag, MyComm, &send_requests[fn]);
1271 MPI_DOUBLE, nbr_rank, tag, MyComm, &recv_requests[fn]);
1274 MPI_Waitall(num_face_nbrs, recv_requests, statuses);
1275 MPI_Waitall(num_face_nbrs, send_requests, statuses);
1288 mfem_error(
"ParMesh::ExchangeFaceNbrNodes() : "
1289 "Nodes are not ParGridFunction!");
1297 int nbr_lproc = (nbs[0]) ? nbs[0] : nbs[1];
1308 s2l_face = &svert_lvert;
1312 s2l_face = &sedge_ledge;
1316 s2l_face = &sface_lface;
1334 for (
int i = 0; i < s2l_face->
Size(); i++)
1349 for (
int i = 0; i < s2l_face->
Size(); i++)
1351 int lface = (*s2l_face)[i];
1352 int nbr_elem_idx = -1 -
faces_info[lface].Elem2No;
1413 return svert_lvert.
Size();
1417 return sedge_ledge.
Size();
1419 return sface_lface.
Size();
1426 case 1:
return svert_lvert[sface];
1427 case 2:
return sedge_ledge[sface];
1429 return sface_lface[sface];
1448 for (
int i = 0; i < shared_edges.Size(); i++)
1450 v = shared_edges[i]->GetVertices();
1451 sedge_ledge[i] = v_to_v(v[0], v[1]);
1463 for (
int i = 0; i < shared_faces.Size(); i++)
1466 v = shared_faces[i]->GetVertices();
1470 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2]);
1476 void ParMesh::LocalRefinement(
const Array<int> &marked_el,
int type)
1487 DeleteFaceNbrData();
1500 int uniform_refinement = 0;
1504 uniform_refinement = 1;
1512 Array<int> middle(v_to_v.NumberOfEntries());
1519 for (i = 0; i < marked_el.
Size(); i++)
1521 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1525 for (i = 0; i < marked_el.
Size(); i++)
1527 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1530 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1534 for (i = 0; i < marked_el.
Size(); i++)
1536 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1539 Bisection(j, v_to_v, NULL, NULL, middle);
1541 Bisection(j, v_to_v, NULL, NULL, middle);
1543 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1545 Bisection(marked_el[i], v_to_v, NULL, NULL, middle);
1557 int need_refinement;
1558 int refined_edge[5][3] =
1566 int faces_in_group, max_faces_in_group = 0;
1568 int **face_splittings =
new int*[
GetNGroups()-1];
1572 face_splittings[i] =
new int[faces_in_group];
1573 if (faces_in_group > max_faces_in_group)
1575 max_faces_in_group = faces_in_group;
1578 int neighbor, *iBuf =
new int[max_faces_in_group];
1580 Array<int> group_faces;
1583 MPI_Request request;
1587 int ref_loops_all = 0, ref_loops_par = 0;
1591 need_refinement = 0;
1594 if (
elements[i]->NeedRefinement(v_to_v, middle))
1596 need_refinement = 1;
1597 Bisection(i, v_to_v, NULL, NULL, middle);
1604 if (uniform_refinement)
1611 if (need_refinement == 0)
1621 group_sface.
GetRow(i, group_faces);
1622 faces_in_group = group_faces.Size();
1624 if (faces_in_group != 0)
1626 for (j = 0; j < faces_in_group; j++)
1627 face_splittings[i][j] =
1628 GetFaceSplittings(shared_faces[group_faces[j]], v_to_v,
1639 MPI_Isend(face_splittings[i], faces_in_group, MPI_INT,
1640 neighbor, 0, MyComm, &request);
1647 group_sface.
GetRow(i, group_faces);
1648 faces_in_group = group_faces.Size();
1649 if (faces_in_group != 0)
1660 MPI_Recv(iBuf, faces_in_group, MPI_INT, neighbor,
1661 MPI_ANY_TAG, MyComm, &status);
1663 for (j = 0; j < faces_in_group; j++)
1664 if (iBuf[j] != face_splittings[i][j])
1666 int *v = shared_faces[group_faces[j]]->GetVertices();
1667 for (
int k = 0; k < 3; k++)
1668 if (refined_edge[iBuf[j]][k] == 1 &&
1669 refined_edge[face_splittings[i][j]][k] == 0)
1671 int ii = v_to_v(v[k], v[(k+1)%3]);
1672 if (middle[ii] == -1)
1674 need_refinement = 1;
1676 for (
int c = 0; c < 3; c++)
1686 i = need_refinement;
1687 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR, MyComm);
1690 while (need_refinement == 1);
1694 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0, MyComm);
1697 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
1698 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
1706 delete [] face_splittings[i];
1708 delete [] face_splittings;
1714 need_refinement = 0;
1716 if (
boundary[i]->NeedRefinement(v_to_v, middle))
1718 need_refinement = 1;
1722 while (need_refinement == 1);
1724 if (NumOfBdrElements !=
boundary.Size())
1726 " (NumOfBdrElements != boundary.Size())");
1747 int refinement_edges[2], type, flag;
1753 El = ((BisectedElement *) El)->FirstChild;
1755 ((
Tetrahedron *) El)->ParseRefinementFlag(refinement_edges,
1758 ((
Tetrahedron *) El)->CreateRefinementFlag(refinement_edges,
1805 int uniform_refinement = 0;
1809 uniform_refinement = 1;
1817 int nedges = v_to_v.NumberOfEntries();
1818 int *edge1 =
new int[nedges];
1819 int *edge2 =
new int[nedges];
1820 int *middle =
new int[nedges];
1822 for (i = 0; i < nedges; i++)
1824 edge1[i] = edge2[i] = middle[i] = -1;
1829 int *v =
elements[i]->GetVertices();
1830 for (j = 0; j < 3; j++)
1832 int ind = v_to_v(v[j], v[(j+1)%3]);
1833 (edge1[ind] == -1) ? (edge1[ind] = i) : (edge2[ind] = i);
1838 for (i = 0; i < marked_el.
Size(); i++)
1850 int need_refinement;
1851 int edges_in_group, max_edges_in_group = 0;
1853 int **edge_splittings =
new int*[
GetNGroups()-1];
1857 edge_splittings[i] =
new int[edges_in_group];
1858 if (edges_in_group > max_edges_in_group)
1860 max_edges_in_group = edges_in_group;
1863 int neighbor, *iBuf =
new int[max_edges_in_group];
1865 Array<int> group_edges;
1867 MPI_Request request;
1873 int ref_loops_all = 0, ref_loops_par = 0;
1877 need_refinement = 0;
1878 for (i = 0; i < nedges; i++)
1879 if (middle[i] != -1 && edge1[i] != -1)
1881 need_refinement = 1;
1888 if (uniform_refinement)
1895 if (need_refinement == 0)
1905 group_sedge.
GetRow(i, group_edges);
1906 edges_in_group = group_edges.Size();
1908 if (edges_in_group != 0)
1910 for (j = 0; j < edges_in_group; j++)
1911 edge_splittings[i][j] =
1912 GetEdgeSplittings(shared_edges[group_edges[j]], v_to_v,
1923 MPI_Isend(edge_splittings[i], edges_in_group, MPI_INT,
1924 neighbor, 0, MyComm, &request);
1931 group_sedge.
GetRow(i, group_edges);
1932 edges_in_group = group_edges.Size();
1933 if (edges_in_group != 0)
1944 MPI_Recv(iBuf, edges_in_group, MPI_INT, neighbor,
1945 MPI_ANY_TAG, MyComm, &status);
1947 for (j = 0; j < edges_in_group; j++)
1948 if (iBuf[j] == 1 && edge_splittings[i][j] == 0)
1950 int *v = shared_edges[group_edges[j]]->GetVertices();
1951 int ii = v_to_v(v[0], v[1]);
1953 if (middle[ii] != -1)
1954 mfem_error(
"ParMesh::LocalRefinement (triangles) : "
1957 need_refinement = 1;
1959 for (
int c = 0; c < 2; c++)
1968 i = need_refinement;
1969 MPI_Allreduce(&i, &need_refinement, 1, MPI_INT, MPI_LOR, MyComm);
1972 while (need_refinement == 1);
1976 MPI_Reduce(&i, &ref_loops_all, 1, MPI_INT, MPI_MAX, 0, MyComm);
1979 cout <<
"\n\nParMesh::LocalRefinement : max. ref_loops_all = "
1980 << ref_loops_all <<
", ref_loops_par = " << ref_loops_par
1987 delete [] edge_splittings[i];
1989 delete [] edge_splittings;
1994 int v1[2], v2[2], bisect, temp;
1996 for (i = 0; i < temp; i++)
1998 int *v =
boundary[i]->GetVertices();
1999 bisect = v_to_v(v[0], v[1]);
2000 if (middle[bisect] != -1)
2005 v1[0] = v[0]; v1[1] = middle[bisect];
2006 v2[0] = middle[bisect]; v2[1] = v[1];
2011 #ifdef MFEM_USE_MEMALLOC
2012 BisectedElement *aux =
BEMemory.Alloc();
2015 BisectedElement *aux =
new BisectedElement(
boundary[i]);
2030 mfem_error(
"Only bisection of segment is implemented for bdr"
2034 NumOfBdrElements =
boundary.Size();
2083 NumOfElements += marked_el.
Size();
2086 for (j = 0; j < marked_el.
Size(); j++)
2089 Segment *c_seg = (Segment *)
elements[i];
2090 int *vert = c_seg->GetVertices(), attr = c_seg->GetAttribute();
2091 int new_v = cnv + j, new_e = cne + j;
2093 elements[new_e] =
new Segment(new_v, vert[1], attr);
2096 #ifdef MFEM_USE_MEMALLOC
2097 BisectedElement *aux =
BEMemory.Alloc();
2098 aux->SetCoarseElem(c_seg);
2100 BisectedElement *aux =
new BisectedElement(c_seg);
2102 aux->FirstChild =
new Segment(vert[0], new_v, attr);
2103 aux->SecondChild = new_e;
2136 void ParMesh::NonconformingRefinement(
const Array<Refinement> &refinements,
2141 MFEM_ABORT(
"ParMesh::NonconformingRefinement: NURBS meshes are not "
2142 "supported. Project the NURBS to Nodes first.");
2157 MFEM_ABORT(
"Can't convert conforming ParMesh to nonconforming ParMesh "
2158 "(you need to initialize the ParMesh from a nonconforming "
2176 ParMesh* pmesh2 =
new ParMesh(*
pncmesh);
2184 Swap(*pmesh2,
false);
2206 int i, attr, newv[3], ind, f_ind, *v;
2209 Array<int> group_verts, group_edges, group_faces;
2217 int *I_group_svert, *J_group_svert;
2218 int *I_group_sedge, *J_group_sedge;
2219 int *I_group_sface, *J_group_sface;
2229 I_group_sface = NULL;
2232 I_group_svert[0] = I_group_svert[1] = 0;
2233 I_group_sedge[0] = I_group_sedge[1] = 0;
2236 I_group_sface[0] = I_group_sface[1] = 0;
2253 J_group_sface = NULL;
2257 J_group_svert = J_group_sedge = J_group_sface = NULL;
2260 for (group = 0; group <
GetNGroups()-1; group++)
2263 group_svert.
GetRow(group, group_verts);
2264 group_sedge.
GetRow(group, group_edges);
2265 group_sface.
GetRow(group, group_faces);
2268 for (i = 0; i < group_sedge.
RowSize(group); i++)
2270 v = shared_edges[group_edges[i]]->GetVertices();
2271 ind = middle[v_to_v(v[0], v[1])];
2277 attr = shared_edges[group_edges[i]]->GetAttribute();
2278 shared_edges.Append(
new Segment(v[1], ind, attr));
2285 for (i = 0; i < group_sface.
RowSize(group); i++)
2287 v = shared_faces[group_faces[i]]->GetVertices();
2288 ind = middle[v_to_v(v[0], v[1])];
2291 attr = shared_faces[group_faces[i]]->GetAttribute();
2293 shared_edges.Append(
new Segment(v[2], ind, attr));
2296 f_ind = group_faces.
Size();
2297 shared_faces.Append(
new Triangle(v[1], v[2], ind, attr));
2299 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2300 shared_faces[group_faces[i]]->SetVertices(newv);
2304 ind = middle[v_to_v(v[0], v[1])];
2308 shared_edges.Append(
new Segment(v[2], ind, attr));
2311 shared_faces.Append(
new Triangle(v[1], v[2], ind, attr));
2313 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2314 shared_faces[group_faces[i]]->SetVertices(newv);
2318 v = shared_faces[group_faces[f_ind]]->GetVertices();
2319 ind = middle[v_to_v(v[0], v[1])];
2323 shared_edges.Append(
new Segment(v[2], ind, attr));
2326 shared_faces.Append(
new Triangle(v[1], v[2], ind, attr));
2328 newv[0] = v[2]; newv[1] = v[0]; newv[2] = ind;
2329 shared_faces[group_faces[f_ind]]->SetVertices(newv);
2334 I_group_svert[group+1] = I_group_svert[group] + group_verts.
Size();
2335 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.
Size();
2338 I_group_sface[group+1] = I_group_sface[group] + group_faces.
Size();
2342 J = J_group_svert+I_group_svert[group];
2343 for (i = 0; i < group_verts.
Size(); i++)
2345 J[i] = group_verts[i];
2347 J = J_group_sedge+I_group_sedge[group];
2348 for (i = 0; i < group_edges.
Size(); i++)
2350 J[i] = group_edges[i];
2354 J = J_group_sface+I_group_sface[group];
2355 for (i = 0; i < group_faces.
Size(); i++)
2357 J[i] = group_faces[i];
2366 for (i = 0; i < shared_edges.Size(); i++)
2368 v = shared_edges[i]->GetVertices();
2369 sedge_ledge[i] = new_v_to_v(v[0], v[1]);
2375 for (i = 0; i < shared_faces.Size(); i++)
2377 v = shared_faces[i]->GetVertices();
2378 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2]);
2383 group_svert.
SetIJ(I_group_svert, J_group_svert);
2384 group_sedge.
SetIJ(I_group_sedge, J_group_sedge);
2387 group_sface.
SetIJ(I_group_sface, J_group_sface);
2391 void ParMesh::QuadUniformRefinement()
2394 DeleteFaceNbrData();
2405 GridFunction *nodes =
Nodes;
2413 int i, attr, ind, *v;
2416 Array<int> sverts, sedges;
2418 int *I_group_svert, *J_group_svert;
2419 int *I_group_sedge, *J_group_sedge;
2424 I_group_svert[0] = I_group_svert[1] = 0;
2425 I_group_sedge[0] = I_group_sedge[1] = 0;
2432 for (group = 0; group <
GetNGroups()-1; group++)
2435 group_svert.
GetRow(group, sverts);
2436 group_sedge.
GetRow(group, sedges);
2439 for (i = 0; i < group_sedge.
RowSize(group); i++)
2441 v = shared_edges[sedges[i]]->GetVertices();
2442 ind = oedge + sedge_ledge[sedges[i]];
2446 attr = shared_edges[sedges[i]]->GetAttribute();
2447 shared_edges.Append(
new Segment(v[1], ind, attr));
2448 sedges.Append(sedge_ledge.
Append(-1)-1);
2452 I_group_svert[group+1] = I_group_svert[group] + sverts.Size();
2453 I_group_sedge[group+1] = I_group_sedge[group] + sedges.Size();
2456 J = J_group_svert+I_group_svert[group];
2457 for (i = 0; i < sverts.Size(); i++)
2461 J = J_group_sedge+I_group_sedge[group];
2462 for (i = 0; i < sedges.Size(); i++)
2471 for (i = 0; i < shared_edges.Size(); i++)
2473 v = shared_edges[i]->GetVertices();
2474 sedge_ledge[i] = v_to_v(v[0], v[1]);
2477 group_svert.
SetIJ(I_group_svert, J_group_svert);
2478 group_sedge.
SetIJ(I_group_sedge, J_group_sedge);
2488 void ParMesh::HexUniformRefinement()
2491 DeleteFaceNbrData();
2508 GridFunction *nodes =
Nodes;
2516 int i, attr, newv[4], ind, m[5];
2520 Array<int> group_verts, group_edges, group_faces;
2522 int *I_group_svert, *J_group_svert;
2523 int *I_group_sedge, *J_group_sedge;
2524 int *I_group_sface, *J_group_sface;
2530 I_group_svert[0] = I_group_svert[1] = 0;
2531 I_group_sedge[0] = I_group_sedge[1] = 0;
2532 I_group_sface[0] = I_group_sface[1] = 0;
2542 for (group = 0; group <
GetNGroups()-1; group++)
2545 group_svert.
GetRow(group, group_verts);
2546 group_sedge.
GetRow(group, group_edges);
2547 group_sface.
GetRow(group, group_faces);
2550 for (i = 0; i < group_sedge.
RowSize(group); i++)
2552 shared_edges[group_edges[i]]->GetVertices(v);
2553 ind = oedge + v_to_v(v[0], v[1]);
2555 group_verts.Append(svert_lvert.
Append(ind)-1);
2557 attr = shared_edges[group_edges[i]]->GetAttribute();
2558 shared_edges.Append(
new Segment(v[1], ind, attr));
2559 group_edges.Append(sedge_ledge.
Append(-1)-1);
2560 newv[0] = v[0]; newv[1] = ind;
2561 shared_edges[group_edges[i]]->SetVertices(newv);
2565 for (i = 0; i < group_sface.
RowSize(group); i++)
2567 shared_faces[group_faces[i]]->GetVertices(v);
2568 m[0] = oface+(*faces_tbl)(v[0], v[1], v[2], v[3]);
2570 group_verts.Append(svert_lvert.
Append(m[0])-1);
2572 attr = shared_faces[group_faces[i]]->GetAttribute();
2573 m[1] = oedge + v_to_v(v[0], v[1]);
2574 m[2] = oedge + v_to_v(v[1], v[2]);
2575 m[3] = oedge + v_to_v(v[2], v[3]);
2576 m[4] = oedge + v_to_v(v[3], v[0]);
2577 shared_edges.Append(
new Segment(m[1], m[0], attr));
2578 group_edges.Append(sedge_ledge.
Append(-1)-1);
2579 shared_edges.Append(
new Segment(m[2], m[0], attr));
2580 group_edges.Append(sedge_ledge.
Append(-1)-1);
2581 shared_edges.Append(
new Segment(m[3], m[0], attr));
2582 group_edges.Append(sedge_ledge.
Append(-1)-1);
2583 shared_edges.Append(
new Segment(m[4], m[0], attr));
2584 group_edges.Append(sedge_ledge.
Append(-1)-1);
2586 newv[0] = v[0]; newv[1] = m[1]; newv[2] = m[0]; newv[3] = m[4];
2587 shared_faces[group_faces[i]]->SetVertices(newv);
2588 shared_faces.Append(
new Quadrilateral(m[1],v[1],m[2],m[0],attr));
2589 group_faces.Append(sface_lface.
Append(-1)-1);
2590 shared_faces.Append(
new Quadrilateral(m[0],m[2],v[2],m[3],attr));
2591 group_faces.Append(sface_lface.
Append(-1)-1);
2592 shared_faces.Append(
new Quadrilateral(m[4],m[0],m[3],v[3],attr));
2593 group_faces.Append(sface_lface.
Append(-1)-1);
2596 I_group_svert[group+1] = I_group_svert[group] + group_verts.Size();
2597 I_group_sedge[group+1] = I_group_sedge[group] + group_edges.Size();
2598 I_group_sface[group+1] = I_group_sface[group] + group_faces.Size();
2601 J = J_group_svert+I_group_svert[group];
2602 for (i = 0; i < group_verts.Size(); i++)
2604 J[i] = group_verts[i];
2606 J = J_group_sedge+I_group_sedge[group];
2607 for (i = 0; i < group_edges.Size(); i++)
2609 J[i] = group_edges[i];
2611 J = J_group_sface+I_group_sface[group];
2612 for (i = 0; i < group_faces.Size(); i++)
2614 J[i] = group_faces[i];
2621 for (i = 0; i < shared_edges.Size(); i++)
2623 shared_edges[i]->GetVertices(v);
2624 sedge_ledge[i] = new_v_to_v(v[0], v[1]);
2629 for (i = 0; i < shared_faces.Size(); i++)
2631 shared_faces[i]->GetVertices(v);
2632 sface_lface[i] = (*faces_tbl)(v[0], v[1], v[2], v[3]);
2636 group_svert.
SetIJ(I_group_svert, J_group_svert);
2637 group_sedge.
SetIJ(I_group_sedge, J_group_sedge);
2638 group_sface.
SetIJ(I_group_sface, J_group_sface);
2648 void ParMesh::NURBSUniformRefinement()
2652 cout <<
"\nParMesh::NURBSUniformRefinement : Not supported yet!\n";
2658 MFEM_ASSERT(
Dim == spaceDim,
"2D manifolds not supported");
2664 out <<
"NETGEN_Neutral_Format\n";
2669 for (j = 0; j <
Dim; j++)
2677 out << NumOfElements <<
'\n';
2682 out <<
elements[i]->GetAttribute();
2683 for (j = 0; j < nv; j++)
2685 out <<
" " << ind[j]+1;
2691 out << NumOfBdrElements + shared_faces.Size() <<
'\n';
2697 out <<
boundary[i]->GetAttribute();
2698 for (j = 0; j < nv; j++)
2700 out <<
" " << ind[j]+1;
2705 for (i = 0; i < shared_faces.Size(); i++)
2707 nv = shared_faces[i]->GetNVertices();
2708 ind = shared_faces[i]->GetVertices();
2709 out << shared_faces[i]->GetAttribute();
2710 for (j = 0; j < nv; j++)
2712 out <<
" " << ind[j]+1;
2724 <<
"1 " <<
NumOfVertices <<
" " << NumOfElements <<
" 0 0 0 0 0 0 0\n"
2725 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
2726 <<
"0 0 " << NumOfBdrElements+shared_faces.Size()
2727 <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
2728 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
2729 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
2734 <<
" " <<
vertices[i](2) <<
" 0.0\n";
2741 out << i+1 <<
" " <<
elements[i]->GetAttribute();
2742 for (j = 0; j < nv; j++)
2744 out <<
" " << ind[j]+1;
2754 out <<
boundary[i]->GetAttribute();
2755 for (j = 0; j < nv; j++)
2757 out <<
" " << ind[j]+1;
2759 out <<
" 1.0 1.0 1.0 1.0\n";
2763 for (i = 0; i < shared_faces.Size(); i++)
2765 nv = shared_faces[i]->GetNVertices();
2766 ind = shared_faces[i]->GetVertices();
2767 out << shared_faces[i]->GetAttribute();
2768 for (j = 0; j < nv; j++)
2770 out <<
" " << ind[j]+1;
2772 out <<
" 1.0 1.0 1.0 1.0\n";
2781 out <<
"areamesh2\n\n";
2784 out << NumOfBdrElements + shared_edges.Size() <<
'\n';
2788 attr =
boundary[i]->GetAttribute();
2791 for (j = 0; j < v.
Size(); j++)
2793 out << v[j] + 1 <<
" ";
2798 for (i = 0; i < shared_edges.Size(); i++)
2800 attr = shared_edges[i]->GetAttribute();
2801 shared_edges[i]->GetVertices(v);
2803 for (j = 0; j < v.
Size(); j++)
2805 out << v[j] + 1 <<
" ";
2811 out << NumOfElements <<
'\n';
2814 attr =
elements[i]->GetAttribute();
2830 for (j = 0; j < v.
Size(); j++)
2832 out << v[j] + 1 <<
" ";
2841 for (j = 0; j <
Dim; j++)
2852 bool print_shared =
true;
2853 int i, j, shared_bdr_attr;
2859 s2l_face = ((
Dim == 1) ? &svert_lvert :
2860 ((
Dim == 2) ? &sedge_ledge : &sface_lface));
2864 s2l_face = &nc_shared_faces;
2871 for (
unsigned i = 0; i < sfaces.
conforming.size(); i++)
2874 if (index < nfaces) { nc_shared_faces.
Append(index); }
2876 for (
unsigned i = 0; i < sfaces.
masters.size(); i++)
2878 int index = sfaces.
masters[i].index;
2879 if (index < nfaces) { nc_shared_faces.
Append(index); }
2881 for (
unsigned i = 0; i < sfaces.
slaves.size(); i++)
2883 int index = sfaces.
slaves[i].index;
2884 if (index < nfaces) { nc_shared_faces.
Append(index); }
2895 out <<
"MFEM mesh v1.0\n";
2899 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
2904 "# TETRAHEDRON = 4\n"
2908 out <<
"\ndimension\n" <<
Dim
2909 <<
"\n\nelements\n" << NumOfElements <<
'\n';
2916 if (print_shared &&
Dim > 1)
2918 num_bdr_elems += s2l_face->
Size();
2920 out <<
"\nboundary\n" << num_bdr_elems <<
'\n';
2926 if (print_shared &&
Dim > 1)
2934 shared_bdr_attr = MyRank + 1;
2936 for (i = 0; i < s2l_face->
Size(); i++)
2939 faces[(*s2l_face)[i]]->SetAttribute(shared_bdr_attr);
2946 out << spaceDim <<
'\n';
2970 for (
int i = 0; i < nv; i++)
2978 int i, j, k, p, nv_ne[2], &nv = nv_ne[0], &ne = nv_ne[1], vc;
2986 out <<
"MFEM mesh v1.0\n";
2990 "\n#\n# MFEM Geometry Types (see mesh/geom.hpp):\n#\n"
2995 "# TETRAHEDRON = 4\n"
2999 out <<
"\ndimension\n" <<
Dim;
3003 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3006 out <<
"\n\nelements\n" << ne <<
'\n';
3010 out << 1 <<
' ' <<
elements[i]->GetGeometryType();
3014 for (j = 0; j < nv; j++)
3021 for (p = 1; p < NRanks; p++)
3023 MPI_Recv(nv_ne, 2, MPI_INT, p, 444, MyComm, &status);
3025 MPI_Recv(&ints[0], ne, MPI_INT, p, 445, MyComm, &status);
3026 for (i = 0; i < ne; )
3029 out << p+1 <<
' ' << ints[i];
3032 for (j = 0; j < k; j++)
3034 out <<
' ' << vc + ints[i++];
3047 ne += 1 +
elements[i]->GetNVertices();
3050 MPI_Send(nv_ne, 2, MPI_INT, 0, 444, MyComm);
3058 MFEM_ASSERT(ints.
Size() == ne,
"");
3059 MPI_Send(&ints[0], ne, MPI_INT, 0, 445, MyComm);
3066 ne += ((
Dim == 2) ? shared_edges : shared_faces).Size();
3081 dump_element(
boundary[i], ints); ne++;
3086 for (i = 0; i < shared.
Size(); i++)
3088 dump_element(shared[i], ints); ne++;
3095 for (i = 0; i < (int) list.
conforming.size(); i++)
3098 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3100 for (i = 0; i < (int) list.
masters.size(); i++)
3102 int index = list.
masters[i].index;
3103 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3105 for (i = 0; i < (int) list.
slaves.size(); i++)
3107 int index = list.
slaves[i].index;
3108 if (index < nfaces) { dump_element(
faces[index], ints); ne++; }
3112 MPI_Reduce(&ne, &k, 1, MPI_INT, MPI_SUM, 0, MyComm);
3115 out <<
"\nboundary\n" << k <<
'\n';
3117 for (p = 0; p < NRanks; p++)
3121 MPI_Recv(nv_ne, 2, MPI_INT, p, 446, MyComm, &status);
3123 MPI_Recv(ints.
GetData(), ne, MPI_INT, p, 447, MyComm, &status);
3130 for (i = 0; i < ne; )
3133 out << p+1 <<
' ' << ints[i];
3136 for (j = 0; j < k; j++)
3138 out <<
' ' << vc + ints[i++];
3149 MPI_Send(nv_ne, 2, MPI_INT, 0, 446, MyComm);
3150 MPI_Send(ints.
GetData(), ne, MPI_INT, 0, 447, MyComm);
3154 MPI_Reduce(&
NumOfVertices, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3157 out <<
"\nvertices\n" << nv <<
'\n';
3163 out << spaceDim <<
'\n';
3173 for (p = 1; p < NRanks; p++)
3175 MPI_Recv(&nv, 1, MPI_INT, p, 448, MyComm, &status);
3177 MPI_Recv(&vert[0], nv*spaceDim, MPI_DOUBLE, p, 449, MyComm, &status);
3178 for (i = 0; i < nv; i++)
3183 out <<
' ' << vert[i*spaceDim+j];
3197 vert[i*spaceDim+j] =
vertices[i](j);
3200 MPI_Send(&vert[0], NumOfVertices*spaceDim, MPI_DOUBLE, 0, 449, MyComm);
3226 mfem_error(
"ParMesh::PrintAsOne : Nodes have no parallel info!");
3234 MFEM_ASSERT(
Dim == spaceDim,
"2D Manifolds not supported.");
3237 int i, j, k, nv, ne, p;
3245 out <<
"NETGEN_Neutral_Format\n";
3248 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3252 for (j = 0; j <
Dim; j++)
3258 for (p = 1; p < NRanks; p++)
3260 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3262 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445, MyComm, &status);
3263 for (i = 0; i < nv; i++)
3265 for (j = 0; j <
Dim; j++)
3267 out <<
" " << vert[Dim*i+j];
3275 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3282 for (j = 0; j < nv; j++)
3284 out <<
" " << ind[j]+1;
3289 for (p = 1; p < NRanks; p++)
3291 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3292 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3294 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447, MyComm, &status);
3295 for (i = 0; i < ne; i++)
3298 for (j = 0; j < 4; j++)
3300 out <<
" " << k+ints[i*4+j]+1;
3307 nv = NumOfBdrElements + shared_faces.Size();
3308 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3316 for (j = 0; j < nv; j++)
3318 out <<
" " << ind[j]+1;
3323 for (i = 0; i < shared_faces.Size(); i++)
3325 nv = shared_faces[i]->GetNVertices();
3326 ind = shared_faces[i]->GetVertices();
3328 for (j = 0; j < nv; j++)
3330 out <<
" " << ind[j]+1;
3335 for (p = 1; p < NRanks; p++)
3337 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3338 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3340 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447, MyComm, &status);
3341 for (i = 0; i < ne; i++)
3344 for (j = 0; j < 3; j++)
3346 out <<
" " << k+ints[i*3+j]+1;
3356 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3360 for (j = 0; j <
Dim; j++)
3364 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3368 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3369 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
3370 MPI_Send(&NumOfElements, 1, MPI_INT, 0, 446, MyComm);
3371 ints.
SetSize(NumOfElements*4);
3375 for (j = 0; j < 4; j++)
3380 MPI_Send(&ints[0], 4*NumOfElements, MPI_INT, 0, 447, MyComm);
3382 nv = NumOfBdrElements + shared_faces.Size();
3383 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3384 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
3385 ne = NumOfBdrElements + shared_faces.Size();
3386 MPI_Send(&ne, 1, MPI_INT, 0, 446, MyComm);
3391 for (j = 0; j < 3; j++)
3396 for ( ; i < ne; i++)
3399 for (j = 0; j < 3; j++)
3404 MPI_Send(&ints[0], 3*ne, MPI_INT, 0, 447, MyComm);
3410 int i, j, k, nv, ne, p;
3416 int TG_nv, TG_ne, TG_nbe;
3420 MPI_Reduce(&
NumOfVertices, &TG_nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3421 MPI_Reduce(&NumOfElements, &TG_ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3422 nv = NumOfBdrElements + shared_faces.Size();
3423 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0, MyComm);
3426 <<
"1 " << TG_nv <<
" " << TG_ne <<
" 0 0 0 0 0 0 0\n"
3427 <<
"0 0 0 1 0 0 0 0 0 0 0\n"
3428 <<
"0 0 " << TG_nbe <<
" 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
3429 <<
"0.0 0.0 0.0 0 0 0.0 0.0 0 0.0\n"
3430 <<
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
3436 <<
" " <<
vertices[i](2) <<
" 0.0\n";
3437 for (p = 1; p < NRanks; p++)
3439 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3441 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445, MyComm, &status);
3442 for (i = 0; i < nv; i++)
3443 out << i+1 <<
" 0.0 " << vert[
Dim*i] <<
" " << vert[
Dim*i+1]
3444 <<
" " << vert[
Dim*i+2] <<
" 0.0\n";
3453 out << i+1 <<
" " << 1;
3454 for (j = 0; j < nv; j++)
3456 out <<
" " << ind[j]+1;
3461 for (p = 1; p < NRanks; p++)
3463 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3464 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3466 MPI_Recv(&ints[0], 8*ne, MPI_INT, p, 447, MyComm, &status);
3467 for (i = 0; i < ne; i++)
3469 out << i+1 <<
" " << p+1;
3470 for (j = 0; j < 8; j++)
3472 out <<
" " << k+ints[i*8+j]+1;
3487 for (j = 0; j < nv; j++)
3489 out <<
" " << ind[j]+1;
3491 out <<
" 1.0 1.0 1.0 1.0\n";
3494 for (i = 0; i < shared_faces.Size(); i++)
3496 nv = shared_faces[i]->GetNVertices();
3497 ind = shared_faces[i]->GetVertices();
3499 for (j = 0; j < nv; j++)
3501 out <<
" " << ind[j]+1;
3503 out <<
" 1.0 1.0 1.0 1.0\n";
3506 for (p = 1; p < NRanks; p++)
3508 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3509 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3511 MPI_Recv(&ints[0], 4*ne, MPI_INT, p, 447, MyComm, &status);
3512 for (i = 0; i < ne; i++)
3515 for (j = 0; j < 4; j++)
3517 out <<
" " << k+ints[i*4+j]+1;
3519 out <<
" 1.0 1.0 1.0 1.0\n";
3526 MPI_Reduce(&
NumOfVertices, &TG_nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3527 MPI_Reduce(&NumOfElements, &TG_ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3528 nv = NumOfBdrElements + shared_faces.Size();
3529 MPI_Reduce(&nv, &TG_nbe, 1, MPI_INT, MPI_SUM, 0, MyComm);
3534 for (j = 0; j <
Dim; j++)
3538 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE, 0, 445, MyComm);
3540 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
3541 MPI_Send(&NumOfElements, 1, MPI_INT, 0, 446, MyComm);
3542 ints.
SetSize(NumOfElements*8);
3546 for (j = 0; j < 8; j++)
3551 MPI_Send(&ints[0], 8*NumOfElements, MPI_INT, 0, 447, MyComm);
3553 MPI_Send(&NumOfVertices, 1, MPI_INT, 0, 444, MyComm);
3554 ne = NumOfBdrElements + shared_faces.Size();
3555 MPI_Send(&ne, 1, MPI_INT, 0, 446, MyComm);
3560 for (j = 0; j < 4; j++)
3565 for ( ; i < ne; i++)
3568 for (j = 0; j < 4; j++)
3573 MPI_Send(&ints[0], 4*ne, MPI_INT, 0, 447, MyComm);
3579 int i, j, k, attr, nv, ne, p;
3588 out <<
"areamesh2\n\n";
3591 nv = NumOfBdrElements + shared_edges.Size();
3592 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3597 attr =
boundary[i]->GetAttribute();
3600 for (j = 0; j < v.
Size(); j++)
3602 out << v[j] + 1 <<
" ";
3607 for (i = 0; i < shared_edges.Size(); i++)
3609 attr = shared_edges[i]->GetAttribute();
3610 shared_edges[i]->GetVertices(v);
3612 for (j = 0; j < v.
Size(); j++)
3614 out << v[j] + 1 <<
" ";
3619 for (p = 1; p < NRanks; p++)
3621 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3622 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3624 MPI_Recv(&ints[0], 2*ne, MPI_INT, p, 447, MyComm, &status);
3625 for (i = 0; i < ne; i++)
3628 for (j = 0; j < 2; j++)
3630 out <<
" " << k+ints[i*2+j]+1;
3639 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3643 attr =
elements[i]->GetAttribute();
3645 out << 1 <<
" " << 3 <<
" ";
3646 for (j = 0; j < v.
Size(); j++)
3648 out << v[j] + 1 <<
" ";
3653 for (p = 1; p < NRanks; p++)
3655 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3656 MPI_Recv(&ne, 1, MPI_INT, p, 446, MyComm, &status);
3658 MPI_Recv(&ints[0], 3*ne, MPI_INT, p, 447, MyComm, &status);
3659 for (i = 0; i < ne; i++)
3661 out << p+1 <<
" " << 3;
3662 for (j = 0; j < 3; j++)
3664 out <<
" " << k+ints[i*3+j]+1;
3673 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3677 for (j = 0; j <
Dim; j++)
3683 for (p = 1; p < NRanks; p++)
3685 MPI_Recv(&nv, 1, MPI_INT, p, 444, MyComm, &status);
3687 MPI_Recv(&vert[0],
Dim*nv, MPI_DOUBLE, p, 445, MyComm, &status);
3688 for (i = 0; i < nv; i++)
3690 for (j = 0; j <
Dim; j++)
3692 out <<
" " << vert[Dim*i+j];
3701 nv = NumOfBdrElements + shared_edges.Size();
3702 MPI_Reduce(&nv, &ne, 1, MPI_INT, MPI_SUM, 0, MyComm);
3704 ne = NumOfBdrElements + shared_edges.Size();
3705 MPI_Send(&ne, 1, MPI_INT, 0, 446, MyComm);
3710 for (j = 0; j < 2; j++)
3715 for ( ; i < ne; i++)
3718 for (j = 0; j < 2; j++)
3723 MPI_Send(&ints[0], 2*ne, MPI_INT, 0, 447, MyComm);
3726 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3728 MPI_Send(&NumOfElements, 1, MPI_INT, 0, 446, MyComm);
3729 ints.
SetSize(NumOfElements*3);
3733 for (j = 0; j < 3; j++)
3738 MPI_Send(&ints[0], 3*NumOfElements, MPI_INT, 0, 447, MyComm);
3741 MPI_Reduce(&ne, &nv, 1, MPI_INT, MPI_SUM, 0, MyComm);
3745 for (j = 0; j <
Dim; j++)
3749 MPI_Send(&vert[0], Dim*NumOfVertices, MPI_DOUBLE,
3759 double h_min, h_max, kappa_min, kappa_max, h,
kappa;
3763 out <<
"Parallel Mesh Stats:" <<
'\n';
3769 h = pow(fabs(J.
Det()), 1.0/
double(
Dim));
3774 kappa_min = kappa_max =
kappa;
3778 if (h < h_min) { h_min = h; }
3779 if (h > h_max) { h_max = h; }
3780 if (kappa < kappa_min) { kappa_min =
kappa; }
3781 if (kappa > kappa_max) { kappa_max =
kappa; }
3785 double gh_min, gh_max, gk_min, gk_max;
3786 MPI_Reduce(&h_min, &gh_min, 1, MPI_DOUBLE, MPI_MIN, 0, MyComm);
3787 MPI_Reduce(&h_max, &gh_max, 1, MPI_DOUBLE, MPI_MAX, 0, MyComm);
3788 MPI_Reduce(&kappa_min, &gk_min, 1, MPI_DOUBLE, MPI_MIN, 0, MyComm);
3789 MPI_Reduce(&kappa_max, &gk_max, 1, MPI_DOUBLE, MPI_MAX, 0, MyComm);
3792 long mindata[5], maxdata[5], sumdata[5];
3803 ldata[0] -= group_svert.
RowSize(gr-1);
3804 ldata[1] -= group_sedge.
RowSize(gr-1);
3805 ldata[2] -= group_sface.
RowSize(gr-1);
3808 MPI_Reduce(ldata, mindata, 5, MPI_LONG, MPI_MIN, 0, MyComm);
3809 MPI_Reduce(ldata, sumdata, 5, MPI_LONG, MPI_SUM, 0, MyComm);
3810 MPI_Reduce(ldata, maxdata, 5, MPI_LONG, MPI_MAX, 0, MyComm);
3816 << setw(12) <<
"minimum"
3817 << setw(12) <<
"average"
3818 << setw(12) <<
"maximum"
3819 << setw(12) <<
"total" <<
'\n';
3821 << setw(12) << mindata[0]
3822 << setw(12) << sumdata[0]/NRanks
3823 << setw(12) << maxdata[0]
3824 << setw(12) << sumdata[0] <<
'\n';
3826 << setw(12) << mindata[1]
3827 << setw(12) << sumdata[1]/NRanks
3828 << setw(12) << maxdata[1]
3829 << setw(12) << sumdata[1] <<
'\n';
3832 << setw(12) << mindata[2]
3833 << setw(12) << sumdata[2]/NRanks
3834 << setw(12) << maxdata[2]
3835 << setw(12) << sumdata[2] <<
'\n';
3837 << setw(12) << mindata[3]
3838 << setw(12) << sumdata[3]/NRanks
3839 << setw(12) << maxdata[3]
3840 << setw(12) << sumdata[3] <<
'\n';
3841 out <<
" neighbors "
3842 << setw(12) << mindata[4]
3843 << setw(12) << sumdata[4]/NRanks
3844 << setw(12) << maxdata[4] <<
'\n';
3847 << setw(12) <<
"minimum"
3848 << setw(12) <<
"maximum" <<
'\n';
3850 << setw(12) << gh_min
3851 << setw(12) << gh_max <<
'\n';
3853 << setw(12) << gk_min
3854 << setw(12) << gk_max <<
'\n';
3866 DeleteFaceNbrData();
3868 for (
int i = 0; i < shared_faces.Size(); i++)
3872 for (
int 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.
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 (...)
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
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.
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.
T * GetData()
Returns the data.
Data type dense matrix using column-major storage.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
int GetBdrElementEdgeIndex(int i) const
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.
virtual void OnMeshUpdated(Mesh *mesh)
Abstract parallel finite element space.
Array< int > face_nbr_vertices_offset
void DeleteCoarseTables()
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".
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)
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)
Array< FaceInfo > fc_faces_info
bool IAmMaster(int g) const
A parallel extension of the NCMesh class.
Element * NewElement(int geom)
FaceElementTransformations FaceElemTr
template void SortPairs< int, int >(Pair< int, int > *, int)
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
void ExchangeFaceNbrData()
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
void PrintAsOne(std::ostream &out=std::cout)
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 GetSharedFace(int sface) const
Return the local face index for the given shared face.
int GetNumNeighbors() const
void GetLocalSegToTriTransformation(IsoparametricTransformation &loc, int i)
std::vector< Master > masters
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
int InitialPartition(int index) const
Assigns elements to processors at the initial stage (ParMesh creation).
void CheckElementOrientation(bool fix_it=true)
Check the orientation of the elements.
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.
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.
int GetVDim() const
Returns vector dimension.
FiniteElementSpace * FESpace()
virtual void ReorientTetMesh()
Data type tetrahedron element.
int GetOrdering() const
Return the ordering method.
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 RefineGroups(const DSTable &v_to_v, int *middle)
Update the groups after tet refinement.
Array< Vertex > face_nbr_vertices
std::vector< Slave > slaves
Abstract finite element space.
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)
MemAlloc< BisectedElement, 1024 > BEMemory
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
virtual void PrintXG(std::ostream &out=std::cout) const
static FiniteElementCollection * New(const char *name)
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
virtual const char * Name() const
virtual void Refine(const Array< Refinement > &refinements)
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.
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)
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'.
const NCList & GetSharedFaces()
void ParseRefinementFlag(int refinement_edges[2], int &type, int &flag)
Class for parallel grid function.
Table send_face_nbr_elements
Table * GetFaceToAllElementTable() const
void InitFromNCMesh(const NCMesh &ncmesh)
Initialize vertices/elements/boundary/tables from a nonconforming mesh.
FaceElementTransformations * GetSharedFaceTransformations(int)
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.
virtual void LimitNCLevel(int max_level)
To be implemented.
Table * GetVertexToElementTable()
The returned Table must be destroyed by the caller.
const Element * GetBdrElement(int i) const
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