diff --git a/cmake/modules/AddUMFPackFlags.cmake b/cmake/modules/AddUMFPackFlags.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5ed6cdc2b45dcb5b8c18004db04d65c677f0cadb
--- /dev/null
+++ b/cmake/modules/AddUMFPackFlags.cmake
@@ -0,0 +1,18 @@
+# module providing convenience mehtods for compiling bianries with UMFPack support
+#
+# Provides the following functions:
+#
+# add_dune_umfpack_flags(target1 target2...)
+#
+# adds UMFPack flags to the targets for compilation and linking
+function(add_dune_umfpack_flags _targets)
+  if(UMFPACK_FOUND)
+    foreach(_target ${_targets})
+      target_link_libraries(${_target} ${UMFPACK_DUNE_LIBRARIES})
+      get_target_property(_props ${_target} COMPILE_FLAGS)
+      string(REPLACE "_props-NOTFOUND" "" _props "${_props}")
+      set_target_properties(${_target} PROPERTIES COMPILE_FLAGS
+        "${_props} ${UMFPACK_DUNE_COMPILE_FLAGS} -DENABLE_UMFPACK")
+    endforeach(_target ${_targets})
+  endif(UMFPACK_FOUND)
+endfunction(add_dune_umfpack_flags)
\ No newline at end of file
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
index b9bbda94686b3c4f4c0c4b3e18e5946ede991096..84d034cedfda0459747696f572c23622c6d1d746 100644
--- a/cmake/modules/CMakeLists.txt
+++ b/cmake/modules/CMakeLists.txt
@@ -1,7 +1,9 @@
 set(modules
   AddSuperLUFlags.cmake
+  AddUMFPackFlags.cmake
   DuneIstlMacros.cmake
-  FindSuperLU.cmake)
+  FindSuperLU.cmake
+  FindUMFPack.cmake)
 
 install(FILES ${modules} DESTINATION
   ${DUNE_INSTALL_MODULEDIR})
diff --git a/cmake/modules/DuneIstlMacros.cmake b/cmake/modules/DuneIstlMacros.cmake
index d9d87a3748b8f62f5e3ba12008bbc528e51e47a1..3f4d7594d3cc9bd3642514affdb1a39385a3b948 100644
--- a/cmake/modules/DuneIstlMacros.cmake
+++ b/cmake/modules/DuneIstlMacros.cmake
@@ -3,3 +3,5 @@ find_package(ParMETIS)
 include(AddParMETISFlags)
 find_package(SuperLU)
 include(AddSuperLUFlags)
+find_package(UMFPack)
+include(AddUMFPackFlags)
diff --git a/cmake/modules/FindUMFPack.cmake b/cmake/modules/FindUMFPack.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..8e60b4350c412e62d9d560b11275070a29cc04c0
--- /dev/null
+++ b/cmake/modules/FindUMFPack.cmake
@@ -0,0 +1,112 @@
+# Module that checks whether UMFPack is available.
+#
+# Variables used by this module which you may want to set:
+# UMFPACK_ROOT   Path list to search for UMFPack
+#
+# Sets the following variables
+#
+# UMFPACK_FOUND          True if UMFPack was found and usable
+# UMFPACK_INCLUDE_DIRS   Path to the UMFPack include dirs
+# UMFPACK_LIBRARIES      Name of the UMFPack libraries
+#
+
+find_package(BLAS QUIET REQUIRED)
+if(NOT BLAS_FOUND)
+  message(WARNING "UMFPack requires BLAS which was not found, skipping the test.")
+  return()
+endif()
+
+find_library(AMD_LIBRARY
+  NAMES "amd"
+  PATHS ${UMFPACK_ROOT}
+  PATH_SUFFIXES "lib" "lib32" "lib64" "AMD" "AMD/Lib"
+  NO_DEFAULT_PATH
+)
+
+find_library(AMD_LIBRARY
+  NAMES "amd"
+  PATH_SUFFIXES "lib" "lib32" "lib64" "AMD" "AMD/Lib"
+)
+
+if(NOT AMD_LIBRARY)
+  message(WARNING "UMFPack requires AMD which was not found, skipping the test.")
+  return()
+endif()
+
+#look for header files at positions given by the user
+find_path(UMFPACK_INCLUDE_DIR
+  NAMES "umfpack.h"
+  PATHS ${UMFPACK_ROOT}
+  PATH_SUFFIXES "umfpack" "include/umfpack" "suitesparse" "include" "src" "UMFPACK" "UMFPACK/Include"
+  NO_DEFAULT_PATH
+)
+#now also look for default paths
+find_path(UMFPACK_INCLUDE_DIR
+  NAMES "umfpack.h"
+  PATH_SUFFIXES "umfpack" "include/umfpack" "suitesparse" "include" "UMFPACK" "UMFPACK/Include"
+)
+
+#look for library at positions given by the user
+find_library(UMFPACK_LIBRARY
+  NAMES "umfpack"
+  PATHS ${UMFPACK_ROOT}
+  PATH_SUFFIXES "lib" "lib32" "lib64" "UMFPACK" "UMFPACK/Lib"
+  NO_DEFAULT_PATH
+)
+#now  also include the deafult paths
+find_library(UMFPACK_LIBRARY
+  NAMES "umfpack"
+  PATH_SUFFIXES "lib" "lib32" "lib64" "UMFPACK" "UMFPACK/Lib"
+)
+
+if(UMFPACK_INCLUDE_DIR)
+  set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${UMFPACK_INCLUDE_DIR} ${AMD_INCLUDE_DIR})
+endif()
+if(UMFPACK_LIBRARY)
+  set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${UMFPACK_LIBRARY})
+endif()
+if(BLAS_LIBRARIES)
+  set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${BLAS_LIBRARIES})
+endif()
+if(AMD_LIBRARY)
+  set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${AMD_LIBRARY})
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+  "UMFPack"
+  DEFAULT_MSG
+  UMFPACK_INCLUDE_DIR
+  UMFPACK_LIBRARY
+)
+
+mark_as_advanced(UMFPACK_INCLUDE_DIR UMFPACK_LIBRARY)
+
+if(UMFPACK_FOUND)
+  set(UMFPACK_INCLUDE_DIRS ${UMFPACK_INCLUDE_DIR})
+  set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARY})
+  file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+    "Determining location of UMFPack succeded:\n"
+    "Include directory: ${UMFPACK_INCLUDE_DIRS}\n"
+    "Library directory: ${UMFPACK_LIBRARIES}\n\n")
+  set(UMFPACK_DUNE_COMPILE_FLAGS "-I${UMFPACK_INCLUDE_DIRS}"
+    CACHE STRING "Compile Flags used by DUNE when compiling with UMFPack programs")
+  set(UMFPACK_DUNE_LIBRARIES ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES} ${AMD_LIBRARY}
+    CACHE STRING "LIbraries used by DUNE when linking UMFPack programs")
+else(UMFPACK_FOUND)
+  file(APPEND ${CMAKE_BINARY_DIR}${CMAKES_FILES_DIRECTORY}/CMakeError.log
+    "Determing location of UMFPack failed:\n"
+    "Include directory: ${UMFPACK_INCLUDE_DIRS}\n"
+    "Library directory: ${UMFPACK_LIBRARIES}\n\n")
+endif(UMFPACK_FOUND)
+
+#set HAVE_UMFPACK for config.h
+set(HAVE_UMFPACK UMFPACK_FOUND)
+
+#add all umfpack related flags to ALL_PKG_FLAGS, this must happen regardless of a target using add_dune_umfpack_flags
+if(UMFPACK_FOUND)
+  set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "${UMFPACK_DUNE_COMPILE_FLAGS}")
+  foreach(dir "${UMFPACK_INCLUDE_DIRS}")
+    set_property(GLOBAL APPEND PROPERTY ALL_PKG_FLAGS "-I${dir}")
+  endforeach()
+endif()
\ No newline at end of file
diff --git a/cmake/modules/Makefile.am b/cmake/modules/Makefile.am
index 1c8e622ffcaec8cc316d1c9a3f4cd64ec79da259..9c3e667f30de9149dbf978e8e4744b976ea926a5 100644
--- a/cmake/modules/Makefile.am
+++ b/cmake/modules/Makefile.am
@@ -1,5 +1,8 @@
-MODULES = DuneIstlMacros.cmake \
- FindSuperLU.cmake
+MODULES = AddSuperLUFlags.cmake \
+ AddUMFPackFlags.cmake \
+ DuneIstlMacros.cmake \
+ FindSuperLU.cmake \
+ FindUMFPack.cmake
 
 modulesdir= $(datadir)/cmake/modules
 dist_modules_DATA = ${MODULES}
diff --git a/config.h.cmake b/config.h.cmake
index d7894dc2ac100a662a2c5d4d1a6c1ddb3e62edfa..5c460704e8810296d0390cea0f35e4d6135c304a 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -42,6 +42,9 @@
 /* Define to ENABLE_SUPERLU if the SuperLU library is available */
 #cmakedefine HAVE_SUPERLU ENABLE_SUPERLU
 
+/* Define to if the UMFPack library is available */
+#cmakedefine HAVE_UMFPACK ENABLE_UMFPACK
+
 /* define to 1 because older versions of SuperLU are no longer supported*/
 #define SUPERLU_POST_2005_VERSION 1
 
diff --git a/dune/istl/CMakeLists.txt b/dune/istl/CMakeLists.txt
index f96b0548f8804ec4f3f5c96fffd9f99396f0c47f..e9db20ef8d4ba539e34fd5c8df81ce2553bd5dc5 100644
--- a/dune/istl/CMakeLists.txt
+++ b/dune/istl/CMakeLists.txt
@@ -9,6 +9,7 @@ install(FILES
    bdmatrix.hh
    btdmatrix.hh
    bvector.hh
+   colcompmatrix.hh
    diagonalmatrix.hh
    gsetc.hh
    ilu.hh
@@ -40,5 +41,6 @@ install(FILES
    solvertype.hh
    superlu.hh
    supermatrix.hh
+   umfpack.hh
    vbvector.hh
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/istl)
diff --git a/dune/istl/Makefile.am b/dune/istl/Makefile.am
index f36255c2653eb53d16d23bf2212efb7fbaa413c3..06c2c3137114a8345301b28492d7a5c89da52e76 100644
--- a/dune/istl/Makefile.am
+++ b/dune/istl/Makefile.am
@@ -8,6 +8,7 @@ istl_HEADERS = basearray.hh \
 	bdmatrix.hh \
 	btdmatrix.hh \
 	bvector.hh \
+	colcompmatrix.hh \
 	diagonalmatrix.hh \
 	gsetc.hh \
 	ilu.hh \
@@ -39,8 +40,8 @@ istl_HEADERS = basearray.hh \
 	solvertype.hh \
 	superlu.hh \
 	supermatrix.hh \
-	vbvector.hh
-
+	vbvector.hh \
+	umfpack.hh
 
 include $(top_srcdir)/am/global-rules
 
diff --git a/dune/istl/colcompmatrix.hh b/dune/istl/colcompmatrix.hh
new file mode 100644
index 0000000000000000000000000000000000000000..e4cc3bdeb3ec6a255d93f1ac08442edf50ec61e7
--- /dev/null
+++ b/dune/istl/colcompmatrix.hh
@@ -0,0 +1,597 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COLCOMPMATRIX_HH
+#define DUNE_COLCOMPMATRIX_HH
+#include "bcrsmatrix.hh"
+#include "bvector.hh"
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/typetraits.hh>
+#include <limits>
+
+namespace Dune
+{
+  /**
+   * @brief Provides access to an iterator over all matrix rows.
+   *
+   * @tparam M The type of the matrix.
+   */
+  template<class M>
+  class MatrixRowSet
+  {
+  public:
+    //! @brief The type of the matrix.
+    typedef M Matrix;
+    //! @brief The matrix row iterator type.
+    typedef typename Matrix::ConstRowIterator const_iterator;
+
+    /**
+     * @brief Construct an row set over all matrix rows.
+     * @param m The matrix for which we manage the rows.
+     */
+    MatrixRowSet(const Matrix& m)
+      : m_(m)
+    {}
+
+    //! @brief Get the row iterator at the first row.
+    const_iterator begin() const
+    {
+      return m_.begin();
+    }
+    //! @brief Get the row iterator at the end of all rows.
+    const_iterator end() const
+    {
+      return m_.end();
+    }
+  private:
+    const Matrix& m_;
+  };
+
+  /**
+   * @brief Provides access to an iterator over an arbitrary subset
+   * of matrix rows.
+   *
+   * @tparam M The type of the matrix.
+   * @tparam S the type of the set of valid row indices.
+   */
+  template<class M, class S>
+  class MatrixRowSubset
+  {
+  public:
+    /** @brief the type of the matrix class. */
+    typedef M Matrix;
+    /** @brief the type of the set of valid row indices. */
+    typedef S RowIndexSet;
+
+    /**
+     * @brief Construct an row set over all matrix rows.
+     * @param m The matrix for which we manage the rows.
+     * @param s The set of row indices we manage.
+     */
+    MatrixRowSubset(const Matrix& m, const RowIndexSet& s)
+      : m_(m), s_(s)
+    {}
+
+    const Matrix& matrix() const
+    {
+      return m_;
+    }
+
+    const RowIndexSet& rowIndexSet() const
+    {
+      return s_;
+    }
+
+    //! @brief The matrix row iterator type.
+    class const_iterator
+      : public ForwardIteratorFacade<const_iterator, const typename Matrix::row_type>
+    {
+    public:
+      const_iterator(typename Matrix::const_iterator firstRow,
+                     typename RowIndexSet::const_iterator pos)
+        : firstRow_(firstRow), pos_(pos)
+      {}
+
+
+      const typename Matrix::row_type& dereference() const
+      {
+        return *(firstRow_+ *pos_);
+      }
+      bool equals(const const_iterator& o) const
+      {
+        return pos_==o.pos_;
+      }
+      void increment()
+      {
+        ++pos_;
+      }
+      typename RowIndexSet::value_type index() const
+      {
+        return *pos_;
+      }
+
+    private:
+      //! @brief Iterator pointing to the first row of the matrix.
+      typename Matrix::const_iterator firstRow_;
+      //! @brief Iterator pointing to the current row index.
+      typename RowIndexSet::const_iterator pos_;
+    };
+
+    //! @brief Get the row iterator at the first row.
+    const_iterator begin() const
+    {
+      return const_iterator(m_.begin(), s_.begin());
+    }
+    //! @brief Get the row iterator at the end of all rows.
+    const_iterator end() const
+    {
+      return const_iterator(m_.begin(), s_.end());
+    }
+
+  private:
+    //! @brief The matrix for which we manage the row subset.
+    const Matrix& m_;
+    //! @brief The set of row indices we manage.
+    const RowIndexSet& s_;
+  };
+
+  /**
+   * @brief Utility class for converting an ISTL Matrix into a column-compressed matrix
+   * @tparam M the matrix type
+   */
+  template<class M>
+  struct ColCompMatrix
+  {};
+
+  /**
+   * @brief Inititializer for the ColCompMatrix
+   * as needed by OverlappingSchwarz
+   * @tparam M the matrix type
+   */
+  template<class M>
+  struct ColCompMatrixInitializer
+  {};
+
+  template<class M, class X, class TM, class TD, class T1>
+  class SeqOverlappingSchwarz;
+
+  template<class T>
+  struct SeqOverlappingSchwarzAssembler;
+
+  /**
+   * @brief Converter for BCRSMatrix to column-compressed Matrix.
+   * specialization for BCRSMatrix
+   */
+  template<class B, class TA, int n, int m>
+  class ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
+  {
+    template<class M, class X, class TM, class TD, class T1>
+    friend class SeqOverlappingSchwarz;
+    friend struct ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<B,n,m>,TA> >;
+
+  public:
+    /** @brief The type of the matrix to convert. */
+    typedef BCRSMatrix<FieldMatrix<B,n,m>,TA> Matrix;
+    friend struct SeqOverlappingSchwarzAssembler<ColCompMatrix<Matrix> >;
+
+    typedef typename Matrix::size_type size_type;
+
+    /**
+     * @brief Constructor that initializes the data.
+     * @param mat The matrix to convert.
+     */
+    explicit ColCompMatrix(const Matrix& mat);
+
+    ColCompMatrix();
+
+    /** @brief Destructor */
+    virtual ~ColCompMatrix();
+
+    /**
+     * @brief Get the number of rows.
+     * @return  The number of rows.
+     */
+    size_type N() const
+    {
+      return N_;
+    }
+
+    size_type nnz() const
+    {
+      return Nnz_/n/m;
+    }
+
+    /**
+     * @brief Get the number of columns.
+     * @return  The number of columns.
+     */
+    size_type M() const
+    {
+      return M_;
+    }
+
+    B* getValues() const
+    {
+      return values;
+    }
+
+    int* getRowIndex() const
+    {
+      return rowindex;
+    }
+
+    int* getColStart() const
+    {
+      return colstart;
+    }
+
+    ColCompMatrix& operator=(const Matrix& mat);
+    ColCompMatrix& operator=(const ColCompMatrix& mat);
+
+    /**
+     * @brief Initialize data from a given set of matrix rows and columns
+     * @tparam The type of the row index set.
+     * @param mat the matrix with the values
+     * @param mrs The set of row (and column) indices to represent
+     */
+    virtual void setMatrix(const Matrix& mat, const std::set<std::size_t>& mrs);
+    /** @brief free allocated space. */
+    virtual void free();
+
+    /** @brief Initialize data from given matrix. */
+    virtual void setMatrix(const Matrix& mat);
+
+  public:
+    int N_, M_, Nnz_;
+    B* values;
+    int* rowindex;
+    int* colstart;
+  };
+
+  template<class T, class A, int n, int m>
+  class ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >
+  {
+    template<class I, class S, class D>
+    friend class OverlappingSchwarzInitializer;
+  public:
+    typedef Dune::BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
+    typedef Dune::ColCompMatrix<Matrix> ColCompMatrix;
+    typedef typename Matrix::row_type::const_iterator CIter;
+    typedef typename Matrix::size_type size_type;
+
+    ColCompMatrixInitializer(ColCompMatrix& lum);
+
+    ColCompMatrixInitializer();
+
+    virtual ~ColCompMatrixInitializer();
+
+    template<typename Iter>
+    void addRowNnz(const Iter& row) const;
+
+    template<typename Iter, typename Set>
+    void addRowNnz(const Iter& row, const Set& s) const;
+
+    void allocate();
+
+    template<typename Iter>
+    void countEntries(const Iter& row, const CIter& col) const;
+
+    void countEntries(size_type colidx) const;
+
+    void calcColstart() const;
+
+    template<typename Iter>
+    void copyValue(const Iter& row, const CIter& col) const;
+
+    void copyValue(const CIter& col, size_type rowindex, size_type colidx) const;
+
+    virtual void createMatrix() const;
+
+  protected:
+
+    void allocateMatrixStorage() const;
+
+    void allocateMarker();
+
+    ColCompMatrix* mat;
+    size_type cols;
+    mutable size_type *marker;
+  };
+
+  template<class T, class A, int n, int m>
+  ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::ColCompMatrixInitializer(ColCompMatrix& mat_)
+    : mat(&mat_), cols(mat_.N()), marker(0)
+  {
+    mat->Nnz_=0;
+  }
+
+  template<class T, class A, int n, int m>
+  ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::ColCompMatrixInitializer()
+    : mat(0), cols(0), marker(0)
+  {}
+
+  template<class T, class A, int n, int m>
+  ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::~ColCompMatrixInitializer()
+  {
+    if(marker)
+      delete[] marker;
+  }
+
+  template<class T, class A, int n, int m>
+  template<typename Iter>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::addRowNnz(const Iter& row) const
+  {
+    mat->Nnz_+=row->getsize();
+  }
+
+  template<class T, class A, int n, int m>
+  template<typename Iter, typename Map>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::addRowNnz(const Iter& row,
+                                                                            const Map& indices) const
+  {
+    typedef typename  Iter::value_type::const_iterator RIter;
+    typedef typename Map::const_iterator MIter;
+    MIter siter =indices.begin();
+    for(RIter entry=row->begin(); entry!=row->end(); ++entry)
+    {
+      for(; siter!=indices.end() && *siter<entry.index(); ++siter) ;
+      if(siter==indices.end())
+        break;
+      if(*siter==entry.index())
+        // index is in subdomain
+        ++mat->Nnz_;
+    }
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::allocate()
+  {
+    allocateMatrixStorage();
+    allocateMarker();
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::allocateMatrixStorage() const
+  {
+    mat->Nnz_*=n*m;
+    // initialize data
+    mat->values=new T[mat->Nnz_];
+    mat->rowindex=new int[mat->Nnz_];
+    mat->colstart=new int[cols+1];
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::allocateMarker()
+  {
+    marker = new typename Matrix::size_type[cols];
+
+    for(size_type i=0; i < cols; ++i)
+      marker[i]=0;
+  }
+
+  template<class T, class A, int n, int m>
+  template<typename Iter>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::countEntries(const Iter& row, const CIter& col) const
+  {
+    countEntries(col.index());
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::countEntries(size_type colindex) const
+  {
+    for(size_type i=0; i < m; ++i)
+    {
+      assert(colindex*m+i<cols);
+      marker[colindex*m+i]+=n;
+    }
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::calcColstart() const
+  {
+    mat->colstart[0]=0;
+    for(size_type i=0; i < cols; ++i) {
+      assert(i<cols);
+      mat->colstart[i+1]=mat->colstart[i]+marker[i];
+      marker[i]=mat->colstart[i];
+    }
+  }
+
+  template<class T, class A, int n, int m>
+  template<typename Iter>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::copyValue(const Iter& row, const CIter& col) const
+  {
+    copyValue(col, row.index(), col.index());
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::copyValue(const CIter& col, size_type rowindex, size_type colindex) const
+  {
+    for(size_type i=0; i<n; i++) {
+      for(size_type j=0; j<m; j++) {
+        assert(colindex*m+j<cols-1 || (int)marker[colindex*m+j]<mat->colstart[colindex*m+j+1]);
+        assert((int)marker[colindex*m+j]<mat->Nnz_);
+        mat->rowindex[marker[colindex*m+j]]=rowindex*n+i;
+        mat->values[marker[colindex*m+j]]=(*col)[i][j];
+        ++marker[colindex*m+j]; // index for next entry in column
+      }
+    }
+  }
+
+  template<class T, class A, int n, int m>
+  void ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::createMatrix() const
+  {
+    delete[] marker;
+    marker=0;
+  }
+
+  template<class F, class MRS>
+  void copyToColCompMatrix(F& initializer, const MRS& mrs)
+  {
+    typedef typename MRS::const_iterator Iter;
+    typedef typename  std::iterator_traits<Iter>::value_type::const_iterator CIter;
+    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
+      initializer.addRowNnz(row);
+
+    initializer.allocate();
+
+    for(Iter row=mrs.begin(); row!= mrs.end(); ++row) {
+
+      for(CIter col=row->begin(); col != row->end(); ++col)
+        initializer.countEntries(row, col);
+    }
+
+    initializer.calcColstart();
+
+    for(Iter row=mrs.begin(); row!= mrs.end(); ++row) {
+      for(CIter col=row->begin(); col != row->end(); ++col) {
+        initializer.copyValue(row, col);
+      }
+
+    }
+    initializer.createMatrix();
+  }
+
+  template<class F, class M,class S>
+  void copyToColCompMatrix(F& initializer, const MatrixRowSubset<M,S>& mrs)
+  {
+    typedef MatrixRowSubset<M,S> MRS;
+    typedef typename MRS::RowIndexSet SIS;
+    typedef typename SIS::const_iterator SIter;
+    typedef typename MRS::const_iterator Iter;
+    typedef typename std::iterator_traits<Iter>::value_type row_type;
+    typedef typename row_type::const_iterator CIter;
+
+    // Calculate upper Bound for nonzeros
+    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
+      initializer.addRowNnz(row, mrs.rowIndexSet());
+
+    initializer.allocate();
+
+    typedef typename MRS::Matrix::size_type size_type;
+
+    // A vector containing the corresponding indices in
+    // the to create submatrix.
+    // If an entry is the maximum of size_type then this index will not appear in
+    // the submatrix.
+    std::vector<size_type> subMatrixIndex(mrs.matrix().N(),
+                                          std::numeric_limits<size_type>::max());
+    size_type s=0;
+    for(SIter index = mrs.rowIndexSet().begin(); index!=mrs.rowIndexSet().end(); ++index)
+      subMatrixIndex[*index]=s++;
+
+    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
+      for(CIter col=row->begin(); col != row->end(); ++col) {
+        if(subMatrixIndex[col.index()]!=std::numeric_limits<size_type>::max())
+          // This column is in our subset (use submatrix column index)
+          initializer.countEntries(subMatrixIndex[col.index()]);
+      }
+
+    initializer.calcColstart();
+
+    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
+      for(CIter col=row->begin(); col != row->end(); ++col) {
+        if(subMatrixIndex[col.index()]!=std::numeric_limits<size_type>::max())
+          // This value is in our submatrix -> copy (use submatrix indices
+          initializer.copyValue(col, subMatrixIndex[row.index()], subMatrixIndex[col.index()]);
+      }
+    initializer.createMatrix();
+  }
+
+#ifndef DOXYGEN
+
+  template<class B, class TA, int n, int m>
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::ColCompMatrix()
+    : N_(0), M_(0), Nnz_(0), values(0), rowindex(0), colstart(0)
+  {}
+
+  template<class B, class TA, int n, int m>
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
+  ::ColCompMatrix(const Matrix& mat)
+    : N_(n*mat.N()), M_(m*mat.M()), Nnz_(n*m*mat.nonzeroes())
+  {}
+
+  template<class B, class TA, int n, int m>
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >&
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator=(const Matrix& mat)
+  {
+    if(N_+M_+Nnz_!=0)
+      free();
+    setMatrix(mat);
+    return *this;
+  }
+
+  template<class B, class TA, int n, int m>
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >&
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator=(const ColCompMatrix& mat)
+  {
+    if(N_+M_+Nnz_!=0)
+      free();
+    N_=mat.N_;
+    M_=mat.M_;
+    Nnz_= mat.Nnz_;
+    if(M_>0) {
+      colstart=new int[M_+1];
+      for(int i=0; i<=M_; ++i)
+        colstart[i]=mat.colstart[i];
+    }
+
+    if(Nnz_>0) {
+      values = new B[Nnz_];
+      rowindex = new int[Nnz_];
+
+      for(int i=0; i<Nnz_; ++i)
+        values[i]=mat.values[i];
+
+      for(int i=0; i<Nnz_; ++i)
+        rowindex[i]=mat.rowindex[i];
+    }
+    return *this;
+  }
+
+  template<class B, class TA, int n, int m>
+  void ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
+  ::setMatrix(const Matrix& mat)
+  {
+    N_=n*mat.N();
+    M_=m*mat.M();
+    ColCompMatrixInitializer<Matrix> initializer(*this);
+
+    copyToColCompMatrix(initializer, MatrixRowSet<Matrix>(mat));
+  }
+
+  template<class B, class TA, int n, int m>
+  void ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
+  ::setMatrix(const Matrix& mat, const std::set<std::size_t>& mrs)
+  {
+    if(N_+M_+Nnz_!=0)
+      free();
+    N_=mrs.size()*n;
+    M_=mrs.size()*m;
+    ColCompMatrixInitializer<Matrix> initializer(*this);
+
+    copyToColCompMatrix(initializer, MatrixRowSubset<Matrix,std::set<std::size_t> >(mat,mrs));
+  }
+
+  template<class B, class TA, int n, int m>
+  ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::~ColCompMatrix()
+  {
+    if(N_+M_+Nnz_!=0)
+      free();
+  }
+
+  template<class B, class TA, int n, int m>
+  void ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::free()
+  {
+    delete[] values;
+    delete[] rowindex;
+    delete[] colstart;
+    N_ = 0;
+    M_ = 0;
+    Nnz_ = 0;
+  }
+
+#endif // DOXYGEN
+
+}
+#endif
diff --git a/dune/istl/overlappingschwarz.hh b/dune/istl/overlappingschwarz.hh
index 25dd795c26f63bde3413fedf1e87d2475aa500db..4af4e300e7dd9da4137d4cea871792c477d79c25 100644
--- a/dune/istl/overlappingschwarz.hh
+++ b/dune/istl/overlappingschwarz.hh
@@ -203,13 +203,24 @@ namespace Dune
     DynamicMatrix<K> A;
   };
 
-  template<typename T>
-  struct OverlappingAssigner
+  template<typename T, bool tag>
+  class OverlappingAssignerHelper
   {};
 
+  template<typename T>
+  struct OverlappingAssigner : public OverlappingAssignerHelper<T,Dune::StoresColumnCompressed<T>::value >
+  {
+    public:
+    OverlappingAssigner(std::size_t maxlength, const typename T::matrix_type& mat,
+                        const typename T::range_type& b, typename T::range_type& x)
+      : OverlappingAssignerHelper<T,Dune::StoresColumnCompressed<T>::value >
+      (maxlength,mat,b,x)
+      {}
+  };
+
   // specialization for DynamicMatrix
   template<class K, int n, class Al, class X, class Y>
-  class OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  class OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   {
   public:
     typedef BCRSMatrix< FieldMatrix<K,n,n>, Al> matrix_type;
@@ -225,7 +236,7 @@ namespace Dune
      * @param b_ the global right hand side.
      * @param x_ the global left hand side.
      */
-    OverlappingAssigner(std::size_t maxlength, const BCRSMatrix<FieldMatrix<K,n,n>, Al>& mat_, const X& b_, Y& x_);
+    OverlappingAssignerHelper(std::size_t maxlength, const BCRSMatrix<FieldMatrix<K,n,n>, Al>& mat_, const X& b_, Y& x_);
 
     /**
      * @brief Deallocates memory of the local vector.
@@ -298,11 +309,11 @@ namespace Dune
   };
 
 #if HAVE_SUPERLU
-  template<typename T, typename A, int n, int m>
-  struct OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >
+  template<template<class> class S, int n, int m, typename T, typename A>
+  struct OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>, A> >, true>
   {
-    typedef BCRSMatrix<FieldMatrix<T,n,m>,A> matrix_type;
-    typedef typename SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> >::range_type range_type;
+    typedef BCRSMatrix<FieldMatrix<T,n,m>, A> matrix_type;
+    typedef typename S<BCRSMatrix<FieldMatrix<T,n,m>, A> >::range_type range_type;
     typedef typename range_type::field_type field_type;
     typedef typename range_type::block_type block_type;
 
@@ -315,7 +326,7 @@ namespace Dune
      * @param b the global right hand side.
      * @param x the global left hand side.
      */
-    OverlappingAssigner(std::size_t maxlength, const BCRSMatrix<FieldMatrix<T,n,m>,A>& mat,
+    OverlappingAssignerHelper(std::size_t maxlength, const matrix_type& mat,
                         const range_type& b, range_type& x);
     /**
      * @brief Deallocates memory of the local vector.
@@ -467,7 +478,7 @@ namespace Dune
 
   // specialization for ILU0
   template<class M, class X, class Y>
-  class OverlappingAssigner<ILU0SubdomainSolver<M,X,Y> >
+  class OverlappingAssignerHelper<ILU0SubdomainSolver<M,X,Y>, false>
     : public OverlappingAssignerILUBase<M,X,Y>
   {
   public:
@@ -478,7 +489,7 @@ namespace Dune
      * @param b the global right hand side.
      * @param x the global left hand side.
      */
-    OverlappingAssigner(std::size_t maxlength, const M& mat,
+    OverlappingAssignerHelper(std::size_t maxlength, const M& mat,
                         const Y& b, X& x)
       : OverlappingAssignerILUBase<M,X,Y>(maxlength, mat,b,x)
     {}
@@ -486,7 +497,7 @@ namespace Dune
 
   // specialization for ILUN
   template<class M, class X, class Y>
-  class OverlappingAssigner<ILUNSubdomainSolver<M,X,Y> >
+  class OverlappingAssignerHelper<ILUNSubdomainSolver<M,X,Y>,false>
     : public OverlappingAssignerILUBase<M,X,Y>
   {
   public:
@@ -497,7 +508,7 @@ namespace Dune
      * @param b the global right hand side.
      * @param x the global left hand side.
      */
-    OverlappingAssigner(std::size_t maxlength, const M& mat,
+    OverlappingAssignerHelper(std::size_t maxlength, const M& mat,
                         const Y& b, X& x)
       : OverlappingAssignerILUBase<M,X,Y>(maxlength, mat,b,x)
     {}
@@ -673,13 +684,18 @@ namespace Dune
     }
   };
 
+  template<class T, bool tag>
+  struct SeqOverlappingSchwarzAssemblerHelper
+  {};
+
   template<class T>
   struct SeqOverlappingSchwarzAssembler
+    : public SeqOverlappingSchwarzAssemblerHelper<T,Dune::StoresColumnCompressed<T>::value>
   {};
 
 
   template<class K, int n, class Al, class X, class Y>
-  struct SeqOverlappingSchwarzAssembler< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  struct SeqOverlappingSchwarzAssemblerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   {
     typedef BCRSMatrix< FieldMatrix<K,n,n>, Al> matrix_type;
     template<class RowToDomain, class Solvers, class SubDomains>
@@ -688,17 +704,15 @@ namespace Dune
                                              bool onTheFly);
   };
 
-#if HAVE_SUPERLU
-  template<class T>
-  struct SeqOverlappingSchwarzAssembler<SuperLU<T> >
+  template<template<class> class S, typename T, typename A, int m, int n>
+  struct SeqOverlappingSchwarzAssemblerHelper<S<BCRSMatrix<FieldMatrix<T,m,n>,A> >,true>
   {
-    typedef T matrix_type;
+    typedef BCRSMatrix<FieldMatrix<T,m,n>,A> matrix_type;
     template<class RowToDomain, class Solvers, class SubDomains>
     static std::size_t assembleLocalProblems(const RowToDomain& rowToDomain, const matrix_type& mat,
                                              Solvers& solvers, const SubDomains& domains,
                                              bool onTheFly);
   };
-#endif
 
   template<class M,class X, class Y>
   struct SeqOverlappingSchwarzAssemblerILUBase
@@ -711,12 +725,12 @@ namespace Dune
   };
 
   template<class M,class X, class Y>
-  struct SeqOverlappingSchwarzAssembler<ILU0SubdomainSolver<M,X,Y> >
+  struct SeqOverlappingSchwarzAssemblerHelper<ILU0SubdomainSolver<M,X,Y>,false>
     : public SeqOverlappingSchwarzAssemblerILUBase<M,X,Y>
   {};
 
   template<class M,class X, class Y>
-  struct SeqOverlappingSchwarzAssembler<ILUNSubdomainSolver<M,X,Y> >
+  struct SeqOverlappingSchwarzAssemblerHelper<ILUNSubdomainSolver<M,X,Y>,false>
     : public SeqOverlappingSchwarzAssemblerILUBase<M,X,Y>
   {};
 
@@ -1098,7 +1112,7 @@ namespace Dune
   template<class K, int n, class Al, class X, class Y>
   template<class RowToDomain, class Solvers, class SubDomains>
   std::size_t
-  SeqOverlappingSchwarzAssembler< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >::
+  SeqOverlappingSchwarzAssemblerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>::
   assembleLocalProblems(const RowToDomain& rowToDomain,
                         const matrix_type& mat,
                         Solvers& solvers,
@@ -1118,15 +1132,16 @@ namespace Dune
   }
 
 #if HAVE_SUPERLU
-  template<class T>
+  template<template<class> class S, typename T, typename A, int m, int n>
   template<class RowToDomain, class Solvers, class SubDomains>
-  std::size_t SeqOverlappingSchwarzAssembler<SuperLU<T> >::assembleLocalProblems(const RowToDomain& rowToDomain,
+  std::size_t SeqOverlappingSchwarzAssemblerHelper<S<BCRSMatrix<FieldMatrix<T,m,n>,A> >,true>::assembleLocalProblems(const RowToDomain& rowToDomain,
                                                                                  const matrix_type& mat,
                                                                                  Solvers& solvers,
                                                                                  const SubDomains& subDomains,
                                                                                  bool onTheFly)
   {
-    typedef typename std::vector<SuperMatrixInitializer<matrix_type> >::iterator InitializerIterator;
+    typedef typename S<BCRSMatrix<FieldMatrix<T,m,n>,A> >::MatrixInitializer MatrixInitializer;
+    typedef typename std::vector<MatrixInitializer>::iterator InitializerIterator;
     typedef typename SubDomains::const_iterator DomainIterator;
     typedef typename Solvers::iterator SolverIterator;
     std::size_t maxlength = 0;
@@ -1140,7 +1155,7 @@ namespace Dune
       DomainIterator domain=subDomains.begin();
 
       // Create the initializers list.
-      std::vector<SuperMatrixInitializer<matrix_type> > initializers(subDomains.size());
+      std::vector<MatrixInitializer> initializers(subDomains.size());
 
       SolverIterator solver=solvers.begin();
       for(InitializerIterator initializer=initializers.begin(); initializer!=initializers.end();
@@ -1148,27 +1163,21 @@ namespace Dune
         solver->mat.N_=SeqOverlappingSchwarzDomainSize<matrix_type>::size(*domain);
         solver->mat.M_=SeqOverlappingSchwarzDomainSize<matrix_type>::size(*domain);
         //solver->setVerbosity(true);
-        *initializer=SuperMatrixInitializer<matrix_type>(solver->mat);
+        *initializer=MatrixInitializer(solver->mat);
       }
 
       // Set up the supermatrices according to the subdomains
-      typedef OverlappingSchwarzInitializer<std::vector<SuperMatrixInitializer<matrix_type> >,
+      typedef OverlappingSchwarzInitializer<std::vector<MatrixInitializer>,
           RowToDomain, SubDomains> Initializer;
 
       Initializer initializer(initializers, rowToDomain, subDomains);
-      copyToSuperMatrix(initializer, mat);
-      if(solvers.size()==1)
-        assert(solvers[0].mat==mat);
-
-      /*    for(SolverIterator solver=solvers.begin(); solver!=solvers.end(); ++solver)
-            dPrint_CompCol_Matrix("superlu", &static_cast<SuperMatrix&>(solver->mat)); */
+      copyToColCompMatrix(initializer, mat);
 
       // Calculate the LU decompositions
-      std::for_each(solvers.begin(), solvers.end(), std::mem_fun_ref(&SuperLU<matrix_type>::decompose));
+      std::for_each(solvers.begin(), solvers.end(), std::mem_fun_ref(&S<BCRSMatrix<FieldMatrix<T,m,n>,A> >::decompose));
       for(SolverIterator solver=solvers.begin(); solver!=solvers.end(); ++solver) {
         assert(solver->mat.N()==solver->mat.M());
         maxlength=std::max(maxlength, solver->mat.N());
-        //writeCompColMatrixToMatlab(static_cast<SuperLUMatrix<M>&>(solver->mat), std::cout);
       }
     }
     return maxlength;
@@ -1263,8 +1272,8 @@ namespace Dune
   }
 
   template<class K, int n, class Al, class X, class Y>
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
-  ::OverlappingAssigner(std::size_t maxlength, const BCRSMatrix<FieldMatrix<K,n,n>, Al>& mat_,
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
+  ::OverlappingAssignerHelper(std::size_t maxlength, const BCRSMatrix<FieldMatrix<K,n,n>, Al>& mat_,
                         const X& b_, Y& x_) :
     mat(&mat_),
     rhs_( new DynamicVector<field_type>(maxlength, 42) ),
@@ -1277,7 +1286,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   void
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::deallocate()
   {
     delete rhs_;
@@ -1286,7 +1295,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   void
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::resetIndexForNextDomain()
   {
     i=0;
@@ -1294,7 +1303,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   DynamicVector<K> &
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::lhs()
   {
     return *lhs_;
@@ -1302,7 +1311,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   DynamicVector<K> &
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::rhs()
   {
     return *rhs_;
@@ -1310,7 +1319,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   void
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::relaxResult(field_type relax)
   {
     lhs() *= relax;
@@ -1318,7 +1327,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   void
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::operator()(const size_type& domainIndex)
   {
     lhs() = 0.0;
@@ -1363,7 +1372,7 @@ namespace Dune
 
   template<class K, int n, class Al, class X, class Y>
   void
-  OverlappingAssigner< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y > >
+  OverlappingAssignerHelper< DynamicMatrixSubdomainSolver< BCRSMatrix< FieldMatrix<K,n,n>, Al>, X, Y >,false>
   ::assignResult(block_type& res)
   {
     // assign the result of the local solve to the global vector
@@ -1375,9 +1384,9 @@ namespace Dune
 
 #if HAVE_SUPERLU
 
-  template<typename T, typename A, int n, int m>
-  OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >
-  ::OverlappingAssigner(std::size_t maxlength,
+  template<template<class> class S, int n, int m, typename T, typename A>
+  OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>
+  ::OverlappingAssignerHelper(std::size_t maxlength,
                         const BCRSMatrix<FieldMatrix<T,n,m>,A>& mat_,
                         const range_type& b_,
                         range_type& x_)
@@ -1390,15 +1399,15 @@ namespace Dune
 
   }
 
-  template<typename T, typename A, int n, int m>
-  void OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::deallocate()
+  template<template<class> class S, int n, int m, typename T, typename A>
+  void OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::deallocate()
   {
     delete[] rhs_;
     delete[] lhs_;
   }
 
-  template<typename T, typename A, int n, int m>
-  void OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::operator()(const size_type& domainIndex)
+  template<template<class> class S, int n, int m, typename T, typename A>
+  void OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::operator()(const size_type& domainIndex)
   {
     //assign right hand side of current domainindex block
     // rhs is an array of doubles!
@@ -1425,8 +1434,9 @@ namespace Dune
     }
 
   }
-  template<typename T, typename A, int n, int m>
-  void OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::relaxResult(field_type relax)
+
+  template<template<class> class S, int n, int m, typename T, typename A>
+  void OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::relaxResult(field_type relax)
   {
     for(size_type j=i+n; i<j; ++i) {
       assert(i<maxlength_);
@@ -1435,8 +1445,8 @@ namespace Dune
     i-=n;
   }
 
-  template<typename T, typename A, int n, int m>
-  void OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::assignResult(block_type& res)
+  template<template<class> class S, int n, int m, typename T, typename A>
+  void OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::assignResult(block_type& res)
   {
     // assign the result of the local solve to the global vector
     for(size_type j=0; j<n; ++j, ++i) {
@@ -1445,22 +1455,22 @@ namespace Dune
     }
   }
 
-  template<typename T, typename A, int n, int m>
-  void OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::resetIndexForNextDomain()
+  template<template<class> class S, int n, int m, typename T, typename A>
+  void OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::resetIndexForNextDomain()
   {
     i=0;
   }
 
-  template<typename T, typename A, int n, int m>
-  typename OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::field_type*
-  OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::lhs()
+  template<template<class> class S, int n, int m, typename T, typename A>
+  typename OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::field_type*
+  OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::lhs()
   {
     return lhs_;
   }
 
-  template<typename T, typename A, int n, int m>
-  typename OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::field_type*
-  OverlappingAssigner<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >::rhs()
+  template<template<class> class S, int n, int m, typename T, typename A>
+  typename OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::field_type*
+  OverlappingAssignerHelper<S<BCRSMatrix<FieldMatrix<T,n,m>,A> >,true>::rhs()
   {
     return rhs_;
   }
diff --git a/dune/istl/solvertype.hh b/dune/istl/solvertype.hh
index 0a3f2409212ba8f823f01eb8f825a7d7ee8e2d5b..12f174f01402a225d37c505fb8d5f88217069843 100644
--- a/dune/istl/solvertype.hh
+++ b/dune/istl/solvertype.hh
@@ -22,5 +22,17 @@ namespace Dune
       value =false
     };
   };
+
+  template<typename Solver>
+  struct StoresColumnCompressed
+  {
+    enum
+    {
+      /**
+       * @brief whether the solver internally uses column compressed storage
+       */
+      value = false
+    };
+  };
 } // end namespace Dune
 #endif
diff --git a/dune/istl/superlu.hh b/dune/istl/superlu.hh
index 4bc725ca43c13b13f4d83d409c102dfa0f417bba..efecbcf45a460d07b860cb011c84dda84c31b7a0 100644
--- a/dune/istl/superlu.hh
+++ b/dune/istl/superlu.hh
@@ -83,8 +83,8 @@ namespace Dune
   template<class M, class T, class TM, class TD, class TA>
   class SeqOverlappingSchwarz;
 
-  template<class T>
-  struct SeqOverlappingSchwarzAssembler;
+  template<class T, bool tag>
+  struct SeqOverlappingSchwarzAssemblerHelper;
 
   template<class T>
   struct SuperLUSolveChooser
@@ -285,10 +285,13 @@ namespace Dune
               typename A::template rebind<FieldVector<T,n> >::other> >
   {
   public:
-    /* @brief The matrix type. */
+    /** @brief The matrix type. */
     typedef Dune::BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
-    /* @brief The corresponding SuperLU Matrix type.*/
+    typedef Dune::BCRSMatrix<FieldMatrix<T,n,m>,A> matrix_type;
+    /** @brief The corresponding SuperLU Matrix type.*/
     typedef Dune::SuperLUMatrix<Matrix> SuperLUMatrix;
+    /** @brief Type of an associated initializer class. */
+    typedef SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> > MatrixInitializer;
     /** @brief The type of the domain of the solver. */
     typedef Dune::BlockVector<
         FieldVector<T,m>,
@@ -363,7 +366,7 @@ namespace Dune
     friend class std::mem_fun_ref_t<void,SuperLU>;
     template<class M,class X, class TM, class TD, class T1>
     friend class SeqOverlappingSchwarz;
-    friend struct SeqOverlappingSchwarzAssembler<SuperLU<Matrix> >;
+    friend struct SeqOverlappingSchwarzAssemblerHelper<SuperLU<Matrix>,true>;
 
     /** @brief computes the LU Decomposition */
     void decompose();
@@ -708,6 +711,12 @@ namespace Dune
   {
     enum { value=true};
   };
+
+  template<typename T, typename A, int n, int m>
+  struct StoresColumnCompressed<SuperLU<BCRSMatrix<FieldMatrix<T,n,m>,A> > >
+  {
+    enum { value = true };
+  };
 }
 
 #endif // HAVE_SUPERLU
diff --git a/dune/istl/supermatrix.hh b/dune/istl/supermatrix.hh
index 600bd083a09e5ec6fc6336c15199e90eb374c915..fbe437571781481dfd70d44a13ab409c5ba6a219 100644
--- a/dune/istl/supermatrix.hh
+++ b/dune/istl/supermatrix.hh
@@ -52,6 +52,8 @@
 #include <dune/common/typetraits.hh>
 #include <limits>
 
+#include"colcompmatrix.hh"
+
 namespace Dune
 {
 
@@ -155,131 +157,6 @@ namespace Dune
   };
 #endif
 
-  /**
-   * @brief Provides access to an iterator over all matrix rows.
-   *
-   * @tparam M The type of the matrix.
-   */
-  template<class M>
-  class MatrixRowSet
-  {
-  public:
-    // @brief The type of the matrix.
-    typedef M Matrix;
-    // @brief The matrix row iterator type.
-    typedef typename Matrix::ConstRowIterator const_iterator;
-
-    /**
-     * @brief Construct an row set over all matrix rows.
-     * @param m The matrix for which we manage the rows.
-     */
-    MatrixRowSet(const Matrix& m)
-      : m_(m)
-    {}
-
-    // @brief Get the row iterator at the first row.
-    const_iterator begin() const
-    {
-      return m_.begin();
-    }
-    //@brief Get the row iterator at the end of all rows.
-    const_iterator end() const
-    {
-      return m_.end();
-    }
-  private:
-    const Matrix& m_;
-  };
-
-  /**
-   * @brief Provides access to an iterator over an arbitrary subset
-   * of matrix rows.
-   *
-   * @tparam M The type of the matrix.
-   * @tparam S the type of the set of valid row indices.
-   */
-  template<class M, class S>
-  class MatrixRowSubset
-  {
-  public:
-    /* @brief the type of the matrix class. */
-    typedef M Matrix;
-    /* @brief the type of the set of valid row indices. */
-    typedef S RowIndexSet;
-
-    /**
-     * @brief Construct an row set over all matrix rows.
-     * @param m The matrix for which we manage the rows.
-     + @param s The set of row indices we manage.
-     */
-    MatrixRowSubset(const Matrix& m, const RowIndexSet& s)
-      : m_(m), s_(s)
-    {}
-
-    const Matrix& matrix() const
-    {
-      return m_;
-    }
-
-    const RowIndexSet& rowIndexSet() const
-    {
-      return s_;
-    }
-
-    // @brief The matrix row iterator type.
-    class const_iterator
-      : public ForwardIteratorFacade<const_iterator, const typename Matrix::row_type>
-    {
-    public:
-      const_iterator(typename Matrix::const_iterator firstRow,
-                     typename RowIndexSet::const_iterator pos)
-        : firstRow_(firstRow), pos_(pos)
-      {}
-
-
-      const typename Matrix::row_type& dereference() const
-      {
-        return *(firstRow_+ *pos_);
-      }
-      bool equals(const const_iterator& o) const
-      {
-        return pos_==o.pos_;
-      }
-      void increment()
-      {
-        ++pos_;
-      }
-      typename RowIndexSet::value_type index() const
-      {
-        return *pos_;
-      }
-
-    private:
-      // @brief Iterator pointing to the first row of the matrix.
-      typename Matrix::const_iterator firstRow_;
-      // @brief Iterator pointing to the current row index.
-      typename RowIndexSet::const_iterator pos_;
-    };
-
-    // @brief Get the row iterator at the first row.
-    const_iterator begin() const
-    {
-      return const_iterator(m_.begin(), s_.begin());
-    }
-    //@brief Get the row iterator at the end of all rows.
-    const_iterator end() const
-    {
-      return const_iterator(m_.begin(), s_.end());
-    }
-
-  private:
-    // @brief The matrix for which we manage the row subset.
-    const Matrix& m_;
-    // @brief The set of row indices we manage.
-    const RowIndexSet& s_;
-
-  };
-
   template<class T>
   struct BaseGetSuperLUType
   {
@@ -337,13 +214,6 @@ namespace Dune
   struct SuperMatrixInitializer
   {};
 
-  template<class M, class X, class TM, class TD, class T1>
-  class SeqOverlappingSchwarz;
-
-
-  template<class T>
-  struct SeqOverlappingSchwarzAssembler;
-
   template<class T>
   class SuperLU;
 
@@ -352,11 +222,11 @@ namespace Dune
    */
   template<class B, class TA, int n, int m>
   class SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
+    : public ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
   {
     template<class M, class X, class TM, class TD, class T1>
     friend class SeqOverlappingSchwarz;
     friend struct SuperMatrixInitializer<BCRSMatrix<FieldMatrix<B,n,m>,TA> >;
-
   public:
     /** @brief The type of the matrix to convert. */
     typedef BCRSMatrix<FieldMatrix<B,n,m>,TA> Matrix;
@@ -369,12 +239,18 @@ namespace Dune
      * @brief Constructor that initializes the data.
      * @param mat The matrix to convert.
      */
-    SuperLUMatrix(const Matrix& mat);
+    explicit SuperLUMatrix(const Matrix& mat) : ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >(mat)
+    {}
 
-    SuperLUMatrix();
+    SuperLUMatrix() : ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >()
+    {}
 
     /** @brief Destructor */
-    ~SuperLUMatrix();
+    virtual ~SuperLUMatrix()
+    {
+      if (this->N_+this->M_*this->Nnz_ != 0)
+        free();
+    }
 
     /** @brief Cast to a SuperLU Matrix */
     operator SuperMatrix&()
@@ -387,491 +263,92 @@ namespace Dune
     {
       return A;
     }
-    bool operator==(const Matrix& mat) const;
 
-    /**
-     * @brief Get the number of rows.
-     * @return  The number of rows.
-     */
-    size_type N() const
+    SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >& operator=(const BCRSMatrix<FieldMatrix<B,n,m>,TA>& mat)
     {
-      return N_;
+      this->ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator=(mat);
+      SuperMatrixCreateSparseChooser<B>
+           ::create(&A, this->N_, this->M_, this->colstart[this->N_],
+             this->values,this->rowindex, this->colstart, SLU_NC,
+             static_cast<Dtype_t>(GetSuperLUType<B>::type), SLU_GE);
+      return *this;
     }
 
-    size_type nnz() const
+    SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >& operator=(const SuperLUMatrix <BCRSMatrix<FieldMatrix<B,n,m>,TA> >& mat)
     {
-      return Nnz_/n/m;
+      this->ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator=(mat);
+      SuperMatrixCreateSparseChooser<B>
+           ::create(&A, this->N_, this->M_, this->colstart[this->N_],
+             this->values,this->rowindex, this->colstart, SLU_NC,
+             static_cast<Dtype_t>(GetSuperLUType<B>::type), SLU_GE);
+      return *this;
     }
 
     /**
-     * @brief Get the number of columns.
-     * @return  The number of columns.
+     * @brief Initialize data from a given set of matrix rows and columns
+     * @tparam The type of the row index set.
+     * @param mat the matrix with the values
+     * @param mrs The set of row (and column) indices to represent
      */
-    size_type M() const
+    virtual void setMatrix(const Matrix& mat, const std::set<std::size_t>& mrs)
     {
-      return M_;
+      if(this->N_+this->M_+this->Nnz_!=0)
+        free();
+      this->N_=mrs.size()*n;
+      this->M_=mrs.size()*m;
+      SuperMatrixInitializer<Matrix> initializer(*this);
+
+      copyToColCompMatrix(initializer, MatrixRowSubset<Matrix,std::set<std::size_t> >(mat,mrs));
     }
 
-    SuperLUMatrix& operator=(const Matrix& mat);
+    /** @brief Initialize data from given matrix. */
+    virtual void setMatrix(const Matrix& mat)
+    {
+      this->N_=n*mat.N();
+      this->M_=m*mat.M();
+      SuperMatrixInitializer<Matrix> initializer(*this);
 
-    SuperLUMatrix& operator=(const SuperLUMatrix& mat);
+      copyToColCompMatrix(initializer, MatrixRowSet<Matrix>(mat));
+    }
 
-    /**
-     * @brief Initialize data from a given set of matrix rows and columns
-     * @tparam The type of the row index set.
-     * @param mat the matrix with the values
-     * @param mrs The set of row (and column) indices to represent
-     */
-    template<class S>
-    void setMatrix(const Matrix& mat, const S& mrs);
     /** @brief free allocated space. */
-    void free();
+    virtual void free()
+    {
+      ColCompMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::free();
+      SUPERLU_FREE(A.Store);
+    }
   private:
-    /** @brief Initialize data from given matrix. */
-    void setMatrix(const Matrix& mat);
-
-    int N_, M_, Nnz_;
-    B* values;
-    int* rowindex;
-    int* colstart;
     SuperMatrix A;
   };
 
-  template<class T, class A, int n, int m>
-  void writeCompColMatrixToMatlab(const SuperLUMatrix<BCRSMatrix<FieldMatrix<T,n,m>,A> >& mat,
-                                  std::ostream& os)
-  {
-    const SuperMatrix a=static_cast<const SuperMatrix&>(mat);
-    NCformat *astore = (NCformat *) a.Store;
-    double* dp = (double*)astore->nzval;
-
-    // remember old flags
-    std::ios_base::fmtflags oldflags = os.flags();
-    // set the output format
-    //os.setf(std::ios_base::scientific, std::ios_base::floatfield);
-    int oldprec = os.precision();
-    //os.precision(10);
-    //dPrint_CompCol_Matrix("A", const_cast<SuperMatrix*>(&a));
-
-    os <<"[";
-    for(int row=0; row<a.nrow; ++row) {
-      for(int col= 0; col < a.ncol; ++col) {
-        // linear search for col
-        int i;
-        for(i=astore->colptr[col]; i < astore->colptr[col+1]; ++i)
-          if(astore->rowind[i]==row) {
-            os<<dp[i]<<" ";
-            break;
-          }
-        if(i==astore->colptr[col+1])
-          // entry not present
-          os<<0<<" ";
-      }
-      if(row==a.nrow-1)
-        os<<"]";
-      os<<std::endl;
-    }
-    // reset the output format
-    os.flags(oldflags);
-    os.precision(oldprec);
-  }
-
-
   template<class T, class A, int n, int m>
   class SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >
+    : public ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >
   {
     template<class I, class S, class D>
     friend class OverlappingSchwarzInitializer;
   public:
-    typedef Dune::BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
+    typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
     typedef Dune::SuperLUMatrix<Matrix> SuperLUMatrix;
-    typedef typename Matrix::row_type::const_iterator CIter;
-    typedef typename Matrix::size_type size_type;
-
-    SuperMatrixInitializer(SuperLUMatrix& lum);
-
-    SuperMatrixInitializer();
-
-    ~SuperMatrixInitializer();
-
-    template<typename Iter>
-    void addRowNnz(const Iter& row) const;
-
-    template<typename Iter, typename Set>
-    void addRowNnz(const Iter& row, const Set& s) const;
-
-    void allocate();
-
-    template<typename Iter>
-    void countEntries(const Iter& row, const CIter& col) const;
-
-    void countEntries(size_type colidx) const;
-
-    void calcColstart() const;
-
-    template<typename Iter>
-    void copyValue(const Iter& row, const CIter& col) const;
-
-    void copyValue(const CIter& col, size_type rowindex, size_type colidx) const;
-
-    void createMatrix() const;
-
-  private:
-
-    void allocateMatrixStorage() const;
-
-    void allocateMarker();
-
-    SuperLUMatrix* mat;
-    size_type cols;
-    mutable size_type *marker;
-  };
-
-  template<class T, class A, int n, int m>
-  SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::SuperMatrixInitializer(SuperLUMatrix& mat_)
-    : mat(&mat_), cols(mat_.N()), marker(0)
-  {
-    mat->Nnz_=0;
-  }
 
-  template<class T, class A, int n, int m>
-  SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::SuperMatrixInitializer()
-    : mat(0), cols(0), marker(0)
-  {}
-
-  template<class T, class A, int n, int m>
-  SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::~SuperMatrixInitializer()
-  {
-    if(marker)
-      delete[] marker;
-  }
+    SuperMatrixInitializer(SuperLUMatrix& lum) : ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >(lum)
+      ,slumat(&lum)
+    {}
 
-  template<class T, class A, int n, int m>
-  template<typename Iter>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::addRowNnz(const Iter& row) const
-  {
-    mat->Nnz_+=row->getsize();
-  }
+    SuperMatrixInitializer() : ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >()
+    {}
 
-  template<class T, class A, int n, int m>
-  template<typename Iter, typename Map>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::addRowNnz(const Iter& row,
-                                                                            const Map& indices) const
-  {
-    typedef typename  Iter::value_type::const_iterator RIter;
-    typedef typename Map::const_iterator MIter;
-    MIter siter =indices.begin();
-    for(RIter entry=row->begin(); entry!=row->end(); ++entry)
+    virtual void createMatrix() const
     {
-      for(; siter!=indices.end() && *siter<entry.index(); ++siter) ;
-      if(siter==indices.end())
-        break;
-      if(*siter==entry.index())
-        // index is in subdomain
-        ++mat->Nnz_;
-    }
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::allocate()
-  {
-    allocateMatrixStorage();
-    allocateMarker();
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::allocateMatrixStorage() const
-  {
-    mat->Nnz_*=n*m;
-    // initialize data
-    mat->values=new T[mat->Nnz_];
-    mat->rowindex=new int[mat->Nnz_];
-    mat->colstart=new int[cols+1];
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::allocateMarker()
-  {
-    marker = new typename Matrix::size_type[cols];
-
-    for(size_type i=0; i < cols; ++i)
-      marker[i]=0;
-  }
-
-  template<class T, class A, int n, int m>
-  template<typename Iter>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::countEntries(const Iter& row, const CIter& col) const
-  {
-    countEntries(col.index());
-
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::countEntries(size_type colindex) const
-  {
-    for(size_type i=0; i < m; ++i) {
-      assert(colindex*m+i<cols);
-      marker[colindex*m+i]+=n;
-    }
-
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::calcColstart() const
-  {
-    mat->colstart[0]=0;
-    for(size_type i=0; i < cols; ++i) {
-      assert(i<cols);
-      mat->colstart[i+1]=mat->colstart[i]+marker[i];
-      marker[i]=mat->colstart[i];
-    }
-  }
-
-  template<class T, class A, int n, int m>
-  template<typename Iter>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::copyValue(const Iter& row, const CIter& col) const
-  {
-    copyValue(col, row.index(), col.index());
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::copyValue(const CIter& col, size_type rowindex, size_type colindex) const
-  {
-    for(size_type i=0; i<n; i++) {
-      for(size_type j=0; j<m; j++) {
-        assert(colindex*m+j<cols-1 || (int)marker[colindex*m+j]<mat->colstart[colindex*m+j+1]);
-        assert((int)marker[colindex*m+j]<mat->Nnz_);
-        mat->rowindex[marker[colindex*m+j]]=rowindex*n+i;
-        mat->values[marker[colindex*m+j]]=(*col)[i][j];
-        ++marker[colindex*m+j]; // index for next entry in column
-      }
-    }
-  }
-
-  template<class T, class A, int n, int m>
-  void SuperMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::createMatrix() const
-  {
-    delete[] marker;
-    marker=0;
-    SuperMatrixCreateSparseChooser<T>
-    ::create(&mat->A, mat->N_, mat->M_, mat->colstart[cols],
-             mat->values, mat->rowindex, mat->colstart, SLU_NC,
+      ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> >::createMatrix();
+      SuperMatrixCreateSparseChooser<T>
+           ::create(&slumat->A, slumat->N_, slumat->M_, slumat->colstart[this->cols],
+             slumat->values,slumat->rowindex, slumat->colstart, SLU_NC,
              static_cast<Dtype_t>(GetSuperLUType<T>::type), SLU_GE);
-  }
-
-  template<class F, class MRS>
-  void copyToSuperMatrix(F& initializer, const MRS& mrs)
-  {
-    typedef typename MRS::const_iterator Iter;
-    typedef typename  std::iterator_traits<Iter>::value_type::const_iterator CIter;
-    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
-      initializer.addRowNnz(row);
-
-    initializer.allocate();
-
-    for(Iter row=mrs.begin(); row!= mrs.end(); ++row) {
-
-      for(CIter col=row->begin(); col != row->end(); ++col)
-        initializer.countEntries(row, col);
-    }
-
-    initializer.calcColstart();
-
-    for(Iter row=mrs.begin(); row!= mrs.end(); ++row) {
-      for(CIter col=row->begin(); col != row->end(); ++col) {
-        initializer.copyValue(row, col);
-      }
-
-    }
-    initializer.createMatrix();
-  }
-
-  template<class F, class M,class S>
-  void copyToSuperMatrix(F& initializer, const MatrixRowSubset<M,S>& mrs)
-  {
-    typedef MatrixRowSubset<M,S> MRS;
-    typedef typename MRS::RowIndexSet SIS;
-    typedef typename SIS::const_iterator SIter;
-    typedef typename MRS::const_iterator Iter;
-    typedef typename std::iterator_traits<Iter>::value_type row_type;
-    typedef typename row_type::const_iterator CIter;
-
-    // Calculate upper Bound for nonzeros
-    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
-      initializer.addRowNnz(row, mrs.rowIndexSet());
-
-    initializer.allocate();
-
-    typedef typename MRS::Matrix::size_type size_type;
-
-    // A vector containing the corresponding indices in
-    // the to create submatrix.
-    // If an entry is the maximum of size_type then this index will not appear in
-    // the submatrix.
-    std::vector<size_type> subMatrixIndex(mrs.matrix().N(),
-                                          std::numeric_limits<size_type>::max());
-    size_type s=0;
-    for(SIter index = mrs.rowIndexSet().begin(); index!=mrs.rowIndexSet().end(); ++index)
-      subMatrixIndex[*index]=s++;
-
-    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
-      for(CIter col=row->begin(); col != row->end(); ++col) {
-        if(subMatrixIndex[col.index()]!=std::numeric_limits<size_type>::max())
-          // This column is in our subset (use submatrix column index)
-          initializer.countEntries(subMatrixIndex[col.index()]);
-      }
-
-    initializer.calcColstart();
-
-    for(Iter row=mrs.begin(); row!= mrs.end(); ++row)
-      for(CIter col=row->begin(); col != row->end(); ++col) {
-        if(subMatrixIndex[col.index()]!=std::numeric_limits<size_type>::max())
-          // This value is in our submatrix -> copy (use submatrix indices
-          initializer.copyValue(col, subMatrixIndex[row.index()], subMatrixIndex[col.index()]);
-      }
-    initializer.createMatrix();
-  }
-
-#ifndef DOXYGEN
-
-  template<class B, class TA, int n, int m>
-  bool SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator==(const BCRSMatrix<FieldMatrix<B,n,m>,TA>& mat) const
-  {
-    const NCformat* S=static_cast<const NCformat *>(A.Store);
-    for(size_type col=0; col < M(); ++col) {
-      for(int j=S->colptr[col]; j < S->colptr[col+1]; ++j) {
-        int row=S->rowind[j];
-        if((mat[row/n][col/m])[row%n][col%m]!=reinterpret_cast<B*>(S->nzval)[j]) {
-          std::cerr<<" bcrs["<<row/n<<"]["<<col/m<<"]["<<row%n<<"]["<<row%m
-                   <<"]="<<(mat[row/n][col/m])[row%n][col%m]<<" super["<<row<<"]["<<col<<"]="<<reinterpret_cast<B*>(S->nzval)[j];
-
-          return false;
-        }
-      }
-    }
-
-    return true;
-  }
-
-#endif // DOYXGEN
-
-  template<class B, class TA, int n, int m>
-  bool operator==(SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >& sla, BCRSMatrix<FieldMatrix<B,n,m>,TA>& a)
-  {
-    return a==sla;
-  }
-
-#ifndef DOXYGEN
-
-  template<class B, class TA, int n, int m>
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::SuperLUMatrix()
-    : N_(0), M_(0), Nnz_(0), values(0), rowindex(0), colstart(0)
-  {}
-
-  template<class B, class TA, int n, int m>
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
-  ::SuperLUMatrix(const Matrix& mat)
-    : N_(n*mat.N()), M_(m*mat.M()), Nnz_(n*m*mat.Nnz())
-  {}
-
-  template<class B, class TA, int n, int m>
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >&
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator=(const Matrix& mat)
-  {
-    if(N_+M_+Nnz_!=0)
-      free();
-    setMatrix(mat);
-    return *this;
-  }
-
-  template<class B, class TA, int n, int m>
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >&
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::operator=(const SuperLUMatrix& mat)
-  {
-    if(N_+M_+Nnz_!=0)
-      free();
-    N_=mat.N_;
-    M_=mat.M_;
-    Nnz_= mat.Nnz_;
-    if(M_>0) {
-      colstart=new int[M_+1];
-      for(int i=0; i<=M_; ++i)
-        colstart[i]=mat.colstart[i];
     }
-
-    if(Nnz_>0) {
-      values = new B[Nnz_];
-      rowindex = new int[Nnz_];
-
-      for(int i=0; i<Nnz_; ++i)
-        values[i]=mat.values[i];
-
-      for(int i=0; i<Nnz_; ++i)
-        rowindex[i]=mat.rowindex[i];
-    }
-    if(M_+Nnz_>0)
-      dCreate_CompCol_Matrix(&A, N_, M_, Nnz_,
-                             values, rowindex, colstart, SLU_NC, static_cast<Dtype_t>(GetSuperLUType<B>::type), SLU_GE);
-    return *this;
-  }
-
-  template<class B, class TA, int n, int m>
-  void SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
-  ::setMatrix(const Matrix& mat)
-  {
-    N_=n*mat.N();
-    M_=m*mat.M();
-    SuperMatrixInitializer<Matrix> initializer(*this);
-
-    copyToSuperMatrix(initializer, MatrixRowSet<Matrix>(mat));
-
-#ifdef DUNE_ISTL_WITH_CHECKING
-    char name[] = {'A',0};
-    if(N_<0)
-      SuperMatrixPrinter<B>::print(name,&A);
-    assert(*this==mat);
-#endif
-  }
-
-  template<class B, class TA, int n, int m>
-  template<class S>
-  void SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >
-  ::setMatrix(const Matrix& mat, const S& mrs)
-  {
-    if(N_+M_+Nnz_!=0)
-      free();
-    N_=mrs.size()*n;
-    M_=mrs.size()*m;
-    SuperMatrixInitializer<Matrix> initializer(*this);
-
-    copyToSuperMatrix(initializer, MatrixRowSubset<Matrix,S>(mat,mrs));
-
-#ifdef DUNE_ISTL_WITH_CHECKING
-    char name[] = {'A',0};
-    if(N_<0)
-      SuperMatrixPrinter<B>::print(name,&A);
-#endif
-  }
-
-  template<class B, class TA, int n, int m>
-  SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::~SuperLUMatrix()
-  {
-    if(N_+M_+Nnz_!=0)
-      free();
-  }
-
-  template<class B, class TA, int n, int m>
-  void SuperLUMatrix<BCRSMatrix<FieldMatrix<B,n,m>,TA> >::free()
-  {
-    delete[] values;
-    delete[] rowindex;
-    delete[] colstart;
-    SUPERLU_FREE(A.Store);
-    N_=M_=Nnz_=0;
-  }
-
-#endif // DOXYGEN
-
+    private:
+    SuperLUMatrix* slumat;
+  };
 }
 #endif
 #endif
diff --git a/dune/istl/test/CMakeLists.txt b/dune/istl/test/CMakeLists.txt
index 60b3dfed0e2f741925ed79f5d91883128ed061e3..9c9ad552e9f769cff6fe0632b90958c99ea32f2a 100644
--- a/dune/istl/test/CMakeLists.txt
+++ b/dune/istl/test/CMakeLists.txt
@@ -21,14 +21,22 @@ endif(HAVE_PARDISO)
 if(SUPERLU_FOUND)
   set(SUPERLUTESTS
   complexrhstest superlutest superluztest superluctest superlustest
-    overlappingschwarztest)
+  )
 endif(SUPERLU_FOUND)
 
+if(UMFPACK_FOUND)
+  set(UMFPACKTESTS umfpacktest)
+endif()
+
+if ((SUPERLU_FOUND) OR (UMFPACK_FOUND))
+  set(OVLPSCHWARZTESTS overlappingschwarztest)
+endif()
+
 if(HAVE_MPI)
   set(MPITESTS vectorcommtest matrixmarkettest matrixredisttest)
 endif(HAVE_MPI)
 
-set(ALLTESTS ${MPITESTS} ${NORMALTEST} ${PARDISOTEST} ${SUPERLUTESTS})
+set(ALLTESTS ${MPITESTS} ${NORMALTEST} ${PARDISOTEST} ${SUPERLUTESTS} ${UMFPACKTESTS} ${OVLPSCHWARZTESTS})
 
 
 # We do not want want to build the tests during make all,
@@ -78,11 +86,25 @@ if(SUPERLU_FOUND)
   add_executable(superluztest "superlutest.cc")
   set_property(TARGET superluztest APPEND PROPERTY COMPILE_DEFINITIONS "SUPERLU_NTYPE=3")
 
-  add_executable(overlappingschwarztest "overlappingschwarztest.cc")
-
   add_dune_superlu_flags("${SUPERLUTESTS}")
 endif(SUPERLU_FOUND)
 
+if(UMFPACK_FOUND)
+  add_executable(umfpacktest umfpacktest.cc)
+  add_dune_umfpack_flags(umfpacktest)
+  set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "umfpack_decomp")
+endif()
+
+if ((SUPERLU_FOUND) OR (UMFPACK_FOUND))
+  add_executable(overlappingschwarztest "overlappingschwarztest.cc")
+  if (SUPERLU_FOUND)
+    add_dune_superlu_flags(overlappingschwarztest)
+  endif()
+  if (UMFPACK_FOUND)
+    add_dune_umfpack_flags(overlappingschwarztest)
+  endif()
+endif()
+
 if(HAVE_MPI)
   add_executable(matrixredisttest "matrixredisttest.cc")
   add_executable(vectorcommtest "vectorcommtest.cc")
diff --git a/dune/istl/test/Makefile.am b/dune/istl/test/Makefile.am
index c0de4632f4cd9f65b52592e50e483bed7f994cd0..bd531d34644ba5ca62e7a0ad38a0d1715e69be43 100644
--- a/dune/istl/test/Makefile.am
+++ b/dune/istl/test/Makefile.am
@@ -9,13 +9,17 @@ if MPI
 endif
 
 if SUPERLU
-  SUPERLUTESTS =  superlutest superluztest superluctest superlustest overlappingschwarztest
+  SUPERLUTESTS =  superlutest superluztest superluctest superlustest
 endif
 
 if PARDISO
   PARDISOTEST = test_pardiso
 endif
 
+if UMFPACK
+  UMFPACKTEST = umfpacktest
+endif
+
 # which tests where program to build and run are equal
 NORMALTESTS = basearraytest \
               bcrsbuildtest \
@@ -29,18 +33,24 @@ NORMALTESTS = basearraytest \
               matrixutilstest \
               mmtest \
               mv \
+              overlappingschwarztest \
               scaledidmatrixtest \
               seqmatrixmarkettest \
               vbvectortest
 
 # list of tests to run (indicestest is special case)
-TESTS = $(NORMALTESTS) $(MPITESTS) $(SUPERLUTESTS) $(PARDISOTEST) $(PARMETISTESTS)
+TESTS = $(NORMALTESTS) $(MPITESTS) $(SUPERLUTESTS) $(PARDISOTEST) $(PARMETISTESTS) $(UMFPACKTEST)
 
 # programs just to build when "make check" is used
-check_PROGRAMS = $(NORMALTESTS) $(MPITESTS) $(SUPERLUTESTS) $(PARDISOTEST) $(PARMETISTESTS)
+check_PROGRAMS = $(NORMALTESTS) $(MPITESTS) $(SUPERLUTESTS) $(PARDISOTEST) $(PARMETISTESTS) $(UMFPACKTEST)
 
 # define the programs
 
+overlappingschwarztest_SOURCES = overlappingschwarztest.cc
+overlappingschwarztest_LDADD =
+overlappingschwarztest_LDFLAGS= $(AM_LDFLAGS)
+overlappingschwarztest_CPPFLAGS= $(AM_CPPFLAGS)
+
 if SUPERLU
   superlutest_SOURCES = superlutest.cc
   superlutest_LDADD= $(SUPERLU_LIBS)
@@ -64,13 +74,21 @@ if SUPERLU
   superluztest_LDFLAGS= $(AM_LDFLAGS) $(SUPERLU_LDFLAGS)
   superluztest_CPPFLAGS=$(AM_CPPFLAGS) $(SUPERLU_CPPFLAGS) -DSUPERLU_NTYPE=3
 
-  overlappingschwarztest_SOURCES = overlappingschwarztest.cc
-  overlappingschwarztest_LDADD= $(SUPERLU_LIBS)
-  overlappingschwarztest_LDFLAGS= $(AM_LDFLAGS) $(SUPERLU_LDFLAGS)
-  overlappingschwarztest_CPPFLAGS=$(AM_CPPFLAGS) $(SUPERLU_CPPFLAGS)
+  overlappingschwarztest_LDADD += $(SUPERLU_LIBS)
+  overlappingschwarztest_LDFLAGS +=  $(SUPERLU_LDFLAGS)
+  overlappingschwarztest_CPPFLAGS += $(SUPERLU_CPPFLAGS)
 endif
 
+if UMFPACK
+  umfpacktest_SOURCES= umfpacktest.cc
+  umfpacktest_LDADD= $(UMFPACK_LIBS)
+  umfpacktest_LDFLAGS= $(AM_LDFLAGS) $(UMFPACK_LDFLAGS)
+  umfpacktest_CPPFLAGS= $(AM_CPPFLAGS) $(UMFPACK_CPPFLAGS)
 
+  overlappingschwarztest_LDADD += $(UMFPACK_LIBS)
+  overlappingschwarztest_LDFLAGS += $(UMFPACK_LDFLAGS)
+  overlappingschwarztest_CPPFLAGS += $(UMFPACK_CPPFLAGS)
+endif
 
 if PARDISO
   test_pardiso_SOURCES = test_pardiso.cc
@@ -145,3 +163,5 @@ endif
 include $(top_srcdir)/am/global-rules
 
 EXTRA_DIST = CMakeLists.txt
+
+CLEANFILES = umfpack_decomp
\ No newline at end of file
diff --git a/dune/istl/test/overlappingschwarztest.cc b/dune/istl/test/overlappingschwarztest.cc
index 2355942608900be47c12cc1ca2a74eae6935cd31..226e00a38e5d175eb1abae131b0a21626b606c29 100644
--- a/dune/istl/test/overlappingschwarztest.cc
+++ b/dune/istl/test/overlappingschwarztest.cc
@@ -11,6 +11,8 @@
 #include <dune/common/sllist.hh>
 #include <dune/istl/overlappingschwarz.hh>
 #include <dune/istl/solvers.hh>
+#include<dune/istl/superlu.hh>
+#include<dune/istl/umfpack.hh>
 
 #include <iterator>
 
@@ -137,11 +139,20 @@ int main(int argc, char** argv)
   //  b=0;
   //  x=100;
   //  setBoundary(x,b,N);
-  //Dune::SeqOverlappingSchwarz<BCRSMat,BVector,Dune::AdditiveSchwarzMode,
-  //    Dune::SuperLU<BCRSMat> > prec0(mat, domains, 1);
-  Dune::SeqOverlappingSchwarz<BCRSMat,BVector> prec0(mat, domains, 1);
+#if HAVE_UMFPACK
+  std::cout << "Do testing with UMFPack" << std::endl;
+  Dune::SeqOverlappingSchwarz<BCRSMat,BVector,Dune::AdditiveSchwarzMode,
+      Dune::UMFPack<BCRSMat> > prec0(mat, domains, 1);
   Dune::LoopSolver<BVector> solver0(fop, prec0, 1e-2,100,2);
   solver0.apply(x,b, res);
+#endif
+#if HAVE_SUPERLU
+  std::cout << "Do testing with SuperLU" << std::endl;
+  Dune::SeqOverlappingSchwarz<BCRSMat,BVector,Dune::AdditiveSchwarzMode,
+      Dune::SuperLU<BCRSMat> > slu_prec0(mat, domains, 1);
+  Dune::LoopSolver<BVector> slu_solver(fop, slu_prec0, 1e-2,100,2);
+  slu_solver.apply(x,b, res);
+#endif
   return 0;
 
   std::cout<<"Additive Schwarz not on the fly (domains vector)"<<std::endl;
diff --git a/dune/istl/test/umfpacktest.cc b/dune/istl/test/umfpacktest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ce45368ef0c31653b3909db09f00970c0579bfbf
--- /dev/null
+++ b/dune/istl/test/umfpacktest.cc
@@ -0,0 +1,80 @@
+#include "config.h"
+
+#include <complex>
+#include<iostream>
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/timer.hh>
+#include <dune/istl/bvector.hh>
+#include <dune/istl/colcompmatrix.hh>
+#include <dune/istl/io.hh>
+#include <dune/istl/operators.hh>
+#include <dune/istl/umfpack.hh>
+
+#include "laplacian.hh"
+
+
+int main(int argc, char** argv)
+{
+  try
+  {
+    typedef int I;
+    typedef double FIELD_TYPE;
+    //typedef std::complex<double> FIELD_TYPE;
+
+    const int BS=1;
+    std::size_t N=100;
+
+    if(argc>1)
+      N = atoi(argv[1]);
+    std::cout<<"testing for N="<<N<<" BS="<<1<<std::endl;
+
+    typedef Dune::FieldMatrix<FIELD_TYPE,BS,BS> MatrixBlock;
+    typedef Dune::BCRSMatrix<MatrixBlock> BCRSMat;
+    typedef Dune::FieldVector<FIELD_TYPE,BS> VectorBlock;
+    typedef Dune::BlockVector<VectorBlock> Vector;
+    typedef Dune::MatrixAdapter<BCRSMat,Vector,Vector> Operator;
+
+    BCRSMat mat;
+    Operator fop(mat);
+    Vector b(N*N), x(N*N);
+
+    setupLaplacian(mat,N);
+    b=1;
+    x=0;
+
+    Dune::Timer watch;
+
+    watch.reset();
+
+    Dune::UMFPack<BCRSMat> solver(mat,1);
+
+    Dune::InverseOperatorResult res;
+
+    Dune::UMFPack<BCRSMat> solver1;
+
+    std::set<std::size_t> mrs;
+    for(std::size_t s=0; s < N/2; ++s)
+      mrs.insert(s);
+
+    solver1.setSubMatrix(mat,mrs);
+    solver1.setVerbosity(true);
+
+    solver.apply(x,b, res);
+    solver.free();
+
+    solver1.apply(x,b, res);
+    solver1.apply(reinterpret_cast<FIELD_TYPE*>(&x[0]), reinterpret_cast<FIELD_TYPE*>(&b[0]));
+
+    Dune::UMFPack<BCRSMat> save_solver(mat,"umfpack_decomp",0);
+    Dune::UMFPack<BCRSMat> load_solver(mat,"umfpack_decomp",0);
+    return 0;
+  }
+  catch(Dune::Exception &e)
+  {
+    std::cerr << "Dune reported error: " << e << std::endl;
+  }
+  catch (...)
+  {}
+}
diff --git a/dune/istl/umfpack.hh b/dune/istl/umfpack.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6aa92c0816f77fcf79964d918d740727a18efbce
--- /dev/null
+++ b/dune/istl/umfpack.hh
@@ -0,0 +1,460 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_UMFPACK_HH
+#define DUNE_UMFPACK_HH
+
+#if HAVE_UMFPACK
+
+#include<complex>
+#include<type_traits>
+
+#include<umfpack.h>
+
+#include<dune/common/exceptions.hh>
+#include<dune/common/fmatrix.hh>
+#include<dune/common/fvector.hh>
+#include<dune/istl/bcrsmatrix.hh>
+#include<dune/istl/solvers.hh>
+#include<dune/istl/solvertype.hh>
+
+#include"colcompmatrix.hh"
+
+
+namespace Dune {
+  /**
+   * @addtogroup ISTL
+   *
+   * @{
+   */
+  /**
+   * @file
+   * @author Dominic Kempf
+   * @brief Classes for using UMFPack with ISTL matrices.
+   */
+
+  // FORWARD DECLARATIONS
+  template<class M, class T, class TM, class TD, class TA>
+  class SeqOverlappingSchwarz;
+
+  template<class T, bool tag>
+  struct SeqOverlappingSchwarzAssemblerHelper;
+
+  /** @brief use the UMFPack Package to directly solve linear systems
+   * @tparam Matrix the matrix type defining the system
+   * Details on UMFPack are to be found on
+   * http://www.cise.ufl.edu/research/sparse/umfpack/
+   */
+  template<class Matrix>
+  class UMFPack
+  {};
+
+  // wrapper class for C-Function Calls in the backend. Choose the right function namespace
+  // depending on the template parameter used.
+  template<typename T>
+  struct UMFPackMethodChooser
+  {};
+
+  template<>
+  struct UMFPackMethodChooser<double>
+  {
+    template<typename... A>
+    static void defaults(A... args)
+    {
+      umfpack_di_defaults(args...);
+    }
+    template<typename... A>
+    static void free_numeric(A... args)
+    {
+      umfpack_di_free_numeric(args...);
+    }
+    template<typename... A>
+    static void free_symbolic(A... args)
+    {
+      umfpack_di_free_symbolic(args...);
+    }
+    template<typename... A>
+    static int load_numeric(A... args)
+    {
+      return umfpack_di_load_numeric(args...);
+    }
+    template<typename... A>
+    static void numeric(A... args)
+    {
+      umfpack_di_numeric(args...);
+    }
+    template<typename... A>
+    static void report_info(A... args)
+    {
+      umfpack_di_report_info(args...);
+    }
+    template<typename... A>
+    static void report_status(A... args)
+    {
+      umfpack_di_report_status(args...);
+    }
+    template<typename... A>
+    static int save_numeric(A... args)
+    {
+      return umfpack_di_save_numeric(args...);
+    }
+    template<typename... A>
+    static void solve(A... args)
+    {
+      umfpack_di_solve(args...);
+    }
+    template<typename... A>
+    static void symbolic(A... args)
+    {
+      umfpack_di_symbolic(args...);
+    }
+  };
+
+  template<>
+  struct UMFPackMethodChooser<std::complex<double> >
+  {
+    template<typename... A>
+    static void defaults(A... args)
+    {
+      umfpack_zi_defaults(args...);
+    }
+    template<typename... A>
+    static void free_numeric(A... args)
+    {
+      umfpack_zi_free_numeric(args...);
+    }
+    template<typename... A>
+    static void free_symbolic(A... args)
+    {
+      umfpack_zi_free_symbolic(args...);
+    }
+    template<typename... A>
+    static int load_numeric(A... args)
+    {
+      return umfpack_zi_load_numeric(args...);
+    }
+    template<typename... A>
+    static void numeric(const int* cs, const int* ri, const double* val, A... args)
+    {
+      umfpack_zi_numeric(cs,ri,val,NULL,args...);
+    }
+    template<typename... A>
+    static void report_info(A... args)
+    {
+      umfpack_zi_report_info(args...);
+    }
+    template<typename... A>
+    static void report_status(A... args)
+    {
+      umfpack_zi_report_status(args...);
+    }
+    template<typename... A>
+    static int save_numeric(A... args)
+    {
+      return umfpack_zi_save_numeric(args...);
+    }
+    template<typename... A>
+    static void solve(int m, const int* cs, const int* ri, std::complex<double>* val, double* x, const double* b,A... args)
+    {
+      const double* cval = reinterpret_cast<const double*>(val);
+      umfpack_zi_solve(m,cs,ri,cval,NULL,x,NULL,b,NULL,args...);
+    }
+    template<typename... A>
+    static void symbolic(int m, int n, const int* cs, const int* ri, const double* val, A... args)
+    {
+      umfpack_zi_symbolic(m,n,cs,ri,val,NULL,args...);
+    }
+  };
+
+  /** @brief use the UMFPack Package to directly solve linear systems
+   *
+   * Specialization for the Dune::BCRSMatrix. UMFPack will always go double
+   * precision and supports complex numbers
+   * too (use std::complex<double> for that).
+   */
+  template<typename T, typename A, int n, int m>
+  class UMFPack<BCRSMatrix<FieldMatrix<T,n,m>,A > >
+      : public InverseOperator<
+          BlockVector<FieldVector<T,m>,
+              typename A::template rebind<FieldVector<T,m> >::other>,
+          BlockVector<FieldVector<T,n>,
+              typename A::template rebind<FieldVector<T,n> >::other> >
+  {
+    public:
+    /** @brief The matrix type. */
+    typedef Dune::BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
+    typedef Dune::BCRSMatrix<FieldMatrix<T,n,m>,A> matrix_type;
+    /** @brief The corresponding SuperLU Matrix type.*/
+    typedef Dune::ColCompMatrix<Matrix> UMFPackMatrix;
+    /** @brief Type of an associated initializer class. */
+    typedef ColCompMatrixInitializer<BCRSMatrix<FieldMatrix<T,n,m>,A> > MatrixInitializer;
+    /** @brief The type of the domain of the solver. */
+    typedef Dune::BlockVector<
+        FieldVector<T,m>,
+        typename A::template rebind<FieldVector<T,m> >::other> domain_type;
+    /** @brief The type of the range of the solver. */
+    typedef Dune::BlockVector<
+        FieldVector<T,n>,
+        typename A::template rebind<FieldVector<T,n> >::other> range_type;
+
+    /** @brief construct a solver object from a BCRSMatrix
+     *  @param mat_ the matrix to solve for
+     *  @param verbose [0..2] set the verbosity level, defaults to 0
+     */
+    UMFPack(const Matrix& mat_, int verbose=0)
+    {
+      //check whether T is a supported type
+      static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
+                    "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
+      Caller::defaults(UMF_Control);
+      setVerbosity(verbose);
+      setMatrix(mat_);
+    }
+
+    /** @brief default constructor
+     */
+    UMFPack() : verbose(0)
+    {
+      //check whether T is a supported type
+      static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
+                    "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
+      Caller::defaults(UMF_Control);
+    }
+
+    /** @brief try loading a decomposition from file and do a decomposition if unsuccesful
+     * @param mat_ the matrix to decompose when no decoposition file found
+     * @param file the decomposition file
+     * @param verbose the verbosity level
+     * use saveDecomposition(char* file) for manually storing a decomposition. This constructor
+     * will decompose mat_ and store the result to file if no file wasnt found in the first place.
+     * Thus, if you always use this you will only compute the decomposition once (and when you manually
+     * deleted the decomposition file).
+     */
+    UMFPack(const Matrix& mat_, const char* file, int verbose=0)
+    {
+      //check whether T is a supported type
+      static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
+                    "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
+      Caller::defaults(UMF_Control);
+      setVerbosity(verbose);
+      int errcode = Caller::load_numeric(&UMF_Numeric, const_cast<char*>(file));
+      if ((errcode == UMFPACK_ERROR_out_of_memory) || (errcode == UMFPACK_ERROR_file_IO))
+      {
+        setMatrix(mat_);
+        saveDecomposition(file);
+      }
+      else
+        std::cout << "UMFPack decomposition succesfully loaded from " << file << std::endl;
+    }
+
+    /** @brief try loading a decomposition from file
+     * @param file the decomposition file
+     * @param verbose the verbosity level
+     * throws an exception when not being able to load the file. Doesnt need knowledge of the
+     * actual matrix!
+     */
+    UMFPack(const char* file, int verbose=0)
+    {
+      //check whether T is a supported type
+      static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
+                    "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
+      Caller::defaults(UMF_Control);
+      int errcode = Caller::load_numeric(&UMF_Numeric, const_cast<char*>(file));
+      if (errcode == UMFPACK_ERROR_out_of_memory)
+        DUNE_THROW(Dune::Exception, "ran out of memory while loading UMFPack decomposition");
+      if (errcode == UMFPACK_ERROR_file_IO)
+        DUNE_THROW(Dune::Exception, "IO error while loading UMFPack decomposition");
+      std::cout << "UMFPack decomposition succesfully loaded from " << file << std::endl;
+      setVerbosity(verbose);
+    }
+
+    ~UMFPack()
+    {
+      if (mat.N() + mat.M() > 0)
+      free();
+    }
+
+    /**
+     *  \copydoc InverseOperator::apply(X&, Y&, InverserOperatorResult&)
+     */
+    void apply(domain_type& x, range_type& b, InverseOperatorResult& res)
+    {
+      Caller::solve(UMFPACK_A,
+                    mat.getColStart(),
+                    mat.getRowIndex(),
+                    mat.getValues(),
+                    reinterpret_cast<double*>(&x[0]),
+                    reinterpret_cast<double*>(&b[0]),
+                    UMF_Numeric,
+                    UMF_Control,
+                    UMF_Info);
+
+      //this is a direct solver
+      res.iterations = 1;
+      res.converged = true;
+
+      printOnApply();
+    }
+
+    /**
+     *  \copydoc InverseOperator::apply(X&,Y&,double,InverseOperatorResult&)
+     */
+    void apply (domain_type& x, range_type& b, double reduction, InverseOperatorResult& res)
+    {
+      apply(x,b,res);
+    }
+
+    /**
+     * @brief additional apply method with c-arrays in analogy to superlu
+     * @param x solution array
+     * @param b rhs array
+     */
+    void apply(T* x, T* b)
+    {
+      Caller::solve(UMFPACK_A,
+                    mat.getColStart(),
+                    mat.getRowIndex(),
+                    mat.getValues(),
+                    x,
+                    b,
+                    UMF_Numeric,
+                    UMF_Control,
+                    UMF_Info);
+      printOnApply();
+    }
+
+    /** @brief saves a decomposition to a file
+     * @param file the filename to save to
+     */
+    void saveDecomposition(const char* file)
+    {
+      int errcode = Caller::save_numeric(UMF_Numeric, const_cast<char*>(file));
+      if (errcode != UMFPACK_OK)
+        DUNE_THROW(Dune::Exception,"IO ERROR while trying to save UMFPack decomposition");
+    }
+
+    /** @brief Initialize data from given matrix. */
+    void setMatrix(const Matrix& _mat)
+    {
+      if (mat.N() + mat.M() > 0)
+        free();
+      mat = _mat;
+      decompose();
+    }
+
+    template<class S>
+    void setSubMatrix(const Matrix& _mat, const S& rowIndexSet)
+    {
+      if (mat.N() + mat.M() > 0)
+        free();
+      mat.setMatrix(_mat,rowIndexSet);
+      decompose();
+    }
+
+    /** @brief sets the verbosity level for the UMFPack solver
+     * @param v verbosity level
+     * The following levels are implemented:
+     * 0 - only error messages
+     * 1 - a bit of statistics on decomposition and solution
+     * 2 - lots of statistics on decomposition and solution
+     */
+    void setVerbosity(int v)
+    {
+      verbose = v;
+      // set the verbosity level in UMFPack
+      if (verbose == 0)
+        UMF_Control[UMFPACK_PRL] = 1;
+      if (verbose == 1)
+        UMF_Control[UMFPACK_PRL] = 2;
+      if (verbose == 2)
+        UMF_Control[UMFPACK_PRL] = 4;
+    }
+
+    /**
+     * @brief free allocated space.
+     * @warning later calling apply will result in an error.
+     */
+    void free()
+    {
+      Caller::free_symbolic(&UMF_Symbolic);
+      Caller::free_numeric(&UMF_Numeric);
+      mat.free();
+    }
+
+    private:
+    typedef typename Dune::UMFPackMethodChooser<T> Caller;
+
+    template<class M,class X, class TM, class TD, class T1>
+    friend class SeqOverlappingSchwarz;
+    friend struct SeqOverlappingSchwarzAssemblerHelper<UMFPack<Matrix>,true>;
+
+    /** @brief computes the LU Decomposition */
+    void decompose()
+    {
+      Caller::symbolic(static_cast<int>(mat.N()),
+                       static_cast<int>(mat.N()),
+                       mat.getColStart(),
+                       mat.getRowIndex(),
+                       reinterpret_cast<double*>(mat.getValues()),
+                       &UMF_Symbolic,
+                       UMF_Control,
+                       UMF_Info);
+      Caller::numeric(mat.getColStart(),
+                      mat.getRowIndex(),
+                      reinterpret_cast<double*>(mat.getValues()),
+                      UMF_Symbolic,
+                      &UMF_Numeric,
+                      UMF_Control,
+                      UMF_Info);
+      Caller::report_status(UMF_Control,UMF_Info[UMFPACK_STATUS]);
+      if (verbose == 1)
+      {
+        std::cout << "[UMFPack Decomposition]" << std::endl;
+        std::cout << "Wallclock Time taken: " << UMF_Info[UMFPACK_NUMERIC_WALLTIME] << " (CPU Time: " << UMF_Info[UMFPACK_NUMERIC_TIME] << ")" << std::endl;
+        std::cout << "Flops taken: " << UMF_Info[UMFPACK_FLOPS] << std::endl;
+        std::cout << "Peak Memory Usage: " << UMF_Info[UMFPACK_PEAK_MEMORY]*UMF_Info[UMFPACK_SIZE_OF_UNIT] << " bytes" << std::endl;
+        std::cout << "Condition number estimate: " << 1./UMF_Info[UMFPACK_RCOND] << std::endl;
+        std::cout << "Numbers of non-zeroes in decomposition: L: " << UMF_Info[UMFPACK_LNZ] << " U: " << UMF_Info[UMFPACK_UNZ] << std::endl;
+      }
+      if (verbose == 2)
+      {
+        Caller::report_info(UMF_Control,UMF_Info);
+      }
+    }
+
+    void printOnApply()
+    {
+      Caller::report_status(UMF_Control,UMF_Info[UMFPACK_STATUS]);
+      if (verbose > 0)
+      {
+        std::cout << "[UMFPack Solve]" << std::endl;
+        std::cout << "Wallclock Time: " << UMF_Info[UMFPACK_SOLVE_WALLTIME] << " (CPU Time: " << UMF_Info[UMFPACK_SOLVE_TIME] << ")" << std::endl;
+        std::cout << "Flops Taken: " << UMF_Info[UMFPACK_SOLVE_FLOPS] << std::endl;
+        std::cout << "Iterative Refinement steps taken: " << UMF_Info[UMFPACK_IR_TAKEN] << std::endl;
+        std::cout << "Error Estimate: " << UMF_Info[UMFPACK_OMEGA1] << " resp. " << UMF_Info[UMFPACK_OMEGA2] << std::endl;
+      }
+    }
+
+    UMFPackMatrix mat;
+    int verbose;
+    void *UMF_Symbolic;
+    void *UMF_Numeric;
+    double UMF_Info[UMFPACK_INFO];
+    double UMF_Control[UMFPACK_CONTROL];
+  };
+
+  template<typename T, typename A, int n, int m>
+  struct IsDirectSolver<UMFPack<BCRSMatrix<FieldMatrix<T,n,m>,A> > >
+  {
+    enum { value=true};
+  };
+
+  template<typename T, typename A, int n, int m>
+  struct StoresColumnCompressed<UMFPack<BCRSMatrix<FieldMatrix<T,n,m>,A> > >
+  {
+    enum { value = true };
+  };
+}
+
+#endif //HAVE_UMFPACK
+
+#endif //DUNE_UMFPACK_HH
diff --git a/m4/dune_istl.m4 b/m4/dune_istl.m4
index 1c03bc230d2c1091aa56330201320e228fec0ac8..fcc3bed05ddbdf8a8c3d2845d45105138f2c417b 100644
--- a/m4/dune_istl.m4
+++ b/m4/dune_istl.m4
@@ -3,6 +3,7 @@ AC_DEFUN([DUNE_ISTL_CHECKS],
   AC_REQUIRE([DUNE_PATH_PARMETIS])
   AC_REQUIRE([DUNE_PATH_SUPERLU])
   AC_REQUIRE([DUNE_PATH_SUPERLU_DIST])
+  AC_REQUIRE([DUNE_PATH_UMFPACK])
   AC_REQUIRE([DUNE_PARDISO])
   AC_REQUIRE([__AC_FC_NAME_MANGLING])
   AC_REQUIRE([AC_PROG_F77])
diff --git a/m4/umfpack.m4 b/m4/umfpack.m4
new file mode 100644
index 0000000000000000000000000000000000000000..189b04a7a369bd712a289e3e22ac7268f60a5248
--- /dev/null
+++ b/m4/umfpack.m4
@@ -0,0 +1,141 @@
+# courtesy of the dune-fem maintainers
+
+AC_DEFUN([DUNE_PATH_UMFPACK],[
+  AC_REQUIRE([AC_PROG_CC])
+
+  AC_ARG_WITH(umfpack,
+    AC_HELP_STRING([--with-umfpack=PATH],[directory with UMFPACK inside]))
+  AC_ARG_WITH(umfpack-includedir,
+    AC_HELP_STRING([--with-umfpack-includedir=PATH],[directory with UMFPACK headers inside]))
+  AC_ARG_WITH(umfpack-libdir,
+    AC_HELP_STRING([--with-umfpack-libdir=PATH],[directory with UMFPACK libraries inside]))
+
+# store old values
+ac_save_LDFLAGS="$LDFLAGS"
+ac_save_CPPFLAGS="$CPPFLAGS"
+ac_save_LIBS="$LIBS"
+
+UMFPACKYES=0
+## do nothing if no --with-umfpack was supplied
+if test x$with_umfpack != x && test x$with_umfpack != xno ; then
+  UMFPACKYES=1
+fi
+if test x$with_umfpack_includedir != x && test x$with_umfpack_includedir != xno ; then
+  UMFPACKYES=1
+fi
+if test x$with_umfpack_libdir != x && test x$with_umfpack_libdir != xno ; then
+  UMFPACKYES=1
+fi
+
+if test x$UMFPACKYES = x1 ; then
+
+  # is --with-umfpack=bla used?
+  if test "x$with_umfpack" != x ; then
+    UMFPACKROOT=`cd $with_umfpack && pwd`
+	  if ! test -d $UMFPACKROOT;  then
+      AC_MSG_WARN([UMFPACK directory $with_umfpack does not exist])
+  	fi
+
+    if test "x$UMFPACKROOT" = x; then
+      # use some default value...
+      UMFPACKROOT="/usr/local/umfpack"
+    fi
+
+    UMFAMD_LIB_PATH="$UMFPACKROOT/AMD/Lib"
+    UMFPACK_LIB_PATH="$UMFPACKROOT/UMFPACK/Lib"
+    UMFPACK_INCLUDE_PATH="$UMFPACKROOT/UMFPACK/Include"
+  else 
+    if test "x$with_umfpack_includedir" != x ; then 
+      UMFPACK_INCLUDE_PATH=`cd $with_umfpack_includedir && pwd`
+      if ! test -d $UMFPACK_INCLUDE_PATH;  then
+        AC_MSG_WARN([UMFPACK directory $with_umfpack_includedir does not exist])
+      fi
+    fi
+    if test "x$with_umfpack_libdir" != x ; then 
+      UMFPACK_LIB_PATH=`cd $with_umfpack_libdir && pwd`
+      if ! test -d $UMFPACK_LIB_PATH;  then
+        AC_MSG_WARN([UMFPACK directory $with_umfpack_libdir does not exist])
+      fi
+    fi
+    UMFAMD_LIB_PATH=$UMFPACK_LIB_PATH
+  fi
+
+  # set variables so that tests can use them
+  REM_CPPFLAGS=$CPPFLAGS
+
+  LDFLAGS="$LDFLAGS -L$UMFPACK_LIB_PATH -L$UMFAMD_LIB_PATH"
+  UMFPACK_INC_FLAG="-I$UMFPACK_INCLUDE_PATH -I$UMFPACKROOT/UFconfig -I$UMFPACKROOT/AMD/Include -I$UMFPACKROOT/SuiteSparse_config -DENABLE_UMFPACK=1"
+  CPPFLAGS="$CPPFLAGS $UMFPACK_INC_FLAG $MPI_CPPFLAGS"
+
+  # check for header
+  AC_LANG_PUSH([C])
+  AC_CHECK_HEADERS([umfpack.h], 
+     [UMFPACK_CPPFLAGS="$UMFPACK_INC_FLAG"
+    HAVE_UMFPACK="1"],
+    AC_MSG_WARN([umfpack.h not found in $UMFPACK_INCLUDE_PATH]))
+   
+  CPPFLAGS="$REM_CPPFLAGS"
+  REM_CPPFLAGS=
+
+  REM_LDFLAGS=$LDFLAGS
+
+  # if header is found...
+  if test x$HAVE_UMFPACK = x1 ; then
+    AC_CHECK_LIB(umfpack,[main],
+    [UMFPACK_LIBS="-lumfpack"
+           UMFPACK_LDFLAGS="-L$UMFPACK_LIB_PATH"],
+	  [HAVE_UMFPACK="0"
+	  AC_MSG_WARN(libumfpack not found!)])
+  fi
+
+  # if lib is found...
+  if test x$HAVE_UMFPACK = x1 ; then
+    AC_CHECK_LIB(amd,[main],
+    [UMFPACK_LIBS="$UMFPACK_LIBS -lamd"
+           UMFPACK_LDFLAGS="$UMFPACK_LDFLAGS -L$UMFAMD_LIB_PATH"
+           LIBS="$LIBS $UMFPACK_LIBS"],
+	  [HAVE_UMFPACK="0"
+	  AC_MSG_WARN(libamd not found!)])
+  fi
+
+  LDFLAGS=$REM_LDFLAGS
+  AC_LANG_POP
+
+## end of umfpack check (--without wasn't set)
+fi
+
+# survived all tests?
+if test x$HAVE_UMFPACK = x1 ; then
+  AC_SUBST(UMFPACK_LIBS, $UMFPACK_LIBS)
+  AC_SUBST(UMFPACK_LDFLAGS, $UMFPACK_LDFLAGS)
+  AC_SUBST(UMFPACK_CPPFLAGS, $UMFPACK_CPPFLAGS)
+  AC_DEFINE(HAVE_UMFPACK, ENABLE_UMFPACK,
+    [This is only true if umfpack-library was found by configure 
+     _and_ if the application uses the UMFPACK_CPPFLAGS])
+
+  # add to global list
+  DUNE_ADD_ALL_PKG([UMFPACK], [\${UMFPACK_CPPFLAGS}],
+                   [\${UMFPACK_LDFLAGS}], [\${UMFPACK_LIBS}])
+
+  # set variable for summary
+  with_umfpack="yes"
+
+else
+  AC_SUBST(UMFPACK_LIBS, "")
+  AC_SUBST(UMFPACK_LDFLAGS, "")
+  AC_SUBST(UMFPACK_CPPFLAGS, "")
+
+  # set variable for summary
+  with_umfpack="no"
+fi
+  
+# also tell automake
+AM_CONDITIONAL(UMFPACK, test x$HAVE_UMFPACK = x1)
+
+# reset old values
+LIBS="$ac_save_LIBS"
+CPPFLAGS="$ac_save_CPPFLAGS"
+LDFLAGS="$ac_save_LDFLAGS"
+
+  DUNE_ADD_SUMMARY_ENTRY([UMFPACK],[$with_umfpack])
+])