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,...)
Definition: exceptions.hh:314
 
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:257
 
Dune namespace.
Definition: alignedallocator.hh:13