numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
operator_conjugate_gradient.h
Go to the documentation of this file.
1/*
2 * Copyright 2024 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <limits>
23
24#include <Eigen/Core>
25
32
34
37 "num_collect::linear::impl::operator_conjugate_gradient");
38
45template <base::concepts::dense_vector Vector>
47public:
49 using vector_type = Vector;
50
52 using scalar_type = typename vector_type::Scalar;
53
59
76 template <base::concepts::invocable<const vector_type&, vector_type&>
77 CoeffFunction>
78 void solve(CoeffFunction&& coeff_function, const vector_type& rhs,
79 vector_type& solution) {
80 iterations_ = 0;
81
82 coeff_function(solution, residual_);
83 residual_ = rhs - residual_;
84 const scalar_type tolerance =
85 tolerance_rate_ * tolerance_rate_ * rhs.squaredNorm();
86 NUM_COLLECT_LOG_TRACE(this->logger(), "tolerance={}", tolerance);
87 scalar_type residual_norm = residual_.squaredNorm();
88 if (residual_norm <= tolerance) {
90 "No iteration needed. residual_norm={}", residual_norm);
91 return;
92 }
93 p_ = residual_;
95 coeff_function(p_, coeff_p_);
96 const scalar_type alpha = residual_.squaredNorm() /
97 (p_.dot(coeff_p_) +
98 std::numeric_limits<scalar_type>::epsilon());
99 solution += alpha * p_;
101 residual_ -= alpha * coeff_p_;
102 residual_norm = residual_.squaredNorm();
103 if (residual_norm <= tolerance) {
104 break;
105 }
106 const scalar_type beta = residual_norm /
107 (previous_residual_.squaredNorm() +
108 std::numeric_limits<scalar_type>::epsilon());
109 p_ = residual_ + beta * p_;
110 ++iterations_;
111 }
113 "Finished iterations: iterations={}, residual_norm={}", iterations_,
114 residual_norm);
115 }
116
125 tolerance_rate_ = val;
126 return *this;
127 }
128
134 auto iterations() -> index_type { return iterations_; }
135
136private:
139
141 static constexpr index_type default_max_iterations = 1000;
142
145
148 Eigen::NumTraits<scalar_type>::dummy_precision();
149
152
155
165};
166
167} // namespace num_collect::linear::impl
Class to perform conjugate gradient (CG) method golub2013 for linear operators.
static constexpr scalar_type default_tolerance_rate
Default rate of tolerance.
static constexpr index_type default_max_iterations
Default maximum number of iterations.
typename vector_type::Scalar scalar_type
Type of scalars.
auto tolerance_rate(const scalar_type &val) -> operator_conjugate_gradient &
Set the rate of tolerances.
void solve(CoeffFunction &&coeff_function, const vector_type &rhs, vector_type &solution)
Solve.
auto iterations() -> index_type
Get the number of iterations.
Class of tags of logs without memory management.
Class to incorporate logging in algorithms.
logging_mixin(log_tag_view tag)
Constructor.
auto logger() const noexcept -> const num_collect::logging::logger &
Access to the logger.
Definition of dense_vector concept.
Definition of index_type type.
Definition of invocable concept.
Definition of log_tag_view class.
Definition of macros for logging.
#define NUM_COLLECT_LOG_SUMMARY(LOGGER,...)
Write a summary log.
#define NUM_COLLECT_LOG_TRACE(LOGGER,...)
Write a trace log.
Definition of logging_mixin class.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
Namespace of internal implementations.
constexpr auto operator_conjugate_gradient_tag
Log tag of operator_conjugate_gradient.