1
+ """
2
+ NonlinearSafeTerminationReturnCode
3
+
4
+ Return Codes for the safe nonlinear termination conditions.
5
+ """
1
6
@enumx NonlinearSafeTerminationReturnCode begin
7
+ """
8
+ NonlinearSafeTerminationReturnCode.Success
9
+
10
+ Termination Condition was satisfied!
11
+ """
2
12
Success
13
+ """
14
+ NonlinearSafeTerminationReturnCode.Default
15
+
16
+ Default Return Code. Used for type stability and conveys no additional information!
17
+ """
3
18
Default
19
+ """
20
+ NonlinearSafeTerminationReturnCode.PatienceTermination
21
+
22
+ Terminate if there has been no improvement for the last `patience_steps`.
23
+ """
4
24
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
+ """
5
31
ProtectiveTermination
32
+ """
33
+ NonlinearSafeTerminationReturnCode.Failure
34
+
35
+ Termination Condition was not satisfied!
36
+ """
6
37
Failure
7
38
end
8
39
@@ -12,34 +43,149 @@ abstract type AbstractSafeBestNonlinearTerminationMode <:
12
43
AbstractSafeNonlinearTerminationMode end
13
44
14
45
# 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
+ ``\| \f rac{\p artial u}{\p artial t} \| \l eq reltol \t imes \| \f rac{\p artial u}{\p artial t} + u \| ``
75
+ or ``\| \f rac{\p artial u}{\p artial t} \| \l eq abstol``
76
+ """
77
+ struct NormTerminationMode <: AbstractNonlinearTerminationMode end
78
+
79
+ @doc doc"""
80
+ RelTerminationMode <: AbstractNonlinearTerminationMode
81
+
82
+ Terminates if
83
+ ``all \l eft(| \f rac{\p artial u}{\p artial t} | \l eq reltol \t imes | u | \r ight)``.
84
+ """
85
+ struct RelTerminationMode <: AbstractNonlinearTerminationMode end
86
+
87
+ @doc doc"""
88
+ RelNormTerminationMode <: AbstractNonlinearTerminationMode
89
+
90
+ Terminates if
91
+ ``\| \f rac{\p artial u}{\p artial t} \| \l eq reltol \t imes \| \f rac{\p artial u}{\p artial t} + u \| ``
92
+ """
93
+ struct RelNormTerminationMode <: AbstractNonlinearTerminationMode end
94
+
95
+ @doc doc"""
96
+ AbsTerminationMode <: AbstractNonlinearTerminationMode
97
+
98
+ Terminates if ``all \l eft( | \f rac{\p artial u}{\p artial t} | \l eq abstol \r ight)``.
99
+ """
100
+ struct AbsTerminationMode <: AbstractNonlinearTerminationMode end
101
+
102
+ @doc doc"""
103
+ AbsNormTerminationMode <: AbstractNonlinearTerminationMode
104
+
105
+ Terminates if ``\| \f rac{\p artial u}{\p artial t} \| \l eq 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
21
128
end
22
129
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
32
149
end
33
150
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
43
189
end
44
190
45
191
mutable struct NonlinearTerminationModeCache{uType, T,
@@ -78,8 +224,8 @@ function _get_tolerance(::Nothing, ::Type{T}) where {T}
78
224
end
79
225
80
226
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 }
83
229
abstol = _get_tolerance (abstol, T)
84
230
reltol = _get_tolerance (reltol, T)
85
231
TT = typeof (abstol)
@@ -113,12 +259,12 @@ end
113
259
(cache:: NonlinearTerminationModeCache )(du, u, uprev) = cache (cache. mode, du, u, uprev)
114
260
115
261
function (cache:: NonlinearTerminationModeCache )(mode:: AbstractNonlinearTerminationMode , du,
116
- u, uprev)
262
+ u, uprev)
117
263
return check_convergence (mode, du, u, uprev, cache. abstol, cache. reltol)
118
264
end
119
265
120
266
function (cache:: NonlinearTerminationModeCache )(mode:: AbstractSafeNonlinearTerminationMode ,
121
- du, u, uprev)
267
+ du, u, uprev)
122
268
if mode isa AbsSafeTerminationMode || mode isa AbsSafeBestTerminationMode
123
269
objective = NONLINEARSOLVE_DEFAULT_NORM (du)
124
270
criteria = cache. abstol
@@ -130,7 +276,7 @@ function (cache::NonlinearTerminationModeCache)(mode::AbstractSafeNonlinearTermi
130
276
131
277
# Protective Break
132
278
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))
134
280
cache. retcode = NonlinearSafeTerminationReturnCode. ProtectiveTermination
135
281
return true
136
282
end
@@ -172,11 +318,11 @@ function (cache::NonlinearTerminationModeCache)(mode::AbstractSafeNonlinearTermi
172
318
end
173
319
174
320
function check_convergence (:: SteadyStateDiffEqTerminationMode , duₙ, uₙ, uₙ₋₁, abstol,
175
- reltol)
321
+ reltol)
176
322
return all ((abs .(duₙ) .≤ abstol) .| (abs .(duₙ) .≤ reltol .* abs .(uₙ)))
177
323
end
178
324
function check_convergence (:: SimpleNonlinearSolveTerminationMode , duₙ, uₙ, uₙ₋₁, abstol,
179
- reltol)
325
+ reltol)
180
326
return all ((abs .(duₙ) .≤ abstol) .| (abs .(duₙ) .≤ reltol .* abs .(uₙ))) ||
181
327
isapprox (uₙ, uₙ₋₁; atol = abstol, rtol = reltol)
182
328
end
@@ -188,15 +334,15 @@ function check_convergence(::RelTerminationMode, duₙ, uₙ, uₙ₋₁, abstol
188
334
return all (abs .(duₙ) .≤ reltol .* abs .(uₙ))
189
335
end
190
336
function check_convergence (:: Union {RelNormTerminationMode, RelSafeTerminationMode,
191
- RelSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
337
+ RelSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
192
338
return NONLINEARSOLVE_DEFAULT_NORM (duₙ) ≤
193
339
reltol * NONLINEARSOLVE_DEFAULT_NORM (duₙ .+ uₙ)
194
340
end
195
341
function check_convergence (:: AbsTerminationMode , duₙ, uₙ, uₙ₋₁, abstol, reltol)
196
342
return all (abs .(duₙ) .≤ abstol)
197
343
end
198
344
function check_convergence (:: Union {AbsNormTerminationMode, AbsSafeTerminationMode,
199
- AbsSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
345
+ AbsSafeBestTerminationMode}, duₙ, uₙ, uₙ₋₁, abstol, reltol)
200
346
return NONLINEARSOLVE_DEFAULT_NORM (duₙ) ≤ abstol
201
347
end
202
348
@@ -242,8 +388,8 @@ mutable struct NLSolveSafeTerminationResult{T, uType}
242
388
end
243
389
244
390
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)
247
393
u = u != = nothing ? copy (u) : u
248
394
Base. depwarn (" NLSolveSafeTerminationResult has been deprecated in favor of the new dispatch based termination conditions. Please use the new termination conditions API!" ,
249
395
:NLSolveSafeTerminationResult )
@@ -330,9 +476,9 @@ get_termination_mode(::NLSolveTerminationCondition{mode}) where {mode} = mode
330
476
331
477
# Don't specify `mode` since the defaults would depend on the package
332
478
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}
336
482
Base. depwarn (" NLSolveTerminationCondition has been deprecated in favor of the new dispatch based termination conditions. Please use the new termination conditions API!" ,
337
483
:NLSolveTerminationCondition )
338
484
@assert mode ∈ instances (NLSolveTerminationMode. T)
@@ -346,9 +492,9 @@ function NLSolveTerminationCondition(mode; abstol::T = 1e-8, reltol::T = 1e-6,
346
492
end
347
493
348
494
function (cond:: NLSolveTerminationCondition )(storage:: Union {
349
- NLSolveSafeTerminationResult,
350
- Nothing,
351
- })
495
+ NLSolveSafeTerminationResult,
496
+ Nothing,
497
+ })
352
498
mode = get_termination_mode (cond)
353
499
# We need both the dispatches to support solvers that don't use the integrator
354
500
# interface like SimpleNonlinearSolve
438
584
439
585
# Convergence Criteria
440
586
@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}
442
588
return _has_converged (du, u, uprev, mode, abstol, reltol)
443
589
end
444
590
0 commit comments