From 26fdde6f5b6bf71ba59b80ea888211a2db14680e Mon Sep 17 00:00:00 2001
From: "Praetorius, Simon" <simon.praetorius@tu-dresden.de>
Date: Wed, 1 May 2019 13:05:52 +0200
Subject: [PATCH] Removed the direct solver specialization ofr double types in
 favour of the separate initialization in the creators

---
 examples/navier_stokes.cc                     | 12 ++-
 src/amdis/Assembler.hpp                       | 25 +++---
 src/amdis/AssemblerInterface.hpp              | 22 +++---
 src/amdis/DataTransfer.inc.hpp                |  3 +-
 src/amdis/Mesh.hpp                            |  6 +-
 src/amdis/OperatorList.hpp                    | 17 +++--
 src/amdis/PeriodicBC.inc.hpp                  |  9 ++-
 src/amdis/ProblemStat.hpp                     |  4 +-
 src/amdis/ProblemStatTraits.hpp               |  3 +-
 src/amdis/gridfunctions/DiscreteFunction.hpp  |  2 +-
 src/amdis/linearalgebra/DOFMatrixBase.hpp     |  5 +-
 src/amdis/linearalgebra/DOFMatrixBase.inc.hpp |  6 +-
 src/amdis/linearalgebra/DOFVectorBase.hpp     |  4 +-
 src/amdis/linearalgebra/DOFVectorBase.inc.hpp |  6 +-
 .../linearalgebra/eigen/DirectRunner.hpp      | 15 ++--
 .../linearalgebra/eigen/SolverCreator.hpp     | 18 +++--
 src/amdis/linearalgebra/istl/DirectRunner.hpp | 29 +++----
 .../istl/ISTL_Preconditioner.hpp              | 24 ++++--
 src/amdis/linearalgebra/istl/ISTL_Solver.hpp  | 26 ++++---
 src/amdis/linearalgebra/mtl/ITL_Solver.hpp    | 12 ++-
 src/amdis/linearalgebra/mtl/KrylovRunner.hpp  |  6 +-
 src/amdis/linearalgebra/mtl/UmfpackRunner.hpp | 76 +++++++------------
 src/amdis/linearalgebra/mtl/itl/details.hpp   |  7 +-
 src/amdis/linearalgebra/mtl/itl/fgmres.hpp    |  3 +-
 .../mtl/itl/fgmres_householder.hpp            |  3 +-
 src/amdis/linearalgebra/mtl/itl/gmres2.hpp    |  3 +-
 .../mtl/itl/gmres_householder.hpp             |  3 +-
 .../localoperators/ZeroOrderTestTrialvec.hpp  |  2 +-
 .../ZeroOrderTestvecTrialvec.hpp              |  4 +-
 test/CMakeLists.txt                           |  3 +
 test/ProblemStatTest.cpp                      | 36 +++++++++
 31 files changed, 235 insertions(+), 159 deletions(-)
 create mode 100644 test/ProblemStatTest.cpp

diff --git a/examples/navier_stokes.cc b/examples/navier_stokes.cc
index 4735e5f3..86fea59d 100644
--- a/examples/navier_stokes.cc
+++ b/examples/navier_stokes.cc
@@ -7,17 +7,21 @@
 
 using namespace AMDiS;
 
-using Grid = Dune::YaspGrid<2>;
-using Basis = TaylorHoodBasis<Grid>;
+struct NavierStokesBasis
+{
+  using Grid = Dune::YaspGrid<GRIDDIM>;
+  using GlobalBasis = typename TaylorHoodBasis<Grid>::GlobalBasis;
+  using CoefficientType = double;
+};
 
 int main(int argc, char** argv)
 {
   AMDiS::init(argc, argv);
 
-  ProblemStat<Basis> prob("stokes");
+  ProblemStat<NavierStokesBasis> prob("stokes");
   prob.initialize(INIT_ALL);
 
-  ProblemInstat<Basis> probInstat("stokes", prob);
+  ProblemInstat<NavierStokesBasis> probInstat("stokes", prob);
   probInstat.initialize(INIT_UH_OLD);
 
   double viscosity = 1.0;
diff --git a/src/amdis/Assembler.hpp b/src/amdis/Assembler.hpp
index 59d52169..dad37e90 100644
--- a/src/amdis/Assembler.hpp
+++ b/src/amdis/Assembler.hpp
@@ -16,19 +16,18 @@ namespace AMDiS
 {
   /// Implementation of interface \ref AssemblerBase
   /**
-   * \tparam LC  LocalContext
+   * \tparam Traits  See \ref DefaultAssemblerTraits
    **/
-  template <class LC, class Operator, class... Nodes>
+  template <class Traits, class Operator, class... Nodes>
   class Assembler
-      : public AssemblerInterface<LC, Nodes...>
+      : public AssemblerInterface<Traits, Nodes...>
   {
-    using Super = AssemblerInterface<LC, Nodes...>;
-
-  private:
+    using Super = AssemblerInterface<Traits, Nodes...>;
 
+    using LocalContext = typename Traits::LocalContext;
     using Element = typename Super::Element;
     using Geometry = typename Super::Geometry;
-    using ElementMatrixVector = typename Super::ElementMatrixVector;
+    using ElementContainer = typename Traits::ElementContainer;
 
   public:
 
@@ -77,11 +76,11 @@ namespace AMDiS
      * \ref calculateElementVector or \ref calculateElementMatrix on the
      * vector or matrix operator, respectively.
      **/
-    void assemble(LC const& localContext, Nodes const&... nodes,
-                  ElementMatrixVector& elementMatrixVector) final
+    void assemble(LocalContext const& localContext, Nodes const&... nodes,
+                  ElementContainer& ElementContainer) final
     {
-      ContextGeometry<LC> contextGeo{localContext, element(), geometry()};
-      assembleImpl(contextGeo, nodes..., elementMatrixVector);
+      ContextGeometry<LocalContext> contextGeo{localContext, element(), geometry()};
+      assembleImpl(contextGeo, nodes..., ElementContainer);
     }
 
 
@@ -133,10 +132,10 @@ namespace AMDiS
 
 
   /// Generate a \ref Assembler on a given LocalContext `LC` (element or intersection)
-  template <class LC, class Operator, class... Nodes>
+  template <class Traits, class Operator, class... Nodes>
   auto makeAssembler(Operator&& op, Nodes const&...)
   {
-    return Assembler<LC, Underlying_t<Operator>, Nodes...>{FWD(op)};
+    return Assembler<Traits, Underlying_t<Operator>, Nodes...>{FWD(op)};
   }
 
 } // end namespace AMDiS
diff --git a/src/amdis/AssemblerInterface.hpp b/src/amdis/AssemblerInterface.hpp
index 68e9b5d2..5cfee9af 100644
--- a/src/amdis/AssemblerInterface.hpp
+++ b/src/amdis/AssemblerInterface.hpp
@@ -9,10 +9,18 @@
 
 namespace AMDiS
 {
+  template <class LC, class C>
+  struct DefaultAssemblerTraits
+  {
+    using LocalContext = LC;
+    using ElementContainer = C;
+  };
+
   /// Abstract base-class of a \ref Assembler
-  template <class LocalContext, class... Nodes>
+  template <class Traits, class... Nodes>
   class AssemblerInterface
   {
+    using LocalContext = typename Traits::LocalContext;
     using ContextType = Impl::ContextTypes<LocalContext>;
 
   public:
@@ -25,14 +33,6 @@ namespace AMDiS
     static_assert( numNodes == 1 || numNodes == 2,
       "VectorAssembler gets 1 Node, MatrixAssembler gets 2 Nodes!");
 
-    using ElementMatrix = Dune::DynamicMatrix<double>; // TODO: choose correct value_type
-    using ElementVector = Dune::DynamicVector<double>;
-
-    /// Either an ElementVector or an ElementMatrix (depending on the number of nodes)
-    using ElementMatrixVector = std::conditional_t<
-      (sizeof...(Nodes)==1), ElementVector, std::conditional_t<
-      (sizeof...(Nodes)==2), ElementMatrix, void>>;
-
   public:
     /// Virtual destructor
     virtual ~AssemblerInterface() = default;
@@ -44,9 +44,9 @@ namespace AMDiS
     virtual void unbind() = 0;
 
     /// Assemble an element matrix or element vector on the test- (and trial-) function node(s)
-    virtual void assemble(LocalContext const& localContext,
+    virtual void assemble(typename Traits::LocalContext const& localContext,
                           Nodes const&... nodes,
-                          ElementMatrixVector& elementMatrixVector) = 0;
+                          typename Traits::ElementContainer& elementMatrixVector) = 0;
   };
 
 } // end namespace AMDiS
diff --git a/src/amdis/DataTransfer.inc.hpp b/src/amdis/DataTransfer.inc.hpp
index b6f01e93..bf2efd78 100644
--- a/src/amdis/DataTransfer.inc.hpp
+++ b/src/amdis/DataTransfer.inc.hpp
@@ -156,7 +156,8 @@ namespace AMDiS
     // Interpolate from possibly vanishing elements
     if (mightCoarsen) {
       auto maxLevel = gv.grid().maxLevel();
-      ctype const checkInsideTolerance = std::sqrt(std::numeric_limits<ctype>::epsilon());
+      using std::sqrt;
+      ctype const checkInsideTolerance = sqrt(std::numeric_limits<ctype>::epsilon());
       for (auto const& e : elements(gv))
       {
         auto father = e;
diff --git a/src/amdis/Mesh.hpp b/src/amdis/Mesh.hpp
index 1d1d0948..be361b73 100644
--- a/src/amdis/Mesh.hpp
+++ b/src/amdis/Mesh.hpp
@@ -141,7 +141,7 @@ namespace AMDiS
 
     static std::unique_ptr<Grid> create(std::string const& meshName)
     {
-      Dune::FieldVector<double, dim> L; L = 1.0;  // extension of the domain
+      Dune::FieldVector<T, dim> L; L = 1.0;  // extension of the domain
       Parameters::get(meshName + "->dimension", L);
 
       auto s = Dune::filledArray<std::size_t(dim)>(1); // number of cells on coarse mesh in each direction
@@ -161,8 +161,8 @@ namespace AMDiS
 
     static std::unique_ptr<Grid> create(std::string const& meshName)
     {
-      Dune::FieldVector<double, dim> lowerleft;  lowerleft = 0.0; // Lower left corner of the domain
-      Dune::FieldVector<double, dim> upperright; upperright = 1.0; // Upper right corner of the domain
+      Dune::FieldVector<T, dim> lowerleft;  lowerleft = 0.0; // Lower left corner of the domain
+      Dune::FieldVector<T, dim> upperright; upperright = 1.0; // Upper right corner of the domain
       Parameters::get(meshName + "->min corner", lowerleft);
       Parameters::get(meshName + "->max corner", upperright);
 
diff --git a/src/amdis/OperatorList.hpp b/src/amdis/OperatorList.hpp
index bf780920..92963412 100644
--- a/src/amdis/OperatorList.hpp
+++ b/src/amdis/OperatorList.hpp
@@ -20,7 +20,7 @@ namespace AMDiS
     };
   }
 
-  template <class GridView>
+  template <class GridView, class Container>
   class OperatorLists
   {
     using Element = typename GridView::template Codim<0>::Entity;
@@ -102,11 +102,14 @@ namespace AMDiS
       auto const& onBoundary() const { return boundary_; }
 
     private:
+      using ElementTraits = DefaultAssemblerTraits<Element,Container>;
+      using IntersectionTraits = DefaultAssemblerTraits<Intersection,Container>;
+
       /// The type of local operators associated with grid elements
-      using ElementAssembler = AssemblerInterface<Element, Nodes...>;
+      using ElementAssembler = AssemblerInterface<ElementTraits, Nodes...>;
 
       /// The type of local operators associated with grid intersections
-      using IntersectionAssembler = AssemblerInterface<Intersection, Nodes...>;
+      using IntersectionAssembler = AssemblerInterface<IntersectionTraits, Nodes...>;
 
       /// List of operators to be assembled on grid elements
       std::vector<std::shared_ptr<ElementAssembler>> element_;
@@ -136,12 +139,12 @@ namespace AMDiS
   };
 
 
-  template <class RowBasis, class ColBasis>
+  template <class RowBasis, class ColBasis, class ElementMatrix>
   using MatrixOperators
-    = MatrixData<RowBasis, ColBasis, OperatorLists<typename RowBasis::GridView>::template MatData>;
+    = MatrixData<RowBasis, ColBasis, OperatorLists<typename RowBasis::GridView,ElementMatrix>::template MatData>;
 
-  template <class GlobalBasis>
+  template <class GlobalBasis, class ElementVector>
   using VectorOperators
-    = VectorData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView>::template VecData>;
+    = VectorData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView,ElementVector>::template VecData>;
 
 } // end namespace AMDiS
diff --git a/src/amdis/PeriodicBC.inc.hpp b/src/amdis/PeriodicBC.inc.hpp
index 94aa7469..0c92fecd 100644
--- a/src/amdis/PeriodicBC.inc.hpp
+++ b/src/amdis/PeriodicBC.inc.hpp
@@ -43,7 +43,8 @@ template <class D, class MI>
 void PeriodicBC<D,MI>::
 initAssociations(Basis const& basis)
 {
-  static const double tol = std::sqrt(std::numeric_limits<typename D::field_type>::epsilon());
+  using std::sqrt;
+  static const auto tol = sqrt(std::numeric_limits<typename D::field_type>::epsilon());
   periodicNodes_.clear();
   periodicNodes_.resize(basis.dimension(), false);
 
@@ -107,8 +108,9 @@ namespace Impl
 
     bool operator()(D const& lhs, D const& rhs) const
     {
+      using std::abs;
       for (int i = 0; i < D::dimension; i++) {
-        if (std::abs(lhs[i] - rhs[i]) < tol_)
+        if (abs(lhs[i] - rhs[i]) < tol_)
           continue;
         return lhs[i] < rhs[i];
       }
@@ -127,7 +129,8 @@ template <class D, class MI>
 void PeriodicBC<D,MI>::
 initAssociations2(Basis const& basis)
 {
-  static const double tol = std::sqrt(std::numeric_limits<typename D::field_type>::epsilon());
+  using std::sqrt;
+  static const auto tol = sqrt(std::numeric_limits<typename D::field_type>::epsilon());
   periodicNodes_.clear();
   periodicNodes_.resize(basis.dimension(), false);
 
diff --git a/src/amdis/ProblemStat.hpp b/src/amdis/ProblemStat.hpp
index 97046397..35cea992 100644
--- a/src/amdis/ProblemStat.hpp
+++ b/src/amdis/ProblemStat.hpp
@@ -70,8 +70,8 @@ namespace AMDiS
     /// Dimension of the world
     static constexpr int dow = Grid::dimensionworld;
 
-    using SystemMatrix = DOFMatrix<GlobalBasis, GlobalBasis, double>;
-    using SystemVector = DOFVector<GlobalBasis, double>;
+    using SystemMatrix = DOFMatrix<GlobalBasis, GlobalBasis, typename Traits::CoefficientType>;
+    using SystemVector = DOFVector<GlobalBasis, typename Traits::CoefficientType>;
 
     using LinearSolverType = LinearSolverInterface<typename SystemMatrix::BaseMatrix, typename SystemVector::BaseVector>;
 
diff --git a/src/amdis/ProblemStatTraits.hpp b/src/amdis/ProblemStatTraits.hpp
index 0be129b5..6bd0c49b 100644
--- a/src/amdis/ProblemStatTraits.hpp
+++ b/src/amdis/ProblemStatTraits.hpp
@@ -64,7 +64,7 @@ namespace AMDiS
   };
 
 
-  template <class Grid, class PreBasisCreator>
+  template <class Grid, class PreBasisCreator, class T = double>
   struct DefaultBasisCreator
   {
     using GridView = typename Grid::LeafGridView;
@@ -75,6 +75,7 @@ namespace AMDiS
     }
 
     using GlobalBasis = decltype(create(std::declval<GridView>()));
+    using CoefficientType = T;
   };
 
   /// \brief ProblemStatTraits for a (composite) basis composed of
diff --git a/src/amdis/gridfunctions/DiscreteFunction.hpp b/src/amdis/gridfunctions/DiscreteFunction.hpp
index 3a367a3a..9323112d 100644
--- a/src/amdis/gridfunctions/DiscreteFunction.hpp
+++ b/src/amdis/gridfunctions/DiscreteFunction.hpp
@@ -32,7 +32,7 @@ namespace AMDiS
   template <class GB, class VT, class TP>
   class DiscreteFunction
   {
-    static_assert(std::is_arithmetic<VT>::value, "");
+    // static_assert(Dune::IsNumber<VT>::value, "");
 
   private:
     using GlobalBasis = GB;
diff --git a/src/amdis/linearalgebra/DOFMatrixBase.hpp b/src/amdis/linearalgebra/DOFMatrixBase.hpp
index 213759ed..a197930c 100644
--- a/src/amdis/linearalgebra/DOFMatrixBase.hpp
+++ b/src/amdis/linearalgebra/DOFMatrixBase.hpp
@@ -37,12 +37,13 @@ namespace AMDiS
 
     /// The index/size - type
     using size_type = typename RowBasis::size_type;
+    using value_type = typename Backend::value_type;
 
     /// The type of the data matrix used in the backend
     using BaseMatrix = typename Backend::BaseMatrix;
 
     /// The type of the matrix filled on an element with local contributions
-    using ElementMatrix = Dune::DynamicMatrix<double>;
+    using ElementMatrix = Dune::DynamicMatrix<value_type>;
 
   public:
     /// Constructor. Stores the shared_ptr to the bases.
@@ -166,7 +167,7 @@ namespace AMDiS
     ElementMatrix elementMatrix_;
 
     /// List of operators associated to row/col node
-    MatrixOperators<RowBasis,ColBasis> operators_;
+    MatrixOperators<RowBasis,ColBasis,ElementMatrix> operators_;
   };
 
 } // end namespace AMDiS
diff --git a/src/amdis/linearalgebra/DOFMatrixBase.inc.hpp b/src/amdis/linearalgebra/DOFMatrixBase.inc.hpp
index f06bbde6..e37a52c2 100644
--- a/src/amdis/linearalgebra/DOFMatrixBase.inc.hpp
+++ b/src/amdis/linearalgebra/DOFMatrixBase.inc.hpp
@@ -32,10 +32,11 @@ void DOFMatrixBase<RB,CB,B>::
 insert(RowLocalView const& rowLocalView, ColLocalView const& colLocalView,
        ElementMatrix const& elementMatrix)
 {
+  using std::abs;
   for (size_type i = 0; i < rowLocalView.size(); ++i) {
     size_type const row = flatMultiIndex(rowLocalView.index(i));
     for (size_type j = 0; j < colLocalView.size(); ++j) {
-      if (std::abs(elementMatrix[i][j]) > threshold<double>) {
+      if (abs(elementMatrix[i][j]) > threshold<double>) {
         size_type const col = flatMultiIndex(colLocalView.index(j));
         backend_.insert(row, col, elementMatrix[i][j]);
       }
@@ -59,8 +60,9 @@ addOperator(ContextTag contextTag, Expr const& expr,
   auto j = child(colBasis_->localView().tree(), makeTreePath(col));
 
   using LocalContext = typename ContextTag::type;
+  using Traits = DefaultAssemblerTraits<LocalContext, ElementMatrix>;
   auto op = makeLocalOperator<LocalContext>(expr, rowBasis_->gridView());
-  auto localAssembler = makeUniquePtr(makeAssembler<LocalContext>(std::move(op), i, j));
+  auto localAssembler = makeUniquePtr(makeAssembler<Traits>(std::move(op), i, j));
 
   operators_[i][j].push(contextTag, std::move(localAssembler));
 }
diff --git a/src/amdis/linearalgebra/DOFVectorBase.hpp b/src/amdis/linearalgebra/DOFVectorBase.hpp
index 62603d66..9f17f9aa 100644
--- a/src/amdis/linearalgebra/DOFVectorBase.hpp
+++ b/src/amdis/linearalgebra/DOFVectorBase.hpp
@@ -73,7 +73,7 @@ namespace AMDiS
     using BaseVector = typename Backend::BaseVector;
 
     /// The type of the vector filled on an element with local contributions
-    using ElementVector = Dune::DynamicVector<double>;
+    using ElementVector = Dune::DynamicVector<value_type>;
 
     /// Defines an interface to transfer the data during grid adaption
     using DataTransfer = DataTransferInterface<Self>;
@@ -290,7 +290,7 @@ namespace AMDiS
     ElementVector elementVector_;
 
     /// List of operators associated to nodes, filled in \ref addOperator().
-    VectorOperators<GlobalBasis> operators_;
+    VectorOperators<GlobalBasis,ElementVector> operators_;
 
     /// Data interpolation when the grid changes, set by default
     /// to \ref DataTransferOperation::INTERPOLATE.
diff --git a/src/amdis/linearalgebra/DOFVectorBase.inc.hpp b/src/amdis/linearalgebra/DOFVectorBase.inc.hpp
index 4795c768..783eb899 100644
--- a/src/amdis/linearalgebra/DOFVectorBase.inc.hpp
+++ b/src/amdis/linearalgebra/DOFVectorBase.inc.hpp
@@ -30,8 +30,9 @@ template <class GB, class B>
 void DOFVectorBase<GB,B>::
 insert(LocalView const& localView, ElementVector const& elementVector)
 {
+  using std::abs;
   for (size_type i = 0; i < localView.size(); ++i) {
-    if (std::abs(elementVector[i]) > threshold<double>) {
+    if (abs(elementVector[i]) > threshold<double>) {
       size_type const idx = flatMultiIndex(localView.index(i));
       backend_[idx] += elementVector[i];
     }
@@ -50,8 +51,9 @@ addOperator(ContextTag contextTag, Expr const& expr, TreePath path)
   auto i = child(basis_->localView().tree(), makeTreePath(path));
 
   using LocalContext = typename ContextTag::type;
+  using Traits = DefaultAssemblerTraits<LocalContext, ElementVector>;
   auto op = makeLocalOperator<LocalContext>(expr, basis_->gridView());
-  auto localAssembler = makeUniquePtr(makeAssembler<LocalContext>(std::move(op), i));
+  auto localAssembler = makeUniquePtr(makeAssembler<Traits>(std::move(op), i));
 
   operators_[i].push(contextTag, std::move(localAssembler));
 }
diff --git a/src/amdis/linearalgebra/eigen/DirectRunner.hpp b/src/amdis/linearalgebra/eigen/DirectRunner.hpp
index afcfa234..f37208b9 100644
--- a/src/amdis/linearalgebra/eigen/DirectRunner.hpp
+++ b/src/amdis/linearalgebra/eigen/DirectRunner.hpp
@@ -10,23 +10,24 @@
 namespace AMDiS
 {
   /**
-   * \ingroup Solver
-   * \class AMDiS::DirectRunner
-   * \brief \implements RunnerInterface for the (external) direct solvers
-   */
-  template <class LU, class Matrix, class VectorX, class VectorB>
+  * \ingroup Solver
+  * \class AMDiS::DirectRunner
+  * \brief \implements RunnerInterface for the (external) direct solvers
+  */
+  template <template <class> class Solver, class Matrix, class VectorX, class VectorB>
   class DirectRunner
       : public RunnerInterface<Matrix, VectorX, VectorB>
   {
   protected:
     using Super = RunnerInterface<Matrix, VectorX, VectorB>;
+    using EigenSolver = Solver<Matrix>;
 
   public:
     /// Constructor.
     DirectRunner(std::string const& prefix)
       : solver_{}
     {
-      SolverConfig<LU>::init(prefix, solver_);
+      SolverConfig<Solver>::init(prefix, solver_);
       Parameters::get(prefix + "->reuse pattern", reusePattern_);
     }
 
@@ -64,7 +65,7 @@ namespace AMDiS
     }
 
   private:
-    LU solver_;
+    EigenSolver solver_;
     bool reusePattern_ = false;
     bool initialized_ = false;
   };
diff --git a/src/amdis/linearalgebra/eigen/SolverCreator.hpp b/src/amdis/linearalgebra/eigen/SolverCreator.hpp
index 4110f9ef..8d283837 100644
--- a/src/amdis/linearalgebra/eigen/SolverCreator.hpp
+++ b/src/amdis/linearalgebra/eigen/SolverCreator.hpp
@@ -100,7 +100,7 @@ namespace AMDiS
     using SolverCreator
       = IterativeSolverCreator<Matrix, VectorX, VectorB, IterativeSolver>;
 
-    template <class DirectSolver>
+    template <template <class> class DirectSolver>
     using DirectSolverCreator
       = typename LinearSolver<Matrix, VectorX, VectorB,
           DirectRunner<DirectSolver, Matrix, VectorX, VectorB>>::Creator;
@@ -148,21 +148,27 @@ namespace AMDiS
       auto dgmres = new SolverCreator<DGMRES>;
       Map::addCreator("dgmres", dgmres);
 
+      // default iterative solver
+      Map::addCreator("default", gmres);
+
+      init_direct(std::is_same<typename Dune::FieldTraits<T>::real_type, double>{});
+    }
+
+    static void init_direct(std::false_type) {}
+    static void init_direct(std::true_type)
+    {
 #if HAVE_SUITESPARSE_UMFPACK
       // sparse LU factorization and solver based on UmfPack
-      auto umfpack = new DirectSolverCreator<Eigen::UmfPackLU<Matrix>>;
+      auto umfpack = new DirectSolverCreator<Eigen::UmfPackLU>;
       Map::addCreator("umfpack", umfpack);
 #endif
 
 #if HAVE_SUPERLU
       // sparse direct LU factorization and solver based on the SuperLU library
-      auto superlu = new DirectSolverCreator<Eigen::SuperLU<Matrix>>;
+      auto superlu = new DirectSolverCreator<Eigen::SuperLU>;
       Map::addCreator("superlu", superlu);
 #endif
 
-      // default iterative solver
-      Map::addCreator("default", gmres);
-
       // default direct solvers
 #if HAVE_SUITESPARSE_UMFPACK
       Map::addCreator("direct", umfpack);
diff --git a/src/amdis/linearalgebra/istl/DirectRunner.hpp b/src/amdis/linearalgebra/istl/DirectRunner.hpp
index f2785b64..6a3f7852 100644
--- a/src/amdis/linearalgebra/istl/DirectRunner.hpp
+++ b/src/amdis/linearalgebra/istl/DirectRunner.hpp
@@ -3,6 +3,8 @@
 #include <algorithm>
 #include <string>
 
+#include <dune/common/ftraits.hh>
+
 #include <amdis/Output.hpp>
 #include <amdis/linearalgebra/RunnerInterface.hpp>
 #include <amdis/linearalgebra/SolverInfo.hpp>
@@ -10,17 +12,18 @@
 namespace AMDiS
 {
   /**
-   * \ingroup Solver
-   * \class AMDiS::DirectRunner
-   * \brief \implements RunnerInterface for the (external) direct solvers
-   */
-  template <class Solver, class Matrix, class VectorX, class VectorB>
+  * \ingroup Solver
+  * \class AMDiS::DirectRunner
+  * \brief \implements RunnerInterface for the (external) direct solvers
+  */
+  template <template <class> class Solver, class Mat, class Sol, class Rhs>
   class DirectRunner
-      : public RunnerInterface<Matrix, VectorX, VectorB>
+      : public RunnerInterface<Mat, Sol, Rhs>
   {
   protected:
-    using Super = RunnerInterface<Matrix, VectorX, VectorB>;
-    using BaseSolver  = Dune::InverseOperator<VectorX, VectorB>;
+    using Super = RunnerInterface<Mat, Sol, Rhs>;
+    using BaseSolver  = Dune::InverseOperator<Sol, Rhs>;
+    using ISTLSolver = Solver<Mat>;
 
   public:
     /// Constructor.
@@ -29,7 +32,7 @@ namespace AMDiS
     {}
 
     /// Implementes \ref RunnerInterface::init()
-    void init(Matrix const& A) override
+    void init(Mat const& A) override
     {
       solver_ = solverCreator_.create(A);
     }
@@ -41,14 +44,14 @@ namespace AMDiS
     }
 
     /// Implementes \ref RunnerInterface::solve()
-    int solve(Matrix const& A, VectorX& x, VectorB const& b,
-                      SolverInfo& solverInfo) override
+    int solve(Mat const& A, Sol& x, Rhs const& b,
+              SolverInfo& solverInfo) override
     {
       // storing some statistics
       Dune::InverseOperatorResult statistics;
 
       // solve the linear system
-      VectorB _b = b;
+      Rhs _b = b;
       solver_->apply(x, _b, statistics);
 
       solverInfo.setRelResidual(statistics.reduction);
@@ -57,7 +60,7 @@ namespace AMDiS
     }
 
   private:
-    ISTLSolverCreator<Solver> solverCreator_;
+    ISTLSolverCreator<Solver<Mat>> solverCreator_;
     std::shared_ptr<BaseSolver> solver_;
   };
 }
diff --git a/src/amdis/linearalgebra/istl/ISTL_Preconditioner.hpp b/src/amdis/linearalgebra/istl/ISTL_Preconditioner.hpp
index 923e1d00..ca8c16e4 100644
--- a/src/amdis/linearalgebra/istl/ISTL_Preconditioner.hpp
+++ b/src/amdis/linearalgebra/istl/ISTL_Preconditioner.hpp
@@ -102,19 +102,31 @@ namespace AMDiS
       auto ssor = new PreconCreator<Dune::SeqSSOR<Mat, Sol, Rhs>>;
       Map::addCreator("ssor", ssor);
 
+      init_ilu(std::is_arithmetic<typename Dune::FieldTraits<Mat>::field_type>{});
+      init_amg(std::is_same<typename Dune::FieldTraits<Mat>::real_type, double>{});
+
+      auto richardson = new PreconCreator<Dune::Richardson<Sol, Rhs>>;
+      Map::addCreator("richardson", richardson);
+      Map::addCreator("default", richardson);
+    }
+
+    static void init_ilu(std::false_type) {}
+    static void init_ilu(std::true_type)
+    {
       auto ilu = new PreconCreator<Dune::SeqILU<Mat, Sol, Rhs>>;
-      Map::addCreator("ilu", ilu);
-      Map::addCreator("ilu0", ilu);
+      Map::addCreator("ilu", id(ilu));
+      Map::addCreator("ilu0", id(ilu));
+    }
 
+    static void init_amg(std::false_type) {}
+    static void init_amg(std::true_type)
+    {
       auto amg = new AMGPreconCreator<Dune::Amg::AMG, Mat, Sol, Rhs>;
       Map::addCreator("amg", amg);
       auto fastamg = new AMGPreconCreator<Dune::Amg::FastAMG, Mat, Sol, Rhs>;
       Map::addCreator("fastamg", fastamg);
-
-      auto richardson = new PreconCreator<Dune::Richardson<Sol, Rhs>>;
-      Map::addCreator("richardson", richardson);
-      Map::addCreator("default", richardson);
     }
+
   };
 
 } // end namespace AMDiS
diff --git a/src/amdis/linearalgebra/istl/ISTL_Solver.hpp b/src/amdis/linearalgebra/istl/ISTL_Solver.hpp
index 35bcd6bf..700cb1fa 100644
--- a/src/amdis/linearalgebra/istl/ISTL_Solver.hpp
+++ b/src/amdis/linearalgebra/istl/ISTL_Solver.hpp
@@ -143,15 +143,15 @@ namespace AMDiS
     using Matrix = Dune::BCRSMatrix<Block,Alloc>;
     using SolverBase = LinearSolverInterface<Matrix, VectorX, VectorB>;
 
-    template <class ISTLSolver>
+    template <class Solver>
     using SolverCreator
       = typename LinearSolver<Matrix, VectorX, VectorB,
-          ISTLRunner<ISTLSolver, Matrix, VectorX, VectorB>>::Creator;
+          ISTLRunner<Solver, Matrix, VectorX, VectorB>>::Creator;
 
-    template <class ISTLSolver>
+    template <template <class M> class Solver>
     using DirectSolverCreator
       = typename LinearSolver<Matrix, VectorX, VectorB,
-          DirectRunner<ISTLSolver, Matrix, VectorX, VectorB>>::Creator;
+          DirectRunner<Solver, Matrix, VectorX, VectorB>>::Creator;
 
     using Map = CreatorMap<SolverBase>;
 
@@ -175,25 +175,31 @@ namespace AMDiS
       auto fcg = new SolverCreator<Dune::GeneralizedPCGSolver<VectorX>>;
       Map::addCreator("fcg", fcg);
 
+      // default iterative solver
+      Map::addCreator("default", gmres);
+
+      init_direct(std::is_same<typename Dune::FieldTraits<Matrix>::real_type, double>{});
+    }
+
+    static void init_direct(std::false_type) {}
+    static void init_direct(std::true_type)
+    {
 #if HAVE_SUITESPARSE_UMFPACK
-      auto umfpack = new DirectSolverCreator<Dune::UMFPack<Matrix>>;
+      auto umfpack = new DirectSolverCreator<Dune::UMFPack>;
       Map::addCreator("umfpack", umfpack);
 #endif
 
 #if HAVE_SUPERLU
-      auto superlu = new DirectSolverCreator<Dune::SuperLU<Matrix>>;
+      auto superlu = new DirectSolverCreator<Dune::SuperLU>;
       Map::addCreator("superlu", superlu);
 #endif
 
-      // default direct solvers
+    // default direct solvers
 #if HAVE_SUITESPARSE_UMFPACK
       Map::addCreator("direct", umfpack);
 #elif HAVE_SUPERLU
       Map::addCreator("direct", superlu);
 #endif
-
-      // default iterative solver
-      Map::addCreator("default", gmres);
     }
   };
 
diff --git a/src/amdis/linearalgebra/mtl/ITL_Solver.hpp b/src/amdis/linearalgebra/mtl/ITL_Solver.hpp
index 2cd2df2b..5f2946d2 100644
--- a/src/amdis/linearalgebra/mtl/ITL_Solver.hpp
+++ b/src/amdis/linearalgebra/mtl/ITL_Solver.hpp
@@ -453,6 +453,15 @@ namespace AMDiS
       auto preonly = new SolverCreator<preonly_type>;
       Map::addCreator("preonly", preonly);
 
+      // default iterative solver
+      Map::addCreator("default", gmres);
+
+      init_direct(std::is_same<typename Dune::FieldTraits<T>::real_type, double>{});
+    }
+
+    static void init_direct(std::false_type) {}
+    static void init_direct(std::true_type)
+    {
 #ifdef HAVE_UMFPACK
       auto umfpack = new UmfpackSolverCreator;
       Map::addCreator("umfpack", umfpack);
@@ -460,9 +469,6 @@ namespace AMDiS
       // default direct solvers
       Map::addCreator("direct", umfpack);
 #endif
-
-      // default iterative solver
-      Map::addCreator("default", gmres);
     }
   };
 
diff --git a/src/amdis/linearalgebra/mtl/KrylovRunner.hpp b/src/amdis/linearalgebra/mtl/KrylovRunner.hpp
index e51a1a74..2e5c62c1 100644
--- a/src/amdis/linearalgebra/mtl/KrylovRunner.hpp
+++ b/src/amdis/linearalgebra/mtl/KrylovRunner.hpp
@@ -89,9 +89,9 @@ namespace AMDiS
         r -= A * x;
 
       // print information about the solution process
-      itl::cyclic_iteration<double> iter(r, maxIter_, solverInfo.relTolerance(),
-                                                      solverInfo.absTolerance(),
-                                                      printCycle_);
+      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_);
       iter.set_quite(solverInfo.info() == 0);
       iter.suppress_resume(solverInfo.info() == 0);
 
diff --git a/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp b/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp
index f1f382db..01a45ef9 100644
--- a/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp
+++ b/src/amdis/linearalgebra/mtl/UmfpackRunner.hpp
@@ -15,37 +15,49 @@
 namespace AMDiS
 {
   /**
-   * \ingroup Solver
-   * \class AMDiS::UmfpackRunner
-   * \brief \implements RunnerInterface
-   * Wrapper for the external
-   *   [UMFPACK solver](http://faculty.cse.tamu.edu/davis/suitesparse.html)
-   *
-   * This is a direct solver for large sparse matrices.
-   */
+  * \ingroup Solver
+  * \class AMDiS::UmfpackRunner
+  * \brief \implements RunnerInterface
+  * Wrapper for the external
+  *   [UMFPACK solver](http://faculty.cse.tamu.edu/davis/suitesparse.html)
+  *
+  * This is a direct solver for large sparse matrices.
+  */
   template <class Matrix, class Vector>
   class UmfpackRunner;
 
-  template <class Matrix, class Vector>
-  class UmfpackRunnerBase
-      : public RunnerInterface<Matrix, Vector, Vector>
+  template <class T, class Param, class Vector>
+  class UmfpackRunner<mtl::compressed2D<T, Param>, Vector>
+      : public RunnerInterface<mtl::compressed2D<T, Param>, Vector, Vector>
   {
-  protected:
+    using Matrix = mtl::compressed2D<T, Param>;
     using Super = RunnerInterface<Matrix, Vector>;
     using PreconBase = typename Super::PreconBase;
 
-    using FullMatrix = Matrix;
-    using SolverType = mtl::mat::umfpack::solver<FullMatrix>;
+    using SolverType = mtl::mat::umfpack::solver<Matrix>;
 
   public:
     /// Constructor. Reads UMFPACK parameters from initfile
-    UmfpackRunnerBase(std::string const& prefix)
+    UmfpackRunner(std::string const& prefix)
     {
       Parameters::get(prefix + "->store symbolic", storeSymbolic_); // ?
       Parameters::get(prefix + "->symmetric strategy", symmetricStrategy_);
       Parameters::get(prefix + "->alloc init", allocInit_);
     }
 
+    /// Implementation of \ref RunnerInterface::init()
+    void init(Matrix const& matrix) override
+    {
+      try {
+        solver_.reset(new SolverType(matrix, symmetricStrategy_, allocInit_));
+      } catch (mtl::mat::umfpack::error const& e) {
+        error_exit("UMFPACK_ERROR(factorize, {}) = {}", e.code, e.what());
+      }
+    }
+
+    /// Implementation of \ref RunnerInterface::exit()
+    void exit() override {}
+
     /// Implementation of \ref RunnerBase::solve()
     int solve(Matrix const& A, Vector& x, Vector const& b,
               SolverInfo& solverInfo) override
@@ -55,9 +67,9 @@ namespace AMDiS
 
       int code = 0;
       try {
-	      code = (*solver_)(x, b);
+        code = (*solver_)(x, b);
       } catch (mtl::mat::umfpack::error& e) {
-	      error_exit("UMFPACK_ERROR(solve, {}) = {}", e.code, e.what());
+        error_exit("UMFPACK_ERROR(solve, {}) = {}", e.code, e.what());
       }
 
       auto r = Vector(b);
@@ -70,9 +82,6 @@ namespace AMDiS
       return code;
     }
 
-    /// Implementation of \ref RunnerInterface::exit()
-    void exit() override {}
-
   protected:
     std::shared_ptr<SolverType> solver_;
 
@@ -80,33 +89,6 @@ namespace AMDiS
     int symmetricStrategy_ = 0;
     double allocInit_ = 0.7;
   };
-
-
-  // specialization for full-matrices
-  template <class T, class Param, class Vector>
-  class UmfpackRunner<mtl::compressed2D<T, Param>, Vector>
-      : public UmfpackRunnerBase<mtl::compressed2D<T, Param>, Vector>
-  {
-    using FullMatrix = mtl::compressed2D<T, Param>;
-    using Super = UmfpackRunnerBase<FullMatrix, Vector>;
-
-    using SolverType = typename Super::SolverType;
-
-  public:
-    UmfpackRunner(std::string const& prefix)
-      : Super(prefix)
-    {}
-
-    /// Implementation of \ref RunnerInterface::init()
-    void init(FullMatrix const& fullMatrix) override
-    {
-      try {
-        Super::solver_.reset(new SolverType(fullMatrix, Super::symmetricStrategy_, Super::allocInit_));
-      } catch (mtl::mat::umfpack::error const& e) {
-        error_exit("UMFPACK_ERROR(factorize, {}) = {}", e.code, e.what());
-      }
-    }
-  };
 }
 
 #endif // HAVE_UMFPACK
diff --git a/src/amdis/linearalgebra/mtl/itl/details.hpp b/src/amdis/linearalgebra/mtl/itl/details.hpp
index 1d199bc3..310b19fc 100644
--- a/src/amdis/linearalgebra/mtl/itl/details.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/details.hpp
@@ -49,7 +49,8 @@ namespace itl
     //       }
     //     }
 
-    inline void rotmat(const double& a, const double& b , double& c, double& s)
+    template <class T>
+    inline void rotmat(const T& a, const T& b , T& c, T& s)
     {
       using std::abs;
       using std::sqrt;
@@ -60,13 +61,13 @@ namespace itl
       }
       else if ( abs(b) > abs(a) )
       {
-        double temp = a / b;
+        T temp = a / b;
         s = 1.0 / sqrt( 1.0 + temp*temp );
         c = temp * s;
       }
       else
       {
-        double temp = b / a;
+        T temp = b / a;
         c = 1.0 / sqrt( 1.0 + temp*temp );
         s = temp * c;
       }
diff --git a/src/amdis/linearalgebra/mtl/itl/fgmres.hpp b/src/amdis/linearalgebra/mtl/itl/fgmres.hpp
index 101ff799..21e4216b 100644
--- a/src/amdis/linearalgebra/mtl/itl/fgmres.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/fgmres.hpp
@@ -139,7 +139,8 @@ namespace itl
       H[k][k] = cs[k]*H[k][k] + sn[k]*H[k+1][k];
       H[k+1][k] = 0.0;
 
-      rho = std::abs(s[k+1]);
+      using std::abs;
+      rho = abs(s[k+1]);
     }
 
     // reduce k, to get regular matrix
diff --git a/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp b/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp
index 2609cda1..2f066ee7 100644
--- a/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/fgmres_householder.hpp
@@ -152,7 +152,8 @@ namespace itl
       irange range(num_rows(H));
       H[iall][k] = w[range];
 
-      rho = std::abs(s[k+1]);
+      using std::abs;
+      rho = abs(s[k+1]);
     }
 
     // reduce k, to get regular matrix
diff --git a/src/amdis/linearalgebra/mtl/itl/gmres2.hpp b/src/amdis/linearalgebra/mtl/itl/gmres2.hpp
index e4180602..c65c7afe 100644
--- a/src/amdis/linearalgebra/mtl/itl/gmres2.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/gmres2.hpp
@@ -140,7 +140,8 @@ namespace itl
       H[k][k] = cs[k]*H[k][k] + sn[k]*H[k+1][k];
       H[k+1][k] = 0.0;
 
-      rho = std::abs(s[k+1]);
+      using std::abs;
+      rho = abs(s[k+1]);
     }
 
     // reduce k, to get regular matrix
diff --git a/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp b/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp
index c8bdb836..eea75969 100644
--- a/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp
+++ b/src/amdis/linearalgebra/mtl/itl/gmres_householder.hpp
@@ -148,7 +148,8 @@ namespace itl
       irange range(num_rows(H));
       H[iall][k] = w[range];
 
-      rho = std::abs(s[k+1]) / bnrm2;
+      using std::abs;
+      rho = abs(s[k+1]) / bnrm2;
     }
 
     // reduce k, to get regular matrix
diff --git a/src/amdis/localoperators/ZeroOrderTestTrialvec.hpp b/src/amdis/localoperators/ZeroOrderTestTrialvec.hpp
index ef7360dd..95e7761f 100644
--- a/src/amdis/localoperators/ZeroOrderTestTrialvec.hpp
+++ b/src/amdis/localoperators/ZeroOrderTestTrialvec.hpp
@@ -42,7 +42,7 @@ namespace AMDiS
         "RN must be Leaf-Node and CN must be a Power-Node.");
 
       static const std::size_t CHILDREN = CN::CHILDREN;
-      static_assert( std::is_same<typename GridFct::Range, Dune::FieldVector<double, int(CHILDREN)>>::value, "" );
+      static_assert( Size_v<typename GridFct::Range> == CHILDREN, "" );
 
       auto const& quad = this->getQuadratureRule(contextGeo.type(), rowNode, colNode);
       auto const& rowLocalFE = rowNode.finiteElement();
diff --git a/src/amdis/localoperators/ZeroOrderTestvecTrialvec.hpp b/src/amdis/localoperators/ZeroOrderTestvecTrialvec.hpp
index dab0476f..2d04c6f3 100644
--- a/src/amdis/localoperators/ZeroOrderTestvecTrialvec.hpp
+++ b/src/amdis/localoperators/ZeroOrderTestvecTrialvec.hpp
@@ -154,7 +154,7 @@ namespace AMDiS
                                   Mat& elementMatrix, tag::matrix)
     {
       static const std::size_t CHILDREN = RN::CHILDREN;
-      static_assert( std::is_same<expr_value_type, Dune::FieldMatrix<double, int(CHILDREN), int(CHILDREN)>>::value, "" );
+      static_assert(Rows_v<expr_value_type> == CHILDREN && Cols_v<expr_value_type> == CHILDREN, "" );
 
       auto const& rowLocalFE = rowNode.child(0).finiteElement();
       auto const& colLocalFE = colNode.child(0).finiteElement();
@@ -170,7 +170,7 @@ namespace AMDiS
 
         // The multiplicative factor in the integral transformation formula
         const auto factor = contextGeo.integrationElement(quad[iq].position()) * quad[iq].weight();
-        const Dune::FieldMatrix<double, int(CHILDREN), int(CHILDREN)> exprValue = Super::coefficient(local);
+        const auto exprValue = Super::coefficient(local);
 
         auto const& rowShapeValues = rowShapeValuesCache[iq];
         auto const& colShapeValues = colShapeValuesCache[iq];
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 51040f8f..51f2e08c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -49,6 +49,9 @@ dune_add_test(SOURCES OperationsTest.cpp
 dune_add_test(SOURCES OperatorsTest.cpp
   LINK_LIBRARIES amdis)
 
+dune_add_test(SOURCES ProblemStatTest.cpp
+  LINK_LIBRARIES amdis)
+
 dune_add_test(SOURCES RangeTypeTest.cpp
   LINK_LIBRARIES amdis)
 
diff --git a/test/ProblemStatTest.cpp b/test/ProblemStatTest.cpp
new file mode 100644
index 00000000..9ad40cb9
--- /dev/null
+++ b/test/ProblemStatTest.cpp
@@ -0,0 +1,36 @@
+#include <amdis/AMDiS.hpp>
+#include <amdis/LocalOperators.hpp>
+#include <amdis/ProblemStat.hpp>
+
+using namespace AMDiS;
+
+using Grid = Dune::YaspGrid<2>;
+
+template <class T>
+struct Param
+    : DefaultBasisCreator<Grid, Impl::LagrangePreBasisCreator<1,1>, T>
+{};
+
+template <class T>
+void test()
+{
+  ProblemStat<Param<T>> prob("ellipt");
+  prob.initialize(INIT_ALL);
+  prob.boundaryManager()->setBoxBoundary({1,1,2,2});
+
+  prob.addMatrixOperator(sot(T(1)), 0, 0);
+  prob.addVectorOperator(zot(T(1)), 0);
+  prob.addDirichletBC(BoundaryType{1}, 0,0, T(0));
+}
+
+int main(int argc, char** argv)
+{
+  AMDiS::init(argc, argv);
+
+  test<float>();
+  test<double>();
+  test<long double>();
+
+  AMDiS::finalize();
+  return 0;
+}
-- 
GitLab