dune-istl 2.12-git
Loading...
Searching...
No Matches
ldl.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_LDL_HH
6#define DUNE_ISTL_LDL_HH
7
8#if HAVE_SUITESPARSE_LDL || defined DOXYGEN
9
10#include <memory>
11#include <type_traits>
12
13#ifdef __cplusplus
14extern "C"
15{
16#include <ldl.h>
17#include <amd.h>
18}
19#endif
20
22
25#include <dune/istl/foreach.hh>
26#include <dune/istl/solvers.hh>
29
30namespace Dune {
42 // forward declarations
43 template<class M, class T, class TM, class TD, class TA>
44 class SeqOverlappingSchwarz;
45
46 template<class T, bool tag>
47 struct SeqOverlappingSchwarzAssemblerHelper;
48
61 template<typename M>
62 class LDL : public InverseOperator<
63 typename DefaultMatrixVectorTraits<M>::domain_type,
64 typename DefaultMatrixVectorTraits<M>::range_type>
65 {
66 public:
68 typedef M Matrix;
69 typedef M matrix_type;
71
73 typedef Dune::ISTL::Impl::BCCSMatrix<field_type,int> LDLMatrix;
75 typedef ISTL::Impl::BCCSMatrixInitializer<M, int> MatrixInitializer;
80
86
96 LDL(const Matrix& matrix, int verbose=0) : matrixIsLoaded_(false), verbose_(verbose)
97 {
98 //check whether T is a supported type
99 static_assert(std::is_same<field_type,double>::value,"Unsupported Type in LDL (only double supported)");
100 setMatrix(matrix);
101 }
102
112 LDL(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false), verbose_(verbose)
113 {
114 //check whether T is a supported type
115 static_assert(std::is_same<field_type,double>::value,"Unsupported Type in LDL (only double supported)");
116 setMatrix(matrix);
117 }
118
128 LDL(const Matrix& matrix, const ParameterTree& config)
129 : LDL(matrix, config.get<int>("verbose", 0))
130 {}
131
133 LDL() : matrixIsLoaded_(false), verbose_(0)
134 {}
135
137 virtual ~LDL()
138 {
139 if ((ldlMatrix_.N() + ldlMatrix_.M() > 0) || matrixIsLoaded_)
140 free();
141 }
142
143 public:
146 {
147 BlockVector<field_type> B(ldlMatrix_.N()), X(ldlMatrix_.M());
148 Impl::flatVectorForEachMasked(b, maskVector_, [&](auto const& b_i, std::size_t i) { B[i] = b_i; });
149 apply(X.data(), B.data());
150 Impl::flatVectorForEachMasked(x, maskVector_, [&](auto& x_i, std::size_t i) { x_i = X[i]; });
151
152 // this is a direct solver
153 res.iterations = 1;
154 res.converged = true;
155 }
156
158 void apply(domain_type& x, range_type& b, [[maybe_unused]] double reduction, InverseOperatorResult& res) override
159 {
160 apply(x,b,res);
161 }
162
169 {
170 const int dimMat(ldlMatrix_.N());
171 ldl_perm(dimMat, Y_, b, P_);
172 ldl_lsolve(dimMat, Y_, Lp_, Li_, Lx_);
173 ldl_dsolve(dimMat, Y_, D_);
174 ldl_ltsolve(dimMat, Y_, Lp_, Li_, Lx_);
175 ldl_permt(dimMat, x, Y_, P_);
176 }
177
178 void setOption([[maybe_unused]] unsigned int option, [[maybe_unused]] double value)
179 {}
180
182 void setMatrix(const Matrix& matrix)
183 {
184 if ((ldlMatrix_.N() + ldlMatrix_.M() > 0) || matrixIsLoaded_)
185 free();
186
187 if (ldlMatrix_.N() + ldlMatrix_.M() + ldlMatrix_.nonzeroes() != 0)
188 ldlMatrix_.free();
189 ldlMatrix_.setSize(MatrixDimension<Matrix>::rowdim(matrix),
191 MatrixInitializer initializer(ldlMatrix_);
192
193 copyToBCCSMatrix(initializer, matrix);
194
195 maskVector_.clear();
196 maskVector_.resize(matrix.N(), true);
197
198 decompose();
199 }
200
201 template<class S>
202 void setSubMatrix(const Matrix& matrix, const S& rowIndexSet)
203 {
204 if ((ldlMatrix_.N() + ldlMatrix_.M() > 0) || matrixIsLoaded_)
205 free();
206
207 if (ldlMatrix_.N() + ldlMatrix_.M() + ldlMatrix_.nonzeroes() != 0)
208 ldlMatrix_.free();
209
210 ldlMatrix_.setSize(rowIndexSet.size()*MatrixDimension<Matrix>::rowdim(matrix) / matrix.N(),
211 rowIndexSet.size()*MatrixDimension<Matrix>::coldim(matrix) / matrix.M());
212 MatrixInitializer initializer(ldlMatrix_);
213
214 copyToBCCSMatrix(initializer, ISTL::Impl::MatrixRowSubset<Matrix,std::set<std::size_t> >(matrix,rowIndexSet));
215
216 maskVector_.clear();
217 maskVector_.resize(matrix.N(), false);
218 for (auto i : rowIndexSet)
219 maskVector_[i] = true;
220
221 decompose();
222 }
223
228 inline void setVerbosity(int v)
229 {
230 verbose_=v;
231 }
232
238 {
239 return ldlMatrix_;
240 }
241
246 void free()
247 {
248 delete [] D_;
249 delete [] Y_;
250 delete [] Lp_;
251 delete [] Lx_;
252 delete [] Li_;
253 delete [] P_;
254 delete [] Pinv_;
255 ldlMatrix_.free();
256 matrixIsLoaded_ = false;
257 }
258
260 inline const char* name()
261 {
262 return "LDL";
263 }
264
269 inline double* getD()
270 {
271 return D_;
272 }
273
278 inline int* getLp()
279 {
280 return Lp_;
281 }
282
287 inline int* getLi()
288 {
289 return Li_;
290 }
291
296 inline double* getLx()
297 {
298 return Lx_;
299 }
300
301 private:
302 template<class,class,class,class,class>
304
306
308 void decompose()
309 {
310 // allocate vectors
311 const int dimMat(ldlMatrix_.N());
312 D_ = new double [dimMat];
313 Y_ = new double [dimMat];
314 Lp_ = new int [dimMat + 1];
315 Parent_ = new int [dimMat];
316 Lnz_ = new int [dimMat];
317 Flag_ = new int [dimMat];
318 Pattern_ = new int [dimMat];
319 P_ = new int [dimMat];
320 Pinv_ = new int [dimMat];
321
322 double Info [AMD_INFO];
323 if(amd_order (dimMat, ldlMatrix_.getColStart(), ldlMatrix_.getRowIndex(), P_, (double *) NULL, Info) < AMD_OK)
324 DUNE_THROW(InvalidStateException,"Error: AMD failed!");
325 if(verbose_ > 0)
326 amd_info (Info);
327 // compute the symbolic factorisation
328 ldl_symbolic(dimMat, ldlMatrix_.getColStart(), ldlMatrix_.getRowIndex(), Lp_, Parent_, Lnz_, Flag_, P_, Pinv_);
329 // initialise those entries of additionalVectors_ whose dimension is known only now
330 Lx_ = new double [Lp_[dimMat]];
331 Li_ = new int [Lp_[dimMat]];
332 // compute the numeric factorisation
333 const int rank(ldl_numeric(dimMat, ldlMatrix_.getColStart(), ldlMatrix_.getRowIndex(), ldlMatrix_.getValues(),
334 Lp_, Parent_, Lnz_, Li_, Lx_, D_, Y_, Pattern_, Flag_, P_, Pinv_));
335 // free temporary vectors
336 delete [] Flag_;
337 delete [] Pattern_;
338 delete [] Parent_;
339 delete [] Lnz_;
340
341 if(rank!=dimMat)
342 DUNE_THROW(InvalidStateException,"Error: LDL factorisation failed!");
343 }
344
345 LDLMatrix ldlMatrix_;
346 bool matrixIsLoaded_;
347 int verbose_;
348 int* Lp_;
349 int* Parent_;
350 int* Lnz_;
351 int* Flag_;
352 int* Pattern_;
353 int* P_;
354 int* Pinv_;
355 double* D_;
356 double* Y_;
357 double* Lx_;
358 int* Li_;
359
360 std::vector<bool> maskVector_;
361 };
362
363 template<typename M>
365 {
366 enum {value = true};
367 };
368
369 template<typename T, typename A>
371 {
372 enum {value = true};
373 };
374
376 [](auto opTraits, const auto& op, const Dune::ParameterTree& config)
377 -> std::shared_ptr<typename decltype(opTraits)::solver_type>
378 {
379 using OpTraits = decltype(opTraits);
380 using M = typename OpTraits::matrix_type;
381 // works only for sequential operators
382 if constexpr (OpTraits::isParallel){
383 if(opTraits.getCommOrThrow(op).communicator().size() > 1)
384 DUNE_THROW(Dune::InvalidStateException, "LDL works only for sequential operators.");
385 }
386 // check if LDL<M>* is convertible to
387 // InverseOperator*. This allows only the explicit
388 // specialized variants of LDL
389 if constexpr (std::is_convertible_v<LDL<M>*,
390 Dune::InverseOperator<typename OpTraits::domain_type,
391 typename OpTraits::range_type>*> &&
392 std::is_same_v<typename FieldTraits<M>::field_type, double>
393 ){
394 const auto& A = opTraits.getAssembledOpOrThrow(op);
395 const M& mat = A->getmat();
396 int verbose = config.get("verbose", 0);
397 return std::make_shared<LDL<M>>(mat,verbose);
398 }
400 "Unsupported Type in LDL (only FieldMatrix<double,...> supported)");
401 });
402
403} // end namespace Dune
404
405
406#endif //HAVE_SUITESPARSE_LDL
407#endif //DUNE_ISTL_LDL_HH
#define DUNE_REGISTER_SOLVER(name,...)
Definition solverregistry.hh:17
Templates characterizing the type of a solver.
Implementations of the inverse operator interface.
FieldTraits< M >::field_type field_type
Definition ldl.hh:70
virtual ~LDL()
Default constructor.
Definition ldl.hh:137
double * getLx()
Get factorization Lx.
Definition ldl.hh:296
SolverCategory::Category category() const override
Category of the solver (see SolverCategory::Category)
Definition ldl.hh:82
void apply(field_type *x, field_type *b)
Additional apply method with c-arrays in analogy to superlu.
Definition ldl.hh:168
DefaultMatrixVectorTraits< M >::range_type range_type
The type of the range of the solver.
Definition ldl.hh:79
void apply(domain_type &x, range_type &b, InverseOperatorResult &res) override
Apply inverse operator,.
Definition ldl.hh:145
LDL(const Matrix &matrix, int verbose, bool)
Constructor for compatibility with SuperLU standard constructor.
Definition ldl.hh:112
DefaultMatrixVectorTraits< M >::domain_type domain_type
The type of the domain of the solver.
Definition ldl.hh:77
int * getLi()
Get factorization Li.
Definition ldl.hh:287
void setMatrix(const Matrix &matrix)
Initialize data from given matrix.
Definition ldl.hh:182
LDLMatrix & getInternalMatrix()
Return the column compress matrix.
Definition ldl.hh:237
const char * name()
Get method name.
Definition ldl.hh:260
void free()
Free allocated space.
Definition ldl.hh:246
ISTL::Impl::BCCSMatrixInitializer< M, int > MatrixInitializer
Type of an associated initializer class.
Definition ldl.hh:75
M Matrix
The matrix type.
Definition ldl.hh:68
void setSubMatrix(const Matrix &matrix, const S &rowIndexSet)
Definition ldl.hh:202
double * getD()
Get factorization diagonal matrix D.
Definition ldl.hh:269
int * getLp()
Get factorization Lp.
Definition ldl.hh:278
void setVerbosity(int v)
Sets the verbosity level for the solver.
Definition ldl.hh:228
void setOption(unsigned int option, double value)
Definition ldl.hh:178
M matrix_type
Definition ldl.hh:69
LDL(const Matrix &matrix, int verbose=0)
Construct a solver object from a BCRSMatrix.
Definition ldl.hh:96
LDL(const Matrix &matrix, const ParameterTree &config)
Constructs the LDL solver.
Definition ldl.hh:128
void apply(domain_type &x, range_type &b, double reduction, InverseOperatorResult &res) override
apply inverse operator, with given convergence criteria.
Definition ldl.hh:158
LDL()
Default constructor.
Definition ldl.hh:133
Dune::ISTL::Impl::BCCSMatrix< field_type, int > LDLMatrix
The corresponding SuperLU Matrix type.
Definition ldl.hh:73
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
A vector of blocks with memory management.
Definition bvector.hh:392
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
The LDL direct sparse solver for ISTL matrices.
Definition ldl.hh:65
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
T clear(T... args)
T resize(T... args)