46 "num_collect::ode::inexact_newton_update_equation_solver");
64template <concepts::differentiable_problem Problem>
83template <concepts::single_variate_differentiable_problem Problem>
86 inexact_newton_update_equation_solver<Problem>> {
103 static_assert(!problem_type::allowed_evaluations.mass,
104 "Mass matrix is not supported.");
128 step_size_ = step_size;
129 variable_ = variable;
130 slope_coeff_ = slope_coeff;
132 problem_->evaluate_on(time_, variable_,
137 step_size_ * slope_coeff_ * problem_->jacobian());
153 solution_offset_ = solution_offset;
154 solution_ = &solution;
155 update_norm_.reset();
156 if (update_reduction_rate_) {
157 constexpr auto exponent =
static_cast<scalar_type>(0.8);
158 constexpr auto min_rate =
static_cast<scalar_type>(0.5);
160 *update_reduction_rate_ = pow(*update_reduction_rate_, exponent);
161 if (*update_reduction_rate_ < min_rate) {
162 *update_reduction_rate_ = min_rate;
179 init(solution_offset, solution);
190 this->logger(),
"Initialization must be done before iterations.");
192 temp_variable_ = variable_ + (*solution_);
194 problem_->evaluate_on(
196 residual_ = (*solution_) -
197 step_size_ * slope_coeff_ * problem_->diff_coeff() -
199 update_ = -coeff_inverse_ * residual_;
200 *solution_ += update_;
203 tolerances().calc_norm(variable_, update_);
205 update_reduction_rate_ = update_norm / (*update_norm_);
207 update_norm_ = update_norm;
218 bool converged =
false;
219 if (update_norm_ && update_reduction_rate_ &&
220 *update_reduction_rate_ <
static_cast<scalar_type>(1)) {
222 (*update_reduction_rate_ /
223 (
static_cast<scalar_type>(1) - *update_reduction_rate_)) *
229 return converged || (iterations_ > max_iterations);
240 iteration_logger.template append<index_type>(
241 "Iter.", &this_type::iterations);
242 iteration_logger.template append<scalar_type>(
243 "Update", &this_type::update_norm);
252 return solution_offset_;
264 return *update_norm_;
331 std::optional<scalar_type> update_norm_{};
334 std::optional<scalar_type> update_reduction_rate_{};
337 static constexpr auto default_tolerance_rate =
366template <concepts::multi_variate_differentiable_problem Problem>
369 inexact_newton_update_equation_solver<Problem>> {
381 using scalar_type =
typename problem_type::scalar_type;
386 static_assert(!problem_type::allowed_evaluations.mass,
387 "Mass matrix is not supported.");
407 template <
typename VariableExpression>
410 const Eigen::MatrixBase<VariableExpression>& variable,
414 step_size_ = step_size;
415 variable_ = variable;
416 slope_coeff_ = slope_coeff;
418 problem_->evaluate_on(time_, variable_,
422 lu_.compute(jacobian_type::Identity(dim, dim) -
423 step_size_ * slope_coeff_ * problem_->jacobian());
435 template <
typename OffsetExpression>
436 void init(
const Eigen::MatrixBase<OffsetExpression>& solution_offset,
438 solution_offset_ = solution_offset;
439 solution_ = &solution;
440 update_norm_.reset();
441 if (update_reduction_rate_) {
442 constexpr auto exponent =
static_cast<scalar_type>(0.8);
443 constexpr auto min_rate =
static_cast<scalar_type>(0.5);
445 *update_reduction_rate_ = pow(*update_reduction_rate_, exponent);
446 if (*update_reduction_rate_ < min_rate) {
447 *update_reduction_rate_ = min_rate;
463 template <
typename OffsetExpression>
465 const Eigen::MatrixBase<OffsetExpression>& solution_offset,
468 init(solution_offset, solution);
479 this->logger(),
"Initialization must be done before iterations.");
481 temp_variable_ = variable_ + (*solution_);
483 problem_->evaluate_on(
485 residual_ = (*solution_) -
486 step_size_ * slope_coeff_ * problem_->diff_coeff() -
488 update_ = -lu_.solve(residual_);
489 if (!update_.array().isFinite().all()) {
491 "Failed to solve an equation. step_size={}, cond={}.",
492 step_size_, lu_.rcond());
494 *solution_ += update_;
497 tolerances().calc_norm(variable_, update_);
499 update_reduction_rate_ = update_norm / (*update_norm_);
501 update_norm_ = update_norm;
512 bool converged =
false;
513 if (update_norm_ && update_reduction_rate_ &&
514 *update_reduction_rate_ <
static_cast<scalar_type>(1)) {
516 (*update_reduction_rate_ /
517 (
static_cast<scalar_type>(1) - *update_reduction_rate_)) *
523 return converged || (iterations_ > max_iterations);
534 iteration_logger.template append<index_type>(
535 "Iter.", &this_type::iterations);
536 iteration_logger.template append<scalar_type>(
537 "Update", &this_type::update_norm);
546 return solution_offset_;
558 return *update_norm_;
592 problem_type* problem_{
nullptr};
598 scalar_type step_size_{};
601 scalar_type slope_coeff_{};
604 variable_type variable_{};
607 variable_type solution_offset_{};
610 variable_type* solution_{
nullptr};
613 Eigen::PartialPivLU<jacobian_type> lu_{};
616 variable_type temp_variable_{};
619 variable_type residual_{};
622 variable_type update_{};
625 std::optional<scalar_type> update_norm_{};
628 std::optional<scalar_type> update_reduction_rate_{};
631 static constexpr auto default_tolerance_rate =
632 static_cast<scalar_type
>(1e-2);
635 scalar_type tolerance_rate_{default_tolerance_rate};
641 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 updates using inexact Newton method.
void update_jacobian(problem_type &problem, scalar_type time, scalar_type step_size, const Eigen::MatrixBase< VariableExpression > &variable, scalar_type slope_coeff)
Update Jacobian and internal parameters.
typename problem_type::scalar_type scalar_type
Type of scalars.
auto update_norm() const -> scalar_type
Get the norm of update.
inexact_newton_update_equation_solver()
Constructor.
void update_jacobian(problem_type &problem, scalar_type time, scalar_type step_size, const variable_type &variable, scalar_type slope_coeff)
Update Jacobian and internal parameters.
auto solution_offset() const -> const variable_type &
Get the offset of the solution added to the term of slopes.
void iterate()
Iterate the algorithm once.
auto iterations() const -> index_type
Get the number of iterations.
void init(const Eigen::MatrixBase< OffsetExpression > &solution_offset, variable_type &solution)
Initialize for solving an equation.
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 configure_iteration_logger(logging::iterations::iteration_logger< inexact_newton_update_equation_solver< Problem > > &iteration_logger) const
Configure an iteration logger.
auto tolerances(const error_tolerances< variable_type > &val) -> inexact_newton_update_equation_solver &
Set the error tolerances.
auto tolerances() const -> const error_tolerances< variable_type > &
Get the error tolerances.
void init(const scalar_type &time, const Eigen::MatrixBase< OffsetExpression > &solution_offset, variable_type &solution)
Initialize for solving an equation.
typename problem_type::variable_type variable_type
Type of variables.
Problem problem_type
Type of problem.
void init(const variable_type &solution_offset, variable_type &solution)
Initialize for solving an equation.
void init(const scalar_type &time, const variable_type &solution_offset, variable_type &solution)
Initialize for solving an equation.
auto is_stop_criteria_satisfied() const -> bool
Determine if stopping criteria of the algorithm are satisfied.
Class to solve equations of implicit updates 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_update_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.