13#ifndef AGGLOMERATIONPRECONDITIONER_HH
14#define AGGLOMERATIONPRECONDITIONER_HH
27 namespace AgglomerationPreconditionerDetails
29 template <
class Entry>
30 class AgglomerationPreconditionerEngine
32 using field_type =
typename Entry::field_type;
33 static int const blocksize = Entry::rows;
37 template <
class Matrix,
class Space>
38 AgglomerationPreconditionerEngine(Matrix
const& A, Space
const& space)
40 using std::begin;
using std::end;
51 size_t const n = space.degreesOfFreedom();
52 size_t const m = space.indexSet().size(0);
53 NumaCRSPatternCreator<> creator(n,m);
54 for (
auto ci=space.gridView().template begin<0>(); ci!=space.gridView().template end<0>(); ++ci)
56 auto cidx = space.indexSet().index(*ci);
57 auto const& gidx = space.mapper().globalIndices(cidx);
58 creator.addElements(begin(gidx),end(gidx),&cidx,&cidx+1,
true);
60 P = NumaBCRSMatrix<Entry>(std::make_shared<NumaCRSPattern<>>(creator),
61 unitMatrix<typename Entry::field_type,blocksize>());
63 Pt = NumaBCRSMatrix<Entry>(P,
false,
true,
false);
66 inverseDiagonalPAP.resize(m,0);
67 for (
size_t i=0; i<m; ++i)
69 auto const& row = P[i];
70 auto ki =
rangeView(row.getindexptr(),row.getindexptr()+row.size());
75 auto const& Ak = A[k];
78 while (al!=end(Ak) && l!=end(ki))
82 inverseDiagonalPAP[i] += *al;
86 else if (*l < al.index())
92 inverseDiagonalPAP[i].invert();
98 template <
class Domain,
class Range>
99 void applyAgglomerated(Domain& x, Range
const& y)
102 size_t const m = inverseDiagonalPAP.size();
106 for (
size_t i=0; i<m; ++i)
107 z[i] = inverseDiagonalPAP[i] * z[i];
112 template <
class Domain,
class Range>
113 field_type applyAgglomeratedDp(Domain& x, Range
const& y)
115 applyAgglomerated(x,y);
118 for (
size_t i=0; i<P.N(); ++i)
124 std::vector<Entry> inverseDiagonalPAP;
125 NumaBCRSMatrix<Entry> P, Pt;
156 template <
class Operator>
161 using typename Base::domain_type;
162 using typename Base::range_type;
164 static int const blocksize = range_type::block_type::dimension;
165 static_assert(blocksize==domain_type::block_type::dimension,
"Operator matrix entries must be square for Jacobi preconditioning.");
170 static int const category = Dune::SolverCategory::sequential;
178 template <
class Space>
181 engine(opA.getmat(),space)
187 virtual void apply(domain_type& x, range_type
const& y)
196 virtual field_type
applyDp(domain_type& x, range_type
const& y)
199 return engine.applyDp(x,y);
208 return jac1.requiresInitializedInput();
213 AgglomerationPreconditionerDetails::AgglomerationPreconditionerEngine<Entry> engine;
218 template <
class Assembler,
222 IstlInterfaceDetail::RangeBlockSelector<firstRow,firstRow+1,firstCol,firstCol+1>,
224 :
public SymmetricPreconditioner<typename AssembledGalerkinOperator<Assembler,firstRow,firstRow+1,firstCol,firstCol+1,
225 IstlInterfaceDetail::RangeBlockSelector<firstRow,firstRow+1,firstCol,firstCol+1>,
226 true>::domain_type,typename AssembledGalerkinOperator<Assembler,firstRow,firstRow+1,firstCol,firstCol+1,
227 IstlInterfaceDetail::RangeBlockSelector<firstRow,firstRow+1,firstCol,firstCol+1>,
231 IstlInterfaceDetail::RangeBlockSelector<firstRow,firstRow+1,firstCol,firstCol+1>,
235 using typename Base::domain_type;
236 using typename Base::range_type;
238 using RangeEntry =
typename boost::fusion::result_of::value_at_c<typename range_type::Sequence,0>::type::block_type;
239 using DomainEntry =
typename boost::fusion::result_of::value_at_c<typename domain_type::Sequence,0>::type::block_type;
240 static int const blocksize = RangeEntry::dimension;
241 static_assert(blocksize==DomainEntry::dimension,
"Matrixe entries have to be square for Jacobi preconditioning");
246 static int const category = Dune::SolverCategory::sequential;
254 template <
class Space>
263 virtual void apply(domain_type& x, range_type
const& y)
266 auto const& y0 = boost::fusion::at_c<0>(y.data);
267 auto& x0 = boost::fusion::at_c<0>(x.data);
268 engine.applyDp(x0,y0);
274 virtual field_type
applyDp(domain_type& x, range_type
const& y)
277 auto const& y0 = boost::fusion::at_c<0>(y.data);
278 auto& x0 = boost::fusion::at_c<0>(x.data);
279 return engine.applyDp(x0,y0);
288 return jac1.requiresInitializedInput();
293 AgglomerationPreconditionerDetails::AgglomerationPreconditionerEngine<Entry> engine;
virtual field_type applyDp(domain_type &x, range_type const &y)
Computes and returns .
virtual bool requiresInitializedInput() const
Returns true if the target vector x has to be initialized to zero before calling apply or applyDp.
AgglomerationPreconditioner(Operator const &opA, Space const &space)
Constructor.
virtual void apply(domain_type &x, range_type const &y)
Computes .
An agglomeration-based preconditioner for elliptic problems discretized with higher-order Lagrange fi...
AgglomerationPreconditioner(Operator const &opA, Space const &space)
Constructor.
virtual bool requiresInitializedInput() const
Returns true if the target vector x has to be initialized to zero before calling apply or applyDp.
static int const category
virtual field_type applyDp(domain_type &x, range_type const &y)
Computes and returns .
virtual void apply(domain_type &x, range_type const &y)
Computes .
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
A NUMA-aware compressed row storage matrix adhering mostly to the Dune ISTL interface (to complete....
Interface for symmetric preconditioners.
RangeView< It > rangeView(It first, It last)
Convenience function for constructing range views on the fly.