ExaDG
Loading...
Searching...
No Matches
elementwise_krylov_solvers.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef INCLUDE_SOLVERS_AND_PRECONDITIONERS_ELEMENTWISE_KRYLOV_SOLVERS_H_
23#define INCLUDE_SOLVERS_AND_PRECONDITIONERS_ELEMENTWISE_KRYLOV_SOLVERS_H_
24
25// deal.II
26#include <deal.II/base/aligned_vector.h>
27#include <deal.II/base/vectorization.h>
28
29// ExaDG
30#include <exadg/solvers_and_preconditioners/solvers/solver_data.h>
31
32namespace ExaDG
33{
34namespace Elementwise
35{
36template<typename Number, typename Number2>
37bool
38all_smaller(Number const a, const Number2 b)
39{
40 return a < b;
41}
42
43template<typename Number, typename Number2>
44bool
45all_smaller(dealii::VectorizedArray<Number> const a, Number2 const b)
46{
47 for(unsigned int i = 0; i < dealii::VectorizedArray<Number>::size(); ++i)
48 if(a[i] >= b)
49 return false;
50 return true;
51}
52
53template<typename Number>
54bool
55all_true(Number const a)
56{
57 return (a >= 0);
58}
59
60template<typename Number>
61bool
62all_true(dealii::VectorizedArray<Number> const a)
63{
64 for(unsigned int i = 0; i < dealii::VectorizedArray<Number>::size(); ++i)
65 if(a[i] < 0)
66 return false;
67 return true;
68}
69
70template<typename Number, typename Number2>
71bool
72converged(Number & is_converged,
73 Number norm_r_abs,
74 Number2 ABS_TOL,
75 Number norm_r_rel,
76 Number2 REL_TOL,
77 unsigned int k,
78 unsigned int MAX_ITER)
79{
80 bool is_converged_bool = true;
81 if(norm_r_abs < ABS_TOL or norm_r_rel < REL_TOL or k >= MAX_ITER)
82 {
83 is_converged = 1.0;
84 is_converged_bool = true;
85 }
86 else
87 {
88 is_converged = -1.0;
89 is_converged_bool = false;
90 }
91
92 return is_converged_bool;
93}
94
95template<typename Number, typename Number2>
96bool
97converged(dealii::VectorizedArray<Number> & is_converged,
98 dealii::VectorizedArray<Number> norm_r_abs,
99 Number2 ABS_TOL,
100 dealii::VectorizedArray<Number> norm_r_rel,
101 Number2 REL_TOL,
102 unsigned int k,
103 unsigned int MAX_ITER)
104{
105 for(unsigned int v = 0; v < dealii::VectorizedArray<Number>::size(); ++v)
106 {
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;
109 else
110 is_converged[v] = -1.0;
111 }
112
113 return all_true(is_converged);
114}
115
116template<typename Number>
117void
118adjust_division_by_zero(Number &)
119{
120}
121
122template<typename Number>
123void
124adjust_division_by_zero(dealii::VectorizedArray<Number> & x)
125{
126 for(unsigned int i = 0; i < dealii::VectorizedArray<Number>::size(); ++i)
127 if(x[i] < 1e-30)
128 x[i] = 1;
129}
130
131template<typename value_type>
132void
133scale(value_type * dst, value_type const scalar, unsigned int const size)
134{
135 for(unsigned int i = 0; i < size; ++i)
136 dst[i] *= scalar;
137}
138
139template<typename value_type, typename value_type_scalar>
140void
141scale(value_type * dst, value_type_scalar const scalar, unsigned int const size)
142{
143 for(unsigned int i = 0; i < size; ++i)
144 dst[i] = scalar * dst[i];
145}
146
147template<typename value_type>
148value_type
149inner_product(value_type const * vector1, value_type const * vector2, unsigned int const size)
150{
151 value_type result = value_type();
152 for(unsigned int i = 0; i < size; ++i)
153 result += vector1[i] * vector2[i];
154
155 return result;
156}
157
158template<typename value_type>
159value_type
160l2_norm(value_type const * vector, unsigned int const size)
161{
162 return std::sqrt(inner_product(vector, vector, size));
163}
164
165template<typename value_type>
166void
167vector_init(value_type * vector, unsigned int const size)
168{
169 for(unsigned int i = 0; i < size; ++i)
170 vector[i] = 0.0;
171}
172
173template<typename value_type>
174void
175equ(value_type * dst,
176 value_type const scalar,
177 value_type const * in_vector,
178 unsigned int const size)
179{
180 for(unsigned int i = 0; i < size; ++i)
181 dst[i] = scalar * in_vector[i];
182}
183
184template<typename value_type>
185void
186equ(value_type * dst,
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)
192{
193 for(unsigned int i = 0; i < size; ++i)
194 dst[i] = scalar1 * in_vector1[i] + scalar2 * in_vector2[i];
195}
196
197template<typename value_type>
198void
199add(value_type * dst,
200 value_type const scalar,
201 value_type const * in_vector,
202 unsigned int const size)
203{
204 for(unsigned int i = 0; i < size; ++i)
205 dst[i] += scalar * in_vector[i];
206}
207
208/*
209 * Base class.
210 */
211template<typename value_type, typename Matrix, typename Preconditioner>
213{
214public:
215 virtual ~SolverBase()
216 {
217 }
218
219 virtual void
220 solve(Matrix const * matrix,
221 value_type * solution,
222 value_type const * rhs,
223 Preconditioner const * preconditioner) = 0;
224};
225
226/*
227 * CG solver.
228 */
229template<typename value_type, typename Matrix, typename Preconditioner>
230class SolverCG : public SolverBase<value_type, Matrix, Preconditioner>
231{
232public:
233 SolverCG(unsigned int const unknowns, SolverData const & solver_data);
234
235 void
236 solve(Matrix const * matrix,
237 value_type * solution,
238 value_type const * rhs,
239 Preconditioner const * preconditioner) final;
240
241private:
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;
248};
249
250/*
251 * Implementation of CG solver
252 */
253template<typename value_type, typename Matrix, typename Preconditioner>
255 SolverData const & solver_data)
256 : M(unknowns),
257 ABS_TOL(solver_data.abs_tol),
258 REL_TOL(solver_data.rel_tol),
259 MAX_ITER(solver_data.max_iter)
260{
261 storage.resize(3 * M);
262 p = storage.begin();
263 r = storage.begin() + M;
264 v = storage.begin() + 2 * M;
265}
266
267template<typename value_type, typename Matrix, typename Preconditioner>
268void
269SolverCG<value_type, Matrix, Preconditioner>::solve(Matrix const * matrix,
270 value_type * solution,
271 value_type const * rhs,
272 Preconditioner const * preconditioner)
273{
274 value_type one;
275 one = 1.0;
276
277 // guess initial solution
278 vector_init(solution, M);
279
280 // apply matrix vector product: v = A*solution
281 matrix->vmult(v, solution);
282
283 // compute residual: r = rhs-A*solution
284 equ(r, one, rhs, -one, v, M);
285 value_type norm_r0 = l2_norm(r, M);
286
287 // precondition
288 preconditioner->vmult(p, r);
289
290 // compute norm of residual
291 value_type norm_r_abs = norm_r0;
292 value_type norm_r_rel = one;
293
294 // compute (r^{0})^T * y^{0} = (r^{0})^T * p^{0}
295 value_type r_times_y = inner_product(r, p, M);
296
297 unsigned int n_iter = 0;
298
299 while(true)
300 {
301 // v = A*p
302 matrix->vmult(v, p);
303
304 // p_times_v = p^T*v
305 value_type p_times_v = inner_product(p, v, M);
306 adjust_division_by_zero(p_times_v);
307
308 // alpha = (r^T*y) / (p^T*v)
309 value_type alpha = (r_times_y) / (p_times_v);
310
311 // solution <- solution + alpha*p
312 add(solution, alpha, p, M);
313
314 // r <- r - alpha*v
315 add(r, -alpha, v, M);
316
317 // calculate residual norm
318 norm_r_abs = l2_norm(r, M);
319 norm_r_rel = norm_r_abs / norm_r0;
320
321 // increment iteration counter
322 ++n_iter;
323
324 // check convergence
325 if(all_smaller(norm_r_abs, ABS_TOL) or all_smaller(norm_r_rel, REL_TOL) or (n_iter > MAX_ITER))
326 {
327 break;
328 }
329
330 // precondition: y = P^{-1} * r
331 // Note: we use v instead of y to avoid
332 // the storage of another variable y
333 preconditioner->vmult(v, r);
334
335 // compute r_times_y_new = r^T*y
336 value_type r_times_y_new = inner_product(r, v, M);
337
338 // beta = (r^T*y)_new / (r^T*y)
339 value_type beta = r_times_y_new / r_times_y;
340
341 // p <- y + beta*p
342 equ(p, one, v, beta, p, M);
343
344 r_times_y = r_times_y_new;
345 }
346
347 // std::cout<<"Number of iterations = "<< n_iter << std::endl;
348}
349
350
351/*
352 * GMRES solver with right preconditioning and restart.
353 */
354template<typename value_type, typename Matrix, typename Preconditioner>
355class SolverGMRES : public SolverBase<value_type, Matrix, Preconditioner>
356{
357public:
358 SolverGMRES(unsigned int const unknowns, SolverData const & solver_data);
359
360 void
361 solve(Matrix const * A, value_type * x, value_type const * b, Preconditioner const * P) final;
362
363private:
364 // Matrix size MxM
365 unsigned int const M;
366
367 // absolute and relative solver tolerances
368 double const ABS_TOL;
369 double const REL_TOL;
370
371 // maximum number of (overall iterations)
372 unsigned int const MAX_ITER;
373
374 // maximum number of iterations before restart
375 unsigned int const MAX_KRYLOV_SIZE;
376
377 // absolute and relative norm of residual
378 value_type norm_r_abs;
379 value_type norm_r_initial;
380 value_type norm_r_rel;
381
382 // store convergence status which is necessary
383 // for the dealii::VectorizedArray data type where the
384 // convergence status of the different elements
385 // of dealii::VectorizedArray has to be tracked seperately
386 value_type convergence_status;
387
388 // accumulated iterations
389 unsigned int iterations;
390 // local iteration counter which
391 // will be reset after restart
392 unsigned int k;
393
394 // matrices of variable size
395 dealii::AlignedVector<dealii::AlignedVector<value_type>> V;
396 dealii::AlignedVector<dealii::AlignedVector<value_type>> H;
397
398 // temporary vector
399 dealii::AlignedVector<value_type> temp;
400
401 // vectors of variable size
402 dealii::AlignedVector<value_type> res;
403 dealii::AlignedVector<value_type> s;
404 dealii::AlignedVector<value_type> c;
405
406 // neutral element of multiplication
407 // for data of type value_type
408 value_type one;
409
410 void
411 clear();
412
413 void
414 do_solve(Matrix const * A, value_type * x, value_type const * b, Preconditioner const * P);
415
416 void
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);
421
422 template<typename Number>
423 void perform_givens_rotation_and_calculate_residual(Number);
424
425 template<typename Number>
426 void perform_givens_rotation_and_calculate_residual(dealii::VectorizedArray<Number>);
427
428 template<typename Number>
429 void print(Number, std::string);
430
431 template<typename Number>
432 void
433 print(dealii::VectorizedArray<Number> y, std::string name);
434};
435
436/*
437 * Implementation of GMRES solver.
438 */
439template<typename value_type, typename Matrix, typename Preconditioner>
441 SolverData const & solver_data)
442 : M(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),
447 iterations(0),
448 k(0)
449{
450 norm_r_abs = 1.0;
451 norm_r_initial = 1.0;
452 norm_r_rel = 1.0;
453
454 // negative values = false (not converged)
455 convergence_status = -1.0;
456
457 temp = dealii::AlignedVector<value_type>(M);
458
459 one = 1.0;
460}
461
462template<typename value_type, typename Matrix, typename Preconditioner>
463void
464SolverGMRES<value_type, Matrix, Preconditioner>::clear()
465{
466 // clear all data
467 V.clear();
468 H.clear();
469 res.clear();
470 s.clear();
471 c.clear();
472}
473
474template<typename value_type, typename Matrix, typename Preconditioner>
475template<typename Number>
476void SolverGMRES<value_type, Matrix, Preconditioner>::print(Number, std::string)
477{
478}
479
480/*
481 * Print function for data of type dealii::VectorizedArray
482 */
483template<typename value_type, typename Matrix, typename Preconditioner>
484template<typename Number>
485void
486SolverGMRES<value_type, Matrix, Preconditioner>::print(dealii::VectorizedArray<Number> y,
487 std::string name)
488{
489 for(unsigned int v = 0; v < dealii::VectorizedArray<double>::size(); ++v)
490 {
491 std::cout << name << "[" << v << "] = " << y[v] << std::endl;
492 }
493}
494
495/*
496 * w: new search direction
497 * H: Hessenberg matrix
498 * V: contains orthogonal vectors
499 * dim: number of orthogonal vectors
500 *
501 * fill dim-th column of Hessenberg matrix
502 * and update vector w such that it is orthogonal
503 * the all previous vector in V
504 *
505 * The operations performed here are "unproblematic"
506 * and can be performed also in the case of the
507 * dealii::VectorizedArray data type, i.e., the values written
508 * to the Hessenberg matrix in this function are
509 * ignored in case that the solver has already converged
510 * for a specific component of the vectorized array
511 * (we explicitly overwrite this column of the Hessenberg
512 * matrix when performing the Givens rotation.
513 */
514template<typename value_type, typename Matrix, typename Preconditioner>
515void
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)
521{
522 for(unsigned int i = 0; i < dim; ++i)
523 {
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);
526 }
527
528 H[dim - 1][dim] = l2_norm(w.begin(), M);
529}
530
531template<typename value_type, typename Matrix, typename Preconditioner>
532template<typename Number>
533void
534 SolverGMRES<value_type, Matrix, Preconditioner>::perform_givens_rotation_and_calculate_residual(
535 Number)
536{
537 // Givens rotations for Hessenberg matrix
538 for(int i = 0; i <= int(k) - 1; ++i)
539 {
540 value_type H_i_k = H[k][i];
541 value_type H_ip1_k = H[k][i + 1];
542
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;
545 }
546
547 // Givens rotations for residual-vector
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);
551
552 H[k][k] = beta;
553
554 value_type res_k_store = res[k];
555
556 res[k] = c[k] * res_k_store;
557 res.push_back(-s[k] * res_k_store);
558}
559
560template<typename value_type, typename Matrix, typename Preconditioner>
561template<typename Number>
562void
563 SolverGMRES<value_type, Matrix, Preconditioner>::perform_givens_rotation_and_calculate_residual(
564 dealii::VectorizedArray<Number>)
565{
566 dealii::VectorizedArray<Number> H_i_k = dealii::VectorizedArray<Number>();
567 dealii::VectorizedArray<Number> H_ip1_k = dealii::VectorizedArray<Number>();
568
569 for(unsigned int v = 0; v < dealii::VectorizedArray<Number>::size(); ++v)
570 {
571 if(convergence_status[v] > 0.0)
572 {
573 // Set a value of 1 for row_index = col_index
574 // The (k,k) entry is set to 1 because we divide by H(k,k) during
575 // the backward substitution.
576 H[k][k][v] = 1.0;
577 // set a value of 0 for all other entries of this column
578 // this has to be done in order to not change the results of
579 // the backward substitution.
580 for(int i = 0; i <= int(k) - 1; ++i)
581 H[k][i][v] = 0.0;
582 }
583 else
584 {
585 // Givens rotations for Hessenberg matrix
586 for(int i = 0; i <= int(k) - 1; ++i)
587 {
588 H_i_k[v] = H[k][i][v];
589 H_ip1_k[v] = H[k][i + 1][v];
590
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];
593 }
594 }
595 }
596
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>();
604
605 for(unsigned int v = 0; v < dealii::VectorizedArray<Number>::size(); ++v)
606 {
607 if(convergence_status[v] > 0.0)
608 {
609 // set residual to zero
610 // This has to be done in order to ensure that the
611 // vector v^(k) does not contribute to the solution x,
612 // see also backward substitution.
613 res_k[v] = 0.0;
614 }
615 else
616 {
617 // Givens rotations for residual-vector
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];
624 }
625 }
626
627 s.push_back(sin);
628 c.push_back(cos);
629 res[k] = res_k;
630 res.push_back(res_kp1);
631}
632
633/*
634 * Linear system of equations: Ax = b
635 * A: matrix
636 * P: preconditioner
637 * x: solution vector
638 * b: rhs vector
639 * r: residual r = b - A*x
640 */
641template<typename value_type, typename Matrix, typename Preconditioner>
642void
643SolverGMRES<value_type, Matrix, Preconditioner>::solve(Matrix const * A,
644 value_type * x,
645 value_type const * b,
646 Preconditioner const * P)
647{
648 iterations = 0;
649
650 // restarted GMRES
651 do
652 {
653 // reset local iteration counter
654 k = 0;
655
656 // make sure that memory allocated
657 // in previous solves is released
658 clear();
659
660 // apply GMRES solver where the
661 // maximum number of iterations is set
662 // to the maximum size of the Krylov subspace
663 do_solve(A, x, b, P);
664
665 iterations += k;
666
667 } while(not converged(
668 convergence_status, norm_r_abs, ABS_TOL, norm_r_rel, REL_TOL, iterations, MAX_ITER));
669
670 // output convergence info
671 // std::cout << "Number of iterations = " << iterations << std::endl;
672
673 // std::cout<<std::endl;
674 // print(convergence_status,"convergence status");
675 //
676 // // check convergence by computing the residual using
677 // // the solution x: r = b - A*x
678 //
679 // //temp2 = A*x
680 // dealii::AlignedVector<value_type> temp2 = dealii::AlignedVector<value_type>(M);
681 // A->vmult(temp2.begin(),x);
682 // // temp = b - temp2 = b - A*x = r
683 // equ(temp.begin(),one,b,-one,temp2.begin());
684 // print(l2_norm(temp.begin()),"l2-norm of residual");
685}
686
687template<typename value_type, typename Matrix, typename Preconditioner>
688void
689SolverGMRES<value_type, Matrix, Preconditioner>::do_solve(Matrix const * A,
690 value_type * x,
691 value_type const * b,
692 Preconditioner const * P)
693{
694 // apply matrix vector product: r = A*x
695 V.push_back(dealii::AlignedVector<value_type>(M));
696 A->vmult(V[0].begin(), x);
697
698 // compute residual r = b - A*x and its norm
699 equ(V[0].begin(), one, b, -one, V[0].begin(), M);
700 res.push_back(l2_norm(V[0].begin(), M));
701
702 // reset initial residual only in the first iteration
703 // but not for the restarted iterations and
704 // make sure that initial residual is not zero
705 if(iterations == k)
706 {
707 norm_r_initial = res[0];
708 adjust_division_by_zero(norm_r_initial);
709 }
710
711 // compute absolute and relative residuals
712 norm_r_abs = res[0];
713 norm_r_rel = res[0] / norm_r_initial;
714
715 while(
716 not converged(convergence_status, norm_r_abs, ABS_TOL, norm_r_rel, REL_TOL, k, MAX_KRYLOV_SIZE))
717 {
718 // normalize vector v^(k)
719 if(k == 0)
720 {
721 adjust_division_by_zero(res[0]);
722 scale(V[0].begin(), one / res[0], M);
723 }
724 else
725 {
726 int k_last = k - 1;
727
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);
730 }
731
732 // calculate new search direction by performing
733 // matrix-vector product: V[k+1] = A*V[k]
734 V.push_back(dealii::AlignedVector<value_type>(M));
735
736 // apply preconditioner
737 P->vmult(temp.begin(), V[k].begin());
738 // apply matrix-vector product
739 A->vmult(V[k + 1].begin(), temp.begin());
740
741 // resize H
742 H.push_back(dealii::AlignedVector<value_type>(k + 2));
743
744 // perform modified Gram-Schmidt orthogonalization
745 modified_gram_schmidt(V[k + 1], H, V, k + 1);
746
747 value_type dummy = value_type();
748 perform_givens_rotation_and_calculate_residual(dummy);
749
750 // calculate residual norm
751 norm_r_abs = std::abs(res[k + 1]);
752 norm_r_rel = norm_r_abs / norm_r_initial;
753
754 // increment local iteration counter
755 ++k;
756 }
757
758 // calculate solution
759 dealii::AlignedVector<value_type> y(k);
760 dealii::AlignedVector<value_type> delta = dealii::AlignedVector<value_type>(M);
761
762 /*
763 * calculate solution as linear combination of
764 * Krylov subspace vectors multiplied by coefficients y:
765 *
766 * x = x_0 + M^{-1}*V*y
767 *
768 * obtain coefficients y by backward substitution:
769 *
770 * H * y = res, where ...
771 * ... H is an uppper triangular matrix of dimension k x k, and
772 * ... y, res are vectors of dimension k
773 *
774 * standard: e.g. double/float type
775 * _ _ _ _ _ _
776 * | H_00 H_01 H_02 H_03 | | y_0 | | res_0 |
777 * | 0 H_11 H_12 H_13 | | y_1 | | res_1 | -> ...
778 * | 0 0 H_22 H_23 | | y_2 | = | res_2 | -> y_2 = (res_2-H_23*y_3)/H_22
779 * | 0 0 0 H_33 | | y_3 | | res_3 | -> y_3 = res_3/H_33
780 * |_ 0 0 0 0 _| |_ * _| |_ res_k+1 _|
781 *
782 * dealii::VectorizedArray: assume that the solver converged after 2 iterations
783 * for some components of the dealii::VectorizedArray
784 * but after 4 iterations for the other components
785 * _ _ _ _ _ _
786 * | H_00 H_01 0 0 | | y_0 | | res_0 | -> y_0 = (res_0-H_01*y_0)/H_00
787 * | 0 H_11 0 0 | | y_1 | | res_1 | -> y_1 = res_1/H_11
788 * | 0 0 1 0 | | y_2 | = | 0 | -> y_2 = 0 -> no contribution of v^(2)
789 * | 0 0 0 1 | | y_3 | | 0 | -> y_3 = 0 -> no contribution of v^(3)
790 * |_ 0 0 0 0 _| |_ * _| |_ res_k+1 _|
791 *
792 */
793 for(int i = int(k) - 1; i >= 0; --i)
794 {
795 value_type sum = value_type();
796 for(unsigned int j = i + 1; j <= k - 1; ++j)
797 {
798 sum += H[j][i] * y[j];
799 }
800 adjust_division_by_zero(H[i][i]);
801 y[i] = one / H[i][i] * (res[i] - sum);
802
803 add(delta.begin(), y[i], V[i].begin(), M);
804 }
805
806 // apply preconditioner and/or add to solution vector
807 P->vmult(temp.begin(), delta.begin());
808 add(x, one, temp.begin(), M);
809}
810
811} // namespace Elementwise
812} // namespace ExaDG
813
814#endif /* INCLUDE_SOLVERS_AND_PRECONDITIONERS_ELEMENTWISE_KRYLOV_SOLVERS_H_ */
Definition elementwise_krylov_solvers.h:213
Definition elementwise_krylov_solvers.h:231
Definition elementwise_krylov_solvers.h:356
Definition driver.cpp:33
Definition solver_data.h:34