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:256
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