From d4dd632072981ba32c8bf7aded97ea4675a39ac2 Mon Sep 17 00:00:00 2001
From: Uli Sack <usack@math.fu-berlin.de>
Date: Wed, 25 Jan 2012 09:45:09 +0000
Subject: [PATCH] added specialization for MatrixType=SumOperator<SparseMatrix,
 LowRankMatrix>

[[Imported from SVN: r5474]]
---
 .../compressedmultigridtransfer.hh            | 154 ++++++++++++++++++
 1 file changed, 154 insertions(+)

diff --git a/dune/solvers/transferoperators/compressedmultigridtransfer.hh b/dune/solvers/transferoperators/compressedmultigridtransfer.hh
index 37b3ea74..cce655cb 100644
--- a/dune/solvers/transferoperators/compressedmultigridtransfer.hh
+++ b/dune/solvers/transferoperators/compressedmultigridtransfer.hh
@@ -5,6 +5,9 @@
 #include <dune/common/fmatrix.hh>
 #include <dune/common/bitsetvector.hh>
 
+#include <dune/solvers/operators/sumoperator.hh>
+#include <dune/solvers/common/staticmatrixtools.hh>
+
 #include "genericmultigridtransfer.hh"
 #include "multigridtransfer.hh"
 
@@ -142,6 +145,157 @@ public:
 
 
 
+protected:
+
+    TransferOperatorType* matrix_;
+    bool matrixInternallyAllocated;
+
+};
+
+template<
+    class VectorType,
+    class BitVectorType,
+    class SparseMatrixType,
+    class LowRankMatrixType >
+class CompressedMultigridTransfer<VectorType, BitVectorType, SumOperator<SparseMatrixType, LowRankMatrixType> > :
+    public MultigridTransfer<VectorType, BitVectorType, SumOperator<SparseMatrixType,LowRankMatrixType> >
+{
+
+    enum {blocksize = VectorType::block_type::dimension};
+
+    typedef typename VectorType::field_type field_type;
+
+public:
+
+    typedef SumOperator<SparseMatrixType, LowRankMatrixType> OperatorType;
+
+    typedef Dune::BCRSMatrix<Dune::FieldMatrix<field_type,1,1> > TransferOperatorType;
+
+    CompressedMultigridTransfer()
+    {
+        matrix_ = new TransferOperatorType;
+        matrixInternallyAllocated = true;
+    }
+
+    virtual ~CompressedMultigridTransfer()
+    {
+        if (matrixInternallyAllocated)
+            delete matrix_;
+    }
+
+
+    /** \brief Sets up the operator between two P1 spaces
+     *
+     * \param grid The grid
+     * \param cL The coarse grid level
+     * \param fL The fine grid level
+     */
+    template <class GridType>
+    void setup(const GridType& grid, int cL, int fL)
+    {
+        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(*matrix_, grid, cL, fL);
+    }
+
+
+    /** \brief Restrict a function from the fine onto the coarse grid
+     */
+    virtual void restrict(const VectorType& f, VectorType &t) const
+    {
+        GenericMultigridTransfer::restrict(*matrix_, f, t, -1);
+    }
+
+
+    /** \brief Restrict a bitfield from the fine onto the coarse grid
+     */
+    virtual void restrictScalarBitField(const Dune::BitSetVector<1>& f, Dune::BitSetVector<1>& t) const
+    {
+        GenericMultigridTransfer::restrictScalarBitField(*matrix_, f, t, -1);
+    }
+
+
+    /** \brief Restrict a vector valued bitfield from the fine onto the coarse grid
+     */
+    virtual void restrict(const BitVectorType& f, BitVectorType& t) const
+    {
+        GenericMultigridTransfer::restrictBitField(*matrix_, f, t, -1);
+    }
+
+
+    /** \brief Restrict a vector valued bitfield from the fine onto the coarse grid
+     * Fine bits only influence their father bits
+     */
+    virtual void restrictToFathers(const BitVectorType& f, BitVectorType& t) const
+    {
+        GenericMultigridTransfer::restrictBitFieldToFathers(*matrix_, f, t, -1);
+    }
+
+
+    /** \brief Prolong a function from the coarse onto the fine grid
+     */
+    virtual void prolong(const VectorType& f, VectorType &t) const
+    {
+        GenericMultigridTransfer::prolong(*matrix_, f, t, -1);
+    }
+
+
+    /** \brief Galerkin assemble a coarse stiffness matrix
+     */
+    virtual void galerkinRestrict(const OperatorType& fineMat, OperatorType& coarseMat) const
+    {
+        GenericMultigridTransfer::galerkinRestrict(*matrix_, fineMat.sparseMatrix(), coarseMat.sparseMatrix(), -1);
+
+        const typename LowRankMatrixType::LowRankFactorType& lr_fine_factor(fineMat.lowRankMatrix().lowRankFactor());
+        typename LowRankMatrixType::LowRankFactorType& lr_coarse_factor(coarseMat.lowRankMatrix().lowRankFactor());
+
+        lr_coarse_factor = 0;
+
+        for (size_t i=0; i<matrix_->N(); ++i)
+        {
+            typename TransferOperatorType::ColIterator j_it  = (*matrix_)[i].begin();
+            typename TransferOperatorType::ColIterator j_end = (*matrix_)[i].end();
+
+            for (; j_it!=j_end; ++j_it)
+            {
+                size_t j = j_it.index();
+
+                for (size_t k=0; k<lr_fine_factor.N(); ++k)
+                    StaticMatrix::axpy(lr_coarse_factor[k][j], *j_it, lr_fine_factor[k][i]);
+            }
+        }
+    }
+
+
+    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix   
+    *
+    * Set occupation of Galerkin restricted coarse matrix. Call this one before
+    * galerkinRestrict to ensure all non-zeroes are present
+    * \param fineMat The fine level matrix
+    * \param coarseMat The coarse level matrix
+    */
+    virtual void galerkinRestrictSetOccupation(const OperatorType& fineMat, OperatorType& coarseMat) const
+    {
+        GenericMultigridTransfer::galerkinRestrictSetOccupation(*matrix_, fineMat.sparseMatrix(), coarseMat.sparseMatrix(), -1);
+
+        coarseMat.lowRankMatrix().lowRankFactor().setSize(fineMat.lowRankMatrix().lowRankFactor().N(), matrix_->M());
+    }
+
+
+    /** \brief Direct access to the operator matrix, if you absolutely want it! */
+    const TransferOperatorType& getMatrix() const {
+        return *matrix_;
+    }
+
+    /** \brief Set matrix! */
+    void setMatrix(TransferOperatorType& matrix)
+    {
+        if (matrixInternallyAllocated)
+            delete matrix_;
+        matrixInternallyAllocated = false;
+        matrix_ = &matrix;
+    }
+
+
+
 protected:
 
     TransferOperatorType* matrix_;
-- 
GitLab