GetFEM  5.5
gmm_precond_ildltt.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2003-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 /**@file gmm_precond_ildltt.h
32  @author Yves Renard <Yves.Renard@insa-lyon.fr>
33  @date June 30, 2003.
34  @brief incomplete LDL^t (cholesky) preconditioner with fill-in and threshold.
35 */
36 
37 #ifndef GMM_PRECOND_ILDLTT_H
38 #define GMM_PRECOND_ILDLTT_H
39 
40 // Store U = LT and D in indiag. On each line, the fill-in is the number
41 // of non-zero elements on the line of the original matrix plus K, except if
42 // the matrix is dense. In this case the fill-in is K on each line.
43 
44 #include "gmm_precond_ilut.h"
45 
46 namespace gmm {
47  /** incomplete LDL^t (cholesky) preconditioner with fill-in and
48  threshold. */
49  template <typename Matrix>
51  public :
52  typedef typename linalg_traits<Matrix>::value_type value_type;
53  typedef typename number_traits<value_type>::magnitude_type magnitude_type;
54 
56 
57  row_matrix<svector> U;
58  std::vector<magnitude_type> indiag;
59 
60  protected:
61  size_type K;
62  double eps;
63 
64  template<typename M> void do_ildltt(const M&, row_major);
65  void do_ildltt(const Matrix&, col_major);
66 
67  public:
68  void build_with(const Matrix& A, int k_ = -1, double eps_ = double(-1)) {
69  if (k_ >= 0) K = k_;
70  if (eps_ >= double(0)) eps = eps_;
71  gmm::resize(U, mat_nrows(A), mat_ncols(A));
72  indiag.resize(std::min(mat_nrows(A), mat_ncols(A)));
73  do_ildltt(A, typename principal_orientation_type<typename
74  linalg_traits<Matrix>::sub_orientation>::potype());
75  }
76  ildltt_precond(const Matrix& A, int k_, double eps_)
77  : U(mat_nrows(A),mat_ncols(A)), K(k_), eps(eps_) { build_with(A); }
78  ildltt_precond(void) { K=10; eps = 1E-7; }
79  ildltt_precond(size_type k_, double eps_) : K(k_), eps(eps_) {}
80  size_type memsize() const {
81  return sizeof(*this) + nnz(U)*sizeof(value_type) + indiag.size() * sizeof(magnitude_type);
82  }
83  };
84 
85  template<typename Matrix> template<typename M>
86  void ildltt_precond<Matrix>::do_ildltt(const M& A,row_major) {
87  typedef value_type T;
88  typedef typename number_traits<T>::magnitude_type R;
89 
90  size_type n = mat_nrows(A);
91  if (n == 0) return;
92  svector w(n);
93  T tmp;
94  R prec = default_tol(R()), max_pivot = gmm::abs(A(0,0)) * prec;
95 
96  gmm::clear(U);
97  for (size_type i = 0; i < n; ++i) {
98  gmm::copy(mat_const_row(A, i), w);
99  double norm_row = gmm::vect_norm2(w);
100 
101  for (size_type krow = 0, k; krow < w.nb_stored(); ++krow) {
102  typename svector::iterator wk = w.begin() + krow;
103  if ((k = wk->c) >= i) break;
104  if (gmm::is_complex(wk->e)) {
105  tmp = gmm::conj(U(k, i))/indiag[k]; // not completely satisfactory ..
106  gmm::add(scaled(mat_row(U, k), -tmp), w);
107  }
108  else {
109  tmp = wk->e;
110  if (gmm::abs(tmp) < eps * norm_row) { w.sup(k); --krow; }
111  else { wk->e += tmp; gmm::add(scaled(mat_row(U, k), -tmp), w); }
112  }
113  }
114  tmp = w[i];
115 
116  if (gmm::abs(gmm::real(tmp)) <= max_pivot)
117  { GMM_WARNING2("pivot " << i << " is too small"); tmp = T(1); }
118 
119  max_pivot = std::max(max_pivot, std::min(gmm::abs(tmp) * prec, R(1)));
120  indiag[i] = R(1) / gmm::real(tmp);
121  gmm::clean(w, eps * norm_row);
122  gmm::scale(w, T(indiag[i]));
123  std::sort(w.begin(), w.end(), elt_rsvector_value_less_<T>());
124  typename svector::const_iterator wit = w.begin(), wite = w.end();
125  for (size_type nnu = 0; wit != wite; ++wit) // copy to be optimized ...
126  if (wit->c > i) { if (nnu < K) { U(i, wit->c) = wit->e; ++nnu; } }
127  }
128  }
129 
130  template<typename Matrix>
131  void ildltt_precond<Matrix>::do_ildltt(const Matrix& A, col_major)
132  { do_ildltt(gmm::conjugated(A), row_major()); }
133 
134  template <typename Matrix, typename V1, typename V2> inline
135  void mult(const ildltt_precond<Matrix>& P, const V1 &v1, V2 &v2) {
136  gmm::copy(v1, v2);
137  gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true);
138  for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i];
139  gmm::upper_tri_solve(P.U, v2, true);
140  }
141 
142  template <typename Matrix, typename V1, typename V2> inline
143  void transposed_mult(const ildltt_precond<Matrix>& P,const V1 &v1, V2 &v2)
144  { mult(P, v1, v2); }
145 
146  template <typename Matrix, typename V1, typename V2> inline
147  void left_mult(const ildltt_precond<Matrix>& P, const V1 &v1, V2 &v2) {
148  copy(v1, v2);
149  gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true);
150  for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i];
151  }
152 
153  template <typename Matrix, typename V1, typename V2> inline
154  void right_mult(const ildltt_precond<Matrix>& P, const V1 &v1, V2 &v2)
155  { copy(v1, v2); gmm::upper_tri_solve(P.U, v2, true); }
156 
157  template <typename Matrix, typename V1, typename V2> inline
158  void transposed_left_mult(const ildltt_precond<Matrix>& P, const V1 &v1,
159  V2 &v2) {
160  copy(v1, v2);
161  gmm::upper_tri_solve(P.U, v2, true);
162  for (size_type i = 0; i < P.indiag.size(); ++i) v2[i] *= P.indiag[i];
163  }
164 
165  template <typename Matrix, typename V1, typename V2> inline
166  void transposed_right_mult(const ildltt_precond<Matrix>& P, const V1 &v1,
167  V2 &v2)
168  { copy(v1, v2); gmm::lower_tri_solve(gmm::conjugated(P.U), v2, true); }
169 
170 }
171 
172 #endif
173 
incomplete LDL^t (cholesky) preconditioner with fill-in and threshold.
sparse vector built upon std::vector.
Definition: gmm_vector.h:995
size_type nnz(const L &l)
count the number of non-zero entries of a vector or matrix.
Definition: gmm_blas.h:68
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:976
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
Definition: gmm_blas.h:556
void clear(L &l)
clear (fill with zeros) a vector or matrix.
Definition: gmm_blas.h:58
void resize(V &v, size_type n)
*‍/
Definition: gmm_blas.h:209
void clean(L &l, double threshold)
Clean a vector or matrix (replace near-zero entries with zeroes).
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*‍/
Definition: gmm_blas.h:1663
void add(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:1275
ILUT: Incomplete LU with threshold and K fill-in Preconditioner.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48