12 #include "../config/config.hpp"
18 #include "../fem/fe_coll.hpp"
19 #include "../fem/fespace.hpp"
111 if (it->vertex) { it->vertex->index = -1; }
120 for (
int j = 0; j <
GI[(int) elem->
geom].
nv; j++)
123 if (vindex < 0) { vindex =
NVertices++; }
131 if (it->vertex && it->vertex->index >= 0)
140 if (it->vertex && it->vertex->index < 0)
156 if (it->edge) { it->edge->index = -1; }
171 if (it->edge && it->edge->index < 0)
199 owner = std::min(owner, elem->
rank);
209 owner = std::min(owner, elem->
rank);
264 struct MasterSlaveInfo
267 int slaves_begin, slaves_end;
268 MasterSlaveInfo() : master(-1), slaves_begin(0), slaves_end(0) {}
274 std::vector<MasterSlaveInfo> info(nitems);
276 for (
unsigned i = 0; i < list.
masters.size(); i++)
282 for (
unsigned i = 0; i < list.
slaves.size(); i++)
296 for (
int i = 0; i < size; i++)
301 const MasterSlaveInfo &msi = info[index];
309 for (
int j = msi.slaves_begin; j < msi.slaves_end; j++)
318 static bool is_shared(
const Table& groups,
int index,
int MyRank)
323 int size = groups.
RowSize(index);
329 const int* group = groups.
GetRow(index);
330 for (
int i = 0; i < size; i++)
332 if (group[i] == MyRank) {
return true; }
343 for (
unsigned i = 0; i < list.
conforming.size(); i++)
345 if (is_shared(groups, list.
conforming[i].index, MyRank))
350 for (
unsigned i = 0; i < list.
masters.size(); i++)
352 if (is_shared(groups, list.
masters[i].index, MyRank))
357 for (
unsigned i = 0; i < list.
slaves.size(); i++)
359 if (is_shared(groups, list.
slaves[i].index, MyRank))
382 for (
int j = 0; j <
GI[(int) elem->
geom].
nv; j++)
388 owner = std::min(owner, elem->
rank);
392 MeshId &
id = vertex_id[index];
393 id.index = (node->
edge ? -1 : index);
407 for (
int i = 0; i < nvertices; i++)
409 if (is_shared(
vertex_group, i, MyRank) && vertex_id[i].index >= 0)
422 for (
int i = 0; i < 2; i++)
427 if (local) { local[i] = lf; }
431 for (
int j = 0; j < 4; j++)
433 ids[i][j] = e[i]->
node[fv[j]]->
id;
441 if (
Dim < 3) {
return; }
452 if (it->ref_count == 2 && it->index <
NFaces)
454 Element* e[2] = { it->elem[0], it->elem[1] };
455 if (e[0]->rank == e[1]->rank) {
continue; }
456 if (e[0]->rank > e[1]->rank) { std::swap(e[0], e[1]); }
471 for (i = j = 0; i < bdr_vertices.
Size(); i++)
473 if (bdr_vertices[i] <
NVertices) { bdr_vertices[j++] = bdr_vertices[i]; }
478 for (i = j = 0; i < bdr_edges.
Size(); i++)
480 if (bdr_edges[i] <
NEdges) { bdr_edges[j++] = bdr_edges[i]; }
495 for (
int i = 0; i < nleaves; i++)
510 for (
int i = 0; i < nleaves; i++)
518 else if (boundary_set[i] && etype)
534 for (
int i = 0; i < 8; i++)
536 if (elem->
child[i] &&
566 static void set_to_array(
const std::set<T> &set,
Array<T> &array)
570 for (std::set<int>::iterator it = set.begin(); it != set.end(); ++it)
585 set_to_array(ranks, neighbors);
610 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
614 MFEM_ASSERT(face != NULL,
"");
617 MFEM_ASSERT(e[0] != NULL && e[1] != NULL,
"");
619 if (e[0]->rank == MyRank) { std::swap(e[0], e[1]); }
620 MFEM_ASSERT(e[0]->rank != MyRank && e[1]->rank == MyRank,
"");
626 for (
unsigned i = 0; i < shared.
masters.size(); i++)
634 MFEM_ASSERT(e[0] != NULL && e[1] != NULL,
"");
638 if (loc0 == loc1) {
continue; }
639 if (loc0) { std::swap(e[0], e[1]); }
646 MFEM_ASSERT(fnbr.
Size() <= bound,
"oops, bad upper bound");
656 for (
int i = 0; i < fnbr.
Size(); i++)
675 std::map<Vertex*, int> vert_map;
676 for (
int i = 0; i < fnbr.
Size(); i++)
684 for (
int k = 0; k < gi.
nv; k++)
687 if (!v) { v = vert_map.size(); }
691 if (!i || elem->
rank != fnbr[i-1]->rank)
703 std::map<Vertex*, int>::iterator it;
704 for (it = vert_map.begin(); it != vert_map.end(); ++it)
713 for (
int i = 0, last_rank = -1; i < send_elems.
Size(); i++)
716 if (c.
from != last_rank)
724 c.
from = send_elems[i-1].from;
730 for (
unsigned i = 0; i < shared.
conforming.size(); i++)
736 if (e[0]->rank == MyRank) { std::swap(e[0], e[1]); }
760 for (
int i = nfaces; i < pmesh.
faces_info.Size(); i++)
769 for (
unsigned i = 0; i < shared.
masters.size(); i++)
779 if (sloc == mloc) {
continue; }
796 if (!sloc &&
Dim == 3)
800 std::swap((*pm2)(0,1), (*pm2)(0,3));
801 std::swap((*pm2)(1,1), (*pm2)(1,3));
818 MFEM_ASSERT(fi.
NCFace < 0,
"");
846 bool removeAll =
true;
849 for (
int i = 0; i < 8; i++)
855 if (!
remove[i]) { removeAll =
false; }
860 if (removeAll) {
return true; }
863 for (
int i = 0; i < 8; i++)
873 return elem->
rank < 0;
881 MFEM_WARNING(
"Can't prune 3D aniso meshes yet.");
913 for (
int i = 0; i < refinements.
Size(); i++)
917 "anisotropic parallel refinement not supported yet in 3D.");
919 MFEM_VERIFY(
Iso ||
Dim < 3,
920 "parallel refinement of 3D aniso meshes not supported yet.");
927 for (
int i = 0; i < neighbors.
Size(); i++)
929 send_ref[neighbors[i]].SetNCMesh(
this);
937 for (
int i = 0; i < refinements.
Size(); i++)
943 for (
int j = 0; j < ranks.
Size(); j++)
945 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
953 for (
int i = 0; i < refinements.
Size(); i++)
960 for (
int j = 0; j < neighbors.
Size(); j++)
970 for (
int i = 0; i < msg.
Size(); i++)
985 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
992 long size = refinements.
Size(), glob_size;
993 MPI_Allreduce(&size, &glob_size, 1, MPI_LONG, MPI_SUM,
MyComm);
995 if (!glob_size) {
break; }
1003 MFEM_VERIFY(
Dim < 3 ||
Iso,
1004 "derefinement of 3D anisotropic meshes not implemented yet.");
1028 for (
int i = 0; i < derefs.
Size(); i++)
1030 int row = derefs[i];
1032 "invalid derefinement number.");
1037 int coarse_rank = INT_MAX;
1038 for (
int j = 0; j < size; j++)
1041 coarse_rank = std::min(coarse_rank, fine_rank);
1043 for (
int j = 0; j < size; j++)
1045 new_ranks[fine[j]] = coarse_rank;
1049 int target_elements = 0;
1050 for (
int i = 0; i < new_ranks.Size(); i++)
1052 if (new_ranks[i] == MyRank) { target_elements++; }
1066 for (
int i = 0; i < neighbors.
Size(); i++)
1068 send_deref[neighbors[i]].SetNCMesh(
this);
1075 for (
int i = 0; i < derefs.
Size(); i++)
1078 Element* parent = old_elements[fine[0]]->parent;
1082 for (
int j = 0; j < ranks.
Size(); j++)
1084 send_deref[ranks[j]].AddDerefinement(parent, new_ranks[fine[0]]);
1094 for (
int i = 0; i < old_elements.
Size(); i++)
1096 old_elements[i]->index = i;
1101 old_elements.
Copy(coarse);
1102 for (
int i = 0; i < derefs.
Size(); i++)
1105 Element* parent = old_elements[fine[0]]->parent;
1114 for (
int j = 0; j < neighbors.
Size(); j++)
1124 for (
int i = 0; i < msg.
Size(); i++)
1142 for (
int i = 0; i < coarse.
Size(); i++)
1144 int index = coarse[i]->index;
1148 index = -1 - coarse[i]->rank;
1158 for (
int i = 0; i < coarse.
Size(); i++)
1163 index = old_elements[index]->index;
1172 template<
typename Type>
1174 const Table &deref_table)
1187 for (
int i = 0; i < deref_table.
Size(); i++)
1189 const int* fine = deref_table.
GetRow(i);
1190 int size = deref_table.
RowSize(i);
1191 MFEM_ASSERT(size <= 8,
"");
1193 int ranks[8], min_rank = INT_MAX, max_rank = INT_MIN;
1194 for (
int j = 0; j < size; j++)
1197 min_rank = std::min(min_rank, ranks[j]);
1198 max_rank = std::max(max_rank, ranks[j]);
1202 if (min_rank != max_rank)
1205 for (
int j = 0; j < size; j++)
1207 if (ranks[j] != MyRank) { neigh.
Append(ranks[j]); }
1212 for (
int j = 0; j < size; j++)
1214 Type *data = &elem_data[fine[j]];
1216 int rnk = ranks[j], len = 1;
1222 for (
int k = 0; k < neigh.
Size(); k++)
1224 MPI_Request* req =
new MPI_Request;
1225 MPI_Isend(data, len, datatype, neigh[k], 292,
MyComm, req);
1231 MPI_Request* req =
new MPI_Request;
1232 MPI_Irecv(data, len, datatype, rnk, 292,
MyComm, req);
1239 for (
int i = 0; i < requests.
Size(); i++)
1241 MPI_Wait(requests[i], MPI_STATUS_IGNORE);
1248 ParNCMesh::SynchronizeDerefinementData<int>(
Array<int> &,
const Table &);
1260 for (
int i = 0; i < deref_table.
Size(); i++)
1262 const int* fine = deref_table.
GetRow(i),
1263 size = deref_table.
RowSize(i);
1266 for (
int j = 0; j < size; j++)
1269 if (child->
rank == MyRank)
1274 for (
int k = 0; k <
Dim; k++)
1276 if ((parent->
ref_type & (1 << k)) &&
1277 splits[k] >= max_nc_level)
1279 leaf_ok[fine[j]] = 0;
break;
1291 for (
int i = 0; i < deref_table.
Size(); i++)
1293 const int* fine = deref_table.
GetRow(i),
1294 size = deref_table.
RowSize(i);
1296 for (
int j = 0; j < size; j++)
1298 if (!leaf_ok[fine[j]])
1300 level_ok[i] = 0;
break;
1318 long local_elems =
NElements, total_elems = 0;
1319 MPI_Allreduce(&local_elems, &total_elems, 1, MPI_LONG, MPI_SUM,
MyComm);
1321 long first_elem_global = 0;
1322 MPI_Scan(&local_elems, &first_elem_global, 1, MPI_LONG, MPI_SUM,
MyComm);
1323 first_elem_global -= local_elems;
1332 new_ranks[i] =
Partition(first_elem_global + (j++), total_elems);
1345 for (
int i = 0; i < old_elements.
Size(); i++)
1375 int begin = 0, end = 0;
1395 for (
int i = 0; i < rank_neighbors.
Size(); i++)
1397 Element* e = rank_neighbors[i];
1405 recv_ghost_ranks[rank].SetNCMesh(
this);
1414 NeighborElementRankMessage::Map::iterator it;
1415 for (it = recv_ghost_ranks.begin(); it != recv_ghost_ranks.end(); ++it)
1418 for (
int i = 0; i < msg.
Size(); i++)
1420 int ghost_index = msg.
elements[i]->index;
1422 new_ranks[ghost_index] = msg.
values[i];
1426 recv_ghost_ranks.clear();
1437 int received_elements = 0;
1441 if (e->
rank == MyRank && new_ranks[i] == MyRank)
1443 received_elements++;
1445 e->
rank = new_ranks[i];
1459 int begin = 0, end = 0;
1463 int rank = owned_elements[begin]->rank;
1464 while (end < owned_elements.
Size() &&
1465 owned_elements[end]->rank == rank) { end++; }
1470 rank_elems.
MakeRef(&owned_elements[begin], end - begin);
1481 for (
int i = 0; i < batch.
Size(); i++)
1516 while (received_elements < target_elements)
1524 for (
int i = 0; i < msg.
Size(); i++)
1526 int elem_rank = msg.
values[i];
1529 if (elem_rank == MyRank) { received_elements++; }
1548 const Table &old_element_dofs,
1549 long old_global_offset,
1556 RebalanceDofMessage::Map::iterator it;
1566 for (
int i = 0; i < ne; i++)
1587 RebalanceDofMessage::Map::iterator it;
1592 nd += msg.
dofs.size();
1603 for (
unsigned i = 0; i < msg.
elem_ids.size(); i++)
1607 for (
unsigned i = 0; i < msg.
dofs.size(); i++)
1620 : ncmesh(other.ncmesh), include_ref_types(other.include_ref_types)
1628 data.Append(value & 0xff);
1629 data.Append((value >> 8) & 0xff);
1630 data.Append((value >> 16) & 0xff);
1631 data.Append((value >> 24) & 0xff);
1637 return (
int) data[pos] +
1638 ((int) data[pos+1] << 8) +
1639 ((int) data[pos+2] << 16) +
1640 ((int) data[pos+3] << 24);
1646 for (
int i = 0; i < elements.
Size(); i++)
1649 while (e && e->
flag != flag)
1668 for (
int i = 0; i < 8; i++)
1678 if (include_ref_types)
1683 for (
int i = 0; i < 8; i++)
1685 if (mask & (1 << i))
1687 EncodeTree(elem->
child[i]);
1695 FlagElements(elements, 1);
1701 for (
int i = 0; i < roots.
Size(); i++)
1706 EncodeTree(roots[i]);
1711 FlagElements(elements, 0);
1717 int mask = data[pos++];
1724 if (include_ref_types)
1726 int ref_type = data[pos++];
1729 ncmesh->RefineElement(elem, ref_type);
1731 else { MFEM_ASSERT(ref_type == elem->
ref_type,
"") }
1733 else { MFEM_ASSERT(elem->
ref_type != 0,
""); }
1735 for (
int i = 0; i < 8; i++)
1737 if (mask & (1 << i))
1739 DecodeTree(elem->
child[i], pos, elements);
1748 while ((root = GetInt(pos)) >= 0)
1751 DecodeTree(ncmesh->root_elements[root], pos, elements);
1755 template<
typename T>
1756 static inline void write(std::ostream& os, T value)
1758 os.write((
char*) &value,
sizeof(T));
1761 template<
typename T>
1762 static inline T read(std::istream& is)
1765 is.read((
char*) &value,
sizeof(T));
1771 write<int>(os, data.Size());
1772 os.write((
const char*) data.GetData(), data.Size());
1777 data.SetSize(read<int>(is));
1778 is.read((
char*) data.GetData(), data.Size());
1786 std::map<Element*, int> element_id;
1792 for (
int type = 0; type < 3; type++)
1794 for (
int i = 0; i < ids[type].
Size(); i++)
1796 elements.
Append(ids[type][i].element);
1807 for (
int i = 0; i < decoded.
Size(); i++)
1809 element_id[decoded[i]] = i;
1814 for (
int type = 0; type < 3; type++)
1816 write<int>(os, ids[type].
Size());
1817 for (
int i = 0; i < ids[type].
Size(); i++)
1819 const MeshId&
id = ids[type][i];
1820 write<int>(os, element_id[
id.element]);
1821 write<char>(os,
id.local);
1836 for (
int type = 0; type < 3; type++)
1838 int ne = read<int>(is);
1841 for (
int i = 0; i < ne; i++)
1843 int el_num = read<int>(is);
1844 Element* elem = elements[el_num];
1845 MFEM_VERIFY(!elem->ref_type,
"not a leaf element: " << el_num);
1847 MeshId &
id = ids[type][i];
1849 id.local = read<char>(is);
1857 id.index = elem->node[
id.local]->vertex->index;
1862 const int* ev = gi.
edges[
id.local];
1863 Node* node =
nodes.Peek(elem->node[ev[0]], elem->node[ev[1]]);
1864 MFEM_ASSERT(node && node->
edge,
"edge not found.");
1870 const int* fv = gi.faces[
id.local];
1871 Face* face =
faces.Peek(elem->node[fv[0]], elem->node[fv[1]],
1872 elem->node[fv[2]], elem->node[fv[3]]);
1873 MFEM_ASSERT(face,
"face not found.");
1874 id.index = face->
index;
1887 MFEM_ASSERT(type >= 0 && type < 3,
"");
1894 MFEM_ASSERT(type >= 0 && type < 3,
"");
1896 if (id_dofs[type].find(
id) == id_dofs[type].end())
1898 MFEM_ABORT(
"type/ID " << type <<
"/" <<
id.index <<
" not found in "
1899 "neighbor message. Ghost layers out of sync?");
1902 std::vector<int> &vec = id_dofs[type][id];
1905 ndofs = this->ndofs;
1909 std::vector<int> &dofs)
1916 int v0 =
id.element->node[ev[0]]->vertex->index;
1917 int v1 =
id.element->node[ev[1]]->vertex->index;
1919 if ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1]))
1921 std::vector<int> tmp(dofs);
1925 MFEM_ASSERT((
int) dofs.size() == 2*nv + ne,
"");
1928 for (
int i = 0; i < 2; i++)
1930 for (
int k = 0; k < nv; k++)
1932 dofs[nv*i + k] = tmp[nv*(1-i) + k];
1938 for (
int i = 0; i < ne; i++)
1940 dofs[2*nv + i] = (ind[i] >= 0) ? tmp[2*nv + ind[i]]
1941 : -1 - tmp[2*nv + (-1 - ind[i])];
1946 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
1948 write<int>(os, dofs.size());
1950 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
1953 static void read_dofs(std::istream &is, std::vector<int> &dofs)
1955 dofs.resize(read<int>(is));
1956 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
1961 IdToDofs::iterator it;
1965 for (
int type = 0; type < 3; type++)
1967 ids[type].
Reserve(id_dofs[type].size());
1968 for (it = id_dofs[type].begin(); it != id_dofs[type].end(); ++it)
1970 ids[type].
Append(it->first);
1975 std::ostringstream stream;
1976 pncmesh->EncodeMeshIds(stream, ids);
1979 for (
int type = 0; type < 3; type++)
1981 for (it = id_dofs[type].begin(); it != id_dofs[type].end(); ++it)
1983 if (type == 1) { ReorderEdgeDofs(it->first, it->second); }
1984 write_dofs(stream, it->second);
1988 id_dofs[type].clear();
1991 write<int>(stream, ndofs);
1993 stream.str().swap(data);
1998 std::istringstream stream(data);
2002 pncmesh->DecodeMeshIds(stream, ids);
2005 for (
int type = 0; type < 3; type++)
2007 id_dofs[type].clear();
2008 for (
int i = 0; i < ids[type].
Size(); i++)
2011 read_dofs(stream, id_dofs[type][
id]);
2012 if (type == 1) { ReorderEdgeDofs(
id, id_dofs[type][
id]); }
2016 ndofs = read<int>(stream);
2024 std::ostringstream stream;
2027 write<int>(stream, rows.size());
2028 for (std::set<int>::iterator it = rows.begin(); it != rows.end(); ++it)
2030 write<int>(stream, *it);
2034 stream.str().swap(data);
2039 std::istringstream stream(data);
2043 int size = read<int>(stream);
2044 for (
int i = 0; i < size; i++)
2046 rows.insert(rows.end(), read<int>(stream));
2055 MFEM_ASSERT(rows.find(row) == rows.end(),
"");
2056 Row& row_data = rows[row];
2058 row_data.srow = srow;
2063 MFEM_ASSERT(rows.find(row) != rows.end(),
2064 "row " << row <<
" not found in neighbor message.");
2065 Row& row_data = rows[row];
2066 cols.
SetSize(row_data.cols.size());
2067 cols.
Assign(row_data.cols.data());
2068 srow = row_data.srow;
2073 std::ostringstream stream;
2076 write<int>(stream, rows.size());
2077 for (std::map<int, Row>::iterator it = rows.begin(); it != rows.end(); ++it)
2079 write<int>(stream, it->first);
2080 Row& row_data = it->second;
2081 MFEM_ASSERT((
int) row_data.cols.size() == row_data.srow.Size(),
"");
2082 write_dofs(stream, row_data.cols);
2083 stream.write((
const char*) row_data.srow.GetData(),
2084 sizeof(double) * row_data.srow.Size());
2088 stream.str().swap(data);
2093 std::istringstream stream(data);
2099 int size = read<int>(stream);
2100 for (
int i = 0; i < size; i++)
2102 Row& row_data = rows[read<int>(stream)];
2103 read_dofs(stream, row_data.
cols);
2106 sizeof(double) * row_data.
srow.
Size());
2112 template<
class ValueType,
bool RefTypes,
int Tag>
2115 std::ostringstream ostream;
2118 tmp_elements.
MakeRef(elements.data(), elements.size());
2121 eset.
Encode(tmp_elements);
2128 std::map<Element*, int> element_index;
2129 for (
int i = 0; i < decoded.
Size(); i++)
2131 element_index[decoded[i]] = i;
2134 write<int>(ostream, values.size());
2135 MFEM_ASSERT(elements.size() == values.size(),
"");
2137 for (
unsigned i = 0; i < values.size(); i++)
2139 write<int>(ostream, element_index[elements[i]]);
2140 write<ValueType>(ostream, values[i]);
2143 ostream.str().swap(data);
2146 template<
class ValueType,
bool RefTypes,
int Tag>
2149 std::istringstream istream(data);
2155 eset.
Decode(tmp_elements);
2158 elements.assign(el, el + tmp_elements.
Size());
2159 values.resize(elements.size());
2161 int count = read<int>(istream);
2162 for (
int i = 0; i < count; i++)
2164 int index = read<int>(istream);
2165 MFEM_ASSERT(index >= 0 && (
size_t)index < values.size(),
"");
2166 values[index] = read<ValueType>(istream);
2176 eset.SetNCMesh(ncmesh);
2181 eset.Decode(decoded);
2183 elem_ids.resize(decoded.
Size());
2184 for (
int i = 0; i < decoded.
Size(); i++)
2186 elem_ids[i] = decoded[i]->index;
2192 std::ostringstream stream;
2195 write<long>(stream, dof_offset);
2196 write_dofs(stream, dofs);
2198 stream.str().swap(data);
2203 std::istringstream stream(data);
2206 dof_offset = read<long>(stream);
2207 read_dofs(stream, dofs);
2214 elem_ids.resize(elems.
Size());
2215 for (
int i = 0; i < elems.
Size(); i++)
2217 elem_ids[i] = elems[i]->index;
2230 for (
int i = 0; i < cle.
Size(); i++)
2232 cle[i]->attribute = cle[i]->rank + 1;
2237 debug_mesh.
ncmesh = copy;
2243 #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< Element * > ghost_layer
list of elements whose 'element_type' == 2.
void AddElementRank(Element *elem, int rank)
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()
void FindNeighbors(const Element *elem, Array< Element * > &neighbors, const Array< Element * > *search_set=NULL)
char ref_type
refinement XYZ bit mask (7 = full isotropic)
void CalcFaceOrientations()
int index
edge number in the Mesh
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
Iterator over items contained in the HashTable.
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 if the new size is different.
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.
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.
static int find_node(Element *elem, Node *node)
void DecodeTree(Element *elem, int &pos, Array< Element * > &elements) const
void SetDerefMatrixCodes(Element *parent, Array< Element * > &coarse)
void SynchronizeDerefinementData(Array< Type > &elem_data, const Table &deref_table)
int index
vertex number in the Mesh
void NeighborExpand(const Array< Element * > &elements, Array< Element * > &expanded, const Array< Element * > *search_set=NULL)
int GetInt(int pos) const
virtual void OnMeshUpdated(Mesh *mesh)
virtual void Derefine(const Array< int > &derefs)
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)
Element * parent
parent element, NULL if this is a root element
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)
Element * element
NCMesh::Element containing this vertex/edge/face.
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).
Array< int > face_nbr_elements_offset
bool PruneTree(Element *elem)
Internal. Recursive part of Prune().
int index
face number in the Mesh
void MakeFromList(int nrows, const Array< Connection > &list)
std::vector< Element * > elements
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)
Element * elem[2]
up to 2 elements sharing the face
std::vector< Master > masters
void FlagElements(const Array< Element * > &elements, char flag)
Array< int > old_index_or_rank
RebalanceDofMessage::Map recv_rebalance_dofs
int InitialPartition(int index) const
Helper to get the partition when the serial mesh is being split initially.
void EncodeTree(Element *elem)
void RefineElement(Element *elem, char ref_type)
Array< Element * > boundary_layer
list of type 3 elements
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.
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)
void SetElements(const Array< Element * > &elems, NCMesh *ncmesh)
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
static GeomInfo GI[Geometry::NumGeom]
int slaves_end
slave faces
bool Iso
true if the mesh only contains isotropic refinements
void DerefineElement(Element *elem)
std::map< int, NeighborDerefinementMessage > Map
virtual void BuildEdgeList()
static bool compare_ranks(const Element *a, const Element *b)
void FindSetNeighbors(const Array< char > &elem_set, Array< Element * > *neighbors, Array< char > *neighbor_set=NULL)
Array< Vertex > face_nbr_vertices
std::vector< Slave > slaves
virtual void BuildFaceList()
void GetDebugMesh(Mesh &debug_mesh) const
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.
Element * child[8]
2-8 children (if ref_type != 0)
Face * GetFace(Element *elem, int face_no)
Array< Element * > leaf_elements
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 ElementNeighborProcessors(Element *elem, Array< int > &ranks)
virtual void ElementSharesFace(Element *elem, Face *face)
virtual void ElementSharesEdge(Element *elem, Edge *edge)
void Decode(Array< Element * > &elements) const
bool CheckElementType(Element *elem, int type)
virtual void Refine(const Array< Refinement > &refinements)
static bool compare_ranks_indices(const Element *a, const Element *b)
void RecvRebalanceDofs(Array< int > &elements, Array< long > &dofs)
Receive element DOFs sent by SendRebalanceDofs().
void GetRow(int row, Array< int > &cols, Vector &srow)
void Isend(int rank, MPI_Comm comm)
Non-blocking send to processor 'rank'.
Array< Connection > index_rank
Node * node[8]
element corners (if ref_type == 0)
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)
T & Last()
Return the last element in the array.
virtual void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level)
int GetNEdges() const
Return the number of edges.
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Array< Element * > root_elements
void AddElementRank(Element *elem, int rank)
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)
void Encode(const Array< Element * > &elements)
const NCList & GetSharedFaces()
static int find_element_edge(Element *elem, int v0, int v1)
std::map< int, RebalanceMessage > Map
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
void ReorderEdgeDofs(const NCMesh::MeshId &id, std::vector< int > &dofs)
Array< Element * > tmp_neighbors
void NeighborProcessors(Array< int > &neighbors)
void CountSplits(Element *elem, int splits[3]) const
Table send_face_nbr_elements
static int get_face_orientation(Face *face, Element *e1, Element *e2, int local[2]=NULL)
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.
virtual void UpdateVertices()
update Vertex::index and vertex_nodeId
Class for parallel meshes.
Abstract data type element.
int rank
processor number (ParNCMesh)
virtual void LimitNCLevel(int max_nc_level)
Parallel version of NCMesh::LimitNCLevel.
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