12 #include "../config/config.hpp"
18 #include "../fem/fe_coll.hpp"
91 if (it->vertex) { it->vertex->index = -1; }
100 for (
int j = 0; j <
GI[(int) elem->geom].
nv; j++)
102 int &vindex = elem->node[j]->vertex->index;
103 if (vindex < 0) { vindex =
NVertices++; }
111 if (it->vertex && it->vertex->index >= 0)
120 if (it->vertex && it->vertex->index < 0)
136 if (it->edge) { it->edge->index = -1; }
148 if (it->edge && it->edge->index < 0)
170 owner = std::min(owner, elem->rank);
180 owner = std::min(owner, elem->rank);
235 struct MasterSlaveInfo
238 int slaves_begin, slaves_end;
239 MasterSlaveInfo() : master(-1), slaves_begin(0), slaves_end(0) {}
245 std::vector<MasterSlaveInfo> info(nitems);
247 for (
unsigned i = 0; i < list.masters.size(); i++)
249 const Master &mf = list.masters[i];
253 for (
unsigned i = 0; i < list.slaves.size(); i++)
255 const Slave& sf = list.slaves[i];
267 for (
int i = 0; i < size; i++)
272 const MasterSlaveInfo &msi = info[index];
280 for (
int j = msi.slaves_begin; j < msi.slaves_end; j++)
289 static bool is_shared(
const Table& groups,
int index,
int MyRank)
294 int size = groups.
RowSize(index);
300 const int* group = groups.
GetRow(index);
301 for (
int i = 0; i < size; i++)
303 if (group[i] == MyRank) {
return true; }
314 for (
unsigned i = 0; i < list.conforming.size(); i++)
316 if (is_shared(groups, list.conforming[i].index, MyRank))
318 shared.conforming.push_back(list.conforming[i]);
321 for (
unsigned i = 0; i < list.masters.size(); i++)
323 if (is_shared(groups, list.masters[i].index, MyRank))
325 shared.masters.push_back(list.masters[i]);
328 for (
unsigned i = 0; i < list.slaves.size(); i++)
330 if (is_shared(groups, list.slaves[i].index, MyRank))
332 shared.slaves.push_back(list.slaves[i]);
353 for (
int j = 0; j <
GI[(int) elem->geom].
nv; j++)
355 Node* node = elem->node[j];
359 owner = std::min(owner, elem->rank);
363 MeshId &
id = vertex_id[index];
364 id.index = (node->
edge ? -1 : index);
378 for (
int i = 0; i < nvertices; i++)
380 if (is_shared(
vertex_group, i, MyRank) && vertex_id[i].index >= 0)
398 if (it->ref_count == 2 && it->index <
NFaces)
400 Element* e[2] = { it->elem[0], it->elem[1] };
401 if (e[0]->rank == e[1]->rank) {
continue; }
402 if (e[0]->rank > e[1]->rank) { std::swap(e[0], e[1]); }
405 for (
int i = 0; i < 2; i++)
413 for (
int j = 0; j < 4; j++)
415 ids[i][j] = e[i]->node[fv[j]]->id;
432 for (i = j = 0; i < bdr_vertices.
Size(); i++)
434 if (bdr_vertices[i] <
NVertices) { bdr_vertices[j++] = bdr_vertices[i]; }
439 for (i = j = 0; i < bdr_edges.
Size(); i++)
441 if (bdr_edges[i] <
NEdges) { bdr_edges[j++] = bdr_edges[i]; }
455 for (
int i = 0; i < nleaves; i++)
469 for (
int i = 0; i < nleaves; i++)
486 MFEM_ASSERT(!elem->ref_type,
"not a leaf.");
518 neighbors.
Reserve(ranks.size());
520 std::set<int>::iterator it;
521 for (it = ranks.begin(); it != ranks.end(); ++it)
535 bool removeAll =
true;
538 for (
int i = 0; i < 8; i++)
544 if (!
remove[i]) { removeAll =
false; }
549 if (removeAll) {
return true; }
552 for (
int i = 0; i < 8; i++)
570 MFEM_WARNING(
"Can't prune aniso meshes yet.");
590 for (
int i = 0; i < refinements.
Size(); i++)
594 "anisotropic parallel refinement not supported yet in 3D.");
596 MFEM_VERIFY(
Iso ||
Dim < 3,
597 "parallel refinement of 3D aniso meshes not supported yet.");
604 for (
int i = 0; i < neighbors.
Size(); i++)
606 send_ref[neighbors[i]].SetNCMesh(
this);
614 for (
int i = 0; i < refinements.
Size(); i++)
620 for (
int j = 0; j < ranks.
Size(); j++)
622 send_ref[ranks[j]].AddRefinement(elem, ref.
ref_type);
630 for (
int i = 0; i < refinements.
Size(); i++)
637 for (
int j = 0; j < neighbors.
Size(); j++)
647 for (
unsigned i = 0; i < msg.
refinements.size(); i++)
665 MFEM_ABORT(
"not implemented in parallel yet.");
676 data[pos] = value & 0xff;
677 data[pos+1] = (value >> 8) & 0xff;
678 data[pos+2] = (value >> 16) & 0xff;
679 data[pos+3] = (value >> 24) & 0xff;
685 return (
int) data[pos] +
686 ((int) data[pos+1] << 8) +
687 ((int) data[pos+2] << 16) +
688 ((int) data[pos+3] << 24);
692 (
Element* elem,
const std::set<Element*> &elements)
695 if (elements.find(elem) != elements.end())
704 int mpos = data.Size();
709 for (
int i = 0; i < 8; i++)
713 if (EncodeTree(elem->
child[i], elements))
715 mask |= (
unsigned char) 1 << i;
743 for (
int i = 0; i < ncmesh_roots.
Size(); i++)
745 if (EncodeTree(ncmesh_roots[i], elements))
747 SetInt(header_pos, i);
750 header_pos = data.Size();
751 data.SetSize(header_pos + 4);
756 SetInt(header_pos, -1);
762 int mask = data[pos++];
769 for (
int i = 0; i < 8; i++)
773 DecodeTree(elem->
child[i], pos, elements);
783 while ((root = GetInt(pos)) >= 0)
786 DecodeTree(ncmesh_roots[root], pos, elements);
791 static inline void write(std::ostream& os, T value)
793 os.write((
char*) &value,
sizeof(T));
797 static inline T read(std::istream& is)
800 is.read((
char*) &value,
sizeof(T));
806 write<int>(os, data.Size());
807 os.write((
const char*) data.GetData(), data.Size());
812 data.SetSize(read<int>(is));
813 is.read((
char*) data.GetData(), data.Size());
822 std::map<Element*, int> element_id;
827 std::set<Element*> elements;
828 for (
int type = 0; type <
dim; type++)
830 for (
int i = 0; i < ids[type].
Size(); i++)
832 elements.insert(ids[type][i].element);
842 for (
int i = 0; i < decoded.
Size(); i++)
844 element_id[decoded[i]] = i;
849 for (
int type = 0; type <
dim; type++)
851 write<int>(os, ids[type].
Size());
852 for (
int i = 0; i < ids[type].
Size(); i++)
854 const MeshId&
id = ids[type][i];
855 write<int>(os, element_id[
id.element]);
856 write<char>(os,
id.local);
862 bool decode_indices)
const
871 for (
int type = 0; type <
dim; type++)
873 int ne = read<int>(is);
876 for (
int i = 0; i < ne; i++)
878 int el_num = read<int>(is);
879 Element* elem = elements[el_num];
880 MFEM_VERIFY(!elem->ref_type,
"not a leaf element: " << el_num);
882 MeshId &
id = ids[type][i];
884 id.local = read<char>(is);
886 if (!decode_indices) {
continue; }
894 id.index = elem->node[
id.local]->vertex->index;
899 const int* ev = gi.
edges[
id.local];
900 Node* node =
nodes.Peek(elem->node[ev[0]], elem->node[ev[1]]);
901 MFEM_ASSERT(node && node->
edge,
"edge not found.");
907 const int* fv = gi.
faces[
id.local];
908 Face* face =
faces.Peek(elem->node[fv[0]], elem->node[fv[1]],
909 elem->node[fv[2]], elem->node[fv[3]]);
910 MFEM_ASSERT(face,
"face not found.");
911 id.index = face->
index;
923 MFEM_ASSERT(type >= 0 && type < 3,
"");
930 MFEM_ASSERT(type >= 0 && type < 3,
"");
932 if (id_dofs[type].find(
id) == id_dofs[type].end())
934 MFEM_ABORT(
"type/ID " << type <<
"/" <<
id.index <<
" not found in "
935 "neighbor message. Ghost layers out of sync?");
938 std::vector<int> &vec = id_dofs[type][id];
945 std::vector<int> &dofs)
952 int v0 =
id.element->node[ev[0]]->vertex->index;
953 int v1 =
id.element->node[ev[1]]->vertex->index;
955 if ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1]))
957 std::vector<int> tmp(dofs);
961 MFEM_ASSERT((
int) dofs.size() == 2*nv + ne,
"");
964 for (
int i = 0; i < 2; i++)
966 for (
int k = 0; k < nv; k++)
968 dofs[nv*i + k] = tmp[nv*(1-i) + k];
974 for (
int i = 0; i < ne; i++)
976 dofs[2*nv + i] = (ind[i] >= 0) ? tmp[2*nv + ind[i]]
977 : -1 - tmp[2*nv + (-1 - ind[i])];
982 static void write_dofs(std::ostream &os,
const std::vector<int> &dofs)
984 write<int>(os, dofs.size());
986 os.write((
const char*) dofs.data(), dofs.size() *
sizeof(int));
989 static void read_dofs(std::istream &is, std::vector<int> &dofs)
991 dofs.resize(read<int>(is));
992 is.read((
char*) dofs.data(), dofs.size() *
sizeof(int));
997 IdToDofs::iterator it;
1001 for (
int type = 0; type < 3; type++)
1003 ids[type].
Reserve(id_dofs[type].size());
1004 for (it = id_dofs[type].begin(); it != id_dofs[type].end(); ++it)
1006 ids[type].
Append(it->first);
1011 std::ostringstream stream;
1012 pncmesh->EncodeMeshIds(stream, ids, 3);
1015 for (
int type = 0; type < 3; type++)
1017 for (it = id_dofs[type].begin(); it != id_dofs[type].end(); ++it)
1019 if (type == 1) { ReorderEdgeDofs(it->first, it->second); }
1020 write_dofs(stream, it->second);
1024 id_dofs[type].clear();
1027 write<int>(stream, ndofs);
1029 stream.str().swap(data);
1034 std::istringstream stream(data);
1038 pncmesh->DecodeMeshIds(stream, ids, 3,
true);
1041 for (
int type = 0; type < 3; type++)
1043 id_dofs[type].clear();
1044 for (
int i = 0; i < ids[type].
Size(); i++)
1047 read_dofs(stream, id_dofs[type][
id]);
1048 if (type == 1) { ReorderEdgeDofs(
id, id_dofs[type][
id]); }
1052 ndofs = read<int>(stream);
1060 std::ostringstream stream;
1063 write<int>(stream, rows.size());
1064 for (std::set<int>::iterator it = rows.begin(); it != rows.end(); ++it)
1066 write<int>(stream, *it);
1070 stream.str().swap(data);
1075 std::istringstream stream(data);
1079 int size = read<int>(stream);
1080 for (
int i = 0; i < size; i++)
1082 rows.insert(rows.end(), read<int>(stream));
1091 MFEM_ASSERT(rows.find(row) == rows.end(),
"");
1092 Row& row_data = rows[row];
1094 row_data.srow = srow;
1099 MFEM_ASSERT(rows.find(row) != rows.end(),
1100 "row " << row <<
" not found in neighbor message.");
1101 Row& row_data = rows[row];
1102 cols.
SetSize(row_data.cols.size());
1103 cols.
Assign(row_data.cols.data());
1104 srow = row_data.srow;
1109 std::ostringstream stream;
1112 write<int>(stream, rows.size());
1113 for (std::map<int, Row>::iterator it = rows.begin(); it != rows.end(); ++it)
1115 write<int>(stream, it->first);
1116 Row& row_data = it->second;
1117 MFEM_ASSERT((
int) row_data.cols.size() == row_data.srow.Size(),
"");
1118 write_dofs(stream, row_data.cols);
1119 stream.write((
const char*) row_data.srow.GetData(),
1120 sizeof(double) * row_data.srow.Size());
1124 stream.str().swap(data);
1129 std::istringstream stream(data);
1135 int size = read<int>(stream);
1136 for (
int i = 0; i < size; i++)
1138 Row& row_data = rows[read<int>(stream)];
1139 read_dofs(stream, row_data.
cols);
1142 sizeof(double) * row_data.
srow.
Size());
1153 ids.
Reserve(refinements.size());
1154 for (
unsigned i = 0; i < refinements.size(); i++)
1156 const ElemRefType &ref = refinements[i];
1160 std::ostringstream stream;
1161 pncmesh->EncodeMeshIds(stream, &ids, 1);
1163 stream.str().swap(data);
1171 std::istringstream stream(data);
1172 pncmesh->DecodeMeshIds(stream, &ids, 1,
false);
1174 refinements.clear();
1175 refinements.reserve(ids.
Size());
1176 for (
int i = 0; i < ids.
Size(); i++)
1178 AddRefinement(ids[i].element, ids[i].local);
1193 for (
int i = 0; i < cle.
Size(); i++)
1195 cle[i]->attribute = (cle[i]->rank ==
MyRank) ? 1 : 2;
1200 debug_mesh.
ncmesh = copy;
1206 #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)
virtual void LimitNCLevel(int max_level)
Array< Element * > ghost_layer
list of elements whose 'element_type' == 2.
Array< char > element_type
void EncodeMeshIds(std::ostream &os, Array< MeshId > ids[], int dim) const
Write to 'os' a processor-independent encoding of vertex/edge/face IDs.
int Size() const
Logical size of the array.
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()
bool EncodeTree(Element *elem, const std::set< Element * > &elements)
int index
edge number in the Mesh
void AddDofs(int type, const NCMesh::MeshId &id, const Array< int > &dofs)
Add vertex/edge/face DOFs to an outgoing message.
Array< char > face_orient
Iterator over items contained in the HashTable.
virtual void BuildFaceList()
void Dump(std::ostream &os) const
void SetSize(int s)
Resizes the vector if the new size is different.
void BuildSharedVertices()
T * GetData()
Returns the data.
void Load(std::istream &is)
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)
static int find_node(Element *elem, Node *node)
void DecodeTree(Element *elem, int &pos, Array< Element * > &elements) const
int index
vertex number in the Mesh
int GetInt(int pos) const
virtual void OnMeshUpdated(Mesh *mesh)
std::vector< MeshId > conforming
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
virtual void AssignLeafIndices()
void MakeShared(const Table &groups, const NCList &list, NCList &shared)
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'.
virtual void OnMeshUpdated(Mesh *mesh)
ParNCMesh(MPI_Comm comm, const NCMesh &ncmesh)
Array< int > vertex_owner
void DecodeMeshIds(std::istream &is, Array< MeshId > ids[], int dim, bool decode_indices) const
Read from 'is' a processor-independent encoding of vertex/edge/face IDs.
bool PruneTree(Element *elem)
Internal. Recursive part of Prune().
int index
face number in the Mesh
void MakeFromList(int nrows, const Array< Connection > &list)
int Append(const T &el)
Append element to array, resize if necessary.
int InitialPartition(int index) const
Assigns elements to processors at the initial stage (ParMesh creation).
void RefineElement(Element *elem, char ref_type)
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.
void SetInt(int pos, int value)
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)
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)
virtual void BuildEdgeList()
void FindSetNeighbors(const Array< char > &elem_set, Array< Element * > *neighbors, Array< char > *neighbor_set=NULL)
virtual void BuildFaceList()
void GetDebugMesh(Mesh &debug_mesh) const
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)
Array< Element * > leaf_elements
Helper struct for defining a connectivity table, see Table::MakeFromList.
void Decode(Array< Element * > &elements, const Array< Element * > &ncmesh_roots) const
void ElementNeighborProcessors(Element *elem, Array< int > &ranks)
virtual void ElementSharesFace(Element *elem, Face *face)
virtual void ElementSharesEdge(Element *elem, Edge *edge)
virtual void Refine(const Array< Refinement > &refinements)
void GetRow(int row, Array< int > &cols, Vector &srow)
std::vector< ElemRefType > refinements
Array< Connection > index_rank
static int find_hex_face(int a, int b, int c)
void SetNCMesh(ParNCMesh *pncmesh)
Set pointer to ParNCMesh (needed to encode the message).
int GetNEdges() const
Return the number of edges.
Array< Element * > root_elements
static void WaitAllSent(MapT &rank_msg)
Helper to wait for all messages in a map container to be sent.
int GetNFaces() const
Return the number of faces in a 3D mesh.
void AddRow(int row, const Array< int > &cols, const Vector &srow)
void AddMasterSlaveRanks(int nitems, const NCList &list)
void ReorderEdgeDofs(const NCMesh::MeshId &id, std::vector< int > &dofs)
Array< Element * > tmp_neighbors
void NeighborProcessors(Array< int > &neighbors)
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
Abstract data type element.
virtual void LimitNCLevel(int max_level)
To be implemented.
Array< unsigned char > data
encoded refinement (sub-)trees
static void Probe(int &rank, int &size, MPI_Comm comm)