4#include "krylov/gmres_base.h"
5#include "common/macros.h"
9namespace rsmesh::krylov {
10 bool gmres_base::print_progress =
true;
12 double gmres_base::absolute_residual()
const {
return std::abs(g_(iter_)); }
14 bool gmres_base::converged()
const {
return converged_; }
16 index_t gmres_base::iteration_count()
const {
return iter_; }
18 index_t gmres_base::max_iterations()
const {
return max_iter_; }
20 double gmres_base::relative_residual()
const {
return std::abs(g_(iter_)) / rhs_norm_; }
22 void gmres_base::set_left_preconditioner(
const linear_operator& left_preconditioner) {
23 RSMESH_ASSERT(left_preconditioner.size() == m_);
25 left_pc_ = &left_preconditioner;
28 void gmres_base::set_initial_solution(
const valuesd& x0) {
29 RSMESH_ASSERT(x0.rows() == m_);
34 void gmres_base::set_right_preconditioner(
const linear_operator& right_preconditioner) {
35 RSMESH_ASSERT(right_preconditioner.size() == m_);
37 right_pc_ = &right_preconditioner;
40 void gmres_base::setup() {
41 c_ = valuesd::Zero(max_iter_);
42 s_ = valuesd::Zero(max_iter_);
44 g_ = valuesd::Zero(max_iter_ + 1);
48 r0 = left_preconditioned(rhs_);
50 r0 = left_preconditioned(rhs_ - op_(x0_));
53 vs_.emplace_back(r0 / g_(0));
55 r_ = Eigen::MatrixXd::Zero(max_iter_ + 1, max_iter_);
58 valuesd gmres_base::solution_vector()
const {
61 valuesd y = valuesd::Zero(iter_);
62 for (index_t j = iter_ - 1; j >= 0; j--) {
64 for (index_t i = j + 1; i <= iter_ - 1; i++) {
65 y(j) -= r_(j, i) * y(i);
70 valuesd x = valuesd::Zero(m_);
71 for (index_t i = 0; i < iter_; i++) {
72 x += y(i) * vs_.at(i);
74 x = right_preconditioned(x);
80 void gmres_base::solve(
double tolerance) {
81 for (; iter_ < max_iter_;) {
83 std::cout << iter_ <<
": \t" << relative_residual() << std::endl;
86 if (relative_residual() < tolerance) {
92 std::cout << iter_ <<
": \t" << relative_residual() << std::endl;
96 gmres_base::gmres_base(
const linear_operator& op,
const valuesd& rhs, index_t max_iter)
98 m_(static_cast<index_t>(rhs.rows())),
100 x0_(valuesd::Zero(m_)),
102 rhs_norm_(rhs.norm()) {}
104 valuesd gmres_base::left_preconditioned(
const valuesd& x)
const {
105 return left_pc_ !=
nullptr ? (*left_pc_)(x) : x;
108 valuesd gmres_base::right_preconditioned(
const valuesd& x)
const {
109 return right_pc_ !=
nullptr ? (*right_pc_)(x) : x;