12 #include "../config/config.hpp"
18 #include "../general/binaryio.hpp"
26 using namespace bin_io;
52 , MyComm(other.MyComm)
53 , NRanks(other.NRanks)
54 , MyRank(other.MyRank)
76 for (
int i = 0; i < 3; i++)
112 for (
int i = 0; i < nleafs; i++)
131 for (
int i = 0; i < nleafs; i++)
150 if (node->HasVertex()) { node->vert_index = -1; }
159 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
161 int &vindex =
nodes[el.
node[j]].vert_index;
162 if (vindex < 0) { vindex =
NVertices++; }
170 if (node->HasVertex() && node->vert_index >= 0)
179 if (node->HasVertex() && node->vert_index < 0)
195 if (node->HasEdge()) { node->edge_index = -1; }
210 if (node->HasEdge() && node->edge_index < 0)
242 for (
int j = 0; j < gi.
nf; j++)
244 const int *fv = gi.
faces[j];
247 MFEM_ASSERT(face,
"face not found!");
267 if (face->index < 0) { face->index =
NFaces + (nghosts++); }
277 int f_index =
faces[face].index;
280 owner = std::min(owner, el.
rank);
291 el_loc = (el.
index << 4) | local;
301 if (
Dim < 3) {
return; }
339 int e_index =
nodes[enode].edge_index;
342 owner = std::min(owner, el.
rank);
353 el_loc = (el.
index << 4) | local;
394 int v_index =
nodes[vnode].vert_index;
397 owner = std::min(owner, el.
rank);
408 el_loc = (el.
index << 4) | local;
447 for (
int i = 0; i < num; i++)
459 for (
unsigned i = 0; i < list.
masters.size(); i++)
463 char master_old_flag = master_flag;
467 int si = list.
slaves[j].index;
471 master_flag |= slave_flag;
472 slave_flag |= master_old_flag;
486 for (
unsigned i = 0; i < list.
conforming.size(); i++)
493 for (
unsigned i = 0; i < list.
masters.size(); i++)
500 for (
unsigned i = 0; i < list.
slaves.size(); i++)
502 int si = list.
slaves[i].index;
512 if (lhs.size() == rhs.size())
514 for (
unsigned i = 0; i < lhs.size(); i++)
516 if (lhs[i] < rhs[i]) {
return true; }
520 return lhs.size() < rhs.size();
526 for (
unsigned i = 1; i < group.size(); i++)
528 if (group[i] <= group[i-1]) {
return false; }
536 if (group.size() == 1 && group[0] ==
MyRank)
540 MFEM_ASSERT(group_sorted(group),
"invalid group");
552 MFEM_ASSERT(rank != INT_MAX,
"invalid rank");
553 static std::vector<int> group;
563 for (
unsigned i = 0; i < group.size(); i++)
565 if (group[i] == rank) {
return true; }
576 entity_group.
SetSize(nentities);
582 int begin = 0, end = 0;
583 while (begin < index_rank.
Size())
585 int index = index_rank[begin].from;
586 if (index >= nentities)
590 while (end < index_rank.
Size() && index_rank[end].from ==
index)
594 group.resize(end - begin);
595 for (
int i = begin; i < end; i++)
597 group[i - begin] = index_rank[i].to;
606 for (
int i = 0; i < ranks.
Size(); i++)
619 int v[4], e[4], eo[4];
640 for (
int j = 0; j < 2; j++)
664 for (
int j = 0; j < nfv; j++)
679 for (
int i = 0; i < 3; i++)
692 for (
int i = 0; i < 2; i++)
701 if (local) { local[i] = lf; }
705 for (
int j = 0; j < 4; j++)
707 ids[i][j] = e[i]->
node[fv[j]];
717 if (
Dim < 3) {
return; }
728 if (face->elem[0] >= 0 && face->elem[1] >= 0 && face->index <
NFaces)
733 if (e1->
rank == e2->
rank) {
continue; }
734 if (e1->
rank > e2->
rank) { std::swap(e1, e2); }
749 for (i = j = 0; i < bdr_vertices.
Size(); i++)
751 if (bdr_vertices[i] <
NVertices) { bdr_vertices[j++] = bdr_vertices[i]; }
756 for (i = j = 0; i < bdr_edges.
Size(); i++)
758 if (bdr_edges[i] <
NEdges) { bdr_edges[j++] = bdr_edges[i]; }
773 for (
int i = 0; i < nleaves; i++)
788 for (
int i = 0; i < nleaves; i++)
796 else if (boundary_set[i] && etype)
813 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
843 static void set_to_array(
const std::set<T> &set,
Array<T> &array)
847 for (std::set<int>::iterator it = set.begin(); it != set.end(); ++it)
864 set_to_array(ranks, neighbors);
876 group_shared.
MakeI(ngroups-1);
880 for (
int i = 0; i < conf_group.
Size(); i++)
884 if (entity_geom && (*entity_geom)[i] !=
geom) {
continue; }
891 shared_local.
SetSize(num_shared);
892 group_shared.
MakeJ();
895 for (
int i = 0, j = 0; i < conf_group.
Size(); i++)
899 if (entity_geom && (*entity_geom)[i] !=
geom) {
continue; }
909 for (
int i = 0; i < group_shared.
Size(); i++)
911 int size = group_shared.
RowSize(i);
912 int *row = group_shared.
GetRow(i);
915 ref_row.
Sort([&](
const int a,
const int b)
923 if (lgo_a != lgo_b) {
return lgo_a < lgo_b; }
925 return (el_loc_a & 0xf) < (el_loc_b & 0xf);
935 for (
int ent = 0; ent <
Dim; ent++)
950 for (
unsigned i = 0; i <
groups.size(); i++)
952 if (
groups[i].size() > 1 || !i)
955 group_map[i] = int_groups.
Insert(iset);
962 for (
int ent = 0; ent < 3; ent++)
967 ecg = group_map[ecg];
1001 for (
int i = 0; i < slt.
Size(); i++)
1006 int v[4], e[4], eo[4];
1013 for (
int i = 0; i < slq.
Size(); i++)
1023 for (
int ent = 0; ent <
Dim; ent++)
1047 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
1051 MFEM_ASSERT(face != NULL,
"");
1053 MFEM_ASSERT(face->
elem[0] >= 0 && face->
elem[1] >= 0,
"");
1056 if (e[0]->rank ==
MyRank) { std::swap(e[0], e[1]); }
1057 MFEM_ASSERT(e[0]->rank !=
MyRank && e[1]->rank ==
MyRank,
"");
1063 for (
unsigned i = 0; i < shared.
masters.size(); i++)
1069 if (sf.
index < 0) {
continue; }
1076 if (loc0 == loc1) {
continue; }
1077 if (loc0) { std::swap(e[0], e[1]); }
1084 MFEM_ASSERT(fnbr.
Size() <= bound,
"oops, bad upper bound");
1098 for (
int i = 0; i < fnbr.
Size(); i++)
1117 std::map<int, int> vert_map;
1118 for (
int i = 0; i < fnbr.
Size(); i++)
1126 for (
int k = 0; k < gi.
nv; k++)
1128 int &v = vert_map[elem->
node[k]];
1129 if (!v) { v = vert_map.size(); }
1133 if (!i || elem->
rank != fnbr[i-1]->rank)
1148 std::map<int, int>::iterator it;
1149 for (it = vert_map.begin(); it != vert_map.end(); ++it)
1161 for (
int i = 0, last_rank = -1; i < send_elems.
Size(); i++)
1164 if (c.
from != last_rank)
1172 c.
from = send_elems[i-1].from;
1178 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
1184 if (e[0]->rank ==
MyRank) { std::swap(e[0], e[1]); }
1201 if (shared.
slaves.size())
1207 MFEM_ASSERT(pmesh.
faces_info.Size() == nfaces,
"");
1210 for (
int i = nfaces; i < pmesh.
faces_info.Size(); i++)
1221 for (
unsigned i = 0; i < shared.
masters.size(); i++)
1227 if (sf.
index < 0) {
continue; }
1235 if (sloc == mloc) {
continue; }
1264 if (!sloc &&
Dim == 3)
1268 std::swap((*pm2)(0,1), (*pm2)(0,3));
1269 std::swap((*pm2)(1,1), (*pm2)(1,3));
1286 MFEM_ASSERT(fi.
NCFace < 0,
"");
1315 bool removeAll =
true;
1318 for (
int i = 0; i < 8; i++)
1321 if (el.
child[i] >= 0)
1324 if (!
remove[i]) { removeAll =
false; }
1329 if (removeAll) {
return true; }
1332 for (
int i = 0; i < 8; i++)
1352 MFEM_WARNING(
"Can't prune 3D aniso meshes yet.");
1388 for (
int i = 0; i < refinements.
Size(); i++)
1392 "anisotropic parallel refinement not supported yet in 3D.");
1394 MFEM_VERIFY(
Iso ||
Dim < 3,
1395 "parallel refinement of 3D aniso meshes not supported yet.");
1402 for (
int i = 0; i < neighbors.
Size(); i++)
1404 send_ref[neighbors[i]].SetNCMesh(
this);
1412 for (
int i = 0; i < refinements.
Size(); i++)
1418 for (
int j = 0; j < ranks.
Size(); j++)
1420 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
1428 for (
int i = 0; i < refinements.
Size(); i++)
1435 for (
int j = 0; j < neighbors.
Size(); j++)
1445 for (
int i = 0; i < msg.
Size(); i++)
1460 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
1467 long size = refinements.
Size(), glob_size;
1468 MPI_Allreduce(&size, &glob_size, 1, MPI_LONG, MPI_SUM,
MyComm);
1470 if (!glob_size) {
break; }
1478 MFEM_VERIFY(
Dim < 3 ||
Iso,
1479 "derefinement of 3D anisotropic meshes not implemented yet.");
1503 for (
int i = 0; i < derefs.
Size(); i++)
1505 int row = derefs[i];
1507 "invalid derefinement number.");
1512 int coarse_rank = INT_MAX;
1513 for (
int j = 0; j < size; j++)
1516 coarse_rank = std::min(coarse_rank, fine_rank);
1518 for (
int j = 0; j < size; j++)
1520 new_ranks[fine[j]] = coarse_rank;
1524 int target_elements = 0;
1525 for (
int i = 0; i < new_ranks.Size(); i++)
1527 if (new_ranks[i] ==
MyRank) { target_elements++; }
1541 for (
int i = 0; i < neighbors.
Size(); i++)
1543 send_deref[neighbors[i]].SetNCMesh(
this);
1550 for (
int i = 0; i < derefs.
Size(); i++)
1553 int parent =
elements[old_elements[fine[0]]].parent;
1557 for (
int j = 0; j < ranks.
Size(); j++)
1559 send_deref[ranks[j]].AddDerefinement(parent, new_ranks[fine[0]]);
1569 for (
int i = 0; i < old_elements.
Size(); i++)
1571 elements[old_elements[i]].index = i;
1576 old_elements.
Copy(coarse);
1577 for (
int i = 0; i < derefs.
Size(); i++)
1580 int parent =
elements[old_elements[fine[0]]].parent;
1589 for (
int j = 0; j < neighbors.
Size(); j++)
1599 for (
int i = 0; i < msg.
Size(); i++)
1617 for (
int i = 0; i < coarse.
Size(); i++)
1623 index = -1 -
elements[coarse[i]].rank;
1633 for (
int i = 0; i < coarse.
Size(); i++)
1647 template<
typename Type>
1649 const Table &deref_table)
1662 for (
int i = 0; i < deref_table.
Size(); i++)
1664 const int* fine = deref_table.
GetRow(i);
1665 int size = deref_table.
RowSize(i);
1666 MFEM_ASSERT(size <= 8,
"");
1668 int ranks[8], min_rank = INT_MAX, max_rank = INT_MIN;
1669 for (
int j = 0; j < size; j++)
1672 min_rank = std::min(min_rank, ranks[j]);
1673 max_rank = std::max(max_rank, ranks[j]);
1677 if (min_rank != max_rank)
1680 for (
int j = 0; j < size; j++)
1687 for (
int j = 0; j < size; j++)
1689 Type *data = &elem_data[fine[j]];
1691 int rnk = ranks[j], len = 1;
1697 for (
int k = 0; k < neigh.
Size(); k++)
1699 MPI_Request* req =
new MPI_Request;
1700 MPI_Isend(data, len, datatype, neigh[k], 292,
MyComm, req);
1706 MPI_Request* req =
new MPI_Request;
1707 MPI_Irecv(data, len, datatype, rnk, 292,
MyComm, req);
1714 for (
int i = 0; i < requests.
Size(); i++)
1716 MPI_Wait(requests[i], MPI_STATUS_IGNORE);
1723 ParNCMesh::SynchronizeDerefinementData<int>(
Array<int> &,
const Table &);
1735 for (
int i = 0; i < deref_table.
Size(); i++)
1737 const int *fine = deref_table.
GetRow(i),
1738 size = deref_table.
RowSize(i);
1743 for (
int j = 0; j < size; j++)
1751 for (
int k = 0; k <
Dim; k++)
1754 splits[k] >= max_nc_level)
1756 leaf_ok[fine[j]] = 0;
break;
1768 for (
int i = 0; i < deref_table.
Size(); i++)
1770 const int* fine = deref_table.
GetRow(i),
1771 size = deref_table.
RowSize(i);
1773 for (
int j = 0; j < size; j++)
1775 if (!leaf_ok[fine[j]])
1777 level_ok[i] = 0;
break;
1794 if (!custom_partition)
1800 long local_elems =
NElements, total_elems = 0;
1801 MPI_Allreduce(&local_elems, &total_elems, 1, MPI_LONG, MPI_SUM,
MyComm);
1803 long first_elem_global = 0;
1804 MPI_Scan(&local_elems, &first_elem_global, 1, MPI_LONG, MPI_SUM,
MyComm);
1805 first_elem_global -= local_elems;
1811 new_ranks[i] =
Partition(first_elem_global + (j++), total_elems);
1824 "Size of the partition array must match the number "
1825 "of local mesh elements (ParMesh::GetNE()).");
1828 custom_partition->
Copy(new_ranks);
1838 for (
int i = 0; i < old_elements.
Size(); i++)
1851 bool sfc = (target_elements >= 0);
1868 int begin = 0, end = 0;
1888 for (
int i = 0; i < rank_neighbors.
Size(); i++)
1890 int elem = rank_neighbors[i];
1898 recv_ghost_ranks[rank].SetNCMesh(
this);
1907 NeighborElementRankMessage::Map::iterator it;
1908 for (it = recv_ghost_ranks.begin(); it != recv_ghost_ranks.end(); ++it)
1911 for (
int i = 0; i < msg.
Size(); i++)
1915 new_ranks[ghost_index] = msg.
values[i];
1919 recv_ghost_ranks.clear();
1930 int received_elements = 0;
1936 received_elements++;
1938 el.
rank = new_ranks[i];
1941 int nsent = 0, nrecv = 0;
1948 owned_elements.
Sort([&](
const int a,
const int b)
1957 int begin = 0, end = 0;
1961 int rank =
elements[owned_elements[begin]].rank;
1962 while (end < owned_elements.
Size() &&
1963 elements[owned_elements[end]].rank == rank) { end++; }
1968 rank_elems.
MakeRef(&owned_elements[begin], end - begin);
1979 for (
int i = 0; i < batch.
Size(); i++)
1981 int elem = batch[i];
2027 while (received_elements < target_elements)
2036 for (
int i = 0; i < msg.
Size(); i++)
2038 int elem_rank = msg.
values[i];
2041 if (elem_rank ==
MyRank) { received_elements++; }
2063 MPI_Request barrier = MPI_REQUEST_NULL;
2075 for (
int i = 0; i < msg.
Size(); i++)
2087 if (barrier != MPI_REQUEST_NULL)
2089 MPI_Test(&barrier, &done, MPI_STATUS_IGNORE);
2095 int err = MPI_Ibarrier(
MyComm, &barrier);
2097 MFEM_VERIFY(err == MPI_SUCCESS,
"");
2098 MFEM_VERIFY(barrier != MPI_REQUEST_NULL,
"");
2109 int glob_sent, glob_recv;
2110 MPI_Reduce(&nsent, &glob_sent, 1, MPI_INT, MPI_SUM, 0,
MyComm);
2111 MPI_Reduce(&nrecv, &glob_recv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
2115 MFEM_ASSERT(glob_sent == glob_recv,
2116 "(glob_sent, glob_recv) = ("
2117 << glob_sent <<
", " << glob_recv <<
")");
2124 const Table &old_element_dofs,
2125 long old_global_offset,
2132 RebalanceDofMessage::Map::iterator it;
2142 for (
int i = 0; i < ne; i++)
2163 RebalanceDofMessage::Map::iterator it;
2168 nd += msg.
dofs.size();
2179 for (
unsigned i = 0; i < msg.
elem_ids.size(); i++)
2183 for (
unsigned i = 0; i < msg.
dofs.size(); i++)
2196 : ncmesh(other.ncmesh), include_ref_types(other.include_ref_types)
2204 data.Append(value & 0xff);
2205 data.Append((value >> 8) & 0xff);
2206 data.Append((value >> 16) & 0xff);
2207 data.Append((value >> 24) & 0xff);
2213 return (
int) data[pos] +
2214 ((int) data[pos+1] << 8) +
2215 ((int) data[pos+2] << 16) +
2216 ((int) data[pos+3] << 24);
2221 for (
int i = 0; i < elements.
Size(); i++)
2223 int elem = elements[i];
2226 Element &el = ncmesh->elements[elem];
2227 if (el.
flag == flag) {
break; }
2236 Element &el = ncmesh->elements[elem];
2246 for (
int i = 0; i < 8; i++)
2248 if (el.
child[i] >= 0 && ncmesh->elements[el.
child[i]].flag)
2256 if (include_ref_types)
2261 for (
int i = 0; i < 8; i++)
2263 if (mask & (1 << i))
2265 EncodeTree(el.
child[i]);
2273 FlagElements(elements, 1);
2278 for (
int i = 0; i < ncmesh->root_state.Size(); i++)
2280 if (ncmesh->elements[i].flag)
2288 FlagElements(elements, 0);
2294 std::ostringstream oss;
2295 for (
int i = 0; i < ref_path.Size(); i++)
2297 oss <<
" elem " << ref_path[i] <<
" (";
2298 const Element &el = ncmesh->elements[ref_path[i]];
2299 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2301 if (j) { oss <<
", "; }
2302 oss << ncmesh->RetrieveNode(el, j);
2314 ref_path.Append(elem);
2316 int mask = data[pos++];
2323 Element &el = ncmesh->elements[elem];
2324 if (include_ref_types)
2326 int ref_type = data[pos++];
2329 ncmesh->RefineElement(elem, ref_type);
2331 else { MFEM_ASSERT(ref_type == el.
ref_type,
"") }
2335 MFEM_ASSERT(el.
ref_type != 0,
"Path not found:\n"
2336 << RefPath() <<
" mask = " << mask);
2339 for (
int i = 0; i < 8; i++)
2341 if (mask & (1 << i))
2343 DecodeTree(el.
child[i], pos, elements);
2348 ref_path.DeleteLast();
2355 while ((root = GetInt(pos)) >= 0)
2358 DecodeTree(root, pos, elements);
2364 write<int>(os, data.Size());
2365 os.write((
const char*) data.GetData(), data.Size());
2370 data.SetSize(read<int>(is));
2371 is.read((
char*) data.GetData(), data.Size());
2387 for (
unsigned i = 0; i <
groups.size(); i++)
2393 for (
int i = 0; i < ids[0].
Size(); i++)
2395 find_v[i].one = ids[0][i].index;
2409 for (
int j = 0; j < 2; j++)
2414 k = find_v[pos].two;
2425 for (
int i = 0; i < ids[1].
Size(); i++)
2427 find_e[i].one = ids[1][i].index;
2439 int v[4], e[4], eo[4], pos, k;
2441 for (
int j = 0; j < nfv; j++)
2445 k = find_v[pos].two;
2451 k = find_e[pos].two;
2466 for (
int i = 0; i < gi.
nv; i++)
2468 if (
nodes[el.
node[i]].vert_index ==
id.index)
2475 MFEM_ABORT(
"Vertex not found.");
2481 const int *ev =
GI[old.
Geom()].
edges[(int)
id.local];
2483 MFEM_ASSERT(node != NULL,
"Edge not found.");
2489 for (
int i = 0; i < gi.
ne; i++)
2491 const int* ev = gi.
edges[i];
2492 if ((el.
node[ev[0]] == node->
p1 && el.
node[ev[1]] == node->
p2) ||
2493 (el.
node[ev[1]] == node->
p1 && el.
node[ev[0]] == node->
p2))
2501 MFEM_ABORT(
"Edge not found.");
2507 const MeshId &first = ids[find[pos].two];
2508 while (++pos < find.Size() && ids[find[pos].two].index == first.
index)
2510 MeshId &other = ids[find[pos].two];
2518 std::map<int, int> stream_id;
2524 for (
int type = 0; type < 3; type++)
2526 for (
int i = 0; i < ids[type].
Size(); i++)
2528 elements.
Append(ids[type][i].element);
2540 for (
int i = 0; i < decoded.
Size(); i++)
2542 stream_id[decoded[i]] = i;
2547 for (
int type = 0; type < 3; type++)
2549 write<int>(os, ids[type].
Size());
2550 for (
int i = 0; i < ids[type].
Size(); i++)
2552 const MeshId&
id = ids[type][i];
2553 write<int>(os, stream_id[
id.element]);
2554 write<char>(os,
id.local);
2569 for (
int type = 0; type < 3; type++)
2571 int ne = read<int>(is);
2574 for (
int i = 0; i < ne; i++)
2576 int el_num = read<int>(is);
2577 int elem = elems[el_num];
2580 MFEM_VERIFY(!el.
ref_type,
"not a leaf element: " << el_num);
2582 MeshId &
id = ids[type][i];
2584 id.local = read<char>(is);
2592 id.index =
nodes[el.
node[(int)
id.local]].vert_index;
2597 const int* ev = gi.edges[(int)
id.local];
2599 MFEM_ASSERT(node && node->
HasEdge(),
"edge not found.");
2605 const int* fv = gi.faces[(int)
id.local];
2608 MFEM_ASSERT(face,
"face not found.");
2609 id.index = face->
index;
2619 std::map<GroupId, GroupId> stream_id;
2620 for (
int i = 0; i < ids.
Size(); i++)
2622 if (i && ids[i] == ids[i-1]) {
continue; }
2623 unsigned size = stream_id.size();
2624 GroupId &sid = stream_id[ids[i]];
2625 if (size != stream_id.size()) { sid = size; }
2629 write<short>(os, stream_id.size());
2630 for (std::map<GroupId, GroupId>::iterator
2631 it = stream_id.begin(); it != stream_id.end(); ++it)
2633 write<GroupId>(os, it->second);
2637 write<short>(os, group.size());
2638 for (
unsigned i = 0; i < group.size(); i++)
2640 write<int>(os, group[i]);
2646 write<short>(os, -1);
2651 write<int>(os, ids.
Size());
2652 for (
int i = 0; i < ids.
Size(); i++)
2654 write<GroupId>(os, stream_id[ids[i]]);
2660 int ngroups = read<short>(is);
2666 for (
int i = 0; i < ngroups; i++)
2668 int id = read<GroupId>(is);
2669 int size = read<short>(is);
2673 for (
int i = 0; i < size; i++)
2675 ranks[i] = read<int>(is);
2687 for (
int i = 0; i < ids.
Size(); i++)
2689 ids[i] = groups[read<GroupId>(is)];
2696 template<
class ValueType,
bool RefTypes,
int Tag>
2699 std::ostringstream ostream;
2705 eset.
Encode(tmp_elements);
2713 std::map<int, int> element_index;
2714 for (
int i = 0; i < decoded.
Size(); i++)
2716 element_index[decoded[i]] = i;
2719 write<int>(ostream, values.size());
2720 MFEM_ASSERT(
elements.size() == values.size(),
"");
2722 for (
unsigned i = 0; i < values.size(); i++)
2724 write<int>(ostream, element_index[
elements[i]]);
2725 write<ValueType>(ostream, values[i]);
2728 ostream.str().swap(data);
2731 template<
class ValueType,
bool RefTypes,
int Tag>
2734 std::istringstream istream(data);
2740 eset.
Decode(tmp_elements);
2742 int* el = tmp_elements.
GetData();
2746 int count = read<int>(istream);
2747 for (
int i = 0; i < count; i++)
2749 int index = read<int>(istream);
2750 MFEM_ASSERT(index >= 0 && (
size_t) index < values.size(),
"");
2751 values[
index] = read<ValueType>(istream);
2761 eset.SetNCMesh(ncmesh);
2766 eset.Decode(decoded);
2768 elem_ids.resize(decoded.
Size());
2769 for (
int i = 0; i < decoded.
Size(); i++)
2771 elem_ids[i] = eset.GetNCMesh()->elements[decoded[i]].index;
2775 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
2777 write<int>(os, dofs.size());
2779 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
2782 static void read_dofs(std::istream &is, std::vector<int> &dofs)
2784 dofs.resize(read<int>(is));
2785 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
2790 std::ostringstream stream;
2793 write<long>(stream, dof_offset);
2794 write_dofs(stream, dofs);
2796 stream.str().swap(data);
2801 std::istringstream stream(data);
2804 dof_offset = read<long>(stream);
2805 read_dofs(stream, dofs);
2812 elem_ids.resize(elems.
Size());
2813 for (
int i = 0; i < elems.
Size(); i++)
2815 elem_ids[i] = eset.GetNCMesh()->elements[elems[i]].index;
2828 for (
int i = 0; i < cle.
Size(); i++)
2836 debug_mesh.
ncmesh = copy;
2847 for (
int i = 0; i < 3; i++)
2864 return (elem_ids.capacity() + dofs.capacity()) *
sizeof(
int);
2867 template<
typename K,
typename V>
2868 static long map_memory_usage(
const std::map<K, V> &map)
2871 for (
typename std::map<K, V>::const_iterator
2872 it = map.begin(); it != map.end(); ++it)
2874 result += it->second.MemoryUsage();
2875 result +=
sizeof(std::pair<K, V>) + 3*
sizeof(
void*) +
sizeof(bool);
2883 for (
unsigned i = 0; i <
groups.size(); i++)
2885 groups_size +=
groups[i].capacity() *
sizeof(int);
2887 const int approx_node_size =
2888 sizeof(std::pair<CommGroup, GroupId>) + 3*
sizeof(
void*) +
sizeof(bool);
2889 return groups_size +
group_id.size() * approx_node_size;
2892 template<
typename Type,
int Size>
2893 static long arrays_memory_usage(
const Array<Type> (&arrays)[Size])
2896 for (
int i = 0; i < Size; i++)
2898 total += arrays[i].MemoryUsage();
2905 long total_groups_owners = 0;
2906 for (
int i = 0; i < 3; i++)
2943 << arrays_memory_usage(
entity_owner) <<
" entity_owner\n"
2970 #endif // MFEM_USE_MPI
NCList face_list
lazy-initialized list of faces, see GetFaceList
NCList edge_list
lazy-initialized list of edges, see GetEdgeList
NCMesh(const Mesh *mesh, std::istream *vertex_parents=NULL)
int Partition(long index, long total_elements) const
Return the processor number for a global element number.
ElementSet(NCMesh *ncmesh=NULL, bool include_ref_types=false)
void SendRebalanceDofs(int old_ndofs, const Table &old_element_dofs, long old_global_offset, FiniteElementSpace *space)
Use the communication pattern from last Rebalance() to send element DOFs.
void DecodeMeshIds(std::istream &is, Array< MeshId > ids[])
void Create(ListOfIntegerSets &groups, int mpitag)
Array< char > element_type
int Size() const
Logical size of the array.
std::vector< ValueType > values
long PartitionFirstIndex(int rank, long total_elements) const
Return the global index of the first element owned by processor 'rank'.
void GetConformingSharedStructures(class ParMesh &pmesh)
CoarseFineTransformations transforms
storage for data returned by Get[De]RefinementTransforms()
void Recreate(const int n, const int *p)
int elem[2]
up to 2 elements sharing the face
virtual void Trim()
Save memory by releasing all non-essential and cached data.
char ref_type
refinement XYZ bit mask (7 = full isotropic)
std::vector< int > CommGroup
void CalcFaceOrientations()
int GetFaceVerticesEdges(const MeshId &face_id, int vert_index[4], int edge_index[4], int edge_orientation[4]) const
void SetDerefMatrixCodes(int parent, Array< int > &fine_coarse)
Helper struct to convert a C++ type to an MPI type.
void MakeSharedList(const NCList &list, NCList &shared)
char flag
generic flag/marker, can be used by algorithms
Array< char > face_orient
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.
std::vector< int > elem_ids
void ChangeRemainingMeshIds(Array< MeshId > &ids, int pos, const Array< Pair< int, int > > &find)
virtual void BuildFaceList()
void Dump(std::ostream &os) const
virtual void Trim()
Save memory by releasing all non-essential and cached data.
int index
element number in the Mesh, -1 if refined
Array< Element * > face_nbr_elements
const NCList & GetSharedVertices()
GroupId GetSingletonGroup(int rank)
void GetFaceNeighbors(class ParMesh &pmesh)
Lists all edges/faces in the nonconforming mesh.
std::string RefPath() const
void SetNCMesh(ParNCMesh *pncmesh)
Set pointer to ParNCMesh (needed to encode the message).
std::map< int, NeighborElementRankMessage > Map
void Copy(Array ©) const
Create a copy of the current array.
virtual void ElementSharesVertex(int elem, int local, int vnode)
std::vector< int > elements
T * GetData()
Returns the data.
void Load(std::istream &is)
Table derefinements
possible derefinements, see GetDerefinementTable
Data type dense matrix using column-major storage.
NCList vertex_list
lazy-initialized list of vertices, see GetVertexList
void InitDerefTransforms()
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
char geom
Geometry::Type of the element (char for storage only)
void SynchronizeDerefinementData(Array< Type > &elem_data, const Table &deref_table)
int GetInt(int pos) const
virtual void OnMeshUpdated(Mesh *mesh)
virtual void Derefine(const Array< int > &derefs)
void SetElements(const Array< int > &elems, NCMesh *ncmesh)
bool operator<(const Pair< A, B > &p, const Pair< A, B > &q)
Comparison operator for class Pair, based on the first element only.
Array< Vert3 > shared_trias
void CountSplits(int elem, int splits[3]) const
Geometry::Type Geom() const
std::vector< MeshId > conforming
void ChangeEdgeMeshIdElement(NCMesh::MeshId &id, int elem)
Array< int > face_nbr_group
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
void GetLimitRefinements(Array< Refinement > &refinements, int max_level)
bool GroupContains(GroupId id, int rank) const
Return true if group 'id' contains the given rank.
int PrintMemoryDetail() const
void EncodeTree(int elem)
int spaceDim
dimensions of the elements and the vertex coordinates
virtual void AssignLeafIndices()
const NCList & GetSharedEdges()
Array< int > vertex_nodeId
void DeleteAll()
Delete whole array.
static int find_element_edge(const Element &el, int vn0, int vn1, bool abort=true)
int index
Mesh element number.
int master
master number (in Mesh numbering)
void Recv(int rank, int size, MPI_Comm comm)
Post-probe receive from processor 'rank' of message size 'size'.
const NCList & GetFaceList()
Return the current list of conforming and nonconforming faces.
const NCList & GetSharedList(int entity)
Helper to get shared vertices/edges/faces ('entity' == 0/1/2 resp.).
Array< NCFaceInfo > nc_faces_info
virtual void OnMeshUpdated(Mesh *mesh)
A parallel extension of the NCMesh class.
static int find_local_face(int geom, int a, int b, int c)
RebalanceDofMessage::Map send_rebalance_dofs
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
void FlagElements(const Array< int > &elements, char flag)
void Decode(Array< int > &elements) const
Face * GetFace(Element &elem, int face_no)
void AddElementRank(int elem, int rank)
Array< int > face_nbr_elements_offset
int index
face number in the Mesh
void MakeFromList(int nrows, const Array< Connection > &list)
Array< Element * > shared_edges
Array< DenseMatrix * > aux_pm_store
Stores modified point matrices created by GetFaceNeighbors.
virtual void SetAttributes()
int Append(const T &el)
Append element to array, resize if necessary.
void RedistributeElements(Array< int > &new_ranks, int target_elements, bool record_comm)
void GetSubArray(int offset, int sa_size, Array< T > &sa) const
void FindNeighbors(int elem, Array< int > &neighbors, const Array< int > *search_set=NULL)
std::vector< Master > masters
void ElementNeighborProcessors(int elem, Array< int > &ranks)
void AddConnection(int r, int c)
Array< int > old_index_or_rank
void CreateGroups(int nentities, Array< Connection > &index_rank, Array< GroupId > &entity_group)
RebalanceDofMessage::Map recv_rebalance_dofs
int InitialPartition(int index) const
Helper to get the partitioning when the serial mesh gets split initially.
int Insert(IntegerSet &s)
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
virtual void BuildEdgeList()
Identifies a vertex/edge/face in both Mesh and NCMesh.
int parent
parent element, -1 if this is a root element, -2 if free
std::map< int, NeighborRefinementMessage > Map
static void IsendAll(MapT &rank_msg, MPI_Comm comm)
Helper to send all messages in a rank-to-message map container.
signed char local
local number within 'element'
void Sort()
Sorts the array. This requires operator< to be defined for T.
int FindSorted(const T &el) const
Do bisection search for 'el' in a sorted array; return -1 if not found.
int GetVDim() const
Returns vector dimension.
int Size() const
Returns the number of TYPE I elements.
virtual void ElementSharesFace(int elem, int local, int face)
A class for non-conforming AMR on higher-order hexahedral, prismatic, quadrilateral or triangular mes...
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
int element
NCMesh::Element containing this vertex/edge/face.
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
Array< Vert4 > shared_quads
void Rebalance(const Array< int > *custom_partition=NULL)
static GeomInfo GI[Geometry::NumGeom]
void Clear(bool hard=false)
static bool TestAllSent(MapT &rank_msg)
int slaves_end
slave faces
void DecodeGroups(std::istream &is, Array< GroupId > &ids)
void AdjustMeshIds(Array< MeshId > ids[], int rank)
virtual void ElementSharesEdge(int elem, int local, int enode)
bool Iso
true if the mesh only contains isotropic refinements
Array< int > tmp_neighbors
std::map< int, NeighborDerefinementMessage > Map
Array< Connection > entity_index_rank[3]
virtual void BuildEdgeList()
Array< GroupId > entity_owner[3]
void Encode(const Array< int > &elements)
Array< char > tmp_shared_flag
Array< Vertex > face_nbr_vertices
std::vector< Slave > slaves
virtual void BuildFaceList()
Nonconforming edge/face within a bigger edge/face.
void DerefineElement(int elem)
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void GetDebugMesh(Mesh &debug_mesh) const
bool PruneTree(int elem)
Internal. Recursive part of Prune().
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
void AddAColumnInRow(int r)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
mfem::Element * NewMeshElement(int geom) const
static void RecvAll(MapT &rank_msg, MPI_Comm comm)
Helper to receive all messages in a rank-to-message map container.
Helper struct for defining a connectivity table, see Table::MakeFromList.
void Issend(int rank, MPI_Comm comm)
void RefineElement(int elem, char ref_type)
virtual void Refine(const Array< Refinement > &refinements)
int child[8]
2-8 children (if ref_type != 0)
void RecvRebalanceDofs(Array< int > &elements, Array< long > &dofs)
Receive element DOFs sent by SendRebalanceDofs().
Array< int > leaf_elements
Table group_svert
Shared objects in each group.
Array< int > boundary_layer
list of type 3 elements
void Isend(int rank, MPI_Comm comm)
int index(int i, int j, int nx, int ny)
void AddElementRank(int elem, int rank)
void InitOwners(int num, Array< GroupId > &entity_owner)
void ChangeVertexMeshIdElement(NCMesh::MeshId &id, int elem)
void DecodeTree(int elem, int &pos, Array< int > &elements) const
Array< FaceInfo > faces_info
void SetAttribute(const int attr)
Set element's attribute.
virtual void AssignLeafIndices()
void EncodeGroups(std::ostream &os, const Array< GroupId > &ids)
virtual void BuildVertexList()
void CalculatePMatrixGroups()
NCMesh * ncmesh
Optional non-conforming mesh extension.
Array< int > entity_elem_local[3]
Array< int > leaf_glob_order
T & Last()
Return the last element in the array.
void NeighborExpand(const Array< int > &elems, Array< int > &expanded, const Array< int > *search_set=NULL)
BlockArray< Element > elements
virtual void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level)
void FindSetNeighbors(const Array< char > &elem_set, Array< int > *neighbors, Array< char > *neighbor_set=NULL)
int GetNEdges() const
Return the number of edges.
Array< int > ghost_layer
list of elements whose 'element_type' == 2.
void GetEdgeVertices(const MeshId &edge_id, int vert_index[2], bool oriented=true) const
Return Mesh vertex indices of an edge identified by 'edge_id'.
void MakeRef(T *, int)
Make this Array a reference to a pointer.
static void WaitAllSent(MapT &rank_msg)
Helper to wait for all messages in a map container to be sent.
void EncodeMeshIds(std::ostream &os, Array< MeshId > ids[])
void AddConnections(int entity, int index, const Array< int > &ranks)
long MemoryUsage() const
Return total number of bytes allocated.
void MakeSharedTable(int ngroups, int ent, Array< int > &shared_local, Table &group_shared, Array< char > *entity_geom=NULL, char geom=0)
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
Array< int > svert_lvert
Shared to local index mapping.
const NCList & GetSharedFaces()
std::map< int, RebalanceMessage > Map
static int get_face_orientation(Face &face, Element &e1, Element &e2, int local[2]=NULL)
virtual void BuildVertexList()
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
Array< GroupId > entity_pmat_group[3]
void NeighborProcessors(Array< int > &neighbors)
long GroupsMemoryUsage() const
static bool IProbe(int &rank, int &size, MPI_Comm comm)
Table send_face_nbr_elements
char ref_type
bit mask of X,Y,Z refinements (bits 0,1,2 respectively)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void InitFromNCMesh(const NCMesh &ncmesh)
Initialize vertices/elements/boundary/tables from a nonconforming mesh.
static int find_node(const Element &el, int node)
bool CheckElementType(int elem, int type)
virtual void UpdateVertices()
update Vertex::index and vertex_nodeId
Class for parallel meshes.
Abstract data type element.
GroupId GetGroupId(const CommGroup &group)
Data type line segment element.
const double * CalcVertexPos(int node) const
int rank
processor number (ParNCMesh), -1 if undefined/unknown
virtual void LimitNCLevel(int max_nc_level)
Parallel version of NCMesh::LimitNCLevel.
int node[8]
element corners (if ref_type == 0)
Array< unsigned char > data
encoded refinement (sub-)trees
DenseMatrix point_matrix
position within the master edge/face
static void Probe(int &rank, int &size, MPI_Comm comm)
virtual void Refine(const Array< Refinement > &refinements)
ParNCMesh(MPI_Comm comm, const NCMesh &ncmesh, int *part=NULL)
Array< GroupId > entity_conf_group[3]
Array< char > face_geom
face geometry by face index, set by OnMeshUpdated
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const