diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h index de41cf3049a5de8d64a99ab6c8cb7b2b82d5a532..a3329e04ea0b05e055dca2164c9da6d52374abb4 100644 --- a/AMDiS/src/AMDiS.h +++ b/AMDiS/src/AMDiS.h @@ -81,7 +81,6 @@ #include "Operator.h" #include "OperatorTerm.h" #include "Parametric.h" -#include "PeriodicMap.h" #include "PeriodicBC.h" #include "ProblemStat.h" #include "ProblemInstat.h" diff --git a/AMDiS/src/Mesh.cc b/AMDiS/src/Mesh.cc index 7501e0d623a4236e64c740c08ba37ea87be8e860..edbc576acede825eae36fac0a79f196dc328d697 100644 --- a/AMDiS/src/Mesh.cc +++ b/AMDiS/src/Mesh.cc @@ -34,7 +34,6 @@ #include "CoarseningManager.h" #include "DOFIterator.h" #include "VertexVector.h" -#include "PeriodicMap.h" #include "Projection.h" #include "ElInfoStack.h" #include "Serializer.h" diff --git a/AMDiS/src/PeriodicMap.h b/AMDiS/src/PeriodicMap.h deleted file mode 100644 index dac987dfa102d9c581870a94e55da6dbaab6db67..0000000000000000000000000000000000000000 --- a/AMDiS/src/PeriodicMap.h +++ /dev/null @@ -1,86 +0,0 @@ -// ============================================================================ -// == == -// == AMDiS - Adaptive multidimensional simulations == -// == == -// == http://www.amdis-fem.org == -// == == -// ============================================================================ -// -// Software License for AMDiS -// -// Copyright (c) 2010 Dresden University of Technology -// All rights reserved. -// Authors: Simon Vey, Thomas Witkowski et al. -// -// This file is part of AMDiS -// -// See also license.opensource.txt in the distribution. - - - -/** \file PeriodicMap.h */ - -#ifndef AMDIS_PERIODICMAP_H -#define AMDIS_PERIODICMAP_H - -#include "Global.h" - -#include <map> - -namespace AMDiS { - - class PeriodicMap - { - public: - void setEntry(DegreeOfFreedom key, DegreeOfFreedom entry) { - // no trivial entries! - if (key == entry) - return; - - // if a key equal to entry exists ... - if (getEntry(entry) >= 0) { - if (getEntry(entry) == key) { - return; - } - // ... let it be equal entries - setEntry(key, getEntry(entry)); - return; - } - - // replace entries equal to key - std::map<DegreeOfFreedom, DegreeOfFreedom>::iterator it; - for (it = periodicMap.begin(); it != periodicMap.end(); ++it) { - if (it->second == key) { - it->second = entry; - } - } - - // if key exists already - if (getEntry(key) >= 0) { - // insert new entry with old entry as key - setEntry(getEntry(key), entry); - } - - // set entry - periodicMap[key] = entry; - }; - - DegreeOfFreedom getEntry(DegreeOfFreedom key) { - std::map<DegreeOfFreedom, DegreeOfFreedom>::iterator it; - it = periodicMap.find(key); - if (it != periodicMap.end()) { - return it->second; - } else { - return -1; - } - }; - - - - protected: - std::map<DegreeOfFreedom, DegreeOfFreedom> periodicMap; - }; - -} - -#endif diff --git a/AMDiS/src/io/MacroReader.cc b/AMDiS/src/io/MacroReader.cc index 00058080e29b13a603445145ac4ea1b2e445fd2a..b315f0c93defe221b1d609d8ca7c3ddc22eea395 100644 --- a/AMDiS/src/io/MacroReader.cc +++ b/AMDiS/src/io/MacroReader.cc @@ -10,6 +10,10 @@ // See also license.opensource.txt in the distribution. +#include <string.h> +#include <map> +#include <iostream> +#include <fstream> #include "MacroReader.h" #include "MacroWriter.h" #include "MacroElement.h" @@ -17,17 +21,12 @@ #include "Boundary.h" #include "FiniteElemSpace.h" #include "Mesh.h" -#include <string.h> #include "FixVec.h" -#include "PeriodicMap.h" #include "ElInfo.h" #include "Initfile.h" #include "DOFIterator.h" #include "LeafData.h" #include "VertexVector.h" -#include <map> -#include <iostream> -#include <fstream> namespace AMDiS { @@ -64,7 +63,7 @@ namespace AMDiS { int mode = -1; // 0: drop dofs, 1: associate dofs int result; BoundaryType boundaryType; - PeriodicMap periodicMap; + MacroReader::PeriodicMap periodicMap; fscanf(file, "%*s %d", &n); fscanf(file, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s"); diff --git a/AMDiS/src/io/MacroReader.h b/AMDiS/src/io/MacroReader.h index 75b251e7e8eb5a30bb171119d3725aef041d09b3..c8bcc36087f3e64b040f1d7072708500172fada8 100644 --- a/AMDiS/src/io/MacroReader.h +++ b/AMDiS/src/io/MacroReader.h @@ -41,6 +41,53 @@ namespace AMDiS { */ class MacroReader { + // Is used to read periodic macros + class PeriodicMap + { + public: + void setEntry(DegreeOfFreedom key, DegreeOfFreedom entry) + { + // no trivial entries! + if (key == entry) + return; + + // if a key equal to entry exists ... + if (getEntry(entry) >= 0) { + if (getEntry(entry) == key) + return; + + // ... let it be equal entries + setEntry(key, getEntry(entry)); + return; + } + + // replace entries equal to key + for (map<DegreeOfFreedom, DegreeOfFreedom>::iterator it = + periodicMap.begin(); it != periodicMap.end(); ++it) + if (it->second == key) + it->second = entry; + + // if key exists already, insert new entry with old entry as key + if (getEntry(key) >= 0) + setEntry(getEntry(key), entry); + + // set entry + periodicMap[key] = entry; + } + + DegreeOfFreedom getEntry(DegreeOfFreedom key) + { + map<DegreeOfFreedom, DegreeOfFreedom>::iterator it = periodicMap.find(key); + if (it != periodicMap.end()) + return it->second; + return -1; + } + + protected: + map<DegreeOfFreedom, DegreeOfFreedom> periodicMap; + }; + + public: /// Creates a Mesh by reading the macro file with the given filename. static MacroInfo* readMacro(std::string filename, diff --git a/AMDiS/src/parallel/InteriorBoundary.h b/AMDiS/src/parallel/InteriorBoundary.h index ed46d8670a26f7949ada81b515bae06927c7233f..1865c2c3de47abbb21ebdb500790d7aab9b38a4d 100644 --- a/AMDiS/src/parallel/InteriorBoundary.h +++ b/AMDiS/src/parallel/InteriorBoundary.h @@ -95,6 +95,8 @@ namespace AMDiS { ExcludeList excludedSubstructures; }; + + /** \brief * Defines one atomic part of the boundary, i.e., two boundary objects where the * boundary goes through. @@ -118,6 +120,8 @@ namespace AMDiS { BoundaryType type; }; + + /** \brief * Defines the interior boundary, i.e. a bound within the domain. It is used for * the classical domain decomposition parallelization. diff --git a/AMDiS/src/parallel/MeshDistributor.cc b/AMDiS/src/parallel/MeshDistributor.cc index 9b0d6349a17ddee4edf403db0114399d844bb926..6b6550ab66321b06a72d574ba68cfcedc5ff49f3 100644 --- a/AMDiS/src/parallel/MeshDistributor.cc +++ b/AMDiS/src/parallel/MeshDistributor.cc @@ -2014,8 +2014,7 @@ namespace AMDiS { // Clear all periodic DOF mappings calculated before. We do it from scratch. periodicDofs.clear(); - periodicDofMap.clear(); - periodicDofAssociations.clear(); + periodicMap.clear(); for (unsigned int i = 0; i < feSpaces.size(); i++) createPeriodicMap(feSpaces[i]); @@ -2064,10 +2063,8 @@ namespace AMDiS { DegreeOfFreedom globalDof1 = dofFeData[feSpace].mapLocalGlobalDofs[*(dofs1[j])]; - if (periodicDofAssociations[feSpace][globalDof0].count(type) == 0) { - periodicDofMap[feSpace][type][globalDof0] = globalDof1; - periodicDofAssociations[feSpace][globalDof0].insert(type); - } + if (!periodicMap.isPeriodicOnBound(feSpace, type, globalDof0)) + periodicMap.add(feSpace, type, globalDof0, globalDof1); } } @@ -2121,10 +2118,8 @@ namespace AMDiS { // Check if this global DOF with the corresponding boundary type was // not added before by another periodic boundary from other rank. - if (periodicDofAssociations[feSpace][globalDofIndex].count(type) == 0) { - periodicDofMap[feSpace][type][globalDofIndex] = mapGlobalDofIndex; - periodicDofAssociations[feSpace][globalDofIndex].insert(type); - } + if (!periodicMap.isPeriodicOnBound(feSpace, type, globalDofIndex)) + periodicMap.add(feSpace, type, globalDofIndex, mapGlobalDofIndex); } } @@ -2151,17 +2146,15 @@ namespace AMDiS { DegreeOfFreedom globalDof = dofFeData[feSpace].mapLocalGlobalDofs[*dofs[i]]; - TEST_EXIT_DBG(periodicDofAssociations[feSpace].count(globalDof)) - ("Should hot happen!\n"); + std::set<BoundaryType>& assoc = + periodicMap.getAssociations(feSpace, globalDof); + TEST_EXIT_DBG(assoc.size() > 0)("Should not happen!\n"); - for (std::set<BoundaryType>::iterator perAscIt = periodicDofAssociations[feSpace][globalDof].begin(); - perAscIt != periodicDofAssociations[feSpace][globalDof].end(); ++perAscIt) - if (*perAscIt >= -3) { - TEST_EXIT_DBG(periodicDofMap[feSpace][*perAscIt].count(globalDof) == 1) - ("Should not happen!\n"); + for (std::set<BoundaryType>::iterator perAscIt = assoc.begin(); + perAscIt != assoc.end(); ++perAscIt) + if (*perAscIt >= -3) perObjMap[*perAscIt][globalDof] = - periodicDofMap[feSpace][*perAscIt][globalDof]; - } + periodicMap.map(feSpace, *perAscIt, globalDof); } } @@ -2172,19 +2165,12 @@ namespace AMDiS { stdMpi2.startCommunication(); for (map<int, PeriodicDofMap>::iterator it = stdMpi2.getRecvData().begin(); - it != stdMpi2.getRecvData().end(); ++it) { + it != stdMpi2.getRecvData().end(); ++it) for (PeriodicDofMap::iterator perIt = it->second.begin(); - perIt != it->second.end(); ++perIt) { + perIt != it->second.end(); ++perIt) for (DofMapping::iterator dofIt = perIt->second.begin(); - dofIt != perIt->second.end(); ++dofIt) { - TEST_EXIT_DBG(periodicDofMap[feSpace][perIt->first].count(dofIt->second) == 0 || - periodicDofMap[feSpace][perIt->first][dofIt->second] == dofIt->first) - ("Should not happen!\n"); - - periodicDofMap[feSpace][perIt->first][dofIt->second] = dofIt->first; - } - } - } + dofIt != perIt->second.end(); ++dofIt) + periodicMap.add(feSpace, perIt->first, dofIt->second, dofIt->first); } @@ -2275,11 +2261,7 @@ namespace AMDiS { SerUtil::serialize(out, dofFeData[feSpaces[i]].mapLocalDofIndex); } - for (unsigned int i = 0; i < nFeSpace; i++) - serialize(out, periodicDofMap[feSpaces[i]]); - - for (unsigned int i = 0; i < nFeSpace; i++) - serialize(out, periodicDofAssociations[feSpaces[i]]); + periodicMap.serialize(out, feSpaces); SerUtil::serialize(out, macroElementNeighbours); @@ -2352,12 +2334,7 @@ namespace AMDiS { SerUtil::deserialize(in, dofFeData[feSpaces[i]].mapLocalDofIndex); } - - for (unsigned int i = 0; i < nFeSpace; i++) - deserialize(in, periodicDofMap[feSpaces[i]]); - - for (unsigned int i = 0; i < nFeSpace; i++) - deserialize(in, periodicDofAssociations[feSpaces[i]]); + periodicMap.deserialize(in, feSpaces); SerUtil::deserialize(in, macroElementNeighbours); @@ -2379,73 +2356,4 @@ namespace AMDiS { deserialized = true; } - - void MeshDistributor::serialize(ostream &out, PeriodicDofMap &data) - { - int mapSize = data.size(); - SerUtil::serialize(out, mapSize); - - for (PeriodicDofMap::iterator it = data.begin(); it != data.end(); ++it) { - int type = it->first; - DofMapping dofMap = it->second; - - SerUtil::serialize(out, type); - SerUtil::serialize(out, dofMap); - } - } - - - void MeshDistributor::serialize(ostream &out, map<int, std::set<int> >& data) - { - int mapSize = data.size(); - SerUtil::serialize(out, mapSize); - - for (map<int, std::set<int> >::iterator it = data.begin(); it != data.end(); ++it) { - int dof = it->first; - std::set<int> typeSet = it->second; - - SerUtil::serialize(out, dof); - SerUtil::serialize(out, typeSet); - } - } - - - void MeshDistributor::deserialize(istream &in, PeriodicDofMap &data) - { - data.clear(); - - int mapSize = 0; - SerUtil::deserialize(in, mapSize); - - for (int i = 0; i < mapSize; i++) { - int type; - DofMapping dofMap; - - SerUtil::deserialize(in, type); - SerUtil::deserialize(in, dofMap); - - data[type] = dofMap; - } - } - - - void MeshDistributor::deserialize(istream &in, - map<int, std::set<int> >& data) - { - data.clear(); - - int mapSize = 0; - SerUtil::deserialize(in, mapSize); - - for (int i = 0; i < mapSize; i++) { - int dof; - std::set<int> typeSet; - - SerUtil::deserialize(in, dof); - SerUtil::deserialize(in, typeSet); - - data[dof] = typeSet; - } - } - } diff --git a/AMDiS/src/parallel/MeshDistributor.h b/AMDiS/src/parallel/MeshDistributor.h index 8953f16b022e47b47c61e1d0ea085365b943cb85..9fd7cb286f45dd857215a257bc9b556b8e7f9865 100644 --- a/AMDiS/src/parallel/MeshDistributor.h +++ b/AMDiS/src/parallel/MeshDistributor.h @@ -30,6 +30,7 @@ #include "parallel/ParallelTypes.h" #include "parallel/MeshPartitioner.h" #include "parallel/InteriorBoundary.h" +#include "parallel/PeriodicMap.h" #include "parallel/StdMpi.h" #include "AMDiS_fwd.h" #include "Global.h" @@ -277,58 +278,10 @@ namespace AMDiS { return dofFeData[feSpace].mapLocalDofIndex[dof]; } - /// Returns the periodic mapping for all boundary DOFs in rank. - inline PeriodicDofMap& getPeriodicMapping(const FiniteElemSpace *feSpace) + /// Returns the periodic mapping handler, \ref periodicMap. + inline PeriodicMap& getPeriodicMap() { - return periodicDofMap[feSpace]; - } - - /// Returns for a global DOF index of a given FE space its periodic mapping - /// for a given boundary type. - inline int getPeriodicMapping(const FiniteElemSpace *feSpace, - BoundaryType type, - int globalDofIndex) - { - FUNCNAME("MeshDistributor::getPeriodicMapping()"); - - TEST_EXIT_DBG(periodicDofMap.count(feSpace))("Should not happen!\n"); - TEST_EXIT_DBG(periodicDofMap[feSpace][type].count(globalDofIndex) == 1) - ("There is no periodic association for global DOF %d for boundary type %d!\n", - globalDofIndex, type); - - return periodicDofMap[feSpace][type][globalDofIndex]; - } - - /// For a given global DOF index, this function returns the set of periodic - /// associations, i.e., the boundary types the DOF is associated to, for - /// this DOF. - inline std::set<BoundaryType>& getPerDofAssociations(const FiniteElemSpace* feSpace, - int globalDofIndex) - { - FUNCNAME("MeshDistributor::getPerDofAssociations()"); - - TEST_EXIT_DBG(periodicDofAssociations.count(feSpace)) - ("Should not happen!\n"); - TEST_EXIT_DBG(periodicDofAssociations[feSpace].count(globalDofIndex)) - ("Should not happen!\n"); - - return periodicDofAssociations[feSpace][globalDofIndex]; - } - - /// Returns true, if the DOF (global index) is a periodic DOF. - inline bool isPeriodicDof(const FiniteElemSpace *feSpace, int globalDofIndex) - { - return (periodicDofAssociations[feSpace].count(globalDofIndex) > 0 && - periodicDofAssociations[feSpace][globalDofIndex].size() > 0); - } - - /// Returns true, if the DOF (global index) of a given FE space is a - /// periodic DOF for the given boundary type. - inline bool isPeriodicDof(const FiniteElemSpace *feSpace, - BoundaryType type, - int globalDofIndex) - { - return (periodicDofMap[feSpace][type].count(globalDofIndex) > 0); + return periodicMap; } DofComm& getSendDofs() @@ -556,16 +509,6 @@ namespace AMDiS { map<int, map<const FiniteElemSpace*, DofContainer> > &data, map<const FiniteElemSpace*, map<int, const DegreeOfFreedom*> > &dofMap); - /// Writes a periodic dof mapping to an output stream. - void serialize(ostream &out, PeriodicDofMap &data); - - void serialize(ostream &out, map<int, std::set<int> >& data); - - /// Reads a periodic dof mapping from an input stream. - void deserialize(istream &in, PeriodicDofMap &data); - - void deserialize(istream &in, map<int, std::set<int> >& data); - /// Writes a mapping from dof pointers to some values to an output stream. template<typename T> void serialize(ostream &out, map<const DegreeOfFreedom*, T> &data) @@ -710,24 +653,8 @@ namespace AMDiS { */ DofComm periodicDofs; - /** \brief - * If periodic boundaries are used, this map stores, for each periodic - * boundary type, for all DOFs in rank's partition (that are on periodic - * boundaries), the corresponding mapped periodic DOFs. The mapping is - * defined by using global DOF indices. - */ - PeriodicDofMapFeSpace periodicDofMap; - - /** \brief - * If periodic boundaries are used, this map stores to each periodic DOF in - * rank's partition the set of periodic boundaries the DOF is associated to. - * In 2D, most DOFs are only on one periodic boundary. Only, e.g., in a box - * with all boundaries being periodic, the four corners are associated by - * two different boundaries. - */ - map<const FiniteElemSpace*, map<DegreeOfFreedom, std::set<BoundaryType> > > periodicDofAssociations; + PeriodicMap periodicMap; - /// This set of values must be interchanged between ranks when the mesh is /// repartitioned. vector<DOFVector<double>*> interchangeVectors; diff --git a/AMDiS/src/parallel/ParallelDebug.cc b/AMDiS/src/parallel/ParallelDebug.cc index 7bda65f6a96f26a3e63e8e0989f71b1000988b25..751224e98ca791a99fda386c5c76533548ab3b93 100644 --- a/AMDiS/src/parallel/ParallelDebug.cc +++ b/AMDiS/src/parallel/ParallelDebug.cc @@ -157,9 +157,11 @@ namespace AMDiS { // === 1. check: All periodic DOFs should have at least a correct number === // === of periodic associations. === - - for (map<int, std::set<BoundaryType> >::iterator it = pdb.periodicDofAssociations[feSpace].begin(); - it != pdb.periodicDofAssociations[feSpace].end(); ++it) { + + PeriodicMap &perMap = pdb.getPeriodicMap(); + for (map<int, std::set<BoundaryType> >::iterator it = + perMap.periodicDofAssociations[feSpace].begin(); + it != perMap.periodicDofAssociations[feSpace].end(); ++it) { WorldVector<double> c; pdb.mesh->getDofIndexCoords(it->first, pdb.feSpaces[0], c); int nAssoc = it->second.size(); @@ -178,7 +180,7 @@ namespace AMDiS { for (int i = 1; i < pdb.mpiSize; i++) stdMpi.recv(i); } else { - stdMpi.send(0, pdb.periodicDofMap[feSpace]); + stdMpi.send(0, perMap.periodicDofMap[feSpace]); } stdMpi.startCommunication(); @@ -190,7 +192,7 @@ namespace AMDiS { if (pdb.mpiRank == 0) { // Stores to each rank the periodic DOF mappings of this rank. map<int, PeriodicDofMap> rankToMaps; - PeriodicDofMap dofMap = pdb.periodicDofMap[feSpace]; + PeriodicDofMap dofMap = perMap.periodicDofMap[feSpace]; rankToMaps[0] = dofMap; for (int i = 1; i < pdb.mpiSize; i++) { @@ -678,6 +680,8 @@ namespace AMDiS { ERROR_EXIT("Function must be rewritten!\n"); #if 0 + PeriodicMap &perMap = pdb.getPeriodicMap(); + const FiniteElemSpace* feSpace = pdb.feSpaces[0]; typedef map<DegreeOfFreedom, DegreeOfFreedom> DofMapping; @@ -686,8 +690,8 @@ namespace AMDiS { if (rank == -1 || pdb.mpiRank == rank) { cout << "====== DOF MAP PERIODIC ====== " << endl; - for (PeriodicDofMap::iterator it = pdb.periodicDofMap.begin(); - it != pdb.periodicDofMap.end(); ++it) { + for (PeriodicDofMap::iterator it = perMap.periodicDofMap.begin(); + it != perMap.periodicDofMap.end(); ++it) { cout << "DOF MAP " << it->first << ": "; for (std::set<DegreeOfFreedom>::iterator dofit = it->second.begin(); dofit != it->second.end(); ++dofit) diff --git a/AMDiS/src/parallel/ParallelTypes.h b/AMDiS/src/parallel/ParallelTypes.h index f96734ea2eeb7dee3e4734816fa8341a362f0e45..4f85959ce920df8ab7bbfa8c87da449595c257b4 100644 --- a/AMDiS/src/parallel/ParallelTypes.h +++ b/AMDiS/src/parallel/ParallelTypes.h @@ -62,12 +62,6 @@ namespace AMDiS { typedef map<const DegreeOfFreedom*, DegreeOfFreedom> DofIndexMap; - /// Mapps a boundar type, i.e., a boundary identifier index, to a periodic - /// DOF mapping. - typedef map<BoundaryType, DofMapping> PeriodicDofMap; - - typedef map<const FiniteElemSpace*, PeriodicDofMap> PeriodicDofMapFeSpace; - typedef vector<MeshStructure> MeshCodeVec; } diff --git a/AMDiS/src/parallel/PeriodicMap.cc b/AMDiS/src/parallel/PeriodicMap.cc new file mode 100644 index 0000000000000000000000000000000000000000..78f8ccb55f8e6450f806701219eff40f8ec9003f --- /dev/null +++ b/AMDiS/src/parallel/PeriodicMap.cc @@ -0,0 +1,116 @@ +// +// Software License for AMDiS +// +// Copyright (c) 2010 Dresden University of Technology +// All rights reserved. +// Authors: Simon Vey, Thomas Witkowski et al. +// +// This file is part of AMDiS +// +// See also license.opensource.txt in the distribution. + + +#include <fstream> +#include "parallel/PeriodicMap.h" + +namespace AMDiS { + + void PeriodicMap::serialize(ostream &out, + vector<const FiniteElemSpace*> feSpaces) + { + FUNCNAME("PeriodicMap::serialize()"); + + int nFeSpace = static_cast<int>(feSpaces.size()); + + for (int i = 0; i < nFeSpace; i++) + serialize(out, periodicDofMap[feSpaces[i]]); + + for (int i = 0; i < nFeSpace; i++) + serialize(out, periodicDofAssociations[feSpaces[i]]); + } + + + void PeriodicMap::deserialize(istream &in, + vector<const FiniteElemSpace*> feSpaces) + { + FUNCNAME("PeriodicMap::deserialize()"); + + int nFeSpace = static_cast<int>(feSpaces.size()); + + for (int i = 0; i < nFeSpace; i++) + deserialize(in, periodicDofMap[feSpaces[i]]); + + for (int i = 0; i < nFeSpace; i++) + deserialize(in, periodicDofAssociations[feSpaces[i]]); + } + + + void PeriodicMap::serialize(ostream &out, PeriodicDofMap &data) + { + int mapSize = data.size(); + SerUtil::serialize(out, mapSize); + + for (PeriodicDofMap::iterator it = data.begin(); it != data.end(); ++it) { + int type = it->first; + DofMapping dofMap = it->second; + + SerUtil::serialize(out, type); + SerUtil::serialize(out, dofMap); + } + } + + + void PeriodicMap::serialize(ostream &out, std::map<int, std::set<int> >& data) + { + int mapSize = data.size(); + SerUtil::serialize(out, mapSize); + + for (std::map<int, std::set<int> >::iterator it = data.begin(); + it != data.end(); ++it) { + int dof = it->first; + std::set<int> typeSet = it->second; + + SerUtil::serialize(out, dof); + SerUtil::serialize(out, typeSet); + } + } + + + void PeriodicMap::deserialize(istream &in, PeriodicDofMap &data) + { + data.clear(); + + int mapSize = 0; + SerUtil::deserialize(in, mapSize); + + for (int i = 0; i < mapSize; i++) { + int type; + DofMapping dofMap; + + SerUtil::deserialize(in, type); + SerUtil::deserialize(in, dofMap); + + data[type] = dofMap; + } + } + + + void PeriodicMap::deserialize(istream &in, std::map<int, std::set<int> >& data) + { + data.clear(); + + int mapSize = 0; + SerUtil::deserialize(in, mapSize); + + for (int i = 0; i < mapSize; i++) { + int dof; + std::set<int> typeSet; + + SerUtil::deserialize(in, dof); + SerUtil::deserialize(in, typeSet); + + data[dof] = typeSet; + } + } + +} diff --git a/AMDiS/src/parallel/PeriodicMap.h b/AMDiS/src/parallel/PeriodicMap.h new file mode 100644 index 0000000000000000000000000000000000000000..a6204b4b550a9f80297caaf4105bf68e275aab4f --- /dev/null +++ b/AMDiS/src/parallel/PeriodicMap.h @@ -0,0 +1,181 @@ +// ============================================================================ +// == == +// == AMDiS - Adaptive multidimensional simulations == +// == == +// == http://www.amdis-fem.org == +// == == +// ============================================================================ +// +// Software License for AMDiS +// +// Copyright (c) 2010 Dresden University of Technology +// All rights reserved. +// Authors: Simon Vey, Thomas Witkowski et al. +// +// This file is part of AMDiS +// +// See also license.opensource.txt in the distribution. + + + +/** file PeriodicMap.h */ + +#ifndef AMDIS_PERIODIC_MAP +#define AMDIS_PERIODIC_MAP + +#include <map> +#include <set> +#include <vector> +#include "parallel/ParallelTypes.h" +#include "Boundary.h" +#include "Serializer.h" + +namespace AMDiS { + + /// Maps a boundary type, i.e., a boundary identifier index, to a periodic + /// DOF mapping. + typedef std::map<BoundaryType, DofMapping> PeriodicDofMap; + + /// Different FE spaces may have different DOFs on the same mesh. Thus we + /// need to have a periodic DOF mapping for each FE space. + typedef std::map<const FiniteElemSpace*, PeriodicDofMap> PeriodicDofMapFeSpace; + + + /** \brief + * This class stores information about the periodic DOFs in the (sub)domain. + * To each DOF on a periodic boundary there is the information to which DOF + * is is periodic. Here we use global DOF indices. Furtheremore, a DOF can have + * different periodic mapping. Assume we have a 2D box with all four edges + * being periodic. Than, the four corner vertices have all two periodic + * mapping. So, a periodic mapping is identified by the global DOF index to be + * mapped and the boundary index. + */ + class PeriodicMap { + public: + PeriodicMap() {} + + void clear() + { + periodicDofMap.clear(); + periodicDofAssociations.clear(); + } + + + inline PeriodicDofMap& getPeriodicMap(const FiniteElemSpace *feSpace) + { + return periodicDofMap[feSpace]; + } + + + inline int map(const FiniteElemSpace *feSpace, + BoundaryType type, + int globalDofIndex) + { + FUNCNAME("PeriodicMap::map()"); + + TEST_EXIT_DBG(periodicDofMap.count(feSpace))("Should not happen!\n"); + TEST_EXIT_DBG(periodicDofMap[feSpace][type].count(globalDofIndex) == 1) + ("There is no periodic association for global DOF %d for boundary type %d!\n", + globalDofIndex, type); + + return periodicDofMap[feSpace][type][globalDofIndex]; + } + + + inline void add(const FiniteElemSpace *feSpace, + BoundaryType type, + DegreeOfFreedom dof0, DegreeOfFreedom dof1) + { + FUNCNAME("PeriodicMap::map()"); + + TEST_EXIT_DBG(periodicDofMap[feSpace][type].count(dof0) == 0 || + periodicDofMap[feSpace][type][dof0] == dof1) + ("Should not happen!\n"); + + periodicDofMap[feSpace][type][dof0] = dof1; + periodicDofAssociations[feSpace][dof0].insert(type); + } + + + /// For a given global DOF index, this function returns the set of periodic + /// associations, i.e., the boundary types the DOF is associated to, for + /// this DOF. + inline std::set<BoundaryType>& getAssociations(const FiniteElemSpace* feSpace, + int globalDofIndex) + { + FUNCNAME("PeriodicMap::getAssociations()"); + + TEST_EXIT_DBG(periodicDofAssociations.count(feSpace)) + ("Should not happen!\n"); + TEST_EXIT_DBG(periodicDofAssociations[feSpace].count(globalDofIndex)) + ("Should not happen!\n"); + + return periodicDofAssociations[feSpace][globalDofIndex]; + } + + + /// Returns true, if the DOF (global index) is a periodic DOF. + inline bool isPeriodic(const FiniteElemSpace *feSpace, int globalDofIndex) + { + return (periodicDofAssociations[feSpace].count(globalDofIndex) > 0 && + periodicDofAssociations[feSpace][globalDofIndex].size() > 0); + } + + + inline bool isPeriodicOnBound(const FiniteElemSpace *feSpace, + BoundaryType type, + int globalDofIndex) + { + return periodicDofAssociations[feSpace][globalDofIndex].count(type); + } + + + /// Returns true, if the DOF (global index) of a given FE space is a + /// periodic DOF for the given boundary type. + inline bool isPeriodic(const FiniteElemSpace *feSpace, + BoundaryType type, + int globalDofIndex) + { + return (periodicDofMap[feSpace][type].count(globalDofIndex) > 0); + } + + /// Write the state of the object to serialization file. + void serialize(std::ostream &out, + vector<const FiniteElemSpace*> feSpaces); + + /// Read the state of the object from serialization file. + void deserialize(std::istream &in, + vector<const FiniteElemSpace*> feSpaces); + + private: + /// Write \ref periodicDofMap to serialization file. + void serialize(std::ostream &out, PeriodicDofMap &data); + + /// Write \ref periodicDofAssociations to serialization file + void serialize(std::ostream &out, std::map<int, std::set<int> >& data); + + /// Read \ref periodicDofMap from serialization file. + void deserialize(std::istream &in, PeriodicDofMap &data); + + /// Read \ref periodicDofAssociations from serialization file. + void deserialize(std::istream &in, std::map<int, std::set<int> >& data); + + + private: + /// This map stores, for each FE space, a mapping from boundary indices + /// to DOF mappings. So, if an FE space and a boundary index is provided, + /// we eventually get a mapping from global DOF indices to global DOF + /// indices. + PeriodicDofMapFeSpace periodicDofMap; + + /// This map stores to each periodic DOF the set of periodic boundaries the + /// DOF is associated to. In 2D, most DOFs are only on one periodic boundary. + // Only, e.g., in a box with all boundaries being periodic, the four corners + /// are associated by two different boundaries. + std::map<const FiniteElemSpace*, std::map<DegreeOfFreedom, std::set<BoundaryType> > > periodicDofAssociations; + + friend class ParallelDebug; + }; +} + +#endif diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc index 02840c8c80c739413f28e37a4feb2e920a4db475..feb95913e353afb458bcd9b4af234d0a688cc127 100644 --- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc +++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc @@ -217,6 +217,9 @@ namespace AMDiS { vector<int> globalCols; + // Get periodic mapping object + PeriodicMap &perMap = meshDistributor->getPeriodicMap(); + // === Traverse all rows of the dof matrix and insert row wise the values === // === to the PETSc matrix. === @@ -230,7 +233,7 @@ namespace AMDiS { int globalRowDof = meshDistributor->mapLocalToGlobal(rowFe, *cursor); // Test if the current row DOF is a periodic DOF. - bool periodicRow = meshDistributor->isPeriodicDof(rowFe, globalRowDof); + bool periodicRow = perMap.isPeriodic(rowFe, globalRowDof); if (!periodicRow) { // === Row DOF index is not periodic. === @@ -248,7 +251,7 @@ namespace AMDiS { int globalColDof = meshDistributor->mapLocalToGlobal(colFe, col(*icursor)); // Test if the current col dof is a periodic dof. - bool periodicCol = meshDistributor->isPeriodicDof(colFe, globalColDof); + bool periodicCol = perMap.isPeriodic(colFe, globalColDof); // Get PETSc's mat col index. int colIndex = dofToMatIndex.get(dispAddCol, globalColDof); @@ -265,8 +268,7 @@ namespace AMDiS { // Create set of all periodic associations of the column index. std::set<int> perAsc; - std::set<int>& perColAsc = - meshDistributor->getPerDofAssociations(colFe, globalColDof); + std::set<int>& perColAsc = perMap.getAssociations(colFe, globalColDof); for (std::set<int>::iterator it = perColAsc.begin(); it != perColAsc.end(); ++it) if (*it >= -3) @@ -291,11 +293,11 @@ namespace AMDiS { int nCols = static_cast<int>(newCols.size()); for (int i = 0; i < nCols; i++) { - TEST_EXIT_DBG(meshDistributor->isPeriodicDof(colFe, *it, newCols[i])) + TEST_EXIT_DBG(perMap.isPeriodic(colFe, *it, newCols[i])) ("Wrong periodic DOF associations at boundary %d with DOF %d!\n", *it, newCols[i]); - newCols.push_back(meshDistributor->getPeriodicMapping(colFe, *it, newCols[i])); + newCols.push_back(perMap.map(colFe, *it, newCols[i])); } } @@ -336,17 +338,15 @@ namespace AMDiS { std::set<int> perAsc; - if (meshDistributor->isPeriodicDof(colFe, globalColDof)) { - std::set<int>& perColAsc = - meshDistributor->getPerDofAssociations(colFe, globalColDof); + if (perMap.isPeriodic(colFe, globalColDof)) { + std::set<int>& perColAsc = perMap.getAssociations(colFe, globalColDof); for (std::set<int>::iterator it = perColAsc.begin(); it != perColAsc.end(); ++it) if (*it >= -3) perAsc.insert(*it); } - std::set<int>& perRowAsc = - meshDistributor->getPerDofAssociations(rowFe, globalRowDof); + std::set<int>& perRowAsc = perMap.getAssociations(rowFe, globalRowDof); for (std::set<int>::iterator it = perRowAsc.begin(); it != perRowAsc.end(); ++it) if (*it >= -3) @@ -372,14 +372,14 @@ namespace AMDiS { for (int i = 0; i < nEntry; i++) { int perRowDof = 0; - if (meshDistributor->isPeriodicDof(rowFe, *it, entry[i].first)) - perRowDof = meshDistributor->getPeriodicMapping(rowFe, *it, entry[i].first); + if (perMap.isPeriodic(rowFe, *it, entry[i].first)) + perRowDof = perMap.map(rowFe, *it, entry[i].first); else perRowDof = entry[i].first; int perColDof; - if (meshDistributor->isPeriodicDof(colFe, *it, entry[i].second)) - perColDof = meshDistributor->getPeriodicMapping(colFe, *it, entry[i].second); + if (perMap.isPeriodic(colFe, *it, entry[i].second)) + perColDof = perMap.map(colFe, *it, entry[i].second); else perColDof = entry[i].second; @@ -426,6 +426,7 @@ namespace AMDiS { FUNCNAME("PetscSolverGlobalMatrix::setDofVector()"); const FiniteElemSpace *feSpace = vec->getFeSpace(); + PeriodicMap &perMap = meshDistributor->getPeriodicMap(); // Traverse all used DOFs in the dof vector. DOFVector<double>::Iterator dofIt(vec, USED_DOFS); @@ -439,15 +440,14 @@ namespace AMDiS { // Get PETSc's mat index of the row DOF. int index = dofToMatIndex.get(dispAdd, globalRowDof); - if (meshDistributor->isPeriodicDof(feSpace, globalRowDof)) { - std::set<int>& perAsc = - meshDistributor->getPerDofAssociations(feSpace, globalRowDof); + if (perMap.isPeriodic(feSpace, globalRowDof)) { + std::set<int>& perAsc = perMap.getAssociations(feSpace, globalRowDof); double value = *dofIt / (perAsc.size() + 1.0); VecSetValues(petscVec, 1, &index, &value, ADD_VALUES); - for (std::set<int>::iterator perIt = perAsc.begin(); perIt != perAsc.end(); ++perIt) { - int mappedDof = - meshDistributor->getPeriodicMapping(feSpace, *perIt, globalRowDof); + for (std::set<int>::iterator perIt = perAsc.begin(); + perIt != perAsc.end(); ++perIt) { + int mappedDof = perMap.map(feSpace, *perIt, globalRowDof); int mappedIndex = dofToMatIndex.get(dispAdd, mappedDof); VecSetValues(petscVec, 1, &mappedIndex, &value, ADD_VALUES); } diff --git a/AMDiS/src/parallel/StdMpi.h b/AMDiS/src/parallel/StdMpi.h index 9ed7a75a37b59181aa630818f8dec3f03d841523..33d7c94d1e876268fcce22727d13dbc8b19296ff 100644 --- a/AMDiS/src/parallel/StdMpi.h +++ b/AMDiS/src/parallel/StdMpi.h @@ -166,7 +166,7 @@ namespace AMDiS { }; - // MeshDistributor::PeriodicDofMap + // PeriodicMap::PeriodicDofMap template<> struct StdMpiHelper<map<BoundaryType, map<DegreeOfFreedom, DegreeOfFreedom> > > { static MPI_Datatype mpiDataType;