GetFEM  5.5
gmm_precond_ilu.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2026 Yves Renard
5 
6  This file is a part of GetFEM
7 
8  GetFEM is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program. If not, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 // This file is a modified version of ilu.h from ITL.
32 // See http://osl.iu.edu/research/itl/
33 // Following the corresponding Copyright notice.
34 //===========================================================================
35 //
36 // Copyright (c) 1998-2020, University of Notre Dame. All rights reserved.
37 // Redistribution and use in source and binary forms, with or without
38 // modification, are permitted provided that the following conditions are met:
39 //
40 // * Redistributions of source code must retain the above copyright
41 // notice, this list of conditions and the following disclaimer.
42 // * Redistributions in binary form must reproduce the above copyright
43 // notice, this list of conditions and the following disclaimer in the
44 // documentation and/or other materials provided with the distribution.
45 // * Neither the name of the University of Notre Dame nor the
46 // names of its contributors may be used to endorse or promote products
47 // derived from this software without specific prior written permission.
48 //
49 // THIS SOFTWARE IS PROVIDED BY THE TRUSTEES OF INDIANA UNIVERSITY AND
50 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
51 // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
52 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES
53 // OF INDIANA UNIVERSITY AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
54 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 //
61 //===========================================================================
62 
63 /**@file gmm_precond_ilu.h
64  @author Andrew Lumsdaine <lums@osl.iu.edu>
65  @author Lie-Quan Lee <llee@osl.iu.edu>
66  @author Yves Renard <yves.renard@insa-lyon.fr>
67  @date June 5, 2003.
68  @brief Incomplete LU without fill-in Preconditioner.
69 */
70 
71 #ifndef GMM_PRECOND_ILU_H
72 #define GMM_PRECOND_ILU_H
73 
74 //
75 // Notes: The idea under a concrete Preconditioner such
76 // as Incomplete LU is to create a Preconditioner
77 // object to use in iterative methods.
78 //
79 
80 #include "gmm_precond.h"
81 
82 namespace gmm {
83  /** Incomplete LU without fill-in Preconditioner. */
84  template <typename Matrix>
85  class ilu_precond {
86 
87  public :
88  typedef typename linalg_traits<Matrix>::value_type value_type;
89  typedef csr_matrix_ref<value_type *, size_type *, size_type *, 0> tm_type;
90 
91  tm_type U, L;
92  bool invert;
93  protected :
94  std::vector<value_type> L_val, U_val;
95  std::vector<size_type> L_ind, U_ind, L_ptr, U_ptr;
96 
97  template<typename M> void do_ilu(const M& A, row_major);
98  void do_ilu(const Matrix& A, col_major);
99 
100  public:
101 
102  size_type nrows() const { return mat_nrows(L); }
103  size_type ncols() const { return mat_ncols(U); }
104 
105  void build_with(const Matrix& A) {
106  invert = false;
107  L_ptr.resize(mat_nrows(A)+1);
108  U_ptr.resize(mat_nrows(A)+1);
109  do_ilu(A, typename principal_orientation_type<typename
110  linalg_traits<Matrix>::sub_orientation>::potype());
111  }
112  ilu_precond(const Matrix& A) { build_with(A); }
113  ilu_precond() {}
114  size_type memsize() const {
115  return sizeof(*this) +
116  (L_val.size()+U_val.size()) * sizeof(value_type) +
117  (L_ind.size()+L_ptr.size()) * sizeof(size_type) +
118  (U_ind.size()+U_ptr.size()) * sizeof(size_type);
119  }
120  };
121 
122  template <typename Matrix> template <typename M>
123  void ilu_precond<Matrix>::do_ilu(const M& A, row_major) {
124  typedef typename linalg_traits<Matrix>::storage_type store_type;
125  typedef value_type T;
126  typedef typename number_traits<T>::magnitude_type R;
127 
128  size_type L_loc = 0, U_loc = 0, n = mat_nrows(A), i, j, k;
129  if (n == 0) return;
130  L_ptr[0] = 0; U_ptr[0] = 0;
131  R prec = default_tol(R());
132  R max_pivot = gmm::abs(A(0,0)) * prec;
133 
134  for (int count = 0; count < 2; ++count) {
135  if (count) {
136  L_val.resize(L_loc); L_ind.resize(L_loc);
137  U_val.resize(U_loc); U_ind.resize(U_loc);
138  }
139  L_loc = U_loc = 0;
140  for (i = 0; i < n; ++i) {
141  typedef typename linalg_traits<M>::const_sub_row_type row_type;
142  row_type row = mat_const_row(A, i);
143  typename linalg_traits<typename org_type<row_type>::t>::const_iterator
144  it = vect_const_begin(row), ite = vect_const_end(row);
145 
146  if (count) {
147  U_val[U_loc] = T(0);
148  U_ind[U_loc] = i;
149  }
150  ++U_loc; // diagonal element
151 
152  for (k = 0; it != ite && k < 1000; ++it, ++k) {
153  // if a plain row is present, retains only the 1000 firsts
154  // nonzero elements. ---> a sort should be done.
155  j = index_of_it(it, k, store_type());
156  if (j < i) {
157  if (count) {
158  L_val[L_loc] = *it;
159  L_ind[L_loc] = j;
160  }
161  L_loc++;
162  } else if (i == j) {
163  if (count) U_val[U_loc-1] = *it;
164  } else {
165  if (count) {
166  U_val[U_loc] = *it;
167  U_ind[U_loc] = j;
168  }
169  U_loc++;
170  }
171  }
172  L_ptr[i+1] = L_loc;
173  U_ptr[i+1] = U_loc;
174  }
175  }
176 
177  if (A(0,0) == T(0)) {
178  U_val[U_ptr[0]] = T(1);
179  GMM_WARNING2("pivot 0 is too small");
180  }
181 
182  size_type qn, pn, rn;
183  for (i = 1; i < n; i++) {
184 
185  pn = U_ptr[i];
186  if (gmm::abs(U_val[pn]) <= max_pivot) {
187  U_val[pn] = T(1);
188  GMM_WARNING2("pivot " << i << " is too small");
189  }
190  max_pivot = std::max(max_pivot,
191  std::min(gmm::abs(U_val[pn]) * prec, R(1)));
192 
193  for (j = L_ptr[i]; j < L_ptr[i+1]; j++) {
194  pn = U_ptr[L_ind[j]];
195 
196  T multiplier = (L_val[j] /= U_val[pn]);
197 
198  qn = j + 1;
199  rn = U_ptr[i];
200 
201  for (pn++; pn < U_ptr[L_ind[j]+1] && U_ind[pn] < i; pn++) {
202  while (qn < L_ptr[i+1] && L_ind[qn] < U_ind[pn])
203  qn++;
204  if (qn < L_ptr[i+1] && U_ind[pn] == L_ind[qn])
205  L_val[qn] -= multiplier * U_val[pn];
206  }
207  for (; pn < U_ptr[L_ind[j]+1]; pn++) {
208  while (rn < U_ptr[i+1] && U_ind[rn] < U_ind[pn])
209  rn++;
210  if (rn < U_ptr[i+1] && U_ind[pn] == U_ind[rn])
211  U_val[rn] -= multiplier * U_val[pn];
212  }
213  }
214  }
215 
216  L = tm_type(&(L_val[0]), &(L_ind[0]), &(L_ptr[0]), n, mat_ncols(A));
217  U = tm_type(&(U_val[0]), &(U_ind[0]), &(U_ptr[0]), n, mat_ncols(A));
218  }
219 
220  template <typename Matrix>
221  void ilu_precond<Matrix>::do_ilu(const Matrix& A, col_major) {
222  do_ilu(gmm::transposed(A), row_major());
223  invert = true;
224  }
225 
226  template <typename Matrix, typename V1, typename V2> inline
227  void mult(const ilu_precond<Matrix>& P, const V1 &v1, V2 &v2) {
228  gmm::copy(v1, v2);
229  if (P.invert) {
230  gmm::lower_tri_solve(gmm::transposed(P.U), v2, false);
231  gmm::upper_tri_solve(gmm::transposed(P.L), v2, true);
232  }
233  else {
234  gmm::lower_tri_solve(P.L, v2, true);
235  gmm::upper_tri_solve(P.U, v2, false);
236  }
237  }
238 
239  template <typename Matrix, typename V1, typename V2> inline
240  void transposed_mult(const ilu_precond<Matrix>& P,const V1 &v1,V2 &v2) {
241  gmm::copy(v1, v2);
242  if (P.invert) {
243  gmm::lower_tri_solve(P.L, v2, true);
244  gmm::upper_tri_solve(P.U, v2, false);
245  }
246  else {
247  gmm::lower_tri_solve(gmm::transposed(P.U), v2, false);
248  gmm::upper_tri_solve(gmm::transposed(P.L), v2, true);
249  }
250  }
251 
252  template <typename Matrix, typename V1, typename V2> inline
253  void left_mult(const ilu_precond<Matrix>& P, const V1 &v1, V2 &v2) {
254  copy(v1, v2);
255  if (P.invert) gmm::lower_tri_solve(gmm::transposed(P.U), v2, false);
256  else gmm::lower_tri_solve(P.L, v2, true);
257  }
258 
259  template <typename Matrix, typename V1, typename V2> inline
260  void right_mult(const ilu_precond<Matrix>& P, const V1 &v1, V2 &v2) {
261  copy(v1, v2);
262  if (P.invert) gmm::upper_tri_solve(gmm::transposed(P.L), v2, true);
263  else gmm::upper_tri_solve(P.U, v2, false);
264  }
265 
266  template <typename Matrix, typename V1, typename V2> inline
267  void transposed_left_mult(const ilu_precond<Matrix>& P, const V1 &v1,
268  V2 &v2) {
269  copy(v1, v2);
270  if (P.invert) gmm::upper_tri_solve(P.U, v2, false);
271  else gmm::upper_tri_solve(gmm::transposed(P.L), v2, true);
272  }
273 
274  template <typename Matrix, typename V1, typename V2> inline
275  void transposed_right_mult(const ilu_precond<Matrix>& P, const V1 &v1,
276  V2 &v2) {
277  copy(v1, v2);
278  if (P.invert) gmm::lower_tri_solve(P.L, v2, true);
279  else gmm::lower_tri_solve(gmm::transposed(P.U), v2, false);
280  }
281 
282 
283 }
284 
285 #endif
286 
Incomplete LU without fill-in Preconditioner.
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:976
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
gmm preconditioners.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48