dune-istl 2.12-git
Loading...
Searching...
No Matches
spqr.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5#ifndef DUNE_ISTL_SPQR_HH
6#define DUNE_ISTL_SPQR_HH
7
8#if HAVE_SUITESPARSE_SPQR || defined DOXYGEN
9
10#include <complex>
11#include <type_traits>
12
13#include <SuiteSparseQR.hpp>
14
17
20#include <dune/istl/foreach.hh>
21#include <dune/istl/solvers.hh>
24
25namespace Dune {
37 // forward declarations
38 template<class M, class T, class TM, class TD, class TA>
39 class SeqOverlappingSchwarz;
40
41 template<class T, bool tag>
42 struct SeqOverlappingSchwarzAssemblerHelper;
43
56 template<typename M>
57 class SPQR : public InverseOperator<
58 typename DefaultMatrixVectorTraits<M>::domain_type,
59 typename DefaultMatrixVectorTraits<M>::range_type>
60 {
61 public:
63 typedef M Matrix;
64 typedef M matrix_type;
67
69 typedef ISTL::Impl::BCCSMatrix<field_type,int> SPQRMatrix;
71 typedef ISTL::Impl::BCCSMatrixInitializer<M, int> MatrixInitializer;
76
82
91 SPQR(const Matrix& matrix, int verbose=0) : matrixIsLoaded_(false), verbose_(verbose)
92 {
93 //check whether T is a supported type
95 "Unsupported Type in SPQR (only double and std::complex<double> supported)");
96 cc_ = new cholmod_common();
97 cholmod_l_start(cc_);
98 setMatrix(matrix);
99 }
100
109 SPQR(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false), verbose_(verbose)
110 {
111 //check whether T is a supported type
113 "Unsupported Type in SPQR (only double and std::complex<double> supported)");
114 cc_ = new cholmod_common();
115 cholmod_l_start(cc_);
116 setMatrix(matrix);
117 }
118
128 SPQR(const Matrix& matrix, const ParameterTree& config)
129 : SPQR(matrix, config.get<int>("verbose", 0))
130 {}
131
133 SPQR() : matrixIsLoaded_(false), verbose_(0)
134 {
135 //check whether T is a supported type
137 "Unsupported Type in SPQR (only double and std::complex<double> supported)");
138 cc_ = new cholmod_common();
139 cholmod_l_start(cc_);
140 }
141
143 virtual ~SPQR()
144 {
145 if ((spqrMatrix_.N() + spqrMatrix_.M() > 0) || matrixIsLoaded_)
146 free();
147 cholmod_l_finish(cc_);
148 }
149
152 {
153 // copy b into the internal storage
154 Impl::flatVectorForEachMasked(b, maskVector_, [&](auto const& b_i, std::size_t i) {
155 (static_cast<field_type*>(B_->x))[i] = b_i; });
156
157 cholmod_dense* BTemp = B_;
158 B_ = SuiteSparseQR_qmult<field_type>(0, spqrfactorization_, B_, cc_);
159 cholmod_dense* X = SuiteSparseQR_solve<field_type>(1, spqrfactorization_, B_, cc_);
160 cholmod_l_free_dense(&BTemp, cc_);
161
162 // copy the internal solution to x
163 Impl::flatVectorForEachMasked(x, maskVector_, [&](auto& x_i, std::size_t i) {
164 x_i = (static_cast<field_type const*>(X->x))[i]; });
165
166 cholmod_l_free_dense(&X, cc_);
167 // this is a direct solver
168 res.iterations = 1;
169 res.converged = true;
170 if(verbose_ > 0)
171 {
172 std::cout<<std::endl<<"Solving with SuiteSparseQR"<<std::endl;
173 std::cout<<"Flops Taken: "<<cc_->SPQR_flopcount<<std::endl;
174 std::cout<<"Analysis Time: "<<cc_->SPQR_analyze_time<<" s"<<std::endl;
175 std::cout<<"Factorize Time: "<<cc_->SPQR_factorize_time<<" s"<<std::endl;
176 std::cout<<"Backsolve Time: "<<cc_->SPQR_solve_time<<" s"<<std::endl;
177 std::cout<<"Peak Memory Usage: "<<cc_->memory_usage<<" bytes"<<std::endl;
178 std::cout<<"Rank Estimate: "<<cc_->SPQR_istat[4]<<std::endl<<std::endl;
179 }
180 }
181
183 void apply (domain_type& x, range_type& b, [[maybe_unused]] double reduction, InverseOperatorResult& res) override
184 {
185 apply(x, b, res);
186 }
187
188 void setOption([[maybe_unused]] unsigned int option, [[maybe_unused]] double value)
189 {}
190
192 void setMatrix(const Matrix& matrix)
193 {
194 if ((spqrMatrix_.N() + spqrMatrix_.M() > 0) || matrixIsLoaded_)
195 free();
196
197 if (spqrMatrix_.N() + spqrMatrix_.M() + spqrMatrix_.nonzeroes() != 0)
198 spqrMatrix_.free();
199 spqrMatrix_.setSize(MatrixDimension<Matrix>::rowdim(matrix),
201 ISTL::Impl::BCCSMatrixInitializer<Matrix, int> initializer(spqrMatrix_);
202
203 copyToBCCSMatrix(initializer, matrix);
204
205 maskVector_.clear();
206 maskVector_.resize(matrix.N(), true);
207
208 decompose();
209 }
210
211 template<class S>
212 void setSubMatrix(const Matrix& matrix, const S& rowIndexSet)
213 {
214 if ((spqrMatrix_.N() + spqrMatrix_.M() > 0) || matrixIsLoaded_)
215 free();
216
217 if (spqrMatrix_.N() + spqrMatrix_.M() + spqrMatrix_.nonzeroes() != 0)
218 spqrMatrix_.free();
219
220 spqrMatrix_.setSize(rowIndexSet.size()*MatrixDimension<Matrix>::rowdim(matrix) / matrix.N(),
221 rowIndexSet.size()*MatrixDimension<Matrix>::coldim(matrix) / matrix.M());
222 MatrixInitializer initializer(spqrMatrix_);
223
224 copyToBCCSMatrix(initializer, ISTL::Impl::MatrixRowSubset<Matrix,std::set<std::size_t> >(matrix,rowIndexSet));
225
226 maskVector_.clear();
227 maskVector_.resize(matrix.N(), false);
228 for (auto i : rowIndexSet)
229 maskVector_[i] = true;
230
231 decompose();
232 }
233
238 inline void setVerbosity(int v)
239 {
240 verbose_=v;
241 }
242
247 inline SuiteSparseQR_factorization<field_type>* getFactorization()
248 {
249 return spqrfactorization_;
250 }
251
257 {
258 return spqrMatrix_;
259 }
260
265 void free()
266 {
267 cholmod_l_free_sparse(&A_, cc_);
268 cholmod_l_free_dense(&B_, cc_);
269 SuiteSparseQR_free<field_type>(&spqrfactorization_, cc_);
270 spqrMatrix_.free();
271 matrixIsLoaded_ = false;
272 }
273
275 inline const char* name()
276 {
277 return "SPQR";
278 }
279
280 private:
281 template<class,class,class,class,class>
283
285
287 static constexpr int xtype ()
288 {
289 return std::is_same_v<field_type,double> ? CHOLMOD_REAL : CHOLMOD_COMPLEX;
290 }
291
293 void decompose()
294 {
295 const std::size_t nrows(spqrMatrix_.N());
296 const std::size_t ncols(spqrMatrix_.M());
297 const std::size_t nnz(spqrMatrix_.getColStart()[ncols]);
298
299 // initialise the matrix A (sorted, packed, unsymmetric, real/complex entries)
300 A_ = cholmod_l_allocate_sparse(nrows, ncols, nnz, 1, 1, 0, xtype(), cc_);
301
302 // copy all the entries of Ap, Ai, Ax
303 for(std::size_t k = 0; k != (ncols+1); ++k)
304 (static_cast<long int *>(A_->p))[k] = spqrMatrix_.getColStart()[k];
305
306 for(std::size_t k = 0; k != nnz; ++k)
307 {
308 (static_cast<long int*>(A_->i))[k] = spqrMatrix_.getRowIndex()[k];
309 (static_cast<field_type*>(A_->x))[k] = spqrMatrix_.getValues()[k];
310 }
311
312 // initialise the vector B
313 B_ = cholmod_l_allocate_dense(nrows, 1, nrows, xtype(), cc_);
314 // compute factorization of A
315 spqrfactorization_=SuiteSparseQR_factorize<field_type>(SPQR_ORDERING_DEFAULT,SPQR_DEFAULT_TOL,A_,cc_);
316 }
317
318 SPQRMatrix spqrMatrix_;
319 bool matrixIsLoaded_;
320 int verbose_;
321 cholmod_common* cc_;
322 cholmod_sparse* A_;
323 cholmod_dense* B_;
324 SuiteSparseQR_factorization<field_type>* spqrfactorization_;
325 std::vector<bool> maskVector_;
326 };
327
328 template<typename M>
330 {
331 enum {value = true};
332 };
333
334 template<typename T, typename A>
336 {
337 enum {value = true};
338 };
339
341 [](auto opTraits, const auto& op, const Dune::ParameterTree& config)
342 -> std::shared_ptr<typename decltype(opTraits)::solver_type>
343 {
344 using OpTraits = decltype(opTraits);
345 using M = typename OpTraits::matrix_type;
346 // works only for sequential operators
347 if constexpr (OpTraits::isParallel){
348 if(opTraits.getCommOrThrow(op).communicator().size() > 1)
349 DUNE_THROW(Dune::InvalidStateException, "SPQR works only for sequential operators.");
350 }
351 // check if SPQR<M>* is convertible to
352 // InverseOperator*. This allows only the explicit
353 // specialized variants of SPQR
354 // std::complex is temporary disabled, because it fails if libc++ is used
355 if constexpr (std::is_convertible_v<SPQR<M>*,
356 Dune::InverseOperator<typename OpTraits::domain_type,
357 typename OpTraits::range_type>*> &&
358 std::is_same_v<typename FieldTraits<M>::field_type, double>
359 ){
360 const auto& A = opTraits.getAssembledOpOrThrow(op);
361 const M& mat = A->getmat();
362 int verbose = config.get("verbose", 0);
363 return std::make_shared<Dune::SPQR<M>>(mat,verbose);
364 }
366 "Unsupported Type in SPQR (only FieldMatrix<double,...> supported)");
367 });
368
369} // end namespace Dune
370
371
372#endif //HAVE_SUITESPARSE_SPQR
373#endif //DUNE_ISTL_SPQR_HH
#define DUNE_REGISTER_SOLVER(name,...)
Definition solverregistry.hh:17
Templates characterizing the type of a solver.
Implementations of the inverse operator interface.
M Matrix
The matrix type.
Definition spqr.hh:63
DefaultMatrixVectorTraits< M >::range_type range_type
The type of the range of the solver.
Definition spqr.hh:75
void free()
Free allocated space.
Definition spqr.hh:265
void setSubMatrix(const Matrix &matrix, const S &rowIndexSet)
Definition spqr.hh:212
SPQR()
Default constructor.
Definition spqr.hh:133
void setMatrix(const Matrix &matrix)
Initialize data from given matrix.
Definition spqr.hh:192
SolverCategory::Category category() const override
Category of the solver (see SolverCategory::Category)
Definition spqr.hh:78
SuiteSparseQR_factorization< field_type > * getFactorization()
Return the matrix factorization.
Definition spqr.hh:247
virtual ~SPQR()
Destructor.
Definition spqr.hh:143
void setOption(unsigned int option, double value)
Definition spqr.hh:188
void setVerbosity(int v)
Sets the verbosity level for the solver.
Definition spqr.hh:238
const char * name()
Get method name.
Definition spqr.hh:275
ISTL::Impl::BCCSMatrixInitializer< M, int > MatrixInitializer
Type of an associated initializer class.
Definition spqr.hh:71
ISTL::Impl::BCCSMatrix< field_type, int > SPQRMatrix
The corresponding SuperLU Matrix type.
Definition spqr.hh:69
void apply(domain_type &x, range_type &b, InverseOperatorResult &res) override
Apply inverse operator,.
Definition spqr.hh:151
void apply(domain_type &x, range_type &b, double reduction, InverseOperatorResult &res) override
apply inverse operator, with given convergence criteria.
Definition spqr.hh:183
FieldTraits< M >::field_type field_type
The type of the entries.
Definition spqr.hh:66
DefaultMatrixVectorTraits< M >::domain_type domain_type
The type of the domain of the solver.
Definition spqr.hh:73
SPQR(const Matrix &matrix, int verbose=0)
Construct a solver object from a BCRSMatrix.
Definition spqr.hh:91
M matrix_type
Definition spqr.hh:64
SPQR(const Matrix &matrix, int verbose, bool)
Constructor for compatibility with SuperLU standard constructor.
Definition spqr.hh:109
SPQRMatrix & getInternalMatrix()
Return the column coppressed matrix.
Definition spqr.hh:256
SPQR(const Matrix &matrix, const ParameterTree &config)
Constructs the SPQR solver.
Definition spqr.hh:128
Matrix & mat
Definition matrixmatrix.hh:347
static constexpr size_type M()
#define DUNE_THROW(E,...)
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Definition matrixutils.hh:221
A sparse block matrix with compressed row storage.
Definition bcrsmatrix.hh:468
Definition defaultmatrixvectortraits.hh:47
std::string get(const std::string &key, const std::string &defaultValue) const
Sequential overlapping Schwarz preconditioner.
Definition overlappingschwarz.hh:755
Definition overlappingschwarz.hh:694
Statistics about the application of an inverse operator.
Definition solver.hh:50
int iterations
Number of iterations.
Definition solver.hh:69
bool converged
True if convergence criterion has been met.
Definition solver.hh:75
Abstract base class for all solvers.
Definition solver.hh:101
Category
Definition solvercategory.hh:23
@ sequential
Category for sequential solvers.
Definition solvercategory.hh:25
Definition solverregistry.hh:37
Definition solvertype.hh:16
@ value
Whether this is a direct solver.
Definition solvertype.hh:24
Definition solvertype.hh:30
@ value
whether the solver internally uses column compressed storage
Definition solvertype.hh:36
The SPQR package to directly solve linear systems for ISTL matrices.
Definition spqr.hh:60
T clear(T... args)
T endl(T... args)
T resize(T... args)