45 "num_collect::ode::inexact_newton_slope_equation_solver");
61template <concepts::differentiable_problem Problem>
78template <concepts::single_variate_differentiable_problem Problem>
81 inexact_newton_slope_equation_solver<Problem>> {
98 static_assert(!problem_type::allowed_evaluations.mass,
99 "Mass matrix is not supported.");
123 step_size_ = step_size;
124 variable_ = variable;
125 solution_coeff_ = solution_coeff;
127 problem_->evaluate_on(time_, variable_,
132 step_size_ * solution_coeff_ * problem_->jacobian());
146 solution_ = &solution;
147 update_norm_.reset();
148 if (update_reduction_rate_) {
149 constexpr auto exponent =
static_cast<scalar_type>(0.8);
150 constexpr auto min_rate =
static_cast<scalar_type>(0.5);
152 *update_reduction_rate_ = pow(*update_reduction_rate_, exponent);
153 if (*update_reduction_rate_ < min_rate) {
154 *update_reduction_rate_ = min_rate;
168 this->logger(),
"Initialization must be done before iterations.");
171 variable_ + step_size_ * solution_coeff_ * (*solution_);
173 problem_->evaluate_on(
175 residual_ = (*solution_) - problem_->diff_coeff();
176 update_ = -coeff_inverse_ * residual_;
177 *solution_ += update_;
180 tolerances().calc_norm(variable_, update_);
182 update_reduction_rate_ = update_norm / (*update_norm_);
184 update_norm_ = update_norm;
195 bool converged =
false;
196 if (update_norm_ && update_reduction_rate_ &&
197 *update_reduction_rate_ <
static_cast<scalar_type>(1)) {
199 (*update_reduction_rate_ /
200 (
static_cast<scalar_type>(1) - *update_reduction_rate_)) *
206 return converged || (iterations_ > max_iterations);
217 iteration_logger.template append<index_type>(
218 "Iter.", &this_type::iterations);
219 iteration_logger.template append<scalar_type>(
220 "Update", &this_type::update_norm);
232 return *update_norm_;
296 std::optional<scalar_type> update_norm_{};
299 std::optional<scalar_type> update_reduction_rate_{};
302 static constexpr auto default_tolerance_rate =
329template <concepts::multi_variate_differentiable_problem Problem>
332 inexact_newton_slope_equation_solver<Problem>> {
344 using scalar_type =
typename problem_type::scalar_type;
349 static_assert(!problem_type::allowed_evaluations.mass,
350 "Mass matrix is not supported.");
370 template <
typename VariableExpression>
373 const Eigen::MatrixBase<VariableExpression>& variable,
377 step_size_ = step_size;
378 variable_ = variable;
379 solution_coeff_ = solution_coeff;
381 problem_->evaluate_on(time_, variable_,
385 lu_.compute(jacobian_type::Identity(dim, dim) -
386 step_size_ * solution_coeff_ * problem_->jacobian());
395 solution_ = &solution;
396 update_norm_.reset();
397 if (update_reduction_rate_) {
398 constexpr auto exponent =
static_cast<scalar_type>(0.8);
399 constexpr auto min_rate =
static_cast<scalar_type>(0.5);
401 *update_reduction_rate_ = pow(*update_reduction_rate_, exponent);
402 if (*update_reduction_rate_ < min_rate) {
403 *update_reduction_rate_ = min_rate;
417 this->logger(),
"Initialization must be done before iterations.");
420 variable_ + step_size_ * solution_coeff_ * (*solution_);
422 problem_->evaluate_on(
424 residual_ = (*solution_) - problem_->diff_coeff();
425 update_ = -lu_.solve(residual_);
426 if (!update_.array().isFinite().all()) {
428 "Failed to solve an equation. step_size={}, cond={}.",
429 step_size_, lu_.rcond());
431 *solution_ += update_;
434 tolerances().calc_norm(variable_, update_);
436 update_reduction_rate_ = update_norm / (*update_norm_);
438 update_norm_ = update_norm;
449 bool converged =
false;
450 if (update_norm_ && update_reduction_rate_ &&
451 *update_reduction_rate_ <
static_cast<scalar_type>(1)) {
453 (*update_reduction_rate_ /
454 (
static_cast<scalar_type>(1) - *update_reduction_rate_)) *
460 return converged || (iterations_ > max_iterations);
471 iteration_logger.template append<index_type>(
472 "Iter.", &this_type::iterations);
473 iteration_logger.template append<scalar_type>(
474 "Update", &this_type::update_norm);
486 return *update_norm_;
520 problem_type* problem_{
nullptr};
526 scalar_type step_size_{};
529 scalar_type solution_coeff_{};
532 variable_type variable_{};
535 variable_type* solution_{
nullptr};
538 Eigen::PartialPivLU<jacobian_type> lu_{};
541 variable_type temp_variable_{};
544 variable_type residual_{};
547 variable_type update_{};
550 std::optional<scalar_type> update_norm_{};
553 std::optional<scalar_type> update_reduction_rate_{};
556 static constexpr auto default_tolerance_rate =
557 static_cast<scalar_type
>(1e-2);
560 scalar_type tolerance_rate_{default_tolerance_rate};
566 error_tolerances<variable_type> tolerances_{};
Definition of iterative_solver_base class.
Class of exception on failure in algorithm.
Base class of iterative solvers.
Class to write logs of iterations.
Class of tags of logs without memory management.
Class of error tolerances hairer1993.
Class to solve equations of implicit slopes using inexact Newton method.
Problem problem_type
Type of problem.
typename problem_type::variable_type variable_type
Type of variables.
auto tolerances(const error_tolerances< variable_type > &val) -> inexact_newton_slope_equation_solver &
Set the error tolerances.
auto is_stop_criteria_satisfied() const -> bool
Determine if stopping criteria of the algorithm are satisfied.
void configure_iteration_logger(logging::iterations::iteration_logger< this_type > &iteration_logger) const
Configure an iteration logger.
typename problem_type::jacobian_type jacobian_type
Type of Jacobian.
void update_jacobian(problem_type &problem, scalar_type time, scalar_type step_size, const Eigen::MatrixBase< VariableExpression > &variable, scalar_type solution_coeff)
Update Jacobian and internal parameters.
void iterate()
Iterate the algorithm once.
void update_jacobian(problem_type &problem, scalar_type time, scalar_type step_size, const variable_type &variable, scalar_type solution_coeff)
Update Jacobian and internal parameters.
typename problem_type::scalar_type scalar_type
Type of scalars.
void init(variable_type &solution)
Initialize for solving an equation.
auto update_norm() const -> scalar_type
Get the norm of update.
auto iterations() const -> index_type
Get the number of iterations.
auto tolerances() const -> const error_tolerances< variable_type > &
Get the error tolerances.
inexact_newton_slope_equation_solver()
Constructor.
Class to solve equations of implicit slopes using inexact Newton method.
Definition of differentiable_problem concept.
Definition of error_tolerances class.
Definition of evaluation_type enumeration.
Definition of exceptions.
Definition of index_type type.
Definition of iteration_logger class.
Definition of log_tag_view class.
Definition of macros for logging.
#define NUM_COLLECT_LOG_AND_THROW(EXCEPTION_TYPE,...)
Write an error log and throw an exception for an error.
Definition of multi_variate_differentiable_problem concept.
std::ptrdiff_t index_type
Type of indices in this library.
auto isfinite(const T &val) -> bool
Check whether a number is finite.
Namespace of solvers of ordinary differential equations (ODE).
constexpr auto inexact_newton_slope_equation_solver_tag
Log tag.
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 single_variate_differentiable_problem concept.
Struct to specify types of evaluations.