17#ifndef MULTI_GRID_SOLVER_HH_
18#define MULTI_GRID_SOLVER_HH_
27#include "dune/grid/common/grid.hh"
28#include "dune/istl/bcrsmatrix.hh"
29#include "dune/common/fmatrix.hh"
30#include "dune/common/fvector.hh"
39 namespace MultiGridSolver_Detail
45 template <
class Scalar,
int n,
bool resetSolution=false>
51 if(resetSolution) y *= 0.0;
55 auto riter = P.begin(), rend = P.end();
56 for(;riter!=rend; ++riter)
58 auto citer = riter->begin(), cend = riter->end();
59 for(;citer!=cend; ++citer) y[riter.index()] += alpha * (*citer)[0][0] * x[citer.index()];
64 template <
class Scalar,
int n,
bool resetSolution=false>
70 if(resetSolution) y *= 0.0;
74 auto riter = P.begin(), rend = P.end();
75 for(;riter!=rend; ++riter)
77 auto citer = riter->begin(), cend = riter->end();
78 for(;citer!=cend; ++citer) y[citer.index()] += alpha * (*citer)[0][0] * x[riter.index()];
82 template <
class Scalar,
int n>
87 axpy<Scalar,n,true>(P,x,y);
90 template <
class Scalar,
int n>
95 atxpy<Scalar,n,true>(P,x,y);
129 template <
class Gr
id >
132 typedef typename Grid::LevelGridView::IndexSet::IndexType IndexType;
133 typedef typename std::pair<IndexType,float> FatherIndexValue;
134 typedef typename std::vector<FatherIndexValue> FatherSimplexPairs;
142 for(
int levelNr=1; levelNr<=grd.maxLevel(); levelNr++)
143 findParents(grd,levelNr);
147 void findParents(
const Grid& grd,
int levelNr )
157 typedef typename Grid::template Codim<0>::LevelIterator ElementLevelIterator;
158 typedef typename Grid::LevelGridView::IndexSet::IndexType IndexType;
160 std::vector<FatherSimplexPairs> levelParents;
161 levelParents.resize( grd.size(levelNr,Grid::dimension) );
164 std::vector<bool> processed(grd.size(Grid::dimension),
false);
167 std::vector<bool> disappears( grd.size(levelNr-1,Grid::dimension) ,
true );
169 typename Grid::LevelGridView::IndexSet
const& indexSet = grd.levelView(levelNr).indexSet() ;
170 typename Grid::LevelGridView::IndexSet
const& fatherIndexSet = grd.levelView(levelNr-1).indexSet();
173 ElementLevelIterator itEnd = grd.levelGridView(levelNr).template end<0>() ;
174 for (ElementLevelIterator it = grd.levelGridView(levelNr).template begin<0>() ; it != itEnd; ++it)
177 std::vector<IndexType> fatherIndices;
180 typename Grid::template Codim<0>::Entity itFather = (*it).father();
182 for(
int i=0 ; i<=Grid::dimension ; i++ )
184 fatherIndices.push_back( fatherIndexSet.subIndex(*itFather, i, Grid::dimension) );
186 disappears[ indexSet.subIndex( *itFather,i,Grid::dimension ) ] =
false;
190 for(
int i=0 ; i<=Grid::dimension ; i++ )
192 IndexType idx_child = indexSet.subIndex(*it, i, Grid::dimension);
193 if (!processed[idx_child])
195 processed[idx_child] =
true;
197 std::vector<float> relativeCoord;
198 relativeCoord.push_back(1);
201 relativeCoord.push_back( it->geometryInFather().corner(i)[
component] );
202 relativeCoord.front() -= relativeCoord.back();
207 FatherIndexValue couple;
209 couple.second = relativeCoord[
component];
210 levelParents[idx_child].push_back(couple);
227 for (
int k = 0 ; k < disappears.size(); k++ )
239 template <
class Gr
id,
class Scalar=
double>
242 std::vector<Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1>>> stack;
244 int maxiLevel = grd.maxLevel();
248 std::vector<std::vector<int> > disappear(parentalNodes.
levelDisappear);
250 int disappearSumBefore = 0, disappearSumAfter = 0;
252 for(
int levelNr = 1 ; levelNr <= maxiLevel ; levelNr++)
254 disappearSumBefore = disappearSumAfter;
255 disappearSumAfter += disappear[levelNr-1].size();
257 int prolCols = grd.size( levelNr-1 , Grid::dimension ) + disappearSumBefore ;
258 int prolRows = grd.size( levelNr , Grid::dimension ) + disappearSumAfter ;
266 int nz = disappearSumAfter + grd.size(levelNr,Grid::dimension)*(Grid::dimension+1);
273 auto row = prolMatrix.createbegin(), rend = prolMatrix.createend();
274 for (;row!=rend; ++row)
276 if (row.index() < disappearSumBefore)
277 row.insert( row.index() );
278 else if (row.index() >= disappearSumBefore && row.index() < disappearSumAfter )
279 row.insert( disappearSumBefore + disappear[levelNr-1][ row.index() - disappearSumBefore ] );
281 for(
int k = 0 ; k <= Grid::dimension ; k++ )
282 if (parentalNodes.
levelParentsVector[levelNr-1][row.index()-disappearSumAfter][k].second > 0)
283 row.insert( parentalNodes.
levelParentsVector[levelNr-1][row.index()-disappearSumAfter][k].first + disappearSumBefore );
287 for(
int row = 0 ; row < disappearSumBefore ; row++)
288 prolMatrix[row][row] = 1;
289 for(
int indx = 0 ; indx < disappear[levelNr-1].size(); indx++)
290 prolMatrix[ disappearSumBefore + indx ][ disappear[levelNr-1][indx] + disappearSumBefore ] = 1;
291 for(
int row = disappearSumAfter ; row < prolRows ; row++)
293 for(
int k = 0 ; k <= Grid::dimension ; k++ )
294 if (parentalNodes.
levelParentsVector[levelNr-1][row-disappearSumAfter ][k].second > 0)
296 prolMatrix[row][ parentalNodes.
levelParentsVector[levelNr-1][row-disappearSumAfter][k].first + disappearSumBefore ]
301 stack.push_back( prolMatrix );
320 template <
class Gr
id,
class Scalar,
int nComponents=1,
class Matrix = Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,nComponents,nComponents> > >
331 size_t prolongationStackSize = prolongations.size();
334 levelMatrixStack.back() = A;
336 for(
int level = prolongationStackSize; level>0; --level)
339 std::unique_ptr<Dune::MatrixIndexSet> C =
conjugationPattern( prolongations[level-1] , levelMatrixStack[level] , onlyLowerTriangle);
347 conjugation( Cnew , prolongations[level-1] , levelMatrixStack[level] , onlyLowerTriangle );
349 levelMatrixStack[level-1] = Cnew;
354 Dune::BCRSMatrix<MatrixBlock>
const&
stiffnessMatrix(
size_t level)
const {
return levelMatrixStack[level]; }
357 size_t size()
const {
return levelMatrixStack.size(); }
359 Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1> >
const&
prolongation(
size_t level)
const {
return prolongations[level]; }
363 std::vector<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1> > > prolongations;
364 std::vector<Matrix> levelMatrixStack;
376 template <
class Gr
id,
int nComponents=1>
379 typedef double Scalar;
391 : parameter(params), levelStack(grid,A),
393 mgPre(
"MULTIGRIDSOLVER: ")
396 template <
class Assembler,
int row,
int col,
class BlockFilter>
399 ? *(A.getAssembler().template get<
MatrixAsTriplet<Scalar> >(false,row,row+1,col,col+1).
transpose().template toBCRS<nComponents>())
400 : *(A.getAssembler().template get<
MatrixAsTriplet<Scalar> >(false,row,row+1,col,col+1).template toBCRS<nComponents>()),
408 int level = levelStack.
size() - 1;
409 double relDefect = 1;
411 for(
int i=0;i<parameter.
maxSteps;i++)
413 mgSolveRecursive( solution , rightHand , level );
417 relDefect = defect.two_norm()/rightHand.two_norm();
418 if( relDefect < parameter.
maxTol)
420 if(parameter.
verbose) std::cout << mgPre <<
"converged after " << i <<
" iterations (relative defect = " << relDefect <<
")." << std::endl;
424 if(parameter.
verbose) std::cout << mgPre <<
"NOT converged after " << parameter.
maxSteps <<
" iterations (relative defect = " << relDefect <<
")." << std::endl;
430 void mgSolveRecursive(CoeffVector& solution, CoeffVector& rightHand,
int level)
434 solver.apply(solution,rightHand);
439 applySmoothing( solution , rightHand , level );
440 CoeffVector levelRightHand( levelStack.
prolongation(level-1).M() ), tmpRhs(rightHand);
441 levelRightHand = 0.0;
446 CoeffVector levelError(levelRightHand);
449 mgSolveRecursive( levelError , levelRightHand , level - 1 );
453 applySmoothing( solution , rightHand , level );
457 void applySmoothing( CoeffVector& solution , CoeffVector
const& rhs ,
int level )
460 jacobi.apply(solution,rhs);
464 const MultiGridSolver_Detail::MultiLevelStack<Grid,Scalar,nComponents> levelStack;
465 DirectSolver<CoeffVector,CoeffVector> solver;
471 explicit Parameter(
size_t maxSteps_,
size_t maxSmoothingSteps_,
double maxTol_,
double relaxation_=0.5,
bool verbose_=
false)
475 explicit Parameter(
size_t maxSteps_=100,
size_t maxSmoothingSteps_=10,
size_t maxCGSteps_=1000,
size_t lookahead_=25,
476 double maxTol_=1e-9,
double relaxation_=0.5,
bool verbose_=
false,
bool useDirectLevel0Solver_ =
true)
492 template <
class Gr
id,
int nComponents=1>
495 typedef double Scalar;
504 template <
class Assembler,
int row,
int col,
class BlockFilter>
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
Operator with matrix-representation and coordinate mappings.
MultiGridPreconditioner(Dune::BCRSMatrix< MatrixBlock > const &A, Grid const &grid, Parameter p=Parameter())
MultiGridPreconditioner(AssembledGalerkinOperator< Assembler, row, row+1, col, col+1, BlockFilter > const &A, Grid const &grid, Parameter p=Parameter())
MultiGridSolver< Grid, nComponents >::Parameter Parameter
size_t size() const
Number of grid levels.
Dune::BCRSMatrix< MatrixBlock > const & stiffnessMatrix(size_t level) const
Read-only access to level-th entry of matrix stack, i.e. to the stiffness matrix corresponding to lev...
MultiLevelStack(Grid const &grid, Matrix const &A, bool onlyLowerTriangle=false)
Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const & prolongation(size_t level) const
Finds the parent nodes and their interpolation weight for each node in the grid. usage eg....
std::vector< std::vector< FatherSimplexPairs > > levelParentsVector
std::vector< std::vector< int > > levelDisappear
ParentalNodes(Grid const &grd)
void setParameter(Parameter p)
MultigridSolver(Dune::BCRSMatrix< MatrixBlock > const &A, Grid const &grid, Parameter params=Parameter())
void apply(CoeffVector &solution, CoeffVector &rightHand)
MultigridSolver(AssembledGalerkinOperator< Assembler, row, row+1, col, col+1, BlockFilter > const &A, Grid const &grid, Parameter params=Parameter(), bool transposed=false)
This file contains various utility functions that augment the basic functionality of Dune.
NumaBCRSMatrix< Dune::FieldMatrix< Scalar, m, m > > stiffnessMatrix(Space const &space, Conductivity const &kappa)
Creates a stiffness matrix for the given FE space.
DirectType
Available direct solvers for linear equation systems.
@ MUMPS
MUMPS sparse solver.
MatrixProperties
Characterizations of sparse matrix properties.
void applyProlongation(Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BlockVector< Dune::FieldVector< Scalar, n > > const &x, Dune::BlockVector< Dune::FieldVector< Scalar, n > > &y)
void atxpy(Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BlockVector< Dune::FieldVector< Scalar, n > > const &x, Dune::BlockVector< Dune::FieldVector< Scalar, n > > &y, Scalar alpha=1.0)
Compute . If resetSolution=true computes .
void applyTransposedProlongation(Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BlockVector< Dune::FieldVector< Scalar, n > > const &x, Dune::BlockVector< Dune::FieldVector< Scalar, n > > &y)
std::vector< Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > > computeProlongations(const Grid &grd)
Compute prolongation matrices between consecutive grid levels.
void axpy(Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BlockVector< Dune::FieldVector< Scalar, n > > const &x, Dune::BlockVector< Dune::FieldVector< Scalar, n > > &y, Scalar alpha=1.0)
Compute . If resetSolution=true computes .
void conjugation(Dune::BCRSMatrix< Entry > &C, Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BCRSMatrix< Entry > const &A, bool onlyLowerTriangle=false)
Computes the triple sparse matrix product .
auto & component(LinearProductSpace< Scalar, Sequence > &x)
std::unique_ptr< Dune::MatrixIndexSet > conjugationPattern(Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > const &P, Dune::BCRSMatrix< Entry > const &A, bool onlyLowerTriangle=false)
Creates the sparsity pattern of .
Parameter(size_t maxSteps_, size_t maxSmoothingSteps_, double maxTol_, double relaxation_=0.5, bool verbose_=false)
Parameter & operator=(Parameter const &)=default
bool useDirectLevel0Solver
Parameter(size_t maxSteps_=100, size_t maxSmoothingSteps_=10, size_t maxCGSteps_=1000, size_t lookahead_=25, double maxTol_=1e-9, double relaxation_=0.5, bool verbose_=false, bool useDirectLevel0Solver_=true)
Parameter(Parameter const &)=default