diff --git a/cmake/modules/AmdisMacros.cmake b/cmake/modules/AmdisMacros.cmake
index 8ae3c82b0955582c19de4adfd6c56eed5216bd45..b670bfcd309a3eb030325317e7b43ffa1b1c17e8 100644
--- a/cmake/modules/AmdisMacros.cmake
+++ b/cmake/modules/AmdisMacros.cmake
@@ -24,10 +24,14 @@ endif (NOT BACKEND)
 if (BACKEND STREQUAL "MTL" OR BACKEND STREQUAL "MTL4")
   find_package(MTL REQUIRED)
   set(HAVE_MTL TRUE)
-  if (MTL_FOUND)
-    message(STATUS "  Found MTL, version: ${MTL_VERSION}")
-    dune_register_package_flags(LIBRARIES MTL::MTL COMPILE_DEFINITIONS "ENABLE_MTL=1")
-  endif (MTL_FOUND)
+  message(STATUS "  Found MTL, version: ${MTL_VERSION}")
+  dune_register_package_flags(LIBRARIES MTL::MTL COMPILE_DEFINITIONS "ENABLE_MTL=1")
+
+  find_package(HYPRE)
+  if (HYPRE_FOUND)
+    set(HAVE_HYPRE TRUE)
+    dune_register_package_flags(LIBRARIES HYPRE::HYPRE COMPILE_DEFINITIONS "ENABLE_HYPRE=1")
+  endif(HYPRE_FOUND)
 elseif (BACKEND STREQUAL "EIGEN" OR BACKEND STREQUAL "EIGEN3")
   find_package(Eigen3 REQUIRED 3.3.5)
   set(HAVE_EIGEN TRUE)
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
index 6d866c15744a1740cbf0c02832a8ff3495953c7f..5474caf6870ee17a78f4d6204c5cf42c1d8ba0b0 100644
--- a/cmake/modules/CMakeLists.txt
+++ b/cmake/modules/CMakeLists.txt
@@ -2,6 +2,7 @@ install(FILES
     AddAmdisExecutable.cmake
     AmdisMacros.cmake
     AmdisCXXFeatures.cmake
+    FindHYPRE.cmake
     FindMTL.cmake
     FindPETSc.cmake
     PkgConfigLinkLibraries.cmake
diff --git a/cmake/modules/FindHYPRE.cmake b/cmake/modules/FindHYPRE.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..f3fbf34ad47106e00798e3397db8ba41e0add0ed
--- /dev/null
+++ b/cmake/modules/FindHYPRE.cmake
@@ -0,0 +1,75 @@
+# FindHYPRE.cmake
+#
+# Finds the HYPRE library
+#
+# This will define the following variables
+#
+#    HYPRE_FOUND
+#    HYPRE_INCLUDE_DIR
+#    HYPRE_LIBRARIES
+#
+# and the following imported targets
+#
+#     HYPRE::HYPRE
+#
+# Author: Simon Praetorius <simon.praetorius@tu-dresden.de>
+
+
+mark_as_advanced(HYPRE_FOUND HYPRE_INCLUDE_DIR HYPRE_LIBRARIES)
+
+find_path(HYPRE_INCLUDE_DIR HYPRE.h
+  PATHS
+    /opt/software/hypre
+    ${HYPRE_DIR} ${HYPRE_ROOT}
+    ENV HYPRE_DIR ENV HYPRE_ROOT
+    ENV EBROOTHYPRE
+  PATH_SUFFIXES
+    hypre include include/hypre
+  NO_DEFAULT_PATH)
+find_path(HYPRE_INCLUDE_DIR HYPRE.h
+  PATH_SUFFIXES hypre include include/hypre)
+
+find_library(HYPRE_LIBRARY HYPRE
+  PATHS
+    /opt/software/hypre
+    ${HYPRE_DIR} ${HYPRE_ROOT}
+    ENV HYPRE_DIR ENV HYPRE_ROOT
+    ENV EBROOTHYPRE
+  PATH_SUFFIXES
+    lib
+  NO_DEFAULT_PATH)
+find_library(HYPRE_LIBRARY HYPRE
+  PATH_SUFFIXES lib)
+
+if (HYPRE_LIBRARY)
+  set(HYPRE_LIBRARIES ${HYPRE_LIBRARY})
+  get_filename_component(HYPRE_LIBRARY_DIR ${HYPRE_LIBRARY} DIRECTORY)
+
+  foreach(_lib_name "HYPRE_FEI" "HYPRE_core")
+    find_library(_lib ${_lib_name} HINTS ${HYPRE_LIBRARY_DIR} NO_DEFAULT_PATH)
+    if (_lib)
+      list(APPEND HYPRE_LIBRARIES ${_lib})
+    endif (_lib)
+    unset(_lib)
+  endforeach()
+  unset(_lib_name)
+endif (HYPRE_LIBRARY)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(HYPRE
+  REQUIRED_VARS HYPRE_INCLUDE_DIR HYPRE_LIBRARY
+)
+
+# text for feature summary
+set_package_properties("HYPRE" PROPERTIES
+  DESCRIPTION "high performance preconditioners")
+
+
+if(HYPRE_FOUND AND NOT TARGET HYPRE::HYPRE)
+  add_library(HYPRE::HYPRE INTERFACE IMPORTED)
+
+  set_target_properties(HYPRE::HYPRE PROPERTIES
+    INTERFACE_INCLUDE_DIRECTORIES "${HYPRE_INCLUDE_DIR}"
+    INTERFACE_LINK_LIBRARIES "${HYPRE_LIBRARIES}"
+  )
+endif()
diff --git a/cmake/modules/FindMTL.cmake b/cmake/modules/FindMTL.cmake
index 8c20f0752d99a13cfde4541073c4c5619016b4f0..80a84429c1100d6a6d28d04d5a5aebe17bc413f3 100644
--- a/cmake/modules/FindMTL.cmake
+++ b/cmake/modules/FindMTL.cmake
@@ -18,16 +18,15 @@
 mark_as_advanced(MTL_FOUND MTL_COMPILE_DEFINITIONS MTL_INCLUDE_DIR)
 
 find_path(MTL_INCLUDE_DIR boost/numeric/mtl/mtl.hpp
-  HINTS
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/mtl4
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mtl4
-    ${MTL_DIR}/../../include
-    $ENV{MTL_DIR}/../../include
-    ENV EBROOTMTL
   PATHS
     /opt/software/mtl
     /opt/sources/mtl
     /opt/development/mtl
+    ${MTL_DIR} ${MTL_ROOT}
+    ENV MTL_DIR ENV MTL_ROOT
+    ENV EBROOTMTL
+  PATH_SUFFIXES
+    include
 )
 
 set(MTL_COMPILE_DEFINITIONS MTL_ASSERT_FOR_THROW=1)
@@ -40,6 +39,10 @@ find_package_handle_standard_args(MTL
   REQUIRED_VARS MTL_INCLUDE_DIR
 )
 
+# text for feature summary
+set_package_properties("MTL" PROPERTIES
+  DESCRIPTION "Matrix Template Library")
+
 if(MTL_FOUND AND NOT TARGET MTL::MTL)
   add_library(MTL::MTL INTERFACE IMPORTED)
 
@@ -48,8 +51,12 @@ if(MTL_FOUND AND NOT TARGET MTL::MTL)
     list(APPEND MTL_COMPILE_DEFINITIONS "MTL_HAS_UMFPACK")
   endif (SuiteSparse_FOUND)
 
+  find_package(HYPRE QUIET)
+  if (HYPRE_FOUND)
+    list(APPEND MTL_COMPILE_DEFINITIONS "MTL_HAS_HYPRE")
+  endif (HYPRE_FOUND)
+
   set_target_properties(MTL::MTL PROPERTIES
     INTERFACE_INCLUDE_DIRECTORIES "${MTL_INCLUDE_DIR}"
-    INTERFACE_COMPILE_DEFINITIONS "${MTL_COMPILE_DEFINITIONS}"
-  )
+    INTERFACE_COMPILE_DEFINITIONS "${MTL_COMPILE_DEFINITIONS}")
 endif()
diff --git a/config.h.cmake b/config.h.cmake
index ec1f0739d074008e846f16240807478bb9e0a836..9317b1e2b2a8e976ecb3ef4dd1e5123a714febe0 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -43,11 +43,14 @@
 /* Define to true if the MTL library is available */
 #cmakedefine HAVE_MTL 1
 
+/* Define to true if the HYPRE library is available */
+#cmakedefine HAVE_HYPRE ENABLE_HYPRE
+
 /* Define to true if the Eigen3 library is available */
 #cmakedefine HAVE_EIGEN 1
 
 /* Define to true if the PETSc library is available */
-#cmakedefine HAVE_PETSC ENABLE_PETSC
+#cmakedefine HAVE_PETSC 1
 
 /* some detected compiler features may be used in AMDiS */
 #cmakedefine AMDIS_HAS_CXX_FOLD_EXPRESSIONS 1
diff --git a/src/amdis/linearalgebra/mtl/CMakeLists.txt b/src/amdis/linearalgebra/mtl/CMakeLists.txt
index 1306877d8b3f4d0fcca5642dc4f6a459a3c68d23..8b79796a4bc8b8463ef0fad70e1a362783b82fd2 100644
--- a/src/amdis/linearalgebra/mtl/CMakeLists.txt
+++ b/src/amdis/linearalgebra/mtl/CMakeLists.txt
@@ -1,10 +1,12 @@
 install(FILES
     Constraints.hpp
+    HyprePrecon.hpp
     ITL_Preconditioner.hpp
     ITL_Solver.hpp
     KrylovRunner.hpp
     MatrixBackend.hpp
     Preconditioner.hpp
+    SolverPrecon.hpp
     Traits.hpp
     UmfpackRunner.hpp
     VectorBackend.hpp
diff --git a/src/amdis/linearalgebra/mtl/HyprePrecon.hpp b/src/amdis/linearalgebra/mtl/HyprePrecon.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb6935196b37201b75976a1bf7fd912ed9704067
--- /dev/null
+++ b/src/amdis/linearalgebra/mtl/HyprePrecon.hpp
@@ -0,0 +1,153 @@
+#pragma once
+
+#if HAVE_HYPRE
+
+#include <dune/common/unused.hh>
+#include <amdis/linearalgebra/mtl/itl/hypre.hpp>
+
+namespace AMDiS
+{
+  /// \brief Interface to the HYPRE BoomerAMG preconditioner [...]
+  /**
+   * Parameters provided by AMDiS:
+   *
+   * [PRECON]->cycle mode:
+   * 	1...V-cycle
+   *	2...W-cycle
+   *
+   * [PRECON]->interpolation type:
+   *  0...classical modified interpolation
+   *	1...LS interpolation (for use with GSMG)
+   * 	2...classical modified interpolation for hyperbolic PDEs
+   * 	3...direct interpolation (with separation of weights)
+   * 	4...multipass interpolation
+   * 	5...multipass interpolation (with separation of weights)
+   * 	6...extended+i interpolation
+   * 	7...extended+i (if no common C neighbor) interpolation
+   * 	8...standard interpolation
+   * 	9...standard interpolation (with separation of weights)
+   * 	10..classical block interpolation (for use with nodal systems version only)
+   * 	11..classical block interpolation (for use with nodal systems version only)
+   * 		with diagonalized diagonal blocks
+   * 	12..FF interpolation
+   * 	13..FF1 interpolation
+   * 	14..extended interpolation
+   *
+   *  [PRECON]->info:
+   * 	0...no printout (default)
+   * 	1...print setup information
+   * 	2...print solve information
+   * 	3...print both setup and solve information
+   *
+   *  [PRECON]->relax type:
+   * 	0...Jacobi
+   * 	1...Gauss-Seidel, sequential (very slow!)
+   * 	2...Gauss-Seidel, interior points in parallel, boundary sequential (slow!)
+   * 	3...hybrid Gauss-Seidel or SOR, forward solve
+   * 	4...hybrid Gauss-Seidel or SOR, backward solve
+   * 	5...hybrid chaotic Gauss-Seidel (works only with OpenMP)
+   * 	6...hybrid symmetric Gauss-Seidel or SSOR
+   * 	9...Gaussian elimination (only on coarsest level)
+   **/
+  template <class Traits>
+  class HyprePrecon
+      : public PreconditionerInterface<Traits>
+  {
+    using Self = HyprePrecon;
+    using Matrix = typename Traits::Mat;
+    using Vector = typename Traits::Vec;
+    using Super = PreconditionerInterface<Traits>;
+
+  public:
+    /// A creator to be used instead of the constructor.
+    struct Creator : CreatorInterfaceName<Super>
+    {
+      std::unique_ptr<Super> createWithString(std::string prefix) override
+      {
+        return std::make_unique<Self>(prefix);
+      }
+    };
+
+  public:
+    HyprePrecon(std::string const& prefix)
+    {
+      // read HYPRE parameters
+      int maxIter = 1, cycleMode = -1, interpolation = -1, relaxation = -1, info = 1;
+      Parameters::get(prefix + "->max iteration", maxIter);
+      Parameters::get(prefix + "->cycle mode", cycleMode);
+      Parameters::get(prefix + "->interpolation type", interpolation);
+      Parameters::get(prefix + "->relax type", relaxation);
+      Parameters::get(prefix + "->info", info);
+
+      config_.maxIter(maxIter);
+      config_.interpolationType(interpolation);
+      config_.relaxType(relaxation);
+      config_.cycle(cycleMode);
+      config_.printLevel(info);
+    }
+
+    /// Implementation of \ref PreconditionerBase::init()
+    void init(Matrix const& fullMatrix) override
+    {
+      hypreMatrix_.init(fullMatrix);
+      HYPRE_IJMatrixGetObject(hypreMatrix_, (void**)(&matrix_));
+      HYPRE_BoomerAMGCreate(&solver_);
+
+      // apply solver parameters
+      config_(solver_);
+
+      mtl::dense_vector<double> swap(1, 0.0);
+      mtl::HypreParVector x(swap);
+      HYPRE_BoomerAMGSetup(solver_, matrix_, x, x);
+
+      solverCreated_ = true;
+    }
+
+    /// Implementation of \ref PreconditionerInterface::exit()
+    void exit() override
+    {
+      if (solverCreated_)
+	      HYPRE_BoomerAMGDestroy(solver_);
+      solverCreated_ = false;
+    }
+
+    /// Implementation of \ref PreconditionerBase::solve()
+    void solve(Vector const& mtlB, Vector& mtlX) const override
+    {
+      assert(solverCreated_);
+      mtl::HypreParVector x(mtlB); // use b as initial guess
+      mtl::HypreParVector b(mtlB);
+
+      DUNE_UNUSED int error = HYPRE_BoomerAMGSolve(solver_, matrix_, b, x);
+      assert(error != 0);
+
+      // write output back to MTL vector
+      mtl::convert(x.getHypreVector(), mtlX);
+    }
+
+    /// Implementation of \ref PreconditionerBase::adjoint_solve()
+    void adjoint_solve(Vector const& mtlB, Vector& mtlX) const override
+    {
+      assert(solverCreated_);
+      mtl::HypreParVector x(mtlB); // use b as initial guess
+      mtl::HypreParVector b(mtlB);
+
+      DUNE_UNUSED int error = HYPRE_BoomerAMGSolveT(solver_, matrix_, b, x);
+      assert(error != 0);
+
+      // write output back to MTL vector
+      mtl::convert(x.getHypreVector(), mtlX);
+    }
+
+  private:
+    mtl::HypreMatrix hypreMatrix_;
+    HYPRE_ParCSRMatrix matrix_;
+    HYPRE_Solver solver_;
+
+    mtl::AMGConfigurator config_;
+    bool solverCreated_ = false;
+  };
+
+} // end namespace AMDiS
+
+#endif // HAVE_HYPRE
diff --git a/src/amdis/linearalgebra/mtl/ITL_Preconditioner.hpp b/src/amdis/linearalgebra/mtl/ITL_Preconditioner.hpp
index 687d708891e2193350293fa0b189f274616c5f38..1bb2a41312f86be043bb8902deb8cb6387407629 100644
--- a/src/amdis/linearalgebra/mtl/ITL_Preconditioner.hpp
+++ b/src/amdis/linearalgebra/mtl/ITL_Preconditioner.hpp
@@ -6,10 +6,15 @@
 #include <boost/numeric/itl/pc/ic_0.hpp>
 #include <boost/numeric/mtl/vector/assigner.hpp>
 
-#include <amdis/linearalgebra/mtl/itl/masslumping.hpp>
+#include <amdis/CreatorMap.hpp>
 #include <amdis/linearalgebra/mtl/Preconditioner.hpp>
+#include <amdis/linearalgebra/mtl/SolverPrecon.hpp>
 #include <amdis/linearalgebra/mtl/Traits.hpp>
-#include <amdis/CreatorMap.hpp>
+#include <amdis/linearalgebra/mtl/itl/masslumping.hpp>
+
+#if HAVE_HYPRE
+#include <amdis/linearalgebra/mtl/HyprePrecon.hpp>
+#endif
 
 namespace AMDiS
 {
@@ -73,6 +78,7 @@ namespace AMDiS
   template <class Matrix>
   using ICPreconditioner = itl::pc::ic_0<Matrix>;
 
+
   template <class Traits>
   class DefaultCreators< PreconditionerInterface<Traits> >
   {
@@ -107,20 +113,28 @@ namespace AMDiS
       Map::addCreator("identity", pc_id);
       Map::addCreator("no", pc_id);
 
+      auto pc_solver = new typename SolverPrecon<Traits>::Creator;
+      Map::addCreator("solver", pc_solver);
+
+#if HAVE_HYPRE
+      auto pc_hypre = new typename HyprePrecon<Traits>::Creator;
+      Map::addCreator("hypre", pc_hypre);
+#endif
+
       Map::addCreator("default", pc_id);
     }
   };
 
-  template <class Traits>
-  itl::pc::solver<PreconditionerInterface<Traits>, typename Traits::Vec, false>
-  solve(PreconditionerInterface<Traits> const& P, typename Traits::Vec const& vin)
+  template <class Traits, class Vector>
+  itl::pc::solver<PreconditionerInterface<Traits>, Vector, false>
+  solve(PreconditionerInterface<Traits> const& P, Vector const& vin)
   {
     return {P, vin};
   }
 
-  template <class Traits>
-  itl::pc::solver<PreconditionerInterface<Traits>, typename Traits::Vec, true>
-  adjoint_solve(PreconditionerInterface<Traits> const& P, typename Traits::Vec const& vin)
+  template <class Traits, class Vector>
+  itl::pc::solver<PreconditionerInterface<Traits>, Vector, true>
+  adjoint_solve(PreconditionerInterface<Traits> const& P, Vector const& vin)
   {
     return {P, vin};
   }
diff --git a/src/amdis/linearalgebra/mtl/ITL_Solver.hpp b/src/amdis/linearalgebra/mtl/ITL_Solver.hpp
index bc2360a6f047fda0d0b05bc5cba4a41d86fcc544..3aeae41e922182c8b8895e3acf1a7dba3ef82ec2 100644
--- a/src/amdis/linearalgebra/mtl/ITL_Solver.hpp
+++ b/src/amdis/linearalgebra/mtl/ITL_Solver.hpp
@@ -36,10 +36,10 @@ namespace AMDiS
   {
   public:
     explicit cg_solver_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::cg(A, x, b, l, r, iter);
+      return itl::cg(A, x, b, precon, iter);
     }
   };
 
@@ -56,10 +56,10 @@ namespace AMDiS
   {
   public:
     explicit cgs_solver_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const&, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::cgs(A, x, b, l, iter);
+      return itl::cgs(A, x, b, precon, iter);
     }
   };
 
@@ -76,10 +76,10 @@ namespace AMDiS
   {
   public:
     explicit bicg_solver_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const&, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::bicg(A, x, b, l, iter);
+      return itl::bicg(A, x, b, precon, iter);
     }
   };
 
@@ -96,10 +96,10 @@ namespace AMDiS
   {
   public:
     explicit bicgstab_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const&, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::bicgstab(A, x, b, l, iter);
+      return itl::bicgstab(A, x, b, precon, iter);
     }
   };
 
@@ -116,10 +116,10 @@ namespace AMDiS
   {
   public:
     explicit bicgstab2_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const&, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::bicgstab_2(A, x, b, l, iter);
+      return itl::bicgstab_2(A, x, b, precon, iter);
     }
   };
 
@@ -135,10 +135,11 @@ namespace AMDiS
   {
   public:
     explicit qmr_solver_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::qmr(A, x, b, l, r, iter);
+      itl::pc::identity<LinOp> id(A);
+      return itl::qmr(A, x, b, precon, id, iter);
     }
   };
 
@@ -149,16 +150,17 @@ namespace AMDiS
    * Quasi-Minimal Residual method \implements ITL_Solver
    *
    * Solves a linear system by the Transposed-Free Quasi-Minimal Residual method
-   * (TFQMR). Does not use preconditioning currently.
+   * (TFQMR).
    */
   class tfqmr_solver_type
   {
   public:
     explicit tfqmr_solver_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::tfqmr(A, x, b, l, r, iter);
+      itl::pc::identity<LinOp> id(A);
+      return itl::tfqmr(A, x, b, precon, id, iter);
     }
   };
 
@@ -179,10 +181,11 @@ namespace AMDiS
     {
       Parameters::get(name + "->ell", ell);
     }
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::bicgstab_ell(A, x, b, l, r, iter, ell);
+      itl::pc::identity<LinOp> id(A);
+      return itl::bicgstab_ell(A, x, b, precon, id, iter, ell);
     }
   };
 
@@ -205,17 +208,18 @@ namespace AMDiS
       Parameters::get(name + "->restart", restart);
       Parameters::get(name + "->orthogonalization", ortho);
     }
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
+      itl::pc::identity<LinOp> id(A);
       switch (ortho)
       {
       default:
       case GRAM_SCHMIDT:
-        return itl::gmres2(A, x, b, l, r, iter, restart);
+        return itl::gmres2(A, x, b, id, precon, iter, restart);
         break;
       case HOUSEHOLDER:
-        return itl::gmres_householder(A, x, b, l, iter, restart);
+        return itl::gmres_householder(A, x, b, precon, iter, restart);
         break;
       }
     }
@@ -240,6 +244,8 @@ namespace AMDiS
    * Peter Sonneveld and Martin B. van Gijzen, IDR(s): a family of simple and fast
    * algorithms for solving large nonsymmetric linear systems.
    * SIAM J. Sci. Comput. Vol. 31, No. 2, pp. 1035-1062 (2008). (copyright SIAM)
+   *
+   * NOTE: preconditioners are ignored.
    */
   class idr_s_type
   {
@@ -249,10 +255,11 @@ namespace AMDiS
     {
       Parameters::get(name + "->s", s);
     }
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const&, I& iter)
     {
-      return itl::idr_s(A, x, b, l, r, iter, s);
+      itl::pc::identity<LinOp> id(A);
+      return itl::idr_s(A, x, b, id, id, iter, s);
     }
   };
 
@@ -269,10 +276,10 @@ namespace AMDiS
   {
   public:
     explicit minres_solver_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::minres(A, x, b, l, r, iter);
+      return itl::minres(A, x, b, precon, iter);
     }
   };
 
@@ -295,10 +302,11 @@ namespace AMDiS
     {
       Parameters::get(name + "->restart", restart);
     }
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::gcr(A, x, b, l, r, iter, restart);
+      itl::pc::identity<LinOp> id(A);
+      return itl::gcr(A, x, b, id, precon, iter, restart);
     }
   };
 
@@ -322,17 +330,18 @@ namespace AMDiS
       Parameters::get(name + "->restart", restart);
       Parameters::get(name + "->orthogonalization", orthogonalization);
     }
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& r, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
+      itl::pc::identity<LinOp> id(A);
       switch (orthogonalization)
       {
       default:
       case GRAM_SCHMIDT:
-        return itl::fgmres(A, x, b, l, r, iter, restart);
+        return itl::fgmres(A, x, b, id, precon, iter, restart);
         break;
       case HOUSEHOLDER:
-        return itl::fgmres_householder(A, x, b, r, iter, restart);
+        return itl::fgmres_householder(A, x, b, precon, iter, restart);
         break;
       }
     }
@@ -357,10 +366,10 @@ namespace AMDiS
   {
   public:
     explicit preonly_type(std::string const& /*name*/) {}
-    template <class LinOp, class X, class B, class L, class R, class I>
-    int operator()(LinOp const& A, X& x, B const& b, L const& l, R const& /*r*/, I& iter)
+    template <class LinOp, class X, class B, class P, class I>
+    int operator()(LinOp const& A, X& x, B const& b, P const& precon, I& iter)
     {
-      return itl::preonly(A, x, b, l, iter);
+      return itl::preonly(A, x, b, precon, iter);
     }
   };
 
diff --git a/src/amdis/linearalgebra/mtl/KrylovRunner.hpp b/src/amdis/linearalgebra/mtl/KrylovRunner.hpp
index a17f1feb5ab9af5b100b1d032063f53a0fd844ea..3087971bc11c93c533a3999d3ede8554a624424d 100644
--- a/src/amdis/linearalgebra/mtl/KrylovRunner.hpp
+++ b/src/amdis/linearalgebra/mtl/KrylovRunner.hpp
@@ -29,81 +29,80 @@ namespace AMDiS
     using Vector = typename Traits::Vec;
     using Comm = typename Traits::Comm;
     using PreconBase = PreconditionerInterface<Traits>;
+    using FloatType = typename Traits::CoefficientType;
 
   public:
     /// Constructor.
     explicit KrylovRunner(std::string const& prefix)
       : itlSolver_(prefix)
+      , prefix_(prefix)
     {
-      initPrecon(prefix);
-
-      Parameters::get(prefix + "->max iteration", maxIter_);
-      Parameters::get(prefix + "->print cycle", printCycle_);
+      Parameters::get(prefix_ + "->absolute tolerance", aTol_);
+      Parameters::get(prefix_ + "->relative tolerance", rTol_);
+      Parameters::get(prefix_ + "->max iteration", maxIter_);
+      Parameters::get(prefix_ + "->print cycle", printCycle_);
     }
 
     /// Implementation of \ref RunnerInterface::init()
     void init(Matrix const& A, Comm& comm) override
     {
       DUNE_UNUSED_PARAMETER(comm);
-      L_->init(A);
-      R_->init(A);
+      initPrecon(prefix_);
+      P_->init(A);
     }
 
     /// Implementation of \ref RunnerInterface::exit()
     void exit() override
     {
-      L_->exit();
-      R_->exit();
+      P_->exit();
     }
 
     /// Implementation of \ref RunnerInterface::solve()
     int solve(Matrix const& A, Vector& x, Vector const& b, SolverInfo& solverInfo) override
     {
-      test_exit(bool(L_), "There is no left preconditioner");
-      test_exit(bool(R_), "There is no right preconditioner");
-
-      auto r = Vector(b);
-      if (two_norm(x) != 0)
-        r -= A * x;
+      test_exit(bool(P_), "There is no preconditioner");
 
       // print information about the solution process
-      using T = typename Dune::FieldTraits<typename Vector::value_type>::real_type;
-      itl::cyclic_iteration<T> iter(two_norm(r),
-        maxIter_, solverInfo.relTolerance(), solverInfo.absTolerance(), printCycle_);
+      itl::cyclic_iteration<FloatType> iter(two_norm(b - A*x),
+        maxIter_, rTol_, aTol_, printCycle_);
       iter.set_quite(solverInfo.info() == 0);
       iter.suppress_resume(solverInfo.info() == 0);
 
-      int error = itlSolver_(A, x, b, *L_, *R_, iter);
+      int error = itlSolver_(A, x, b, *P_, iter);
       solverInfo.setAbsResidual(iter.resid());
       solverInfo.setRelResidual(iter.relresid());
 
       return error;
     }
 
-  private:
+  protected:
     /// Create left/right preconditioners from parameters given in the init-file
     void initPrecon(std::string const& prefix)
     {
       // Creator for the left preconditioner
-      std::string leftPreconName = "", rightPreconName = "";
-      Parameters::get(prefix + "->left precon", leftPreconName);
-      Parameters::get(prefix + "->right precon", rightPreconName);
-
-      auto leftCreator
-        = CreatorMap<PreconBase>::getCreator(leftPreconName, prefix + "->left precon");
-      auto rightCreator
-        = CreatorMap<PreconBase>::getCreator(rightPreconName, prefix + "->right precon");
+      std::string preconName = "default";
+      Parameters::get(prefix + "->precon", preconName);
 
-      L_ = leftCreator->create();
-      R_ = rightCreator->create();
+      auto creator
+        = named(CreatorMap<PreconBase>::getCreator(preconName, prefix + "->precon"));
+      P_ = creator->createWithString(prefix + "->precon");
     }
 
   private:
     /// The itl solver object that performes the actual solve
     ITLSolver itlSolver_;
 
-    /// Pointer to the left and right preconditioner
-    std::shared_ptr<PreconBase> L_, R_;
+    /// The parameter prefix
+    std::string prefix_;
+
+    /// Pointer to the left/right preconditioner
+    std::shared_ptr<PreconBase> P_;
+
+    /// Absolute solver tolerance ||b - A*x|| < aTol
+    FloatType aTol_ = 0;
+
+    /// Relative solver tolerance ||b - A*x||/||b - A*x0|| < rTol
+    FloatType rTol_ = 1.e-6;
 
     /// The maximal number of iterations
     std::size_t maxIter_ = 1000;
diff --git a/src/amdis/linearalgebra/mtl/Preconditioner.hpp b/src/amdis/linearalgebra/mtl/Preconditioner.hpp
index f8bd006fe559c67f128e12a238c07d8e868e90bd..906b300f0d9b675b395f0df22eb1165ff7cf6fe0 100644
--- a/src/amdis/linearalgebra/mtl/Preconditioner.hpp
+++ b/src/amdis/linearalgebra/mtl/Preconditioner.hpp
@@ -20,9 +20,9 @@ namespace AMDiS
 
   public:
     /// A creator to be used instead of the constructor.
-    struct Creator : CreatorInterface<Super>
+    struct Creator : CreatorInterfaceName<Super>
     {
-      std::unique_ptr<Super> create() override
+      std::unique_ptr<Super> createWithString(std::string) override
       {
         return std::make_unique<Self>();
       }
@@ -42,17 +42,17 @@ namespace AMDiS
     }
 
     /// Implementation of \ref PreconditionerBase::solve()
-    void solve(Vector const& vin, Vector& vout) const override
+    void solve(Vector const& x, Vector& y) const override
     {
       test_exit_dbg(bool(precon_), "No preconditioner initialized!");
-      precon_->solve(vin, vout);
+      precon_->solve(x, y);
     }
 
     /// Implementation of \ref PreconditionerBase::adjoint_solve()
-    void adjoint_solve(Vector const& vin, Vector& vout) const override
+    void adjoint_solve(Vector const& x, Vector& y) const override
     {
       test_exit_dbg(bool(precon_), "No preconditioner initialized!");
-      precon_->adjoint_solve(vin, vout);
+      precon_->adjoint_solve(x, y);
     }
 
   private:
diff --git a/src/amdis/linearalgebra/mtl/SolverPrecon.hpp b/src/amdis/linearalgebra/mtl/SolverPrecon.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..68b6fefadd9be890d707f5d4257507d9d6f6c558
--- /dev/null
+++ b/src/amdis/linearalgebra/mtl/SolverPrecon.hpp
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <memory>
+
+#include <amdis/CreatorMap.hpp>
+#include <amdis/Initfile.hpp>
+#include <amdis/Output.hpp>
+#include <amdis/linearalgebra/LinearSolverInterface.hpp>
+#include <amdis/linearalgebra/PreconditionerInterface.hpp>
+
+namespace AMDiS
+{
+  /**
+   * \ingroup Solver
+   *
+   * \brief Use a LinearSolver as Preconditioner
+   */
+  template <class Traits>
+  class SolverPrecon
+      : public PreconditionerInterface<Traits>
+  {
+    using Self = SolverPrecon;
+    using Matrix = typename Traits::Mat;
+    using Vector = typename Traits::Vec;
+    using Super = PreconditionerInterface<Traits>;
+
+  public:
+    /// A creator to be used instead of the constructor.
+    struct Creator : CreatorInterfaceName<Super>
+    {
+      std::unique_ptr<Super> createWithString(std::string prefix) override
+      {
+        return std::make_unique<Self>(std::move(prefix));
+      }
+    };
+
+  public:
+    SolverPrecon(std::string const& prefix)
+      : solverInfo_(prefix + "->solver")
+      , comm_(Environment::comm())
+    {
+      std::string solverName = "default";
+      Parameters::get(prefix + "->solver", solverName);
+
+      auto solverCreator = named(CreatorMap<LinearSolverInterface<Traits>>::getCreator(solverName, prefix + "->solver"));
+      solver_ = solverCreator->createWithString(prefix + "->solver");
+    }
+
+    /// Implementation of \ref PreconditionerBase::init()
+    void init(Matrix const& fullMatrix) override
+    {
+      matrix_ = &fullMatrix;
+    }
+
+    /// Implementation of \ref PreconditionerInterface::exit()
+    void exit() override
+    {
+      matrix_ = nullptr;
+    }
+
+    /// Implementation of \ref PreconditionerBase::solve()
+    void solve(Vector const& x, Vector& y) const override
+    {
+      test_exit_dbg(bool(solver_), "No solver initialized!");
+      test_exit_dbg(bool(matrix_), "No matrix initialized!");
+
+      y.checked_change_resource(x);
+      test_exit(size(y) == num_cols(*matrix_), "incompatible size");
+      solver_->solve(*matrix_, y, x, comm_, solverInfo_);
+    }
+
+    /// Implementation of \ref PreconditionerBase::adjoint_solve()
+    void adjoint_solve(Vector const& x, Vector& y) const override
+    {
+      error_exit("Not Implemented.");
+      test_exit_dbg(bool(solver_), "No solver initialized!");
+      test_exit_dbg(bool(matrix_), "No matrix initialized!");
+
+      y.checked_change_resource(x);
+      test_exit(size(y) == num_rows(*matrix_), "incompatible size");
+      // solver_->adjointSolve(*matrix_, y, x, comm_, solverInfo_);
+    }
+
+  private:
+    mutable SolverInfo solverInfo_;
+    mutable typename Traits::Comm comm_;
+
+    std::shared_ptr<LinearSolverInterface<Traits>> solver_;
+    Matrix const* matrix_ = nullptr;
+  };
+
+} // namespace AMDiS
diff --git a/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp b/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp
index 643cfbaf865402ec4b316768547ac191c1ccc4c5..4703b6ca4670888e87d5998c1705635657955d20 100644
--- a/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp
+++ b/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp
@@ -72,11 +72,7 @@ namespace AMDiS
         umfpack_error_exit("solve", e.code);
       }
 
-      auto r = Vector(b);
-      if (two_norm(x) != 0)
-        r -= A * x;
-
-      solverInfo.setAbsResidual(two_norm(r));
+      solverInfo.setAbsResidual(two_norm(b - A*x));
       solverInfo.setError(code);
 
       return code;
diff --git a/src/amdis/linearalgebra/mtl/itl/CMakeLists.txt b/src/amdis/linearalgebra/mtl/itl/CMakeLists.txt
index ffe212d96d8944dd67b60cd142df139215a5cdac..4df82e7b979899cc047b0bbe00d9fa3883efc111 100644
--- a/src/amdis/linearalgebra/mtl/itl/CMakeLists.txt
+++ b/src/amdis/linearalgebra/mtl/itl/CMakeLists.txt
@@ -1,5 +1,4 @@
 install(FILES
-  block_diagonal.hpp
   details.hpp
   fgmres_householder.hpp
   fgmres.hpp
@@ -10,5 +9,4 @@ install(FILES
   masslumping.hpp
   minres.hpp
   preonly.hpp
-  umfpack2_solve.hpp
 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/linearalgebra/mtl/itl)
diff --git a/src/amdis/linearalgebra/mtl/itl/block_diagonal.hpp b/src/amdis/linearalgebra/mtl/itl/block_diagonal.hpp
deleted file mode 100644
index b295a389e6e8a5dc83ecc3ea125a6675efd64613..0000000000000000000000000000000000000000
--- a/src/amdis/linearalgebra/mtl/itl/block_diagonal.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-#include <boost/numeric/itl/pc/diagonal.hpp>
-
-#include <amdis/linearalgebra/mtl/BlockMTLMatrix.hpp>
-
-namespace itl
-{
-  namespace pc
-  {
-    /// Diagonal Preconditioner
-    template <class MTLMatrix, std::size_t _N, std::size_t _M, class Value>
-    class diagonal<AMDiS::BlockMTLMatrix<MTLMatrix, _N, _M>, Value>
-    {
-      using Self       = diagonal;
-      using MatrixType = AMDiS::BlockMTLMatrix<MTLMatrix, _N, _M>;
-
-    public:
-      using value_type = Value;
-      using size_type  = typename mtl::Collection<MatrixType>::size_type;
-
-      /// Constructor takes matrix reference
-      explicit diagonal(const MatrixType& A) : inv_diag(num_rows(A))
-      {
-        MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square());
-        using math::reciprocal;
-
-        std::array<mtl::irange, _N> r_rows;
-        A.getRowRanges(r_rows);
-
-        for (std::size_t i = 0; i < _N; i++)
-          inv_diag[r_rows[i]] = mtl::mat::diagonal(A[i][i]);
-
-        for (size_type i = 0; i < num_rows(A); ++i)
-          inv_diag[i]= reciprocal(inv_diag[i]);
-      }
-
-      /// Member function solve, better use free function solve
-      template <typename Vector>
-      Vector solve(const Vector& x) const
-      {
-        Vector y(resource(x));
-        solve(x, y);
-        return y;
-      }
-
-      template <typename VectorIn, typename VectorOut>
-      void solve(const VectorIn& x, VectorOut& y) const
-      {
-        y.checked_change_resource(x);
-        MTL_THROW_IF(size(x) != size(inv_diag), mtl::incompatible_size());
-        for (size_type i= 0; i < size(inv_diag); ++i)
-          y[i]= inv_diag[i] * x[i];
-      }
-
-      /// Member function for solving adjoint problem, better use free function adjoint_solve
-      template <typename Vector>
-      Vector adjoint_solve(const Vector& x) const
-      {
-        Vector y(resource(x));
-        adjoint_solve(x, y);
-        return y;
-      }
-
-      template <typename VectorIn, typename VectorOut>
-      void adjoint_solve(const VectorIn& x, VectorOut& y) const
-      {
-        using mtl::conj;
-        y.checked_change_resource(x);
-        MTL_THROW_IF(size(x) != size(inv_diag), mtl::incompatible_size());
-        for (size_type i= 0; i < size(inv_diag); ++i)
-          y[i]= conj(inv_diag[i]) * x[i];
-      }
-
-    protected:
-      mtl::vec::dense_vector<value_type>    inv_diag;
-    };
-
-
-  }
-} // namespace itl::pc
diff --git a/src/amdis/linearalgebra/mtl/itl/details.hpp b/src/amdis/linearalgebra/mtl/itl/details.hpp
index 310b19fcdf518aa7dedcbe5f28e8185fe13cfb16..878ecada7320f7256bb98dc6cc767c3806e04d7e 100644
--- a/src/amdis/linearalgebra/mtl/itl/details.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/details.hpp
@@ -1,37 +1,11 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius
-
-
-#ifndef ITL_DETAIL_INCLUDE
-#define ITL_DETAIL_INCLUDE
+#pragma once
 
 #include <boost/math/special_functions/sign.hpp>
 
 namespace itl
 {
-
   namespace details
   {
-
     /// Compute the Givens rotation matrix parameters for a and b.
     //     template<typename T>
     //     void rotmat(const T& a, const T& b , T& c, T& s)
@@ -40,12 +14,12 @@ namespace itl
     //
     //       const T zero = math::zero(T());
     //       if (a == zero) {
-    // 	c = 0.0;
-    // 	s = 1.0;
+    // 	        c = 0.0;
+    // 	        s = 1.0;
     //       } else {
-    // 	double temp = abs(a) / sqrt( conj(a)*a + conj(b)*b );
-    // 	c = temp;
-    // 	s = temp * (b / a);
+    // 	        double temp = abs(a) / sqrt( conj(a)*a + conj(b)*b );
+    // 	        c = temp;
+    // 	        s = temp * (b / a);
     //       }
     //     }
 
@@ -72,7 +46,6 @@ namespace itl
         s = temp * c;
       }
     }
-  }
-}
 
-#endif // ITL_DETAIL_INCLUDE
+  } // end namespace details
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/fgmres.hpp b/src/amdis/linearalgebra/mtl/itl/fgmres.hpp
index 21e4216b4b43060d870edc37107dd68587756a3c..ebf3a37c836ff6325258685fde89c8ab56238d5e 100644
--- a/src/amdis/linearalgebra/mtl/itl/fgmres.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/fgmres.hpp
@@ -1,30 +1,7 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius
-
-
-#ifndef ITL_FGMRES_INCLUDE
-#define ITL_FGMRES_INCLUDE
+#pragma once
 
 #include <algorithm>
+
 #include <boost/numeric/mtl/concept/collection.hpp>
 #include <boost/numeric/mtl/vector/dense_vector.hpp>
 #include <boost/numeric/mtl/matrix/dense2D.hpp>
@@ -38,7 +15,6 @@
 
 namespace itl
 {
-
   /// Flexible Generalized Minimal Residual method (without restart)
   /// Cite: Youcef Saad, A Flexible Inner-Outer Preconditioned GMRES Algorithm, 1993
   /** It computes at most kmax_in iterations (or size(x) depending on what is smaller)
@@ -193,10 +169,4 @@ namespace itl
     return iter;
   }
 
-
-
-} // namespace itl
-
-#endif // ITL_FGMRES_INCLUDE
-
-
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp b/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp
index 2f066ee7472f46b3f0e32b010cee9be92dd9a6a6..92f33adff72e9f97c2e6ddaf823d43ac660dbf5e 100644
--- a/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp
@@ -1,30 +1,7 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius (adopted from previous implementation)
-
-
-#ifndef ITL_FGMRES_HOUSEHOLDER_INCLUDE
-#define ITL_FGMRES_HOUSEHOLDER_INCLUDE
+#pragma once
 
 #include <algorithm>
+
 #include <boost/numeric/mtl/concept/collection.hpp>
 #include <boost/numeric/mtl/vector/dense_vector.hpp>
 #include <boost/numeric/mtl/matrix/dense2D.hpp>
@@ -38,7 +15,6 @@
 
 namespace itl
 {
-
   /// Flexible Generalized Minimal Residual method (without restart) using householder othogonalization
   /** It computes at most kmax_in iterations (or size(x) depending on what is smaller)
       regardless on whether the termination criterion is reached or not.   **/
@@ -207,10 +183,4 @@ namespace itl
     return iter;
   }
 
-
-
-} // namespace itl
-
-#endif // ITL_FGMRES_HOUSEHOLDER_INCLUDE
-
-
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/gcr.hpp b/src/amdis/linearalgebra/mtl/itl/gcr.hpp
index 4e56b148979ed7310270a48930cd0bbe4863ae2d..dccecde44d0410de2f1569e103008c3a25749f58 100644
--- a/src/amdis/linearalgebra/mtl/itl/gcr.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/gcr.hpp
@@ -1,34 +1,9 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius
-
-
-#ifndef ITL_GCR_INCLUDE
-#define ITL_GCR_INCLUDE
+#pragma once
 
 #include <boost/numeric/mtl/concept/collection.hpp>
 
 namespace itl
 {
-
   template <typename Matrix, typename Vector, typename Preconditioner, typename Iteration>
   int gcr_full(const Matrix& A, Vector& x, const Vector& b, const Preconditioner& P, Iteration& iter)
   {
@@ -117,7 +92,5 @@ Cite:
 
     return iter;
   }
-} // namespace itl;
-
-#endif // ITL_GMR_INCLUDE
 
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/gmres2.hpp b/src/amdis/linearalgebra/mtl/itl/gmres2.hpp
index c65c7afe97c7dabd7393d48ad365b4dba2ea09bd..4ecbe564f444475e4562d6e78f5f18ba0ad821d1 100644
--- a/src/amdis/linearalgebra/mtl/itl/gmres2.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/gmres2.hpp
@@ -1,30 +1,7 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius (adopted from previous implementation)
-
-
-#ifndef ITL_GMRES2_INCLUDE
-#define ITL_GMRES2_INCLUDE
+#pragma once
 
 #include <algorithm>
+
 #include <boost/numeric/mtl/concept/collection.hpp>
 #include <boost/numeric/mtl/vector/dense_vector.hpp>
 #include <boost/numeric/mtl/matrix/dense2D.hpp>
@@ -38,7 +15,6 @@
 
 namespace itl
 {
-
   /// Generalized Minimal Residual method (without restart)
   /** It computes at most kmax_in iterations (or size(x) depending on what is smaller)
       regardless on whether the termination criterion is reached or not.   **/
@@ -196,10 +172,4 @@ namespace itl
     return iter;
   }
 
-
-
-} // namespace itl
-
-#endif // ITL_GMRES2_INCLUDE
-
-
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp b/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp
index eea759692e35db89045145db006892faef69998a..b2565ca32103ad3477736563921a4405b735d049 100644
--- a/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp
@@ -1,30 +1,7 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius (adopted from previous implementation)
-
-
-#ifndef ITL_GMRES_HOUSEHOLDER_INCLUDE
-#define ITL_GMRES_HOUSEHOLDER_INCLUDE
+#pragma once
 
 #include <algorithm>
+
 #include <boost/numeric/mtl/concept/collection.hpp>
 #include <boost/numeric/mtl/vector/dense_vector.hpp>
 #include <boost/numeric/mtl/matrix/dense2D.hpp>
@@ -38,7 +15,6 @@
 
 namespace itl
 {
-
   /// Generalized Minimal Residual method (without restart) using householder othogonalization.
   /** It computes at most kmax_in iterations (or size(x) depending on what is smaller)
       regardless on whether the termination criterion is reached or not.   **/
@@ -212,10 +188,4 @@ namespace itl
     return iter;
   }
 
-
-
-} // namespace itl
-
-#endif // ITL_GMRES_HOUSEHOLDER_INCLUDE
-
-
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/hypre.hpp b/src/amdis/linearalgebra/mtl/itl/hypre.hpp
index b877658206fd6482e3d23cd8191ec0310e99123c..0c4540708dda77e139552147051abeca23908d13 100644
--- a/src/amdis/linearalgebra/mtl/itl/hypre.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/hypre.hpp
@@ -1,38 +1,13 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
+#pragma once
 
-// Written by Andreas Naumann
+#if MTL_HAS_HYPRE && HAVE_MPI
 
-
-#ifndef AMDIS_HYPRE_SOLVER_HPP
-#define AMDIS_HYPRE_SOLVER_HPP
-
-#ifdef MTL_HAS_HYPRE
-
-#include "mpi.h"
-#include "HYPRE.h"
-#include "HYPRE_parcsr_ls.h"
+#include <mpi.h>
+#include <HYPRE.h>
+#include <HYPRE_parcsr_ls.h>
 
 namespace mtl
 {
-
   class HypreMatrix
   {
   public:
@@ -278,8 +253,6 @@ namespace mtl
     int _maxIter;
   };
 
-} //namespace mtl
+} // end namespace mtl
 
 #endif // MTL_HAS_HYPRE
-
-#endif // HYPRE_SOLVER_HPP
diff --git a/src/amdis/linearalgebra/mtl/itl/masslumping.hpp b/src/amdis/linearalgebra/mtl/itl/masslumping.hpp
index 26d6b684adfbc2013db1bae540108b9c360ad7d5..3754cc87a3bc56f7d17cceacb40e7aa54f251fd0 100644
--- a/src/amdis/linearalgebra/mtl/itl/masslumping.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/masslumping.hpp
@@ -1,17 +1,4 @@
-// Software License for MTL
-//
-// Copyright (c) 2007 The Trustees of Indiana University.
-//               2008 Dresden University of Technology and the Trustees of Indiana University.
-//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
-// All rights reserved.
-// Authors: Peter Gottschling and Andrew Lumsdaine
-//
-// This file is part of the Matrix Template Library
-//
-// See also license.mtl.txt in the distribution.
-
-#ifndef ITL_PC_MASSLUMPING_INCLUDE
-#define ITL_PC_MASSLUMPING_INCLUDE
+#pragma once
 
 #include <boost/numeric/linear_algebra/inverse.hpp>
 
@@ -28,7 +15,6 @@ namespace itl
 {
   namespace pc
   {
-
     /// Diagonal Preconditioner
     template <typename Matrix, typename Value= typename mtl::Collection<Matrix>::value_type>
     class masslumping
@@ -41,7 +27,6 @@ namespace itl
       /// Constructor takes matrix reference
       explicit masslumping(const Matrix& A) : inv_diag(num_rows(A))
       {
-        // 	mtl::vampir_trace<5050> tracer;
         MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square());
         using namespace mtl;
         using namespace mtl::tag;
@@ -127,8 +112,5 @@ namespace itl
       return solver<masslumping<Matrix>, Vector, true>(P, x);
     }
 
-
-  }
-} // namespace itl::pc
-
-#endif // ITL_PC_MASSLUMPING_INCLUDE
+  } // end namespace pc
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/minres.hpp b/src/amdis/linearalgebra/mtl/itl/minres.hpp
index 1c1319eea3cfbf7a878f72e66ea8f3ec5a56e382..8d18154117732989dbe22ba2851e946a91e5b76d 100644
--- a/src/amdis/linearalgebra/mtl/itl/minres.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/minres.hpp
@@ -1,55 +1,28 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Thomas Witkowski
-
-
-#ifndef AMDIS_ITL_MINRES_INCLUDE
-#define AMDIS_ITL_MINRES_INCLUDE
+#pragma once
 
 #include <boost/numeric/mtl/concept/collection.hpp>
 
 namespace itl
 {
-
   /// Minimal Residual method
   template <typename Matrix, typename Vector,
-            typename LeftPreconditioner, typename RightPreconditioner,
-            typename Iteration>
+            typename LeftPreconditioner, typename Iteration>
   int minres(const Matrix& A, Vector& x, const Vector& b,
-             const LeftPreconditioner& L, const RightPreconditioner& /*R*/,
-             Iteration& iter)
+             const LeftPreconditioner& P, Iteration& iter)
   {
-    using std::abs;
+    using std::abs; using std::sqrt;
     using math::reciprocal;
     typedef typename mtl::Collection<Vector>::value_type Scalar;
 
     if (size(b) == 0)
       throw mtl::logic_error("empty rhs vector");
 
-    Scalar                zero= math::zero(b[0]), one= math::one(b[0]);
-    Vector v0(size(x), zero), v1(b - A * x), v2(v1), z1(solve(L, v1)), z2(size(x), zero);
+    Scalar zero= math::zero(b[0]), one= math::one(b[0]);
+    Vector v0(size(x), zero), v1(b - A * x), v2(v1), z1(solve(P, v1)), z2(size(x), zero);
     Vector w0(size(x), zero), w1(size(x), zero), w2(size(x), zero);
 
     Scalar s0(zero), s1(zero), c0(one), c1(one), gamma0(one);
-    Scalar gamma1(sqrt(dot(z1, v1))), gamma2(zero), eta(gamma1);
+    Scalar gamma1(sqrt(abs(dot(z1, v1)))), gamma2(zero), eta(gamma1);
     Scalar sigma1(one), alpha0(zero), alpha1(zero), alpha2(zero), alpha3(zero);
 
     while (!iter.finished(abs(eta)))
@@ -59,9 +32,9 @@ namespace itl
       sigma1 = dot(v2, z1);
       v2 += -(sigma1 / gamma1) * v1 - (gamma1 / gamma0) * v0;
 
-      z2 = solve(L, v2);
+      z2 = solve(P, v2);
 
-      gamma2 = sqrt(dot(z2, v2));
+      gamma2 = sqrt(abs(dot(z2, v2)));
       alpha0 = c1 * sigma1 - c0 * s1 * gamma1;
       alpha1 = sqrt(alpha0 * alpha0 + gamma2 * gamma2);
       alpha2 = s1 * sigma1 + c0 * c1 * gamma1;
@@ -93,6 +66,4 @@ namespace itl
     return iter;
   }
 
-} // namespace itl;
-
-#endif // AMDIS_ITL_MINRES_INCLUDE
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/preonly.hpp b/src/amdis/linearalgebra/mtl/itl/preonly.hpp
index 98f1b6c56d9ac113c3b74598e7e0b5305eb3c2f0..0a926f1bd5fe8a535e31eef3ae1b68106458e0f2 100644
--- a/src/amdis/linearalgebra/mtl/itl/preonly.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/preonly.hpp
@@ -1,40 +1,15 @@
-/******************************************************************************
- *
- * AMDiS - Adaptive multidimensional simulations
- *
- * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
- * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
- *
- * Authors:
- * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- * This file is part of AMDiS
- *
- * See also license.opensource.txt in the distribution.
- *
- ******************************************************************************/
-
-// Written by Simon Praetorius
-
-
-#ifndef ITL_PREONLY_INCLUDE
-#define ITL_PREONLY_INCLUDE
+#pragma once
 
+#include <cassert>
 #include <boost/numeric/mtl/concept/collection.hpp>
 
 namespace itl
 {
-
   /// Solver that simply applies a preconditioner to the rhs vector
   template <typename Matrix, typename Vector, typename Preconditioner, typename Iteration>
   int preonly(const Matrix& A, Vector& x, const Vector& b, const Preconditioner& P, Iteration& iter)
   {
-    if (size(b) == 0)
-      throw mtl::logic_error("empty rhs vector");
+    assert(size(b) != 0);
 
     typedef typename mtl::Collection<Vector>::value_type Scalar;
 
@@ -50,7 +25,4 @@ namespace itl
     return iter;
   }
 
-} // namespace itl
-
-#endif // ITL_PREONLY_INCLUDE
-
+} // end namespace itl
diff --git a/src/amdis/linearalgebra/mtl/itl/umfpack2_solve.hpp b/src/amdis/linearalgebra/mtl/itl/umfpack2_solve.hpp
deleted file mode 100644
index 876bb4edc0a696a77800525a02d9cb66e5efbfc0..0000000000000000000000000000000000000000
--- a/src/amdis/linearalgebra/mtl/itl/umfpack2_solve.hpp
+++ /dev/null
@@ -1,637 +0,0 @@
-// Software License for MTL
-//
-// Copyright (c) 2007 The Trustees of Indiana University.
-//               2008 Dresden University of Technology and the Trustees of Indiana University.
-//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
-// All rights reserved.
-// Authors: Peter Gottschling and Andrew Lumsdaine
-//
-// This file is part of the Matrix Template Library
-//
-// See also license.mtl.txt in the distribution.
-
-#ifndef MTL_MATRIX_UMFPACK2_SOLVE_INCLUDE
-#define MTL_MATRIX_UMFPACK2_SOLVE_INCLUDE
-
-#ifdef MTL_HAS_UMFPACK
-
-#include <iostream>
-
-
-#include <cassert>
-#include <algorithm>
-#include <boost/mpl/bool.hpp>
-#include <boost/numeric/mtl/matrix/compressed2D.hpp>
-#include <boost/numeric/mtl/matrix/parameter.hpp>
-#include <boost/numeric/mtl/concept/collection.hpp>
-#include <boost/numeric/mtl/utility/exception.hpp>
-#include <boost/numeric/mtl/utility/make_copy_or_reference.hpp>
-#include <boost/numeric/mtl/operation/merge_complex_vector.hpp>
-#include <boost/numeric/mtl/operation/split_complex_vector.hpp>
-#include <boost/numeric/mtl/interface/vpt.hpp>
-
-extern "C" {
-#  include <umfpack.h>
-}
-
-namespace mtl
-{
-  namespace mat
-  {
-
-    /// Namespace for Umfpack solver
-    namespace umfpack
-    {
-
-      // conversion for value_type needed if not double or complex<double> (where possible)
-      template <typename Value> struct value         	    {};
-      template<> struct value<long double>
-      {
-        typedef double               type;
-      };
-      template<> struct value<double>
-      {
-        typedef double               type;
-      };
-      template<> struct value<float>
-      {
-        typedef double               type;
-      };
-      template<> struct value<std::complex<long double>>
-      {
-        typedef std::complex<double> type;
-      };
-      template<> struct value<std::complex<double>>
-      {
-        typedef std::complex<double> type;
-      };
-      template<> struct value<std::complex<float>>
-      {
-        typedef std::complex<double> type;
-      };
-
-      template <typename Value> struct use_long
-      {
-        static const bool value= sizeof(Value) > sizeof(int);
-      };
-
-      template <bool Larger> struct index_aux
-      {
-        typedef int     type;
-      };
-#if defined(UF_long)
-      template<> struct index_aux<true>
-      {
-        typedef UF_long type;
-      };
-#elif defined(SuiteSparse_long)
-      template<> struct index_aux<true>
-      {
-        typedef SuiteSparse_long type;
-      };
-#else
-      template<> struct index_aux<true>
-      {
-        typedef long type;
-      };
-#endif
-
-      template <typename Value> struct index
-        : index_aux<use_long<Value>::value> {};
-
-      template <typename Matrix, typename Value, typename Orientation>
-      struct matrix_copy {};
-
-      // If arbitrary compressed matrix -> copy
-      template <typename Value, typename Parameters, typename Orientation>
-      struct matrix_copy<compressed2D<Value, Parameters>, Value, Orientation>
-      {
-        typedef typename value<Value>::type                      value_type;
-        typedef compressed2D<value_type, parameters<col_major>> matrix_type;
-        typedef compressed2D<Value, Parameters>                  in_matrix_type;
-
-        matrix_copy(const in_matrix_type& A) : matrix(A) {}
-        matrix_type matrix;
-      };
-
-      struct error : public domain_error
-      {
-        error(const char* s, int code) : domain_error(s), code(code) {}
-        int code;
-      };
-
-      inline void check(int res, const char* s)
-      {
-        MTL_THROW_IF(res != UMFPACK_OK, error(s, res));
-      }
-
-      /// Class for repeated Umfpack solutions
-      /** Keeps symbolic and numeric preprocessing. Numeric part can be updated.
-          Only defined for compressed2D<double> and compressed2D<complex<double> >. **/
-      template <typename T>
-      class solver
-      {
-      public:
-        /// Constructor referring to matrix \p A (not changed) and optionally Umfpack's strategy and alloc_init (look for the specializations)
-        // \ref solver<compressed2D<double, Parameters> > and \ref solver<compressed2D<std::complex<double>, Parameters> >)
-        explicit solver(const T& A) {}
-
-        /// Update numeric part, for matrices that kept the sparsity and changed the values
-        void update_numeric() {}
-
-        /// Update symbolic and numeric part
-        void update() {}
-
-        /// Solve system A*x == b with matrix passed in constructor
-        /** Please note that the order of b and x is different than in solve() !!! **/
-        template <typename VectorX, typename VectorB>
-        int operator()(VectorX& x, const VectorB& b) const
-        {
-          return 0;
-        }
-
-        /// Solve system A*x == b with matrix passed in constructor
-        /** Please note that the order of b and x is different than in operator() !!! **/
-        template <typename VectorB, typename VectorX>
-        int operator()(const VectorB& b, VectorX& x) const
-        {
-          return 0;
-        }
-      };
-
-      /// Speciatization of solver for \ref matrix::compressed2D with double values
-      template <typename Parameters>
-      class solver<compressed2D<double, Parameters>>
-      {
-        typedef double                                    value_type;
-        typedef compressed2D<value_type, Parameters>      matrix_type;
-        typedef typename matrix_type::size_type           size_type;
-        typedef typename index<size_type>::type           index_type;
-
-        static const bool copy_indices= sizeof(index_type) != sizeof(size_type),
-                          long_indices= use_long<size_type>::value;
-        typedef boost::mpl::bool_<long_indices>           blong;
-        typedef boost::mpl::true_                         true_;
-        typedef boost::mpl::false_                        false_;
-
-        // typedef parameters<col_major>     Parameters;
-
-        void assign_pointers()
-        {
-          if (copy_indices)
-          {
-            if (Apc == 0) Apc= new index_type[n + 1];
-            if (my_nnz != A.nnz() && Aic)
-            {
-              delete[] Aic;
-              Aic= 0;
-            }
-            if (Aic == 0) Aic= new index_type[A.nnz()];
-            std::copy(A.address_major(), A.address_major() + n + 1, Apc);
-            std::copy(A.address_minor(), A.address_minor() + A.nnz(), Aic);
-            Ap= Apc;
-            Ai= Aic;
-          }
-          else
-          {
-            Ap= reinterpret_cast<const index_type*>(A.address_major());
-            Ai= reinterpret_cast<const index_type*>(A.address_minor());
-          }
-          Ax= A.address_data();
-        }
-
-        void init_aux(true_)
-        {
-          check(umfpack_dl_symbolic(n, n, Ap, Ai, Ax, &Symbolic, Control, Info), "Error in dl_symbolic");
-          check(umfpack_dl_numeric(Ap, Ai, Ax, Symbolic, &Numeric, Control, Info), "Error in dl_numeric");
-        }
-
-        void init_aux(false_)
-        {
-          check(umfpack_di_symbolic(n, n, Ap, Ai, Ax, &Symbolic, Control, Info), "Error in di_symbolic");
-#if 0
-          std::cout << "=== INFO of umfpack_*_symbolic ===\n";
-          std::cout << "    UMFPACK_STATUS: " << (Info[UMFPACK_STATUS] == UMFPACK_OK ? "OK" : "ERROR") << "\n";
-          std::cout << "    UMFPACK_NROW: " << Info[UMFPACK_NROW] << "\n";
-          std::cout << "    UMFPACK_NCOL: " << Info[UMFPACK_NCOL] << "\n";
-          std::cout << "    UMFPACK_NZ: " << Info[UMFPACK_NZ] << "\n";
-          std::cout << "    UMFPACK_SIZE_OF_UNIT: " << Info[UMFPACK_SIZE_OF_UNIT] << "\n";
-          std::cout << "    UMFPACK_NDENSE_ROW: " << Info[UMFPACK_NDENSE_ROW] << "\n";
-          std::cout << "    UMFPACK_NEMPTY_ROW: " << Info[UMFPACK_NEMPTY_ROW] << "\n";
-          std::cout << "    UMFPACK_NDENSE_COL: " << Info[UMFPACK_NDENSE_COL] << "\n";
-          std::cout << "    UMFPACK_NEMPTY_COL: " << Info[UMFPACK_NEMPTY_COL] << "\n";
-          std::cout << "    UMFPACK_SYMBOLIC_DEFRAG: " << Info[UMFPACK_SYMBOLIC_DEFRAG] << "\n";
-          std::cout << "    UMFPACK_SYMBOLIC_PEAK_MEMORY: " << Info[UMFPACK_SYMBOLIC_PEAK_MEMORY] << "\n";
-          std::cout << "    UMFPACK_SYMBOLIC_SIZE: " << Info[UMFPACK_SYMBOLIC_SIZE] << "\n";
-          std::cout << "    UMFPACK_VARIABLE_PEAK_ESTIMATE: " << Info[UMFPACK_VARIABLE_PEAK_ESTIMATE]  << "\n";
-          std::cout << "    UMFPACK_NUMERIC_SIZE_ESTIMATE: " << Info[UMFPACK_NUMERIC_SIZE_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_PEAK_MEMORY_ESTIMATE: " << Info[UMFPACK_PEAK_MEMORY_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_FLOPS_ESTIMATE: " << Info[UMFPACK_FLOPS_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_LNZ_ESTIMATE: " << Info[UMFPACK_LNZ_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_UNZ_ESTIMATE: " << Info[UMFPACK_UNZ_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_MAX_FRONT_SIZE_ESTIMATE: " << Info[UMFPACK_MAX_FRONT_SIZE_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_SYMBOLIC_TIME: " << Info[UMFPACK_SYMBOLIC_TIME] << "\n";
-          std::cout << "    UMFPACK_SYMBOLIC_WALLTIME: " << Info[UMFPACK_SYMBOLIC_WALLTIME] << "\n";
-
-          if (Info[UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_SYMMETRIC)
-            std::cout << "    UMFPACK_STRATEGY_USED: SYMMETRIC\n";
-          else
-          {
-            if(Info[UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_UNSYMMETRIC)
-              std::cout << "    UMFPACK_STRATEGY_USED: UNSYMMETRIC\n";
-            else
-            {
-              if (Info[UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_2BY2)
-                std::cout << "    UMFPACK_STRATEGY_USED: 2BY2\n";
-              else
-                std::cout << "    UMFPACK_STRATEGY_USED: UNKOWN STRATEGY " << Info[UMFPACK_STRATEGY_USED] << "\n";
-            }
-          }
-
-          std::cout << "    UMFPACK_ORDERING_USED: " << Info[UMFPACK_ORDERING_USED] << "\n";
-          std::cout << "    UMFPACK_QFIXED: " << Info[UMFPACK_QFIXED] << "\n";
-          std::cout << "    UMFPACK_DIAG_PREFERRED: " << Info[UMFPACK_DIAG_PREFERRED] << "\n";
-          std::cout << "    UMFPACK_ROW_SINGLETONS: " << Info[UMFPACK_ROW_SINGLETONS] << "\n";
-          std::cout << "    UMFPACK_COL_SINGLETONS: " << Info[UMFPACK_COL_SINGLETONS] << "\n";
-          std::cout << "    UMFPACK_PATTERN_SYMMETRY: " << Info[UMFPACK_PATTERN_SYMMETRY] << "\n";
-          std::cout << "    UMFPACK_NZ_A_PLUS_AT: " << Info[UMFPACK_NZ_A_PLUS_AT] << "\n";
-          std::cout << "    UMFPACK_NZDIAG: " << Info[UMFPACK_NZDIAG] << "\n";
-          std::cout << "    UMFPACK_N2: " << Info[UMFPACK_N2] << "\n";
-          std::cout << "    UMFPACK_S_SYMMETRIC: " << Info[UMFPACK_S_SYMMETRIC] << "\n";
-          std::cout << "    UMFPACK_MAX_FRONT_NROWS_ESTIMATE: " << Info[UMFPACK_MAX_FRONT_NROWS_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_MAX_FRONT_NCOLS_ESTIMATE: " << Info[UMFPACK_MAX_FRONT_NCOLS_ESTIMATE] << "\n";
-          std::cout << "    UMFPACK_SYMMETRIC_LUNZ: " << Info[UMFPACK_SYMMETRIC_LUNZ] << "\n";
-          std::cout << "    UMFPACK_SYMMETRIC_FLOPS: " << Info[UMFPACK_SYMMETRIC_FLOPS] << "\n";
-          std::cout << "    UMFPACK_SYMMETRIC_NDENSE: " << Info[UMFPACK_SYMMETRIC_NDENSE] << "\n";
-          std::cout << "    UMFPACK_SYMMETRIC_DMAX: " << Info[UMFPACK_SYMMETRIC_DMAX] << "\n";
-#endif
-
-          check(umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, Control, Info), "Error in di_numeric");
-
-#if 0
-          std::cout << "=== INFO of umfpack_*_numeric ===\n";
-          std::cout << "    UMFPACK_STATUS: " << (Info[UMFPACK_STATUS] == UMFPACK_OK ? "OK" : "ERROR") << "\n";
-          std::cout << "    UMFPACK_VARIABLE_PEAK: " << Info[UMFPACK_VARIABLE_PEAK]  << "\n";
-          std::cout << "    UMFPACK_PEAK_MEMORY: " << Info[UMFPACK_PEAK_MEMORY] << "\n";
-          std::cout << "    UMFPACK_FLOPS: " << Info[UMFPACK_FLOPS] << "\n";
-          std::cout << "    UMFPACK_LNZ: " << Info[UMFPACK_LNZ] << "\n";
-          std::cout << "    UMFPACK_UNZ: " << Info[UMFPACK_UNZ] << "\n";
-          std::cout << "    UMFPACK_NUMERIC_DEFRAG: " << Info[UMFPACK_NUMERIC_DEFRAG] << "\n";
-          std::cout << "    UMFPACK_NUMERIC_REALLOC: " << Info[UMFPACK_NUMERIC_REALLOC] << "\n";
-          std::cout << "    UMFPACK_NUMERIC_COSTLY_REALLOC: " << Info[UMFPACK_NUMERIC_COSTLY_REALLOC] << "\n";
-          std::cout << "    UMFPACK_COMPRESSED_PATTERN: " << Info[UMFPACK_COMPRESSED_PATTERN] << "\n";
-          std::cout << "    UMFPACK_LU_ENTRIES: " << Info[UMFPACK_LU_ENTRIES] << "\n";
-          std::cout << "    UMFPACK_NUMERIC_TIME: " << Info[UMFPACK_NUMERIC_TIME] << "\n";
-          std::cout << "    UMFPACK_RCOND: " << Info[UMFPACK_RCOND] << "\n";
-          std::cout << "    UMFPACK_UDIAG_NZ: " << Info[UMFPACK_UDIAG_NZ] << "\n";
-          std::cout << "    UMFPACK_UMIN: " << Info[UMFPACK_UMIN] << "\n";
-          std::cout << "    UMFPACK_UMAX: " << Info[UMFPACK_UMAX] << "\n";
-          std::cout << "    UMFPACK_MAX_FRONT_NROWS: " << Info[UMFPACK_MAX_FRONT_NROWS] << "\n";
-          std::cout << "    UMFPACK_MAX_FRONT_NCOLS: " << Info[UMFPACK_MAX_FRONT_NCOLS] << "\n";
-          std::cout << "    UMFPACK_ALL_LNZ: " << Info[UMFPACK_ALL_LNZ] << "\n";
-          std::cout << "    UMFPACK_ALL_UNZ: " << Info[UMFPACK_ALL_UNZ] << "\n";
-#endif
-        }
-
-        void init()
-        {
-          MTL_THROW_IF(num_rows(A) != num_cols(A), matrix_not_square());
-          n= num_rows(A);
-          assign_pointers();
-          init_aux(blong());
-        }
-
-
-
-      public:
-        /// Constructor referring to matrix \p A (not changed) and optionally Umfpack's strategy and alloc_init
-        solver(const matrix_type& A, int strategy = UMFPACK_STRATEGY_AUTO, double alloc_init = 0.7)
-          : A(A), Apc(0), Aic(0), my_nnz(0), Symbolic(0), Numeric(0)
-        {
-          vampir_trace<5060> trace;
-          // Use default setings.
-          if (long_indices)
-            umfpack_dl_defaults(Control);
-          else
-            umfpack_di_defaults(Control);
-
-          Control[UMFPACK_STRATEGY] = strategy;
-          Control[UMFPACK_ALLOC_INIT] = alloc_init;
-          init();
-        }
-
-        ~solver()
-        {
-          vampir_trace<5061> trace;
-          if (long_indices)
-          {
-            umfpack_dl_free_numeric(&Numeric);
-            umfpack_dl_free_symbolic(&Symbolic);
-          }
-          else
-          {
-            umfpack_di_free_numeric(&Numeric);
-            umfpack_di_free_symbolic(&Symbolic);
-          }
-          if (Apc) delete[] Apc;
-          if (Aic) delete[] Aic;
-        }
-
-        void update_numeric_aux(true_)
-        {
-          umfpack_dl_free_numeric(&Numeric);
-          check(umfpack_dl_numeric(Ap, Ai, Ax, Symbolic, &Numeric, Control, Info), "Error in dl_numeric");
-        }
-
-        void update_numeric_aux(false_)
-        {
-          umfpack_di_free_numeric(&Numeric);
-          check(umfpack_di_numeric(Ap, Ai, Ax, Symbolic, &Numeric, Control, Info), "Error in di_numeric");
-        }
-
-        /// Update numeric part, for matrices that kept the sparsity and changed the values
-        void update_numeric()
-        {
-          assign_pointers();
-          update_numeric_aux(blong());
-        }
-
-        /// Update symbolic and numeric part
-        void update()
-        {
-          if (long_indices)
-          {
-            umfpack_dl_free_numeric(&Numeric);
-            umfpack_dl_free_symbolic(&Symbolic);
-          }
-          else
-          {
-            umfpack_di_free_numeric(&Numeric);
-            umfpack_di_free_symbolic(&Symbolic);
-          }
-          init();
-        }
-
-        template <typename VectorX, typename VectorB>
-        void solve_aux(int sys, VectorX& xx, const VectorB& bb, true_)
-        {
-          check(umfpack_dl_solve(sys, Ap, Ai, Ax, &xx.value[0], &bb.value[0], Numeric, Control, Info), "Error in dl_solve");
-        }
-
-        template <typename VectorX, typename VectorB>
-        void solve_aux(int sys, VectorX& xx, const VectorB& bb, false_)
-        {
-          check(umfpack_di_solve(sys, Ap, Ai, Ax, &xx.value[0], &bb.value[0], Numeric, Control, Info), "Error in di_solve");
-        }
-
-        /// Solve double system
-        template <typename VectorX, typename VectorB>
-        int operator()(VectorX& x, const VectorB& b)
-        {
-          vampir_trace<5062> trace;
-          MTL_THROW_IF(num_rows(A) != size(x) || num_rows(A) != size(b), incompatible_size());
-          make_in_out_copy_or_reference<dense_vector<value_type>, VectorX> xx(x);
-          make_in_copy_or_reference<dense_vector<value_type>, VectorB>     bb(b);
-          int sys= mtl::traits::is_row_major<Parameters>::value ? UMFPACK_At : UMFPACK_A;
-          solve_aux(sys, xx, bb, blong());
-          return UMFPACK_OK;
-        }
-
-        /// Solve double system
-        template <typename VectorB, typename VectorX>
-        int solve(const VectorB& b, VectorX& x) const
-        {
-          // return (*this)(x, b);
-          return const_cast<solver&>(*this)(x, b); // evil hack because Umfpack has no const
-        }
-
-      private:
-        const matrix_type&  A;
-        int                 n;
-        const index_type*    Ap, *Ai;
-        index_type*          Apc, *Aic;
-        size_type           my_nnz;
-        const double*        Ax;
-        double              Control[UMFPACK_CONTROL], Info[UMFPACK_INFO];
-        void*                Symbolic, *Numeric;
-      };
-
-      /// Speciatization of solver for \ref matrix::compressed2D with double values
-      template <typename Parameters>
-      class solver<compressed2D<std::complex<double>, Parameters>>
-      {
-        typedef std::complex<double>                      value_type;
-        typedef compressed2D<value_type, Parameters>      matrix_type;
-        typedef typename matrix_type::size_type           size_type;
-        typedef typename index<size_type>::type           index_type;
-
-        static const bool copy_indices= sizeof(index_type) != sizeof(size_type),
-                          long_indices= use_long<size_type>::value;
-
-        typedef boost::mpl::bool_<long_indices>           blong;
-        typedef boost::mpl::true_                         true_;
-        typedef boost::mpl::false_                        false_;
-
-
-        void assign_pointers()
-        {
-          if (copy_indices)
-          {
-            if (Apc == 0) Apc= new index_type[n + 1];
-            if (Aic == 0) Aic= new index_type[A.nnz()];
-            std::copy(A.address_major(), A.address_major() + n + 1, Apc);
-            std::copy(A.address_minor(), A.address_minor() + A.nnz(), Aic);
-            Ap= Apc;
-            Ai= Aic;
-          }
-          else
-          {
-            Ap= reinterpret_cast<const index_type*>(A.address_major());
-            Ai= reinterpret_cast<const index_type*>(A.address_minor());
-          }
-          split_complex_vector(A.data, Ax, Az);
-        }
-
-        void init_aux(true_)
-        {
-          check(umfpack_zl_symbolic(n, n, Ap, Ai, &Ax[0], &Az[0], &Symbolic, Control, Info), "Error in zl_symbolic");
-          check(umfpack_zl_numeric(Ap, Ai, &Ax[0], &Az[0], Symbolic, &Numeric, Control, Info), "Error in zl_numeric");
-        }
-
-        void init_aux(false_)
-        {
-          check(umfpack_zi_symbolic(n, n, Ap, Ai, &Ax[0], &Az[0], &Symbolic, Control, Info), "Error in zi_symbolic");
-          check(umfpack_zi_numeric(Ap, Ai, &Ax[0], &Az[0], Symbolic, &Numeric, Control, Info), "Error in zi_numeric");
-        }
-
-        void initialize()
-        {
-          MTL_THROW_IF(num_rows(A) != num_cols(A), matrix_not_square());
-          n= num_rows(A);
-          assign_pointers();
-          init_aux(blong());
-        }
-      public:
-        /// Constructor referring to matrix \p A (not changed) and optionally Umfpack's strategy and alloc_init (look for the specializations)
-        explicit solver(const compressed2D<value_type, Parameters>& A, int strategy = UMFPACK_STRATEGY_AUTO, double alloc_init = 0.7)
-          : A(A), Apc(0), Aic(0)
-        {
-          vampir_trace<5060> trace;
-          // Use default setings.
-          if (long_indices)
-            umfpack_zl_defaults(Control);
-          else
-            umfpack_zi_defaults(Control);
-          // umfpack_zi_defaults(Control);
-
-          Control[UMFPACK_STRATEGY] = strategy;
-          Control[UMFPACK_ALLOC_INIT] = alloc_init;
-          initialize();
-        }
-
-        ~solver()
-        {
-          vampir_trace<5061> trace;
-          if (long_indices)
-          {
-            umfpack_zl_free_numeric(&Numeric);
-            umfpack_zl_free_symbolic(&Symbolic);
-          }
-          else
-          {
-            umfpack_zi_free_numeric(&Numeric);
-            umfpack_zi_free_symbolic(&Symbolic);
-          }
-          if (Apc) delete[] Apc;
-          if (Aic) delete[] Aic;
-        }
-
-        void update_numeric_aux(true_)
-        {
-          umfpack_zl_free_numeric(&Numeric);
-          check(umfpack_zl_numeric(Ap, Ai, &Ax[0], &Az[0], Symbolic, &Numeric, Control, Info), "Error in dl_numeric D");
-        }
-
-        void update_numeric_aux(false_)
-        {
-          umfpack_zi_free_numeric(&Numeric);
-          check(umfpack_zi_numeric(Ap, Ai, &Ax[0], &Az[0], Symbolic, &Numeric, Control, Info), "Error in di_numeric");
-        }
-
-        /// Update numeric part, for matrices that kept the sparsity and changed the values
-        void update_numeric()
-        {
-          assign_pointers();
-          update_numeric_aux(blong());
-        }
-
-        /// Update symbolic and numeric part
-        void update()
-        {
-          Ax.change_dim(0);
-          Az.change_dim(0);
-          if (long_indices)
-          {
-            umfpack_zl_free_numeric(&Numeric);
-            umfpack_zl_free_symbolic(&Symbolic);
-          }
-          else
-          {
-            umfpack_zi_free_numeric(&Numeric);
-            umfpack_zi_free_symbolic(&Symbolic);
-          }
-          initialize();
-        }
-
-        template <typename VectorX, typename VectorB>
-        void solve_aux(int sys, VectorX& Xx, VectorX& Xz, const VectorB& Bx, const VectorB& Bz, true_)
-        {
-          check(umfpack_zl_solve(sys, Ap, Ai, &Ax[0], &Az[0], &Xx[0], &Xz[0], &Bx[0], &Bz[0], Numeric, Control, Info),
-                "Error in zi_solve");
-        }
-
-        template <typename VectorX, typename VectorB>
-        void solve_aux(int sys, VectorX& Xx, VectorX& Xz, const VectorB& Bx, const VectorB& Bz, false_)
-        {
-          check(umfpack_zi_solve(sys, Ap, Ai, &Ax[0], &Az[0], &Xx[0], &Xz[0], &Bx[0], &Bz[0], Numeric, Control, Info),
-                "Error in zi_solve");
-        }
-
-        /// Solve complex system
-        template <typename VectorX, typename VectorB>
-        int operator()(VectorX& x, const VectorB& b)
-        {
-          vampir_trace<5062> trace;
-          MTL_THROW_IF(num_rows(A) != size(x) || num_rows(A) != size(b), incompatible_size());
-          dense_vector<double> Xx(size(x)), Xz(size(x)), Bx, Bz;
-          split_complex_vector(b, Bx, Bz);
-          int sys= mtl::traits::is_row_major<Parameters>::value ? UMFPACK_Aat : UMFPACK_A;
-          solve_aux(sys, Xx, Xz, Bx, Bz, blong());
-          merge_complex_vector(Xx, Xz, x);
-          return UMFPACK_OK;
-        }
-
-        /// Solve complex system
-        template <typename VectorB, typename VectorX>
-        int solve(const VectorB& b, VectorX& x)
-        {
-          return (*this)(x, b);
-        }
-
-      private:
-        const matrix_type&   A;
-        int                  n;
-        const index_type*     Ap, *Ai;
-        index_type*          Apc, *Aic;
-        dense_vector<double> Ax, Az;
-        double               Control[UMFPACK_CONTROL], Info[UMFPACK_INFO];
-        void*                 Symbolic, *Numeric;
-      };
-
-      template <typename Value, typename Parameters>
-      class solver<compressed2D<Value, Parameters>>
-            : matrix_copy<compressed2D<Value, Parameters>, Value, typename Parameters::orientation>,
-              public solver<typename matrix_copy<compressed2D<Value, Parameters>, Value, typename Parameters::orientation>::matrix_type>
-      {
-        typedef matrix_copy<compressed2D<Value, Parameters>, Value, typename Parameters::orientation> copy_type;
-        typedef solver<typename matrix_copy<compressed2D<Value, Parameters>, Value, typename Parameters::orientation>::matrix_type> solver_type;
-      public:
-        explicit solver(const compressed2D<Value, Parameters>& A)
-          : copy_type(A), solver_type(copy_type::matrix), A(A)
-        {}
-
-        void update()
-        {
-          copy_type::matrix= A;
-          solver_type::update();
-        }
-
-        void update_numeric()
-        {
-          copy_type::matrix= A;
-          solver_type::update_numeric();
-        }
-      private:
-        const compressed2D<Value, Parameters>& A;
-      };
-    } // umfpack
-
-    /// Solve A*x == b with umfpack
-    /** Only available when compiled with enabled macro MTL_HAS_UMFPACK.
-        Uses classes umfpack::solver internally.
-        If you want more control on single operations or to keep umfpack's
-        internal factorization, use this class.
-     **/
-    template <typename Value, typename Parameters, typename VectorX, typename VectorB>
-    int umfpack2_solve(const compressed2D<Value, Parameters>& A, VectorX& x, const VectorB& b)
-    {
-      umfpack::solver<compressed2D<Value, Parameters>> solver(A);
-      return solver(x, b);
-    }
-
-  }
-} // namespace mtl::mat
-
-#endif
-
-#endif // MTL_MATRIX_UMFPACK_SOLVE_INCLUDE