27#include <boost/utility/result_of.hpp>
29#include "dune/grid/common/grid.hh"
30#include "dune/istl/preconditioners.hh"
63 template <
class Gr
id,
class Domain,
class Range>
67 typedef typename Grid::LevelGridView::IndexSet::IndexType Index;
68 typedef std::vector<Index> NodeSet;
70 static int const dim = Grid::dimension;
81 assert(grid.leafIndexSet().types(0).size()==1 && grid.leafIndexSet().types(0)[0].isSimplex()
82 &&
"HierarchicalBasisPreconditioner currently requires purely simplicial grids");
87 n = grid.leafIndexSet().size(dim);
90 typedef typename Grid::template Codim<0>::LevelIterator CellLevelIterator;
91 typedef typename Grid::template Codim<dim>::LevelIterator LeafVertexIterator;
94 nodesOnLevel.resize(j+1);
95 for (LeafVertexIterator i=grid.levelGridView(0).template begin<dim>(); i!=grid.levelGridView(0).template end<dim>(); ++i)
96 nodesOnLevel[0].push_back(grid.leafIndexSet().index(*i));
99 coarseElement.reserve(grid.levelIndexSet(0).size(0));
100 for (CellLevelIterator ci=grid.levelGridView(0).template begin<0>(); ci!=grid.levelGridView(0).template end<0>(); ++ci)
103 for (
int i=0; i<=dim; ++i)
104 idx[i] = grid.leafIndexSet().index((ci->template subEntity<dim>(i)));
105 coarseElement.push_back(idx);
109 parents.resize(n,std::make_pair(n,n));
110 for (
int k=1; k<=j; ++k)
114 for (CellLevelIterator ci=grid.levelGridView(k).template begin<0>(); ci!=grid.levelGridView(k).template end<0>(); ++ci)
116 typedef typename Grid::template Codim<0>::Entity
Cell;
117 Cell father = ci->father();
126 for (
int i=0; i<=dim; ++i)
128 typename Grid::template Codim<dim>::Entity vertex = ci->template subEntity<dim>(i);
129 Index idx = grid.leafIndexSet().index(vertex);
134 if (parents[idx].first==n && vertex.level()>0)
145 for (
int m=0; m<=dim; ++m)
146 if (relativeCoord[m] > 0.4)
147 coords[pos++] = (m+1)%(dim+1);
152 parents[idx].first = grid.leafIndexSet().index((father.template subEntity<dim>(coords[0])));
153 parents[idx].second = grid.leafIndexSet().index((father.template subEntity<dim>(coords[1])));
156 nodesOnLevel[k].push_back(idx);
166 int count = nodesOnLevel[0].size();
167 for (
int k=1; k<=j; ++k)
169 for (
typename NodeSet::const_iterator i=nodesOnLevel[k].begin(); i!=nodesOnLevel[k].end(); ++i)
170 assert(parents[*i].first<n && parents[*i].second<n);
171 count += nodesOnLevel[k].size();
180 virtual void pre (Domain& x, Range& b)
188 virtual void apply(Domain& v,
const Range& d)
195 for (
int k=j; k>0; --k)
198 typename Domain::field_type a = std::pow(2.0,(Grid::dimension-2.0)*(k-j));
201 for (
typename NodeSet::const_iterator i=nodesOnLevel[k].begin(); i!=nodesOnLevel[k].end(); ++i)
206 at_c<0>(v.data)[*i] = at_c<0>(r.data)[*i];
207 at_c<0>(v.data)[*i] /= a;
210 at_c<0>(r.data)[parents[*i].first] += 0.5 * at_c<0>(r.data)[*i];
211 at_c<0>(r.data)[parents[*i].second] += 0.5 * at_c<0>(r.data)[*i];
216 coarseGridSolution(v,r);
220 for (
int k=1; k<=j; ++k)
222 for (
typename NodeSet::const_iterator i=nodesOnLevel[k].begin(); i!=nodesOnLevel[k].end(); ++i)
223 at_c<0>(v.data)[*i] += 0.5*(at_c<0>(v.data)[parents[*i].first]+at_c<0>(v.data)[parents[*i].second]);
246 std::vector<NodeSet> nodesOnLevel;
247 std::vector<std::pair<Index,Index> > parents;
250 std::vector<Dune::FieldVector<Index,dim+1> > coarseElement;
255 void coarseGridSolution(Domain& v, Range& r)
const {
258 typename Domain::field_type a = std::pow(2.0,-(Grid::dimension-2.0));
261 for (
typename NodeSet::const_iterator i=nodesOnLevel[0].begin(); i!=nodesOnLevel[0].end(); ++i)
262 at_c<0>(v.data)[*i] = 0;
266 for (
int k=0; k<20; ++k)
269 for (
typename NodeSet::const_iterator i=nodesOnLevel[0].begin(); i!=nodesOnLevel[0].end(); ++i)
271 at_c<0>(dv.data)[*i] = at_c<0>(r.data)[*i];
272 at_c<0>(v.data)[*i] += at_c<0>(dv.data)[*i] / a;
286 typename Dune::Preconditioner<Domain,Range>::field_type s = dim==1? 1.0: dim==2? 1/12.0 : 1/60.0;
287 for (
int i=0; i<coarseElement.size(); ++i)
291 for (
int m=0; m<=dim; ++m)
292 eTdv += at_c<0>(dv.data)[coarseElement[i][m]];
293 for (
int m=0; m<=dim; ++m)
294 at_c<0>(r.data)[coarseElement[i][m]] -= a*s*(-eTdv+(dim+1.1)*at_c<0>(dv.data)[coarseElement[i][m]]);
A hierarchical basis preconditioner.
HierarchicalBasisPreconditioner(Grid const &grid)
Constructor.
virtual bool requiresInitializedInput() const
Returns true if the target vector x has to be initialized to zero before calling apply or applyDp.
virtual void pre(Domain &x, Range &b)
Has to be called before the first call to apply.
virtual SymmetricPreconditioner< Domain, Range >::field_type applyDp(Domain &v, const Range &d) override
Computes and returns .
virtual void post(Domain &x)
Has to be called after the last call to apply.
virtual void apply(Domain &v, const Range &d)
applies the preconditioner to the residual
Interface for symmetric preconditioners.
int count(Cell const &cell, int codim)
Computes the number of subentities of codimension c of a given entity.
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Dune::FieldVector< CoordType, dim+1 > barycentric(Dune::FieldVector< CoordType, dim > const &x)
Computes the barycentric coordinates of a point in the unit simplex.