1#ifndef DUNE_FEM_LDLSOLVER_HH
2#define DUNE_FEM_LDLSOLVER_HH
11#include <dune/common/hybridutilities.hh>
12#include <dune/fem/function/adaptivefunction.hh>
13#include <dune/fem/function/blockvectorfunction.hh>
14#include <dune/fem/function/tuplediscretefunction.hh>
15#include <dune/fem/io/parameter.hh>
16#include <dune/fem/operator/linear/spoperator.hh>
17#include <dune/fem/operator/matrix/colcompspmatrix.hh>
18#include <dune/fem/solver/inverseoperatorinterface.hh>
20#if HAVE_SUITESPARSE_LDL
45template<
class DiscreteFunction,
46 class Matrix = SparseRowMatrix< typename DiscreteFunction::DiscreteFunctionSpaceType::RangeFieldType > >
47class LDLInverseOperator;
49template<
class DiscreteFunction,
class Matrix >
50struct LDLInverseOperatorTraits
53 typedef AdaptiveDiscreteFunction< typename DiscreteFunction::DiscreteFunctionSpaceType > SolverDiscreteFunctionType;
56 typedef OperatorType PreconditionerType;
58 typedef Fem::SparseRowLinearOperator< DiscreteFunction, DiscreteFunction, Matrix > AssembledOperatorType;
61 typedef SolverParameter SolverParameterType;
73template<
class DF,
class Matrix >
74class LDLInverseOperator :
public InverseOperatorInterface< LDLInverseOperatorTraits< DF, Matrix > >
76 typedef LDLInverseOperatorTraits< DF, Matrix > Traits;
77 typedef InverseOperatorInterface< Traits > BaseType;
79 friend class InverseOperatorInterface< Traits >;
82 static const bool preconditioningAvailable =
false;
84 typedef LDLInverseOperator< DF, Matrix > ThisType;
86 typedef typename BaseType :: SolverDiscreteFunctionType
87 SolverDiscreteFunctionType;
89 typedef typename BaseType :: OperatorType OperatorType;
90 typedef typename BaseType :: AssembledOperatorType AssembledOperatorType;
93 typedef ColCompMatrix<typename AssembledOperatorType::MatrixType::MatrixBaseType,int> CCSMatrixType;
95 typedef typename SolverDiscreteFunctionType::DofType DofType;
96 typedef typename SolverDiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
104 LDLInverseOperator(
const double& redEps,
const double& absLimit,
const int& maxIter,
const bool& verbose,
105 const ParameterReader ¶meter = Parameter::container() ) :
106 verbose_(verbose && Parameter::verbose(Parameter::solverStatistics )), ccsmat_()
114 LDLInverseOperator(
const double& redEps,
const double& absLimit,
const int& maxIter,
115 const ParameterReader ¶meter = Parameter::container() ) :
116 verbose_(parameter.getValue<bool>(
"fem.solver.verbose",false) && Parameter::verbose(Parameter::solverStatistics )),
120 LDLInverseOperator(
const SolverParameter ¶meter = SolverParameter(Parameter::container()) )
121 : BaseType(parameter), verbose_(BaseType::verbose())
131 LDLInverseOperator(
const OperatorType& op,
const double& redEps,
const double& absLimit,
const int& maxIter,
const bool& verbose,
132 const ParameterReader ¶meter = Parameter::container() ) :
133 verbose_(verbose), ccsmat_(), isloaded_(false)
144 LDLInverseOperator(
const OperatorType& op,
const double& redEps,
const double& absLimit,
const int& maxIter,
145 const ParameterReader ¶meter = Parameter::container() ) :
146 verbose_(parameter.getValue<bool>(
"fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
151 LDLInverseOperator(
const OperatorType& op,
const ParameterReader ¶meter = Parameter::container() ) :
152 verbose_(parameter.getValue<bool>(
"fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
158 ~LDLInverseOperator()
163 void bind(
const OperatorType& op )
167 BaseType::bind( op );
177 template<
typename... A>
178 void prepare(A... )
const
180 if( ! assembledOperator_ )
181 DUNE_THROW(NotImplemented,
"LDLInverseOperator only works for assembled systems!");
185 ccsmat_ = assembledOperator_->exportMatrix();
192 virtual void finalize()
214 template<
typename... DFs>
215 void apply(
const TupleDiscreteFunction<DFs...>& arg,TupleDiscreteFunction<DFs...>& dest)
const
218 std::vector<DofType> vecArg(arg.size());
219 auto vecArgIt(vecArg.begin());
221 [&](
auto i){vecArgIt=std::copy(std::get<i>(arg).dbegin(),std::get<i>(arg).dend(),vecArgIt);});
222 std::vector<DofType> vecDest(dest.size());
224 apply(vecArg.data(),vecDest.data());
226 auto vecDestIt(vecDest.begin());
227 Hybrid::forEach(std::make_index_sequence<
sizeof...(DFs)>{},[&](
auto i){
for(
auto& dof:dofs(std::get<i>(dest))) dof=(*(vecDestIt++));});
231 void printTexInfo(std::ostream& out)
const
233 out<<
"Solver: LDL direct solver"<<std::endl;
237 void printDecompositionInfo()
const
277 CCSMatrixType& getCCSMatrix()
289 void apply(
const DofType* arg, DofType* dest)
const
294 const std::size_t dimMat(ccsmat_.N());
295 ldl_perm(dimMat, Y_,
const_cast<DofType*
>(arg), P_);
296 ldl_lsolve(dimMat, Y_, Lp_, Li_, Lx_);
297 ldl_dsolve(dimMat, Y_, D_);
298 ldl_ltsolve(dimMat, Y_, Lp_, Li_, Lx_);
299 ldl_permt(dimMat, dest, Y_, P_);
301 const_cast<ThisType*
>(
this)->finalize();
310 int apply(
const SolverDiscreteFunctionType& arg,
311 SolverDiscreteFunctionType& dest)
const
313 apply(arg.leakPointer(),dest.leakPointer());
319 using BaseType :: assembledOperator_;
322 mutable CCSMatrixType ccsmat_;
323 mutable bool isloaded_ =
false;
325 mutable int* Parent_;
328 mutable int* Pattern_;
333 mutable DofType* Lx_;
335 mutable double info_[AMD_INFO];
338 void decompose()
const
341 const std::size_t dimMat(ccsmat_.N());
342 D_ =
new DofType [dimMat];
343 Y_ =
new DofType [dimMat];
344 Lp_ =
new int [dimMat + 1];
345 Parent_ =
new int [dimMat];
346 Lnz_ =
new int [dimMat];
347 Flag_ =
new int [dimMat];
348 Pattern_ =
new int [dimMat];
349 P_ =
new int [dimMat];
350 Pinv_ =
new int [dimMat];
352 if(amd_order (dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), P_, (DofType *) NULL, info_) < AMD_OK)
353 DUNE_THROW(InvalidStateException,
"LDL Error: AMD failed!");
355 printDecompositionInfo();
357 ldl_symbolic(dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), Lp_, Parent_, Lnz_, Flag_, P_, Pinv_);
359 Lx_ =
new DofType [Lp_[dimMat]];
360 Li_ =
new int [Lp_[dimMat]];
362 const std::size_t k(ldl_numeric(dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), ccsmat_.getValues(),
363 Lp_, Parent_, Lnz_, Li_, Lx_, D_, Y_, Pattern_, Flag_, P_, Pinv_));
372 std::cerr<<
"LDL Error: D("<<k<<
","<<k<<
") is zero!"<<std::endl;
373 DUNE_THROW(InvalidStateException,
"LDL Error: factorisation failed!");
379template<
class DF,
class Op,
bool symmetric=false>
380using LDLOp = LDLInverseOperator< DF, typename Op::MatrixType >;
Inverse operator base on CG method. Uses a runtime parameter fem.preconditioning which enables diagon...
Definition: cginverseoperator.hh:408
forward declaration
Definition: discretefunction.hh:51
A few common exception classes.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
Dune namespace.
Definition: alignedallocator.hh:13