/****************************************************************************** * * AMDiS - Adaptive multidimensional simulations * * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis * * Authors: * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * * This file is part of AMDiS * * See also license.opensource.txt in the distribution. * ******************************************************************************/ /** \file InteriorBoundary.h */ #ifndef AMDIS_INTERIORBOUNDARY_H #define AMDIS_INTERIORBOUNDARY_H #include <vector> #include <map> #include "AMDiS_fwd.h" #include "BoundaryObject.h" #include "parallel/ParallelTypes.h" namespace AMDiS { namespace Parallel { /** \brief * Defines the interior boundary, i.e. a bound within the domain. It is used for * the classical domain decomposition parallelization. */ class InteriorBoundary { public: void create(MeshLevelData &levelData, int level, ElementObjectDatabase &elObjDb); RankToBoundMap& getOwn() { return own; } inline MacroElIndexMap& getElIndexMap() { return macroElIndexMap; } inline Element* getElementPtr(int index, Mesh* mesh) { FUNCNAME_DBG("ElementObjectDatabase::getElementPtr()"); TEST_EXIT_DBG(macroElIndexMap[index][mesh]) ("No element pointer in macroElIndex map. Something is wrong.\n"); return macroElIndexMap[index][mesh]; } RankToBoundMap& getOther() { return other; } RankToBoundMap& getPeriodic() { return periodic; } std::vector<AtomicBoundary>& getOwn(int rank) { return own[rank]; } std::vector<AtomicBoundary>& getOther(int rank) { return other[rank]; } std::vector<AtomicBoundary>& getPeriodic(int rank) { return periodic[rank]; } bool hasPeriodic() { return static_cast<bool>(periodic.size()); } int getDegreeOwn(BoundaryObject &bObj); /// 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, Mesh *mesh); private: /// In this function, we put some verification procedures to check for /// consistency if the created interior boundary data. This function is /// enabled even for optimized mode to check all possible meshes. Thus, /// everything herein should be fast. If the code is stable, we can think /// to remove this function. void verifyBoundary(); AtomicBoundary& getNewOwn(int rank); AtomicBoundary& getNewOther(int rank); AtomicBoundary& getNewPeriodic(int rank); /// Checks whether the given boundary is already a other boundary with /// given rank number. Returns true, if the bound is already in the other /// boundary database. bool checkOther(AtomicBoundary& bound, int rank); /// Removes the given boundary object from all owned boundaries. Returns /// true, if at least one object has been removed, otherwise false. bool removeOwn(BoundaryObject& bound); /// Removes the given boundary object from all other boundaries. Returns /// true, if at least one object has been removed, otherwise false. bool removeOther(BoundaryObject& bound); void serialize(std::ostream &out, RankToBoundMap& boundary); void deserialize(std::istream &in, RankToBoundMap& boundary, std::map<int, Element*> &elIndexMap); void serializeExcludeList(std::ostream &out, ExcludeList &list); void deserializeExcludeList(std::istream &in, ExcludeList &list); private: RankToBoundMap own, other, periodic; MacroElIndexMap macroElIndexMap; friend class ParallelDebug; public: /// Iterator for the interior boundary object. class iterator { public: iterator(RankToBoundMap &b) : bound(b), level(0) { reset(); } /// Set the iterator to the first position. void reset() { mapIt = bound.begin(); nextNonempty(); } /// Test if iterator is at the final position. bool end() const { return (mapIt == bound.end()); } /// Move iterator to the next position. void operator++() { #if 0 do { ++vecIt; } while (vecIt != mapIt->second.end() && vecIt->maxLevel < level); #else ++vecIt; #endif if (vecIt == mapIt->second.end()) { ++mapIt; nextNonempty(); } } inline AtomicBoundary& operator*() { return *vecIt; } inline AtomicBoundary* operator->() { return &(*vecIt); } void nextRank() { ++mapIt; nextNonempty(); } inline int getRank() { return mapIt->first; } protected: inline void nextNonempty() { do { // Return, we are at the end. if (mapIt == bound.end()) return; // Search for the next non empty boundary map. while (mapIt->second.size() == 0) { ++mapIt; if (mapIt == bound.end()) return; } vecIt = mapIt->second.begin(); // Search for the next atomic boundary on the mesh level #if 0 while (vecIt != mapIt->second.end() && vecIt->maxLevel < level) ++vecIt; #endif // If vector iterator is not at the end, we have found one and // can return. if (vecIt != mapIt->second.end()) return; // In this case, no boundary on the given level is found, continue // with next rank. ++mapIt; } while (true); } protected: RankToBoundMap::iterator mapIt; std::vector<AtomicBoundary>::iterator vecIt; RankToBoundMap &bound; int level; }; }; class MultiLevelInteriorBoundary { public: void create(MeshLevelData &levelData, ElementObjectDatabase &elObjDb); inline InteriorBoundary& operator[](int level) { TEST_EXIT_DBG(levelIntBound.count(level))("Should not happen!\n"); return levelIntBound[level]; } /// 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, Mesh *mesh); private: std::map<int, InteriorBoundary> levelIntBound; }; } } #endif // AMDIS_INTERIORBOUNDARY_H