numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
gmres_rosenbrock_equation_solver.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 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 <cmath> // IWYU pragma: keep
23#include <limits>
24#include <optional>
25
26#include <Eigen/Core> // IWYU pragma: keep
27
36
38
44template <concepts::multi_variate_problem Problem>
46public:
48 using problem_type = Problem;
49
51 using variable_type = typename problem_type::variable_type;
52
54 using scalar_type = typename problem_type::scalar_type;
55
57 static constexpr bool use_time_derivative =
59
60 static_assert(!problem_type::allowed_evaluations.mass,
61 "Mass matrix is not supported.");
62 // TODO: Support.
63
71 const scalar_type& inverted_jacobian_coeff)
72 : inverted_jacobian_coeff_(inverted_jacobian_coeff) {}
73
83 const scalar_type& time, const scalar_type& step_size,
84 const variable_type& variable) {
85 problem_ = &problem;
86 time_ = time;
87 step_size_ = step_size;
88 variable_ = variable;
89
90 problem.evaluate_on(time, variable,
92 .diff_coeff = true, .time_derivative = use_time_derivative});
93 if constexpr (use_time_derivative) {
94 time_derivative_ = problem.time_derivative();
95 }
96 }
97
106 void apply_jacobian(const Target& target, Result& result) {
108 problem_ != nullptr, "evaluate_and_update_jacobian is not called.");
109
110 const scalar_type target_norm = target.norm();
111 if (target_norm < std::numeric_limits<scalar_type>::min()) {
112 result = variable_type::Zero(target.size());
113 return;
114 }
115 const scalar_type diff_width =
116 std::sqrt(std::numeric_limits<scalar_type>::epsilon()) /
117 target_norm;
118
119 problem_->evaluate_on(time_, variable_ + diff_width * target,
120 evaluation_type{.diff_coeff = true});
121 result = problem_->diff_coeff();
122
123 problem_->evaluate_on(time_, variable_ - diff_width * target,
124 evaluation_type{.diff_coeff = true});
125 result -= problem_->diff_coeff();
126 result /= static_cast<scalar_type>(2) * diff_width;
127 }
128
137 const scalar_type& coeff, variable_type& target) {
138 if constexpr (use_time_derivative) {
139 if (time_derivative_) {
140 target += step_size * coeff * (*time_derivative_);
141 }
142 }
143 }
144
151 void solve(const variable_type& rhs, variable_type& result) {
152 static constexpr index_type max_iterations = 100;
153 const auto coeff_function = [this](const auto& target, auto& result) {
154 this->apply_jacobian(target, result);
156 result += target;
157 };
158 result = variable_type::Zero(rhs.size());
159 for (index_type i = 0; i < max_iterations; ++i) {
160 gmres_.solve(coeff_function, rhs, result);
161 coeff_function(result, residual_);
162 residual_ -= rhs;
163 if (tolerances_.calc_norm(variable_, residual_) <=
165 return;
166 }
167 }
168 }
169
178 return *this;
179 }
180
189 tolerances_ = val;
190 return *this;
191 }
192
193private:
196
199
202
205
207 std::optional<variable_type> time_derivative_{};
208
211
214
216 static constexpr auto default_tolerance_rate =
217 static_cast<scalar_type>(1e-2);
218
221
224
227};
228
229} // namespace num_collect::ode::rosenbrock
Class of error tolerances hairer1993.
Class to solve linear equations using generalized minimal residual (GMRES) golub2013.
Definition gmres.h:45
void solve(CoeffFunction &&coeff_function, const vector_type &rhs, vector_type &solution)
Solve.
Definition gmres.h:73
auto max_subspace_dim(index_type val) -> gmres &
Set the maximum number of dimensions of subspace.
Definition gmres.h:122
Class to solve equations in Rosenbrock methods using GMRES.
void apply_jacobian(const Target &target, Result &result)
Multiply Jacobian matrix to a vector.
scalar_type inverted_jacobian_coeff_
Coefficient multiplied to Jacobian matrices in inverted matrices.
std::optional< variable_type > time_derivative_
Partial derivative with respect to time.
auto max_subspace_dim(index_type val) -> gmres_rosenbrock_equation_solver &
Set the maximum number of dimensions of subspace used in GMRES.
void add_time_derivative_term(const scalar_type &step_size, const scalar_type &coeff, variable_type &target)
Add a term of partial derivative with respect to time.
void evaluate_and_update_jacobian(problem_type &problem, const scalar_type &time, const scalar_type &step_size, const variable_type &variable)
Update Jacobian matrix and internal parameters.
static constexpr bool use_time_derivative
Whether to use partial derivative with respect to time.
void solve(const variable_type &rhs, variable_type &result)
Solve a linear equation.
static constexpr auto default_tolerance_rate
Default rate of tolerance in this solver.
typename problem_type::variable_type variable_type
Type of variables.
auto tolerances(const error_tolerances< variable_type > &val) -> gmres_rosenbrock_equation_solver &
Set the error tolerances.
gmres_rosenbrock_equation_solver(const scalar_type &inverted_jacobian_coeff)
Constructor.
Concept of Eigen's dense vectors with real scalars.
Concept of problems of ordinary differential equations differentiable by time variable.
Definition of error_tolerances class.
Definition of evaluation_type enumeration.
Definition of gmres class.
Definition of index_type type.
Definition of multi_variate_problem concept.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of real_scalar_dense_vector concept.
Struct to specify types of evaluations.
Definition of time_differentiable_problem concept.