diff --git a/AMDiS/bin/Makefile.am b/AMDiS/bin/Makefile.am
index 197e8ecc3d82b8182aaf83b87404acd268aaab47..5e5ae77862efc1febdda152e8073cd15c78d52e6 100644
--- a/AMDiS/bin/Makefile.am
+++ b/AMDiS/bin/Makefile.am
@@ -28,8 +28,9 @@ endif
 
 if USE_PARALLEL_DOMAIN_AMDIS
   PARALLEL_AMDIS_SOURCES += \
+  $(SOURCE_DIR)/parallel/StdMpi.h $(SOURCE_DIR)/parallel/StdMpi.cc \
   $(SOURCE_DIR)/parallel/ParallelDomainBase.h $(SOURCE_DIR)/parallel/ParallelDomainBase.cc \
-  $(SOURCE_DIR)/parallel/ParallelDomainVec.h $(SOURCE_DIR)/parallel/ParallelDomainVec.cc \
+  $(SOURCE_DIR)/parallel/GlobalMatrixSolver.h $(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc \
   $(SOURCE_DIR)/parallel/MpiHelper.h $(SOURCE_DIR)/parallel/MpiHelper.cc 
   libamdis_la_CXXFLAGS += -DHAVE_PARALLEL_DOMAIN_AMDIS=1
   AMDIS_INCLUDES += -I$(PETSC_DIR)/include -I$(PETSC_DIR)/$(PETSC_ARCH)/include
diff --git a/AMDiS/bin/Makefile.in b/AMDiS/bin/Makefile.in
index 1861189a7d751bb335ffb019c25065879554f4d8..94777480f03113c35bd995e01349a9af9ef0874f 100644
--- a/AMDiS/bin/Makefile.in
+++ b/AMDiS/bin/Makefile.in
@@ -38,8 +38,9 @@ build_triplet = @build@
 host_triplet = @host@
 @USE_PARALLEL_AMDIS_TRUE@am__append_1 = -DHAVE_PARALLEL_AMDIS=1
 @USE_PARALLEL_DOMAIN_AMDIS_TRUE@am__append_2 = \
+@USE_PARALLEL_DOMAIN_AMDIS_TRUE@  $(SOURCE_DIR)/parallel/StdMpi.h $(SOURCE_DIR)/parallel/StdMpi.cc \
 @USE_PARALLEL_DOMAIN_AMDIS_TRUE@  $(SOURCE_DIR)/parallel/ParallelDomainBase.h $(SOURCE_DIR)/parallel/ParallelDomainBase.cc \
-@USE_PARALLEL_DOMAIN_AMDIS_TRUE@  $(SOURCE_DIR)/parallel/ParallelDomainVec.h $(SOURCE_DIR)/parallel/ParallelDomainVec.cc \
+@USE_PARALLEL_DOMAIN_AMDIS_TRUE@  $(SOURCE_DIR)/parallel/GlobalMatrixSolver.h $(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc \
 @USE_PARALLEL_DOMAIN_AMDIS_TRUE@  $(SOURCE_DIR)/parallel/MpiHelper.h $(SOURCE_DIR)/parallel/MpiHelper.cc 
 
 @USE_PARALLEL_DOMAIN_AMDIS_TRUE@am__append_3 = -DHAVE_PARALLEL_DOMAIN_AMDIS=1
@@ -73,11 +74,12 @@ am__installdirs = "$(DESTDIR)$(libdir)"
 libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libamdis_la_LIBADD =
-am__libamdis_la_SOURCES_DIST =  \
+am__libamdis_la_SOURCES_DIST = $(SOURCE_DIR)/parallel/StdMpi.h \
+	$(SOURCE_DIR)/parallel/StdMpi.cc \
 	$(SOURCE_DIR)/parallel/ParallelDomainBase.h \
 	$(SOURCE_DIR)/parallel/ParallelDomainBase.cc \
-	$(SOURCE_DIR)/parallel/ParallelDomainVec.h \
-	$(SOURCE_DIR)/parallel/ParallelDomainVec.cc \
+	$(SOURCE_DIR)/parallel/GlobalMatrixSolver.h \
+	$(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc \
 	$(SOURCE_DIR)/parallel/MpiHelper.h \
 	$(SOURCE_DIR)/parallel/MpiHelper.cc \
 	$(PARALLEL_DIR)/ConditionalEstimator.h \
@@ -231,8 +233,9 @@ am__libamdis_la_SOURCES_DIST =  \
 	$(SOURCE_DIR)/parallel/InteriorBoundary.h \
 	$(SOURCE_DIR)/parallel/InteriorBoundary.cc \
 	$(SOURCE_DIR)/Debug.h $(SOURCE_DIR)/Debug.cc
-@USE_PARALLEL_DOMAIN_AMDIS_TRUE@am__objects_1 = libamdis_la-ParallelDomainBase.lo \
-@USE_PARALLEL_DOMAIN_AMDIS_TRUE@	libamdis_la-ParallelDomainVec.lo \
+@USE_PARALLEL_DOMAIN_AMDIS_TRUE@am__objects_1 = libamdis_la-StdMpi.lo \
+@USE_PARALLEL_DOMAIN_AMDIS_TRUE@	libamdis_la-ParallelDomainBase.lo \
+@USE_PARALLEL_DOMAIN_AMDIS_TRUE@	libamdis_la-GlobalMatrixSolver.lo \
 @USE_PARALLEL_DOMAIN_AMDIS_TRUE@	libamdis_la-MpiHelper.lo
 @USE_PARALLEL_AMDIS_FALSE@am__objects_2 = $(am__objects_1)
 @USE_PARALLEL_AMDIS_TRUE@am__objects_2 =  \
@@ -767,6 +770,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-FixVec.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-GNUPlotWriter.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-Global.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-GlobalMatrixSolver.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-InteriorBoundary.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-Lagrange.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-LeafData.Plo@am__quote@
@@ -782,7 +786,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-Operator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-ParMetisPartitioner.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-ParallelDomainBase.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-ParallelDomainVec.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-ParallelProblem.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-Parameters.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-Parametric.Plo@am__quote@
@@ -812,6 +815,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-ScalableQuadrature.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-SecondOrderAssembler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-StandardProblemIteration.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-StdMpi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-SubAssembler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-SubElInfo.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libamdis_la-SurfaceQuadrature.Plo@am__quote@
@@ -856,6 +860,13 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
 
+libamdis_la-StdMpi.lo: $(SOURCE_DIR)/parallel/StdMpi.cc
+@am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -MT libamdis_la-StdMpi.lo -MD -MP -MF "$(DEPDIR)/libamdis_la-StdMpi.Tpo" -c -o libamdis_la-StdMpi.lo `test -f '$(SOURCE_DIR)/parallel/StdMpi.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/StdMpi.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libamdis_la-StdMpi.Tpo" "$(DEPDIR)/libamdis_la-StdMpi.Plo"; else rm -f "$(DEPDIR)/libamdis_la-StdMpi.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$(SOURCE_DIR)/parallel/StdMpi.cc' object='libamdis_la-StdMpi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -c -o libamdis_la-StdMpi.lo `test -f '$(SOURCE_DIR)/parallel/StdMpi.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/StdMpi.cc
+
 libamdis_la-ParallelDomainBase.lo: $(SOURCE_DIR)/parallel/ParallelDomainBase.cc
 @am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -MT libamdis_la-ParallelDomainBase.lo -MD -MP -MF "$(DEPDIR)/libamdis_la-ParallelDomainBase.Tpo" -c -o libamdis_la-ParallelDomainBase.lo `test -f '$(SOURCE_DIR)/parallel/ParallelDomainBase.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/ParallelDomainBase.cc; \
 @am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libamdis_la-ParallelDomainBase.Tpo" "$(DEPDIR)/libamdis_la-ParallelDomainBase.Plo"; else rm -f "$(DEPDIR)/libamdis_la-ParallelDomainBase.Tpo"; exit 1; fi
@@ -863,12 +874,12 @@ libamdis_la-ParallelDomainBase.lo: $(SOURCE_DIR)/parallel/ParallelDomainBase.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -c -o libamdis_la-ParallelDomainBase.lo `test -f '$(SOURCE_DIR)/parallel/ParallelDomainBase.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/ParallelDomainBase.cc
 
-libamdis_la-ParallelDomainVec.lo: $(SOURCE_DIR)/parallel/ParallelDomainVec.cc
-@am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -MT libamdis_la-ParallelDomainVec.lo -MD -MP -MF "$(DEPDIR)/libamdis_la-ParallelDomainVec.Tpo" -c -o libamdis_la-ParallelDomainVec.lo `test -f '$(SOURCE_DIR)/parallel/ParallelDomainVec.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/ParallelDomainVec.cc; \
-@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libamdis_la-ParallelDomainVec.Tpo" "$(DEPDIR)/libamdis_la-ParallelDomainVec.Plo"; else rm -f "$(DEPDIR)/libamdis_la-ParallelDomainVec.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$(SOURCE_DIR)/parallel/ParallelDomainVec.cc' object='libamdis_la-ParallelDomainVec.lo' libtool=yes @AMDEPBACKSLASH@
+libamdis_la-GlobalMatrixSolver.lo: $(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc
+@am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -MT libamdis_la-GlobalMatrixSolver.lo -MD -MP -MF "$(DEPDIR)/libamdis_la-GlobalMatrixSolver.Tpo" -c -o libamdis_la-GlobalMatrixSolver.lo `test -f '$(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/libamdis_la-GlobalMatrixSolver.Tpo" "$(DEPDIR)/libamdis_la-GlobalMatrixSolver.Plo"; else rm -f "$(DEPDIR)/libamdis_la-GlobalMatrixSolver.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc' object='libamdis_la-GlobalMatrixSolver.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -c -o libamdis_la-ParallelDomainVec.lo `test -f '$(SOURCE_DIR)/parallel/ParallelDomainVec.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/ParallelDomainVec.cc
+@am__fastdepCXX_FALSE@	$(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -c -o libamdis_la-GlobalMatrixSolver.lo `test -f '$(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/GlobalMatrixSolver.cc
 
 libamdis_la-MpiHelper.lo: $(SOURCE_DIR)/parallel/MpiHelper.cc
 @am__fastdepCXX_TRUE@	if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libamdis_la_CXXFLAGS) $(CXXFLAGS) -MT libamdis_la-MpiHelper.lo -MD -MP -MF "$(DEPDIR)/libamdis_la-MpiHelper.Tpo" -c -o libamdis_la-MpiHelper.lo `test -f '$(SOURCE_DIR)/parallel/MpiHelper.cc' || echo '$(srcdir)/'`$(SOURCE_DIR)/parallel/MpiHelper.cc; \
diff --git a/AMDiS/libtool b/AMDiS/libtool
index b24ee23d4db5c89b8becf2ee49cfa31486adc673..d6ae6aec3bdfe931f7738cb747117b7a8a279992 100755
--- a/AMDiS/libtool
+++ b/AMDiS/libtool
@@ -30,10 +30,10 @@
 # the same distribution terms that you use for the rest of that program.
 
 # A sed program that does not truncate output.
-SED="/bin/sed"
+SED="/usr/bin/sed"
 
 # Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="/bin/sed -e 1s/^X//"
+Xsed="/usr/bin/sed -e 1s/^X//"
 
 # The HP-UX ksh and POSIX shell print the target directory to stdout
 # if CDPATH is set.
@@ -44,7 +44,7 @@ available_tags=" CXX F77"
 
 # ### BEGIN LIBTOOL CONFIG
 
-# Libtool was configured on host NWRW15:
+# Libtool was configured on host deimos102:
 
 # Shell to use when invoking shell scripts.
 SHELL="/bin/sh"
@@ -66,12 +66,12 @@ fast_install=yes
 
 # The host system.
 host_alias=
-host=i686-pc-linux-gnu
+host=x86_64-unknown-linux-gnu
 host_os=linux-gnu
 
 # The build system.
 build_alias=
-build=i686-pc-linux-gnu
+build=x86_64-unknown-linux-gnu
 build_os=linux-gnu
 
 # An echo program that does not interpret backslashes.
@@ -82,13 +82,13 @@ AR="ar"
 AR_FLAGS="cru"
 
 # A C compiler.
-LTCC="gcc"
+LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc"
 
 # LTCC compiler flags.
 LTCFLAGS="-g -O2"
 
 # A language-specific compiler.
-CC="gcc"
+CC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc"
 
 # Is the compiler the GNU C compiler?
 with_gcc=yes
@@ -97,7 +97,7 @@ with_gcc=yes
 EGREP="grep -E"
 
 # The linker used to build libraries.
-LD="/usr/bin/ld"
+LD="/usr/x86_64-suse-linux/bin/ld -m elf_x86_64"
 
 # Whether we need hard or soft links.
 LN_S="ln -s"
@@ -171,7 +171,7 @@ dlopen_self=unknown
 dlopen_self_static=unknown
 
 # Compiler flag to prevent dynamic linking.
-link_static_flag="-static"
+link_static_flag=""
 
 # Compiler flag to turn off builtin functions.
 no_builtin_flag=" -fno-builtin"
@@ -325,10 +325,10 @@ variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COM
 link_all_deplibs=unknown
 
 # Compile-time system search path for libraries
-sys_lib_search_path_spec=" /usr/lib/gcc/i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/lib/i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/lib/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../ /lib/i386-redhat-linux/4.1.2/ /lib/ /usr/lib/i386-redhat-linux/4.1.2/ /usr/lib/"
+sys_lib_search_path_spec=" /usr/lib64/gcc/x86_64-suse-linux/4.1.2/ /usr/lib/gcc/x86_64-suse-linux/4.1.2/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/4.1.2/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib/../lib64/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../x86_64-suse-linux/4.1.2/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/ /lib/x86_64-suse-linux/4.1.2/ /lib/../lib64/ /usr/lib/x86_64-suse-linux/4.1.2/ /usr/lib/../lib64/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../ /lib/ /usr/lib/"
 
 # Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib/octave-2.9.9 /usr/lib/qt-3.3/lib /usr/lib/qt4/lib "
+sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/X11R6/lib64/Xaw3d /usr/X11R6/lib64 /usr/X11R6/lib/Xaw3d /usr/X11R6/lib /usr/x86_64-suse-linux/lib /usr/local/lib64 /usr/local/lib /opt/kde3/lib64 /opt/kde3/lib /opt/gnome/lib64 /opt/gnome/lib /lib64 /lib /usr/lib64 /usr/lib /opt/cluster/intel/cce/9.1.042/lib /opt/cluster/intel/fce/9.1.036/lib /opt/cluster/Pathscale3.0/lib/2.9.99 /opt/cluster/Pathscale3.0/lib/2.9.99/32 /work/licsoft/compilers/pgi/linux86-64/6.2/lib /work/licsoft/compilers/pgi/linux86-64/6.2/libso "
 
 # Fix the shell variable $srcfile for the compiler.
 fix_srcfile_path=""
@@ -6760,7 +6760,7 @@ build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
 # End:
 # ### BEGIN LIBTOOL TAG CONFIG: CXX
 
-# Libtool was configured on host NWRW15:
+# Libtool was configured on host deimos102:
 
 # Shell to use when invoking shell scripts.
 SHELL="/bin/sh"
@@ -6782,12 +6782,12 @@ fast_install=yes
 
 # The host system.
 host_alias=
-host=i686-pc-linux-gnu
+host=x86_64-unknown-linux-gnu
 host_os=linux-gnu
 
 # The build system.
 build_alias=
-build=i686-pc-linux-gnu
+build=x86_64-unknown-linux-gnu
 build_os=linux-gnu
 
 # An echo program that does not interpret backslashes.
@@ -6798,13 +6798,13 @@ AR="ar"
 AR_FLAGS="cru"
 
 # A C compiler.
-LTCC="gcc"
+LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc"
 
 # LTCC compiler flags.
 LTCFLAGS="-g -O2"
 
 # A language-specific compiler.
-CC="g++"
+CC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpiCC"
 
 # Is the compiler the GNU C compiler?
 with_gcc=yes
@@ -6813,7 +6813,7 @@ with_gcc=yes
 EGREP="grep -E"
 
 # The linker used to build libraries.
-LD="/usr/bin/ld"
+LD="/usr/x86_64-suse-linux/bin/ld -m elf_x86_64"
 
 # Whether we need hard or soft links.
 LN_S="ln -s"
@@ -6887,7 +6887,7 @@ dlopen_self=unknown
 dlopen_self_static=unknown
 
 # Compiler flag to prevent dynamic linking.
-link_static_flag="-static"
+link_static_flag=""
 
 # Compiler flag to turn off builtin functions.
 no_builtin_flag=" -fno-builtin"
@@ -6942,11 +6942,11 @@ striplib="strip --strip-unneeded"
 
 # Dependencies to place before the objects being linked to create a
 # shared library.
-predep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginS.o"
+predep_objects="/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbeginS.o"
 
 # Dependencies to place after the objects being linked to create a
 # shared library.
-postdep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/crtendS.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o"
+postdep_objects="/usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtendS.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o"
 
 # Dependencies to place before the objects being linked to create a
 # shared library.
@@ -6954,11 +6954,11 @@ predeps=""
 
 # Dependencies to place after the objects being linked to create a
 # shared library.
-postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s"
+postdeps="-lmpi_cxx -lmpi -lopen-rte -lopen-pal -libverbs -lrt -lnuma -ldl -lnsl -lutil -ldl -lstdc++ -lm -lgcc_s -lpthread -lc -lgcc_s"
 
 # The library search path used internally by the compiler when linking
 # a shared library.
-compiler_lib_search_path="-L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.."
+compiler_lib_search_path="-L/usr/lib64 -L/licsoft/libraries/openmpi/1.2.6/64bit/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.."
 
 # Method to check whether dependent libraries are shared objects.
 deplibs_check_method="pass_all"
@@ -7038,10 +7038,10 @@ variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COM
 link_all_deplibs=unknown
 
 # Compile-time system search path for libraries
-sys_lib_search_path_spec=" /usr/lib/gcc/i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/lib/i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/lib/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../i386-redhat-linux/4.1.2/ /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../ /lib/i386-redhat-linux/4.1.2/ /lib/ /usr/lib/i386-redhat-linux/4.1.2/ /usr/lib/"
+sys_lib_search_path_spec=" /usr/lib64/gcc/x86_64-suse-linux/4.1.2/ /usr/lib/gcc/x86_64-suse-linux/4.1.2/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/4.1.2/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib/../lib64/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../x86_64-suse-linux/4.1.2/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/ /lib/x86_64-suse-linux/4.1.2/ /lib/../lib64/ /usr/lib/x86_64-suse-linux/4.1.2/ /usr/lib/../lib64/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib/ /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../ /lib/ /usr/lib/"
 
 # Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib/octave-2.9.9 /usr/lib/qt-3.3/lib /usr/lib/qt4/lib "
+sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/X11R6/lib64/Xaw3d /usr/X11R6/lib64 /usr/X11R6/lib/Xaw3d /usr/X11R6/lib /usr/x86_64-suse-linux/lib /usr/local/lib64 /usr/local/lib /opt/kde3/lib64 /opt/kde3/lib /opt/gnome/lib64 /opt/gnome/lib /lib64 /lib /usr/lib64 /usr/lib /opt/cluster/intel/cce/9.1.042/lib /opt/cluster/intel/fce/9.1.036/lib /opt/cluster/Pathscale3.0/lib/2.9.99 /opt/cluster/Pathscale3.0/lib/2.9.99/32 /work/licsoft/compilers/pgi/linux86-64/6.2/lib /work/licsoft/compilers/pgi/linux86-64/6.2/libso "
 
 # Fix the shell variable $srcfile for the compiler.
 fix_srcfile_path=""
@@ -7065,7 +7065,7 @@ include_expsyms=""
 
 # ### BEGIN LIBTOOL TAG CONFIG: F77
 
-# Libtool was configured on host NWRW15:
+# Libtool was configured on host deimos102:
 
 # Shell to use when invoking shell scripts.
 SHELL="/bin/sh"
@@ -7087,12 +7087,12 @@ fast_install=yes
 
 # The host system.
 host_alias=
-host=i686-pc-linux-gnu
+host=x86_64-unknown-linux-gnu
 host_os=linux-gnu
 
 # The build system.
 build_alias=
-build=i686-pc-linux-gnu
+build=x86_64-unknown-linux-gnu
 build_os=linux-gnu
 
 # An echo program that does not interpret backslashes.
@@ -7103,7 +7103,7 @@ AR="ar"
 AR_FLAGS="cru"
 
 # A C compiler.
-LTCC="gcc"
+LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc"
 
 # LTCC compiler flags.
 LTCFLAGS="-g -O2"
@@ -7112,13 +7112,13 @@ LTCFLAGS="-g -O2"
 CC="g77"
 
 # Is the compiler the GNU C compiler?
-with_gcc=yes
+with_gcc=
 
 # An ERE matcher.
 EGREP="grep -E"
 
 # The linker used to build libraries.
-LD="/usr/bin/ld"
+LD="/usr/x86_64-suse-linux/bin/ld -m elf_x86_64"
 
 # Whether we need hard or soft links.
 LN_S="ln -s"
@@ -7346,10 +7346,10 @@ variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COM
 link_all_deplibs=unknown
 
 # Compile-time system search path for libraries
-sys_lib_search_path_spec=" /usr/lib/gcc/i386-redhat-linux/3.4.6/ /usr/lib/gcc/i386-redhat-linux/3.4.6/ /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../i386-redhat-linux/lib/i386-redhat-linux/3.4.6/ /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../i386-redhat-linux/lib/ /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../i386-redhat-linux/3.4.6/ /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../ /lib/i386-redhat-linux/3.4.6/ /lib/ /usr/lib/i386-redhat-linux/3.4.6/ /usr/lib/"
+sys_lib_search_path_spec=" /usr/lib64/gcc-lib/x86_64-suse-linux/3.3.5/ /usr/lib/gcc/x86_64-suse-linux/3.3.5/ /usr/lib64/gcc-lib/x86_64-suse-linux/3.3.5/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/3.3.5/ /usr/lib64/gcc-lib/x86_64-suse-linux/3.3.5/../../../../x86_64-suse-linux/lib/ /usr/lib64/gcc-lib/x86_64-suse-linux/3.3.5/../../../x86_64-suse-linux/3.3.5/ /usr/lib64/gcc-lib/x86_64-suse-linux/3.3.5/../../../ /lib/x86_64-suse-linux/3.3.5/ /lib/ /usr/lib/x86_64-suse-linux/3.3.5/ /usr/lib/"
 
 # Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib/octave-2.9.9 /usr/lib/qt-3.3/lib /usr/lib/qt4/lib "
+sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/X11R6/lib64/Xaw3d /usr/X11R6/lib64 /usr/X11R6/lib/Xaw3d /usr/X11R6/lib /usr/x86_64-suse-linux/lib /usr/local/lib64 /usr/local/lib /opt/kde3/lib64 /opt/kde3/lib /opt/gnome/lib64 /opt/gnome/lib /lib64 /lib /usr/lib64 /usr/lib /opt/cluster/intel/cce/9.1.042/lib /opt/cluster/intel/fce/9.1.036/lib /opt/cluster/Pathscale3.0/lib/2.9.99 /opt/cluster/Pathscale3.0/lib/2.9.99/32 /work/licsoft/compilers/pgi/linux86-64/6.2/lib /work/licsoft/compilers/pgi/linux86-64/6.2/libso "
 
 # Fix the shell variable $srcfile for the compiler.
 fix_srcfile_path=""
diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h
index 2b8a9cfe25496edf0af721e672a4863e23d32b06..3b4849c5a180493bf975ed58b35501060b1479bd 100644
--- a/AMDiS/src/AMDiS.h
+++ b/AMDiS/src/AMDiS.h
@@ -95,7 +95,7 @@
 #if HAVE_PARALLEL_DOMAIN_AMDIS
 #include "parallel/InteriorBoundary.h"
 #include "parallel/MpiHelper.h"
-#include "parallel/ParallelDomainVec.h"
+#include "parallel/GlobalMatrixSolver.h"
 #endif
 
 #endif
diff --git a/AMDiS/src/parallel/GlobalMatrixSolver.cc b/AMDiS/src/parallel/GlobalMatrixSolver.cc
new file mode 100644
index 0000000000000000000000000000000000000000..57838d521fab4bc210ce43aad14118465d8f9eb1
--- /dev/null
+++ b/AMDiS/src/parallel/GlobalMatrixSolver.cc
@@ -0,0 +1,488 @@
+#include "GlobalMatrixSolver.h"
+#include "DOFVector.h"
+#include "Debug.h"
+#include "SystemVector.h"
+#include "parallel/StdMpi.h"
+
+#include "petscksp.h"
+
+namespace AMDiS {
+
+  PetscErrorCode myKSPMonitor(KSP ksp, PetscInt iter, PetscReal rnorm, void *)
+  {    
+    if (iter % 10 == 0 && MPI::COMM_WORLD.Get_rank() == 0)
+      std::cout << "[0]  Petsc-Iteration " << iter << ": " << rnorm << std::endl;
+
+    return 0;
+  }
+ 
+  void GlobalMatrixSolver::solve()
+  {
+    FUNCNAME("GlobalMatrixSolver::solve()");
+
+#ifdef _OPENMP
+    double wtime = omp_get_wtime();
+#endif
+    clock_t first = clock();
+
+    fillPetscMatrix(probStat->getSystemMatrix(), probStat->getRHS());
+    solvePetscMatrix(*(probStat->getSolution()));
+
+#ifdef _OPENMP
+    INFO(info, 8)("solution of discrete system needed %.5f seconds system time / %.5f seconds wallclock time\n",
+		   TIME_USED(first, clock()),
+		   omp_get_wtime() - wtime);
+#else
+    INFO(info, 8)("solution of discrete system needed %.5f seconds\n",
+		   TIME_USED(first, clock()));
+#endif    
+  }
+
+
+  void GlobalMatrixSolver::setDofMatrix(DOFMatrix* mat, int dispMult, 
+					int dispAddRow, int dispAddCol)
+  {
+    FUNCNAME("GlobalMatrixSolver::setDofMatrix()");
+
+    TEST_EXIT(mat)("No DOFMatrix!\n");
+
+    using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
+    namespace traits= mtl::traits;
+    typedef DOFMatrix::base_matrix_type Matrix;
+
+    traits::col<Matrix>::type col(mat->getBaseMatrix());
+    traits::const_value<Matrix>::type value(mat->getBaseMatrix());
+
+    typedef traits::range_generator<row, Matrix>::type cursor_type;
+    typedef traits::range_generator<nz, cursor_type>::type icursor_type;
+
+    std::vector<int> cols;
+    std::vector<double> values;
+    cols.reserve(300);
+    values.reserve(300);
+
+    // === Traverse all rows of the dof matrix and insert row wise the values ===
+    // === to the petsc matrix.                                               ===
+
+    for (cursor_type cursor = begin<row>(mat->getBaseMatrix()), 
+	   cend = end<row>(mat->getBaseMatrix()); cursor != cend; ++cursor) {
+
+      cols.clear();
+      values.clear();
+
+      // Global index of the current row dof.
+      int globalRowDof = mapLocalGlobalDofs[*cursor];
+      // Test if the current row dof is a periodic dof.
+      bool periodicRow = (periodicDof.count(globalRowDof) > 0);
+
+
+      // === Traverse all non zero entries of the row and produce vector cols ===
+      // === with the column indices of all row entries and vector values     ===
+      // === with the corresponding values.                                   ===
+
+      for (icursor_type icursor = begin<nz>(cursor), icend = end<nz>(cursor); 
+	   icursor != icend; ++icursor) {
+
+	// Set only non null values.
+	if (value(*icursor) != 0.0) {
+	  // Global index of the current column index.
+	  int globalColDof = mapLocalGlobalDofs[col(*icursor)];
+	  // Calculate the exact position of the column index in the petsc matrix.
+	  int colIndex = globalColDof * dispMult + dispAddCol;
+
+	  // If the current row is not periodic, but the current dof index is periodic,
+	  // we have to duplicate the value to the other corresponding periodic columns.
+ 	  if (periodicRow == false && periodicDof.count(globalColDof) > 0) {
+	    // The value is assign to n matrix entries, therefore, every entry 
+	    // has only 1/n value of the original entry.
+	    double scalFactor = 1.0 / (periodicDof[globalColDof].size() + 1.0);
+
+	    // Insert original entry.
+ 	    cols.push_back(colIndex);
+ 	    values.push_back(value(*icursor) * scalFactor);
+
+	    // Insert the periodic entries.
+ 	    for (std::set<DegreeOfFreedom>::iterator it = 
+		   periodicDof[globalColDof].begin();
+ 		 it != periodicDof[globalColDof].end(); ++it) {
+ 	      cols.push_back(*it * dispMult + dispAddCol);
+ 	      values.push_back(value(*icursor) * scalFactor);
+	    }
+ 	  } else {
+	    // Neigher row nor column dof index is periodic, simple add entry.
+	    cols.push_back(colIndex);
+	    values.push_back(value(*icursor));
+	  }
+	}
+      }
+
+
+      // === Up to now we have assembled on row. Now, the row must be send to the ===
+      // === corresponding rows to the petsc matrix.                              ===
+
+      // Calculate petsc row index.
+      int rowIndex = globalRowDof * dispMult + dispAddRow;
+      
+      if (periodicRow) {
+	// The row dof is periodic, so send dof to all the corresponding rows.
+
+	double scalFactor = 1.0 / (periodicDof[globalRowDof].size() + 1.0);
+	
+	int diagIndex = -1;
+	for (int i = 0; i < static_cast<int>(values.size()); i++) {
+	  // Change only the non diagonal values in the col. For the diagonal test
+	  // we compare the global dof indices of the dof matrix (not of the petsc
+	  // matrix!).
+	  if ((cols[i] - dispAddCol) / dispMult != globalRowDof)
+	    values[i] *= scalFactor;
+	  else
+	    diagIndex = i;
+	}
+	
+	// Send the main row to the petsc matrix.
+	MatSetValues(petscMatrix, 1, &rowIndex, cols.size(), 
+		     &(cols[0]), &(values[0]), ADD_VALUES);	
+ 
+	// Set diagonal element to zero, i.e., the diagonal element of the current
+	// row is not send to the periodic row indices.
+	if (diagIndex != -1)
+	  values[diagIndex] = 0.0;
+
+	// Send the row to all periodic row indices.
+	for (std::set<DegreeOfFreedom>::iterator it = periodicDof[globalRowDof].begin();
+	     it != periodicDof[globalRowDof].end(); ++it) {
+	  int perRowIndex = *it * dispMult + dispAddRow;
+	  MatSetValues(petscMatrix, 1, &perRowIndex, cols.size(), 
+		       &(cols[0]), &(values[0]), ADD_VALUES);
+	}
+
+      } else {
+	// The row dof is not periodic, simply send the row to the petsc matrix.
+	MatSetValues(petscMatrix, 1, &rowIndex, cols.size(), 
+		     &(cols[0]), &(values[0]), ADD_VALUES);
+      }    
+    }
+  }
+
+
+  void GlobalMatrixSolver::setDofVector(Vec& petscVec, DOFVector<double>* vec, 
+					int dispMult, int dispAdd)
+  {
+    // Traverse all used dofs in the dof vector.
+    DOFVector<double>::Iterator dofIt(vec, USED_DOFS);
+    for (dofIt.reset(); !dofIt.end(); ++dofIt) {
+      // Calculate global row index of the dof.
+      int globalRow = mapLocalGlobalDofs[dofIt.getDOFIndex()];
+      // Calculate petsc index of the row dof.
+      int index = globalRow * dispMult + dispAdd;
+
+      if (periodicDof.count(globalRow) > 0) {
+	// The dof index is periodic, so devide the value to all dof entries.
+
+	double value = *dofIt / (periodicDof[globalRow].size() + 1.0);
+	VecSetValues(petscVec, 1, &index, &value, ADD_VALUES);
+
+	for (std::set<DegreeOfFreedom>::iterator it = periodicDof[globalRow].begin();
+	     it != periodicDof[globalRow].end(); ++it) {
+	  index = *it * dispMult + dispAdd;
+	  VecSetValues(petscVec, 1, &index, &value, ADD_VALUES);
+	}
+
+      } else {
+	// The dof index is not periodic.
+	double value = *dofIt;
+	VecSetValues(petscVec, 1, &index, &value, ADD_VALUES);
+      }
+    }    
+  }
+
+
+  void GlobalMatrixSolver::createPetscNnzStructure(Matrix<DOFMatrix*> *mat)
+  {
+    FUNCNAME("GlobalMatrixSolver::createPetscNnzStructure()");
+
+    TEST_EXIT_DBG(!d_nnz)("There is something wrong!\n");
+    TEST_EXIT_DBG(!o_nnz)("There is something wrong!\n");
+
+    d_nnz = new int[nRankRows];
+    o_nnz = new int[nRankRows];
+    for (int i = 0; i < nRankRows; i++) {
+      d_nnz[i] = 0;
+      o_nnz[i] = 0;
+    }
+
+    using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
+    namespace traits = mtl::traits;
+    typedef DOFMatrix::base_matrix_type Matrix;
+    typedef std::vector<std::pair<int, int> > MatrixNnzEntry;
+
+    // Stores to each rank a list of nnz entries (i.e. pairs of row and column index)
+    // that this rank will send to. This nnz entries will be assembled on this rank,
+    // but because the row DOFs are not DOFs of this rank they will be send to the
+    // owner of the row DOFs.
+    std::map<int, MatrixNnzEntry> sendMatrixEntry;
+
+    for (int i = 0; i < nComponents; i++) {
+      for (int j = 0; j < nComponents; j++) {
+ 	if ((*mat)[i][j]) {
+	  Matrix bmat = (*mat)[i][j]->getBaseMatrix();
+
+	  traits::col<Matrix>::type col(bmat);
+	  traits::const_value<Matrix>::type value(bmat);
+	  
+	  typedef traits::range_generator<row, Matrix>::type cursor_type;
+	  typedef traits::range_generator<nz, cursor_type>::type icursor_type;
+	  
+	  for (cursor_type cursor = begin<row>(bmat), 
+		 cend = end<row>(bmat); cursor != cend; ++cursor) {
+
+	    // Map the local row number to the global DOF index and create from it
+	    // the global PETSc row index of this DOF.
+	    int petscRowIdx = mapLocalGlobalDofs[*cursor] * nComponents + i;
+
+	    if (isRankDof[*cursor]) {
+
+	      // === The current row DOF is a rank dof, so create the corresponding ===
+	      // === nnz values directly on rank's nnz data.                        ===
+
+	      // This is the local row index of the local PETSc matrix.
+	      int localPetscRowIdx = petscRowIdx - rstart * nComponents;
+
+#if (DEBUG != 0)    
+	      if (localPetscRowIdx < 0 || localPetscRowIdx >= nRankRows) {
+		std::cout << "ERROR in rank: " << mpiRank << std::endl;
+		std::cout << "  Wrong r = " << localPetscRowIdx << " " << *cursor 
+			  << " " << mapLocalGlobalDofs[*cursor] << " " 
+			  << nRankRows << std::endl;
+		ERROR_EXIT("Should not happen!\n");
+	      }
+#endif
+	      
+	      // Traverse all non zero entries in this row.
+	      for (icursor_type icursor = begin<nz>(cursor), 
+		     icend = end<nz>(cursor); icursor != icend; ++icursor) {
+		if (value(*icursor) != 0.0) {
+		  int petscColIdx = mapLocalGlobalDofs[col(*icursor)] * nComponents + j;
+
+		  // The row DOF is a rank DOF, if also the column is a rank DOF, 
+		  // increment the d_nnz values for this row, otherwise the o_nnz value.
+		  if (petscColIdx >= rstart * nComponents && 
+		      petscColIdx < rstart * nComponents + nRankRows)
+		    d_nnz[localPetscRowIdx]++;
+		  else
+		    o_nnz[localPetscRowIdx]++;
+		}    
+	      }
+	    } else {
+	      
+	      // === The current row DOF is not a rank dof, i.e., it will be created ===
+	      // === on this rank, but after this it will be send to another rank    ===
+	      // === matrix. So we need to send also the corresponding nnz structure ===
+	      // === of this row to the corresponding rank.                          ===
+
+	      // Find out who is the member of this DOF.
+	      int sendToRank = -1;
+	      for (RankToDofContainer::iterator it = recvDofs.begin();
+		   it != recvDofs.end(); ++it) {
+		for (DofContainer::iterator dofIt = it->second.begin();
+		     dofIt != it->second.end(); ++dofIt) {
+		  if (**dofIt == *cursor) {
+
+		    if (petscRowIdx == 6717) {
+		      debug::writeDofMesh(mpiRank, *cursor, feSpace);
+		      MSG("SEND DOF TO: %d/%d\n", it->first, *cursor);
+		    }
+
+		    sendToRank = it->first;
+		    break;
+		  }
+		}
+
+		if (sendToRank != -1)
+		  break;
+	      }
+
+	      TEST_EXIT_DBG(sendToRank != -1)("Should not happen!\n");
+
+	      // Send all non zero entries to the member of the row DOF.
+	      for (icursor_type icursor = begin<nz>(cursor), 
+		     icend = end<nz>(cursor); icursor != icend; ++icursor) {
+		if (value(*icursor) != 0.0) {
+		  int petscColIdx = mapLocalGlobalDofs[col(*icursor)] * nComponents + j;
+		  
+		  sendMatrixEntry[sendToRank].
+		    push_back(std::make_pair(petscRowIdx, petscColIdx));
+		}
+	      }
+
+	    } // if (isRankDof[*cursor]) ... else ...
+	  } // for each row in mat[i][j]
+	} // if mat[i][j]
+      } 
+    }
+
+    // === Send and recv the nnz row structure to/from other ranks. ===
+
+    StdMpi<MatrixNnzEntry> stdMpi(mpiComm, true);
+    stdMpi.send(sendMatrixEntry);
+    stdMpi.recv(sendDofs);
+    stdMpi.startCommunication<int>(MPI_INT);
+
+    // === Evaluate the nnz structure this rank got from other ranks and add it to ===
+    // === the PETSc nnz data structure.                                           ===
+
+    for (std::map<int, MatrixNnzEntry>::iterator it = stdMpi.getRecvData().begin();
+	 it != stdMpi.getRecvData().end(); ++it) {
+      if (it->second.size() > 0) {
+	for (unsigned int i = 0; i < it->second.size(); i++) {
+	  int r = it->second[i].first;
+	  int c = it->second[i].second;
+
+	  int localRowIdx = r - rstart * nComponents;
+
+	  TEST_EXIT_DBG(localRowIdx >= 0 && localRowIdx < nRankRows)
+	    ("Got row index %d/%d (nRankRows = %d) from rank %d. Should not happen!\n",
+	     r, localRowIdx, nRankRows, it->first);
+	  
+	  if (c < rstart * nComponents || c >= rstart * nComponents + nRankRows)
+	    o_nnz[localRowIdx]++;
+	  else
+	    d_nnz[localRowIdx]++;
+	}
+      }
+    }  
+  }
+
+
+  void GlobalMatrixSolver::fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec)
+  {
+    FUNCNAME("GlobalMatrixSolver::fillPetscMatrix()");
+
+    clock_t first = clock();
+
+    // === Create PETSc vector (rhs, solution and a temporary vector). ===
+
+    VecCreate(PETSC_COMM_WORLD, &petscRhsVec);
+    VecSetSizes(petscRhsVec, nRankRows, nOverallRows);
+    VecSetType(petscRhsVec, VECMPI);
+
+    VecCreate(PETSC_COMM_WORLD, &petscSolVec);
+    VecSetSizes(petscSolVec, nRankRows, nOverallRows);
+    VecSetType(petscSolVec, VECMPI);
+
+    VecCreate(PETSC_COMM_WORLD, &petscTmpVec);
+    VecSetSizes(petscTmpVec, nRankRows, nOverallRows);
+    VecSetType(petscTmpVec, VECMPI);
+
+    if (!d_nnz)
+      createPetscNnzStructure(mat);
+
+    // === Create PETSc matrix with the computed nnz data structure. ===
+
+    MatCreateMPIAIJ(PETSC_COMM_WORLD, nRankRows, nRankRows, nOverallRows, nOverallRows,
+		    0, d_nnz, 0, o_nnz, &petscMatrix);
+
+    INFO(info, 8)("Fill petsc matrix 1 needed %.5f seconds\n", TIME_USED(first, clock()));
+
+#if (DEBUG != 0)
+    int a, b;
+    MatGetOwnershipRange(petscMatrix, &a, &b);
+    TEST_EXIT(a == rstart * nComponents)("Wrong matrix ownership range!\n");
+    TEST_EXIT(b == rstart * nComponents + nRankRows)("Wrong matrix ownership range!\n");
+#endif
+
+    // === Transfer values from DOF matrices to the PETSc matrix. === 
+
+    for (int i = 0; i < nComponents; i++)
+      for (int j = 0; j < nComponents; j++)
+	if ((*mat)[i][j])
+	  setDofMatrix((*mat)[i][j], nComponents, i, j);
+
+    INFO(info, 8)("Fill petsc matrix 2 needed %.5f seconds\n", TIME_USED(first, clock()));
+
+    MatAssemblyBegin(petscMatrix, MAT_FINAL_ASSEMBLY);
+    MatAssemblyEnd(petscMatrix, MAT_FINAL_ASSEMBLY);
+
+    // === Transfer values from DOF vector to the PETSc vector. === 
+
+    for (int i = 0; i < nComponents; i++)
+      setDofVector(petscRhsVec, vec->getDOFVector(i), nComponents, i);
+
+    VecAssemblyBegin(petscRhsVec);
+    VecAssemblyEnd(petscRhsVec);
+
+    INFO(info, 8)("Fill petsc matrix needed %.5f seconds\n", TIME_USED(first, clock()));
+  }
+
+
+  void GlobalMatrixSolver::solvePetscMatrix(SystemVector &vec)
+  {
+    FUNCNAME("GlobalMatrixSolver::solvePetscMatrix()");
+
+#if 0
+    // Set old solution to be initiual guess for petsc solver.
+    for (int i = 0; i < nComponents; i++)
+      setDofVector(petscSolVec, vec->getDOFVector(i), nComponents, i);
+
+    VecAssemblyBegin(petscSolVec);
+    VecAssemblyEnd(petscSolVec);
+#endif
+
+    // === Init Petsc solver. ===
+
+    KSP solver;
+    KSPCreate(PETSC_COMM_WORLD, &solver);
+    KSPSetOperators(solver, petscMatrix, petscMatrix, SAME_NONZERO_PATTERN); 
+    KSPSetTolerances(solver, 0.0, 1e-8, PETSC_DEFAULT, PETSC_DEFAULT);
+    KSPSetType(solver, KSPBCGS);
+    KSPMonitorSet(solver, myKSPMonitor, PETSC_NULL, 0);
+    KSPSetFromOptions(solver);
+    // Do not delete the solution vector, use it for the initial guess.
+    //    KSPSetInitialGuessNonzero(solver, PETSC_TRUE);
+
+
+    // === Run Petsc. ===
+
+    KSPSolve(solver, petscRhsVec, petscSolVec);
+
+    // === Transfere values from Petsc's solution vectors to the dof vectors.
+    PetscScalar *vecPointer;
+    VecGetArray(petscSolVec, &vecPointer);
+
+    for (int i = 0; i < nComponents; i++) {
+      DOFVector<double> *dofvec = vec.getDOFVector(i);
+      for (int j = 0; j < nRankDofs; j++)
+	(*dofvec)[mapLocalToDofIndex[j]] = vecPointer[j * nComponents + i];      
+    }
+
+    VecRestoreArray(petscSolVec, &vecPointer);
+
+
+    // === Synchronize dofs at common dofs, i.e., dofs that correspond to more ===
+    // === than one partition.                                                 ===
+    synchVector(vec);
+
+
+    // === Print information about solution process. ===
+
+    int iterations = 0;
+    KSPGetIterationNumber(solver, &iterations);
+    MSG("  Number of iterations: %d\n", iterations);
+    
+    double norm = 0.0;
+    MatMult(petscMatrix, petscSolVec, petscTmpVec);
+    VecAXPY(petscTmpVec, -1.0, petscRhsVec);
+    VecNorm(petscTmpVec, NORM_2, &norm);
+    MSG("  Residual norm: %e\n", norm);
+
+
+    // === Destroy Petsc's variables. ===
+
+    MatDestroy(petscMatrix);
+    VecDestroy(petscRhsVec);
+    VecDestroy(petscSolVec);
+    VecDestroy(petscTmpVec);
+    KSPDestroy(solver);
+  }
+
+}
diff --git a/AMDiS/src/parallel/GlobalMatrixSolver.h b/AMDiS/src/parallel/GlobalMatrixSolver.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5087f46f36111829b05660366b83dc5ae1aac1e
--- /dev/null
+++ b/AMDiS/src/parallel/GlobalMatrixSolver.h
@@ -0,0 +1,93 @@
+// ============================================================================
+// ==                                                                        ==
+// == AMDiS - Adaptive multidimensional simulations                          ==
+// ==                                                                        ==
+// ============================================================================
+// ==                                                                        ==
+// ==  TU Dresden                                                            ==
+// ==                                                                        ==
+// ==  Institut f�r Wissenschaftliches Rechnen                               ==
+// ==  Zellescher Weg 12-14                                                  ==
+// ==  01069 Dresden                                                         ==
+// ==  germany                                                               ==
+// ==                                                                        ==
+// ============================================================================
+// ==                                                                        ==
+// ==  https://gforge.zih.tu-dresden.de/projects/amdis/                      ==
+// ==                                                                        ==
+// ============================================================================
+
+/** \file GlobalMatrixSolver.h */
+
+#ifndef AMDIS_GLOBALMATRIXSOLVER_H
+#define AMDIS_GLOBALMATRIXSOLVER_H
+
+#include "AMDiS_fwd.h"
+#include "Global.h"
+#include "ParallelDomainBase.h"
+#include "ProblemVec.h"
+#include "ProblemInstat.h"
+
+#include "petsc.h"
+#include "petscsys.h"
+#include "petscao.h"
+
+namespace AMDiS {
+
+  class GlobalMatrixSolver : public ParallelDomainBase
+  {
+  public:
+    GlobalMatrixSolver(ProblemVec *problemStat, ProblemInstatVec *problemInstat)
+      : ParallelDomainBase(problemStat, problemInstat),
+	d_nnz(NULL),
+	o_nnz(NULL)
+    {}
+
+    ~GlobalMatrixSolver()
+    {}
+
+    void solve();
+
+  protected:
+    /// Creates a new non zero pattern structure for the Petsc matrix. 
+    void createPetscNnzStructure(Matrix<DOFMatrix*> *mat);
+    
+    /** \brief
+     * Create a PETSc matrix and PETSc vectors. The given DOF matrices are used to
+     * create the nnz structure of the PETSc matrix and the values are transfered to it.
+     * The given DOF vectors are used to the the values of the PETSc rhs vector.
+     *
+     * \param[in] mat
+     * \param[in] vec
+     */
+    void fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec);
+
+    /// Takes a dof matrix and sends the values to the global petsc matrix.
+    void setDofMatrix(DOFMatrix* mat, int dispMult = 1, 
+		      int dispAddRow = 0, int dispAddCol = 0);
+
+    /// Takes a dof vector and sends its values to a given petsc vector.
+    void setDofVector(Vec& petscVec, DOFVector<double>* vec, 
+		      int disMult = 1, int dispAdd = 0);
+
+    void solvePetscMatrix(SystemVector &vec);
+
+  protected:
+    /// Petsc's matrix structure.
+    Mat petscMatrix;
+
+    /** \brief
+     * Petsc's vector structures for the rhs vector, the solution vector and a
+     * temporary vector for calculating the final residuum.
+     */
+    Vec petscRhsVec, petscSolVec, petscTmpVec;
+
+    /// Arrays definig the non zero pattern of Petsc's matrix.
+    int *d_nnz, *o_nnz;
+  };
+
+  typedef GlobalMatrixSolver ParallelDomainVec;
+
+} //namespace AMDiS
+
+#endif
diff --git a/AMDiS/src/parallel/ParallelDomainBase.cc b/AMDiS/src/parallel/ParallelDomainBase.cc
index 3057c509cf4e42c0b53f7ff82324b99b266f86e2..0f3697fafba27e318a83bab3c7ddf6c741076bd2 100644
--- a/AMDiS/src/parallel/ParallelDomainBase.cc
+++ b/AMDiS/src/parallel/ParallelDomainBase.cc
@@ -25,20 +25,10 @@
 #include "ProblemInstat.h"
 #include "Debug.h"
 
-#include "petscksp.h"
-
 namespace AMDiS {
 
   using boost::lexical_cast;
 
-  PetscErrorCode myKSPMonitor(KSP ksp, PetscInt iter, PetscReal rnorm, void *)
-  {    
-    if (iter % 10 == 0 && MPI::COMM_WORLD.Get_rank() == 0)
-      std::cout << "[0]  Petsc-Iteration " << iter << ": " << rnorm << std::endl;
-
-    return 0;
-  }
-
   inline bool cmpDofsByValue(const DegreeOfFreedom* dof1, const DegreeOfFreedom* dof2)
   {
     return (*dof1 < *dof2);
@@ -55,8 +45,6 @@ namespace AMDiS {
       refineManager(problemStat->getRefinementManager(0)),
       info(problemStat->getInfo()),
       initialPartitionMesh(true),
-      d_nnz(NULL),
-      o_nnz(NULL),
       nRankDofs(0),
       rstart(0),
       nComponents(problemStat->getNumComponents()),
@@ -280,453 +268,6 @@ namespace AMDiS {
   }
 
 
-  void ParallelDomainBase::setDofMatrix(DOFMatrix* mat, int dispMult, 
-					int dispAddRow, int dispAddCol)
-  {
-    FUNCNAME("ParallelDomainBase::setDofMatrix()");
-
-    TEST_EXIT(mat)("No DOFMatrix!\n");
-
-    using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
-    namespace traits= mtl::traits;
-    typedef DOFMatrix::base_matrix_type Matrix;
-
-    traits::col<Matrix>::type col(mat->getBaseMatrix());
-    traits::const_value<Matrix>::type value(mat->getBaseMatrix());
-
-    typedef traits::range_generator<row, Matrix>::type cursor_type;
-    typedef traits::range_generator<nz, cursor_type>::type icursor_type;
-
-    std::vector<int> cols;
-    std::vector<double> values;
-    cols.reserve(300);
-    values.reserve(300);
-
-    // === Traverse all rows of the dof matrix and insert row wise the values ===
-    // === to the petsc matrix.                                               ===
-
-    for (cursor_type cursor = begin<row>(mat->getBaseMatrix()), 
-	   cend = end<row>(mat->getBaseMatrix()); cursor != cend; ++cursor) {
-
-      cols.clear();
-      values.clear();
-
-      // Global index of the current row dof.
-      int globalRowDof = mapLocalGlobalDofs[*cursor];
-      // Test if the current row dof is a periodic dof.
-      bool periodicRow = (periodicDof.count(globalRowDof) > 0);
-
-
-      // === Traverse all non zero entries of the row and produce vector cols ===
-      // === with the column indices of all row entries and vector values     ===
-      // === with the corresponding values.                                   ===
-
-      for (icursor_type icursor = begin<nz>(cursor), icend = end<nz>(cursor); 
-	   icursor != icend; ++icursor) {
-
-	// Set only non null values.
-	if (value(*icursor) != 0.0) {
-	  // Global index of the current column index.
-	  int globalColDof = mapLocalGlobalDofs[col(*icursor)];
-	  // Calculate the exact position of the column index in the petsc matrix.
-	  int colIndex = globalColDof * dispMult + dispAddCol;
-
-	  // If the current row is not periodic, but the current dof index is periodic,
-	  // we have to duplicate the value to the other corresponding periodic columns.
- 	  if (periodicRow == false && periodicDof.count(globalColDof) > 0) {
-	    // The value is assign to n matrix entries, therefore, every entry 
-	    // has only 1/n value of the original entry.
-	    double scalFactor = 1.0 / (periodicDof[globalColDof].size() + 1.0);
-
-	    // Insert original entry.
- 	    cols.push_back(colIndex);
- 	    values.push_back(value(*icursor) * scalFactor);
-
-	    // Insert the periodic entries.
- 	    for (std::set<DegreeOfFreedom>::iterator it = 
-		   periodicDof[globalColDof].begin();
- 		 it != periodicDof[globalColDof].end(); ++it) {
- 	      cols.push_back(*it * dispMult + dispAddCol);
- 	      values.push_back(value(*icursor) * scalFactor);
-	    }
- 	  } else {
-	    // Neigher row nor column dof index is periodic, simple add entry.
-	    cols.push_back(colIndex);
-	    values.push_back(value(*icursor));
-	  }
-	}
-      }
-
-
-      // === Up to now we have assembled on row. Now, the row must be send to the ===
-      // === corresponding rows to the petsc matrix.                              ===
-
-      // Calculate petsc row index.
-      int rowIndex = globalRowDof * dispMult + dispAddRow;
-      
-      if (periodicRow) {
-	// The row dof is periodic, so send dof to all the corresponding rows.
-
-	double scalFactor = 1.0 / (periodicDof[globalRowDof].size() + 1.0);
-	
-	int diagIndex = -1;
-	for (int i = 0; i < static_cast<int>(values.size()); i++) {
-	  // Change only the non diagonal values in the col. For the diagonal test
-	  // we compare the global dof indices of the dof matrix (not of the petsc
-	  // matrix!).
-	  if ((cols[i] - dispAddCol) / dispMult != globalRowDof)
-	    values[i] *= scalFactor;
-	  else
-	    diagIndex = i;
-	}
-	
-	// Send the main row to the petsc matrix.
-	MatSetValues(petscMatrix, 1, &rowIndex, cols.size(), 
-		     &(cols[0]), &(values[0]), ADD_VALUES);	
- 
-	// Set diagonal element to zero, i.e., the diagonal element of the current
-	// row is not send to the periodic row indices.
-	if (diagIndex != -1)
-	  values[diagIndex] = 0.0;
-
-	// Send the row to all periodic row indices.
-	for (std::set<DegreeOfFreedom>::iterator it = periodicDof[globalRowDof].begin();
-	     it != periodicDof[globalRowDof].end(); ++it) {
-	  int perRowIndex = *it * dispMult + dispAddRow;
-	  MatSetValues(petscMatrix, 1, &perRowIndex, cols.size(), 
-		       &(cols[0]), &(values[0]), ADD_VALUES);
-	}
-
-      } else {
-	// The row dof is not periodic, simply send the row to the petsc matrix.
-	MatSetValues(petscMatrix, 1, &rowIndex, cols.size(), 
-		     &(cols[0]), &(values[0]), ADD_VALUES);
-      }    
-    }
-  }
-
-
-  void ParallelDomainBase::setDofVector(Vec& petscVec, DOFVector<double>* vec, 
-					int dispMult, int dispAdd)
-  {
-    // Traverse all used dofs in the dof vector.
-    DOFVector<double>::Iterator dofIt(vec, USED_DOFS);
-    for (dofIt.reset(); !dofIt.end(); ++dofIt) {
-      // Calculate global row index of the dof.
-      int globalRow = mapLocalGlobalDofs[dofIt.getDOFIndex()];
-      // Calculate petsc index of the row dof.
-      int index = globalRow * dispMult + dispAdd;
-
-      if (periodicDof.count(globalRow) > 0) {
-	// The dof index is periodic, so devide the value to all dof entries.
-
-	double value = *dofIt / (periodicDof[globalRow].size() + 1.0);
-	VecSetValues(petscVec, 1, &index, &value, ADD_VALUES);
-
-	for (std::set<DegreeOfFreedom>::iterator it = periodicDof[globalRow].begin();
-	     it != periodicDof[globalRow].end(); ++it) {
-	  index = *it * dispMult + dispAdd;
-	  VecSetValues(petscVec, 1, &index, &value, ADD_VALUES);
-	}
-
-      } else {
-	// The dof index is not periodic.
-	double value = *dofIt;
-	VecSetValues(petscVec, 1, &index, &value, ADD_VALUES);
-      }
-    }    
-  }
-
-
-  void ParallelDomainBase::createPetscNnzStructure(Matrix<DOFMatrix*> *mat)
-  {
-    FUNCNAME("ParallelDomainBase::createPetscNnzStructure()");
-
-    TEST_EXIT_DBG(!d_nnz)("There is something wrong!\n");
-    TEST_EXIT_DBG(!o_nnz)("There is something wrong!\n");
-
-    d_nnz = new int[nRankRows];
-    o_nnz = new int[nRankRows];
-    for (int i = 0; i < nRankRows; i++) {
-      d_nnz[i] = 0;
-      o_nnz[i] = 0;
-    }
-
-    using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
-    namespace traits = mtl::traits;
-    typedef DOFMatrix::base_matrix_type Matrix;
-    typedef std::vector<std::pair<int, int> > MatrixNnzEntry;
-
-    // Stores to each rank a list of nnz entries (i.e. pairs of row and column index)
-    // that this rank will send to. This nnz entries will be assembled on this rank,
-    // but because the row DOFs are not DOFs of this rank they will be send to the
-    // owner of the row DOFs.
-    std::map<int, MatrixNnzEntry> sendMatrixEntry;
-
-    for (int i = 0; i < nComponents; i++) {
-      for (int j = 0; j < nComponents; j++) {
- 	if ((*mat)[i][j]) {
-	  Matrix bmat = (*mat)[i][j]->getBaseMatrix();
-
-	  traits::col<Matrix>::type col(bmat);
-	  traits::const_value<Matrix>::type value(bmat);
-	  
-	  typedef traits::range_generator<row, Matrix>::type cursor_type;
-	  typedef traits::range_generator<nz, cursor_type>::type icursor_type;
-	  
-	  for (cursor_type cursor = begin<row>(bmat), 
-		 cend = end<row>(bmat); cursor != cend; ++cursor) {
-
-	    // Map the local row number to the global DOF index and create from it
-	    // the global PETSc row index of this DOF.
-	    int petscRowIdx = mapLocalGlobalDofs[*cursor] * nComponents + i;
-
-	    if (isRankDof[*cursor]) {
-
-	      // === The current row DOF is a rank dof, so create the corresponding ===
-	      // === nnz values directly on rank's nnz data.                        ===
-
-	      // This is the local row index of the local PETSc matrix.
-	      int localPetscRowIdx = petscRowIdx - rstart * nComponents;
-
-#if (DEBUG != 0)    
-	      if (localPetscRowIdx < 0 || localPetscRowIdx >= nRankRows) {
-		std::cout << "ERROR in rank: " << mpiRank << std::endl;
-		std::cout << "  Wrong r = " << localPetscRowIdx << " " << *cursor 
-			  << " " << mapLocalGlobalDofs[*cursor] << " " 
-			  << nRankRows << std::endl;
-		ERROR_EXIT("Should not happen!\n");
-	      }
-#endif
-	      
-	      // Traverse all non zero entries in this row.
-	      for (icursor_type icursor = begin<nz>(cursor), 
-		     icend = end<nz>(cursor); icursor != icend; ++icursor) {
-		if (value(*icursor) != 0.0) {
-		  int petscColIdx = mapLocalGlobalDofs[col(*icursor)] * nComponents + j;
-
-		  // The row DOF is a rank DOF, if also the column is a rank DOF, 
-		  // increment the d_nnz values for this row, otherwise the o_nnz value.
-		  if (petscColIdx >= rstart * nComponents && 
-		      petscColIdx < rstart * nComponents + nRankRows)
-		    d_nnz[localPetscRowIdx]++;
-		  else
-		    o_nnz[localPetscRowIdx]++;
-		}    
-	      }
-	    } else {
-	      
-	      // === The current row DOF is not a rank dof, i.e., it will be created ===
-	      // === on this rank, but after this it will be send to another rank    ===
-	      // === matrix. So we need to send also the corresponding nnz structure ===
-	      // === of this row to the corresponding rank.                          ===
-
-	      // Find out who is the member of this DOF.
-	      int sendToRank = -1;
-	      for (RankToDofContainer::iterator it = recvDofs.begin();
-		   it != recvDofs.end(); ++it) {
-		for (DofContainer::iterator dofIt = it->second.begin();
-		     dofIt != it->second.end(); ++dofIt) {
-		  if (**dofIt == *cursor) {
-
-		    if (petscRowIdx == 6717) {
-		      debug::writeDofMesh(mpiRank, *cursor, feSpace);
-		      MSG("SEND DOF TO: %d/%d\n", it->first, *cursor);
-		    }
-
-		    sendToRank = it->first;
-		    break;
-		  }
-		}
-
-		if (sendToRank != -1)
-		  break;
-	      }
-
-	      TEST_EXIT_DBG(sendToRank != -1)("Should not happen!\n");
-
-	      // Send all non zero entries to the member of the row DOF.
-	      for (icursor_type icursor = begin<nz>(cursor), 
-		     icend = end<nz>(cursor); icursor != icend; ++icursor) {
-		if (value(*icursor) != 0.0) {
-		  int petscColIdx = mapLocalGlobalDofs[col(*icursor)] * nComponents + j;
-		  
-		  sendMatrixEntry[sendToRank].
-		    push_back(std::make_pair(petscRowIdx, petscColIdx));
-		}
-	      }
-
-	    } // if (isRankDof[*cursor]) ... else ...
-	  } // for each row in mat[i][j]
-	} // if mat[i][j]
-      } 
-    }
-
-    // === Send and recv the nnz row structure to/from other ranks. ===
-
-    StdMpi<MatrixNnzEntry> stdMpi(mpiComm, true);
-    stdMpi.send(sendMatrixEntry);
-    stdMpi.recv(sendDofs);
-    stdMpi.startCommunication<int>(MPI_INT);
-
-    // === Evaluate the nnz structure this rank got from other ranks and add it to ===
-    // === the PETSc nnz data structure.                                           ===
-
-    for (std::map<int, MatrixNnzEntry>::iterator it = stdMpi.getRecvData().begin();
-	 it != stdMpi.getRecvData().end(); ++it) {
-      if (it->second.size() > 0) {
-	for (unsigned int i = 0; i < it->second.size(); i++) {
-	  int r = it->second[i].first;
-	  int c = it->second[i].second;
-
-	  int localRowIdx = r - rstart * nComponents;
-
-	  TEST_EXIT_DBG(localRowIdx >= 0 && localRowIdx < nRankRows)
-	    ("Got row index %d/%d (nRankRows = %d) from rank %d. Should not happen!\n",
-	     r, localRowIdx, nRankRows, it->first);
-	  
-	  if (c < rstart * nComponents || c >= rstart * nComponents + nRankRows)
-	    o_nnz[localRowIdx]++;
-	  else
-	    d_nnz[localRowIdx]++;
-	}
-      }
-    }  
-  }
-
-
-  void ParallelDomainBase::fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec)
-  {
-    FUNCNAME("ParallelDomainBase::fillPetscMatrix()");
-
-    clock_t first = clock();
-
-    // === Create PETSc vector (rhs, solution and a temporary vector). ===
-
-    VecCreate(PETSC_COMM_WORLD, &petscRhsVec);
-    VecSetSizes(petscRhsVec, nRankRows, nOverallRows);
-    VecSetType(petscRhsVec, VECMPI);
-
-    VecCreate(PETSC_COMM_WORLD, &petscSolVec);
-    VecSetSizes(petscSolVec, nRankRows, nOverallRows);
-    VecSetType(petscSolVec, VECMPI);
-
-    VecCreate(PETSC_COMM_WORLD, &petscTmpVec);
-    VecSetSizes(petscTmpVec, nRankRows, nOverallRows);
-    VecSetType(petscTmpVec, VECMPI);
-
-    if (!d_nnz)
-      createPetscNnzStructure(mat);
-
-    // === Create PETSc matrix with the computed nnz data structure. ===
-
-    MatCreateMPIAIJ(PETSC_COMM_WORLD, nRankRows, nRankRows, nOverallRows, nOverallRows,
-		    0, d_nnz, 0, o_nnz, &petscMatrix);
-
-    INFO(info, 8)("Fill petsc matrix 1 needed %.5f seconds\n", TIME_USED(first, clock()));
-
-#if (DEBUG != 0)
-    int a, b;
-    MatGetOwnershipRange(petscMatrix, &a, &b);
-    TEST_EXIT(a == rstart * nComponents)("Wrong matrix ownership range!\n");
-    TEST_EXIT(b == rstart * nComponents + nRankRows)("Wrong matrix ownership range!\n");
-#endif
-
-    // === Transfer values from DOF matrices to the PETSc matrix. === 
-
-    for (int i = 0; i < nComponents; i++)
-      for (int j = 0; j < nComponents; j++)
-	if ((*mat)[i][j])
-	  setDofMatrix((*mat)[i][j], nComponents, i, j);
-
-    INFO(info, 8)("Fill petsc matrix 2 needed %.5f seconds\n", TIME_USED(first, clock()));
-
-    MatAssemblyBegin(petscMatrix, MAT_FINAL_ASSEMBLY);
-    MatAssemblyEnd(petscMatrix, MAT_FINAL_ASSEMBLY);
-
-    // === Transfer values from DOF vector to the PETSc vector. === 
-
-    for (int i = 0; i < nComponents; i++)
-      setDofVector(petscRhsVec, vec->getDOFVector(i), nComponents, i);
-
-    VecAssemblyBegin(petscRhsVec);
-    VecAssemblyEnd(petscRhsVec);
-
-    INFO(info, 8)("Fill petsc matrix needed %.5f seconds\n", TIME_USED(first, clock()));
-  }
-
-
-  void ParallelDomainBase::solvePetscMatrix(SystemVector &vec)
-  {
-    FUNCNAME("ParallelDomainBase::solvePetscMatrix()");
-
-#if 0
-    // Set old solution to be initiual guess for petsc solver.
-    for (int i = 0; i < nComponents; i++)
-      setDofVector(petscSolVec, vec->getDOFVector(i), nComponents, i);
-
-    VecAssemblyBegin(petscSolVec);
-    VecAssemblyEnd(petscSolVec);
-#endif
-
-    // === Init Petsc solver. ===
-
-    KSP solver;
-    KSPCreate(PETSC_COMM_WORLD, &solver);
-    KSPSetOperators(solver, petscMatrix, petscMatrix, SAME_NONZERO_PATTERN); 
-    KSPSetTolerances(solver, 0.0, 1e-8, PETSC_DEFAULT, PETSC_DEFAULT);
-    KSPSetType(solver, KSPBCGS);
-    KSPMonitorSet(solver, myKSPMonitor, PETSC_NULL, 0);
-    KSPSetFromOptions(solver);
-    // Do not delete the solution vector, use it for the initial guess.
-    //    KSPSetInitialGuessNonzero(solver, PETSC_TRUE);
-
-
-    // === Run Petsc. ===
-
-    KSPSolve(solver, petscRhsVec, petscSolVec);
-
-    // === Transfere values from Petsc's solution vectors to the dof vectors.
-    PetscScalar *vecPointer;
-    VecGetArray(petscSolVec, &vecPointer);
-
-    for (int i = 0; i < nComponents; i++) {
-      DOFVector<double> *dofvec = vec.getDOFVector(i);
-      for (int j = 0; j < nRankDofs; j++)
-	(*dofvec)[mapLocalToDofIndex[j]] = vecPointer[j * nComponents + i];      
-    }
-
-    VecRestoreArray(petscSolVec, &vecPointer);
-
-
-    // === Synchronize dofs at common dofs, i.e., dofs that correspond to more ===
-    // === than one partition.                                                 ===
-    synchVector(vec);
-
-
-    // === Print information about solution process. ===
-
-    int iterations = 0;
-    KSPGetIterationNumber(solver, &iterations);
-    MSG("  Number of iterations: %d\n", iterations);
-    
-    double norm = 0.0;
-    MatMult(petscMatrix, petscSolVec, petscTmpVec);
-    VecAXPY(petscTmpVec, -1.0, petscRhsVec);
-    VecNorm(petscTmpVec, NORM_2, &norm);
-    MSG("  Residual norm: %e\n", norm);
-
-
-    // === Destroy Petsc's variables. ===
-
-    MatDestroy(petscMatrix);
-    VecDestroy(petscRhsVec);
-    VecDestroy(petscSolVec);
-    VecDestroy(petscTmpVec);
-    KSPDestroy(solver);
-  }
-  
-
   void ParallelDomainBase::synchVector(DOFVector<double> &vec)
   {
     StdMpi<std::vector<double> > stdMpi(mpiComm);
@@ -868,6 +409,7 @@ namespace AMDiS {
     // === If there is a non zero pattern computed for Petsc matrix, delete it. So ===
     // === it will be recomputed after next assembling.                            ===
 
+#if 0
     if (d_nnz) {
       delete [] d_nnz;
       d_nnz = NULL;
@@ -877,6 +419,7 @@ namespace AMDiS {
       delete [] o_nnz;
       o_nnz = NULL;
     }
+#endif
   }
 
   
@@ -2354,29 +1897,6 @@ namespace AMDiS {
   }
 
 
-  void ParallelDomainBase::solve()
-  {
-    FUNCNAME("ParallelDomainBase::solve()");
-
-#ifdef _OPENMP
-    double wtime = omp_get_wtime();
-#endif
-    clock_t first = clock();
-
-    fillPetscMatrix(probStat->getSystemMatrix(), probStat->getRHS());
-    solvePetscMatrix(*(probStat->getSolution()));
-
-#ifdef _OPENMP
-    INFO(info, 8)("solution of discrete system needed %.5f seconds system time / %.5f seconds wallclock time\n",
-		   TIME_USED(first, clock()),
-		   omp_get_wtime() - wtime);
-#else
-    INFO(info, 8)("solution of discrete system needed %.5f seconds\n",
-		   TIME_USED(first, clock()));
-#endif    
-  }
-
-
   void ParallelDomainBase::serialize(std::ostream &out)
   {
     SerUtil::serialize(out, elemWeights);
diff --git a/AMDiS/src/parallel/ParallelDomainBase.h b/AMDiS/src/parallel/ParallelDomainBase.h
index a3136f9fb4313977f30cf10caf36604239f71ed6..e8fbd32c67fd110548c5053d311b6f09508d4730 100644
--- a/AMDiS/src/parallel/ParallelDomainBase.h
+++ b/AMDiS/src/parallel/ParallelDomainBase.h
@@ -38,10 +38,6 @@
 #include "BoundaryManager.h"
 #include "AMDiS_fwd.h"
 
-#include "petsc.h"
-#include "petscsys.h"
-#include "petscao.h"
-
 namespace AMDiS {
 
   struct DofPtrSortFct {
@@ -56,7 +52,7 @@ namespace AMDiS {
   class ParallelDomainBase : public ProblemIterationInterface,
 			     public ProblemTimeInterface
   {
-  private:
+  protected:
     /// Defines a mapping type from DOFs to rank numbers.
     typedef std::map<const DegreeOfFreedom*, int> DofToRank;
 
@@ -163,7 +159,7 @@ namespace AMDiS {
       iterationIF->endIteration(adaptInfo);
     }
 
-    virtual void solve();
+    virtual void solve() = 0;
 
     virtual int getNumProblems() 
     {
@@ -181,8 +177,6 @@ namespace AMDiS {
       return nRankDofs;
     }
 
-    void solvePetscMatrix(SystemVector &vec);
-
     virtual ProblemStatBase *getProblem(int number = 0) 
     {
       return NULL;
@@ -267,27 +261,6 @@ namespace AMDiS {
 			     DofToRank& boundaryDofs,
 			     DofToBool& vertexDof);
 
-    /// Creates a new non zero pattern structure for the Petsc matrix. 
-    void createPetscNnzStructure(Matrix<DOFMatrix*> *mat);
-
-    /** \brief
-     * Create a PETSc matrix and PETSc vectors. The given DOF matrices are used to
-     * create the nnz structure of the PETSc matrix and the values are transfered to it.
-     * The given DOF vectors are used to the the values of the PETSc rhs vector.
-     *
-     * \param[in] mat
-     * \param[in] vec
-     */
-    void fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec);
-
-    /// Takes a dof matrix and sends the values to the global petsc matrix.
-    void setDofMatrix(DOFMatrix* mat, int dispMult = 1, 
-		      int dispAddRow = 0, int dispAddCol = 0);
-
-    /// Takes a dof vector and sends its values to a given petsc vector.
-    void setDofVector(Vec& petscVec, DOFVector<double>* vec, 
-		      int disMult = 1, int dispAdd = 0);
-
     /** \brief
      * Checks for all given interior boundaries if the elements fit together on both
      * sides of the boundaries. If this is not the case, the mesh is adapted. Because
@@ -541,19 +514,7 @@ namespace AMDiS {
      * of the parition it corresponds to is stored.
      */
     std::map<int, int> oldPartitionVec;    
-
-    /// Petsc's matrix structure.
-    Mat petscMatrix;
-
-    /** \brief
-     * Petsc's vector structures for the rhs vector, the solution vector and a
-     * temporary vector for calculating the final residuum.
-     */
-    Vec petscRhsVec, petscSolVec, petscTmpVec;
-
-    /// Arrays definig the non zero pattern of Petsc's matrix.
-    int *d_nnz, *o_nnz;
-    
+   
     /// Number of DOFs in the rank mesh.
     int nRankDofs;
 
diff --git a/AMDiS/src/parallel/ParallelDomainVec.cc b/AMDiS/src/parallel/ParallelDomainVec.cc
deleted file mode 100644
index 3ba7af68e180f5f13b4aee496d66800e783c3ba4..0000000000000000000000000000000000000000
--- a/AMDiS/src/parallel/ParallelDomainVec.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "boost/lexical_cast.hpp"
-#include "ParallelDomainVec.h"
-#include "ProblemVec.h"
-#include "ProblemInstat.h"
-#include "SystemVector.h"
-#include "Serializer.h"
-#include "BoundaryManager.h"
-
-namespace AMDiS {
-
-  using boost::lexical_cast;
-
-  ParallelDomainVec::ParallelDomainVec(ProblemVec *problem,
-				       ProblemInstatVec *problemInstat)
-    : ParallelDomainBase(problem, problemInstat)
-  {
-    FUNCNAME("ParallelDomainVec::ParallelDomainVec()");
-
-  }
-}
diff --git a/AMDiS/src/parallel/ParallelDomainVec.h b/AMDiS/src/parallel/ParallelDomainVec.h
deleted file mode 100644
index c234c07990c1d36a788b57cbb714642b0b43a9e8..0000000000000000000000000000000000000000
--- a/AMDiS/src/parallel/ParallelDomainVec.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// ============================================================================
-// ==                                                                        ==
-// == AMDiS - Adaptive multidimensional simulations                          ==
-// ==                                                                        ==
-// ============================================================================
-// ==                                                                        ==
-// ==  TU Dresden                                                            ==
-// ==                                                                        ==
-// ==  Institut f�r Wissenschaftliches Rechnen                               ==
-// ==  Zellescher Weg 12-14                                                  ==
-// ==  01069 Dresden                                                         ==
-// ==  germany                                                               ==
-// ==                                                                        ==
-// ============================================================================
-// ==                                                                        ==
-// ==  https://gforge.zih.tu-dresden.de/projects/amdis/                      ==
-// ==                                                                        ==
-// ============================================================================
-
-/** \file ParallelDomainVec.h */
-
-#ifndef AMDIS_PARALLELDOMAINVEC_H
-#define AMDIS_PARALLELDOMAINVEC_H
-
-#include "ParallelDomainBase.h"
-#include "ProblemVec.h"
-#include "BoundaryManager.h"
-
-namespace AMDiS {
-
-  class ParallelDomainVec : public ParallelDomainBase
-  {
-  public:
-    ParallelDomainVec(ProblemVec *problem,
-		      ProblemInstatVec *problemInstat);
-  };
-
-}
-
-#endif // AMDIS_PARALLELDOMAINVEC_H
diff --git a/AMDiS/src/parallel/StdMpi.cc b/AMDiS/src/parallel/StdMpi.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6e1e525fb352bbfb4592ca3452bf6c7f9c3e65f9
--- /dev/null
+++ b/AMDiS/src/parallel/StdMpi.cc
@@ -0,0 +1,220 @@
+#include "StdMpi.h"
+
+namespace AMDiS {
+
+  int intSizeOf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data)
+  {
+    return data.size() * 2;
+  }
+
+  int intSizeOf(std::vector<MeshStructure> &data)
+  {
+    int s = 0;
+    for (unsigned int i = 0; i < data.size(); i++)
+      s += data[i].getCode().size() + 2;
+
+    return s;
+  }
+
+  int intSizeOf(std::vector<WorldVector<double> > &data)
+  {
+    return data.size() * Global::getGeo(WORLD);
+  }
+
+  int intSizeOf(std::vector<int> &data)
+  {
+    return data.size();
+  }
+
+  int intSizeOf(std::vector<double> &data)
+  {
+    return data.size();
+  }
+  
+  int intSizeOf(std::vector<std::pair<int, int> > &data)
+  {
+    return data.size() * 2;
+  }
+
+  int intSizeOf(std::vector<AtomicBoundary> &data)
+  {
+    return data.size() * 3;
+  }
+
+  int intSizeOf(std::vector<BoundaryObject> &data)
+  {
+    return data.size() * 5;
+  }
+
+  int intSizeOf(std::vector<const DegreeOfFreedom*> &data)
+  {
+    return data.size();
+  }
+
+  void makeBuf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data, int* buf)
+  {
+    int i = 0;
+    for (std::map<const DegreeOfFreedom*, DegreeOfFreedom>::iterator it = data.begin();
+	 it != data.end(); ++it) {
+      buf[i++] = *(it->first);
+      buf[i++] = it->second;
+    }
+  }
+  
+  void makeFromBuf(std::vector<std::pair<DegreeOfFreedom, DegreeOfFreedom> > &data, 
+		   int *buf, int bufSize)
+  {    
+    if (bufSize == 0)
+      return;
+
+    TEST_EXIT(bufSize % 2 == 0)("This should not happen!\n");
+
+    data.clear();
+    data.reserve(bufSize / 2);
+
+    for (int i = 0; i < (bufSize / 2); i++)
+      data.push_back(std::make_pair(buf[i * 2], buf[i * 2 + 1]));
+  }
+
+  void makeBuf(std::vector<MeshStructure> &data, unsigned long int *buf)
+  {    
+    int pos = 0;
+    for (unsigned int i = 0; i < data.size(); i++) {
+      buf[pos++] = data[i].getCode().size();
+      buf[pos++] = data[i].getNumElements();
+
+      for (unsigned int j = 0; j < data[i].getCode().size(); j++)
+	buf[pos++] = data[i].getCode()[j];
+    }
+  }
+
+  void makeFromBuf(std::vector<MeshStructure> &data, 
+		   unsigned long int *buf, int bufSize)
+  {
+    int pos = 0;
+
+    while (pos < bufSize) {       
+      int codeSize = buf[pos++];
+      int nElements = buf[pos++];
+      std::vector<unsigned long int> code;
+      code.resize(codeSize);
+      for (int i = 0; i < codeSize; i++)
+	code[i] = buf[pos++];
+
+      MeshStructure meshCode;
+      meshCode.init(code, nElements);
+
+      data.push_back(meshCode);
+    }	
+  }
+
+  void makeBuf(std::vector<WorldVector<double> > &data, double *buf)
+  {
+    int dimOfWorld = Global::getGeo(WORLD);
+    int pos = 0;
+    for (unsigned int i = 0; i < data.size(); i++)
+      for (int j = 0; j < dimOfWorld; j++)
+	buf[pos++] = data[i][j];
+  }
+
+  void makeFromBuf(std::vector<WorldVector<double> > &data, double *buf, int bufSize)
+  {
+    int dimOfWorld = Global::getGeo(WORLD);
+    TEST_EXIT(bufSize % Global::getGeo(WORLD) == 0)("This should not happen!\n");
+
+    int pos = 0;
+    data.resize(bufSize / Global::getGeo(WORLD));
+    for (unsigned int i = 0; i < data.size(); i++)
+      for (int j = 0; j < dimOfWorld; j++)
+	data[i][j] = buf[pos++];
+  }
+
+  void makeBuf(std::vector<int> &data, int *buf)
+  {
+    for (unsigned int i = 0; i < data.size(); i++)
+      buf[i] = data[i];
+  }
+
+  void makeFromBuf(std::vector<int> &data, int *buf, int bufSize)
+  {
+    data.resize(bufSize);
+
+    for (int i = 0; i < bufSize; i++)
+      data[i] = buf[i];
+  }
+
+  void makeBuf(std::vector<double> &data, double *buf)
+  {
+    for (unsigned int i = 0; i < data.size(); i++)
+      buf[i] = data[i];
+  }
+
+  void makeFromBuf(std::vector<double> &data, double *buf, int bufSize)
+  {
+    data.resize(bufSize);
+
+    for (int i = 0; i < bufSize; i++)
+      data[i] = buf[i];
+  }
+
+  void makeBuf(std::vector<std::pair<int, int> > &data, int *buf)
+  {
+    for (unsigned int i = 0; i < data.size(); i++) {
+      buf[i * 2] = data[i].first;
+      buf[i * 2 + 1] = data[i].second;
+    }
+  }
+
+  void makeBuf(std::vector<AtomicBoundary> &data, int *buf)
+  {
+    for (unsigned int i = 0; i < data.size(); i++) {
+      buf[i * 3] = data[i].rankObj.elIndex;
+      buf[i * 3 + 1] = data[i].rankObj.subObj;
+      buf[i * 3 + 2] = data[i].rankObj.ithObj;
+    }
+  }
+
+  void makeFromBuf(std::vector<AtomicBoundary> &data, int *buf, int bufSize)
+  {
+    if (bufSize == 0)
+      return;
+
+    TEST_EXIT(bufSize % 3 == 0)("This should not happen!\n");    
+
+    data.resize(bufSize / 3);
+    for (int i = 0; i < bufSize / 3; i++) {
+      data[i].rankObj.elIndex = buf[i * 3];
+      data[i].rankObj.subObj = static_cast<GeoIndex>(buf[i * 3 + 1]);
+      data[i].rankObj.ithObj = buf[i * 3 + 2];
+    }
+  }
+
+  void makeBuf(std::vector<BoundaryObject> &data, int *buf)
+  {
+    for (unsigned int i = 0; i < data.size(); i++) {
+      buf[i * 5] = data[i].elIndex;
+      buf[i * 5 + 1] = data[i].elType;
+      buf[i * 5 + 2] = data[i].subObj;
+      buf[i * 5 + 3] = data[i].ithObj;
+      buf[i * 5 + 4] = data[i].reverseMode;
+    }
+  }
+
+  void makeFromBuf(std::vector<BoundaryObject> &data, int *buf, int bufSize)
+  {
+    if (bufSize == 0)
+      return;
+
+    TEST_EXIT(bufSize % 5 == 0)("This should not happen!\n");    
+
+    data.resize(bufSize / 5);
+    for (int i = 0; i < bufSize / 5; i++) {
+      data[i].elIndex = buf[i * 5];
+      data[i].elType = buf[i * 5 + 1];
+      data[i].subObj = static_cast<GeoIndex>(buf[i * 5 + 2]);
+      data[i].ithObj = buf[i * 5 + 3];
+      data[i].reverseMode = static_cast<bool>(buf[i * 5 + 4]);
+    }
+  }
+
+}
diff --git a/AMDiS/src/parallel/StdMpi.h b/AMDiS/src/parallel/StdMpi.h
index d7eea5fc0a302fca8b980ee34ab823d65272eca8..0c74719f4ae126d45e529fa257f28201f3df0471 100644
--- a/AMDiS/src/parallel/StdMpi.h
+++ b/AMDiS/src/parallel/StdMpi.h
@@ -29,220 +29,57 @@
 
 namespace AMDiS {
 
-  int intSizeOf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data)
-  {
-    return data.size() * 2;
-  }
+  int intSizeOf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data);
 
-  int intSizeOf(std::vector<MeshStructure> &data)
-  {
-    int s = 0;
-    for (unsigned int i = 0; i < data.size(); i++)
-      s += data[i].getCode().size() + 2;
+  int intSizeOf(std::vector<MeshStructure> &data);
 
-    return s;
-  }
+  int intSizeOf(std::vector<WorldVector<double> > &data);
 
-  int intSizeOf(std::vector<WorldVector<double> > &data)
-  {
-    return data.size() * Global::getGeo(WORLD);
-  }
-
-  int intSizeOf(std::vector<int> &data)
-  {
-    return data.size();
-  }
+  int intSizeOf(std::vector<int> &data);
 
-  int intSizeOf(std::vector<double> &data)
-  {
-    return data.size();
-  }
+  int intSizeOf(std::vector<double> &data);
   
-  int intSizeOf(std::vector<std::pair<int, int> > &data)
-  {
-    return data.size() * 2;
-  }
+  int intSizeOf(std::vector<std::pair<int, int> > &data);
 
-  int intSizeOf(std::vector<AtomicBoundary> &data)
-  {
-    return data.size() * 3;
-  }
+  int intSizeOf(std::vector<AtomicBoundary> &data);
 
-  int intSizeOf(std::vector<BoundaryObject> &data)
-  {
-    return data.size() * 5;
-  }
+  int intSizeOf(std::vector<BoundaryObject> &data);
 
-  int intSizeOf(std::vector<const DegreeOfFreedom*> &data)
-  {
-    return data.size();
-  }
+  int intSizeOf(std::vector<const DegreeOfFreedom*> &data);
 
-  void makeBuf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data, int* buf)
-  {
-    int i = 0;
-    for (std::map<const DegreeOfFreedom*, DegreeOfFreedom>::iterator it = data.begin();
-	 it != data.end(); ++it) {
-      buf[i++] = *(it->first);
-      buf[i++] = it->second;
-    }
-  }
+  void makeBuf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data, int* buf);
   
   void makeFromBuf(std::vector<std::pair<DegreeOfFreedom, DegreeOfFreedom> > &data, 
-		   int *buf, int bufSize)
-  {    
-    if (bufSize == 0)
-      return;
-
-    TEST_EXIT(bufSize % 2 == 0)("This should not happen!\n");
-
-    data.clear();
-    data.reserve(bufSize / 2);
-
-    for (int i = 0; i < (bufSize / 2); i++)
-      data.push_back(std::make_pair(buf[i * 2], buf[i * 2 + 1]));
-  }
+		   int *buf, int bufSize);
 
-  void makeBuf(std::vector<MeshStructure> &data, unsigned long int *buf)
-  {    
-    int pos = 0;
-    for (unsigned int i = 0; i < data.size(); i++) {
-      buf[pos++] = data[i].getCode().size();
-      buf[pos++] = data[i].getNumElements();
-
-      for (unsigned int j = 0; j < data[i].getCode().size(); j++)
-	buf[pos++] = data[i].getCode()[j];
-    }
-  }
+  void makeBuf(std::vector<MeshStructure> &data, unsigned long int *buf);
 
   void makeFromBuf(std::vector<MeshStructure> &data, 
-		   unsigned long int *buf, int bufSize)
-  {
-    int pos = 0;
+		   unsigned long int *buf, int bufSize);
 
-    while (pos < bufSize) {       
-      int codeSize = buf[pos++];
-      int nElements = buf[pos++];
-      std::vector<unsigned long int> code;
-      code.resize(codeSize);
-      for (int i = 0; i < codeSize; i++)
-	code[i] = buf[pos++];
+  void makeBuf(std::vector<WorldVector<double> > &data, double *buf);
 
-      MeshStructure meshCode;
-      meshCode.init(code, nElements);
+  void makeFromBuf(std::vector<WorldVector<double> > &data, double *buf, int bufSize);
 
-      data.push_back(meshCode);
-    }	
-  }
+  void makeBuf(std::vector<int> &data, int *buf);
 
-  void makeBuf(std::vector<WorldVector<double> > &data, double *buf)
-  {
-    int dimOfWorld = Global::getGeo(WORLD);
-    int pos = 0;
-    for (unsigned int i = 0; i < data.size(); i++)
-      for (int j = 0; j < dimOfWorld; j++)
-	buf[pos++] = data[i][j];
-  }
-
-  void makeFromBuf(std::vector<WorldVector<double> > &data, double *buf, int bufSize)
-  {
-    int dimOfWorld = Global::getGeo(WORLD);
-    TEST_EXIT(bufSize % Global::getGeo(WORLD) == 0)("This should not happen!\n");
+  void makeFromBuf(std::vector<int> &data, int *buf, int bufSize);
 
-    int pos = 0;
-    data.resize(bufSize / Global::getGeo(WORLD));
-    for (unsigned int i = 0; i < data.size(); i++)
-      for (int j = 0; j < dimOfWorld; j++)
-	data[i][j] = buf[pos++];
-  }
+  void makeBuf(std::vector<double> &data, double *buf);
 
-  void makeBuf(std::vector<int> &data, int *buf)
-  {
-    for (unsigned int i = 0; i < data.size(); i++)
-      buf[i] = data[i];
-  }
+  void makeFromBuf(std::vector<double> &data, double *buf, int bufSize);
 
-  void makeFromBuf(std::vector<int> &data, int *buf, int bufSize)
-  {
-    data.resize(bufSize);
+  void makeBuf(std::vector<std::pair<int, int> > &data, int *buf);
 
-    for (int i = 0; i < bufSize; i++)
-      data[i] = buf[i];
-  }
+  void makeBuf(std::vector<AtomicBoundary> &data, int *buf);
 
-  void makeBuf(std::vector<double> &data, double *buf)
-  {
-    for (unsigned int i = 0; i < data.size(); i++)
-      buf[i] = data[i];
-  }
-
-  void makeFromBuf(std::vector<double> &data, double *buf, int bufSize)
-  {
-    data.resize(bufSize);
+  void makeFromBuf(std::vector<AtomicBoundary> &data, int *buf, int bufSize);
 
-    for (int i = 0; i < bufSize; i++)
-      data[i] = buf[i];
-  }
+  void makeBuf(std::vector<BoundaryObject> &data, int *buf);
 
-  void makeBuf(std::vector<std::pair<int, int> > &data, int *buf)
-  {
-    for (unsigned int i = 0; i < data.size(); i++) {
-      buf[i * 2] = data[i].first;
-      buf[i * 2 + 1] = data[i].second;
-    }
-  }
+  void makeFromBuf(std::vector<BoundaryObject> &data, int *buf, int bufSize);
 
-  void makeBuf(std::vector<AtomicBoundary> &data, int *buf)
-  {
-    for (unsigned int i = 0; i < data.size(); i++) {
-      buf[i * 3] = data[i].rankObj.elIndex;
-      buf[i * 3 + 1] = data[i].rankObj.subObj;
-      buf[i * 3 + 2] = data[i].rankObj.ithObj;
-    }
-  }
 
-  void makeFromBuf(std::vector<AtomicBoundary> &data, int *buf, int bufSize)
-  {
-    if (bufSize == 0)
-      return;
-
-    TEST_EXIT(bufSize % 3 == 0)("This should not happen!\n");    
-
-    data.resize(bufSize / 3);
-    for (int i = 0; i < bufSize / 3; i++) {
-      data[i].rankObj.elIndex = buf[i * 3];
-      data[i].rankObj.subObj = static_cast<GeoIndex>(buf[i * 3 + 1]);
-      data[i].rankObj.ithObj = buf[i * 3 + 2];
-    }
-  }
-
-  void makeBuf(std::vector<BoundaryObject> &data, int *buf)
-  {
-    for (unsigned int i = 0; i < data.size(); i++) {
-      buf[i * 5] = data[i].elIndex;
-      buf[i * 5 + 1] = data[i].elType;
-      buf[i * 5 + 2] = data[i].subObj;
-      buf[i * 5 + 3] = data[i].ithObj;
-      buf[i * 5 + 4] = data[i].reverseMode;
-    }
-  }
-
-  void makeFromBuf(std::vector<BoundaryObject> &data, int *buf, int bufSize)
-  {
-    if (bufSize == 0)
-      return;
-
-    TEST_EXIT(bufSize % 5 == 0)("This should not happen!\n");    
-
-    data.resize(bufSize / 5);
-    for (int i = 0; i < bufSize / 5; i++) {
-      data[i].elIndex = buf[i * 5];
-      data[i].elType = buf[i * 5 + 1];
-      data[i].subObj = static_cast<GeoIndex>(buf[i * 5 + 2]);
-      data[i].ithObj = buf[i * 5 + 3];
-      data[i].reverseMode = static_cast<bool>(buf[i * 5 + 4]);
-    }
-  }
 
   template<typename SendT, typename RecvT=SendT>
   class StdMpi