dune-fem  2.4.1-rc
spqrsolver.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_SPQRSOLVER_HH
2 #define DUNE_FEM_SPQRSOLVER_HH
3 
4 #include <limits>
5 #include <iostream>
6 #include <type_traits>
7 #include <vector>
8 #include <algorithm>
9 
12 
14 #include <dune/fem/io/parameter.hh>
16 
17 #if HAVE_SPQR
18 #include <SuiteSparseQR.hpp>
19 
20 namespace Dune
21 {
22 namespace Fem
23 {
24 
41 template<class DF, class Op, bool symmetric=false>
42 class SPQROp:public Operator<DF, DF>
43 {
44  public:
45  typedef DF DiscreteFunctionType;
46  typedef Op OperatorType;
47 
48  // \brief The column-compressed matrix type.
49  typedef ColCompMatrix<typename OperatorType::MatrixType::MatrixBaseType> CCSMatrixType;
50  typedef typename DiscreteFunctionType::DofType DofType;
51  typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
52 
60  SPQROp(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter, const bool& verbose,
61  const ParameterReader &paramter = Parameter::container() ) :
62  op_(op), verbose_(verbose), ccsmat_(), isloaded_(false)
63  {
64  cc_ = new cholmod_common();
65  cholmod_l_start(cc_);
66  }
67 
74  SPQROp(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter,
75  const ParameterReader &parameter = Parameter::container() ) :
76  op_(op), verbose_(parameter.getValue<bool>("fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
77  {
78  cc_ = new cholmod_common();
79  cholmod_l_start(cc_);
80  }
81 
82  SPQROp(const OperatorType& op, const ParameterReader &parameter = Parameter::container() ) :
83  op_(op), verbose_(parameter.getValue<bool>("fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
84  {
85  cc_ = new cholmod_common();
86  cholmod_l_start(cc_);
87  }
88  // \brief Destructor.
89  ~SPQROp()
90  {
91  cholmod_l_finish(cc_);
92  }
93 
98  void operator()(const DiscreteFunctionType& arg, DiscreteFunctionType& dest) const
99  {
100  prepare();
101  apply(arg,dest);
102  finalize();
103  }
104 
105  // \brief Decompose matrix.
106  template<typename... A>
107  void prepare(A... ) const
108  {
109  if(!isloaded_)
110  {
111  ccsmat_ = op_.systemMatrix().matrix();
112  decompose();
113  isloaded_ = true;
114  }
115  }
116 
117  // \brief Free allocated memory.
118  inline void finalize() const
119  {
120  if(isloaded_)
121  {
122  ccsmat_.free();
123  cholmod_l_free_sparse(&A_, cc_);
124  cholmod_l_free_dense(&B_, cc_);
125  SuiteSparseQR_free<DofType>(&spqrfactorization_, cc_);
126  isloaded_ = false;
127  }
128  }
129 
136  void apply(const DofType*& arg, DofType*& dest) const
137  {
138  const std::size_t dimMat(ccsmat_.N());
139  // fill B
140  for(std::size_t k = 0; k != dimMat; ++k)
141  (static_cast<DofType*>(B_->x))[k] = arg[k];
142  cholmod_dense* BTemp = B_;
143  B_ = SuiteSparseQR_qmult<DofType>(0, spqrfactorization_, B_, cc_);
144  cholmod_dense* X = SuiteSparseQR_solve<DofType>(1, spqrfactorization_, B_, cc_);
145  cholmod_l_free_dense(&BTemp, cc_);
146  // fill x
147  for(std::size_t k = 0; k != dimMat; ++k)
148  dest[k] = (static_cast<DofType*>(X->x))[k];
149  cholmod_l_free_dense(&X, cc_);
150  // output some statistics
151  if(verbose_ > 0)
152  {
153  std::cout<<std::endl<<"Solving with SuiteSparseQR"<<std::endl;
154  std::cout<<"Flops Taken: "<<cc_->SPQR_flopcount<<std::endl;
155  std::cout<<"Analysis Time: "<<cc_->SPQR_analyze_time<<" s"<<std::endl;
156  std::cout<<"Factorize Time: "<<cc_->SPQR_factorize_time<<" s"<<std::endl;
157  std::cout<<"Backsolve Time: "<<cc_->SPQR_solve_time<<" s"<<std::endl;
158  std::cout<<"Peak Memory Usage: "<<cc_->memory_usage<<" bytes"<<std::endl;
159  std::cout<<"Rank Estimate: "<<cc_->SPQR_istat[4]<<std::endl<<std::endl;
160  }
161  }
162 
169  void apply(const AdaptiveDiscreteFunction<DiscreteFunctionSpaceType>& arg,
170  AdaptiveDiscreteFunction<DiscreteFunctionSpaceType>& dest) const
171  {
172  const DofType* argPtr(arg.leakPointer());
173  DofType* destPtr(dest.leakPointer());
174  apply(argPtr,destPtr);
175  }
176 
183  void apply(const ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& arg,
184  ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& dest) const
185  {
186  // copy DOF arg into a consecutive vector
187  std::vector<DofType> vecArg(arg.size());
188  std::copy(arg.dbegin(),arg.dend(),vecArg.begin());
189  std::vector<DofType> vecDest(dest.size());
190  // apply operator
191  const DofType* argDataPtr(vecArg.data());
192  DofType* destDataPtr(vecDest.data());
193  apply(argDataPtr,destDataPtr);
194  // copy back solution into dest
195  std::copy(vecDest.begin(),vecDest.end(),dest.dbegin());
196  }
197 
198  inline void printTexInfo(std::ostream& out) const
199  {
200  out<<"Solver: SPQR direct solver";
201  out<<"\\\\ \n";
202  }
203 
204  inline double averageCommTime() const
205  {
206  return 0.0;
207  }
208 
209  inline int iterations() const
210  {
211  return 0;
212  }
213 
217  inline SuiteSparseQR_factorization<DofType>*& getFactorization()
218  {
219  return spqrfactorization_;
220  }
221 
225  inline CCSMatrixType& getCCSMatrix()
226  {
227  return ccsmat_;
228  }
229 
230  private:
231  const OperatorType& op_;
232  const bool verbose_;
233  mutable CCSMatrixType ccsmat_;
234  mutable bool isloaded_;
235  mutable cholmod_common* cc_;
236  mutable cholmod_sparse* A_;
237  mutable cholmod_dense* B_;
238  mutable SuiteSparseQR_factorization<DofType>* spqrfactorization_;
239 
240  // /brief Computes the SPQR decomposition.
241  void decompose() const
242  {
243  const std::size_t dimMat(ccsmat_.N());
244  const int nnz(ccsmat_.getColStart()[dimMat]);
245  // initialise the matrix A
246  bool sorted(true);
247  bool packed(true);
248  bool real(std::is_same<DofType,double>::value);
249  A_ = cholmod_l_allocate_sparse(dimMat, dimMat, nnz, sorted, packed, symmetric, real, cc_);
250  // copy all the entries of Ap, Ai, Ax
251  for(std::size_t k = 0; k != (dimMat+1); ++k)
252  (static_cast<long int *>(A_->p))[k] = ccsmat_.getColStart()[k];
253  for(std::size_t k = 0; k != nnz; ++k)
254  {
255  (static_cast<long int*>(A_->i))[k] = ccsmat_.getRowIndex()[k];
256  (static_cast<DofType*>(A_->x))[k] = ccsmat_.getValues()[k];
257  }
258  // initialise the vector B
259  B_ = cholmod_l_allocate_dense(dimMat, 1, dimMat, A_->xtype, cc_);
260  // compute factorization of A
261  spqrfactorization_=SuiteSparseQR_factorize<DofType>(SPQR_ORDERING_DEFAULT,SPQR_DEFAULT_TOL,A_,cc_);
262  }
263 };
264 
265 }
266 }
267 
268 #endif // #if HAVE_SPQR
269 
270 #endif // #ifndef DUNE_FEM_SPQRSOLVER_HH
BasicParameterReader< std::function< const std::string *(const std::string &, const std::string *) > > ParameterReader
Definition: reader.hh:264
Definition: coordinate.hh:4
static ParameterContainer & container()
Definition: io/parameter.hh:190
double real(const std::complex< Double > &x)
Definition: double.hh:890