From 2e76b22626f8a8c95bacce6d3605d96fc8738f9c Mon Sep 17 00:00:00 2001
From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de>
Date: Fri, 17 Feb 2017 07:56:44 +0100
Subject: [PATCH] [staggeredGrid][linear] Remove directSolverBackend class

* Convert matrix (if required) in newtoncontroller, as done in
  mixeddimension
---
 dumux/implicit/staggered/newtoncontroller.hh | 212 +++++++++++++++----
 dumux/implicit/staggered/propertydefaults.hh |   6 +-
 dumux/linear/directsolverbackend.hh          | 200 -----------------
 3 files changed, 173 insertions(+), 245 deletions(-)
 delete mode 100644 dumux/linear/directsolverbackend.hh

diff --git a/dumux/implicit/staggered/newtoncontroller.hh b/dumux/implicit/staggered/newtoncontroller.hh
index 3425808ecb..2d5fdc22d2 100644
--- a/dumux/implicit/staggered/newtoncontroller.hh
+++ b/dumux/implicit/staggered/newtoncontroller.hh
@@ -30,9 +30,21 @@
 #include "properties.hh"
 
 #include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/linear/linearsolveracceptsmultitypematrix.hh>
 #include "newtonconvergencewriter.hh"
 
 namespace Dumux {
+
+namespace Properties
+{
+    SET_PROP(StaggeredModel, LinearSolverBlockSize)
+    {
+        // LinearSolverAcceptsMultiTypeMatrix<T>::value
+        // TODO: make somehow dependend? or only relevant for direct solvers?
+    public:
+        static constexpr auto value = 1;
+    };
+}
 /*!
  * \ingroup PNMModel
  * \brief A PNM specific controller for the newton solver.
@@ -55,77 +67,195 @@ class StaggeredNewtonController : public NewtonController<TypeTag>
     typename DofTypeIndices::CellCenterIdx cellCenterIdx;
     typename DofTypeIndices::FaceIdx faceIdx;
 
+    enum {
+        numEqCellCenter = GET_PROP_VALUE(TypeTag, NumEqCellCenter),
+        numEqFace = GET_PROP_VALUE(TypeTag, NumEqFace)
+    };
+
 public:
     StaggeredNewtonController(const Problem &problem)
         : ParentType(problem)
     {}
 
-        /*!
+    /*!
      * \brief Solve the linear system of equations \f$\mathbf{A}x - b = 0\f$.
      *
      * Throws Dumux::NumericalProblem if the linear solver didn't
      * converge.
      *
+     * If the linear solver doesn't accept multitype matrices we copy the matrix
+     * into a 1x1 block BCRS matrix for solving.
+     *
      * \param A The matrix of the linear system of equations
      * \param x The vector which solves the linear system
      * \param b The right hand side of the linear system
      */
-    void newtonSolveLinear(JacobianMatrix &A,
-                           SolutionVector &x,
-                           SolutionVector &b)
+    template<typename T = TypeTag>
+    typename std::enable_if<!LinearSolverAcceptsMultiTypeMatrix<T>::value, void>::type
+    newtonSolveLinear(JacobianMatrix &A,
+                      SolutionVector &x,
+                      SolutionVector &b)
     {
-        try {
+        try
+        {
             if (this->numSteps_ == 0)
-            {
-                Scalar norm2 = b.two_norm2();
-                if (this->gridView_().comm().size() > 1)
-                    norm2 = this->gridView_().comm().sum(norm2);
+                this->initialResidual_ = b.two_norm();
 
-                this->initialResidual_ = std::sqrt(norm2);
-            }
+            // copy the matrix and the vector to types the IterativeSolverBackend can handle
+            using MatrixBlock = typename Dune::FieldMatrix<Scalar, 1, 1>;
+            using SparseMatrix = typename Dune::BCRSMatrix<MatrixBlock>;
 
-            int converged = this->linearSolver_.solve(A, x, b);
+            // get the new matrix sizes
+            std::size_t numRows = numEqCellCenter*A[cellCenterIdx][cellCenterIdx].N() + numEqFace*A[faceIdx][cellCenterIdx].N();
+            std::size_t numCols = numEqCellCenter*A[cellCenterIdx][cellCenterIdx].M() + numEqFace*A[cellCenterIdx][faceIdx].M();
 
-            // make sure all processes converged
-            int convergedRemote = converged;
-            if (this->gridView_().comm().size() > 1)
-                convergedRemote = this->gridView_().comm().min(converged);
+            // check matrix sizes
+            assert(A[cellCenterIdx][cellCenterIdx].N() == A[cellCenterIdx][faceIdx].N());
+            assert(A[faceIdx][cellCenterIdx].N() == A[faceIdx][faceIdx].N());
+            assert(numRows == numCols);
 
-            if (!converged) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge");
-            }
-            else if (!convergedRemote) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge on a remote process");
-            }
-        }
-        catch (Dune::MatrixBlockError e) {
-            // make sure all processes converged
-            int converged = 0;
-            if (this->gridView_().comm().size() > 1)
-                converged = this->gridView_().comm().min(converged);
+            // create the bcrs matrix the IterativeSolver backend can handle
+            auto M = SparseMatrix(numRows, numCols, SparseMatrix::random);
+
+            // set the rowsizes
+            // A11 and A12
+            for (auto row = A[cellCenterIdx][cellCenterIdx].begin(); row != A[cellCenterIdx][cellCenterIdx].end(); ++row)
+                for (std::size_t i = 0; i < numEqCellCenter; ++i)
+                    M.setrowsize(numEqCellCenter*row.index() + i, row->size()*numEqCellCenter);
+            for (auto row = A[cellCenterIdx][faceIdx].begin(); row != A[cellCenterIdx][faceIdx].end(); ++row)
+                for (std::size_t i = 0; i < numEqCellCenter; ++i)
+                    M.setrowsize(numEqCellCenter*row.index() + i, M.getrowsize(numEqCellCenter*row.index() + i) + row->size()*numEqFace);
+            // A21 and A22
+            for (auto row = A[faceIdx][cellCenterIdx].begin(); row != A[faceIdx][cellCenterIdx].end(); ++row)
+                for (std::size_t i = 0; i < numEqFace; ++i)
+                    M.setrowsize(numEqFace*row.index() + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, row->size()*numEqCellCenter);
+            for (auto row = A[faceIdx][faceIdx].begin(); row != A[faceIdx][faceIdx].end(); ++row)
+                for (std::size_t i = 0; i < numEqFace; ++i)
+                    M.setrowsize(numEqFace*row.index() + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, M.getrowsize(numEqFace*row.index() + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter) + row->size()*numEqFace);
+            M.endrowsizes();
+
+            // set the indices
+            for (auto row = A[cellCenterIdx][cellCenterIdx].begin(); row != A[cellCenterIdx][cellCenterIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqCellCenter; ++i)
+                        for (std::size_t j = 0; j < numEqCellCenter; ++j)
+                            M.addindex(row.index()*numEqCellCenter + i, col.index()*numEqCellCenter + j);
+
+            for (auto row = A[cellCenterIdx][faceIdx].begin(); row != A[cellCenterIdx][faceIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqCellCenter; ++i)
+                        for (std::size_t j = 0; j < numEqFace; ++j)
+                            M.addindex(row.index()*numEqCellCenter + i, col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter);
+
+            for (auto row = A[faceIdx][cellCenterIdx].begin(); row != A[faceIdx][cellCenterIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqFace; ++i)
+                        for (std::size_t j = 0; j < numEqCellCenter; ++j)
+                            M.addindex(row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, col.index()*numEqCellCenter + j);
+
+            for (auto row = A[faceIdx][faceIdx].begin(); row != A[faceIdx][faceIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqFace; ++i)
+                        for (std::size_t j = 0; j < numEqFace; ++j)
+                            M.addindex(row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter);
+            M.endindices();
+
+            // copy values
+            for (auto row = A[cellCenterIdx][cellCenterIdx].begin(); row != A[cellCenterIdx][cellCenterIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqCellCenter; ++i)
+                        for (std::size_t j = 0; j < numEqCellCenter; ++j)
+                            M[row.index()*numEqCellCenter + i][col.index()*numEqCellCenter + j] = A[cellCenterIdx][cellCenterIdx][row.index()][col.index()][i][j];
+
+            for (auto row = A[cellCenterIdx][faceIdx].begin(); row != A[cellCenterIdx][faceIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqCellCenter; ++i)
+                        for (std::size_t j = 0; j < numEqFace; ++j)
+                            M[row.index()*numEqCellCenter + i][col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter] = A[cellCenterIdx][faceIdx][row.index()][col.index()][i][j];
+
+            for (auto row = A[faceIdx][cellCenterIdx].begin(); row != A[faceIdx][cellCenterIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqFace; ++i)
+                        for (std::size_t j = 0; j < numEqCellCenter; ++j)
+                            M[row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter][col.index()*numEqCellCenter + j] = A[faceIdx][cellCenterIdx][row.index()][col.index()][i][j];
+
+            for (auto row = A[faceIdx][faceIdx].begin(); row != A[faceIdx][faceIdx].end(); ++row)
+                for (auto col = row->begin(); col != row->end(); ++col)
+                    for (std::size_t i = 0; i < numEqFace; ++i)
+                        for (std::size_t j = 0; j < numEqFace; ++j)
+                            M[row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter][col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter] = A[faceIdx][faceIdx][row.index()][col.index()][i][j];
+
+            // create the vector the IterativeSolver backend can handle
+            using VectorBlock = typename Dune::FieldVector<Scalar, 1>;
+            using BlockVector = typename Dune::BlockVector<VectorBlock>;
+
+            BlockVector y, bTmp;
+            y.resize(numRows);
+            bTmp.resize(numCols);
+            for (std::size_t i = 0; i < b[cellCenterIdx].N(); ++i)
+                for (std::size_t j = 0; j < numEqCellCenter; ++j)
+                    bTmp[i*numEqCellCenter + j] = b[cellCenterIdx][i][j];
+            for (std::size_t i = 0; i < b[faceIdx].N(); ++i)
+                for (std::size_t j = 0; j < numEqFace; ++j)
+                    bTmp[i*numEqFace + j + b[cellCenterIdx].N()*numEqCellCenter] = b[faceIdx][i][j];
+
+            // solve
+            bool converged = this->linearSolver_.solve(M, y, bTmp);
 
+            // copy back the result y into x
+            for (std::size_t i = 0; i < x[cellCenterIdx].N(); ++i)
+                for (std::size_t j = 0; j < numEqCellCenter; ++j)
+                    x[cellCenterIdx][i][j] = y[i*numEqCellCenter + j];
+            for (std::size_t i = 0; i < x[faceIdx].N(); ++i)
+                for (std::size_t j = 0; j < numEqFace; ++j)
+                    x[faceIdx][i][j] = y[i*numEqFace + j + x[cellCenterIdx].N()*numEqCellCenter];
+
+            if (!converged)
+                DUNE_THROW(NumericalProblem, "Linear solver did not converge");
+        }
+        catch (const Dune::Exception &e)
+        {
             Dumux::NumericalProblem p;
-            std::string msg;
-            std::ostringstream ms(msg);
-//             ms << e.what() << "M=" << A[e.r][e.c];
-//             p.message(ms.str());
-//             throw p;
+            p.message(e.what());
+            throw p;
         }
-        catch (const Dune::Exception &e) {
-            // make sure all processes converged
-            int converged = 0;
-            if (this->gridView_().comm().size() > 1)
-                converged = this->gridView_().comm().min(converged);
+    }
 
+    /*!
+     * \brief Solve the linear system of equations \f$\mathbf{A}x - b = 0\f$.
+     *
+     * Throws Dumux::NumericalProblem if the linear solver didn't
+     * converge.
+     *
+     * \param A The matrix of the linear system of equations
+     * \param x The vector which solves the linear system
+     * \param b The right hand side of the linear system
+     */
+    template<typename T = TypeTag>
+    typename std::enable_if<LinearSolverAcceptsMultiTypeMatrix<T>::value, void>::type
+    newtonSolveLinear(JacobianMatrix &A,
+                      SolutionVector &x,
+                      SolutionVector &b)
+    {
+        try
+        {
+            if (this->numSteps_ == 0)
+                this->initialResidual_ = b.two_norm();
+
+            bool converged = this->linearSolver_.solve(A, x, b);
+
+            if (!converged)
+                DUNE_THROW(NumericalProblem, "Linear solver did not converge");
+        }
+        catch (const Dune::Exception &e)
+        {
             Dumux::NumericalProblem p;
             p.message(e.what());
             throw p;
         }
     }
 
-        /*!
+     /*!
      * \brief Update the current solution with a delta vector.
      *
      * The error estimates required for the newtonConverged() and
diff --git a/dumux/implicit/staggered/propertydefaults.hh b/dumux/implicit/staggered/propertydefaults.hh
index 57dca34ef3..8b6caf0818 100644
--- a/dumux/implicit/staggered/propertydefaults.hh
+++ b/dumux/implicit/staggered/propertydefaults.hh
@@ -47,9 +47,7 @@
 #include <dune/istl/multitypeblockvector.hh>
 #include <dune/istl/multitypeblockmatrix.hh>
 
-#include <dumux/linear/directsolverbackend.hh>
-
-
+#include <dumux/linear/seqsolverbackend.hh>
 
 #include "assembler.hh"
 #include "localresidual.hh"
@@ -213,7 +211,7 @@ SET_PROP(StaggeredModel, DofTypeIndices)
 
 //! set default solver
 // SET_TYPE_PROP(StaggeredModel, LinearSolver, Dumux::GSBiCGSTABBackend<TypeTag>);
-SET_TYPE_PROP(StaggeredModel, LinearSolver, Dumux::StaggeredGridUMFPackBackend<TypeTag>);
+SET_TYPE_PROP(StaggeredModel, LinearSolver, Dumux::UMFPackBackend<TypeTag>);
 
 //! set the block level to 2, suitable for e.g. the Dune::MultiTypeBlockMatrix
 SET_INT_PROP(StaggeredModel, LinearSolverPreconditionerBlockLevel, 2);
diff --git a/dumux/linear/directsolverbackend.hh b/dumux/linear/directsolverbackend.hh
deleted file mode 100644
index b5b2f90b7a..0000000000
--- a/dumux/linear/directsolverbackend.hh
+++ /dev/null
@@ -1,200 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \brief Dumux multidimension direct solver backend
- */
-#ifndef DUMUX_STAGGEREDGRID_DIRECT_SOLVER_BACKEND_HH
-#define DUMUX_STAGGEREDGRID_DIRECT_SOLVER_BACKEND_HH
-
-//#include <dune/istl/superlu.hh>
-#include <dune/istl/umfpack.hh>
-
-#include <dumux/common/parameters.hh>
-#include <dumux/common/basicproperties.hh>
-#include <dumux/linear/linearsolverproperties.hh>
-
-namespace Dumux {
-
-#if HAVE_UMFPACK
-/*! \brief UMFPackBackend for MultiTypeMatrices
- *         Copies the coupled matrix into a single BCRSMatrix.
- *         Very slow!! Only wise to use for verification purposes.
- */
-template <class TypeTag>
-class StaggeredGridUMFPackBackend
-{
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-
-    enum {
-        numEqCellCenter = GET_PROP_VALUE(TypeTag, NumEqCellCenter),
-        numEqFace = GET_PROP_VALUE(TypeTag, NumEqFace)
-    };
-
-    typename GET_PROP(TypeTag, DofTypeIndices)::CellCenterIdx cellCenterIdx;
-    typename GET_PROP(TypeTag, DofTypeIndices)::FaceIdx faceIdx;
-
-public:
-
-  StaggeredGridUMFPackBackend(const Problem& problem) {}
-
-  template<class Matrix, class Vector>
-  bool solve(const Matrix& A, Vector& x, const Vector& b)
-  {
-    // copy the matrix and the vector to types the UMFPackBackend can handle
-    using MatrixBlock = typename Dune::FieldMatrix<Scalar, 1, 1>;
-    using SparseMatrix = typename Dune::BCRSMatrix<MatrixBlock>;
-
-    // get the new matrix sizes
-    std::size_t numRows = numEqCellCenter*A[cellCenterIdx][cellCenterIdx].N() + numEqFace*A[faceIdx][cellCenterIdx].N();
-    std::size_t numCols = numEqCellCenter*A[cellCenterIdx][cellCenterIdx].M() + numEqFace*A[cellCenterIdx][faceIdx].M();
-
-    // check matrix sizes
-    assert(A[cellCenterIdx][cellCenterIdx].N() == A[cellCenterIdx][faceIdx].N());
-    assert(A[faceIdx][cellCenterIdx].N() == A[faceIdx][faceIdx].N());
-    assert(numRows == numCols);
-
-    // create the bcrs matrix the UMFPack backend can handle
-    auto M = SparseMatrix(numRows, numCols, SparseMatrix::random);
-
-    // set the rowsizes
-    // A11 and A12
-    for (auto row = A[cellCenterIdx][cellCenterIdx].begin(); row != A[cellCenterIdx][cellCenterIdx].end(); ++row)
-        for (std::size_t i = 0; i < numEqCellCenter; ++i)
-            M.setrowsize(numEqCellCenter*row.index() + i, row->size()*numEqCellCenter);
-    for (auto row = A[cellCenterIdx][faceIdx].begin(); row != A[cellCenterIdx][faceIdx].end(); ++row)
-        for (std::size_t i = 0; i < numEqCellCenter; ++i)
-            M.setrowsize(numEqCellCenter*row.index() + i, M.getrowsize(numEqCellCenter*row.index() + i) + row->size()*numEqFace);
-    // A21 and A22
-    for (auto row = A[faceIdx][cellCenterIdx].begin(); row != A[faceIdx][cellCenterIdx].end(); ++row)
-        for (std::size_t i = 0; i < numEqFace; ++i)
-            M.setrowsize(numEqFace*row.index() + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, row->size()*numEqCellCenter);
-    for (auto row = A[faceIdx][faceIdx].begin(); row != A[faceIdx][faceIdx].end(); ++row)
-        for (std::size_t i = 0; i < numEqFace; ++i)
-            M.setrowsize(numEqFace*row.index() + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, M.getrowsize(numEqFace*row.index() + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter) + row->size()*numEqFace);
-    M.endrowsizes();
-
-    // set the indices
-    for (auto row = A[cellCenterIdx][cellCenterIdx].begin(); row != A[cellCenterIdx][cellCenterIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqCellCenter; ++i)
-                for (std::size_t j = 0; j < numEqCellCenter; ++j)
-                    M.addindex(row.index()*numEqCellCenter + i, col.index()*numEqCellCenter + j);
-
-    for (auto row = A[cellCenterIdx][faceIdx].begin(); row != A[cellCenterIdx][faceIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqCellCenter; ++i)
-                for (std::size_t j = 0; j < numEqFace; ++j)
-                    M.addindex(row.index()*numEqCellCenter + i, col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter);
-
-    for (auto row = A[faceIdx][cellCenterIdx].begin(); row != A[faceIdx][cellCenterIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqFace; ++i)
-                for (std::size_t j = 0; j < numEqCellCenter; ++j)
-                    M.addindex(row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, col.index()*numEqCellCenter + j);
-
-    for (auto row = A[faceIdx][faceIdx].begin(); row != A[faceIdx][faceIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqFace; ++i)
-                for (std::size_t j = 0; j < numEqFace; ++j)
-                    M.addindex(row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter, col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter);
-    M.endindices();
-
-    // copy values
-    for (auto row = A[cellCenterIdx][cellCenterIdx].begin(); row != A[cellCenterIdx][cellCenterIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqCellCenter; ++i)
-                for (std::size_t j = 0; j < numEqCellCenter; ++j)
-                    M[row.index()*numEqCellCenter + i][col.index()*numEqCellCenter + j] = A[cellCenterIdx][cellCenterIdx][row.index()][col.index()][i][j];
-
-    for (auto row = A[cellCenterIdx][faceIdx].begin(); row != A[cellCenterIdx][faceIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqCellCenter; ++i)
-                for (std::size_t j = 0; j < numEqFace; ++j)
-                    M[row.index()*numEqCellCenter + i][col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter] = A[cellCenterIdx][faceIdx][row.index()][col.index()][i][j];
-
-    for (auto row = A[faceIdx][cellCenterIdx].begin(); row != A[faceIdx][cellCenterIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqFace; ++i)
-                for (std::size_t j = 0; j < numEqCellCenter; ++j)
-                    M[row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter][col.index()*numEqCellCenter + j] = A[faceIdx][cellCenterIdx][row.index()][col.index()][i][j];
-
-    for (auto row = A[faceIdx][faceIdx].begin(); row != A[faceIdx][faceIdx].end(); ++row)
-        for (auto col = row->begin(); col != row->end(); ++col)
-            for (std::size_t i = 0; i < numEqFace; ++i)
-                for (std::size_t j = 0; j < numEqFace; ++j)
-                    M[row.index()*numEqFace + i + A[cellCenterIdx][cellCenterIdx].N()*numEqCellCenter][col.index()*numEqFace + j + A[cellCenterIdx][cellCenterIdx].M()*numEqCellCenter] = A[faceIdx][faceIdx][row.index()][col.index()][i][j];
-
-    // create the vector the UMFPack backend can handle
-    using VectorBlock = typename Dune::FieldVector<Scalar, 1>;
-    using BlockVector = typename Dune::BlockVector<VectorBlock>;
-
-    BlockVector y, bTmp;
-    y.resize(numRows);
-    bTmp.resize(numCols);
-    for (std::size_t i = 0; i < b[cellCenterIdx].N(); ++i)
-        for (std::size_t j = 0; j < numEqCellCenter; ++j)
-            bTmp[i*numEqCellCenter + j] = b[cellCenterIdx][i][j];
-    for (std::size_t i = 0; i < b[faceIdx].N(); ++i)
-        for (std::size_t j = 0; j < numEqFace; ++j)
-            bTmp[i*numEqFace + j + b[cellCenterIdx].N()*numEqCellCenter] = b[faceIdx][i][j];
-
-    int verbosity = GET_PARAM_FROM_GROUP(TypeTag, int, LinearSolver, Verbosity);
-    Dune::UMFPack<SparseMatrix> solver(M, verbosity > 0);
-
-    solver.apply(y, bTmp, result_);
-
-    std::size_t size = y.size();
-    for (std::size_t i = 0; i < size; i++)
-    {
-        if (std::isnan(y[i][0]) || std::isinf(y[i][0]))
-        {
-            result_.converged = false;
-            break;
-        }
-    }
-
-    // copy back the result y into x
-    for (std::size_t i = 0; i < x[cellCenterIdx].N(); ++i)
-        for (std::size_t j = 0; j < numEqCellCenter; ++j)
-            x[cellCenterIdx][i][j] = y[i*numEqCellCenter + j];
-    for (std::size_t i = 0; i < x[faceIdx].N(); ++i)
-        for (std::size_t j = 0; j < numEqFace; ++j)
-            x[faceIdx][i][j] = y[i*numEqFace + j + x[cellCenterIdx].N()*numEqCellCenter];
-
-//     printmatrix(std::cout,M, "umfpack", "");
-
-    return result_.converged;
-  }
-
-  const Dune::InverseOperatorResult& result() const
-  {
-    return result_;
-  }
-
-private:
-  Dune::InverseOperatorResult result_;
-};
-
-#endif // HAVE_UMFPACK
-
-} // end namespace Dumux
-
-#endif
-- 
GitLab