12 #include "../config/config.hpp"
18 #include "../general/binaryio.hpp"
26 using namespace bin_io;
120 if (node->HasVertex()) { node->vert_index = -1; }
129 for (
int j = 0; j <
GI[(int) el.
geom].
nv; j++)
131 int &vindex =
nodes[el.
node[j]].vert_index;
132 if (vindex < 0) { vindex =
NVertices++; }
140 if (node->HasVertex() && node->vert_index >= 0)
149 if (node->HasVertex() && node->vert_index < 0)
165 if (node->HasEdge()) { node->edge_index = -1; }
180 if (node->HasEdge() && node->edge_index < 0)
207 int f_index =
faces[face].index;
210 owner = std::min(owner, el_rank);
247 int e_index =
nodes[enode].edge_index;
250 owner = std::min(owner, el_rank);
283 int v_index =
nodes[vnode].vert_index;
286 owner = std::min(owner, el_rank);
314 if (lhs.size() == rhs.size())
316 for (
unsigned i = 0; i < lhs.size(); i++)
318 if (lhs[i] < rhs[i]) {
return true; }
322 return lhs.size() < rhs.size();
328 for (
unsigned i = 1; i < group.size(); i++)
330 if (group[i] <= group[i-1]) {
return false; }
338 if (group.size() == 1 && group[0] ==
MyRank)
342 MFEM_ASSERT(group_sorted(group),
"invalid group");
354 if (g1 == g2) {
return g1; }
359 join.reserve(cg1.size() + cg2.size());
360 join.insert(join.end(), cg1.begin(), cg1.end());
361 join.insert(join.end(), cg2.begin(), cg2.end());
363 std::sort(join.begin(), join.end());
364 join.erase(std::unique(join.begin(), join.end()), join.end());
371 if (rank == INT_MAX) {
return -1; }
372 static std::vector<int> group;
382 for (
unsigned i = 0; i < group.size(); i++)
384 if (group[i] == rank) {
return true; }
392 for (
int i = 0; i < num; i++)
409 int begin = 0, end = 0;
417 group.resize(end - begin);
418 for (
int i = begin; i < end; i++)
427 struct MasterSlaveInfo
430 int slaves_begin, slaves_end;
431 MasterSlaveInfo() : master(-1), slaves_begin(0), slaves_end(0) {}
436 #if 0 // optimal version for P matrix construction but breaks ParMesh::Print and DG
440 for (
unsigned i = 0; i < list.slaves.size(); i++)
442 const Slave& sf = list.slaves[i];
453 for (
int i = 0; i < size; i++)
458 int master = masters[index];
465 #else // suboptimal version fully linking master and slave entities in groups
468 std::vector<MasterSlaveInfo> info(nitems);
470 for (
unsigned i = 0; i < list.masters.size(); i++)
472 const Master &mf = list.masters[i];
476 for (
unsigned i = 0; i < list.slaves.size(); i++)
478 const Slave& sf = list.slaves[i];
490 for (
int i = 0; i < size; i++)
495 const MasterSlaveInfo &msi = info[index];
503 for (
int j = msi.slaves_begin; j < msi.slaves_end; j++)
531 for (
int j = 0; j < 2; j++)
542 int v[4], e[4], eo[4];
547 for (
int j = 0; j < 4; j++)
565 group_shared =
false;
569 for (
unsigned i = 0; i <
groups.size(); i++)
572 if (group.size() > 1)
574 for (
unsigned j = 0; j < group.size(); j++)
578 group_shared[i] =
true;
587 const NCList &list, NCList &shared)
594 for (
unsigned i = 0; i < list.conforming.size(); i++)
596 if (group_shared[entity_group[list.conforming[i].index]])
598 shared.conforming.push_back(list.conforming[i]);
601 for (
unsigned i = 0; i < list.masters.size(); i++)
603 if (group_shared[entity_group[list.masters[i].index]])
605 shared.masters.push_back(list.masters[i]);
608 for (
unsigned i = 0; i < list.slaves.size(); i++)
610 if (group_shared[entity_group[list.slaves[i].index]])
612 shared.slaves.push_back(list.slaves[i]);
623 for (
int i = 0; i < 2; i++)
631 if (local) { local[i] = lf; }
635 for (
int j = 0; j < 4; j++)
637 ids[i][j] = e[i]->
node[fv[j]];
645 if (
Dim < 3) {
return; }
656 if (face->elem[0] >= 0 && face->elem[1] >= 0 && face->index <
NFaces)
661 if (e1->
rank == e2->
rank) {
continue; }
662 if (e1->
rank > e2->
rank) { std::swap(e1, e2); }
677 for (i = j = 0; i < bdr_vertices.
Size(); i++)
679 if (bdr_vertices[i] <
NVertices) { bdr_vertices[j++] = bdr_vertices[i]; }
684 for (i = j = 0; i < bdr_edges.
Size(); i++)
686 if (bdr_edges[i] <
NEdges) { bdr_edges[j++] = bdr_edges[i]; }
701 for (
int i = 0; i < nleaves; i++)
716 for (
int i = 0; i < nleaves; i++)
724 else if (boundary_set[i] && etype)
741 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
771 static void set_to_array(
const std::set<T> &set,
Array<T> &array)
775 for (std::set<int>::iterator it = set.begin(); it != set.end(); ++it)
790 set_to_array(ranks, neighbors);
809 int bound = shared.conforming.
size() + shared.slaves.size();
815 for (
unsigned i = 0; i < shared.conforming.size(); i++)
817 const MeshId &cf = shared.conforming[i];
819 MFEM_ASSERT(face != NULL,
"");
821 MFEM_ASSERT(face->
elem[0] >= 0 && face->
elem[1] >= 0,
"");
824 if (e[0]->rank ==
MyRank) { std::swap(e[0], e[1]); }
825 MFEM_ASSERT(e[0]->rank !=
MyRank && e[1]->rank ==
MyRank,
"");
831 for (
unsigned i = 0; i < shared.masters.size(); i++)
833 const Master &mf = shared.masters[i];
836 const Slave &sf = full_list.slaves[j];
843 if (loc0 == loc1) {
continue; }
844 if (loc0) { std::swap(e[0], e[1]); }
851 MFEM_ASSERT(fnbr.
Size() <= bound,
"oops, bad upper bound");
861 for (
int i = 0; i < fnbr.
Size(); i++)
880 std::map<int, int> vert_map;
881 for (
int i = 0; i < fnbr.
Size(); i++)
889 for (
int k = 0; k < gi.
nv; k++)
891 int &v = vert_map[elem->
node[k]];
892 if (!v) { v = vert_map.size(); }
896 if (!i || elem->
rank != fnbr[i-1]->rank)
911 std::map<int, int>::iterator it;
912 for (it = vert_map.begin(); it != vert_map.end(); ++it)
924 for (
int i = 0, last_rank = -1; i < send_elems.
Size(); i++)
927 if (c.
from != last_rank)
935 c.
from = send_elems[i-1].from;
941 for (
unsigned i = 0; i < shared.conforming.size(); i++)
943 const MeshId &cf = shared.conforming[i];
947 if (e[0]->rank ==
MyRank) { std::swap(e[0], e[1]); }
964 if (shared.slaves.size())
970 MFEM_ASSERT(pmesh.
faces_info.Size() == nfaces,
"");
973 for (
int i = nfaces; i < pmesh.
faces_info.Size(); i++)
984 for (
unsigned i = 0; i < shared.masters.size(); i++)
986 const Master &mf = shared.masters[i];
989 const Slave &sf = full_list.slaves[j];
997 if (sloc == mloc) {
continue; }
1026 if (!sloc &&
Dim == 3)
1030 std::swap((*pm2)(0,1), (*pm2)(0,3));
1031 std::swap((*pm2)(1,1), (*pm2)(1,3));
1048 MFEM_ASSERT(fi.
NCFace < 0,
"");
1077 bool removeAll =
true;
1080 for (
int i = 0; i < 8; i++)
1083 if (el.
child[i] >= 0)
1086 if (!
remove[i]) { removeAll =
false; }
1091 if (removeAll) {
return true; }
1094 for (
int i = 0; i < 8; i++)
1114 MFEM_WARNING(
"Can't prune 3D aniso meshes yet.");
1144 for (
int i = 0; i < refinements.
Size(); i++)
1148 "anisotropic parallel refinement not supported yet in 3D.");
1150 MFEM_VERIFY(
Iso ||
Dim < 3,
1151 "parallel refinement of 3D aniso meshes not supported yet.");
1158 for (
int i = 0; i < neighbors.
Size(); i++)
1160 send_ref[neighbors[i]].SetNCMesh(
this);
1168 for (
int i = 0; i < refinements.
Size(); i++)
1174 for (
int j = 0; j < ranks.
Size(); j++)
1176 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
1184 for (
int i = 0; i < refinements.
Size(); i++)
1191 for (
int j = 0; j < neighbors.
Size(); j++)
1201 for (
int i = 0; i < msg.
Size(); i++)
1216 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
1223 long size = refinements.
Size(), glob_size;
1224 MPI_Allreduce(&size, &glob_size, 1, MPI_LONG, MPI_SUM,
MyComm);
1226 if (!glob_size) {
break; }
1234 MFEM_VERIFY(
Dim < 3 ||
Iso,
1235 "derefinement of 3D anisotropic meshes not implemented yet.");
1259 for (
int i = 0; i < derefs.
Size(); i++)
1261 int row = derefs[i];
1263 "invalid derefinement number.");
1268 int coarse_rank = INT_MAX;
1269 for (
int j = 0; j < size; j++)
1272 coarse_rank = std::min(coarse_rank, fine_rank);
1274 for (
int j = 0; j < size; j++)
1276 new_ranks[fine[j]] = coarse_rank;
1280 int target_elements = 0;
1281 for (
int i = 0; i < new_ranks.Size(); i++)
1283 if (new_ranks[i] ==
MyRank) { target_elements++; }
1297 for (
int i = 0; i < neighbors.
Size(); i++)
1299 send_deref[neighbors[i]].SetNCMesh(
this);
1306 for (
int i = 0; i < derefs.
Size(); i++)
1309 int parent =
elements[old_elements[fine[0]]].parent;
1313 for (
int j = 0; j < ranks.
Size(); j++)
1315 send_deref[ranks[j]].AddDerefinement(parent, new_ranks[fine[0]]);
1325 for (
int i = 0; i < old_elements.
Size(); i++)
1327 elements[old_elements[i]].index = i;
1332 old_elements.
Copy(coarse);
1333 for (
int i = 0; i < derefs.
Size(); i++)
1336 int parent =
elements[old_elements[fine[0]]].parent;
1345 for (
int j = 0; j < neighbors.
Size(); j++)
1355 for (
int i = 0; i < msg.
Size(); i++)
1373 for (
int i = 0; i < coarse.
Size(); i++)
1375 int index =
elements[coarse[i]].index;
1379 index = -1 -
elements[coarse[i]].rank;
1389 for (
int i = 0; i < coarse.
Size(); i++)
1394 index =
elements[old_elements[index]].index;
1403 template<
typename Type>
1405 const Table &deref_table)
1418 for (
int i = 0; i < deref_table.
Size(); i++)
1420 const int* fine = deref_table.
GetRow(i);
1421 int size = deref_table.
RowSize(i);
1422 MFEM_ASSERT(size <= 8,
"");
1424 int ranks[8], min_rank = INT_MAX, max_rank = INT_MIN;
1425 for (
int j = 0; j < size; j++)
1428 min_rank = std::min(min_rank, ranks[j]);
1429 max_rank = std::max(max_rank, ranks[j]);
1433 if (min_rank != max_rank)
1436 for (
int j = 0; j < size; j++)
1443 for (
int j = 0; j < size; j++)
1445 Type *data = &elem_data[fine[j]];
1447 int rnk = ranks[j], len = 1;
1453 for (
int k = 0; k < neigh.
Size(); k++)
1455 MPI_Request* req =
new MPI_Request;
1456 MPI_Isend(data, len, datatype, neigh[k], 292,
MyComm, req);
1462 MPI_Request* req =
new MPI_Request;
1463 MPI_Irecv(data, len, datatype, rnk, 292,
MyComm, req);
1470 for (
int i = 0; i < requests.
Size(); i++)
1472 MPI_Wait(requests[i], MPI_STATUS_IGNORE);
1479 ParNCMesh::SynchronizeDerefinementData<int>(
Array<int> &,
const Table &);
1491 for (
int i = 0; i < deref_table.
Size(); i++)
1493 const int *fine = deref_table.
GetRow(i),
1494 size = deref_table.
RowSize(i);
1499 for (
int j = 0; j < size; j++)
1507 for (
int k = 0; k <
Dim; k++)
1510 splits[k] >= max_nc_level)
1512 leaf_ok[fine[j]] = 0;
break;
1524 for (
int i = 0; i < deref_table.
Size(); i++)
1526 const int* fine = deref_table.
GetRow(i),
1527 size = deref_table.
RowSize(i);
1529 for (
int j = 0; j < size; j++)
1531 if (!leaf_ok[fine[j]])
1533 level_ok[i] = 0;
break;
1551 long local_elems =
NElements, total_elems = 0;
1552 MPI_Allreduce(&local_elems, &total_elems, 1, MPI_LONG, MPI_SUM,
MyComm);
1554 long first_elem_global = 0;
1555 MPI_Scan(&local_elems, &first_elem_global, 1, MPI_LONG, MPI_SUM,
MyComm);
1556 first_elem_global -= local_elems;
1565 new_ranks[i] =
Partition(first_elem_global + (j++), total_elems);
1578 for (
int i = 0; i < old_elements.
Size(); i++)
1591 const ElemArray &elements;
1592 CompareRanks(
const ElemArray &elements) : elements(elements) {}
1594 inline bool operator()(
const int a,
const int b)
1596 return elements[a].rank < elements[b].rank;
1614 int begin = 0, end = 0;
1634 for (
int i = 0; i < rank_neighbors.
Size(); i++)
1636 int elem = rank_neighbors[i];
1644 recv_ghost_ranks[rank].SetNCMesh(
this);
1653 NeighborElementRankMessage::Map::iterator it;
1654 for (it = recv_ghost_ranks.begin(); it != recv_ghost_ranks.end(); ++it)
1657 for (
int i = 0; i < msg.
Size(); i++)
1661 new_ranks[ghost_index] = msg.
values[i];
1665 recv_ghost_ranks.clear();
1676 int received_elements = 0;
1682 received_elements++;
1684 el.
rank = new_ranks[i];
1698 int begin = 0, end = 0;
1702 int rank =
elements[owned_elements[begin]].rank;
1703 while (end < owned_elements.
Size() &&
1704 elements[owned_elements[end]].rank == rank) { end++; }
1709 rank_elems.
MakeRef(&owned_elements[begin], end - begin);
1720 for (
int i = 0; i < batch.
Size(); i++)
1722 int elem = batch[i];
1757 while (received_elements < target_elements)
1765 for (
int i = 0; i < msg.
Size(); i++)
1767 int elem_rank = msg.
values[i];
1770 if (elem_rank ==
MyRank) { received_elements++; }
1789 const Table &old_element_dofs,
1790 long old_global_offset,
1797 RebalanceDofMessage::Map::iterator it;
1807 for (
int i = 0; i < ne; i++)
1828 RebalanceDofMessage::Map::iterator it;
1833 nd += msg.
dofs.size();
1844 for (
unsigned i = 0; i < msg.
elem_ids.size(); i++)
1848 for (
unsigned i = 0; i < msg.
dofs.size(); i++)
1861 : ncmesh(other.ncmesh), include_ref_types(other.include_ref_types)
1869 data.Append(value & 0xff);
1870 data.Append((value >> 8) & 0xff);
1871 data.Append((value >> 16) & 0xff);
1872 data.Append((value >> 24) & 0xff);
1878 return (
int) data[pos] +
1879 ((int) data[pos+1] << 8) +
1880 ((int) data[pos+2] << 16) +
1881 ((int) data[pos+3] << 24);
1886 for (
int i = 0; i < elements.
Size(); i++)
1888 int elem = elements[i];
1891 Element &el = ncmesh->elements[elem];
1892 if (el.
flag == flag) {
break; }
1901 Element &el = ncmesh->elements[elem];
1911 for (
int i = 0; i < 8; i++)
1913 if (el.
child[i] >= 0 && ncmesh->elements[el.
child[i]].flag)
1921 if (include_ref_types)
1926 for (
int i = 0; i < 8; i++)
1928 if (mask & (1 << i))
1930 EncodeTree(el.
child[i]);
1938 FlagElements(elements, 1);
1943 for (
int i = 0; i < ncmesh->root_count; i++)
1945 if (ncmesh->elements[i].flag)
1953 FlagElements(elements, 0);
1959 int mask = data[pos++];
1966 Element &el = ncmesh->elements[elem];
1967 if (include_ref_types)
1969 int ref_type = data[pos++];
1972 ncmesh->RefineElement(elem, ref_type);
1974 else { MFEM_ASSERT(ref_type == el.
ref_type,
"") }
1976 else { MFEM_ASSERT(el.
ref_type != 0,
""); }
1978 for (
int i = 0; i < 8; i++)
1980 if (mask & (1 << i))
1982 DecodeTree(el.
child[i], pos, elements);
1991 while ((root = GetInt(pos)) >= 0)
1994 DecodeTree(root, pos, elements);
2000 write<int>(os, data.Size());
2001 os.write((
const char*) data.GetData(), data.Size());
2006 data.SetSize(read<int>(is));
2007 is.read((
char*) data.GetData(), data.Size());
2023 for (
unsigned i = 0; i <
groups.size(); i++)
2029 for (
int i = 0; i < ids[0].
Size(); i++)
2031 find_v[i].one = ids[0][i].index;
2045 for (
int j = 0; j < 2; j++)
2050 k = find_v[pos].two;
2061 for (
int i = 0; i < ids[1].
Size(); i++)
2063 find_e[i].one = ids[1][i].index;
2075 int v[4], e[4], eo[4], pos, k;
2077 for (
int j = 0; j < 4; j++)
2081 k = find_v[pos].two;
2087 k = find_e[pos].two;
2102 for (
int i = 0; i < gi.
nv; i++)
2104 if (
nodes[el.
node[i]].vert_index ==
id.index)
2111 MFEM_ABORT(
"Vertex not found.");
2117 const int *ev =
GI[(int) old.
geom].
edges[
id.local];
2119 MFEM_ASSERT(node != NULL,
"Edge not found.");
2125 for (
int i = 0; i < gi.
ne; i++)
2127 const int* ev = gi.
edges[i];
2128 if ((el.
node[ev[0]] == node->p1 && el.
node[ev[1]] == node->p2) ||
2129 (el.
node[ev[1]] == node->p1 && el.
node[ev[0]] == node->p2))
2137 MFEM_ABORT(
"Edge not found.");
2143 const MeshId &first = ids[find[pos].two];
2144 while (++pos < find.Size() && ids[find[pos].two].index == first.
index)
2146 MeshId &other = ids[find[pos].two];
2154 std::map<int, int> stream_id;
2160 for (
int type = 0; type < 3; type++)
2162 for (
int i = 0; i < ids[type].
Size(); i++)
2164 elements.
Append(ids[type][i].element);
2176 for (
int i = 0; i < decoded.
Size(); i++)
2178 stream_id[decoded[i]] = i;
2183 for (
int type = 0; type < 3; type++)
2185 write<int>(os, ids[type].
Size());
2186 for (
int i = 0; i < ids[type].
Size(); i++)
2188 const MeshId&
id = ids[type][i];
2189 write<int>(os, stream_id[
id.element]);
2190 write<char>(os,
id.local);
2205 for (
int type = 0; type < 3; type++)
2207 int ne = read<int>(is);
2210 for (
int i = 0; i < ne; i++)
2212 int el_num = read<int>(is);
2213 int elem = elems[el_num];
2216 MFEM_VERIFY(!el.
ref_type,
"not a leaf element: " << el_num);
2218 MeshId &
id = ids[type][i];
2220 id.local = read<char>(is);
2228 id.index =
nodes[el.
node[
id.local]].vert_index;
2233 const int* ev = gi.edges[
id.local];
2235 MFEM_ASSERT(node && node->
HasEdge(),
"edge not found.");
2241 const int* fv = gi.faces[
id.local];
2244 MFEM_ASSERT(face,
"face not found.");
2245 id.index = face->
index;
2255 std::map<GroupId, GroupId> stream_id;
2256 for (
int i = 0; i < ids.
Size(); i++)
2258 if (i && ids[i] == ids[i-1]) {
continue; }
2259 unsigned size = stream_id.size();
2260 GroupId &sid = stream_id[ids[i]];
2261 if (size != stream_id.size()) { sid = size; }
2265 write<short>(os, stream_id.size());
2266 for (std::map<GroupId, GroupId>::iterator
2267 it = stream_id.begin(); it != stream_id.end(); ++it)
2269 write<GroupId>(os, it->second);
2273 write<short>(os, group.size());
2274 for (
unsigned i = 0; i < group.size(); i++)
2276 write<int>(os, group[i]);
2282 write<short>(os, -1);
2287 write<int>(os, ids.
Size());
2288 for (
int i = 0; i < ids.
Size(); i++)
2290 write<GroupId>(os, stream_id[ids[i]]);
2296 int ngroups = read<short>(is);
2302 for (
int i = 0; i < ngroups; i++)
2304 int id = read<GroupId>(is);
2305 int size = read<short>(is);
2309 for (
int i = 0; i < size; i++)
2311 ranks[i] = read<int>(is);
2323 for (
int i = 0; i < ids.
Size(); i++)
2325 ids[i] = groups[read<GroupId>(is)];
2332 template<
class ValueType,
bool RefTypes,
int Tag>
2335 std::ostringstream ostream;
2341 eset.
Encode(tmp_elements);
2349 std::map<int, int> element_index;
2350 for (
int i = 0; i < decoded.
Size(); i++)
2352 element_index[decoded[i]] = i;
2355 write<int>(ostream, values.size());
2356 MFEM_ASSERT(
elements.size() == values.size(),
"");
2358 for (
unsigned i = 0; i < values.size(); i++)
2360 write<int>(ostream, element_index[
elements[i]]);
2361 write<ValueType>(ostream, values[i]);
2364 ostream.str().swap(data);
2367 template<
class ValueType,
bool RefTypes,
int Tag>
2370 std::istringstream istream(data);
2376 eset.
Decode(tmp_elements);
2378 int* el = tmp_elements.
GetData();
2382 int count = read<int>(istream);
2383 for (
int i = 0; i < count; i++)
2385 int index = read<int>(istream);
2386 MFEM_ASSERT(index >= 0 && (
size_t) index < values.size(),
"");
2387 values[index] = read<ValueType>(istream);
2397 eset.SetNCMesh(ncmesh);
2402 eset.Decode(decoded);
2404 elem_ids.resize(decoded.
Size());
2405 for (
int i = 0; i < decoded.
Size(); i++)
2407 elem_ids[i] = eset.GetNCMesh()->elements[decoded[i]].index;
2411 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
2413 write<int>(os, dofs.size());
2415 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
2418 static void read_dofs(std::istream &is, std::vector<int> &dofs)
2420 dofs.resize(read<int>(is));
2421 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
2426 std::ostringstream stream;
2429 write<long>(stream, dof_offset);
2430 write_dofs(stream, dofs);
2432 stream.str().swap(data);
2437 std::istringstream stream(data);
2440 dof_offset = read<long>(stream);
2441 read_dofs(stream, dofs);
2448 elem_ids.resize(elems.
Size());
2449 for (
int i = 0; i < elems.
Size(); i++)
2451 elem_ids[i] = eset.GetNCMesh()->elements[elems[i]].index;
2464 for (
int i = 0; i < cle.
Size(); i++)
2472 debug_mesh.
ncmesh = copy;
2493 return (elem_ids.capacity() + dofs.capacity()) *
sizeof(
int);
2496 template<
typename K,
typename V>
2497 static long map_memory_usage(
const std::map<K, V> &map)
2500 for (
typename std::map<K, V>::const_iterator
2501 it = map.begin(); it != map.end(); ++it)
2503 result += it->second.MemoryUsage();
2504 result +=
sizeof(std::pair<K, V>) + 3*
sizeof(
void*) +
sizeof(bool);
2512 for (
unsigned i = 0; i <
groups.size(); i++)
2514 groups_size +=
groups[i].capacity() *
sizeof(int);
2516 const int approx_node_size =
2517 sizeof(std::pair<CommGroup, GroupId>) + 3*
sizeof(
void*) +
sizeof(bool);
2518 return groups_size +
group_id.size() * approx_node_size;
2567 <<
index_rank.MemoryUsage() <<
" index_rank\n"
2580 #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[])
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'.
CoarseFineTransformations transforms
storage for data returned by Get[De]RefinementTransforms()
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.
char flag
generic flag/marker, can be used by algorithms
Array< char > face_orient
Array< GroupId > edge_group
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)
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.
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.
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.
void GetEdgeVertices(const MeshId &edge_id, int vert_index[2]) const
Return Mesh vertex indices of an edge identified by 'edge_id'.
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 AddMasterSlaveConnections(int nitems, const NCList &list)
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
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.
Array< NCFaceInfo > nc_faces_info
virtual void OnMeshUpdated(Mesh *mesh)
ParNCMesh(MPI_Comm comm, const NCMesh &ncmesh)
RebalanceDofMessage::Map send_rebalance_dofs
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
void GetSubArray(int offset, int sa_size, Array< T > &sa)
int size
Size of the array.
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
void InitGroups(int num, Array< GroupId > &entity_group)
int index
face number in the Mesh
void MakeFromList(int nrows, const Array< Connection > &list)
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 FindNeighbors(int elem, Array< int > &neighbors, const Array< int > *search_set=NULL)
std::vector< Master > masters
void ElementNeighborProcessors(int elem, Array< int > &ranks)
Array< int > old_index_or_rank
RebalanceDofMessage::Map recv_rebalance_dofs
int InitialPartition(int index) const
Helper to get the partitioning when the serial mesh gets split initially.
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
virtual void BuildEdgeList()
void AugmentMasterGroups()
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.
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)
static GeomInfo GI[Geometry::NumGeom]
virtual void ElementSharesEdge(int elem, int enode)
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)
bool Iso
true if the mesh only contains isotropic refinements
Array< int > tmp_neighbors
std::map< int, NeighborDerefinementMessage > Map
virtual void BuildEdgeList()
void Encode(const Array< int > &elements)
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...
void GetDebugMesh(Mesh &debug_mesh) const
Array< GroupId > vertex_group
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 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.
Array< GroupId > edge_owner
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)
GroupId GetGroupId(int entity, int index) const
Return the communication group ID for a vertex/edge/face.
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)
Array< int > boundary_layer
list of type 3 elements
void Isend(int rank, MPI_Comm comm)
Non-blocking send to processor 'rank'.
virtual void ElementSharesVertex(int elem, int vnode)
void AddElementRank(int elem, int rank)
Array< Connection > index_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
void GetGroupShared(Array< bool > &group_shared)
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)
NCMesh * ncmesh
Optional non-conforming mesh extension.
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 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[])
long MemoryUsage() const
Return total number of bytes allocated.
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.
friend struct CompareRanks
void NeighborProcessors(Array< int > &neighbors)
Array< GroupId > face_owner
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)
void MakeShared(const Array< GroupId > &entity_group, const NCList &list, NCList &shared)
bool CheckElementType(int elem, int type)
virtual void UpdateVertices()
update Vertex::index and vertex_nodeId
Class for parallel meshes.
Abstract data type element.
virtual void ElementSharesFace(int elem, int face)
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)
GroupId JoinGroups(GroupId g1, GroupId g2)
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)
Array< GroupId > vertex_owner
Array< GroupId > face_group
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const