RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
gmres_base.cpp
1//
2// Created by RainSure on 2024/2/13.
3//
4#include "krylov/gmres_base.h"
5#include "common/macros.h"
6#include <cmath>
7#include <iostream>
8
9namespace rsmesh::krylov {
10 bool gmres_base::print_progress = true;
11
12 double gmres_base::absolute_residual() const { return std::abs(g_(iter_)); }
13
14 bool gmres_base::converged() const { return converged_; }
15
16 index_t gmres_base::iteration_count() const { return iter_; }
17
18 index_t gmres_base::max_iterations() const { return max_iter_; }
19
20 double gmres_base::relative_residual() const { return std::abs(g_(iter_)) / rhs_norm_; }
21
22 void gmres_base::set_left_preconditioner(const linear_operator& left_preconditioner) {
23 RSMESH_ASSERT(left_preconditioner.size() == m_);
24
25 left_pc_ = &left_preconditioner;
26 }
27
28 void gmres_base::set_initial_solution(const valuesd& x0) {
29 RSMESH_ASSERT(x0.rows() == m_);
30
31 x0_ = x0;
32 }
33
34 void gmres_base::set_right_preconditioner(const linear_operator& right_preconditioner) {
35 RSMESH_ASSERT(right_preconditioner.size() == m_);
36
37 right_pc_ = &right_preconditioner;
38 }
39
40 void gmres_base::setup() {
41 c_ = valuesd::Zero(max_iter_);
42 s_ = valuesd::Zero(max_iter_);
43
44 g_ = valuesd::Zero(max_iter_ + 1);
45
46 valuesd r0;
47 if (x0_.isZero()) {
48 r0 = left_preconditioned(rhs_);
49 } else {
50 r0 = left_preconditioned(rhs_ - op_(x0_));
51 }
52 g_(0) = r0.norm();
53 vs_.emplace_back(r0 / g_(0));
54
55 r_ = Eigen::MatrixXd::Zero(max_iter_ + 1, max_iter_);
56 }
57
58 valuesd gmres_base::solution_vector() const {
59 // r is an upper triangular matrix.
60 // Perform backward substitution to solve r y == g for y.
61 valuesd y = valuesd::Zero(iter_);
62 for (index_t j = iter_ - 1; j >= 0; j--) {
63 y(j) = g_(j);
64 for (index_t i = j + 1; i <= iter_ - 1; i++) {
65 y(j) -= r_(j, i) * y(i);
66 }
67 y(j) /= r_(j, j);
68 }
69
70 valuesd x = valuesd::Zero(m_);
71 for (index_t i = 0; i < iter_; i++) {
72 x += y(i) * vs_.at(i);
73 }
74 x = right_preconditioned(x);
75 x += x0_;
76
77 return x;
78 }
79
80 void gmres_base::solve(double tolerance) {
81 for (; iter_ < max_iter_;) {
82 if (print_progress) {
83 std::cout << iter_ << ": \t" << relative_residual() << std::endl;
84 }
85 iterate_process();
86 if (relative_residual() < tolerance) {
87 converged_ = true;
88 break;
89 }
90 }
91 if (print_progress) {
92 std::cout << iter_ << ": \t" << relative_residual() << std::endl;
93 }
94 }
95
96 gmres_base::gmres_base(const linear_operator& op, const valuesd& rhs, index_t max_iter)
97 : op_(op),
98 m_(static_cast<index_t>(rhs.rows())),
99 max_iter_(max_iter),
100 x0_(valuesd::Zero(m_)),
101 rhs_(rhs),
102 rhs_norm_(rhs.norm()) {}
103
104 valuesd gmres_base::left_preconditioned(const valuesd& x) const {
105 return left_pc_ != nullptr ? (*left_pc_)(x) : x;
106 }
107
108 valuesd gmres_base::right_preconditioned(const valuesd& x) const {
109 return right_pc_ != nullptr ? (*right_pc_)(x) : x;
110 }
111}