Ordinary Differential Equation (ODE) Solver

Ordinary Differential Equation (ODE) Solver#

Here solves the following explicit initial-value problem:

\[\begin{split}\begin{cases} \dot{\bm{y}} = \bm{f}(t, \bm{y}) \\ \bm{y}(0) = \bm{y}_0 \end{cases}\end{split}\]

Initial-value problem with mass matrix will be supported too:

\[\begin{split}\begin{cases} M(\bm{y}) \dot{\bm{y}} = \bm{f}(t, \bm{y}) \\ \bm{y}(0) = \bm{y}_0 \end{cases}\end{split}\]

@startuml formula_and_problems

title Abstract Model of Formulas and Problems for ODE Solvers

package ode {
    struct evaluation_type {
        + diff_coeff: bool
        + jacobian: bool
        + time_derivative: bool
        + mass: bool
    }
}

package problems {
    class problem {
        + using variable_type = xxx
        + using scalar_type = xxx
        {static} + allowed_evaluations: evaluation_type
        + evaluate_on(time: scalar_type, variable: variable_type,\n\tevaluations: evaluation_type)
        + diff_coeff() : variable_type
    }
    problem ..> evaluation_type

    class differentiable_problem {
        + using jacobian_type = xxx
        + jacobian() : jacobian_type
    }
    problem <|-- differentiable_problem

    class time_differentiable_problem {
        + time_derivative() : variable_type
    }
    differentiable_problem <|-- time_differentiable_problem

    class mass_problem {
        + using mass_type = xxx
        + mass() : mass_type
    }
    problem <|-- mass_problem
}

package ode {
    !startsub formula
    class formula<Problem> {
        + using problem_type = Problem
        {static} + stages : index_type
        {static} + order : index_type
        + init(tolerances: error_tolerances)
        + step(time: scalar_type, step_size: scalar_type,\n\tcurrent: const variable_type&, estimate: variable_type&)
        + problem() : problem_type&
    }
    !endsub
    formula o-- problem

    !startsub solver
    class solver<Formula> {
        + init(time: scalar_type, variable: variable_type)
        + step()
        + solve_till(end_time: scalar_type)
        + time() : scalar_type
        + variable() : const variable_type&
        + step_size() : scalar_type
        + steps() : index_type
        + step_size(val : scalar_type)
    }
    solver o-- formula
    !endsub
}

@enduml

@startuml embedded_formulas

title Abstract Model of Embedded Formulas for ODE Solvers

package ode {
    !includesub ./formula_and_problems.puml!formula
    !includesub ./formula_and_problems.puml!solver

    !startsub embedded_formula
    class embedded_formula<Problem> {
        {static} + lesser_order : index_type
        + step_embedded(time: scalar_type, step_size: scalar_type,\n\tcurrent: const variable_type&, estimate: variable_type&, error: variable_type&)
    }
    !endsub
    formula <|-- embedded_formula

    note as lesser_order_note
        lesser_order can be omitted if its information can't be found.
    end note
    lesser_order_note .up. embedded_formula

    class step_size_limits<Scalar> {
        + upper_limit() : scalar_type
        + lower_limit() : scalar_type
        + upper_limit(val: scalar_type)
        + lower_limit(val: scalar_type)
        + apply(val: scalar_type) : scalar_type
    }

    !startsub error_tolerances
    class error_tolerances<Variable> {
        + check(var: variable_type, err: variable_type) : bool
        + calc_norm(var: variable_type, err: variable_type) : scalar_type
        + tol_rel_error(val: variable_type)
        + tol_abs_error(val: variable_type)
    }
    !endsub

    class step_size_controller<Formula> {
        + init()
        + check_and_calc_next(step_size: scalar_type&,\n\tvar: variable_type, err: variable_type) : bool
        + limits() : step_size_limits
        + tolerances() : error_tolerances
    }
    step_size_controller o-- step_size_limits
    step_size_controller o-- error_tolerances

    class initial_step_size_calculator<Formula> {
        + calculate(time: scalar_type, variable: variable_type,\n\tlimits: step_size_limits) : scalar_type
    }

    class embedded_solver<Formula, StepSizeController> {
        + unset_step_size()
    }
    solver <|-- embedded_solver
    embedded_solver o-- embedded_formula
    embedded_solver o-- step_size_controller
    embedded_solver ..> initial_step_size_calculator
}

@enduml

@startuml implicit_formulas

title Abstract Model of Implicit Runge-Kutta Method

package ode {
    !includesub ../formula_and_problems.puml!formula
    !includesub ../embedded_formulas.puml!embedded_formula
    !includesub ../embedded_formulas.puml!error_tolerances
    formula <|- embedded_formula

    package runge_kutta {

        class slope_equation_solver<Problem> {
            + solve(problem: problem_type&,\n\ttime: scalar_type, step_size: scalar_type,\n\tvariable: const variable_type&, k_coeff: scalar_type)
            + k() : const variable_type&
            + tol_residual_norm(val: scalar_type)
        }
        slope_equation_solver o-- error_tolerances

        class implicit_formula_solver_coeffs {
            {static} + stages: index_type
            {static} + a: array<array<scalar_type, stages>, stages>
            {static} + b: array<scalar_type, stages>
        }

        class step_equation_solver<Problem, Coeffs> {
            + solve(problem: problem_type&,\n\ttime: scalar_type, step_size: scalar_type,\n\tvariable: const variable_type&)
            + k(index: index_type) : const variable_type&
            + tol_residual_norm(val: scalar_type)
        }
        step_equation_solver ..> implicit_formula_solver_coeffs

        ' These may be implemented in the future.
        remove implicit_formula_solver_coeffs
        remove step_equation_solver

        class implicit_formula<Problem> {
            + tol_rel_residual_norm(val: scalar_type)
            + tol_abs_residual_norm(val: scalar_type)
        }
        formula <|-- implicit_formula
        implicit_formula o-- slope_equation_solver
        implicit_formula o-- step_equation_solver

        class implicit_embedded_formula<Problem> {
        }
        implicit_formula <|- implicit_embedded_formula
        embedded_formula <|-- implicit_embedded_formula

        note as implicit_formula_solver_selection_note
            Actually one of these are used in implicit_formula
            depending on formulas.
        end note
        implicit_formula_solver_selection_note .. slope_equation_solver
        implicit_formula_solver_selection_note .. step_equation_solver
        implicit_formula_solver_selection_note .up. implicit_formula

    }
}

@enduml

@startuml rosenbrock_formula

title Abstract Model of Formulas of Rosenbrock Method

package ode {
    !includesub ./formula_and_problems.puml!formula
    !includesub ./embedded_formulas.puml!embedded_formula
    formula <|- embedded_formula

    package rosenbrock {

        class rosenbrock_equation_solver<Problem> {
            + rosenbrock_equation_solver(inverted_jacobian_coeff: scalar_type)
            + evaluate_and_update_jacobian(problem: problem_type&,\n\ttime: scalar_type, step_size: scalar_type,\n\tvariable: variable_type)
            + apply_jacobian(target: variable_type, result: variable_type&)
            + add_time_derivative_term(step_size: scalar_type, coeff: scalar_type, target: variable_type&)
            + solve(rhs: variable_type, result: variable_type&)
        }

        class rosenbrock_formula<Problem, EquationSolver>
        formula <|-- rosenbrock_formula
        rosenbrock_formula o-- rosenbrock_equation_solver

        class embedded_rosenbrock_formula<Problem, EquationSolver>
        rosenbrock_formula <|- embedded_rosenbrock_formula
        embedded_formula <|-- embedded_rosenbrock_formula
    }
}

@enduml