numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
mixed_broyden_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 <limits>
23
24#include <Eigen/Core> // IWYU pragma: keep
25#include <Eigen/LU>
26
34
36
40 "num_collect::ode::rosenbrock::mixed_broyden_rosenbrock_equation_"
41 "solver");
42
49template <concepts::multi_variate_differentiable_problem Problem>
51public:
53 using problem_type = Problem;
54
56 using variable_type = typename problem_type::variable_type;
57
59 using scalar_type = typename problem_type::scalar_type;
60
62 using jacobian_type = typename problem_type::jacobian_type;
63
65 using lu_solver_type = Eigen::PartialPivLU<jacobian_type>;
66
67 static_assert(!problem_type::allowed_evaluations.mass,
68 "Mass matrix is not supported.");
69
77 const scalar_type& inverted_jacobian_coeff)
79 inverted_jacobian_coeff_(inverted_jacobian_coeff) {}
80
90 const scalar_type& time, const scalar_type& step_size,
91 const variable_type& variable) {
92 if (!evaluated_once_) {
93 evaluate_exactly(problem, time, step_size, variable);
94 return;
95 }
96 if (time <= time_) {
97 evaluate_exactly(problem, time, step_size, variable);
98 return;
99 }
100
101 s_ = variable - variable_;
102 if (s_.norm() <
103 variable_.norm() * std::numeric_limits<scalar_type>::epsilon()) {
104 evaluate_exactly(problem, time, step_size, variable);
105 return;
106 }
107
108 problem.evaluate_on(
109 time, variable, evaluation_type{.diff_coeff = true});
110 q_ = problem.diff_coeff() - diff_coeff_;
111 v_ = s_ - step_size * inverted_jacobian_coeff_ * q_;
112 if (v_.norm() <
113 variable_.norm() * std::numeric_limits<scalar_type>::epsilon()) {
114 evaluate_exactly(problem, time, step_size, variable);
115 return;
116 }
117
118 // Update of Jacobian.
119 update_ = (step_size / step_size_ * q_ - jacobian_ * s_) *
120 s_.transpose() / s_.squaredNorm();
122 jacobian_ *= step_size_ / step_size;
123
124 // Update of inverse.
125 update_ = (s_ - inverse_ * v_) * v_.transpose() / v_.squaredNorm();
126 inverse_ += update_;
127
128 time_ = time;
129 step_size_ = step_size;
130 variable_ = variable;
131 diff_coeff_ = problem.diff_coeff();
132
133 NUM_COLLECT_LOG_TRACE(this->logger(), "Using approximate Jacobian.");
134 }
135
142 void apply_jacobian(const variable_type& target, variable_type& result) {
143 result = jacobian_ * target;
144 }
145
154 const scalar_type& coeff, variable_type& target) {
155 // Ignore this term always in this class.
156 (void)step_size;
157 (void)coeff;
158 (void)target;
159 }
160
167 void solve(const variable_type& rhs, variable_type& result) {
168 result = inverse_ * rhs;
169 }
170
171private:
181 void evaluate_exactly(problem_type& problem, const scalar_type& time,
182 const scalar_type& step_size, const variable_type& variable) {
183 problem.evaluate_on(time, variable,
184 evaluation_type{.diff_coeff = true, .jacobian = true});
185 jacobian_ = problem.jacobian();
186
187 const index_type variable_size = variable.size();
188 lu_.compute(jacobian_type::Identity(variable_size, variable_size) -
189 step_size * inverted_jacobian_coeff_ * jacobian_);
190
191 inverse_ = lu_.inverse();
192 if (!inverse_.array().isFinite().all()) {
194 "Failed to solve an equation. step_size={}, cond={}.",
195 step_size_, lu_.rcond());
196 }
197
198 time_ = time;
199 step_size_ = step_size;
200 variable_ = variable;
201 diff_coeff_ = problem.diff_coeff();
202 evaluated_once_ = true;
203
204 NUM_COLLECT_LOG_TRACE(this->logger(), "Using exact Jacobian.");
205 }
206
208 bool evaluated_once_{false};
209
212
215
218
221
224
227
230
241
244};
245
246} // namespace num_collect::ode::rosenbrock
Class of exception on failure in algorithm.
Definition exception.h:93
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.
Class to solve equations in Rosenbrock methods using Broyden's update in novati2008.
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.
void apply_jacobian(const variable_type &target, variable_type &result)
Multiply Jacobian matrix to a vector.
void evaluate_exactly(problem_type &problem, const scalar_type &time, const scalar_type &step_size, const variable_type &variable)
Update Jacobian matrix and internal parameters using exact values from the problem.
void solve(const variable_type &rhs, variable_type &result)
Solve a linear equation.
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.
mixed_broyden_rosenbrock_equation_solver(const scalar_type &inverted_jacobian_coeff)
Constructor.
scalar_type inverted_jacobian_coeff_
Coefficient multiplied to Jacobian matrices in inverted matrices.
Definition of evaluation_type enumeration.
Definition of exceptions.
Definition of index_type type.
Definition of log_tag_view class.
Definition of macros for logging.
#define NUM_COLLECT_LOG_TRACE(LOGGER,...)
Write a trace log.
#define NUM_COLLECT_LOG_AND_THROW(EXCEPTION_TYPE,...)
Write an error log and throw an exception for an error.
Definition of logging_mixin class.
Definition of multi_variate_differentiable_problem concept.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
Struct to specify types of evaluations.