@@ -30,28 +30,32 @@ for large-scale and numerically-difficult nonlinear systems.
30
30
which means that no line search is performed. Algorithms from `LineSearches.jl` can be
31
31
used here directly, and they will be converted to the correct `LineSearch`.
32
32
"""
33
- @concrete struct NewtonRaphson{CJ, AD} <: AbstractNewtonAlgorithm{CJ, AD}
33
+ @concrete struct NewtonRaphson{CJ, AD, TC <: NLSolveTerminationCondition } <: AbstractNewtonAlgorithm{CJ, AD}
34
34
ad:: AD
35
35
linsolve
36
36
precs
37
37
linesearch
38
+ termination_condition:: TC
38
39
end
39
40
40
41
function set_ad (alg:: NewtonRaphson{CJ} , ad) where {CJ}
41
42
return NewtonRaphson {CJ} (ad, alg. linsolve, alg. precs, alg. linesearch)
42
43
end
43
44
44
45
function NewtonRaphson (; concrete_jac = nothing , linsolve = nothing ,
45
- linesearch = LineSearch (), precs = DEFAULT_PRECS, adkwargs... )
46
+ linesearch = LineSearch (), precs = DEFAULT_PRECS, termination_condition = NLSolveTerminationCondition (NLSolveTerminationMode. NLSolveDefault;
47
+ abstol = nothing ,
48
+ reltol = nothing ), adkwargs... )
46
49
ad = default_adargs_to_adtype (; adkwargs... )
47
50
linesearch = linesearch isa LineSearch ? linesearch : LineSearch (; method = linesearch)
48
- return NewtonRaphson {_unwrap_val(concrete_jac)} (ad, linsolve, precs, linesearch)
51
+ return NewtonRaphson {_unwrap_val(concrete_jac)} (ad, linsolve, precs, linesearch, termination_condition )
49
52
end
50
53
51
54
@concrete mutable struct NewtonRaphsonCache{iip} <: AbstractNonlinearSolveCache{iip}
52
55
f
53
56
alg
54
57
u
58
+ uprev
55
59
fu1
56
60
fu2
57
61
du
65
69
internalnorm
66
70
retcode:: ReturnCode.T
67
71
abstol
72
+ reltol
68
73
prob
69
74
stats:: NLStats
70
75
lscache
76
+ tc_storage
71
77
end
72
78
73
79
function SciMLBase. __init (prob:: NonlinearProblem{uType, iip} , alg_:: NewtonRaphson , args... ;
@@ -80,15 +86,28 @@ function SciMLBase.__init(prob::NonlinearProblem{uType, iip}, alg_::NewtonRaphso
80
86
uf, linsolve, J, fu2, jac_cache, du = jacobian_caches (alg, f, u, p, Val (iip);
81
87
linsolve_kwargs)
82
88
83
- return NewtonRaphsonCache {iip} (f, alg, u, fu1, fu2, du, p, uf, linsolve, J,
84
- jac_cache, false , maxiters, internalnorm, ReturnCode. Default, abstol, prob,
85
- NLStats (1 , 0 , 0 , 0 , 0 ), LineSearchCache (alg. linesearch, f, u, p, fu1, Val (iip)))
89
+
90
+ tc = alg. termination_condition
91
+ mode = DiffEqBase. get_termination_mode (tc)
92
+
93
+ atol = _get_tolerance (abstol, tc. abstol, eltype (u))
94
+ rtol = _get_tolerance (reltol, tc. reltol, eltype (u))
95
+
96
+ storage = mode ∈ DiffEqBase. SAFE_TERMINATION_MODES ? NLSolveSafeTerminationResult () :
97
+ nothing
98
+
99
+ return NewtonRaphsonCache {iip} (f, alg, u, copy (u), fu1, fu2, du, p, uf, linsolve, J,
100
+ jac_cache, false , maxiters, internalnorm, ReturnCode. Default, atol, rtol, prob,
101
+ NLStats (1 , 0 , 0 , 0 , 0 ), LineSearchCache (alg. linesearch, f, u, p, fu1, Val (iip)), storage)
86
102
end
87
103
88
104
function perform_step! (cache:: NewtonRaphsonCache{true} )
89
- @unpack u, fu1, f, p, alg, J, linsolve, du = cache
105
+ @unpack u, uprev, fu1, f, p, alg, J, linsolve, du = cache
90
106
jacobian!! (J, cache)
91
107
108
+ tc_storage = cache. tc_storage
109
+ termination_condition = cache. alg. termination_condition (tc_storage)
110
+
92
111
# u = u - J \ fu
93
112
linres = dolinsolve (alg. precs, linsolve; A = J, b = _vec (fu1), linu = _vec (du),
94
113
p, reltol = cache. abstol)
@@ -99,7 +118,9 @@ function perform_step!(cache::NewtonRaphsonCache{true})
99
118
@. u = u - α * du
100
119
f (cache. fu1, u, p)
101
120
102
- cache. internalnorm (fu1) < cache. abstol && (cache. force_stop = true )
121
+ termination_condition (cache. fu1, u, uprev, cache. abstol, cache. reltol) && (cache. force_stop = true )
122
+
123
+ @. uprev = u
103
124
cache. stats. nf += 1
104
125
cache. stats. njacs += 1
105
126
cache. stats. nsolve += 1
@@ -108,7 +129,11 @@ function perform_step!(cache::NewtonRaphsonCache{true})
108
129
end
109
130
110
131
function perform_step! (cache:: NewtonRaphsonCache{false} )
111
- @unpack u, fu1, f, p, alg, linsolve = cache
132
+ @unpack u, uprev, fu1, f, p, alg, linsolve = cache
133
+
134
+ tc_storage = cache. tc_storage
135
+ termination_condition = cache. alg. termination_condition (tc_storage)
136
+
112
137
113
138
cache. J = jacobian!! (cache. J, cache)
114
139
# u = u - J \ fu
@@ -125,7 +150,9 @@ function perform_step!(cache::NewtonRaphsonCache{false})
125
150
cache. u = @. u - α * cache. du # `u` might not support mutation
126
151
cache. fu1 = f (cache. u, p)
127
152
128
- cache. internalnorm (fu1) < cache. abstol && (cache. force_stop = true )
153
+ termination_condition (cache. fu1, cache. u, uprev, cache. abstol, cache. reltol) && (cache. force_stop = true )
154
+
155
+ cache. uprev = cache. u
129
156
cache. stats. nf += 1
130
157
cache. stats. njacs += 1
131
158
cache. stats. nsolve += 1
0 commit comments