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[(int) 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)
237 int f_index =
faces[face].index;
240 owner = std::min(owner, el.
rank);
251 el_loc = (el.
index << 4) | local;
296 int e_index =
nodes[enode].edge_index;
299 owner = std::min(owner, el.
rank);
310 el_loc = (el.
index << 4) | local;
351 int v_index =
nodes[vnode].vert_index;
354 owner = std::min(owner, el.
rank);
365 el_loc = (el.
index << 4) | local;
404 for (
int i = 0; i < num; i++)
416 for (
unsigned i = 0; i < list.
masters.size(); i++)
425 slave_flag |= master_old_flag;
431 for (
unsigned i = 0; i < list.
conforming.size(); i++)
438 for (
unsigned i = 0; i < list.
masters.size(); i++)
445 for (
unsigned i = 0; i < list.
slaves.size(); i++)
456 if (lhs.size() == rhs.size())
458 for (
unsigned i = 0; i < lhs.size(); i++)
460 if (lhs[i] < rhs[i]) {
return true; }
464 return lhs.size() < rhs.size();
470 for (
unsigned i = 1; i < group.size(); i++)
472 if (group[i] <= group[i-1]) {
return false; }
480 if (group.size() == 1 && group[0] ==
MyRank)
484 MFEM_ASSERT(group_sorted(group),
"invalid group");
496 MFEM_ASSERT(rank != INT_MAX,
"invalid rank");
497 static std::vector<int> group;
507 for (
unsigned i = 0; i < group.size(); i++)
509 if (group[i] == rank) {
return true; }
520 entity_group.
SetSize(nentities);
526 int begin = 0, end = 0;
527 while (begin < index_rank.
Size())
529 int index = index_rank[begin].from;
530 if (index >= nentities)
534 while (end < index_rank.
Size() && index_rank[end].from == index)
538 group.resize(end - begin);
539 for (
int i = begin; i < end; i++)
541 group[i - begin] = index_rank[i].to;
550 for (
int i = 0; i < ranks.
Size(); i++)
563 int v[4], e[4], eo[4];
584 for (
int j = 0; j < 2; j++)
606 for (
int j = 0; j < 4; j++)
621 for (
int i = 0; i < 3; i++)
634 for (
int i = 0; i < 2; i++)
642 if (local) { local[i] = lf; }
646 for (
int j = 0; j < 4; j++)
648 ids[i][j] = e[i]->
node[fv[j]];
656 if (
Dim < 3) {
return; }
667 if (face->elem[0] >= 0 && face->elem[1] >= 0 && face->index <
NFaces)
672 if (e1->
rank == e2->
rank) {
continue; }
673 if (e1->
rank > e2->
rank) { std::swap(e1, e2); }
688 for (i = j = 0; i < bdr_vertices.
Size(); i++)
690 if (bdr_vertices[i] <
NVertices) { bdr_vertices[j++] = bdr_vertices[i]; }
695 for (i = j = 0; i < bdr_edges.
Size(); i++)
697 if (bdr_edges[i] <
NEdges) { bdr_edges[j++] = bdr_edges[i]; }
712 for (
int i = 0; i < nleaves; i++)
727 for (
int i = 0; i < nleaves; i++)
735 else if (boundary_set[i] && etype)
752 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
782 static void set_to_array(
const std::set<T> &set,
Array<T> &array)
786 for (std::set<int>::iterator it = set.begin(); it != set.end(); ++it)
801 set_to_array(ranks, neighbors);
809 const Array<int> &elem_local, &leaf_glob_order, &shared_local;
813 : elem_local(el), leaf_glob_order(lgo), shared_local(sl) {}
815 inline bool operator()(
const int a,
const int b)
817 int el_loc_a = elem_local[shared_local[a]];
818 int el_loc_b = elem_local[shared_local[b]];
820 int lgo_a = leaf_glob_order[el_loc_a >> 4];
821 int lgo_b = leaf_glob_order[el_loc_b >> 4];
823 if (lgo_a != lgo_b) {
return lgo_a < lgo_b; }
825 return (el_loc_a & 0xf) < (el_loc_b & 0xf);
834 group_shared.
MakeI(ngroups-1);
838 for (
int i = 0; i < conf_group.
Size(); i++)
847 shared_local.
SetSize(num_shared);
848 group_shared.
MakeJ();
851 for (
int i = 0, j = 0; i < conf_group.
Size(); i++)
863 for (
int i = 0; i < group_shared.
Size(); i++)
865 int size = group_shared.
RowSize(i);
866 int *row = group_shared.
GetRow(i);
879 for (
int ent = 0; ent <
Dim; ent++)
894 for (
unsigned i = 0; i <
groups.size(); i++)
896 if (
groups[i].size() > 1 || !i)
899 group_map[i] = int_groups.
Insert(iset);
906 for (
int ent = 0; ent < 3; ent++)
911 ecg = group_map[ecg];
954 for (
int ent = 0; ent <
Dim; ent++)
984 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
988 MFEM_ASSERT(face != NULL,
"");
990 MFEM_ASSERT(face->
elem[0] >= 0 && face->
elem[1] >= 0,
"");
993 if (e[0]->rank ==
MyRank) { std::swap(e[0], e[1]); }
994 MFEM_ASSERT(e[0]->rank !=
MyRank && e[1]->rank ==
MyRank,
"");
1000 for (
unsigned i = 0; i < shared.
masters.size(); i++)
1012 if (loc0 == loc1) {
continue; }
1013 if (loc0) { std::swap(e[0], e[1]); }
1020 MFEM_ASSERT(fnbr.
Size() <= bound,
"oops, bad upper bound");
1030 for (
int i = 0; i < fnbr.
Size(); i++)
1049 std::map<int, int> vert_map;
1050 for (
int i = 0; i < fnbr.
Size(); i++)
1058 for (
int k = 0; k < gi.
nv; k++)
1060 int &v = vert_map[elem->
node[k]];
1061 if (!v) { v = vert_map.size(); }
1065 if (!i || elem->
rank != fnbr[i-1]->rank)
1080 std::map<int, int>::iterator it;
1081 for (it = vert_map.begin(); it != vert_map.end(); ++it)
1093 for (
int i = 0, last_rank = -1; i < send_elems.
Size(); i++)
1096 if (c.
from != last_rank)
1104 c.
from = send_elems[i-1].from;
1110 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
1116 if (e[0]->rank ==
MyRank) { std::swap(e[0], e[1]); }
1133 if (shared.
slaves.size())
1139 MFEM_ASSERT(pmesh.
faces_info.Size() == nfaces,
"");
1142 for (
int i = nfaces; i < pmesh.
faces_info.Size(); i++)
1153 for (
unsigned i = 0; i < shared.
masters.size(); i++)
1166 if (sloc == mloc) {
continue; }
1195 if (!sloc &&
Dim == 3)
1199 std::swap((*pm2)(0,1), (*pm2)(0,3));
1200 std::swap((*pm2)(1,1), (*pm2)(1,3));
1217 MFEM_ASSERT(fi.
NCFace < 0,
"");
1246 bool removeAll =
true;
1249 for (
int i = 0; i < 8; i++)
1252 if (el.
child[i] >= 0)
1255 if (!
remove[i]) { removeAll =
false; }
1260 if (removeAll) {
return true; }
1263 for (
int i = 0; i < 8; i++)
1283 MFEM_WARNING(
"Can't prune 3D aniso meshes yet.");
1313 for (
int i = 0; i < refinements.
Size(); i++)
1317 "anisotropic parallel refinement not supported yet in 3D.");
1319 MFEM_VERIFY(
Iso ||
Dim < 3,
1320 "parallel refinement of 3D aniso meshes not supported yet.");
1327 for (
int i = 0; i < neighbors.
Size(); i++)
1329 send_ref[neighbors[i]].SetNCMesh(
this);
1337 for (
int i = 0; i < refinements.
Size(); i++)
1343 for (
int j = 0; j < ranks.
Size(); j++)
1345 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
1353 for (
int i = 0; i < refinements.
Size(); i++)
1360 for (
int j = 0; j < neighbors.
Size(); j++)
1370 for (
int i = 0; i < msg.
Size(); i++)
1385 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
1392 long size = refinements.
Size(), glob_size;
1393 MPI_Allreduce(&size, &glob_size, 1, MPI_LONG, MPI_SUM,
MyComm);
1395 if (!glob_size) {
break; }
1403 MFEM_VERIFY(
Dim < 3 ||
Iso,
1404 "derefinement of 3D anisotropic meshes not implemented yet.");
1428 for (
int i = 0; i < derefs.
Size(); i++)
1430 int row = derefs[i];
1432 "invalid derefinement number.");
1437 int coarse_rank = INT_MAX;
1438 for (
int j = 0; j < size; j++)
1441 coarse_rank = std::min(coarse_rank, fine_rank);
1443 for (
int j = 0; j < size; j++)
1445 new_ranks[fine[j]] = coarse_rank;
1449 int target_elements = 0;
1450 for (
int i = 0; i < new_ranks.Size(); i++)
1452 if (new_ranks[i] ==
MyRank) { target_elements++; }
1466 for (
int i = 0; i < neighbors.
Size(); i++)
1468 send_deref[neighbors[i]].SetNCMesh(
this);
1475 for (
int i = 0; i < derefs.
Size(); i++)
1478 int parent =
elements[old_elements[fine[0]]].parent;
1482 for (
int j = 0; j < ranks.
Size(); j++)
1484 send_deref[ranks[j]].AddDerefinement(parent, new_ranks[fine[0]]);
1494 for (
int i = 0; i < old_elements.
Size(); i++)
1496 elements[old_elements[i]].index = i;
1501 old_elements.
Copy(coarse);
1502 for (
int i = 0; i < derefs.
Size(); i++)
1505 int parent =
elements[old_elements[fine[0]]].parent;
1514 for (
int j = 0; j < neighbors.
Size(); j++)
1524 for (
int i = 0; i < msg.
Size(); i++)
1542 for (
int i = 0; i < coarse.
Size(); i++)
1544 int index =
elements[coarse[i]].index;
1548 index = -1 -
elements[coarse[i]].rank;
1558 for (
int i = 0; i < coarse.
Size(); i++)
1563 index =
elements[old_elements[index]].index;
1572 template<
typename Type>
1574 const Table &deref_table)
1587 for (
int i = 0; i < deref_table.
Size(); i++)
1589 const int* fine = deref_table.
GetRow(i);
1590 int size = deref_table.
RowSize(i);
1591 MFEM_ASSERT(size <= 8,
"");
1593 int ranks[8], min_rank = INT_MAX, max_rank = INT_MIN;
1594 for (
int j = 0; j < size; j++)
1597 min_rank = std::min(min_rank, ranks[j]);
1598 max_rank = std::max(max_rank, ranks[j]);
1602 if (min_rank != max_rank)
1605 for (
int j = 0; j < size; j++)
1612 for (
int j = 0; j < size; j++)
1614 Type *data = &elem_data[fine[j]];
1616 int rnk = ranks[j], len = 1;
1622 for (
int k = 0; k < neigh.
Size(); k++)
1624 MPI_Request* req =
new MPI_Request;
1625 MPI_Isend(data, len, datatype, neigh[k], 292,
MyComm, req);
1631 MPI_Request* req =
new MPI_Request;
1632 MPI_Irecv(data, len, datatype, rnk, 292,
MyComm, req);
1639 for (
int i = 0; i < requests.
Size(); i++)
1641 MPI_Wait(requests[i], MPI_STATUS_IGNORE);
1648 ParNCMesh::SynchronizeDerefinementData<int>(
Array<int> &,
const Table &);
1660 for (
int i = 0; i < deref_table.
Size(); i++)
1662 const int *fine = deref_table.
GetRow(i),
1663 size = deref_table.
RowSize(i);
1668 for (
int j = 0; j < size; j++)
1676 for (
int k = 0; k <
Dim; k++)
1679 splits[k] >= max_nc_level)
1681 leaf_ok[fine[j]] = 0;
break;
1693 for (
int i = 0; i < deref_table.
Size(); i++)
1695 const int* fine = deref_table.
GetRow(i),
1696 size = deref_table.
RowSize(i);
1698 for (
int j = 0; j < size; j++)
1700 if (!leaf_ok[fine[j]])
1702 level_ok[i] = 0;
break;
1720 long local_elems =
NElements, total_elems = 0;
1721 MPI_Allreduce(&local_elems, &total_elems, 1, MPI_LONG, MPI_SUM,
MyComm);
1723 long first_elem_global = 0;
1724 MPI_Scan(&local_elems, &first_elem_global, 1, MPI_LONG, MPI_SUM,
MyComm);
1725 first_elem_global -= local_elems;
1734 new_ranks[i] =
Partition(first_elem_global + (j++), total_elems);
1747 for (
int i = 0; i < old_elements.
Size(); i++)
1760 const ElemArray &elements;
1761 CompareRanks(
const ElemArray &elements) : elements(elements) {}
1763 inline bool operator()(
const int a,
const int b)
1765 return elements[a].rank < elements[b].rank;
1783 int begin = 0, end = 0;
1803 for (
int i = 0; i < rank_neighbors.
Size(); i++)
1805 int elem = rank_neighbors[i];
1813 recv_ghost_ranks[rank].SetNCMesh(
this);
1822 NeighborElementRankMessage::Map::iterator it;
1823 for (it = recv_ghost_ranks.begin(); it != recv_ghost_ranks.end(); ++it)
1826 for (
int i = 0; i < msg.
Size(); i++)
1830 new_ranks[ghost_index] = msg.
values[i];
1834 recv_ghost_ranks.clear();
1845 int received_elements = 0;
1851 received_elements++;
1853 el.
rank = new_ranks[i];
1867 int begin = 0, end = 0;
1871 int rank =
elements[owned_elements[begin]].rank;
1872 while (end < owned_elements.
Size() &&
1873 elements[owned_elements[end]].rank == rank) { end++; }
1878 rank_elems.
MakeRef(&owned_elements[begin], end - begin);
1889 for (
int i = 0; i < batch.
Size(); i++)
1891 int elem = batch[i];
1926 while (received_elements < target_elements)
1934 for (
int i = 0; i < msg.
Size(); i++)
1936 int elem_rank = msg.
values[i];
1939 if (elem_rank ==
MyRank) { received_elements++; }
1958 const Table &old_element_dofs,
1959 long old_global_offset,
1966 RebalanceDofMessage::Map::iterator it;
1976 for (
int i = 0; i < ne; i++)
1997 RebalanceDofMessage::Map::iterator it;
2002 nd += msg.
dofs.size();
2013 for (
unsigned i = 0; i < msg.
elem_ids.size(); i++)
2017 for (
unsigned i = 0; i < msg.
dofs.size(); i++)
2030 : ncmesh(other.ncmesh), include_ref_types(other.include_ref_types)
2038 data.Append(value & 0xff);
2039 data.Append((value >> 8) & 0xff);
2040 data.Append((value >> 16) & 0xff);
2041 data.Append((value >> 24) & 0xff);
2047 return (
int) data[pos] +
2048 ((int) data[pos+1] << 8) +
2049 ((int) data[pos+2] << 16) +
2050 ((int) data[pos+3] << 24);
2055 for (
int i = 0; i < elements.
Size(); i++)
2057 int elem = elements[i];
2060 Element &el = ncmesh->elements[elem];
2061 if (el.
flag == flag) {
break; }
2070 Element &el = ncmesh->elements[elem];
2080 for (
int i = 0; i < 8; i++)
2082 if (el.
child[i] >= 0 && ncmesh->elements[el.
child[i]].flag)
2090 if (include_ref_types)
2095 for (
int i = 0; i < 8; i++)
2097 if (mask & (1 << i))
2099 EncodeTree(el.
child[i]);
2107 FlagElements(elements, 1);
2112 for (
int i = 0; i < ncmesh->root_state.Size(); i++)
2114 if (ncmesh->elements[i].flag)
2122 FlagElements(elements, 0);
2128 int mask = data[pos++];
2135 Element &el = ncmesh->elements[elem];
2136 if (include_ref_types)
2138 int ref_type = data[pos++];
2141 ncmesh->RefineElement(elem, ref_type);
2143 else { MFEM_ASSERT(ref_type == el.
ref_type,
"") }
2145 else { MFEM_ASSERT(el.
ref_type != 0,
""); }
2147 for (
int i = 0; i < 8; i++)
2149 if (mask & (1 << i))
2151 DecodeTree(el.
child[i], pos, elements);
2160 while ((root = GetInt(pos)) >= 0)
2163 DecodeTree(root, pos, elements);
2169 write<int>(os, data.Size());
2170 os.write((
const char*) data.GetData(), data.Size());
2175 data.SetSize(read<int>(is));
2176 is.read((
char*) data.GetData(), data.Size());
2192 for (
unsigned i = 0; i <
groups.size(); i++)
2198 for (
int i = 0; i < ids[0].
Size(); i++)
2200 find_v[i].one = ids[0][i].index;
2214 for (
int j = 0; j < 2; j++)
2219 k = find_v[pos].two;
2230 for (
int i = 0; i < ids[1].
Size(); i++)
2232 find_e[i].one = ids[1][i].index;
2244 int v[4], e[4], eo[4], pos, k;
2246 for (
int j = 0; j < 4; j++)
2250 k = find_v[pos].two;
2256 k = find_e[pos].two;
2271 for (
int i = 0; i < gi.
nv; i++)
2273 if (
nodes[el.
node[i]].vert_index ==
id.index)
2280 MFEM_ABORT(
"Vertex not found.");
2286 const int *ev =
GI[(int) old.
geom].
edges[
id.local];
2288 MFEM_ASSERT(node != NULL,
"Edge not found.");
2294 for (
int i = 0; i < gi.
ne; i++)
2296 const int* ev = gi.
edges[i];
2297 if ((el.
node[ev[0]] == node->p1 && el.
node[ev[1]] == node->p2) ||
2298 (el.
node[ev[1]] == node->p1 && el.
node[ev[0]] == node->p2))
2306 MFEM_ABORT(
"Edge not found.");
2312 const MeshId &first = ids[find[pos].two];
2313 while (++pos < find.Size() && ids[find[pos].two].index == first.
index)
2315 MeshId &other = ids[find[pos].two];
2323 std::map<int, int> stream_id;
2329 for (
int type = 0; type < 3; type++)
2331 for (
int i = 0; i < ids[type].
Size(); i++)
2333 elements.
Append(ids[type][i].element);
2345 for (
int i = 0; i < decoded.
Size(); i++)
2347 stream_id[decoded[i]] = i;
2352 for (
int type = 0; type < 3; type++)
2354 write<int>(os, ids[type].
Size());
2355 for (
int i = 0; i < ids[type].
Size(); i++)
2357 const MeshId&
id = ids[type][i];
2358 write<int>(os, stream_id[
id.element]);
2359 write<char>(os,
id.local);
2374 for (
int type = 0; type < 3; type++)
2376 int ne = read<int>(is);
2379 for (
int i = 0; i < ne; i++)
2381 int el_num = read<int>(is);
2382 int elem = elems[el_num];
2385 MFEM_VERIFY(!el.
ref_type,
"not a leaf element: " << el_num);
2387 MeshId &
id = ids[type][i];
2389 id.local = read<char>(is);
2397 id.index =
nodes[el.
node[
id.local]].vert_index;
2402 const int* ev = gi.edges[
id.local];
2404 MFEM_ASSERT(node && node->
HasEdge(),
"edge not found.");
2410 const int* fv = gi.faces[
id.local];
2413 MFEM_ASSERT(face,
"face not found.");
2414 id.index = face->
index;
2424 std::map<GroupId, GroupId> stream_id;
2425 for (
int i = 0; i < ids.
Size(); i++)
2427 if (i && ids[i] == ids[i-1]) {
continue; }
2428 unsigned size = stream_id.size();
2429 GroupId &sid = stream_id[ids[i]];
2430 if (size != stream_id.size()) { sid = size; }
2434 write<short>(os, stream_id.size());
2435 for (std::map<GroupId, GroupId>::iterator
2436 it = stream_id.begin(); it != stream_id.end(); ++it)
2438 write<GroupId>(os, it->second);
2442 write<short>(os, group.size());
2443 for (
unsigned i = 0; i < group.size(); i++)
2445 write<int>(os, group[i]);
2451 write<short>(os, -1);
2456 write<int>(os, ids.
Size());
2457 for (
int i = 0; i < ids.
Size(); i++)
2459 write<GroupId>(os, stream_id[ids[i]]);
2465 int ngroups = read<short>(is);
2471 for (
int i = 0; i < ngroups; i++)
2473 int id = read<GroupId>(is);
2474 int size = read<short>(is);
2478 for (
int i = 0; i < size; i++)
2480 ranks[i] = read<int>(is);
2492 for (
int i = 0; i < ids.
Size(); i++)
2494 ids[i] = groups[read<GroupId>(is)];
2501 template<
class ValueType,
bool RefTypes,
int Tag>
2504 std::ostringstream ostream;
2510 eset.
Encode(tmp_elements);
2518 std::map<int, int> element_index;
2519 for (
int i = 0; i < decoded.
Size(); i++)
2521 element_index[decoded[i]] = i;
2524 write<int>(ostream, values.size());
2525 MFEM_ASSERT(
elements.size() == values.size(),
"");
2527 for (
unsigned i = 0; i < values.size(); i++)
2529 write<int>(ostream, element_index[
elements[i]]);
2530 write<ValueType>(ostream, values[i]);
2533 ostream.str().swap(data);
2536 template<
class ValueType,
bool RefTypes,
int Tag>
2539 std::istringstream istream(data);
2545 eset.
Decode(tmp_elements);
2547 int* el = tmp_elements.
GetData();
2551 int count = read<int>(istream);
2552 for (
int i = 0; i < count; i++)
2554 int index = read<int>(istream);
2555 MFEM_ASSERT(index >= 0 && (
size_t) index < values.size(),
"");
2556 values[index] = read<ValueType>(istream);
2566 eset.SetNCMesh(ncmesh);
2571 eset.Decode(decoded);
2573 elem_ids.resize(decoded.
Size());
2574 for (
int i = 0; i < decoded.
Size(); i++)
2576 elem_ids[i] = eset.GetNCMesh()->elements[decoded[i]].index;
2580 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
2582 write<int>(os, dofs.size());
2584 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
2587 static void read_dofs(std::istream &is, std::vector<int> &dofs)
2589 dofs.resize(read<int>(is));
2590 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
2595 std::ostringstream stream;
2598 write<long>(stream, dof_offset);
2599 write_dofs(stream, dofs);
2601 stream.str().swap(data);
2606 std::istringstream stream(data);
2609 dof_offset = read<long>(stream);
2610 read_dofs(stream, dofs);
2617 elem_ids.resize(elems.
Size());
2618 for (
int i = 0; i < elems.
Size(); i++)
2620 elem_ids[i] = eset.GetNCMesh()->elements[elems[i]].index;
2633 for (
int i = 0; i < cle.
Size(); i++)
2641 debug_mesh.
ncmesh = copy;
2652 for (
int i = 0; i < 3; i++)
2669 return (elem_ids.capacity() + dofs.capacity()) *
sizeof(
int);
2672 template<
typename K,
typename V>
2673 static long map_memory_usage(
const std::map<K, V> &map)
2676 for (
typename std::map<K, V>::const_iterator
2677 it = map.begin(); it != map.end(); ++it)
2679 result += it->second.MemoryUsage();
2680 result +=
sizeof(std::pair<K, V>) + 3*
sizeof(
void*) +
sizeof(bool);
2688 for (
unsigned i = 0; i <
groups.size(); i++)
2690 groups_size +=
groups[i].capacity() *
sizeof(int);
2692 const int approx_node_size =
2693 sizeof(std::pair<CommGroup, GroupId>) + 3*
sizeof(
void*) +
sizeof(bool);
2694 return groups_size +
group_id.size() * approx_node_size;
2697 template<
typename Type,
int Size>
2698 static long arrays_memory_usage(
const Array<Type> (&arrays)[Size])
2701 for (
int i = 0; i < Size; i++)
2703 total += arrays[i].MemoryUsage();
2710 long total_groups_owners = 0;
2711 for (
int i = 0; i < 3; i++)
2748 << arrays_memory_usage(
entity_owner) <<
" entity_owner\n"
2775 #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()
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 GetFaceVerticesEdges(const MeshId &face_id, int vert_index[4], int edge_index[4], int edge_orientation[4]) const
Return Mesh vertex and edge indices of a face identified by 'face_id'.
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.
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)
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.
void CountSplits(int elem, int splits[3]) 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.
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.
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.
int local
local number within 'element'
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()
Geometry::Type geom
Geometry::Type of the element.
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.
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, quadrilateral or triangular meshes...
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
static GeomInfo GI[Geometry::NumGeom]
void Clear(bool hard=false)
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...
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 RefineElement(int elem, char ref_type)
virtual void Refine(const Array< Refinement > &refinements)
static bool compare_ranks_indices(const Element *a, const Element *b)
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
static int find_element_edge(const Element &el, int vn0, int vn1)
Table group_svert
Shared objects in each group.
Array< int > boundary_layer
list of type 3 elements
void Isend(int rank, MPI_Comm comm)
Non-blocking send to processor 'rank'.
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()
static int find_hex_face(int a, int b, int c)
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.
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]
friend struct CompareRanks
void NeighborProcessors(Array< int > &neighbors)
long GroupsMemoryUsage() const
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
void MakeSharedTable(int ngroups, int ent, Array< int > &shared_local, Table &group_shared)
static void Probe(int &rank, int &size, MPI_Comm comm)
ParNCMesh(MPI_Comm comm, const NCMesh &ncmesh, int *part=NULL)
Array< GroupId > entity_conf_group[3]
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const