12 #include "../config/config.hpp"
18 #include "../fem/fe_coll.hpp"
19 #include "../fem/fespace.hpp"
111 if (node->HasVertex()) { node->vert_index = -1; }
120 for (
int j = 0; j <
GI[(int) el.
geom].
nv; j++)
122 int &vindex =
nodes[el.
node[j]].vert_index;
123 if (vindex < 0) { vindex =
NVertices++; }
131 if (node->HasVertex() && node->vert_index >= 0)
140 if (node->HasVertex() && node->vert_index < 0)
156 if (node->HasEdge()) { node->edge_index = -1; }
171 if (node->HasEdge() && node->edge_index < 0)
199 int e_index =
nodes[enode].edge_index;
202 owner = std::min(owner, el_rank);
212 int f_index =
faces[face].index;
215 owner = std::min(owner, el_rank);
270 struct MasterSlaveInfo
273 int slaves_begin, slaves_end;
274 MasterSlaveInfo() : master(-1), slaves_begin(0), slaves_end(0) {}
280 std::vector<MasterSlaveInfo> info(nitems);
282 for (
unsigned i = 0; i < list.
masters.size(); i++)
288 for (
unsigned i = 0; i < list.
slaves.size(); i++)
302 for (
int i = 0; i < size; i++)
307 const MasterSlaveInfo &msi = info[index];
315 for (
int j = msi.slaves_begin; j < msi.slaves_end; j++)
324 static bool is_shared(
const Table& groups,
int index,
int MyRank)
329 int size = groups.
RowSize(index);
335 const int* group = groups.
GetRow(index);
336 for (
int i = 0; i < size; i++)
338 if (group[i] == MyRank) {
return true; }
349 for (
unsigned i = 0; i < list.
conforming.size(); i++)
351 if (is_shared(groups, list.
conforming[i].index, MyRank))
356 for (
unsigned i = 0; i < list.
masters.size(); i++)
358 if (is_shared(groups, list.
masters[i].index, MyRank))
363 for (
unsigned i = 0; i < list.
slaves.size(); i++)
365 if (is_shared(groups, list.
slaves[i].index, MyRank))
390 for (
int j = 0; j <
GI[(int) el.
geom].
nv; j++)
396 owner = std::min(owner, el.
rank);
400 MeshId &
id = vertex_id[index];
401 id.index = (nd.
HasEdge() ? -1 : index);
415 for (
int i = 0; i < nvertices; i++)
417 if (is_shared(
vertex_group, i, MyRank) && vertex_id[i].index >= 0)
430 for (
int i = 0; i < 2; i++)
438 if (local) { local[i] = lf; }
442 for (
int j = 0; j < 4; j++)
444 ids[i][j] = e[i]->
node[fv[j]];
452 if (
Dim < 3) {
return; }
463 if (face->elem[0] >= 0 && face->elem[1] >= 0 && face->index <
NFaces)
468 if (e1->
rank == e2->
rank) {
continue; }
469 if (e1->
rank > e2->
rank) { std::swap(e1, e2); }
484 for (i = j = 0; i < bdr_vertices.
Size(); i++)
486 if (bdr_vertices[i] <
NVertices) { bdr_vertices[j++] = bdr_vertices[i]; }
491 for (i = j = 0; i < bdr_edges.
Size(); i++)
493 if (bdr_edges[i] <
NEdges) { bdr_edges[j++] = bdr_edges[i]; }
508 for (
int i = 0; i < nleaves; i++)
523 for (
int i = 0; i < nleaves; i++)
531 else if (boundary_set[i] && etype)
548 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
578 static void set_to_array(
const std::set<T> &set,
Array<T> &array)
582 for (std::set<int>::iterator it = set.begin(); it != set.end(); ++it)
597 set_to_array(ranks, neighbors);
622 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
626 MFEM_ASSERT(face != NULL,
"");
628 MFEM_ASSERT(face->
elem[0] >= 0 && face->
elem[1] >= 0,
"");
631 if (e[0]->rank == MyRank) { std::swap(e[0], e[1]); }
632 MFEM_ASSERT(e[0]->rank != MyRank && e[1]->rank == MyRank,
"");
638 for (
unsigned i = 0; i < shared.
masters.size(); i++)
650 if (loc0 == loc1) {
continue; }
651 if (loc0) { std::swap(e[0], e[1]); }
658 MFEM_ASSERT(fnbr.
Size() <= bound,
"oops, bad upper bound");
668 for (
int i = 0; i < fnbr.
Size(); i++)
687 std::map<int, int> vert_map;
688 for (
int i = 0; i < fnbr.
Size(); i++)
696 for (
int k = 0; k < gi.
nv; k++)
698 int &v = vert_map[elem->
node[k]];
699 if (!v) { v = vert_map.size(); }
703 if (!i || elem->
rank != fnbr[i-1]->rank)
718 std::map<int, int>::iterator it;
719 for (it = vert_map.begin(); it != vert_map.end(); ++it)
731 for (
int i = 0, last_rank = -1; i < send_elems.
Size(); i++)
734 if (c.
from != last_rank)
742 c.
from = send_elems[i-1].from;
748 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
754 if (e[0]->rank == MyRank) { std::swap(e[0], e[1]); }
777 MFEM_ASSERT(pmesh.
faces_info.Size() == nfaces,
"");
780 for (
int i = nfaces; i < pmesh.
faces_info.Size(); i++)
791 for (
unsigned i = 0; i < shared.
masters.size(); i++)
804 if (sloc == mloc) {
continue; }
833 if (!sloc &&
Dim == 3)
837 std::swap((*pm2)(0,1), (*pm2)(0,3));
838 std::swap((*pm2)(1,1), (*pm2)(1,3));
855 MFEM_ASSERT(fi.
NCFace < 0,
"");
884 bool removeAll =
true;
887 for (
int i = 0; i < 8; i++)
890 if (el.
child[i] >= 0)
893 if (!
remove[i]) { removeAll =
false; }
898 if (removeAll) {
return true; }
901 for (
int i = 0; i < 8; i++)
919 MFEM_WARNING(
"Can't prune 3D aniso meshes yet.");
948 for (
int i = 0; i < refinements.
Size(); i++)
952 "anisotropic parallel refinement not supported yet in 3D.");
954 MFEM_VERIFY(
Iso ||
Dim < 3,
955 "parallel refinement of 3D aniso meshes not supported yet.");
962 for (
int i = 0; i < neighbors.
Size(); i++)
964 send_ref[neighbors[i]].SetNCMesh(
this);
972 for (
int i = 0; i < refinements.
Size(); i++)
978 for (
int j = 0; j < ranks.
Size(); j++)
980 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
988 for (
int i = 0; i < refinements.
Size(); i++)
995 for (
int j = 0; j < neighbors.
Size(); j++)
1005 for (
int i = 0; i < msg.
Size(); i++)
1020 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
1027 long size = refinements.
Size(), glob_size;
1028 MPI_Allreduce(&size, &glob_size, 1, MPI_LONG, MPI_SUM,
MyComm);
1030 if (!glob_size) {
break; }
1038 MFEM_VERIFY(
Dim < 3 ||
Iso,
1039 "derefinement of 3D anisotropic meshes not implemented yet.");
1063 for (
int i = 0; i < derefs.
Size(); i++)
1065 int row = derefs[i];
1067 "invalid derefinement number.");
1072 int coarse_rank = INT_MAX;
1073 for (
int j = 0; j < size; j++)
1076 coarse_rank = std::min(coarse_rank, fine_rank);
1078 for (
int j = 0; j < size; j++)
1080 new_ranks[fine[j]] = coarse_rank;
1084 int target_elements = 0;
1085 for (
int i = 0; i < new_ranks.Size(); i++)
1087 if (new_ranks[i] == MyRank) { target_elements++; }
1101 for (
int i = 0; i < neighbors.
Size(); i++)
1103 send_deref[neighbors[i]].SetNCMesh(
this);
1110 for (
int i = 0; i < derefs.
Size(); i++)
1113 int parent =
elements[old_elements[fine[0]]].parent;
1117 for (
int j = 0; j < ranks.
Size(); j++)
1119 send_deref[ranks[j]].AddDerefinement(parent, new_ranks[fine[0]]);
1129 for (
int i = 0; i < old_elements.
Size(); i++)
1131 elements[old_elements[i]].index = i;
1136 old_elements.
Copy(coarse);
1137 for (
int i = 0; i < derefs.
Size(); i++)
1140 int parent =
elements[old_elements[fine[0]]].parent;
1149 for (
int j = 0; j < neighbors.
Size(); j++)
1159 for (
int i = 0; i < msg.
Size(); i++)
1177 for (
int i = 0; i < coarse.
Size(); i++)
1179 int index =
elements[coarse[i]].index;
1183 index = -1 -
elements[coarse[i]].rank;
1193 for (
int i = 0; i < coarse.
Size(); i++)
1198 index =
elements[old_elements[index]].index;
1207 template<
typename Type>
1209 const Table &deref_table)
1222 for (
int i = 0; i < deref_table.
Size(); i++)
1224 const int* fine = deref_table.
GetRow(i);
1225 int size = deref_table.
RowSize(i);
1226 MFEM_ASSERT(size <= 8,
"");
1228 int ranks[8], min_rank = INT_MAX, max_rank = INT_MIN;
1229 for (
int j = 0; j < size; j++)
1232 min_rank = std::min(min_rank, ranks[j]);
1233 max_rank = std::max(max_rank, ranks[j]);
1237 if (min_rank != max_rank)
1240 for (
int j = 0; j < size; j++)
1242 if (ranks[j] != MyRank) { neigh.
Append(ranks[j]); }
1247 for (
int j = 0; j < size; j++)
1249 Type *data = &elem_data[fine[j]];
1251 int rnk = ranks[j], len = 1;
1257 for (
int k = 0; k < neigh.
Size(); k++)
1259 MPI_Request* req =
new MPI_Request;
1260 MPI_Isend(data, len, datatype, neigh[k], 292,
MyComm, req);
1266 MPI_Request* req =
new MPI_Request;
1267 MPI_Irecv(data, len, datatype, rnk, 292,
MyComm, req);
1274 for (
int i = 0; i < requests.
Size(); i++)
1276 MPI_Wait(requests[i], MPI_STATUS_IGNORE);
1283 ParNCMesh::SynchronizeDerefinementData<int>(
Array<int> &,
const Table &);
1295 for (
int i = 0; i < deref_table.
Size(); i++)
1297 const int *fine = deref_table.
GetRow(i),
1298 size = deref_table.
RowSize(i);
1303 for (
int j = 0; j < size; j++)
1306 if (
elements[child].rank == MyRank)
1311 for (
int k = 0; k <
Dim; k++)
1314 splits[k] >= max_nc_level)
1316 leaf_ok[fine[j]] = 0;
break;
1328 for (
int i = 0; i < deref_table.
Size(); i++)
1330 const int* fine = deref_table.
GetRow(i),
1331 size = deref_table.
RowSize(i);
1333 for (
int j = 0; j < size; j++)
1335 if (!leaf_ok[fine[j]])
1337 level_ok[i] = 0;
break;
1355 long local_elems =
NElements, total_elems = 0;
1356 MPI_Allreduce(&local_elems, &total_elems, 1, MPI_LONG, MPI_SUM,
MyComm);
1358 long first_elem_global = 0;
1359 MPI_Scan(&local_elems, &first_elem_global, 1, MPI_LONG, MPI_SUM,
MyComm);
1360 first_elem_global -= local_elems;
1369 new_ranks[i] =
Partition(first_elem_global + (j++), total_elems);
1382 for (
int i = 0; i < old_elements.
Size(); i++)
1395 const ElemArray &elements;
1396 CompareRanks(
const ElemArray &elements) : elements(elements) {}
1398 inline bool operator()(
const int a,
const int b)
1400 return elements[a].rank < elements[b].rank;
1418 int begin = 0, end = 0;
1438 for (
int i = 0; i < rank_neighbors.
Size(); i++)
1440 int elem = rank_neighbors[i];
1448 recv_ghost_ranks[rank].SetNCMesh(
this);
1457 NeighborElementRankMessage::Map::iterator it;
1458 for (it = recv_ghost_ranks.begin(); it != recv_ghost_ranks.end(); ++it)
1461 for (
int i = 0; i < msg.
Size(); i++)
1465 new_ranks[ghost_index] = msg.
values[i];
1469 recv_ghost_ranks.clear();
1480 int received_elements = 0;
1484 if (el.
rank == MyRank && new_ranks[i] == MyRank)
1486 received_elements++;
1488 el.
rank = new_ranks[i];
1502 int begin = 0, end = 0;
1506 int rank =
elements[owned_elements[begin]].rank;
1507 while (end < owned_elements.
Size() &&
1508 elements[owned_elements[end]].rank == rank) { end++; }
1513 rank_elems.
MakeRef(&owned_elements[begin], end - begin);
1524 for (
int i = 0; i < batch.
Size(); i++)
1526 int elem = batch[i];
1561 while (received_elements < target_elements)
1569 for (
int i = 0; i < msg.
Size(); i++)
1571 int elem_rank = msg.
values[i];
1574 if (elem_rank == MyRank) { received_elements++; }
1593 const Table &old_element_dofs,
1594 long old_global_offset,
1601 RebalanceDofMessage::Map::iterator it;
1611 for (
int i = 0; i < ne; i++)
1632 RebalanceDofMessage::Map::iterator it;
1637 nd += msg.
dofs.size();
1648 for (
unsigned i = 0; i < msg.
elem_ids.size(); i++)
1652 for (
unsigned i = 0; i < msg.
dofs.size(); i++)
1665 : ncmesh(other.ncmesh), include_ref_types(other.include_ref_types)
1673 data.Append(value & 0xff);
1674 data.Append((value >> 8) & 0xff);
1675 data.Append((value >> 16) & 0xff);
1676 data.Append((value >> 24) & 0xff);
1682 return (
int) data[pos] +
1683 ((int) data[pos+1] << 8) +
1684 ((int) data[pos+2] << 16) +
1685 ((int) data[pos+3] << 24);
1690 for (
int i = 0; i < elements.
Size(); i++)
1692 int elem = elements[i];
1695 Element &el = ncmesh->elements[elem];
1696 if (el.
flag == flag) {
break; }
1705 Element &el = ncmesh->elements[elem];
1715 for (
int i = 0; i < 8; i++)
1717 if (el.
child[i] >= 0 && ncmesh->elements[el.
child[i]].flag)
1725 if (include_ref_types)
1730 for (
int i = 0; i < 8; i++)
1732 if (mask & (1 << i))
1734 EncodeTree(el.
child[i]);
1742 FlagElements(elements, 1);
1747 for (
int i = 0; i < ncmesh->root_count; i++)
1749 if (ncmesh->elements[i].flag)
1757 FlagElements(elements, 0);
1763 int mask = data[pos++];
1770 Element &el = ncmesh->elements[elem];
1771 if (include_ref_types)
1773 int ref_type = data[pos++];
1776 ncmesh->RefineElement(elem, ref_type);
1778 else { MFEM_ASSERT(ref_type == el.
ref_type,
"") }
1780 else { MFEM_ASSERT(el.
ref_type != 0,
""); }
1782 for (
int i = 0; i < 8; i++)
1784 if (mask & (1 << i))
1786 DecodeTree(el.
child[i], pos, elements);
1795 while ((root = GetInt(pos)) >= 0)
1798 DecodeTree(root, pos, elements);
1802 template<
typename T>
1803 static inline void write(std::ostream& os, T value)
1805 os.write((
char*) &value,
sizeof(T));
1808 template<
typename T>
1809 static inline T read(std::istream& is)
1812 is.read((
char*) &value,
sizeof(T));
1818 write<int>(os, data.Size());
1819 os.write((
const char*) data.GetData(), data.Size());
1824 data.SetSize(read<int>(is));
1825 is.read((
char*) data.GetData(), data.Size());
1833 std::map<int, int> element_id;
1839 for (
int type = 0; type < 3; type++)
1841 for (
int i = 0; i < ids[type].
Size(); i++)
1843 elements.
Append(ids[type][i].element);
1855 for (
int i = 0; i < decoded.
Size(); i++)
1857 element_id[decoded[i]] = i;
1862 for (
int type = 0; type < 3; type++)
1864 write<int>(os, ids[type].
Size());
1865 for (
int i = 0; i < ids[type].
Size(); i++)
1867 const MeshId&
id = ids[type][i];
1868 write<int>(os, element_id[
id.element]);
1869 write<char>(os,
id.local);
1884 for (
int type = 0; type < 3; type++)
1886 int ne = read<int>(is);
1889 for (
int i = 0; i < ne; i++)
1891 int el_num = read<int>(is);
1892 int elem = elems[el_num];
1895 MFEM_VERIFY(!el.
ref_type,
"not a leaf element: " << el_num);
1897 MeshId &
id = ids[type][i];
1899 id.local = read<char>(is);
1907 id.index =
nodes[el.
node[
id.local]].vert_index;
1912 const int* ev = gi.edges[
id.local];
1914 MFEM_ASSERT(node && node->
HasEdge(),
"edge not found.");
1920 const int* fv = gi.faces[
id.local];
1923 MFEM_ASSERT(face,
"face not found.");
1924 id.index = face->
index;
1937 MFEM_ASSERT(type >= 0 && type < 3,
"");
1944 MFEM_ASSERT(type >= 0 && type < 3,
"");
1946 if (id_dofs[type].find(
id) == id_dofs[type].end())
1948 MFEM_ABORT(
"type/ID " << type <<
"/" <<
id.index <<
" not found in "
1949 "neighbor message. Ghost layers out of sync?");
1952 std::vector<int> &vec = id_dofs[type][id];
1955 ndofs = this->ndofs;
1959 std::vector<int> &dofs)
1967 int v0 = pncmesh->nodes[el.
node[ev[0]]].vert_index;
1968 int v1 = pncmesh->nodes[el.
node[ev[1]]].vert_index;
1970 if ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1]))
1972 std::vector<int> tmp(dofs);
1976 MFEM_ASSERT((
int) dofs.size() == 2*nv + ne,
"");
1979 for (
int i = 0; i < 2; i++)
1981 for (
int k = 0; k < nv; k++)
1983 dofs[nv*i + k] = tmp[nv*(1-i) + k];
1989 for (
int i = 0; i < ne; i++)
1991 dofs[2*nv + i] = (ind[i] >= 0) ? tmp[2*nv + ind[i]]
1992 : -1 - tmp[2*nv + (-1 - ind[i])];
1997 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
1999 write<int>(os, dofs.size());
2001 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
2004 static void read_dofs(std::istream &is, std::vector<int> &dofs)
2006 dofs.resize(read<int>(is));
2007 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
2012 IdToDofs::iterator it;
2016 for (
int type = 0; type < 3; type++)
2018 ids[type].
Reserve(id_dofs[type].size());
2019 for (it = id_dofs[type].begin(); it != id_dofs[type].end(); ++it)
2021 ids[type].
Append(it->first);
2026 std::ostringstream stream;
2027 pncmesh->EncodeMeshIds(stream, ids);
2030 for (
int type = 0; type < 3; type++)
2032 for (it = id_dofs[type].begin(); it != id_dofs[type].end(); ++it)
2034 if (type == 1) { ReorderEdgeDofs(it->first, it->second); }
2035 write_dofs(stream, it->second);
2039 id_dofs[type].clear();
2042 write<int>(stream, ndofs);
2044 stream.str().swap(data);
2049 std::istringstream stream(data);
2053 pncmesh->DecodeMeshIds(stream, ids);
2056 for (
int type = 0; type < 3; type++)
2058 id_dofs[type].clear();
2059 for (
int i = 0; i < ids[type].
Size(); i++)
2062 read_dofs(stream, id_dofs[type][
id]);
2063 if (type == 1) { ReorderEdgeDofs(
id, id_dofs[type][
id]); }
2067 ndofs = read<int>(stream);
2075 std::ostringstream stream;
2078 write<int>(stream, rows.size());
2079 for (std::set<int>::iterator it = rows.begin(); it != rows.end(); ++it)
2081 write<int>(stream, *it);
2085 stream.str().swap(data);
2090 std::istringstream stream(data);
2094 int size = read<int>(stream);
2095 for (
int i = 0; i < size; i++)
2097 rows.insert(rows.end(), read<int>(stream));
2106 MFEM_ASSERT(rows.find(row) == rows.end(),
"");
2107 Row& row_data = rows[row];
2109 row_data.srow = srow;
2114 MFEM_ASSERT(rows.find(row) != rows.end(),
2115 "row " << row <<
" not found in neighbor message.");
2116 Row& row_data = rows[row];
2117 cols.
SetSize(row_data.cols.size());
2118 cols.
Assign(row_data.cols.data());
2119 srow = row_data.srow;
2124 std::ostringstream stream;
2127 write<int>(stream, rows.size());
2128 for (std::map<int, Row>::iterator it = rows.begin(); it != rows.end(); ++it)
2130 write<int>(stream, it->first);
2131 Row& row_data = it->second;
2132 MFEM_ASSERT((
int) row_data.cols.size() == row_data.srow.Size(),
"");
2133 write_dofs(stream, row_data.cols);
2134 stream.write((
const char*) row_data.srow.GetData(),
2135 sizeof(double) * row_data.srow.Size());
2139 stream.str().swap(data);
2144 std::istringstream stream(data);
2150 int size = read<int>(stream);
2151 for (
int i = 0; i < size; i++)
2153 Row& row_data = rows[read<int>(stream)];
2154 read_dofs(stream, row_data.
cols);
2157 sizeof(double) * row_data.
srow.
Size());
2163 template<
class ValueType,
bool RefTypes,
int Tag>
2166 std::ostringstream ostream;
2172 eset.
Encode(tmp_elements);
2180 std::map<int, int> element_index;
2181 for (
int i = 0; i < decoded.
Size(); i++)
2183 element_index[decoded[i]] = i;
2186 write<int>(ostream, values.size());
2187 MFEM_ASSERT(
elements.size() == values.size(),
"");
2189 for (
unsigned i = 0; i < values.size(); i++)
2191 write<int>(ostream, element_index[
elements[i]]);
2192 write<ValueType>(ostream, values[i]);
2195 ostream.str().swap(data);
2198 template<
class ValueType,
bool RefTypes,
int Tag>
2201 std::istringstream istream(data);
2207 eset.
Decode(tmp_elements);
2209 int* el = tmp_elements.
GetData();
2213 int count = read<int>(istream);
2214 for (
int i = 0; i < count; i++)
2216 int index = read<int>(istream);
2217 MFEM_ASSERT(index >= 0 && (
size_t) index < values.size(),
"");
2218 values[index] = read<ValueType>(istream);
2228 eset.SetNCMesh(ncmesh);
2233 eset.Decode(decoded);
2235 elem_ids.resize(decoded.
Size());
2236 for (
int i = 0; i < decoded.
Size(); i++)
2238 elem_ids[i] = eset.GetNCMesh()->elements[decoded[i]].index;
2244 std::ostringstream stream;
2247 write<long>(stream, dof_offset);
2248 write_dofs(stream, dofs);
2250 stream.str().swap(data);
2255 std::istringstream stream(data);
2258 dof_offset = read<long>(stream);
2259 read_dofs(stream, dofs);
2266 elem_ids.resize(elems.
Size());
2267 for (
int i = 0; i < elems.
Size(); i++)
2269 elem_ids[i] = eset.GetNCMesh()->elements[elems[i]].index;
2282 for (
int i = 0; i < cle.
Size(); i++)
2290 debug_mesh.
ncmesh = copy;
2296 #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[])
Read from 'is' a processor-independent encoding of vertex/edge/face 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
char ref_type
refinement XYZ bit mask (7 = full isotropic)
void CalcFaceOrientations()
void SetDerefMatrixCodes(int parent, Array< int > &fine_coarse)
Helper struct to convert a C++ type to an MPI type.
void AddDofs(int type, const NCMesh::MeshId &id, const Array< int > &dofs)
Add vertex/edge/face DOFs to an outgoing message.
char flag
generic flag/marker, can be used by algorithms
Array< char > face_orient
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
std::vector< int > elem_ids
virtual void BuildFaceList()
void Dump(std::ostream &os) const
void SetSize(int s)
Resize the vector to size s.
int index
element number in the Mesh, -1 if refined
Array< Element * > face_nbr_elements
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 BuildSharedVertices()
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()
int Size() const
Returns the size of the vector.
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 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)
void CountSplits(int elem, int splits[3]) const
std::vector< MeshId > conforming
Array< int > face_nbr_group
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
void GetLimitRefinements(Array< Refinement > &refinements, int max_level)
void EncodeTree(int elem)
int spaceDim
dimensions of the elements and the vertex coordinates
virtual void AssignLeafIndices()
const NCList & GetSharedEdges()
void MakeShared(const Table &groups, const NCList &list, NCList &shared)
Array< int > vertex_nodeId
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)
Array< int > vertex_owner
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)
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< 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()
Identifies a vertex/edge/face in both Mesh and NCMesh.
int parent
parent element, -1 if this is a root element, -2 if free
void Assign(const T *)
Copy data from a pointer. Size() elements are copied.
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 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)
int slaves_end
slave faces
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
std::vector< Slave > slaves
virtual void BuildFaceList()
void DerefineElement(int elem)
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 GetDofs(int type, const NCMesh::MeshId &id, Array< int > &dofs, int &ndofs)
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
void GetRow(int row, Array< int > &cols, Vector &srow)
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'.
void AddElementRank(int elem, int rank)
Array< Connection > index_rank
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()
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[])
Write to 'os' a processor-independent encoding of vertex/edge/face IDs.
void AddRow(int row, const Array< int > &cols, const Vector &srow)
void AddMasterSlaveRanks(int nitems, const NCList &list)
const NCList & GetSharedFaces()
std::map< int, RebalanceMessage > Map
static int get_face_orientation(Face &face, Element &e1, Element &e2, int local[2]=NULL)
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
void ReorderEdgeDofs(const NCMesh::MeshId &id, std::vector< int > &dofs)
friend struct CompareRanks
void NeighborProcessors(Array< int > &neighbors)
Table send_face_nbr_elements
char ref_type
bit mask of X,Y,Z refinements (bits 0,1,2 respectively)
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.
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)
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)
void GetFaceNeighbors(ParMesh &pmesh)
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const