Skip to content

Commit 8fccdcc

Browse files
committed
Docs
1 parent 26b99eb commit 8fccdcc

File tree

1 file changed

+188
-42
lines changed

1 file changed

+188
-42
lines changed

src/termination_conditions.jl

Lines changed: 188 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
1+
"""
2+
NonlinearSafeTerminationReturnCode
3+
4+
Return Codes for the safe nonlinear termination conditions.
5+
"""
16
@enumx NonlinearSafeTerminationReturnCode begin
7+
"""
8+
NonlinearSafeTerminationReturnCode.Success
9+
10+
Termination Condition was satisfied!
11+
"""
212
Success
13+
"""
14+
NonlinearSafeTerminationReturnCode.Default
15+
16+
Default Return Code. Used for type stability and conveys no additional information!
17+
"""
318
Default
19+
"""
20+
NonlinearSafeTerminationReturnCode.PatienceTermination
21+
22+
Terminate if there has been no improvement for the last `patience_steps`.
23+
"""
424
PatienceTermination
25+
"""
26+
NonlinearSafeTerminationReturnCode.ProtectiveTermination
27+
28+
Terminate if the objective value increased by this factor wrt initial objective or the
29+
value diverged.
30+
"""
531
ProtectiveTermination
32+
"""
33+
NonlinearSafeTerminationReturnCode.Failure
34+
35+
Termination Condition was not satisfied!
36+
"""
637
Failure
738
end
839

@@ -12,34 +43,149 @@ abstract type AbstractSafeBestNonlinearTerminationMode <:
1243
AbstractSafeNonlinearTerminationMode end
1344

1445
# TODO: Add a mode where the user can pass in custom termination criteria function
15-
for mode in (:SteadyStateDiffEqTerminationMode, :SimpleNonlinearSolveTerminationMode,
16-
:NormTerminationMode, :RelTerminationMode, :RelNormTerminationMode, :AbsTerminationMode,
17-
:AbsNormTerminationMode)
18-
@eval begin
19-
struct $(mode) <: AbstractNonlinearTerminationMode end
20-
end
46+
47+
"""
48+
SteadyStateDiffEqTerminationMode <: AbstractNonlinearTerminationMode
49+
50+
Check if all values of the derivative is close to zero wrt both relative and absolute
51+
tolerance.
52+
53+
The default used in SteadyStateDiffEq.jl! Not recommended for large problems, since the
54+
convergence criteria is very strict and never reliably satisfied for most problems.
55+
"""
56+
struct SteadyStateDiffEqTerminationMode <: AbstractNonlinearTerminationMode end
57+
58+
"""
59+
SimpleNonlinearSolveTerminationMode <: AbstractNonlinearTerminationMode
60+
61+
Check if all values of the derivative is close to zero wrt both relative and absolute
62+
tolerance. Or check that the value of the current and previous state is within the specified
63+
tolerances.
64+
65+
The default used in SimpleNonlinearSolve.jl! Not recommended for large problems, since the
66+
convergence criteria is very strict and never reliably satisfied for most problems.
67+
"""
68+
struct SimpleNonlinearSolveTerminationMode <: AbstractNonlinearTerminationMode end
69+
70+
@doc doc"""
71+
NormTerminationMode <: AbstractNonlinearTerminationMode
72+
73+
Terminates if
74+
``\| \frac{\partial u}{\partial t} \| \leq reltol \times \| \frac{\partial u}{\partial t} + u \|``
75+
or ``\| \frac{\partial u}{\partial t} \| \leq abstol``
76+
"""
77+
struct NormTerminationMode <: AbstractNonlinearTerminationMode end
78+
79+
@doc doc"""
80+
RelTerminationMode <: AbstractNonlinearTerminationMode
81+
82+
Terminates if
83+
``all \left(| \frac{\partial u}{\partial t} | \leq reltol \times | u | \right)``.
84+
"""
85+
struct RelTerminationMode <: AbstractNonlinearTerminationMode end
86+
87+
@doc doc"""
88+
RelNormTerminationMode <: AbstractNonlinearTerminationMode
89+
90+
Terminates if
91+
``\| \frac{\partial u}{\partial t} \| \leq reltol \times \| \frac{\partial u}{\partial t} + u \|``
92+
"""
93+
struct RelNormTerminationMode <: AbstractNonlinearTerminationMode end
94+
95+
@doc doc"""
96+
AbsTerminationMode <: AbstractNonlinearTerminationMode
97+
98+
Terminates if ``all \left( | \frac{\partial u}{\partial t} | \leq abstol \right)``.
99+
"""
100+
struct AbsTerminationMode <: AbstractNonlinearTerminationMode end
101+
102+
@doc doc"""
103+
AbsNormTerminationMode <: AbstractNonlinearTerminationMode
104+
105+
Terminates if ``\| \frac{\partial u}{\partial t} \| \leq abstol``.
106+
"""
107+
struct AbsNormTerminationMode <: AbstractNonlinearTerminationMode end
108+
109+
@doc doc"""
110+
RelSafeTerminationMode <: AbstractSafeNonlinearTerminationMode
111+
112+
Essentially [`RelNormTerminationMode`](@ref) + terminate if there has been no improvement
113+
for the last `patience_steps` + terminate if the solution blows up (diverges).
114+
115+
## Constructor
116+
117+
```julia
118+
RelSafeTerminationMode(; protective_threshold = 1e3, patience_steps = 100,
119+
patience_objective_multiplier = 3, min_max_factor = 1.3)
120+
```
121+
"""
122+
Base.@kwdef struct RelSafeTerminationMode{T1, T2, T3} <:
123+
AbstractSafeNonlinearTerminationMode
124+
protective_threshold::T1 = 1000
125+
patience_steps::Int = 100
126+
patience_objective_multiplier::T2 = 3
127+
min_max_factor::T3 = 1.3
21128
end
22129

23-
for mode in (:RelSafeTerminationMode, :AbsSafeTerminationMode)
24-
@eval begin
25-
Base.@kwdef struct $(mode){T1, T2, T3} <: AbstractSafeNonlinearTerminationMode
26-
protective_threshold::T1 = 1000
27-
patience_steps::Int = 30
28-
patience_objective_multiplier::T2 = 3
29-
min_max_factor::T3 = 1.3
30-
end
31-
end
130+
@doc doc"""
131+
AbsSafeTerminationMode <: AbstractSafeNonlinearTerminationMode
132+
133+
Essentially [`AbsNormTerminationMode`](@ref) + terminate if there has been no improvement
134+
for the last `patience_steps` + terminate if the solution blows up (diverges).
135+
136+
## Constructor
137+
138+
```julia
139+
AbsSafeTerminationMode(; protective_threshold = 1e3, patience_steps = 100,
140+
patience_objective_multiplier = 3, min_max_factor = 1.3)
141+
```
142+
"""
143+
Base.@kwdef struct AbsSafeTerminationMode{T1, T2, T3} <:
144+
AbstractSafeNonlinearTerminationMode
145+
protective_threshold::T1 = 1000
146+
patience_steps::Int = 100
147+
patience_objective_multiplier::T2 = 3
148+
min_max_factor::T3 = 1.3
32149
end
33150

34-
for mode in (:RelSafeBestTerminationMode, :AbsSafeBestTerminationMode)
35-
@eval begin
36-
Base.@kwdef struct $(mode){T1, T2, T3} <: AbstractSafeBestNonlinearTerminationMode
37-
protective_threshold::T1 = 1000
38-
patience_steps::Int = 100
39-
patience_objective_multiplier::T2 = 3
40-
min_max_factor::T3 = 1.3
41-
end
42-
end
151+
@doc doc"""
152+
RelSafeBestTerminationMode <: AbstractSafeBestNonlinearTerminationMode
153+
154+
Essentially [`RelSafeTerminationMode`](@ref), but caches the best solution found so far.
155+
156+
## Constructor
157+
158+
```julia
159+
RelSafeBestTerminationMode(; protective_threshold = 1e3, patience_steps = 100,
160+
patience_objective_multiplier = 3, min_max_factor = 1.3)
161+
```
162+
"""
163+
Base.@kwdef struct RelSafeBestTerminationMode{T1, T2, T3} <:
164+
AbstractSafeNonlinearTerminationMode
165+
protective_threshold::T1 = 1000
166+
patience_steps::Int = 100
167+
patience_objective_multiplier::T2 = 3
168+
min_max_factor::T3 = 1.3
169+
end
170+
171+
@doc doc"""
172+
AbsSafeBestTerminationMode <: AbstractSafeBestNonlinearTerminationMode
173+
174+
Essentially [`AbsSafeTerminationMode`](@ref), but caches the best solution found so far.
175+
176+
## Constructor
177+
178+
```julia
179+
AbsSafeBestTerminationMode(; protective_threshold = 1e3, patience_steps = 100,
180+
patience_objective_multiplier = 3, min_max_factor = 1.3)
181+
```
182+
"""
183+
Base.@kwdef struct AbsSafeBestTerminationMode{T1, T2, T3} <:
184+
AbstractSafeNonlinearTerminationMode
185+
protective_threshold::T1 = 1000
186+
patience_steps::Int = 100
187+
patience_objective_multiplier::T2 = 3
188+
min_max_factor::T3 = 1.3
43189
end
44190

45191
mutable struct NonlinearTerminationModeCache{uType, T,
@@ -78,8 +224,8 @@ function _get_tolerance(::Nothing, ::Type{T}) where {T}
78224
end
79225

80226
function SciMLBase.init(du::Union{AbstractArray{T}, T}, u::Union{AbstractArray{T}, T},
81-
mode::AbstractNonlinearTerminationMode; abstol = nothing, reltol = nothing,
82-
kwargs...) where {T <: Number}
227+
mode::AbstractNonlinearTerminationMode; abstol = nothing, reltol = nothing,
228+
kwargs...) where {T <: Number}
83229
abstol = _get_tolerance(abstol, T)
84230
reltol = _get_tolerance(reltol, T)
85231
TT = typeof(abstol)
@@ -113,12 +259,12 @@ end
113259
(cache::NonlinearTerminationModeCache)(du, u, uprev) = cache(cache.mode, du, u, uprev)
114260

115261
function (cache::NonlinearTerminationModeCache)(mode::AbstractNonlinearTerminationMode, du,
116-
u, uprev)
262+
u, uprev)
117263
return check_convergence(mode, du, u, uprev, cache.abstol, cache.reltol)
118264
end
119265

120266
function (cache::NonlinearTerminationModeCache)(mode::AbstractSafeNonlinearTerminationMode,
121-
du, u, uprev)
267+
du, u, uprev)
122268
if mode isa AbsSafeTerminationMode || mode isa AbsSafeBestTerminationMode
123269
objective = NONLINEARSOLVE_DEFAULT_NORM(du)
124270
criteria = cache.abstol
@@ -130,7 +276,7 @@ function (cache::NonlinearTerminationModeCache)(mode::AbstractSafeNonlinearTermi
130276

131277
# Protective Break
132278
if isinf(objective) || isnan(objective) ||
133-
(objective cache.initial_objective * cache.mode.protective_threshold * length(du))
279+
(objective cache.initial_objective * cache.mode.protective_threshold * length(du))
134280
cache.retcode = NonlinearSafeTerminationReturnCode.ProtectiveTermination
135281
return true
136282
end
@@ -172,11 +318,11 @@ function (cache::NonlinearTerminationModeCache)(mode::AbstractSafeNonlinearTermi
172318
end
173319

174320
function check_convergence(::SteadyStateDiffEqTerminationMode, duₙ, uₙ, uₙ₋₁, abstol,
175-
reltol)
321+
reltol)
176322
return all((abs.(duₙ) .≤ abstol) .| (abs.(duₙ) .≤ reltol .* abs.(uₙ)))
177323
end
178324
function check_convergence(::SimpleNonlinearSolveTerminationMode, duₙ, uₙ, uₙ₋₁, abstol,
179-
reltol)
325+
reltol)
180326
return all((abs.(duₙ) .≤ abstol) .| (abs.(duₙ) .≤ reltol .* abs.(uₙ))) ||
181327
isapprox(uₙ, uₙ₋₁; atol = abstol, rtol = reltol)
182328
end
@@ -188,15 +334,15 @@ function check_convergence(::RelTerminationMode, duₙ, uₙ, uₙ₋₁, abstol
188334
return all(abs.(duₙ) .≤ reltol .* abs.(uₙ))
189335
end
190336
function check_convergence(::Union{RelNormTerminationMode, RelSafeTerminationMode,
191-
RelSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
337+
RelSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
192338
return NONLINEARSOLVE_DEFAULT_NORM(duₙ)
193339
reltol * NONLINEARSOLVE_DEFAULT_NORM(duₙ .+ uₙ)
194340
end
195341
function check_convergence(::AbsTerminationMode, duₙ, uₙ, uₙ₋₁, abstol, reltol)
196342
return all(abs.(duₙ) .≤ abstol)
197343
end
198344
function check_convergence(::Union{AbsNormTerminationMode, AbsSafeTerminationMode,
199-
AbsSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
345+
AbsSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
200346
return NONLINEARSOLVE_DEFAULT_NORM(duₙ) abstol
201347
end
202348

@@ -242,8 +388,8 @@ mutable struct NLSolveSafeTerminationResult{T, uType}
242388
end
243389

244390
function NLSolveSafeTerminationResult(u = nothing; best_objective_value = Inf64,
245-
best_objective_value_iteration = 0,
246-
return_code = NLSolveSafeTerminationReturnCode.Failure)
391+
best_objective_value_iteration = 0,
392+
return_code = NLSolveSafeTerminationReturnCode.Failure)
247393
u = u !== nothing ? copy(u) : u
248394
Base.depwarn("NLSolveSafeTerminationResult has been deprecated in favor of the new dispatch based termination conditions. Please use the new termination conditions API!",
249395
:NLSolveSafeTerminationResult)
@@ -330,9 +476,9 @@ get_termination_mode(::NLSolveTerminationCondition{mode}) where {mode} = mode
330476

331477
# Don't specify `mode` since the defaults would depend on the package
332478
function NLSolveTerminationCondition(mode; abstol::T = 1e-8, reltol::T = 1e-6,
333-
protective_threshold = 1e3, patience_steps::Int = 30,
334-
patience_objective_multiplier = 3,
335-
min_max_factor = 1.3) where {T}
479+
protective_threshold = 1e3, patience_steps::Int = 30,
480+
patience_objective_multiplier = 3,
481+
min_max_factor = 1.3) where {T}
336482
Base.depwarn("NLSolveTerminationCondition has been deprecated in favor of the new dispatch based termination conditions. Please use the new termination conditions API!",
337483
:NLSolveTerminationCondition)
338484
@assert mode instances(NLSolveTerminationMode.T)
@@ -346,9 +492,9 @@ function NLSolveTerminationCondition(mode; abstol::T = 1e-8, reltol::T = 1e-6,
346492
end
347493

348494
function (cond::NLSolveTerminationCondition)(storage::Union{
349-
NLSolveSafeTerminationResult,
350-
Nothing,
351-
})
495+
NLSolveSafeTerminationResult,
496+
Nothing,
497+
})
352498
mode = get_termination_mode(cond)
353499
# We need both the dispatches to support solvers that don't use the integrator
354500
# interface like SimpleNonlinearSolve
@@ -438,7 +584,7 @@ end
438584

439585
# Convergence Criteria
440586
@inline function _has_converged(du, u, uprev, cond::NLSolveTerminationCondition{mode},
441-
abstol = cond.abstol, reltol = cond.reltol) where {mode}
587+
abstol = cond.abstol, reltol = cond.reltol) where {mode}
442588
return _has_converged(du, u, uprev, mode, abstol, reltol)
443589
end
444590

0 commit comments

Comments
 (0)