From 24bf4a2be383f8b787b968ae121953f821acc9ae Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Wed, 16 Nov 2011 16:59:20 +0000
Subject: [PATCH] Quick prototype implementation of a multigrid transfer
 operator from a Pk-basis to a P1-basis.

Doesn't work beyond P2 yet, I'll fix that in a second.

Should eventually go into dune-solvers.

[[Imported from SVN: r8218]]
---
 dune/gfe/Makefile.am         |   1 +
 dune/gfe/pktop1mgtransfer.hh | 229 +++++++++++++++++++++++++++++++++++
 2 files changed, 230 insertions(+)
 create mode 100644 dune/gfe/pktop1mgtransfer.hh

diff --git a/dune/gfe/Makefile.am b/dune/gfe/Makefile.am
index e1eb50a1..70642e14 100644
--- a/dune/gfe/Makefile.am
+++ b/dune/gfe/Makefile.am
@@ -20,6 +20,7 @@ srcinclude_HEADERS = averagedistanceassembler.hh \
                      localgeodesicfestiffness.hh \
                      localgfetestfunctionbasis.hh \
                      maxnormtrustregion.hh \
+                     pktop1mgtransfer.hh \
                      quaternion.hh \
                      realtuple.hh \
                      riemanniantrsolver.hh \
diff --git a/dune/gfe/pktop1mgtransfer.hh b/dune/gfe/pktop1mgtransfer.hh
new file mode 100644
index 00000000..629786e4
--- /dev/null
+++ b/dune/gfe/pktop1mgtransfer.hh
@@ -0,0 +1,229 @@
+#ifndef PK_TO_P1_MG_TRANSFER_HH
+#define PK_TO_P1_MG_TRANSFER_HH
+
+#include <dune/istl/bcrsmatrix.hh>
+#include <dune/common/fmatrix.hh>
+#include <dune/common/bitsetvector.hh>
+
+#include <dune/fufem/functionspacebases/p1nodalbasis.hh>
+#include <dune/fufem/functionspacebases/p2nodalbasis.hh>
+
+#include <dune/solvers/transferoperators/truncatedmgtransfer.hh>
+#include <dune/solvers/transferoperators/compressedmultigridtransfer.hh>
+
+/** \brief Restriction and prolongation operator for truncated multigrid
+ *     from a Pk nodal basis to a p1 one.
+ *
+ * \note This class is a temporary hack.  Certainly there are better ways to do
+ *   this, and of course they should be in dune-solvers.  But I need this quick
+ *   for some rapid prototyping.
+ */
+
+template<
+    class VectorType,
+    class BitVectorType = Dune::BitSetVector<VectorType::block_type::dimension>,
+    class MatrixType = Dune::BCRSMatrix< typename Dune::FieldMatrix<
+        typename VectorType::field_type, VectorType::block_type::dimension, VectorType::block_type::dimension> > >
+class PKtoP1MGTransfer :
+    public TruncatedCompressedMGTransfer<VectorType, BitVectorType, MatrixType>
+{
+
+    enum {blocksize = VectorType::block_type::dimension};
+
+    typedef typename VectorType::field_type field_type;
+
+public:
+
+    typedef typename CompressedMultigridTransfer<VectorType, BitVectorType, MatrixType>::TransferOperatorType TransferOperatorType;
+    
+
+    /** \brief Default constructor */
+    PKtoP1MGTransfer()
+    {}
+
+    template <class Basis, class GridView>
+    void setup(const Basis& fineBasis,
+               const P1NodalBasis<GridView>& p1Basis)
+        {
+        typedef typename TransferOperatorType::block_type TransferMatrixBlock;
+        typedef typename GridView::ctype ctype;
+
+        const int dim = GridView::dimension;
+
+        int rows = fineBasis.size();
+        int cols = p1Basis.size();
+
+        // Make identity matrix
+        TransferMatrixBlock identity(0);
+        for (int i=0; i<identity.N(); i++)
+            identity[i][i] = 1;
+#if 0
+        // A factory for the shape functions
+        typedef typename Dune::PQkLocalFiniteElementCache<ctype, field_type, dim, 1> P1FECache;
+        typedef typename P1FECache::FiniteElementType P1FEType;
+        P1FECache p1FECache;
+
+        typedef typename Dune::PQkLocalFiniteElementCache<ctype, field_type, dim, 2> P2FECache;
+        typedef typename P2FECache::FiniteElementType P2FEType;
+        P2FECache p2FECache;
+#endif
+        this->matrix_->setSize(rows,cols);
+        this->matrix_->setBuildMode(TransferOperatorType::random);
+
+        typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+        
+        const GridView& gridView = p1Basis.getGridView();
+
+        ElementIterator cIt    = gridView.template begin<0>();
+        ElementIterator cEndIt = gridView.template end<0>();
+
+
+        // ///////////////////////////////////////////
+        // Determine the indices present in the matrix
+        // /////////////////////////////////////////////////
+        Dune::MatrixIndexSet indices(rows, cols);
+
+        for (; cIt != cEndIt; ++cIt) {
+
+            typedef typename GridView::template Codim<0>::Entity EntityType;
+
+            // Get local finite element
+            //const P1FEType& coarseBaseSet = p1FECache.get(cIt->type());
+            const typename P1NodalBasis<GridView,double>::LocalFiniteElement& coarseBaseSet = p1Basis.getLocalFiniteElement(*cIt);
+
+            const int numCoarseBaseFct = coarseBaseSet.localBasis().size();
+
+            // preallocate vector for function evaluations
+            std::vector<Dune::FieldVector<field_type,1> > values(numCoarseBaseFct);
+
+            ElementIterator fIt = cIt;
+
+            const Dune::GenericReferenceElement<ctype,dim>& fineRefElement
+                = Dune::GenericReferenceElements<ctype, dim>::general(fIt->type());
+
+            // Get local finite element
+            const typename Basis::LocalFiniteElement& fineBaseSet = fineBasis.getLocalFiniteElement(*fIt);
+
+            const int numFineBaseFct = fineBaseSet.localBasis().size();
+
+
+            for (int j=0; j<numFineBaseFct; j++)
+            {
+                const Dune::LocalKey& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
+
+                int globalFine = fineBasis.index(*fIt, j);
+
+                Dune::FieldVector<ctype, dim> fineBasePosition = fineRefElement.position(jLocalKey.subEntity(), jLocalKey.codim());
+                Dune::FieldVector<ctype, dim> local = fineBasePosition;
+#warning Position computation is wrong!
+                
+                // Evaluate coarse grid base functions
+                coarseBaseSet.localBasis().evaluateFunction(local, values);
+
+                for (int i=0; i<numCoarseBaseFct; i++)
+                {
+                    if (values[i] > 0.001) 
+                    {
+                        const Dune::LocalKey& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
+                        int globalCoarse = p1Basis.index(*cIt, i);
+                        indices.add(globalFine, globalCoarse);
+                    }
+                }
+            }
+
+        }
+
+        indices.exportIdx(*this->matrix_);
+
+        // /////////////////////////////////////////////
+        // Compute the matrix
+        // /////////////////////////////////////////////
+        cIt = gridView.template begin<0>();
+        for (; cIt != cEndIt; ++cIt) {
+
+            // Get local finite element
+            const typename P1NodalBasis<GridView,double>::LocalFiniteElement& coarseBaseSet = p1Basis.getLocalFiniteElement(*cIt);
+
+            const int numCoarseBaseFct = coarseBaseSet.localBasis().size();
+
+            typedef typename GridView::template Codim<0>::Entity EntityType;
+
+            // preallocate vector for function evaluations
+            std::vector<Dune::FieldVector<field_type,1> > values(numCoarseBaseFct);
+
+            ElementIterator fIt = cIt;
+
+            const Dune::GenericReferenceElement<ctype,dim>& fineRefElement
+                = Dune::GenericReferenceElements<ctype, dim>::general(fIt->type());
+
+            // Get local finite element
+            const typename Basis::LocalFiniteElement& fineBaseSet = fineBasis.getLocalFiniteElement(*fIt);
+
+            const int numFineBaseFct = fineBaseSet.localBasis().size();
+
+            for (int j=0; j<numFineBaseFct; j++)
+            {
+                const Dune::LocalKey& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
+
+                int globalFine = fineBasis.index(*fIt, j);
+
+                Dune::FieldVector<ctype, dim> fineBasePosition = fineRefElement.position(jLocalKey.subEntity(), jLocalKey.codim());
+                Dune::FieldVector<ctype, dim> local = fineBasePosition;
+#warning Position computation is wrong!
+
+                // Evaluate coarse grid base functions
+                coarseBaseSet.localBasis().evaluateFunction(local, values);
+
+                for (int i=0; i<numCoarseBaseFct; i++)
+                {
+                    if (values[i] > 0.001) 
+                    {
+                        const Dune::LocalKey& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
+                        int globalCoarse = p1Basis.index(*cIt, i);
+
+                        TransferMatrixBlock matValue = identity;
+                        matValue *= values[i];
+                        (*this->matrix_)[globalFine][globalCoarse] = matValue;
+                    }
+                }
+            }
+
+        }
+
+    }
+
+
+#if 0
+    /** \brief Restrict level fL of f and store the result in level cL of t
+     *
+     * \param critical Has to contain an entry for each degree of freedom.
+     *        Those dofs with a set bit are treated as critical.
+     */
+    void restrict(const VectorType& f, VectorType &t, const BitVectorType& critical) const;
+
+    /** \brief Restriction of  MultiGridTransfer*/
+    using CompressedMultigridTransfer< VectorType, BitVectorType, MatrixType >::restrict;
+
+    /** \brief Prolong level cL of f and store the result in level fL of t
+     * 
+     * \param critical Has to contain an entry for each degree of freedom.
+     *        Those dofs with a set bit are treated as critical.
+     */
+    void prolong(const VectorType& f, VectorType &t, const BitVectorType& critical) const;
+
+    /** \brief Prolongation of  MultiGridTransfer*/
+    using CompressedMultigridTransfer< VectorType, BitVectorType, MatrixType >::prolong;
+
+    /** \brief Galerkin assemble a coarse stiffness matrix
+     *
+     * \param critical Has to contain an entry for each degree of freedom.
+     *        Those dofs with a set bit are treated as critical.
+     */
+    void galerkinRestrict(const MatrixType& fineMat, MatrixType& coarseMat, const BitVectorType& critical) const;
+
+    /** \brief Galerkin restriction of  MultiGridTransfer*/
+    using CompressedMultigridTransfer< VectorType, BitVectorType, MatrixType >::galerkinRestrict;
+#endif
+};
+
+#endif
-- 
GitLab