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 (
int 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 (
int i = 0; i < list.
conforming.Size(); i++)
493 for (
int i = 0; i < list.
masters.Size(); i++)
500 for (
int 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 (
int 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 (
int i = 0; i < shared.
masters.Size(); i++)
1069 if (sf.
element < 0) {
continue; }
1071 MFEM_ASSERT(mf.
element >= 0,
"");
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 (
int 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 (
int i = 0; i < shared.
masters.Size(); i++)
1227 if (sf.
element < 0) {
continue; }
1229 MFEM_ASSERT(mf.
element >= 0,
"");
1235 if (sloc == mloc) {
continue; }
1264 if (!sloc &&
Dim == 3)
1270 std::swap((*pm2)(0,1), (*pm2)(0,3));
1271 std::swap((*pm2)(1,1), (*pm2)(1,3));
1287 else if (!sloc &&
Dim == 2)
1296 MFEM_ASSERT(fi.
NCFace < 0,
"");
1325 bool removeAll =
true;
1328 for (
int i = 0; i < 8; i++)
1331 if (el.
child[i] >= 0)
1334 if (!
remove[i]) { removeAll =
false; }
1339 if (removeAll) {
return true; }
1342 for (
int i = 0; i < 8; i++)
1362 MFEM_WARNING(
"Can't prune 3D aniso meshes yet.");
1398 for (
int i = 0; i < refinements.
Size(); i++)
1402 "anisotropic parallel refinement not supported yet in 3D.");
1404 MFEM_VERIFY(
Iso ||
Dim < 3,
1405 "parallel refinement of 3D aniso meshes not supported yet.");
1412 for (
int i = 0; i < neighbors.
Size(); i++)
1414 send_ref[neighbors[i]].SetNCMesh(
this);
1422 for (
int i = 0; i < refinements.
Size(); i++)
1428 for (
int j = 0; j < ranks.
Size(); j++)
1430 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
1438 for (
int i = 0; i < refinements.
Size(); i++)
1445 for (
int j = 0; j < neighbors.
Size(); j++)
1455 for (
int i = 0; i < msg.
Size(); i++)
1470 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
1477 long size = refinements.
Size(), glob_size;
1478 MPI_Allreduce(&size, &glob_size, 1, MPI_LONG, MPI_SUM,
MyComm);
1480 if (!glob_size) {
break; }
1488 MFEM_VERIFY(
Dim < 3 ||
Iso,
1489 "derefinement of 3D anisotropic meshes not implemented yet.");
1513 for (
int i = 0; i < derefs.
Size(); i++)
1515 int row = derefs[i];
1517 "invalid derefinement number.");
1522 int coarse_rank = INT_MAX;
1523 for (
int j = 0; j < size; j++)
1526 coarse_rank = std::min(coarse_rank, fine_rank);
1528 for (
int j = 0; j < size; j++)
1530 new_ranks[fine[j]] = coarse_rank;
1534 int target_elements = 0;
1535 for (
int i = 0; i < new_ranks.Size(); i++)
1537 if (new_ranks[i] ==
MyRank) { target_elements++; }
1551 for (
int i = 0; i < neighbors.
Size(); i++)
1553 send_deref[neighbors[i]].SetNCMesh(
this);
1560 for (
int i = 0; i < derefs.
Size(); i++)
1563 int parent =
elements[old_elements[fine[0]]].parent;
1567 for (
int j = 0; j < ranks.
Size(); j++)
1569 send_deref[ranks[j]].AddDerefinement(parent, new_ranks[fine[0]]);
1579 for (
int i = 0; i < old_elements.
Size(); i++)
1581 elements[old_elements[i]].index = i;
1586 old_elements.
Copy(coarse);
1587 for (
int i = 0; i < derefs.
Size(); i++)
1590 int parent =
elements[old_elements[fine[0]]].parent;
1599 for (
int j = 0; j < neighbors.
Size(); j++)
1609 for (
int i = 0; i < msg.
Size(); i++)
1627 for (
int i = 0; i < coarse.
Size(); i++)
1633 index = -1 -
elements[coarse[i]].rank;
1643 for (
int i = 0; i < coarse.
Size(); i++)
1657 template<
typename Type>
1659 const Table &deref_table)
1672 for (
int i = 0; i < deref_table.
Size(); i++)
1674 const int* fine = deref_table.
GetRow(i);
1675 int size = deref_table.
RowSize(i);
1676 MFEM_ASSERT(size <= 8,
"");
1678 int ranks[8], min_rank = INT_MAX, max_rank = INT_MIN;
1679 for (
int j = 0; j < size; j++)
1682 min_rank = std::min(min_rank, ranks[j]);
1683 max_rank = std::max(max_rank, ranks[j]);
1687 if (min_rank != max_rank)
1690 for (
int j = 0; j < size; j++)
1697 for (
int j = 0; j < size; j++)
1699 Type *data = &elem_data[fine[j]];
1701 int rnk = ranks[j], len = 1;
1707 for (
int k = 0; k < neigh.
Size(); k++)
1709 MPI_Request* req =
new MPI_Request;
1710 MPI_Isend(data, len, datatype, neigh[k], 292,
MyComm, req);
1716 MPI_Request* req =
new MPI_Request;
1717 MPI_Irecv(data, len, datatype, rnk, 292,
MyComm, req);
1724 for (
int i = 0; i < requests.
Size(); i++)
1726 MPI_Wait(requests[i], MPI_STATUS_IGNORE);
1733 ParNCMesh::SynchronizeDerefinementData<int>(
Array<int> &,
const Table &);
1745 for (
int i = 0; i < deref_table.
Size(); i++)
1747 const int *fine = deref_table.
GetRow(i),
1748 size = deref_table.
RowSize(i);
1753 for (
int j = 0; j < size; j++)
1761 for (
int k = 0; k <
Dim; k++)
1764 splits[k] >= max_nc_level)
1766 leaf_ok[fine[j]] = 0;
break;
1778 for (
int i = 0; i < deref_table.
Size(); i++)
1780 const int* fine = deref_table.
GetRow(i),
1781 size = deref_table.
RowSize(i);
1783 for (
int j = 0; j < size; j++)
1785 if (!leaf_ok[fine[j]])
1787 level_ok[i] = 0;
break;
1804 if (!custom_partition)
1810 long local_elems =
NElements, total_elems = 0;
1811 MPI_Allreduce(&local_elems, &total_elems, 1, MPI_LONG, MPI_SUM,
MyComm);
1813 long first_elem_global = 0;
1814 MPI_Scan(&local_elems, &first_elem_global, 1, MPI_LONG, MPI_SUM,
MyComm);
1815 first_elem_global -= local_elems;
1821 new_ranks[i] =
Partition(first_elem_global + (j++), total_elems);
1834 "Size of the partition array must match the number "
1835 "of local mesh elements (ParMesh::GetNE()).");
1838 custom_partition->
Copy(new_ranks);
1848 for (
int i = 0; i < old_elements.
Size(); i++)
1861 bool sfc = (target_elements >= 0);
1878 int begin = 0, end = 0;
1898 for (
int i = 0; i < rank_neighbors.
Size(); i++)
1900 int elem = rank_neighbors[i];
1908 recv_ghost_ranks[rank].SetNCMesh(
this);
1917 NeighborElementRankMessage::Map::iterator it;
1918 for (it = recv_ghost_ranks.begin(); it != recv_ghost_ranks.end(); ++it)
1921 for (
int i = 0; i < msg.
Size(); i++)
1925 new_ranks[ghost_index] = msg.
values[i];
1929 recv_ghost_ranks.clear();
1940 int received_elements = 0;
1946 received_elements++;
1948 el.
rank = new_ranks[i];
1951 int nsent = 0, nrecv = 0;
1958 owned_elements.
Sort([&](
const int a,
const int b)
1967 int begin = 0, end = 0;
1971 int rank =
elements[owned_elements[begin]].rank;
1972 while (end < owned_elements.
Size() &&
1973 elements[owned_elements[end]].rank == rank) { end++; }
1978 rank_elems.
MakeRef(&owned_elements[begin], end - begin);
1989 for (
int i = 0; i < batch.
Size(); i++)
1991 int elem = batch[i];
2037 while (received_elements < target_elements)
2046 for (
int i = 0; i < msg.
Size(); i++)
2048 int elem_rank = msg.
values[i];
2051 if (elem_rank ==
MyRank) { received_elements++; }
2073 MPI_Request barrier = MPI_REQUEST_NULL;
2085 for (
int i = 0; i < msg.
Size(); i++)
2097 if (barrier != MPI_REQUEST_NULL)
2099 MPI_Test(&barrier, &done, MPI_STATUS_IGNORE);
2105 int err = MPI_Ibarrier(
MyComm, &barrier);
2107 MFEM_VERIFY(err == MPI_SUCCESS,
"");
2108 MFEM_VERIFY(barrier != MPI_REQUEST_NULL,
"");
2119 int glob_sent, glob_recv;
2120 MPI_Reduce(&nsent, &glob_sent, 1, MPI_INT, MPI_SUM, 0,
MyComm);
2121 MPI_Reduce(&nrecv, &glob_recv, 1, MPI_INT, MPI_SUM, 0,
MyComm);
2125 MFEM_ASSERT(glob_sent == glob_recv,
2126 "(glob_sent, glob_recv) = ("
2127 << glob_sent <<
", " << glob_recv <<
")");
2134 const Table &old_element_dofs,
2135 long old_global_offset,
2142 RebalanceDofMessage::Map::iterator it;
2152 for (
int i = 0; i < ne; i++)
2173 RebalanceDofMessage::Map::iterator it;
2178 nd += msg.
dofs.size();
2189 for (
unsigned i = 0; i < msg.
elem_ids.size(); i++)
2193 for (
unsigned i = 0; i < msg.
dofs.size(); i++)
2206 : ncmesh(other.ncmesh), include_ref_types(other.include_ref_types)
2214 data.Append(value & 0xff);
2215 data.Append((value >> 8) & 0xff);
2216 data.Append((value >> 16) & 0xff);
2217 data.Append((value >> 24) & 0xff);
2223 return (
int) data[pos] +
2224 ((int) data[pos+1] << 8) +
2225 ((int) data[pos+2] << 16) +
2226 ((int) data[pos+3] << 24);
2231 for (
int i = 0; i < elements.
Size(); i++)
2233 int elem = elements[i];
2236 Element &el = ncmesh->elements[elem];
2237 if (el.
flag == flag) {
break; }
2246 Element &el = ncmesh->elements[elem];
2256 for (
int i = 0; i < 8; i++)
2258 if (el.
child[i] >= 0 && ncmesh->elements[el.
child[i]].flag)
2266 if (include_ref_types)
2271 for (
int i = 0; i < 8; i++)
2273 if (mask & (1 << i))
2275 EncodeTree(el.
child[i]);
2283 FlagElements(elements, 1);
2288 for (
int i = 0; i < ncmesh->root_state.Size(); i++)
2290 if (ncmesh->elements[i].flag)
2298 FlagElements(elements, 0);
2304 std::ostringstream oss;
2305 for (
int i = 0; i < ref_path.Size(); i++)
2307 oss <<
" elem " << ref_path[i] <<
" (";
2308 const Element &el = ncmesh->elements[ref_path[i]];
2309 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2311 if (j) { oss <<
", "; }
2312 oss << ncmesh->RetrieveNode(el, j);
2324 ref_path.Append(elem);
2326 int mask = data[pos++];
2333 Element &el = ncmesh->elements[elem];
2334 if (include_ref_types)
2336 int ref_type = data[pos++];
2339 ncmesh->RefineElement(elem, ref_type);
2341 else { MFEM_ASSERT(ref_type == el.
ref_type,
"") }
2345 MFEM_ASSERT(el.
ref_type != 0,
"Path not found:\n"
2346 << RefPath() <<
" mask = " << mask);
2349 for (
int i = 0; i < 8; i++)
2351 if (mask & (1 << i))
2353 DecodeTree(el.
child[i], pos, elements);
2358 ref_path.DeleteLast();
2365 while ((root = GetInt(pos)) >= 0)
2368 DecodeTree(root, pos, elements);
2374 write<int>(os, data.Size());
2375 os.write((
const char*) data.GetData(), data.Size());
2380 data.SetSize(read<int>(is));
2381 is.read((
char*) data.GetData(), data.Size());
2397 for (
unsigned i = 0; i <
groups.size(); i++)
2403 for (
int i = 0; i < ids[0].
Size(); i++)
2405 find_v[i].one = ids[0][i].index;
2419 for (
int j = 0; j < 2; j++)
2424 k = find_v[pos].two;
2435 for (
int i = 0; i < ids[1].
Size(); i++)
2437 find_e[i].one = ids[1][i].index;
2449 int v[4], e[4], eo[4], pos, k;
2451 for (
int j = 0; j < nfv; j++)
2455 k = find_v[pos].two;
2461 k = find_e[pos].two;
2476 for (
int i = 0; i < gi.
nv; i++)
2478 if (
nodes[el.
node[i]].vert_index ==
id.index)
2485 MFEM_ABORT(
"Vertex not found.");
2491 const int *ev =
GI[old.
Geom()].
edges[(int)
id.local];
2493 MFEM_ASSERT(node != NULL,
"Edge not found.");
2499 for (
int i = 0; i < gi.
ne; i++)
2501 const int* ev = gi.
edges[i];
2502 if ((el.
node[ev[0]] == node->
p1 && el.
node[ev[1]] == node->
p2) ||
2503 (el.
node[ev[1]] == node->
p1 && el.
node[ev[0]] == node->
p2))
2511 MFEM_ABORT(
"Edge not found.");
2517 const MeshId &first = ids[find[pos].two];
2518 while (++pos < find.Size() && ids[find[pos].two].index == first.
index)
2520 MeshId &other = ids[find[pos].two];
2528 std::map<int, int> stream_id;
2534 for (
int type = 0; type < 3; type++)
2536 for (
int i = 0; i < ids[type].
Size(); i++)
2538 elements.
Append(ids[type][i].element);
2550 for (
int i = 0; i < decoded.
Size(); i++)
2552 stream_id[decoded[i]] = i;
2557 for (
int type = 0; type < 3; type++)
2559 write<int>(os, ids[type].
Size());
2560 for (
int i = 0; i < ids[type].
Size(); i++)
2562 const MeshId&
id = ids[type][i];
2563 write<int>(os, stream_id[
id.element]);
2564 write<char>(os,
id.local);
2579 for (
int type = 0; type < 3; type++)
2581 int ne = read<int>(is);
2584 for (
int i = 0; i < ne; i++)
2586 int el_num = read<int>(is);
2587 int elem = elems[el_num];
2590 MFEM_VERIFY(!el.
ref_type,
"not a leaf element: " << el_num);
2592 MeshId &
id = ids[type][i];
2594 id.local = read<char>(is);
2602 id.index =
nodes[el.
node[(int)
id.local]].vert_index;
2607 const int* ev = gi.edges[(int)
id.local];
2609 MFEM_ASSERT(node && node->
HasEdge(),
"edge not found.");
2615 const int* fv = gi.faces[(int)
id.local];
2618 MFEM_ASSERT(face,
"face not found.");
2619 id.index = face->
index;
2629 std::map<GroupId, GroupId> stream_id;
2630 for (
int i = 0; i < ids.
Size(); i++)
2632 if (i && ids[i] == ids[i-1]) {
continue; }
2633 unsigned size = stream_id.size();
2634 GroupId &sid = stream_id[ids[i]];
2635 if (size != stream_id.size()) { sid = size; }
2639 write<short>(os, stream_id.size());
2640 for (std::map<GroupId, GroupId>::iterator
2641 it = stream_id.begin(); it != stream_id.end(); ++it)
2643 write<GroupId>(os, it->second);
2647 write<short>(os, group.size());
2648 for (
unsigned i = 0; i < group.size(); i++)
2650 write<int>(os, group[i]);
2656 write<short>(os, -1);
2661 write<int>(os, ids.
Size());
2662 for (
int i = 0; i < ids.
Size(); i++)
2664 write<GroupId>(os, stream_id[ids[i]]);
2670 int ngroups = read<short>(is);
2676 for (
int i = 0; i < ngroups; i++)
2678 int id = read<GroupId>(is);
2679 int size = read<short>(is);
2683 for (
int i = 0; i < size; i++)
2685 ranks[i] = read<int>(is);
2697 for (
int i = 0; i < ids.
Size(); i++)
2699 ids[i] = groups[read<GroupId>(is)];
2706 template<
class ValueType,
bool RefTypes,
int Tag>
2709 std::ostringstream ostream;
2715 eset.
Encode(tmp_elements);
2723 std::map<int, int> element_index;
2724 for (
int i = 0; i < decoded.
Size(); i++)
2726 element_index[decoded[i]] = i;
2729 write<int>(ostream, values.size());
2730 MFEM_ASSERT(
elements.size() == values.size(),
"");
2732 for (
unsigned i = 0; i < values.size(); i++)
2734 write<int>(ostream, element_index[
elements[i]]);
2735 write<ValueType>(ostream, values[i]);
2738 ostream.str().swap(data);
2741 template<
class ValueType,
bool RefTypes,
int Tag>
2744 std::istringstream istream(data);
2750 eset.
Decode(tmp_elements);
2752 int* el = tmp_elements.
GetData();
2756 int count = read<int>(istream);
2757 for (
int i = 0; i < count; i++)
2759 int index = read<int>(istream);
2760 MFEM_ASSERT(index >= 0 && (
size_t) index < values.size(),
"");
2761 values[
index] = read<ValueType>(istream);
2771 eset.SetNCMesh(ncmesh);
2776 eset.Decode(decoded);
2778 elem_ids.resize(decoded.
Size());
2779 for (
int i = 0; i < decoded.
Size(); i++)
2781 elem_ids[i] = eset.GetNCMesh()->elements[decoded[i]].index;
2785 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
2787 write<int>(os, dofs.size());
2789 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
2792 static void read_dofs(std::istream &is, std::vector<int> &dofs)
2794 dofs.resize(read<int>(is));
2795 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
2800 std::ostringstream stream;
2803 write<long>(stream, dof_offset);
2804 write_dofs(stream, dofs);
2806 stream.str().swap(data);
2811 std::istringstream stream(data);
2814 dof_offset = read<long>(stream);
2815 read_dofs(stream, dofs);
2822 elem_ids.resize(elems.
Size());
2823 for (
int i = 0; i < elems.
Size(); i++)
2825 elem_ids[i] = eset.GetNCMesh()->elements[elems[i]].index;
2838 for (
int i = 0; i < cle.
Size(); i++)
2846 debug_mesh.
ncmesh = copy;
2857 for (
int i = 0; i < 3; i++)
2874 return (elem_ids.capacity() + dofs.capacity()) *
sizeof(
int);
2877 template<
typename K,
typename V>
2878 static long map_memory_usage(
const std::map<K, V> &map)
2881 for (
typename std::map<K, V>::const_iterator
2882 it = map.begin(); it != map.end(); ++it)
2884 result += it->second.MemoryUsage();
2885 result +=
sizeof(std::pair<K, V>) + 3*
sizeof(
void*) +
sizeof(bool);
2893 for (
unsigned i = 0; i <
groups.size(); i++)
2895 groups_size +=
groups[i].capacity() *
sizeof(int);
2897 const int approx_node_size =
2898 sizeof(std::pair<CommGroup, GroupId>) + 3*
sizeof(
void*) +
sizeof(bool);
2899 return groups_size +
group_id.size() * approx_node_size;
2902 template<
typename Type,
int Size>
2903 static long arrays_memory_usage(
const Array<Type> (&arrays)[Size])
2906 for (
int i = 0; i < Size; i++)
2908 total += arrays[i].MemoryUsage();
2915 long total_groups_owners = 0;
2916 for (
int i = 0; i < 3; i++)
2953 << arrays_memory_usage(
entity_owner) <<
" entity_owner\n"
2980 #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)
Set up the group topology given the list of sets of shared entities.
Array< char > element_type
int Size() const
Return the 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)
Create an integer set from C-array 'p' of 'n' integers. Overwrites any existing set data...
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 Unique()
Removes duplicities from a sorted array. This requires operator== to be defined for T...
T * end()
STL-like end. Returns pointer after the last element of the array.
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 internal array to the provided copy.
virtual void ElementSharesVertex(int elem, int local, int vnode)
unsigned matrix
index into NCList::point_matrices[geom]
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
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 the 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 'el' 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
Copy sub array starting from offset out to the provided sa.
void FindNeighbors(int elem, Array< int > &neighbors, const Array< int > *search_set=NULL)
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.
Array< DenseMatrix * > point_matrices[Geometry::NumGeom]
List of unique point matrices for each slave geometry.
int Insert(IntegerSet &s)
Check to see if set 's' is in the list. If not append it to the end of the list. Returns the index of...
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.
T * begin()
STL-like begin. Returns pointer to the first element of the array.
int parent
parent element, -1 if this is a root element, -2 if free
std::map< int, NeighborRefinementMessage > Map
long MemoryUsage() const
Returns the number of bytes allocated for the array including any reserve.
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 in ascending order. 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]
static bool TestAllSent(MapT &rank_msg)
Return true if all messages in the map container were sent, otherwise return false, without waiting.
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
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 the 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)
Non-blocking synchronous send to processor 'rank'. Returns immediately. Completion (MPI_Wait/Test) me...
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
Array< MeshId > conforming
signed char geom
Geometry::Type (faces only) (char to save RAM)
void Isend(int rank, MPI_Comm comm)
Non-blocking send to processor 'rank'. Returns immediately. Completion (as tested by MPI_Wait/Test) d...
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()
int NGroups() const
Return the number of groups.
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)
Non-blocking probe for incoming message of this type from any rank. If there is an incoming message...
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
static void Probe(int &rank, int &size, MPI_Comm comm)
Blocking probe for incoming message of this type from any rank. Returns the rank and message size...
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