1
1
# Poly Algorithms
2
2
"""
3
- NonlinearSolvePolyAlgorithm(algs, ::Val{pType} = Val(:NLS)) where {pType}
3
+ NonlinearSolvePolyAlgorithm(algs, ::Val{pType} = Val(:NLS);
4
+ start_index = 1) where {pType}
4
5
5
6
A general way to define PolyAlgorithms for `NonlinearProblem` and
6
7
`NonlinearLeastSquaresProblem`. This is a container for a tuple of algorithms that will be
@@ -15,6 +16,10 @@ residual is returned.
15
16
`NonlinearLeastSquaresProblem`. This is used to determine the correct problem type to
16
17
dispatch on.
17
18
19
+ ### Keyword Arguments
20
+
21
+ - `start_index`: the index to start at. Defaults to `1`.
22
+
18
23
### Example
19
24
20
25
```julia
@@ -25,11 +30,14 @@ alg = NonlinearSolvePolyAlgorithm((NewtonRaphson(), Broyden()))
25
30
"""
26
31
struct NonlinearSolvePolyAlgorithm{pType, N, A} <: AbstractNonlinearSolveAlgorithm{:PolyAlg}
27
32
algs:: A
33
+ start_index:: Int
28
34
29
- function NonlinearSolvePolyAlgorithm (algs, :: Val{pType} = Val (:NLS )) where {pType}
35
+ function NonlinearSolvePolyAlgorithm (
36
+ algs, :: Val{pType} = Val (:NLS ); start_index:: Int = 1 ) where {pType}
30
37
@assert pType ∈ (:NLS , :NLLS )
38
+ @assert 0 < start_index ≤ length (algs)
31
39
algs = Tuple (algs)
32
- return new {pType, length(algs), typeof(algs)} (algs)
40
+ return new {pType, length(algs), typeof(algs)} (algs, start_index )
33
41
end
34
42
end
35
43
73
81
74
82
function reinit_cache! (cache:: NonlinearSolvePolyAlgorithmCache , args... ; kwargs... )
75
83
foreach (c -> reinit_cache! (c, args... ; kwargs... ), cache. caches)
76
- cache. current = 1
84
+ cache. current = cache . alg . start_index
77
85
cache. nsteps = 0
78
86
cache. total_time = 0.0
79
87
end
@@ -91,7 +99,7 @@ for (probType, pType) in ((:NonlinearProblem, :NLS), (:NonlinearLeastSquaresProb
91
99
alg. algs),
92
100
alg,
93
101
- 1 ,
94
- 1 ,
102
+ alg . start_index ,
95
103
0 ,
96
104
0.0 ,
97
105
maxtime,
140
148
quote
141
149
fus = tuple ($ (Tuple (resids)... ))
142
150
minfu, idx = __findmin (cache. internalnorm, fus)
151
+ idx += cache. alg. start_index - 1
143
152
stats = __compile_stats (cache. caches[idx])
144
153
u = get_u (cache. caches[idx])
145
154
retcode = cache. caches[idx]. retcode
@@ -194,18 +203,22 @@ for (probType, pType) in ((:NonlinearProblem, :NLS), (:NonlinearLeastSquaresProb
194
203
@eval begin
195
204
@generated function SciMLBase. __solve (
196
205
prob:: $probType , alg:: $algType{N} , args... ; kwargs... ) where {N}
197
- calls = []
206
+ calls = [:(current = alg . start_index) ]
198
207
sol_syms = [gensym (" sol" ) for _ in 1 : N]
199
208
for i in 1 : N
200
209
cur_sol = sol_syms[i]
201
210
push! (calls,
202
211
quote
203
- $ (cur_sol) = SciMLBase. __solve (prob, alg. algs[$ (i)], args... ; kwargs... )
204
- if SciMLBase. successful_retcode ($ (cur_sol))
205
- return SciMLBase. build_solution (
206
- prob, alg, $ (cur_sol). u, $ (cur_sol). resid;
207
- $ (cur_sol). retcode, $ (cur_sol). stats,
208
- original = $ (cur_sol), trace = $ (cur_sol). trace)
212
+ if current == $ i
213
+ $ (cur_sol) = SciMLBase. __solve (
214
+ prob, alg. algs[$ (i)], args... ; kwargs... )
215
+ if SciMLBase. successful_retcode ($ (cur_sol))
216
+ return SciMLBase. build_solution (
217
+ prob, alg, $ (cur_sol). u, $ (cur_sol). resid;
218
+ $ (cur_sol). retcode, $ (cur_sol). stats,
219
+ original = $ (cur_sol), trace = $ (cur_sol). trace)
220
+ end
221
+ current = $ (i + 1 )
209
222
end
210
223
end )
211
224
end
@@ -218,6 +231,7 @@ for (probType, pType) in ((:NonlinearProblem, :NLS), (:NonlinearLeastSquaresProb
218
231
push! (calls, quote
219
232
resids = tuple ($ (Tuple (resids)... ))
220
233
minfu, idx = __findmin (DEFAULT_NORM, resids)
234
+ idx += alg. start_index - 1
221
235
end )
222
236
223
237
for i in 1 : N
@@ -263,6 +277,7 @@ function RobustMultiNewton(::Type{T} = Float64; concrete_jac = nothing, linsolve
263
277
algs = (TrustRegion (; concrete_jac, linsolve, precs, autodiff),
264
278
TrustRegion (; concrete_jac, linsolve, precs, autodiff,
265
279
radius_update_scheme = RadiusUpdateSchemes. Bastin),
280
+ NewtonRaphson (; concrete_jac, linsolve, precs, autodiff),
266
281
NewtonRaphson (; concrete_jac, linsolve, precs,
267
282
linesearch = LineSearchesJL (; method = BackTracking ()), autodiff),
268
283
TrustRegion (; concrete_jac, linsolve, precs,
276
291
"""
277
292
FastShortcutNonlinearPolyalg(::Type{T} = Float64; concrete_jac = nothing,
278
293
linsolve = nothing, precs = DEFAULT_PRECS, must_use_jacobian::Val = Val(false),
279
- prefer_simplenonlinearsolve::Val{SA} = Val(false), autodiff = nothing) where {T}
294
+ prefer_simplenonlinearsolve::Val{SA} = Val(false), autodiff = nothing,
295
+ u0_len::Union{Int, Nothing} = nothing) where {T}
280
296
281
297
A polyalgorithm focused on balancing speed and robustness. It first tries less robust methods
282
298
for more performance and then tries more robust techniques if the faster ones fail.
@@ -285,12 +301,19 @@ for more performance and then tries more robust techniques if the faster ones fa
285
301
286
302
- `T`: The eltype of the initial guess. It is only used to check if some of the algorithms
287
303
are compatible with the problem type. Defaults to `Float64`.
304
+
305
+ ### Keyword Arguments
306
+
307
+ - `u0_len`: The length of the initial guess. If this is `nothing`, then the length of the
308
+ initial guess is not checked. If this is an integer and it is less than `25`, we use
309
+ jacobian based methods.
288
310
"""
289
311
function FastShortcutNonlinearPolyalg (
290
312
:: Type{T} = Float64; concrete_jac = nothing , linsolve = nothing ,
291
313
precs = DEFAULT_PRECS, must_use_jacobian:: Val{JAC} = Val (false ),
292
314
prefer_simplenonlinearsolve:: Val{SA} = Val (false ),
293
- autodiff = nothing ) where {T, JAC, SA}
315
+ u0_len:: Union{Int, Nothing} = nothing , autodiff = nothing ) where {T, JAC, SA}
316
+ start_index = 1
294
317
if JAC
295
318
if __is_complex (T)
296
319
algs = (NewtonRaphson (; concrete_jac, linsolve, precs, autodiff),)
@@ -312,6 +335,7 @@ function FastShortcutNonlinearPolyalg(
312
335
SimpleKlement (),
313
336
NewtonRaphson (; concrete_jac, linsolve, precs, autodiff))
314
337
else
338
+ start_index = u0_len != = nothing ? (u0_len ≤ 25 ? 4 : 1 ) : 1
315
339
algs = (SimpleBroyden (),
316
340
Broyden (; init_jacobian = Val (:true_jacobian ), autodiff),
317
341
SimpleKlement (),
@@ -327,6 +351,8 @@ function FastShortcutNonlinearPolyalg(
327
351
Klement (; linsolve, precs, autodiff),
328
352
NewtonRaphson (; concrete_jac, linsolve, precs, autodiff))
329
353
else
354
+ # TODO : This number requires a bit rigorous testing
355
+ start_index = u0_len != = nothing ? (u0_len ≤ 25 ? 4 : 1 ) : 1
330
356
algs = (Broyden (; autodiff),
331
357
Broyden (; init_jacobian = Val (:true_jacobian ), autodiff),
332
358
Klement (; linsolve, precs, autodiff),
@@ -339,7 +365,7 @@ function FastShortcutNonlinearPolyalg(
339
365
end
340
366
end
341
367
end
342
- return NonlinearSolvePolyAlgorithm (algs, Val (:NLS ))
368
+ return NonlinearSolvePolyAlgorithm (algs, Val (:NLS ); start_index )
343
369
end
344
370
345
371
"""
@@ -392,17 +418,19 @@ end
392
418
# # can use that!
393
419
function SciMLBase. __init (prob:: NonlinearProblem , :: Nothing , args... ; kwargs... )
394
420
must_use_jacobian = Val (prob. f. jac != = nothing )
395
- return SciMLBase. __init (
396
- prob, FastShortcutNonlinearPolyalg (eltype (prob. u0); must_use_jacobian),
397
- args... ; kwargs... )
421
+ return SciMLBase. __init (prob,
422
+ FastShortcutNonlinearPolyalg (
423
+ eltype (prob. u0); must_use_jacobian, u0_len = length (prob. u0)),
424
+ args... ;
425
+ kwargs... )
398
426
end
399
427
400
428
function SciMLBase. __solve (prob:: NonlinearProblem , :: Nothing , args... ; kwargs... )
401
429
must_use_jacobian = Val (prob. f. jac != = nothing )
402
430
prefer_simplenonlinearsolve = Val (prob. u0 isa SArray)
403
431
return SciMLBase. __solve (prob,
404
- FastShortcutNonlinearPolyalg (
405
- eltype (prob. u0); must_use_jacobian, prefer_simplenonlinearsolve ),
432
+ FastShortcutNonlinearPolyalg (eltype (prob . u0); must_use_jacobian,
433
+ prefer_simplenonlinearsolve, u0_len = length (prob. u0)),
406
434
args... ;
407
435
kwargs... )
408
436
end
0 commit comments