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;