dune-istl 2.10
Loading...
Searching...
No Matches
ilu.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_ILU_HH
6#define DUNE_ISTL_ILU_HH
7
8#include <cmath>
9#include <complex>
10#include <map>
11#include <vector>
12
13#include <dune/common/fmatrix.hh>
14#include <dune/common/scalarvectorview.hh>
15#include <dune/common/scalarmatrixview.hh>
16
17#include "istlexception.hh"
18
23namespace Dune {
24
29 namespace ILU {
30
32 template<class M>
34 {
35 // iterator types
36 typedef typename M::RowIterator rowiterator;
37 typedef typename M::ColIterator coliterator;
38 typedef typename M::block_type block;
39
40 // implement left looking variant with stored inverse
41 rowiterator endi=A.end();
42 for (rowiterator i=A.begin(); i!=endi; ++i)
43 {
44 // coliterator is diagonal after the following loop
45 coliterator endij=(*i).end(); // end of row i
46 coliterator ij;
47
48 // eliminate entries left of diagonal; store L factor
49 for (ij=(*i).begin(); ij.index()<i.index(); ++ij)
50 {
51 // find A_jj which eliminates A_ij
52 coliterator jj = A[ij.index()].find(ij.index());
53
54 // compute L_ij = A_jj^-1 * A_ij
55 Impl::asMatrix(*ij).rightmultiply(Impl::asMatrix(*jj));
56
57 // modify row
58 coliterator endjk=A[ij.index()].end(); // end of row j
59 coliterator jk=jj; ++jk;
60 coliterator ik=ij; ++ik;
61 while (ik!=endij && jk!=endjk)
62 if (ik.index()==jk.index())
63 {
64 block B(*jk);
65 Impl::asMatrix(B).leftmultiply(Impl::asMatrix(*ij));
66 *ik -= B;
67 ++ik; ++jk;
68 }
69 else
70 {
71 if (ik.index()<jk.index())
72 ++ik;
73 else
74 ++jk;
75 }
76 }
77
78 // invert pivot and store it in A
79 if (ij.index()!=i.index())
80 DUNE_THROW(ISTLError,"diagonal entry missing");
81 try {
82 Impl::asMatrix(*ij).invert(); // compute inverse of diagonal block
83 }
84 catch (Dune::FMatrixError & e) {
85 DUNE_THROW(MatrixBlockError, "ILU failed to invert matrix block A["
86 << i.index() << "][" << ij.index() << "]" << e.what();
87 th__ex.r=i.index(); th__ex.c=ij.index(););
88 }
89 }
90 }
91
93 template<class M, class X, class Y>
94 void blockILUBacksolve (const M& A, X& v, const Y& d)
95 {
96 // iterator types
97 typedef typename M::ConstRowIterator rowiterator;
98 typedef typename M::ConstColIterator coliterator;
99 typedef typename Y::block_type dblock;
100 typedef typename X::block_type vblock;
101
102 // lower triangular solve
103 rowiterator endi=A.end();
104 for (rowiterator i=A.begin(); i!=endi; ++i)
105 {
106 // We need to be careful here: Directly using
107 // auto rhs = Impl::asVector(d[ i.index() ]);
108 // is not OK in case this is a proxy. Hence
109 // we first have to copy the value. Notice that
110 // this is still not OK, if the vector type itself returns
111 // proxy references.
112 dblock rhsValue(d[i.index()]);
113 auto&& rhs = Impl::asVector(rhsValue);
114 for (coliterator j=(*i).begin(); j.index()<i.index(); ++j)
115 Impl::asMatrix(*j).mmv(Impl::asVector(v[j.index()]),rhs);
116 Impl::asVector(v[i.index()]) = rhs; // Lii = I
117 }
118
119 // upper triangular solve
120 rowiterator rendi=A.beforeBegin();
121 for (rowiterator i=A.beforeEnd(); i!=rendi; --i)
122 {
123 // We need to be careful here: Directly using
124 // auto rhs = Impl::asVector(v[ i.index() ]);
125 // is not OK in case this is a proxy. Hence
126 // we first have to copy the value. Notice that
127 // this is still not OK, if the vector type itself returns
128 // proxy references.
129 vblock rhsValue(v[i.index()]);
130 auto&& rhs = Impl::asVector(rhsValue);
131 coliterator j;
132 for (j=(*i).beforeEnd(); j.index()>i.index(); --j)
133 Impl::asMatrix(*j).mmv(Impl::asVector(v[j.index()]),rhs);
134 auto&& vi = Impl::asVector(v[i.index()]);
135 Impl::asMatrix(*j).mv(rhs,vi); // diagonal stores inverse!
136 }
137 }
138
139 // recursive function template to access first entry of a matrix
140 template<class M>
141 typename M::field_type& firstMatrixElement (M& A,
142 [[maybe_unused]] typename std::enable_if_t<!Dune::IsNumber<M>::value>* sfinae = nullptr)
143 {
144 return firstMatrixElement(*(A.begin()->begin()));
145 }
146
147 template<class K>
149 [[maybe_unused]] typename std::enable_if_t<Dune::IsNumber<K>::value>* sfinae = nullptr)
150 {
151 return<