1#ifndef DUNE_FEM_SPQRSOLVER_HH
2#define DUNE_FEM_SPQRSOLVER_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
53 typedef DiscreteFunction DiscreteFunctionType;
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;
62 typedef SPQRInverseOperator< DiscreteFunction, symmetric, Matrix > InverseOperatorType;
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;
78 typedef DF DiscreteFunctionType;
79 typedef typename BaseType :: OperatorType OperatorType;
80 typedef typename BaseType :: SolverDiscreteFunctionType SolverDiscreteFunctionType;
83 typedef typename Traits :: CCSMatrixType CCSMatrixType;
84 typedef typename DiscreteFunctionType::DofType DofType;
85 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
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
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_);
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
249 std::copy(arg.dbegin(),arg.dend(),vecArg.begin());
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
269 auto vecArgIt(vecArg.begin());
274 apply(vecArg.data(),vecDest.data());
276 auto vecDestIt(vecDest.begin());
287 void printDecompositionInfo()
const
301 void setMaxIterations(
int ) {}
308 return spqrfactorization_;
314 CCSMatrixType& getCCSMatrix()
const
321 using BaseType :: operator_;
322 using BaseType :: assembledOperator_;
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();
336 const std::size_t nnz(ccsmat.getColStart()[dimMat]);
341 A_ = cholmod_l_allocate_sparse(dimMat, dimMat, nnz, sorted, packed, symmetric, real, cc_);
344 (
static_cast<long int *
>(A_->p))[k] = ccsmat.getColStart()[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_);
void * getFactorization()
Dune::BCRSMatrix< FieldMatrix< T, n, m >, TA > Matrix
static TupleAccessTraits< typenameAtType< N, Tuple >::Type >::NonConstType get(Tuple &t)
constexpr auto sorted(std::integer_sequence< T, II... >, Compare comp)
double real(const std::complex< Double > &x)
Definition double.hh:906
IteratorRange< typename DF::DofIteratorType > dofs(DF &df)
Iterates over all DOFs.
Definition rangegenerators.hh:76