diff --git a/src/termination_conditions.jl b/src/termination_conditions.jl index 7917c9e83..ac5427c33 100644 --- a/src/termination_conditions.jl +++ b/src/termination_conditions.jl @@ -1,8 +1,39 @@ +""" + NonlinearSafeTerminationReturnCode + +Return Codes for the safe nonlinear termination conditions. +""" @enumx NonlinearSafeTerminationReturnCode begin + """ + NonlinearSafeTerminationReturnCode.Success + + Termination Condition was satisfied! + """ Success + """ + NonlinearSafeTerminationReturnCode.Default + + Default Return Code. Used for type stability and conveys no additional information! + """ Default + """ + NonlinearSafeTerminationReturnCode.PatienceTermination + + Terminate if there has been no improvement for the last `patience_steps`. + """ PatienceTermination + """ + NonlinearSafeTerminationReturnCode.ProtectiveTermination + + Terminate if the objective value increased by this factor wrt initial objective or the + value diverged. + """ ProtectiveTermination + """ + NonlinearSafeTerminationReturnCode.Failure + + Termination Condition was not satisfied! + """ Failure end @@ -12,34 +43,145 @@ abstract type AbstractSafeBestNonlinearTerminationMode <: AbstractSafeNonlinearTerminationMode end # TODO: Add a mode where the user can pass in custom termination criteria function -for mode in (:SteadyStateDiffEqTerminationMode, :SimpleNonlinearSolveTerminationMode, - :NormTerminationMode, :RelTerminationMode, :RelNormTerminationMode, :AbsTerminationMode, - :AbsNormTerminationMode) - @eval begin - struct $(mode) <: AbstractNonlinearTerminationMode end - end + +""" + SteadyStateDiffEqTerminationMode <: AbstractNonlinearTerminationMode + +Check if all values of the derivative is close to zero wrt both relative and absolute +tolerance. + +The default used in SteadyStateDiffEq.jl! Not recommended for large problems, since the +convergence criteria is very strict and never reliably satisfied for most problems. +""" +struct SteadyStateDiffEqTerminationMode <: AbstractNonlinearTerminationMode end + +""" + SimpleNonlinearSolveTerminationMode <: AbstractNonlinearTerminationMode + +Check if all values of the derivative is close to zero wrt both relative and absolute +tolerance. Or check that the value of the current and previous state is within the specified +tolerances. + +The default used in SimpleNonlinearSolve.jl! Not recommended for large problems, since the +convergence criteria is very strict and never reliably satisfied for most problems. +""" +struct SimpleNonlinearSolveTerminationMode <: AbstractNonlinearTerminationMode end + +@doc doc""" + NormTerminationMode <: AbstractNonlinearTerminationMode + +Terminates if +``\| \frac{\partial u}{\partial t} \| \leq reltol \times \| \frac{\partial u}{\partial t} + u \|`` +or ``\| \frac{\partial u}{\partial t} \| \leq abstol`` +""" +struct NormTerminationMode <: AbstractNonlinearTerminationMode end + +@doc doc""" + RelTerminationMode <: AbstractNonlinearTerminationMode + +Terminates if +``all \left(| \frac{\partial u}{\partial t} | \leq reltol \times | u | \right)``. +""" +struct RelTerminationMode <: AbstractNonlinearTerminationMode end + +@doc doc""" + RelNormTerminationMode <: AbstractNonlinearTerminationMode + +Terminates if +``\| \frac{\partial u}{\partial t} \| \leq reltol \times \| \frac{\partial u}{\partial t} + u \|`` +""" +struct RelNormTerminationMode <: AbstractNonlinearTerminationMode end + +@doc doc""" + AbsTerminationMode <: AbstractNonlinearTerminationMode + +Terminates if ``all \left( | \frac{\partial u}{\partial t} | \leq abstol \right)``. +""" +struct AbsTerminationMode <: AbstractNonlinearTerminationMode end + +@doc doc""" + AbsNormTerminationMode <: AbstractNonlinearTerminationMode + +Terminates if ``\| \frac{\partial u}{\partial t} \| \leq abstol``. +""" +struct AbsNormTerminationMode <: AbstractNonlinearTerminationMode end + +@doc doc""" + RelSafeTerminationMode <: AbstractSafeNonlinearTerminationMode + +Essentially [`RelNormTerminationMode`](@ref) + terminate if there has been no improvement +for the last `patience_steps` + terminate if the solution blows up (diverges). + +## Constructor + +```julia +RelSafeTerminationMode(; protective_threshold = 1e3, patience_steps = 100, + patience_objective_multiplier = 3, min_max_factor = 1.3) +``` +""" +Base.@kwdef struct RelSafeTerminationMode{T1, T2, T3} <: AbstractSafeNonlinearTerminationMode + protective_threshold::T1 = 1000 + patience_steps::Int = 100 + patience_objective_multiplier::T2 = 3 + min_max_factor::T3 = 1.3 end -for mode in (:RelSafeTerminationMode, :AbsSafeTerminationMode) - @eval begin - Base.@kwdef struct $(mode){T1, T2, T3} <: AbstractSafeNonlinearTerminationMode - protective_threshold::T1 = 1000 - patience_steps::Int = 30 - patience_objective_multiplier::T2 = 3 - min_max_factor::T3 = 1.3 - end - end +@doc doc""" + AbsSafeTerminationMode <: AbstractSafeNonlinearTerminationMode + +Essentially [`AbsNormTerminationMode`](@ref) + terminate if there has been no improvement +for the last `patience_steps` + terminate if the solution blows up (diverges). + +## Constructor + +```julia +AbsSafeTerminationMode(; protective_threshold = 1e3, patience_steps = 100, + patience_objective_multiplier = 3, min_max_factor = 1.3) +``` +""" +Base.@kwdef struct AbsSafeTerminationMode{T1, T2, T3} <: AbstractSafeNonlinearTerminationMode + protective_threshold::T1 = 1000 + patience_steps::Int = 100 + patience_objective_multiplier::T2 = 3 + min_max_factor::T3 = 1.3 end -for mode in (:RelSafeBestTerminationMode, :AbsSafeBestTerminationMode) - @eval begin - Base.@kwdef struct $(mode){T1, T2, T3} <: AbstractSafeBestNonlinearTerminationMode - protective_threshold::T1 = 1000 - patience_steps::Int = 100 - patience_objective_multiplier::T2 = 3 - min_max_factor::T3 = 1.3 - end - end +@doc doc""" + RelSafeBestTerminationMode <: AbstractSafeBestNonlinearTerminationMode + +Essentially [`RelSafeTerminationMode`](@ref), but caches the best solution found so far. + +## Constructor + +```julia +RelSafeBestTerminationMode(; protective_threshold = 1e3, patience_steps = 100, + patience_objective_multiplier = 3, min_max_factor = 1.3) +``` +""" +Base.@kwdef struct RelSafeBestTerminationMode{T1, T2, T3} <: AbstractSafeNonlinearTerminationMode + protective_threshold::T1 = 1000 + patience_steps::Int = 100 + patience_objective_multiplier::T2 = 3 + min_max_factor::T3 = 1.3 +end + +@doc doc""" + AbsSafeBestTerminationMode <: AbstractSafeBestNonlinearTerminationMode + +Essentially [`AbsSafeTerminationMode`](@ref), but caches the best solution found so far. + +## Constructor + +```julia +AbsSafeBestTerminationMode(; protective_threshold = 1e3, patience_steps = 100, + patience_objective_multiplier = 3, min_max_factor = 1.3) +``` +""" +Base.@kwdef struct AbsSafeBestTerminationMode{T1, T2, T3} <: AbstractSafeNonlinearTerminationMode + protective_threshold::T1 = 1000 + patience_steps::Int = 100 + patience_objective_multiplier::T2 = 3 + min_max_factor::T3 = 1.3 end mutable struct NonlinearTerminationModeCache{uType, T,