32class ChebyshevPreconditioner
36 static const bool m_use_saad_algo = saad;
37 typedef AlgebraT AlgebraType;
38 typedef typename AlgebraType::Matrix MatrixType;
39 typedef typename AlgebraType::Vector VectorType;
40 typedef typename MatrixType::ValueType ValueType;
43 ChebyshevPreconditioner(AlgebraType& algebra,
44 MatrixType
const& matrix,
48 ITraceMng* trace_mng =
nullptr)
52 , m_polynome_order(polynome_order)
53 , m_factor_max_iter(factor_max_iter)
54 , m_trace_mng(trace_mng)
57 virtual ~ChebyshevPreconditioner()
59 m_algebra.free(m_inv_diag, m_y, m_r);
60 if (m_use_saad_algo) {
64 m_algebra.free(m_p, m_z);
68 void setOutputLevel(
int level)
70 m_output_level = level;
75 m_algebra.allocate(AlgebraType::resource(m_matrix), m_y, m_r);
76 m_algebra.assign(m_y, 0.);
77 m_algebra.assign(m_r, 0.);
78 if (m_use_saad_algo) {
79 m_algebra.allocate(AlgebraType::resource(m_matrix), m_w);
80 m_algebra.assign(m_w, 0.);
83 m_algebra.allocate(AlgebraType::resource(m_matrix), m_p, m_z);
84 m_algebra.assign(m_p, 0.);
85 m_algebra.assign(m_z, 0.);
88 m_algebra.allocate(AlgebraType::resource(m_matrix), m_inv_diag);
89 m_algebra.assign(m_inv_diag, 1.);
90 m_algebra.computeInvDiag(m_matrix, m_inv_diag);
100 m_alpha = m_beta / m_factor;
102 m_delta = (m_beta - m_alpha) / 2;
103 m_theta = (m_beta + m_alpha) / 2;
106 m_trace_mng->info() <<
"CHEBYSHEV PRECONDITIONER";
107 m_trace_mng->info() <<
"Polynome Degree : " << m_polynome_order;
108 m_trace_mng->info() <<
"User EigenValue Ratio : " << m_factor;
109 m_trace_mng->info() <<
"Power Method Max Iter : " << m_factor_max_iter;
110 m_trace_mng->info() <<
"ALPHA : " << m_alpha;
111 m_trace_mng->info() <<
"BETA : " << m_beta;
112 m_trace_mng->info() <<
"EigenValue Ratio : " << m_beta / m_alpha;
113 m_trace_mng->info() <<
"THETA : " << m_theta;
114 m_trace_mng->info() <<
"DELTA : " << m_delta;
121 m_algebra.allocate(AlgebraType::resource(m_matrix), x);
122 std::random_device rd;
125 std::uniform_real_distribution<> dis(-1., 1.);
127 m_algebra.assign(x, [&]([[maybe_unused]] std::size_t i) {
137 ValueType norm = m_algebra.norm2(x);
138 m_algebra.scal(1 / norm, x);
140 for (
int i = 0; i < m_factor_max_iter; ++i) {
141 m_algebra.mult(m_matrix, x, m_y);
142 m_algebra.pointwiseMult(m_inv_diag, m_y, m_y);
143 ValueType xAx = m_algebra.dot(m_y, x);
144 ValueType xdx = m_algebra.dot(x, x);
145 ValueType norme = m_algebra.norm2(m_y);
146 m_algebra.scal(1 / norme, m_y);
147 m_algebra.copy(m_y, x);
149 if (m_trace_mng && m_output_level > 1)
150 m_trace_mng->info() <<
"Iter(" << i <<
") : beta ratio=" << m_beta;
153 m_trace_mng->info() <<
"Max eigen value : " << m_beta;
162 m_algebra.allocate(AlgebraType::resource(m_matrix), x);
164 std::random_device rd;
167 std::uniform_real_distribution<> dis(-1., 1.);
174 m_algebra.assign(x, [&]([[maybe_unused]] std::size_t i) {
179 ValueType norm = m_algebra.norm2(x);
180 m_algebra.scal(1 / norm, x);
182 for (
int i = 0; i < m_factor_max_iter; ++i) {
183 m_algebra.mult(m_matrix, x, m_y);
184 m_algebra.pointwiseMult(m_inv_diag, m_y, m_y);
185 m_algebra.axpy(-m_beta, x, m_y);
187 ValueType xAx = m_algebra.dot(m_y, x);
188 ValueType xdx = m_algebra.dot(x, x);
190 if (m_trace_mng && m_output_level > 1)
191 m_trace_mng->info() <<
"Iter(" << i <<
") : alpha ratio=" << m_alpha;
193 ValueType norme = m_algebra.norm2(m_y);
194 m_algebra.scal(1 / norme, m_y);
195 m_algebra.copy(m_y, x);
199 m_trace_mng->info() <<
"Min eigen value : " << m_alpha;
225 m_algebra.xyz(m_inv_diag, x, m_r);
226 m_trace_mng->info() <<
"||R||" << m_algebra.norm2(m_r);
228 ValueType sigma = m_theta / m_delta;
229 ValueType rho_old = 1. / sigma;
230 ValueType rho = rho_old;
231 m_algebra.copy(m_r, m_w);
232 m_algebra.scal(1 / m_theta, m_w);
233 m_algebra.copy(m_w, y);
235 for (
int k = 1; k < m_polynome_order; ++k) {
237 m_algebra.mult(m_matrix, m_w, m_y);
238 m_algebra.xyz(m_inv_diag, m_y, m_y);
239 m_algebra.axpy(-1., m_y, m_r);
240 m_trace_mng->info() << k <<
" "
241 <<
"||R||" << m_algebra.norm2(m_r);
243 rho = 1. / (2 * sigma - rho_old);
245 m_algebra.scal(rho * rho_old, m_w);
246 m_algebra.axpy(2 * rho / m_delta, m_r, m_w);
249 m_algebra.axpy(1., m_w, y);
258 const ValueType d = (m_beta + m_alpha) / 2;
259 const ValueType c = (m_beta - m_alpha) / 2;
261 m_algebra.copy(x, y);
263 m_algebra.mult(m_matrix, y, m_y);
264 m_algebra.copy(x, m_r);
265 m_algebra.axpy(-1., m_y, m_r);
269 m_algebra.xyz(m_inv_diag, m_r, m_z);
271 m_algebra.copy(m_z, m_p);
272 ValueType alpha = 2 / d;
275 m_algebra.axpy(alpha, m_p, y);
277 for (
int i = 1; i < m_polynome_order; ++i) {
279 m_algebra.mult(m_matrix, y, m_y);
280 m_algebra.copy(x, m_r);
281 m_algebra.axpy(-1., m_y, m_r);
283 m_trace_mng->info() << i <<
" "
284 <<
"||R||" << m_algebra.norm2(m_r);
288 m_algebra.xyz(m_inv_diag, m_r, m_z);
293 ValueType beta = alpha * (c / 2.) * (c / 2.);
294 alpha = 1. / (d - beta);
297 m_algebra.scal(beta, m_p);
298 m_algebra.axpy(1., m_z, m_p);
301 m_algebra.axpy(alpha, m_p, y);
363 m_algebra.pointwiseMult(m_inv_diag, x, m_r);
365 ValueType sigma = m_theta / m_delta;
366 ValueType rho_old = 1. / sigma;
367 ValueType rho = rho_old;
368 m_algebra.copy(m_r, m_w);
369 m_algebra.scal(1 / m_theta, m_w);
370 m_algebra.copy(m_w, y);
372 m_trace_mng->info() <<
"sigma =" << sigma;
373 m_trace_mng->info() <<
"rho =" << rho;
374 m_trace_mng->info() <<
"theta =" << m_theta;
376 for (
int k = 1; k < m_polynome_order; ++k) {
377 m_algebra.mult(m_matrix, m_w, m_y);
378 m_algebra.pointwiseMult(m_inv_diag, m_y, m_y);
379 m_algebra.axpy(-1., m_y, m_r);
381 rho = 1. / (2 * sigma - rho_old);
382 m_algebra.scal(rho * rho_old, m_w);
383 m_algebra.axpy(2 * rho / m_delta, m_r, m_w);
386 m_algebra.axpy(1., m_w, y);
392 void _algo2([[maybe_unused]] AlgebraType& algebra,
396 const ValueType d = (m_beta + m_alpha) / 2;
397 const ValueType c = (m_beta - m_alpha) / 2;
399 m_algebra.copy(x, y);
401 m_algebra.mult(m_matrix, y, m_y);
402 m_algebra.copy(x, m_r);
403 m_algebra.axpy(-1., m_y, m_r);
405 m_algebra.pointwiseMult(m_inv_diag, m_r, m_z);
407 m_algebra.copy(m_z, m_p);
409 ValueType alpha = 2 / d;
410 m_algebra.axpy(alpha, m_p, y);
412 for (
int i = 1; i < m_polynome_order; ++i) {
414 m_algebra.mult(m_matrix, y, m_y);
415 m_algebra.copy(x, m_r);
416 m_algebra.axpy(-1., m_y, m_r);
419 m_algebra.pointwiseMult(m_inv_diag, m_r, m_z);
424 ValueType beta = alpha * (c / 2.) * (c / 2.);
425 alpha = 1. / (d - beta);
428 m_algebra.scal(beta, m_p);
429 m_algebra.axpy(1., m_z, m_p);
432 m_algebra.axpy(alpha, m_p, y);
436 void solve(AlgebraType& algebra,
441 _algo1(algebra, x, y);
443 _algo2(algebra, x, y);
447 AlgebraType& m_algebra;
450 MatrixType
const& m_matrix;
454 ValueType m_factor = 0.;
455 ValueType m_alpha = 0.;
456 ValueType m_beta = 0.;
457 ValueType m_theta = 0.;
458 ValueType m_delta = 0.;
461 int m_polynome_order;
463 int m_factor_max_iter;
465 VectorType m_inv_diag;
467 mutable VectorType m_y;
468 mutable VectorType m_r;
469 mutable VectorType m_w;
470 mutable VectorType m_p;
471 mutable VectorType m_z;
473 ITraceMng* m_trace_mng =
nullptr;
474 int m_output_level = 0;