// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == TU Dresden == // == == // == Institut für Wissenschaftliches Rechnen == // == Zellescher Weg 12-14 == // == 01069 Dresden == // == germany == // == == // ============================================================================ // == == // == https://gforge.zih.tu-dresden.de/projects/amdis/ == // == == // ============================================================================ /** \file InteriorBoundary.h */ #ifndef AMDIS_INTERIORBOUNDARY_H #define AMDIS_INTERIORBOUNDARY_H #include #include #include "AMDiS_fwd.h" #include "MacroElement.h" #include "Element.h" #include "Boundary.h" namespace AMDiS { typedef std::vector > ExcludeList; /// Defines the geometrical objects that forms the boundary; struct BoundaryObject { BoundaryObject() : elType(0), reverseMode(false), excludedSubstructures(0) {} BoundaryObject(Element *e, int eType, GeoIndex sObj, int iObj) : el(e), elIndex(e->getIndex()), elType(eType), subObj(sObj), ithObj(iObj), reverseMode(false), excludedSubstructures(0) {} void setReverseMode(BoundaryObject &otherBound, FiniteElemSpace *feSpace); bool operator==(const BoundaryObject& other) const; bool operator!=(const BoundaryObject& other) const; /// The macro element to which the boundary element corresponds to. Element* el; /// Index of the macro element. int elIndex; /// Element type index, only used in 3d. int elType; /** \brief * Defines the geometrical object at the boundary. It must be "a part" of the * macro element \ref el, i.e., either 1 (a vertex), 2 (an edge) or 3 (a face). */ GeoIndex subObj; /** \brief * Defines which of vertix, edge or face of the macro element is part of the * boundary. * * Example: If the macro element is a triangle, than \ref subObj may be either * 1 (vertex) or 2 (edge). Assume its the last one. So this variable defines * which of the three possible edges of the triangle is at the interior * boundary. */ int ithObj; bool reverseMode; /** \brief * In many situations it may be necessary to exclude some parts of the element to * be part of the boundary. In 3d, when a face is part of the boundary, an edge or * an vertex may be exludeded. In 2d only vertices may be exluded to be part of * an edge boundary. This list contains pairs of exludeded structures. The first * component of every pair denotes if it is a vertex or an edge, and the second * component denotes the local index of the structure. */ ExcludeList excludedSubstructures; }; /** \brief * Defines one atomic part of the boundary, i.e., two boundary objects where the * boundary goes through. */ struct AtomicBoundary { AtomicBoundary() : type(INTERIOR) {} bool operator==(const AtomicBoundary& other) const; /// The rank's part of the boundary. BoundaryObject rankObj; /// The object on the other side of the boundary. BoundaryObject neighObj; /// Integer flag that is used to distinguish between different types of /// boundaries. Till now it is used only for periodic boundaries, which are also /// handles as interior boundaries. BoundaryType type; }; /** \brief * Defines the interior boundary, i.e. a bound within the domain. It is used for * the classical domain decomposition parallelization. */ class InteriorBoundary { public: typedef std::map > RankToBoundMap; /// Iterator for the interior boundary object. class iterator { public: iterator(InteriorBoundary &b) : bound(b) { reset(); } /// Set the iterator to the first position. void reset() { mapIt = bound.boundary.begin(); nextNonempty(); if (mapIt != bound.boundary.end()) vecIt = mapIt->second.begin(); } /// Test if iterator is at the final position. bool end() const { return (mapIt == bound.boundary.end()); } /// Move iterator to the next position. void operator++() { ++vecIt; if (vecIt == mapIt->second.end()) { ++mapIt; nextNonempty(); if (mapIt != bound.boundary.end()) vecIt = mapIt->second.begin(); } } inline AtomicBoundary& operator*() { return *vecIt; } inline AtomicBoundary* operator->() { return &(*vecIt); } void nextRank() { ++mapIt; nextNonempty(); if (mapIt != bound.boundary.end()) vecIt = mapIt->second.begin(); } int getRank() { return mapIt->first; } protected: inline void nextNonempty() { if (mapIt == bound.boundary.end()) return; while (mapIt->second.size() == 0) { ++mapIt; if (mapIt == bound.boundary.end()) return; } } protected: RankToBoundMap::iterator mapIt; std::vector::iterator vecIt; InteriorBoundary &bound; }; public: InteriorBoundary() {} AtomicBoundary& getNewAtomic(int rank); /// Writes this object to a file. void serialize(std::ostream &out); /// Reads the state of an interior boundary from a file. void deserialize(std::istream &in, std::map &elIndexMap); /// Compares this interior boundaries with some other. The order of the /// boundary elements within the object does not play a role. bool operator==(const InteriorBoundary& other) const; protected: void serializeExcludeList(std::ostream &out, ExcludeList &list); void deserializeExcludeList(std::istream &in, ExcludeList &list); public: RankToBoundMap boundary; }; } #endif // AMDIS_INTERIORBOUNDARY_H