KASKADE 7 development version
direct.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2022 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef DIRECT_HH
14#define DIRECT_HH
15
16#include <cmath>
17#include <memory>
18#include <type_traits>
19
20#include <boost/timer/timer.hpp>
21
22#include "dune/istl/operators.hh"
23#include <dune/istl/solvers.hh>
24
25#include "fem/istlinterface.hh"
27
28namespace Kaskade
29{
31 namespace DirectSolver_Detail
32 {
33 class NoScalar{};
34 class NoFieldType{};
35
36 template <class T>
37 typename T::Scalar hasScalar(typename T::Scalar*);
38 template <class T>
40
41 template <class T>
42 typename T::field_type hasFieldType(typename T::field_type*);
43 template <class T>
45
46 template <class T>
47 struct HasScalar
48 {
49 typedef decltype(hasScalar<T>(nullptr)) type;
50 static constexpr bool value = !std::is_same<type,NoScalar>::value;
51 };
52
53 template <class T>
55 {
56 typedef decltype(hasFieldType<T>(nullptr)) type;
57 static constexpr bool value = !std::is_same<type,NoFieldType>::value;
58 };
59
60
61
62 template <class T>
64 {
65 typedef typename std::conditional< HasScalar<T>::value, typename HasScalar<T>::type,
66 typename std::conditional< HasFieldType<T>::value, typename HasFieldType<T>::type, void>::type >::type type;
67
68 };
69
73 template <class Scalar>
74 size_t checkNanInf(Scalar const* x, size_t n, std::string const& what)
75 {
76 size_t nan = 0, inf = 0;
77 for (size_t i=0; i<n; ++i)
78 {
79 if (std::isnan(x[i])) ++nan;
80 if (std::isinf(x[i])) ++inf;
81 }
82 if (nan>0) std::cerr << nan << " " << what << " entries are nan.\n";
83 if (inf>0) std::cerr << inf << " " << what << " entries are inf.\n";
84
85 return nan+inf;
86 }
87 }
89
97 template <class Domain_, class Range_>
98 class DirectSolver: public Dune::InverseOperator<Domain_,Range_>,
99 public Dune::Preconditioner<Domain_,Range_>
100 {
101 public:
103 typedef Domain_ Domain;
104 typedef Range_ Range;
105
112
119
126 template <class GOP, int firstRow, int lastRow, int firstCol, int lastCol>
130 : DirectSolver(A.template get<MatrixAsTriplet<typename AssembledGalerkinOperator<GOP,firstRow,lastRow,
131 firstCol,lastCol>::Scalar>>(),
132 directType,options)
133 { }
134
140 template <class AssembledGOP>
141 [[deprecated]]
142 explicit DirectSolver(AssembledGOP const& A,
143 DirectType directType,
144 MatrixProperties properties)
145 : DirectSolver(A.template get<MatrixAsTriplet<typename AssembledGOP::Scalar>>(),
146 directType,FactorizationOptions(properties))
147 { }
148
152 template <class FieldType>
156 : solver(getFactorization(directType,A,options))
157 , n(A.N())
158 {
159 assert(solver.get()); // make sure the factorization has been successful - otherwise it should have raised an exception
160 }
161
167 template <class FieldType>
168 [[deprecated]]
170 DirectType directType,
171 MatrixProperties properties)
172 : DirectSolver(A,directType,properties)
173 { }
174
180 template <class FieldType>
181 explicit DirectSolver(Dune::BCRSMatrix<Dune::FieldMatrix<FieldType,1,1>> const& A,
184 : solver(getFactorization(directType,A,FactorizationOptions(properties)))
185 , n(A.N())
186 {
187 assert(solver.get()); // make sure the factorization has been successful - otherwise it should have raised an exception
188 }
189
199 template <class FieldType, int n, int m, class Index>
201 DirectType directType,
202 MatrixProperties properties)
203 : DirectSolver(A,directType,FactorizationOptions(properties))
204 { }
205
216 template <class FieldType, int n, int m, class Index>
220 : solver(getFactorization(directType,A,options))
221 , n(A.N()*n)
222 {
223 assert(solver.get()); // make sure the factorization has been successful - otherwise it should have raised an exception
224 }
225
226
227
244 virtual void apply(Domain& x, Range& b, Dune::InverseOperatorResult& res)
245 {
246 apply(x,b,1e-10,res);
247 }
248
255 void apply(Domain& x, Range& b, Dune::InverseOperatorResult& res) const
256 {
257 apply(x,b,1e-10,res);
258 }
259
267 virtual void apply(Domain& x, Range& b, double reduction, Dune::InverseOperatorResult& res)
268 {
269 const_cast<DirectSolver<Domain,Range> const*>(this)->apply(x,b,res);
270 }
271
275 void apply(Domain& x, Range const& b, double reduction, Dune::InverseOperatorResult& res) const
276 {
277 if constexpr (false && contiguousStorage<Domain> && contiguousStorage<Range>)
278 {
281 assert(DirectSolver_Detail::checkNanInf(bp,n,"rhs")==0);
282 solver->solve(bp,xp);
283 assert(DirectSolver_Detail::checkNanInf(xp,n,"solution")==0);
284 }
285 else
286 {
287 std::vector<Scalar> rhs(b.dim()+16); // allocate somewhat more memory - at least UMFPACK
288 vectorToSequence(b,begin(rhs)); // tends to read beyond the array boundary?
289 apply(rhs,reduction,res);
290 vectorFromSequence(x,begin(rhs));
291 }
292 }
293
297 void apply(std::vector<Scalar>& v, double /* reduction */, Dune::InverseOperatorResult& res) const
298 {
299 boost::timer::cpu_timer timer;
300
301 apply(v);
302
303 // Write solver statistics. Currently dummy.
304 res.clear();
305 res.iterations = 1;
306 res.reduction = 1e-10; // dummy!
307 res.converged = true;
308 res.conv_rate = 1e-10;
309 res.elapsed = (double)(timer.elapsed().user)/1e9;
310 }
311
319 virtual void apply(std::vector<Scalar>& v) const
320 {
321 // Check for solver availability. Otherwise return zero solution.
322 if (solver)
323 {
324 assert(v.size() >= n);
325 assert(DirectSolver_Detail::checkNanInf(&v[0],n,"rhs")==0);
326
327 solver->solve(v);
328
329 assert(DirectSolver_Detail::checkNanInf(&v[0],n,"solution")==0);
330 }
331 else
332 std::fill(v.begin(),v.end(),0.0);
333 }
334
342 virtual void apply(Domain& x, Range const& b)
343 {
344 Dune::InverseOperatorResult dummy_res;
345 apply(x,b,0,dummy_res);
346 }
347
351 virtual void apply (Domain& x, Range const& b) const
352 {
353 Dune::InverseOperatorResult dummy_res;
354 apply(x,b,0,dummy_res);
355 }
356
358
364 virtual void pre (Domain& , Range& ) {}
365
371 virtual void post (Domain&) {}
372
378 virtual Dune::SolverCategory::Category category() const override
379 {
380 return Dune::SolverCategory::sequential;
381 }
382
383 private:
384 std::shared_ptr<Factorization<Scalar>> solver;
385 size_t n = 0; // size of the square matrix (with scalar entries)
386 };
387
388 // ----------------------------------------------------------------------------------------------
389
390 // partial specialization for tiny fixed-size matrices
391 template <class S, int n>
392 class DirectSolver<Dune::FieldVector<S,n>,Dune::FieldVector<S,n>>
393 : public Dune::InverseOperator<Dune::FieldVector<S,n>,Dune::FieldVector<S,n>>
394 , public Dune::Preconditioner<Dune::FieldVector<S,n>,Dune::FieldVector<S,n>>
395 {
396 public:
397 typedef S Scalar;
400
407
411 template <class FieldType>
413 inverse(A)
414 {
415 inverse.invert();
416 }
417
424 virtual void apply(Domain& x, Range& b, Dune::InverseOperatorResult& res) { apply(x,b,1e-10,res); }
425
432 void apply(Domain& x, Range& b, Dune::InverseOperatorResult& res) const { apply(x,b,1e-10,res); }
433
439 virtual void apply(Domain& x, Range& b, double reduction, Dune::InverseOperatorResult& res)
440 {
441 const_cast<DirectSolver<Domain,Range> const*>(this)->apply(x,b,res);
442 }
443
450 void apply(Domain& x, Range const& b, double reduction, Dune::InverseOperatorResult& res) const
451 {
452 x = inverse*b;
453
454 // Write solver statistics. Currently dummy.
455 res.clear();
456 res.iterations = 1;
457 res.reduction = 1e-10; // dummy!
458 res.converged = true;
459 res.conv_rate = 1e-10;
460 res.elapsed = 0;
461 }
462
463
464 virtual void pre (Domain &x, Range &b) {}
465
466 virtual void apply (Domain &v, const Range &d)
467 {
468 v = inverse*d;
469 }
470
471 virtual void post (Domain &x) {}
472
473 private:
475 };
476
477 // ----------------------------------------------------------------------------------------------
478
489 template <class GOP, int firstRow, int lastRow, int firstCol, int lastCol>
492 directSolver(AssembledGalerkinOperator<GOP,firstRow,lastRow,firstCol,lastCol> const& A,
494 {
497 return DirectSolver<Domain,Range>(A,directType,properties);
498 }
499
510 template <class Scalar, int n, class Index>
511 DirectSolver<Dune::BlockVector<Dune::FieldVector<Scalar,n>>,
513 directSolver(NumaBCRSMatrix<Dune::FieldMatrix<Scalar,n,n>,Index> const& A,
514 DirectType directType, MatrixProperties properties)
515 {
518 return DirectSolver<Domain,Range>(A,directType,properties);
519 }
520
531 template <class Scalar, int n, class Index>
532 DirectSolver<Dune::BlockVector<Dune::FieldVector<Scalar,n>>,
534 directSolver(NumaBCRSMatrix<Dune::FieldMatrix<Scalar,n,n>,Index> const& A,
536 FactorizationOptions options=FactorizationOptions())
537 {
540 return DirectSolver<Domain,Range>(A,directType,options);
541 }
542
543
544 // ----------------------------------------------------------------------------------------------
545 // ----------------------------------------------------------------------------------------------
546
551 template <class InverseOperator>
552 class InverseLinearOperator: public Dune::LinearOperator<typename InverseOperator::Range, typename InverseOperator::Domain>
553 {
554 public:
555 typedef typename InverseOperator::Domain Domain;
556 typedef typename InverseOperator::Range Range;
557 typedef typename InverseOperator::Scalar Scalar;
558
560
561 InverseLinearOperator(InverseOperator const& op_) : op(op_)
562 {}
563
564 virtual void apply(Domain const& x, Range& y) const
565 {
566 Dune::InverseOperatorResult result;
567 Domain rhs(x);
568 op.apply(y,rhs,result);
569 }
570
571 virtual void applyscaleadd(Scalar alpha, Domain const& x, Range& y) const
572 {
573 Range ynew(y);
574 apply(x,ynew);
575 y.axpy(alpha,ynew);
576 }
577
583 virtual Dune::SolverCategory::Category category() const override
584 {
585 return Dune::SolverCategory::sequential;
586 }
587
588 private:
589 InverseOperator op;
590 };
591
592 //---------------------------------------------------------------------
593
603 template <class GOP, int firstRow, int lastRow, int firstCol, int lastCol>
606 directInverseOperator(AssembledGalerkinOperator<GOP,firstRow,lastRow,firstCol,lastCol> const& A,
608 FactorizationOptions options=FactorizationOptions())
609 {
612 return InverseLinearOperator<DirectSolver<Domain,Range>>(DirectSolver<Domain,Range>(A,directType,options));
613 }
614
615 template <class GOP, int firstRow, int lastRow, int firstCol, int lastCol>
619 DirectType directType, MatrixProperties properties)
620 {
621 return directInverseOperator(A,directType,FactorizationOptions(properties));
622 }
623
624 template <class Matrix, class Domain, class Range>
625 InverseLinearOperator<DirectSolver<Domain,Range> >
628 {
630 }
631
632} // namespace Kaskade
633
634//---------------------------------------------------------------------
635
636#endif
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
typename Assembler::AnsatzVariableSetDescription::template CoefficientVector< firstCol, lastCol > Domain
typename Assembler::TestVariableSetDescription::template CoefficientVector< firstRow, lastRow > Range
void apply(Domain &x, Range &b, Dune::InverseOperatorResult &res) const
Solves the system for the given right hand side.
Definition: direct.hh:432
virtual void apply(Domain &x, Range &b, Dune::InverseOperatorResult &res)
Solves the system for the given right hand side.
Definition: direct.hh:424
void apply(Domain &x, Range const &b, double reduction, Dune::InverseOperatorResult &res) const
Solves the system for the given right hand side.
Definition: direct.hh:450
virtual void apply(Domain &x, Range &b, double reduction, Dune::InverseOperatorResult &res)
Definition: direct.hh:439
DirectSolver(Dune::FieldMatrix< FieldType, n, n > const &A)
Constructs a direct solver from a FieldMatrix matrix.
Definition: direct.hh:412
virtual void apply(Domain &x, Range &b, Dune::InverseOperatorResult &res)
Solves the system for the given right hand side b.
Definition: direct.hh:244
DirectSolver(DirectSolver< Domain, Range > const &ds)=default
Copy constructor.
DirectSolver(AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol > const &A, DirectType directType=DirectType::UMFPACK, FactorizationOptions options=FactorizationOptions())
Constructs a direct solver from an assembled linear operator.
Definition: direct.hh:127
virtual void apply(std::vector< Scalar > &v) const
Solves the system .
Definition: direct.hh:319
virtual void apply(Domain &x, Range const &b)
Solves the system for the given right hand side b.
Definition: direct.hh:342
virtual void apply(Domain &x, Range const &b) const
Solves the system for the given right hand side b.
Definition: direct.hh:351
DirectSolver_Detail::ScalarType< Domain_ >::type Scalar
Definition: direct.hh:102
DirectSolver(MatrixAsTriplet< FieldType > const &A, DirectType directType, MatrixProperties properties)
Constructs a direct solver from a triplet matrix.
Definition: direct.hh:169
virtual void pre(Domain &, Range &)
unused
Definition: direct.hh:364
DirectSolver(NumaBCRSMatrix< Dune::FieldMatrix< FieldType, n, m >, Index > const &A, DirectType directType=DirectType::UMFPACK, FactorizationOptions options=FactorizationOptions())
Constructs a direct solver from a NumaBCRS matrix. A copy of the linear operator is held internally,...
Definition: direct.hh:217
DirectSolver(NumaBCRSMatrix< Dune::FieldMatrix< FieldType, n, m >, Index > const &A, DirectType directType, MatrixProperties properties)
Constructs a direct solver from a NumaBCRS matrix. A copy of the linear operator is held internally,...
Definition: direct.hh:200
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
Definition: direct.hh:378
virtual void post(Domain &)
unused
Definition: direct.hh:371
void apply(Domain &x, Range const &b, double reduction, Dune::InverseOperatorResult &res) const
Solves the system for the given right hand side b.
Definition: direct.hh:275
DirectSolver()
Default constructor.
Definition: direct.hh:111
void apply(Domain &x, Range &b, Dune::InverseOperatorResult &res) const
Solves the system for the given right hand side b.
Definition: direct.hh:255
void apply(std::vector< Scalar > &v, double, Dune::InverseOperatorResult &res) const
The input vector v contains the rhs. It will be overwritten by the solution.
Definition: direct.hh:297
DirectSolver(MatrixAsTriplet< FieldType > const &A, DirectType directType=DirectType::UMFPACK, FactorizationOptions options=FactorizationOptions())
Constructs a direct solver from a triplet matrix.
Definition: direct.hh:153
virtual void apply(Domain &x, Range &b, double reduction, Dune::InverseOperatorResult &res)
Solves the system for the given right hand side b.
Definition: direct.hh:267
DirectSolver(Dune::BCRSMatrix< Dune::FieldMatrix< FieldType, 1, 1 > > const &A, DirectType directType=DirectType::UMFPACK, MatrixProperties properties=MatrixProperties::GENERAL)
Constructs a direct solver from a BCRS matrix. A copy of the linear operator is held internally,...
Definition: direct.hh:181
DirectSolver(AssembledGOP const &A, DirectType directType, MatrixProperties properties)
Constructs a direct solver from an assembled linear operator.
Definition: direct.hh:142
Dune::LinearOperator interface for inverse operators.
Definition: direct.hh:553
InverseLinearOperator(InverseOperator const &op_)
Definition: direct.hh:561
virtual void apply(Domain const &x, Range &y) const
Definition: direct.hh:564
virtual void applyscaleadd(Scalar alpha, Domain const &x, Range &y) const
Definition: direct.hh:571
InverseOperator::Domain Domain
Definition: direct.hh:555
InverseOperator::Range Range
Definition: direct.hh:556
InverseOperator::Scalar Scalar
Definition: direct.hh:557
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
Definition: direct.hh:583
Operator with matrix-representation and coordinate mappings.
A NUMA-aware compressed row storage matrix adhering mostly to the Dune ISTL interface (to complete....
std::unique_ptr< Factorization< Scalar > > getFactorization(DirectType directType, MatrixAsTriplet< Scalar, Index > const &A, FactorizationOptions options)
Creates a factorization of the given triplet matrix.
DirectType
Available direct solvers for linear equation systems.
Definition: enums.hh:35
@ UMFPACK
UMFPack from SuiteSparse, using 32 bit integer indices.
MatrixProperties
Characterizations of sparse matrix properties.
Definition: enums.hh:76
NoFieldType hasFieldType(...)
size_t checkNanInf(Scalar const *x, size_t n, std::string const &what)
Checks a vector for nan/inf and reports their number to stderr.
Definition: direct.hh:74
InverseLinearOperator< DirectSolver< typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Domain, typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Range > > directInverseOperator(AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol > const &A, DirectType directType, MatrixProperties properties)
Definition: direct.hh:618
OutIter vectorToSequence(double x, OutIter iter)
Definition: crsutil.hh:30
InIter vectorFromSequence(FunctionSpaceElement< Space, m > &v, InIter in)
decltype(hasFieldType< T >(nullptr)) type
Definition: direct.hh:56
static constexpr bool value
Definition: direct.hh:50
decltype(hasScalar< T >(nullptr)) type
Definition: direct.hh:49
std::conditional< HasScalar< T >::value, typenameHasScalar< T >::type, typenamestd::conditional< HasFieldType< T >::value, typenameHasFieldType< T >::type, void >::type >::type type
Definition: direct.hh:66
The Options struct allows to specify several options of factorization.