diff --git a/AMDiS/cmake3/CMakeLists.txt b/AMDiS/cmake3/CMakeLists.txt
index 11d5a09ec054cf44b7a41421be783ca0833fdd1c..6c8ad2b11871772f277166100023a82efd9810db 100644
--- a/AMDiS/cmake3/CMakeLists.txt
+++ b/AMDiS/cmake3/CMakeLists.txt
@@ -72,6 +72,7 @@ add_library(amdis
     ${SOURCE_DIR}/DOFAdmin.cc
     ${SOURCE_DIR}/DOFIndexed.cc
     ${SOURCE_DIR}/DOFMatrix.cc
+    ${SOURCE_DIR}/DOFSerializer.cc
     ${SOURCE_DIR}/DOFVector.cc
     ${SOURCE_DIR}/DirichletBC.cc
     ${SOURCE_DIR}/DualTraverse.cc
diff --git a/AMDiS/cmake3/target_enable_boost.cmake b/AMDiS/cmake3/target_enable_boost.cmake
index 5c41b01100c6d2f374298dcf47bc53ac51a0e2a3..cdf5f05bb817750dd4d69c80e604c0958da804ea 100644
--- a/AMDiS/cmake3/target_enable_boost.cmake
+++ b/AMDiS/cmake3/target_enable_boost.cmake
@@ -13,7 +13,7 @@ macro(target_enable_boost _TARGET_ _SCOPE_)
     endif (BOOST_LIBRARYDIR)
 
     set(BOOST_VERSION "1.48")
-    set(BOOST_LIBS_REQUIRED system iostreams filesystem program_options date_time thread)
+    set(BOOST_LIBS_REQUIRED system iostreams filesystem program_options date_time)
     if (WIN32)
       list(APPEND BOOST_LIBS_REQUIRED zlib)
       if (ENABLE_COMPRESSION OR AMDIS_NEED_COMPRESSION)
diff --git a/AMDiS/src/DOFAdmin.h b/AMDiS/src/DOFAdmin.h
index 4583f00339aa0fd45c16a2c4132c3896363d6464..1a148267202738362b15465dc231e70fa2501be3 100644
--- a/AMDiS/src/DOFAdmin.h
+++ b/AMDiS/src/DOFAdmin.h
@@ -182,6 +182,12 @@ namespace AMDiS {
       return mesh;
     }
 
+    /// Returns \ref mesh
+    inline Mesh* getMesh()
+    {
+      return mesh;
+    }
+
     /// Returns \ref dofFree, the array denoting DOFs to be either free or used.
     inline const std::vector<bool>& getDofFree() const
     {
diff --git a/AMDiS/src/DOFSerializer.cc b/AMDiS/src/DOFSerializer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4f93377f1444b95a878426d1f2431c120ec47d25
--- /dev/null
+++ b/AMDiS/src/DOFSerializer.cc
@@ -0,0 +1,129 @@
+#include "DOFSerializer.h"
+
+#include <algorithm>
+
+#include "DOFVector.h"
+#include "Global.h"
+#include "Traverse.h"
+
+namespace AMDiS
+{    
+    
+// satre values of DOFVector on all macro elements to internal container
+void DOFSerializer::gather(DOFVector<double> const* vec, std::vector<double>& values)
+{
+  std::fill(visited_.begin(), visited_.end(), false);
+  values.clear();
+    
+  for (auto* macroEl : mesh_->getMacroElements())
+    gather(macroEl->getIndex(), vec, values, false);
+}
+
+
+// satre values of DOFVector on macro element `macroIndex` to internal container
+void DOFSerializer::gather(int macroIndex, DOFVector<double> const* vec, std::vector<double>& values, bool reset)
+{
+  if (reset) {
+    std::fill(visited_.begin(), visited_.end(), false);
+    values.clear();
+  }
+  
+  TraverseStack stack;
+  ElInfo *elInfo = stack.traverseFirstOneMacro(mesh_, macroIndex, -1, Mesh::CALL_EVERY_EL_PREORDER);
+  while (elInfo) {
+    Element *el = elInfo->getElement();
+    
+    if (el->isLeaf()) {
+      gather(VERTEX, elInfo, vec, values);
+      if (mesh_->getDim() > 1)
+        gather(EDGE, elInfo, vec, values);
+      if (mesh_->getDim() == 3)
+        gather(FACE, elInfo, vec, values);
+      gather(CENTER, elInfo, vec, values);
+    }
+    
+    elInfo = stack.traverseNext(elInfo);
+  }
+}
+
+
+void DOFSerializer::gather(GeoIndex geo, ElInfo* elInfo, DOFVector<double> const* vec, std::vector<double>& values) 
+{
+  int nd;
+  if ((nd = admin_->getNumberOfDofs(geo)))  {
+    int vertices = mesh_->getGeo(geo);
+    int nd0 = admin_->getNumberOfPreDofs(geo);
+    int n0 = mesh_->getNode(geo);
+    for (int n = 0; n < vertices; n++) {
+      for(int d = 0; d < nd; d++) {
+        DegreeOfFreedom globalDof = elInfo->getElement()->getDof(n0 + n, nd0 + d);
+        if (!visited_[globalDof]) {
+          visited_[globalDof] = true;
+          values.push_back((*vec)[globalDof]);
+        }
+      }
+    }
+  }
+}
+
+
+// assign stored values to DOFVector, for all macro elements
+void DOFSerializer::scatter(std::vector<double> const& values, DOFVector<double>* vec) const
+{
+  std::fill(visited_.begin(), visited_.end(), false);
+  counter_ = 0u;
+    
+  for (auto* macroEl : mesh_->getMacroElements())
+    scatter(macroEl->getIndex(), values, vec, false);
+}
+
+
+// assign stored values to DOFVector, on macroElement with index `macroIndex`
+void DOFSerializer::scatter(int macroIndex, std::vector<double> const& values, DOFVector<double>* vec, bool reset) const
+{    
+  if (reset) {
+    std::fill(visited_.begin(), visited_.end(), false);
+    counter_ = 0u;
+  }
+  
+  TraverseStack stack;
+  ElInfo *elInfo = stack.traverseFirstOneMacro(mesh_, macroIndex, -1, Mesh::CALL_EVERY_EL_PREORDER);
+  while (elInfo) {
+    Element *el = elInfo->getElement();
+    
+    if (el->isLeaf()) {
+      scatter(VERTEX, elInfo, values, vec);
+      if (mesh_->getDim() > 1)
+        scatter(EDGE, elInfo, values, vec);
+      if (mesh_->getDim() == 3)
+        scatter(FACE, elInfo, values, vec);
+      scatter(CENTER, elInfo, values, vec);
+    }
+    
+    elInfo = stack.traverseNext(elInfo);
+  }
+}
+
+
+void DOFSerializer::scatter(GeoIndex geo, ElInfo* elInfo, std::vector<double> const& values, DOFVector<double>* vec) const
+{
+  int nd;
+  if ((nd = admin_->getNumberOfDofs(geo)))  {
+    int vertices = mesh_->getGeo(geo);
+    int nd0 = admin_->getNumberOfPreDofs(geo);
+    int n0 = mesh_->getNode(geo);
+    for (int n = 0; n < vertices; n++) {
+      for(int d = 0; d < nd; d++) {
+        DegreeOfFreedom globalDof = elInfo->getElement()->getDof(n0 + n, nd0 + d);
+        if (!visited_[globalDof]) {
+          visited_[globalDof] = true;
+          assert( values.size() < counter_);
+          (*vec)[globalDof] = values[counter_++];
+        }
+      }
+    }
+  }
+}
+
+
+} // end namespace AMDiS
diff --git a/AMDiS/src/DOFSerializer.h b/AMDiS/src/DOFSerializer.h
new file mode 100644
index 0000000000000000000000000000000000000000..3327c4562e3ab1eb349f9dfc9d5e4d2aeea7ac35
--- /dev/null
+++ b/AMDiS/src/DOFSerializer.h
@@ -0,0 +1,91 @@
+/******************************************************************************
+ *
+ * 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 DOFSerializer.h */
+
+#ifndef AMDIS_DOFSERIALIZER_H
+#define AMDIS_DOFSERIALIZER_H
+
+#include <vector>
+#include <algorithm>
+
+#include "DOFAdmin.h"
+#include "ElInfo.h"
+#include "Global.h"
+#include "Mesh.h"
+#include "Traverse.h"
+
+namespace AMDiS
+{
+  // Collect all DOFValues into a std::vector, by traversing the mesh macro-elenment wise
+  // Can be used to transfer data on macro elements or to store values in a file, e.g. in ARHWriter
+  class DOFSerializer
+  {
+  public:
+    
+    /// Constructor, stores a pointer to the DOFAdmin. If the number of values to store can be estimated,
+    /// pass a second argument `numValues`
+    DOFSerializer(DOFAdmin* admin, std::size_t numValues = 0)
+      : admin_(admin)
+      , mesh_(admin->getMesh())
+      , visited_(admin->getUsedSize(), false)
+    {}
+    
+    
+    // satre values of DOFVector on all macro elements to internal container
+    void gather(DOFVector<double> const* vec, std::vector<double>& values);
+    
+    // satre values of DOFVector on macro element `macroIndex` to internal container
+    void gather(int macroIndex, DOFVector<double> const* vec, std::vector<double>& values, bool reset = true);
+    
+    
+    // assign stored values to DOFVector, for all macro elements
+    void scatter(std::vector<double> const& values, DOFVector<double>* vec) const;
+    
+    // assign stored values to DOFVector, on macroElement with index `macroIndex`
+    void scatter(int macroIndex, std::vector<double> const& values, DOFVector<double>* vec, bool reset = true) const;
+
+      
+  protected:
+    
+    // collect values of one geometry-type
+    void gather(GeoIndex geo, ElInfo* elInfo, DOFVector<double> const* vec, std::vector<double>& values);
+    
+    // assign values of one geometry type
+    void scatter(GeoIndex geo, ElInfo* elInfo, std::vector<double> const& values, DOFVector<double>* vec) const;
+    
+    
+  protected:
+    
+    DOFAdmin* admin_;
+    Mesh* mesh_;
+    
+    // stored which DOFs were already visited during traversal
+    mutable std::vector<bool> visited_;
+    
+    // a counter used during assignment of values. To guarantee the same order as during gather
+    mutable std::size_t counter_ = 0u;
+  };
+
+} // end namespace AMDiS
+
+#endif // AMDIS_DOFSERIALIZER_H
diff --git a/AMDiS/src/DualTraverse.cc b/AMDiS/src/DualTraverse.cc
index 8a90e6445a9678acd58ce54474d8800d46adc512..32932afe04263ccce0ca5f26f1f9e56ba77a10ea 100644
--- a/AMDiS/src/DualTraverse.cc
+++ b/AMDiS/src/DualTraverse.cc
@@ -111,6 +111,93 @@ namespace AMDiS {
   }
 
 
+  bool DualTraverse::traverseFirstOneMacro(Mesh *mesh1,
+				   Mesh *mesh2,
+                                   int macroIndex,
+				   int level1,
+				   int level2,
+				   Flag flag1,
+				   Flag flag2,
+				   ElInfo **elInfo1,
+				   ElInfo **elInfo2,
+				   ElInfo **elInfoSmall,
+				   ElInfo **elInfoLarge)
+  {
+    FUNCNAME("DualTraverse::traverseFirst()");
+    // replace CALL_EL_LEVEL by CALL_MG_LEVEL (covers whole domain)
+    if (flag1.isSet(Mesh::CALL_EL_LEVEL)) {
+      flag1 &= ~Mesh::CALL_EL_LEVEL;
+      flag1 |= Mesh::CALL_MG_LEVEL;
+      level1_ = level1;
+    } else {
+      level1_ = -1;
+    }
+
+    if (flag2.isSet(Mesh::CALL_EL_LEVEL)) {
+      flag2 &= ~Mesh::CALL_EL_LEVEL;
+      flag2 |= Mesh::CALL_MG_LEVEL;
+      level2_ = level2;
+    } else {
+      level2_ = -1;
+    }
+
+    // replace CALL_LEAF_EL_LEVEL by CALL_MG_LEVEL (covers whole domain)
+    if (flag1.isSet(Mesh::CALL_LEAF_EL_LEVEL)) {
+      flag1 &= ~Mesh::CALL_LEAF_EL_LEVEL;
+      flag1 |= Mesh::CALL_MG_LEVEL;
+      level1_ = level1;
+      callLeafElLevel1_ = true;
+    } else {
+      level1_ = -1;
+      callLeafElLevel1_ = false;
+    }
+
+    if (flag2.isSet(Mesh::CALL_LEAF_EL_LEVEL)) {
+      flag2 &= ~Mesh::CALL_LEAF_EL_LEVEL;
+      flag2 |= Mesh::CALL_MG_LEVEL;
+      level2_ = level2;
+      callLeafElLevel2_ = true;
+    } else {
+      level2_ = -1;
+      callLeafElLevel2_ = false;
+    }
+
+    // call standard traverse
+    *elInfo1 = stack1.traverseFirstOneMacro(mesh1, macroIndex, level1, flag1);
+    while (*elInfo1 != NULL && skipEl1(*elInfo1)) {
+      *elInfo1 = stack1.traverseNext(*elInfo1);
+    }
+
+    *elInfo2 = stack2.traverseFirstOneMacro(mesh2, macroIndex, level2, flag2);
+    while (*elInfo2 != NULL && skipEl2(*elInfo2)) {
+      *elInfo2 = stack2.traverseNext(*elInfo2);
+    }
+
+    // finished ?
+    if (*elInfo1 == NULL || *elInfo2 == NULL) {
+      TEST_EXIT(*elInfo1 == *elInfo2)("invalid dual traverse\n");
+      return false;
+    }
+
+    rest = 1.0;
+
+    bool accepted = check(elInfo1, elInfo2, elInfoSmall, elInfoLarge);
+
+    // check for non domain covering level traverse
+    if (!accepted ||
+	(level1_ != -1 && (*elInfo1)->getLevel() != level1_) ||
+	(callLeafElLevel1_ && !(*elInfo1)->getElement()->isLeaf()) ||
+	(level2_ != -1 && (*elInfo2)->getLevel() != level2_) ||
+	(callLeafElLevel2_ && !(*elInfo2)->getElement()->isLeaf())) {
+      return traverseNext(elInfo1, elInfo2, elInfoSmall, elInfoLarge);
+    }
+
+    fillSubElInfo(*elInfo1, *elInfo2, *elInfoSmall, *elInfoLarge);
+
+    return true;
+  }
+
+
   bool DualTraverse::traverseNext(ElInfo **elInfo1,
 				  ElInfo **elInfo2,
 				  ElInfo **elInfoSmall,
diff --git a/AMDiS/src/DualTraverse.h b/AMDiS/src/DualTraverse.h
index f5990540ca9ad82882d04211810aff8f3d0d4c36..3a43e2a864b836a8550b2e2fad075372fb3c8bdf 100644
--- a/AMDiS/src/DualTraverse.h
+++ b/AMDiS/src/DualTraverse.h
@@ -78,6 +78,18 @@ namespace AMDiS {
 			   &(dualElInfo.smallElInfo),
 			   &(dualElInfo.largeElInfo));
     }
+    
+    bool traverseFirstOneMacro(Mesh *mesh1,
+                              Mesh *mesh2,
+                              int macroIndex,
+                              int level1,
+                              int level2,
+                              Flag flag1,
+                              Flag flag2,
+                              ElInfo **elInfo1,
+                              ElInfo **elInfo2,
+                              ElInfo **elInfoSmall,
+                              ElInfo **elInfoLarge);
 
     /// Get next ElInfo combination
     bool traverseNext(ElInfo **elInfoNext1,
diff --git a/AMDiS/src/MeshStructure.cc b/AMDiS/src/MeshStructure.cc
index 4cadb1d40e7f23fad6fc8bc4b51c003dd30ceb70..059d4356b0707e7dca87ecf80d7ee3a668a4cf55 100644
--- a/AMDiS/src/MeshStructure.cc
+++ b/AMDiS/src/MeshStructure.cc
@@ -504,7 +504,7 @@ namespace AMDiS {
       elInfo = stack.traverseNext(elInfo);
     }
   }
-
+  
 
   void MeshStructure::setMeshStructureValues(int macroElIndex,
 					     DOFVector<double>* vec,
@@ -519,8 +519,8 @@ namespace AMDiS {
     Mesh *mesh = feSpace->getMesh();
     bool feSpaceHasNonVertexDofs = (feSpace->getBasisFcts()->getDegree() > 1);
     int nVertexPreDofs = feSpace->getAdmin()->getNumberOfPreDofs(VERTEX);
-    unsigned int counter = 0;
-
+    
+    std::size_t counter = 0;
     if (withElIndex) {
       TEST_EXIT(static_cast<int>(values[0]) == macroElIndex)
 	("Value structure code was created for macro element index %d, but should be set to macro element index %d\n",
@@ -568,5 +568,4 @@ namespace AMDiS {
     TEST_EXIT_DBG(values.size() == counter)
       ("Should not happen! values size %d, counter %d\n", values.size(), counter);
   }
-
 }
diff --git a/AMDiS/src/Timer.cc b/AMDiS/src/Timer.cc
index 10598c806703101a9608d8b618323140d630264a..31718f6854c84e4f1742e83a13cedc6732214bdf 100644
--- a/AMDiS/src/Timer.cc
+++ b/AMDiS/src/Timer.cc
@@ -42,7 +42,7 @@ namespace AMDiS {
 #endif
   }
 
-  double Timer::elapsed()
+  double Timer::elapsed() const
   {
 #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
     return MPI::Wtime() - first_mpi;
diff --git a/AMDiS/src/Timer.h b/AMDiS/src/Timer.h
index 2620c73f67934a5d4203429fb7831123f0da9999..7b71a85b1fb423a960ffacc993c1cadc4d494e83 100644
--- a/AMDiS/src/Timer.h
+++ b/AMDiS/src/Timer.h
@@ -42,7 +42,7 @@ namespace AMDiS {
     void reset();
 
     /// returns the elapsed time (from construction or last reset) to now in seconds
-    double elapsed();
+    double elapsed() const;
   };
 }
 
diff --git a/configure.sh b/configure.sh
index cd193f64aa7d447807b142d845c0011307375a9d..af4b439bcd5f4903cf39fedd689efa1d00383879 100755
--- a/configure.sh
+++ b/configure.sh
@@ -196,7 +196,7 @@ if [ "${DOWNLOAD_BOOST}" -eq "1" ]; then
   BOOST_PREFIX=${SRC_DIR}/packages/boost/${BOOST_VERSION}
 
   cd /tmp/src/boost
-  ./bootstrap.sh --prefix=${BOOST_PREFIX} --with-libraries=system,iostreams,filesystem,program_options,date_time,test,thread
+  ./bootstrap.sh --prefix=${BOOST_PREFIX} --with-libraries=system,iostreams,filesystem,program_options,date_time,test,thread,mpi,serialization
   if [ "${ENABLE_COMPRESSION}" = "ON" ]; then
     ./b2 -s cxxflags="-std=c++14" --build-type=minimal variant=release install
   else
diff --git a/tools/install_boost.sh b/tools/install_boost.sh
index 36b56bfa012b52ec5bccdea16d9ff6e7f4a05b53..a71c33cb3150a0b463f228fb2d9fa510b860f670 100755
--- a/tools/install_boost.sh
+++ b/tools/install_boost.sh
@@ -5,22 +5,23 @@ set -x
 
 ROOT=${PWD}
 
-BOOST_VERSION="1.62.0"
+BOOST_VERSION="1.64.0"
 BOOST_FILENAME="boost_${BOOST_VERSION//[.]/_}.tar.gz"
 
-INSTALL_PREFIX=${ROOT}/install
-mkdir -p ${INSTALL_PREFIX}
+BOOST_PREFIX=${ROOT}/../packages/boost/${BOOST_VERSION}
+mkdir -p ${BOOST_PREFIX}
 
 BUILD_DIR=/tmp/$USER/boost_build
 mkdir -p ${BUILD_DIR}
 
+# download boost
+curl -SL "http://netcologne.dl.sourceforge.net/project/boost/boost/${BOOST_VERSION}/${BOOST_FILENAME}" \
+  | tar --strip-components=1 -xzC ${BUILD_DIR}
+cd ${BUILD_DIR}
+  
 # install boost
-if [ ! -d ${INSTALL_PREFIX}/boost ]; then
-  curl -SL "http://netcologne.dl.sourceforge.net/project/boost/boost/${BOOST_VERSION}/${BOOST_FILENAME}" \
-    | tar --strip-components=1 -xzC ${BUILD_DIR}
-  cd ${BUILD_DIR}
-  ./bootstrap.sh --prefix=${INSTALL_PREFIX}/boost \
-                 --with-libraries=system,iostreams,filesystem,program_options,date_time,test
-  ./b2 -s NO_BZIP2=1 cxxflags="-std=c++11" --build-type=minimal variant=release -j 4 install
-  rm -rf ${BUILD_DIR}
-fi
+./bootstrap.sh --prefix=${BOOST_PREFIX} \
+                --with-libraries=system,iostreams,filesystem,program_options,date_time,test,thread,mpi,serialization
+echo "using mpi ;" >> project-config.jam
+./b2 -s NO_BZIP2=1 -s NO_ZLIB=1 cxxflags="-std=c++14" --build-type=minimal variant=release install
+rm -rf ${BUILD_DIR}