Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#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();
#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 it = gridView.template begin<0>();
ElementIterator endIt = gridView.template end<0>();
// ///////////////////////////////////////////
// Determine the indices present in the matrix
// /////////////////////////////////////////////////
Dune::MatrixIndexSet indices(rows, cols);

Oliver Sander
committed
typedef typename P1NodalBasis<GridView,double>::LocalFiniteElement LP1FE;
const LP1FE& coarseBaseSet = p1Basis.getLocalFiniteElement(*it);

Oliver Sander
committed
typedef typename Dune::LocalFiniteElementFunctionBase<LP1FE>::type FunctionBaseClass;

Oliver Sander
committed
typedef typename GridView::template Codim<0>::Entity Element;
AlienElementLocalBasisFunction<Element, LP1FE, FunctionBaseClass> f(*it, *it, coarseBaseSet.localBasis());

Oliver Sander
committed
for (int i=0; i<coarseBaseSet.localBasis().size(); i++) {

Oliver Sander
committed
f.setIndex(i);
std::vector<double> values;
fineBasis.getLocalFiniteElement(*it).localInterpolation().interpolate(f,values);

Oliver Sander
committed
for (size_t j=0; j<values.size(); j++) {

Oliver Sander
committed
size_t globalFine = fineBasis.index(*it, j);
size_t globalCoarse = p1Basis.index(*it, i);
indices.add(globalFine, globalCoarse);
}

Oliver Sander
committed

Oliver Sander
committed
}
}
indices.exportIdx(*this->matrix_);
// /////////////////////////////////////////////
// Compute the matrix
// /////////////////////////////////////////////

Oliver Sander
committed
for (it = gridView.template begin<0>(); it != endIt; ++it) {

Oliver Sander
committed
typedef typename P1NodalBasis<GridView,double>::LocalFiniteElement LP1FE;
const LP1FE& coarseBaseSet = p1Basis.getLocalFiniteElement(*it);

Oliver Sander
committed
typedef typename Dune::LocalFiniteElementFunctionBase<LP1FE>::type FunctionBaseClass;

Oliver Sander
committed
typedef typename GridView::template Codim<0>::Entity Element;
AlienElementLocalBasisFunction<Element, LP1FE, FunctionBaseClass> f(*it, *it, coarseBaseSet.localBasis());

Oliver Sander
committed
for (int i=0; i<coarseBaseSet.localBasis().size(); i++) {

Oliver Sander
committed
f.setIndex(i);
std::vector<double> values;
fineBasis.getLocalFiniteElement(*it).localInterpolation().interpolate(f,values);
for (size_t j=0; j<values.size(); j++) {

Oliver Sander
committed
size_t globalFine = fineBasis.index(*it, j);
size_t globalCoarse = p1Basis.index(*it, i);
(*this->matrix_)[globalFine][globalCoarse] = Dune::ScaledIdentityMatrix<double,TransferMatrixBlock::rows>(values[j]);

Oliver Sander
committed

Oliver Sander
committed
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
}
}
}
#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