DUNE-FEM (unstable)

spqrsolver.hh
1#ifndef DUNE_FEM_SPQRSOLVER_HH
2#define DUNE_FEM_SPQRSOLVER_HH
3
4#include <algorithm>
5#include <iostream>
6#include <tuple>
7#include <vector>
8#include <utility>
9
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>
20
21#if HAVE_SUITESPARSE_SPQR
22#include <SuiteSparseQR.hpp>
23
24namespace Dune
25{
26namespace Fem
27{
28
46template<class DiscreteFunction, bool symmetric=false,
47 class Matrix = SparseRowMatrix< typename DiscreteFunction::DiscreteFunctionSpaceType::RangeFieldType > >
48class SPQRInverseOperator;
49
50template<class DiscreteFunction, bool symmetric, class Matrix>
51struct SPQRInverseOperatorTraits
52{
53 typedef DiscreteFunction DiscreteFunctionType;
54 typedef AdaptiveDiscreteFunction< typename DiscreteFunction::DiscreteFunctionSpaceType > SolverDiscreteFunctionType;
55
57 typedef OperatorType PreconditionerType;
58
59 typedef Fem::SparseRowLinearOperator< DiscreteFunction, DiscreteFunction, Matrix > AssembledOperatorType;
60 typedef ColCompMatrix<typename AssembledOperatorType::MatrixType::MatrixBaseType,int > CCSMatrixType;
61
62 typedef SPQRInverseOperator< DiscreteFunction, symmetric, Matrix > InverseOperatorType;
63 typedef SolverParameter SolverParameterType;
64};
65
66
67
68template< class DF, bool symmetric, class Matrix >
69class SPQRInverseOperator : public InverseOperatorInterface< SPQRInverseOperatorTraits< DF, symmetric, Matrix > >
70{
71 typedef SPQRInverseOperatorTraits< DF, symmetric, Matrix > Traits;
72 typedef InverseOperatorInterface< Traits > BaseType;
73 typedef SPQRInverseOperator< DF, symmetric, Matrix > ThisType;
74public:
76 static const bool preconditioningAvailable = false;
77
78 typedef DF DiscreteFunctionType;
79 typedef typename BaseType :: OperatorType OperatorType;
80 typedef typename BaseType :: SolverDiscreteFunctionType SolverDiscreteFunctionType;
81
82 // \brief The column-compressed matrix type.
83 typedef typename Traits :: CCSMatrixType CCSMatrixType;
84 typedef typename DiscreteFunctionType::DofType DofType;
85 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
86
94 SPQRInverseOperator(const double& redEps, const double& absLimit, const int& maxIter, const bool& verbose,
95 const ParameterReader &parameter = Parameter::container() ) :
96 SPQRInverseOperator(parameter)
97 {}
98
105 SPQRInverseOperator(const double& redEps, const double& absLimit, const int& maxIter,
106 const ParameterReader &parameter = Parameter::container() ) :
107 SPQRInverseOperator(parameter)
108 {}
109
110 SPQRInverseOperator(const SolverParameter& parameter = SolverParameter( Parameter::container() ) )
111 : BaseType(parameter)
112 , verbose_(BaseType::verbose())
113 , ccsmat_(), cc_(new cholmod_common())
114 {
115 cholmod_l_start(cc_);
116 }
117
125 SPQRInverseOperator(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter, const bool& verbose,
126 const ParameterReader &parameter = Parameter::container() ) :
127 SPQRInverseOperator(parameter)
128 {
129 bind(op);
130 }
131
138 SPQRInverseOperator(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter,
139 const ParameterReader &parameter = Parameter::container() ) :
140 SPQRInverseOperator(parameter)
141 {
142 bind(op);
143 }
144
145 SPQRInverseOperator(const OperatorType& op, const ParameterReader &parameter = Parameter::container() ) :
146 SPQRInverseOperator(parameter)
147 {
148 bind(op);
149 }
150
151 SPQRInverseOperator(const SPQRInverseOperator& other) :
152 SPQRInverseOperator(other.parameter())
153 {
154 if( other.operator_ )
155 bind( *(other.operator_) );
156 }
157
158 // \brief Destructor.
159 ~SPQRInverseOperator()
160 {
161 finalize();
162 cholmod_l_finish(cc_);
163 delete cc_;
164 }
165
166 using BaseType :: bind;
167
168 void unbind ()
169 {
170 BaseType::unbind();
171 finalize();
172 }
173
174 // \brief Decompose matrix.
175 template<typename... A>
176 void prepare(A... ) const
177 {
178 if(assembledOperator_ && !ccsmat_ )
179 {
180 ccsmat_.reset( new CCSMatrixType(assembledOperator_->exportMatrix() ) );
181 decompose();
182 }
183 }
184
185 // \brief Free allocated memory.
186 virtual void finalize()
187 {
188 if( ccsmat_ )
189 {
190 ccsmat_.reset();
191 cholmod_l_free_sparse(&A_, cc_);
192 cholmod_l_free_dense(&B_, cc_);
193 SuiteSparseQR_free<DofType>(&spqrfactorization_, cc_);
194 }
195 }
196
203 int apply (const DofType* arg, DofType* dest) const
204 {
205 assert(ccsmat_);
206 const std::size_t dimMat(ccsmat_->N());
207 // fill B
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_);
214 // fill x
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_);
218 // output some statistics
219 if(verbose_ > 0)
220 printDecompositionInfo();
221 return 1;
222 }
223
230 int apply(const SolverDiscreteFunctionType& arg, SolverDiscreteFunctionType& dest) const
231 {
232 prepare();
233 apply(arg.leakPointer(),dest.leakPointer());
234 const_cast<ThisType*>(this)->finalize();
235 return 1;
236 }
237
244 int apply(const ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& arg,
245 ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& dest) const
246 {
247 // copy DOF's arg into a consecutive vector
248 std::vector<DofType> vecArg(arg.size());
249 std::copy(arg.dbegin(),arg.dend(),vecArg.begin());
250 std::vector<DofType> vecDest(dest.size());
251 // apply operator
252 apply(vecArg.data(),vecDest.data());
253 // copy back solution into dest
254 std::copy(vecDest.begin(),vecDest.end(),dest.dbegin());
255 return 1;
256 }
257
264 template<typename... DFs>
265 int apply(const TupleDiscreteFunction<DFs...>& arg,TupleDiscreteFunction<DFs...>& dest) const
266 {
267 // copy DOF's arg into a consecutive vector
268 std::vector<DofType> vecArg(arg.size());
269 auto vecArgIt(vecArg.begin());
270 Hybrid::forEach(std::make_index_sequence<sizeof...(DFs)>{},
271 [&](auto i){vecArgIt=std::copy(std::get<i>(arg).dbegin(),std::get<i>(arg).dend(),vecArgIt);});
272 std::vector<DofType> vecDest(dest.size());
273 // apply operator
274 apply(vecArg.data(),vecDest.data());
275 // copy back solution into dest
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++));});
278 return 1;
279 }
280
281 void printTexInfo(std::ostream& out) const
282 {
283 out<<"Solver: SPQR direct solver"<<std::endl;
284 }
285
286 // \brief Print some statistics about the SPQR decomposition.
287 void printDecompositionInfo() const
288 {
289 if( ccsmat_ )
290 {
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;
298 }
299 }
300
301 void setMaxIterations( int ) {}
302
306 SuiteSparseQR_factorization<DofType>* getFactorization()
307 {
308 return spqrfactorization_;
309 }
310
314 CCSMatrixType& getCCSMatrix() const
315 {
316 assert( ccsmat_ );
317 return *ccsmat_;
318 }
319
320private:
321 using BaseType :: operator_;
322 using BaseType :: assembledOperator_;
323 const bool verbose_;
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;
329
330 // \brief Computes the SPQR decomposition.
331 void decompose() const
332 {
333 CCSMatrixType& ccsmat = getCCSMatrix();
334
335 const std::size_t dimMat(ccsmat.N());
336 const std::size_t nnz(ccsmat.getColStart()[dimMat]);
337 // initialise the matrix A
338 bool sorted(true);
339 bool packed(true);
340 bool real(std::is_same<DofType,double>::value);
341 A_ = cholmod_l_allocate_sparse(dimMat, dimMat, nnz, sorted, packed, symmetric, real, cc_);
342 // copy all the entries of Ap, Ai, Ax
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)
346 {
347 (static_cast<long int*>(A_->i))[k] = ccsmat.getRowIndex()[k];
348 (static_cast<DofType*>(A_->x))[k] = ccsmat.getValues()[k];
349 }
350 // initialise the vector B
351 B_ = cholmod_l_allocate_dense(dimMat, 1, dimMat, A_->xtype, cc_);
352 // compute factorization of A
353 spqrfactorization_=SuiteSparseQR_factorize<DofType>(SPQR_ORDERING_DEFAULT,SPQR_DEFAULT_TOL,A_,cc_);
354 }
355};
356
357
358} // end namespace Fem
359} // end namespace Dune
360
361#endif // #if HAVE_SUITESPARSE_SPQR
362
363#endif // #ifndef DUNE_FEM_SPQRSOLVER_HH
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)