1#ifndef DUNE_FEM_SPQRSOLVER_HH 
    2#define DUNE_FEM_SPQRSOLVER_HH 
   10#include <dune/common/hybridutilities.hh> 
   11#include <dune/fem/function/adaptivefunction.hh> 
   12#include <dune/fem/function/blockvectorfunction.hh> 
   13#include <dune/fem/function/tuplediscretefunction.hh> 
   14#include <dune/fem/io/parameter.hh> 
   15#include <dune/fem/operator/common/operator.hh> 
   16#include <dune/fem/operator/linear/spoperator.hh> 
   17#include <dune/fem/operator/matrix/colcompspmatrix.hh> 
   18#include <dune/fem/operator/linear/spoperator.hh> 
   19#include <dune/fem/solver/inverseoperatorinterface.hh> 
   21#if HAVE_SUITESPARSE_SPQR 
   22#include <SuiteSparseQR.hpp> 
   46template<
class DiscreteFunction, 
bool symmetric=
false,
 
   47          class Matrix = SparseRowMatrix< typename DiscreteFunction::DiscreteFunctionSpaceType::RangeFieldType > >
 
   48class SPQRInverseOperator;
 
   50template<
class DiscreteFunction, 
bool symmetric, 
class Matrix>
 
   51struct SPQRInverseOperatorTraits
 
   54  typedef AdaptiveDiscreteFunction< typename DiscreteFunction::DiscreteFunctionSpaceType > SolverDiscreteFunctionType;
 
   57  typedef OperatorType  PreconditionerType;
 
   59  typedef Fem::SparseRowLinearOperator< DiscreteFunction, DiscreteFunction, Matrix > AssembledOperatorType;
 
   60  typedef ColCompMatrix<typename AssembledOperatorType::MatrixType::MatrixBaseType,int > CCSMatrixType;
 
   63  typedef SolverParameter SolverParameterType;
 
   68template< 
class DF, 
bool symmetric, 
class Matrix >
 
   69class SPQRInverseOperator : 
public InverseOperatorInterface< SPQRInverseOperatorTraits< DF, symmetric, Matrix > >
 
   71  typedef SPQRInverseOperatorTraits< DF, symmetric, Matrix > Traits;
 
   72  typedef InverseOperatorInterface< Traits > BaseType;
 
   73  typedef SPQRInverseOperator< DF, symmetric, Matrix > ThisType;
 
   76  static const bool preconditioningAvailable = 
false;
 
   79  typedef typename BaseType :: OperatorType OperatorType;
 
   80  typedef typename BaseType :: SolverDiscreteFunctionType SolverDiscreteFunctionType;
 
   83  typedef typename Traits :: CCSMatrixType  CCSMatrixType;
 
   84  typedef typename DiscreteFunctionType::DofType DofType;
 
   94  SPQRInverseOperator(
const double& redEps, 
const double& absLimit, 
const int& maxIter, 
const bool& verbose,
 
   95         const ParameterReader ¶meter = Parameter::container() ) :
 
   96    SPQRInverseOperator(parameter)
 
  105  SPQRInverseOperator(
const double& redEps, 
const double& absLimit, 
const int& maxIter,
 
  106         const ParameterReader ¶meter = Parameter::container() ) :
 
  107    SPQRInverseOperator(parameter)
 
  110  SPQRInverseOperator(
const SolverParameter& parameter = SolverParameter( Parameter::container() ) )
 
  111  : BaseType(parameter)
 
  112  , verbose_(BaseType::verbose())
 
  113  , ccsmat_(), cc_(new cholmod_common())
 
  115    cholmod_l_start(cc_);
 
  125  SPQRInverseOperator(
const OperatorType& op, 
const double& redEps, 
const double& absLimit, 
const int& maxIter, 
const bool& verbose,
 
  126      const ParameterReader ¶meter = Parameter::container() ) :
 
  127    SPQRInverseOperator(parameter)
 
  138  SPQRInverseOperator(
const OperatorType& op, 
const double& redEps, 
const double& absLimit, 
const int& maxIter,
 
  139         const ParameterReader ¶meter = Parameter::container() ) :
 
  140    SPQRInverseOperator(parameter)
 
  145  SPQRInverseOperator(
const OperatorType& op, 
const ParameterReader ¶meter = Parameter::container() ) :
 
  146    SPQRInverseOperator(parameter)
 
  151  SPQRInverseOperator(
const SPQRInverseOperator& other) :
 
  152    SPQRInverseOperator(other.parameter())
 
  154    if( other.operator_ )
 
  155      bind( *(other.operator_) );
 
  159  ~SPQRInverseOperator()
 
  162    cholmod_l_finish(cc_);
 
  166  using BaseType :: bind;
 
  175  template<
typename... A>
 
  176  void prepare(A... )
 const 
  178    if(assembledOperator_ && !ccsmat_ )
 
  180      ccsmat_.reset( 
new CCSMatrixType(assembledOperator_->exportMatrix() ) );
 
  186  virtual void finalize()
 
  191      cholmod_l_free_sparse(&A_, cc_);
 
  192      cholmod_l_free_dense(&B_, cc_);
 
  193      SuiteSparseQR_free<DofType>(&spqrfactorization_, cc_);
 
  203  int apply (
const DofType* arg, DofType* dest)
 const 
  206    const std::size_t dimMat(ccsmat_->N());
 
  208    for(std::size_t k = 0; k != dimMat; ++k)
 
  209      (
static_cast<DofType*
>(B_->x))[k] = arg[k];
 
  210    cholmod_dense* BTemp = B_;
 
  211    B_ = SuiteSparseQR_qmult<DofType>(0, spqrfactorization_, B_, cc_);
 
  212    cholmod_dense* X = SuiteSparseQR_solve<DofType>(1, spqrfactorization_, B_, cc_);
 
  213    cholmod_l_free_dense(&BTemp, cc_);
 
  215    for(std::size_t k = 0; k != dimMat; ++k)
 
  216      dest[k] = (
static_cast<DofType*
>(X->x))[k];
 
  217    cholmod_l_free_dense(&X, cc_);
 
  220      printDecompositionInfo();
 
  230  int apply(
const SolverDiscreteFunctionType& arg, SolverDiscreteFunctionType& dest)
 const 
  233    apply(arg.leakPointer(),dest.leakPointer());
 
  234    const_cast<ThisType*
>(
this)->finalize();
 
  244  int apply(
const ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& arg,
 
  245             ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& dest)
 const 
  248    std::vector<DofType> vecArg(arg.size());
 
  249    std::copy(arg.dbegin(),arg.dend(),vecArg.begin());
 
  250    std::vector<DofType> vecDest(dest.size());
 
  252    apply(vecArg.data(),vecDest.data());
 
  254    std::copy(vecDest.begin(),vecDest.end(),dest.dbegin());
 
  264  template<
typename... DFs>
 
  265  int apply(
const TupleDiscreteFunction<DFs...>& arg,TupleDiscreteFunction<DFs...>& dest)
 const 
  268    std::vector<DofType> vecArg(arg.size());
 
  269    auto vecArgIt(vecArg.begin());
 
  271      [&](
auto i){vecArgIt=std::copy(std::get<i>(arg).dbegin(),std::get<i>(arg).dend(),vecArgIt);});
 
  272    std::vector<DofType> vecDest(dest.size());
 
  274    apply(vecArg.data(),vecDest.data());
 
  276    auto vecDestIt(vecDest.begin());
 
  277    Hybrid::forEach(std::make_index_sequence<
sizeof...(DFs)>{},[&](
auto i){
for(
auto& dof:dofs(std::get<i>(dest))) dof=(*(vecDestIt++));});
 
  281  void printTexInfo(std::ostream& out)
 const 
  283    out<<
"Solver: SPQR direct solver"<<std::endl;
 
  287  void printDecompositionInfo()
 const 
  291      std::cout<<std::endl<<
"Solving with SuiteSparseQR"<<std::endl;
 
  292      std::cout<<
"Flops Taken: "<<cc_->SPQR_flopcount<<std::endl;
 
  293      std::cout<<
"Analysis Time: "<<cc_->SPQR_analyze_time<<
" s"<<std::endl;
 
  294      std::cout<<
"Factorize Time: "<<cc_->SPQR_factorize_time<<
" s"<<std::endl;
 
  295      std::cout<<
"Backsolve Time: "<<cc_->SPQR_solve_time<<
" s"<<std::endl;
 
  296      std::cout<<
"Peak Memory Usage: "<<cc_->memory_usage<<
" bytes"<<std::endl;
 
  297      std::cout<<
"Rank Estimate: "<<cc_->SPQR_istat[4]<<std::endl<<std::endl;
 
  301  void setMaxIterations( 
int ) {}
 
  306  SuiteSparseQR_factorization<DofType>* getFactorization()
 
  308    return spqrfactorization_;
 
  314  CCSMatrixType& getCCSMatrix()
 const 
  321  using BaseType :: operator_;
 
  322  using BaseType :: assembledOperator_;
 
  324  mutable std::unique_ptr< CCSMatrixType > ccsmat_;
 
  325  mutable cholmod_common* cc_   = nullptr ;
 
  326  mutable cholmod_sparse* A_    = nullptr ;
 
  327  mutable cholmod_dense* B_     = nullptr ;
 
  328  mutable SuiteSparseQR_factorization<DofType>* spqrfactorization_ = 
nullptr;
 
  331  void decompose()
 const 
  333    CCSMatrixType& ccsmat = getCCSMatrix();
 
  335    const std::size_t dimMat(ccsmat.N());
 
  336    const std::size_t nnz(ccsmat.getColStart()[dimMat]);
 
  340    bool real(std::is_same<DofType,double>::value);
 
  341    A_ = cholmod_l_allocate_sparse(dimMat, dimMat, nnz, 
sorted, packed, symmetric, real, cc_);
 
  343    for(std::size_t k = 0; k != (dimMat+1); ++k)
 
  344      (
static_cast<long int *
>(A_->p))[k] = ccsmat.getColStart()[k];
 
  345    for(std::size_t k = 0; k != nnz; ++k)
 
  347      (
static_cast<long int*
>(A_->i))[k] = ccsmat.getRowIndex()[k];
 
  348      (
static_cast<DofType*
>(A_->x))[k] = ccsmat.getValues()[k];
 
  351    B_ = cholmod_l_allocate_dense(dimMat, 1, dimMat, A_->xtype, cc_);
 
  353    spqrfactorization_=SuiteSparseQR_factorize<DofType>(SPQR_ORDERING_DEFAULT,SPQR_DEFAULT_TOL,A_,cc_);
 
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
 
TupleDiscreteFunctionSpace< typename DiscreteFunctions::DiscreteFunctionSpaceType ... > DiscreteFunctionSpaceType
type for the discrete function space this function lives in
Definition: discretefunction.hh:69
 
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:257
 
Dune namespace.
Definition: alignedallocator.hh:13
 
constexpr auto sorted(std::integer_sequence< T, II... > seq, Compare comp)
Sort a given sequence by the comparator comp.
Definition: integersequence.hh:119