22#ifndef INCLUDE_SOLVERS_AND_PRECONDITIONERS_ELEMENTWISE_KRYLOV_SOLVERS_H_
23#define INCLUDE_SOLVERS_AND_PRECONDITIONERS_ELEMENTWISE_KRYLOV_SOLVERS_H_
26#include <deal.II/base/aligned_vector.h>
27#include <deal.II/base/vectorization.h>
30#include <exadg/solvers_and_preconditioners/solvers/solver_data.h>
36template<
typename Number,
typename Number2>
38all_smaller(Number
const a,
const Number2 b)
43template<
typename Number,
typename Number2>
45all_smaller(dealii::VectorizedArray<Number>
const a, Number2
const b)
47 for(
unsigned int i = 0; i < dealii::VectorizedArray<Number>::size(); ++i)
53template<
typename Number>
55all_true(Number
const a)
60template<
typename Number>
62all_true(dealii::VectorizedArray<Number>
const a)
64 for(
unsigned int i = 0; i < dealii::VectorizedArray<Number>::size(); ++i)
70template<
typename Number,
typename Number2>
72converged(Number & is_converged,
78 unsigned int MAX_ITER)
80 bool is_converged_bool =
true;
81 if(norm_r_abs < ABS_TOL or norm_r_rel < REL_TOL or k >= MAX_ITER)
84 is_converged_bool =
true;
89 is_converged_bool =
false;
92 return is_converged_bool;
95template<
typename Number,
typename Number2>
97converged(dealii::VectorizedArray<Number> & is_converged,
98 dealii::VectorizedArray<Number> norm_r_abs,
100 dealii::VectorizedArray<Number> norm_r_rel,
103 unsigned int MAX_ITER)
105 for(
unsigned int v = 0; v < dealii::VectorizedArray<Number>::size(); ++v)
107 if((norm_r_abs[v] < ABS_TOL or norm_r_rel[v] < REL_TOL or k >= MAX_ITER))
108 is_converged[v] = 1.0;
110 is_converged[v] = -1.0;
113 return all_true(is_converged);
116template<
typename Number>
118adjust_division_by_zero(Number &)
122template<
typename Number>
124adjust_division_by_zero(dealii::VectorizedArray<Number> & x)
126 for(
unsigned int i = 0; i < dealii::VectorizedArray<Number>::size(); ++i)
131template<
typename value_type>
133scale(value_type * dst, value_type
const scalar,
unsigned int const size)
135 for(
unsigned int i = 0; i < size; ++i)
139template<
typename value_type,
typename value_type_scalar>
141scale(value_type * dst, value_type_scalar
const scalar,
unsigned int const size)
143 for(
unsigned int i = 0; i < size; ++i)
144 dst[i] = scalar * dst[i];
147template<
typename value_type>
149inner_product(value_type
const * vector1, value_type
const * vector2,
unsigned int const size)
151 value_type result = value_type();
152 for(
unsigned int i = 0; i < size; ++i)
153 result += vector1[i] * vector2[i];
158template<
typename value_type>
160l2_norm(value_type
const * vector,
unsigned int const size)
162 return std::sqrt(inner_product(vector, vector, size));
165template<
typename value_type>
167vector_init(value_type * vector,
unsigned int const size)
169 for(
unsigned int i = 0; i < size; ++i)
173template<
typename value_type>
176 value_type
const scalar,
177 value_type
const * in_vector,
178 unsigned int const size)
180 for(
unsigned int i = 0; i < size; ++i)
181 dst[i] = scalar * in_vector[i];
184template<
typename value_type>
187 value_type
const scalar1,
188 value_type
const * in_vector1,
189 value_type
const scalar2,
190 value_type
const * in_vector2,
191 unsigned int const size)
193 for(
unsigned int i = 0; i < size; ++i)
194 dst[i] = scalar1 * in_vector1[i] + scalar2 * in_vector2[i];
197template<
typename value_type>
200 value_type
const scalar,
201 value_type
const * in_vector,
202 unsigned int const size)
204 for(
unsigned int i = 0; i < size; ++i)
205 dst[i] += scalar * in_vector[i];
211template<
typename value_type,
typename Matrix,
typename Preconditioner>
220 solve(Matrix
const * matrix,
221 value_type * solution,
222 value_type
const * rhs,
223 Preconditioner
const * preconditioner) = 0;
229template<
typename value_type,
typename Matrix,
typename Preconditioner>
230class SolverCG :
public SolverBase<value_type, Matrix, Preconditioner>
233 SolverCG(
unsigned int const unknowns,
SolverData const & solver_data);
236 solve(Matrix
const * matrix,
237 value_type * solution,
238 value_type
const * rhs,
239 Preconditioner
const * preconditioner)
final;
242 unsigned int const M;
243 double const ABS_TOL;
244 double const REL_TOL;
245 unsigned int const MAX_ITER;
246 dealii::AlignedVector<value_type> storage;
247 value_type * p, *r, *v;
253template<
typename value_type,
typename Matrix,
typename Preconditioner>
254SolverCG<value_type, Matrix, Preconditioner>::SolverCG(
unsigned int const unknowns,
257 ABS_TOL(solver_data.abs_tol),
258 REL_TOL(solver_data.rel_tol),
259 MAX_ITER(solver_data.max_iter)
261 storage.resize(3 * M);
263 r = storage.begin() + M;
264 v = storage.begin() + 2 * M;
267template<
typename value_type,
typename Matrix,
typename Preconditioner>
269SolverCG<value_type, Matrix, Preconditioner>::solve(Matrix
const * matrix,
270 value_type * solution,
271 value_type
const * rhs,
272 Preconditioner
const * preconditioner)
278 vector_init(solution, M);
281 matrix->vmult(v, solution);
284 equ(r, one, rhs, -one, v, M);
285 value_type norm_r0 = l2_norm(r, M);
288 preconditioner->vmult(p, r);
291 value_type norm_r_abs = norm_r0;
292 value_type norm_r_rel = one;
295 value_type r_times_y = inner_product(r, p, M);
297 unsigned int n_iter = 0;
305 value_type p_times_v = inner_product(p, v, M);
306 adjust_division_by_zero(p_times_v);
309 value_type alpha = (r_times_y) / (p_times_v);
312 add(solution, alpha, p, M);
315 add(r, -alpha, v, M);
318 norm_r_abs = l2_norm(r, M);
319 norm_r_rel = norm_r_abs / norm_r0;
325 if(all_smaller(norm_r_abs, ABS_TOL) or all_smaller(norm_r_rel, REL_TOL) or (n_iter > MAX_ITER))
333 preconditioner->vmult(v, r);
336 value_type r_times_y_new = inner_product(r, v, M);
339 value_type beta = r_times_y_new / r_times_y;
342 equ(p, one, v, beta, p, M);
344 r_times_y = r_times_y_new;
354template<
typename value_type,
typename Matrix,
typename Preconditioner>
355class SolverGMRES :
public SolverBase<value_type, Matrix, Preconditioner>
358 SolverGMRES(
unsigned int const unknowns,
SolverData const & solver_data);
361 solve(Matrix
const * A, value_type * x, value_type
const * b, Preconditioner
const * P)
final;
365 unsigned int const M;
368 double const ABS_TOL;
369 double const REL_TOL;
372 unsigned int const MAX_ITER;
375 unsigned int const MAX_KRYLOV_SIZE;
378 value_type norm_r_abs;
379 value_type norm_r_initial;
380 value_type norm_r_rel;
386 value_type convergence_status;
389 unsigned int iterations;
395 dealii::AlignedVector<dealii::AlignedVector<value_type>> V;
396 dealii::AlignedVector<dealii::AlignedVector<value_type>> H;
399 dealii::AlignedVector<value_type> temp;
402 dealii::AlignedVector<value_type> res;
403 dealii::AlignedVector<value_type> s;
404 dealii::AlignedVector<value_type> c;
414 do_solve(Matrix
const * A, value_type * x, value_type
const * b, Preconditioner
const * P);
417 modified_gram_schmidt(dealii::AlignedVector<value_type> & w,
418 dealii::AlignedVector<dealii::AlignedVector<value_type>> & H,
419 dealii::AlignedVector<dealii::AlignedVector<value_type>>
const & V,
420 unsigned int const dim);
422 template<
typename Number>
423 void perform_givens_rotation_and_calculate_residual(Number);
425 template<
typename Number>
426 void perform_givens_rotation_and_calculate_residual(dealii::VectorizedArray<Number>);
428 template<
typename Number>
429 void print(Number, std::string);
431 template<
typename Number>
433 print(dealii::VectorizedArray<Number> y, std::string name);
439template<
typename value_type,
typename Matrix,
typename Preconditioner>
440SolverGMRES<value_type, Matrix, Preconditioner>::SolverGMRES(
unsigned int const unknowns,
443 ABS_TOL(solver_data.abs_tol),
444 REL_TOL(solver_data.rel_tol),
445 MAX_ITER(solver_data.max_iter),
446 MAX_KRYLOV_SIZE(solver_data.max_krylov_size),
451 norm_r_initial = 1.0;
455 convergence_status = -1.0;
457 temp = dealii::AlignedVector<value_type>(M);
462template<
typename value_type,
typename Matrix,
typename Preconditioner>
464SolverGMRES<value_type, Matrix, Preconditioner>::clear()
474template<
typename value_type,
typename Matrix,
typename Preconditioner>
475template<
typename Number>
476void SolverGMRES<value_type, Matrix, Preconditioner>::print(Number, std::string)
483template<
typename value_type,
typename Matrix,
typename Preconditioner>
484template<
typename Number>
486SolverGMRES<value_type, Matrix, Preconditioner>::print(dealii::VectorizedArray<Number> y,
489 for(
unsigned int v = 0; v < dealii::VectorizedArray<double>::size(); ++v)
491 std::cout << name <<
"[" << v <<
"] = " << y[v] << std::endl;
514template<
typename value_type,
typename Matrix,
typename Preconditioner>
516SolverGMRES<value_type, Matrix, Preconditioner>::modified_gram_schmidt(
517 dealii::AlignedVector<value_type> & w,
518 dealii::AlignedVector<dealii::AlignedVector<value_type>> & H,
519 dealii::AlignedVector<dealii::AlignedVector<value_type>>
const & V,
520 unsigned int const dim)
522 for(
unsigned int i = 0; i < dim; ++i)
524 H[dim - 1][i] = inner_product(w.begin(), V[i].begin(), M);
525 add(w.begin(), -H[dim - 1][i], V[i].begin(), M);
528 H[dim - 1][dim] = l2_norm(w.begin(), M);
531template<
typename value_type,
typename Matrix,
typename Preconditioner>
532template<
typename Number>
534 SolverGMRES<value_type, Matrix, Preconditioner>::perform_givens_rotation_and_calculate_residual(
538 for(
int i = 0; i <= int(k) - 1; ++i)
540 value_type H_i_k = H[k][i];
541 value_type H_ip1_k = H[k][i + 1];
543 H[k][i] = c[i] * H_i_k + s[i] * H_ip1_k;
544 H[k][i + 1] = -s[i] * H_i_k + c[i] * H_ip1_k;
548 value_type beta = std::sqrt(H[k][k] * H[k][k] + H[k][k + 1] * H[k][k + 1]);
549 s.push_back(H[k][k + 1] / beta);
550 c.push_back(H[k][k] / beta);
554 value_type res_k_store = res[k];
556 res[k] = c[k] * res_k_store;
557 res.push_back(-s[k] * res_k_store);
560template<
typename value_type,
typename Matrix,
typename Preconditioner>
561template<
typename Number>
563 SolverGMRES<value_type, Matrix, Preconditioner>::perform_givens_rotation_and_calculate_residual(
564 dealii::VectorizedArray<Number>)
566 dealii::VectorizedArray<Number> H_i_k = dealii::VectorizedArray<Number>();
567 dealii::VectorizedArray<Number> H_ip1_k = dealii::VectorizedArray<Number>();
569 for(
unsigned int v = 0; v < dealii::VectorizedArray<Number>::size(); ++v)
571 if(convergence_status[v] > 0.0)
580 for(
int i = 0; i <= int(k) - 1; ++i)
586 for(
int i = 0; i <= int(k) - 1; ++i)
588 H_i_k[v] = H[k][i][v];
589 H_ip1_k[v] = H[k][i + 1][v];
591 H[k][i][v] = c[i][v] * H_i_k[v] + s[i][v] * H_ip1_k[v];
592 H[k][i + 1][v] = -s[i][v] * H_i_k[v] + c[i][v] * H_ip1_k[v];
597 dealii::VectorizedArray<Number> beta = dealii::VectorizedArray<Number>();
598 dealii::VectorizedArray<Number> sin = dealii::VectorizedArray<Number>();
599 dealii::VectorizedArray<Number> cos = dealii::VectorizedArray<Number>();
600 dealii::VectorizedArray<Number> res_k_store = dealii::VectorizedArray<Number>();
601 res_k_store = res[k];
602 dealii::VectorizedArray<Number> res_k = dealii::VectorizedArray<Number>();
603 dealii::VectorizedArray<Number> res_kp1 = dealii::VectorizedArray<Number>();
605 for(
unsigned int v = 0; v < dealii::VectorizedArray<Number>::size(); ++v)
607 if(convergence_status[v] > 0.0)
618 beta[v] = std::sqrt(H[k][k][v] * H[k][k][v] + H[k][k + 1][v] * H[k][k + 1][v]);
619 sin[v] = H[k][k + 1][v] / beta[v];
620 cos[v] = H[k][k][v] / beta[v];
621 H[k][k][v] = beta[v];
622 res_k[v] = cos[v] * res_k_store[v];
623 res_kp1[v] = -sin[v] * res_k_store[v];
630 res.push_back(res_kp1);
641template<
typename value_type,
typename Matrix,
typename Preconditioner>
643SolverGMRES<value_type, Matrix, Preconditioner>::solve(Matrix
const * A,
645 value_type
const * b,
646 Preconditioner
const * P)
663 do_solve(A, x, b, P);
667 }
while(not converged(
668 convergence_status, norm_r_abs, ABS_TOL, norm_r_rel, REL_TOL, iterations, MAX_ITER));
687template<
typename value_type,
typename Matrix,
typename Preconditioner>
689SolverGMRES<value_type, Matrix, Preconditioner>::do_solve(Matrix
const * A,
691 value_type
const * b,
692 Preconditioner
const * P)
695 V.push_back(dealii::AlignedVector<value_type>(M));
696 A->vmult(V[0].begin(), x);
699 equ(V[0].begin(), one, b, -one, V[0].begin(), M);
700 res.push_back(l2_norm(V[0].begin(), M));
707 norm_r_initial = res[0];
708 adjust_division_by_zero(norm_r_initial);
713 norm_r_rel = res[0] / norm_r_initial;
716 not converged(convergence_status, norm_r_abs, ABS_TOL, norm_r_rel, REL_TOL, k, MAX_KRYLOV_SIZE))
721 adjust_division_by_zero(res[0]);
722 scale(V[0].begin(), one / res[0], M);
728 adjust_division_by_zero(H[k_last][k_last + 1]);
729 scale(V[k_last + 1].begin(), one / H[k_last][k_last + 1], M);
734 V.push_back(dealii::AlignedVector<value_type>(M));
737 P->vmult(temp.begin(), V[k].begin());
739 A->vmult(V[k + 1].begin(), temp.begin());
742 H.push_back(dealii::AlignedVector<value_type>(k + 2));
745 modified_gram_schmidt(V[k + 1], H, V, k + 1);
747 value_type dummy = value_type();
748 perform_givens_rotation_and_calculate_residual(dummy);
751 norm_r_abs = std::abs(res[k + 1]);
752 norm_r_rel = norm_r_abs / norm_r_initial;
759 dealii::AlignedVector<value_type> y(k);
760 dealii::AlignedVector<value_type> delta = dealii::AlignedVector<value_type>(M);
793 for(
int i =
int(k) - 1; i >= 0; --i)
795 value_type sum = value_type();
796 for(
unsigned int j = i + 1; j <= k - 1; ++j)
798 sum += H[j][i] * y[j];
800 adjust_division_by_zero(H[i][i]);
801 y[i] = one / H[i][i] * (res[i] - sum);
803 add(delta.begin(), y[i], V[i].begin(), M);
807 P->vmult(temp.begin(), delta.begin());
808 add(x, one, temp.begin(), M);
Definition elementwise_krylov_solvers.h:213
Definition solver_data.h:34