Skip to content

Commit 1e4cfde

Browse files
committed
Broyden supports matrices
1 parent 4c0f628 commit 1e4cfde

File tree

7 files changed

+30
-34
lines changed

7 files changed

+30
-34
lines changed

src/broyden.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function SciMLBase.__init(prob::NonlinearProblem{uType, iip}, alg::GeneralBroyde
5858
fu = evaluate_f(prob, u)
5959
J⁻¹ = __init_identity_jacobian(u, fu)
6060
return GeneralBroydenCache{iip}(f, alg, u, _mutable_zero(u), fu, zero(fu),
61-
zero(fu), p, J⁻¹, zero(fu'), _mutable_zero(u), false, 0, alg.max_resets,
61+
zero(fu), p, J⁻¹, zero(_vec(fu)'), _mutable_zero(u), false, 0, alg.max_resets,
6262
maxiters, internalnorm, ReturnCode.Default, abstol, prob, NLStats(1, 0, 0, 0, 0),
6363
init_linesearch_cache(alg.linesearch, f, u, p, fu, Val(iip)))
6464
end
@@ -67,7 +67,7 @@ function perform_step!(cache::GeneralBroydenCache{true})
6767
@unpack f, p, du, fu, fu2, dfu, u, J⁻¹, J⁻¹df, J⁻¹₂ = cache
6868
T = eltype(u)
6969

70-
mul!(du, J⁻¹, -fu)
70+
mul!(_vec(du), J⁻¹, -_vec(fu))
7171
α = perform_linesearch!(cache.lscache, u, du)
7272
axpy!(α, du, u)
7373
f(fu2, u, p)
@@ -85,10 +85,10 @@ function perform_step!(cache::GeneralBroydenCache{true})
8585
J⁻¹[diagind(J⁻¹)] .= T(1)
8686
cache.resets += 1
8787
else
88-
mul!(J⁻¹df, J⁻¹, dfu)
89-
mul!(J⁻¹₂, du', J⁻¹)
88+
mul!(_vec(J⁻¹df), J⁻¹, _vec(dfu))
89+
mul!(J⁻¹₂, _vec(du)', J⁻¹)
9090
du .= (du .- J⁻¹df) ./ (dot(du, J⁻¹df) .+ T(1e-5))
91-
mul!(J⁻¹, reshape(du, :, 1), J⁻¹₂, 1, 1)
91+
mul!(J⁻¹, _vec(du), J⁻¹₂, 1, 1)
9292
end
9393
fu .= fu2
9494

@@ -99,7 +99,7 @@ function perform_step!(cache::GeneralBroydenCache{false})
9999
@unpack f, p = cache
100100
T = eltype(cache.u)
101101

102-
cache.du = cache.J⁻¹ * -cache.fu
102+
cache.du = _restructure(cache.du, cache.J⁻¹ * -_vec(cache.fu))
103103
α = perform_linesearch!(cache.lscache, cache.u, cache.du)
104104
cache.u = cache.u .+ α * cache.du
105105
cache.fu2 = f(cache.u, p)
@@ -119,10 +119,10 @@ function perform_step!(cache::GeneralBroydenCache{false})
119119
cache.J⁻¹ = J⁻¹
120120
cache.resets += 1
121121
else
122-
cache.J⁻¹df = cache.J⁻¹ * cache.dfu
123-
cache.J⁻¹₂ = cache.du' * cache.J⁻¹
122+
cache.J⁻¹df = _restructure(cache.J⁻¹df, cache.J⁻¹ * _vec(cache.dfu))
123+
cache.J⁻¹₂ = _vec(cache.du)' * cache.J⁻¹
124124
cache.du = (cache.du .- cache.J⁻¹df) ./ (dot(cache.du, cache.J⁻¹df) .+ T(1e-5))
125-
cache.J⁻¹ = cache.J⁻¹ .+ cache.du * cache.J⁻¹₂
125+
cache.J⁻¹ = cache.J⁻¹ .+ _vec(cache.du) * cache.J⁻¹₂
126126
end
127127
cache.fu = cache.fu2
128128

src/levenberg.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,9 @@ function perform_step!(cache::LevenbergMarquardtCache{false})
301301
else
302302
linres = dolinsolve(alg.precs, linsolve;
303303
b = _mutable(_vec(J' * #((2 / h) .* ((f(u .+ h .* v, p) .- fu1) ./ h .- J * v)))),
304-
_vec(((2 / h) .* ((_vec(f(u .+ h .* _restructure(u,v), p)) .- _vec(fu1)) ./ h .- J * _vec(v)))))),
304+
_vec(((2 / h) .*
305+
((_vec(f(u .+ h .* _restructure(u, v), p)) .-
306+
_vec(fu1)) ./ h .- J * _vec(v)))))),
305307
linu = _vec(cache.a), p, reltol = cache.abstol)
306308
cache.linsolve = linres.cache
307309
end
@@ -311,7 +313,7 @@ function perform_step!(cache::LevenbergMarquardtCache{false})
311313
# Require acceptable steps to satisfy the following condition.
312314
norm_v = norm(v)
313315
if 2 * norm(cache.a) α_geodesic * norm_v
314-
cache.δ = _restructure(cache.δ,_vec(v) .+ _vec(cache.a) ./ 2)
316+
cache.δ = _restructure(cache.δ, _vec(v) .+ _vec(cache.a) ./ 2)
315317
@unpack δ, loss_old, norm_v_old, v_old, b_uphill = cache
316318
fu_new = f(u .+ δ, p)
317319
cache.stats.nf += 1
@@ -327,7 +329,7 @@ function perform_step!(cache::LevenbergMarquardtCache{false})
327329
return nothing
328330
end
329331
cache.fu1 = fu_new
330-
cache.v_old = _restructure(cache.v_old,v)
332+
cache.v_old = _restructure(cache.v_old, v)
331333
cache.norm_v_old = norm_v
332334
cache.loss_old = loss
333335
cache.λ_factor = 1 / cache.damping_decrease_factor

src/pseudotransient.jl

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ SIAM Journal on Scientific Computing,25, 553-569.](https://doi.org/10.1137/S1064
2929
[LinearSolve.jl documentation](https://docs.sciml.ai/LinearSolve/stable/).
3030
- `alpha_initial` : the initial pseudo time step. it defaults to 1e-3. If it is small,
3131
you are going to need more iterations to converge but it can be more stable.
32-
33-
34-
35-
3632
"""
3733
@concrete struct PseudoTransient{CJ, AD} <: AbstractNewtonAlgorithm{CJ, AD}
3834
ad::AD
@@ -92,19 +88,14 @@ function SciMLBase.__init(prob::NonlinearProblem{uType, iip}, alg_::PseudoTransi
9288
else
9389
fu1 = _mutable(f(u, p))
9490
end
95-
uf, linsolve, J, fu2, jac_cache, du = jacobian_caches(alg,
96-
f,
97-
u,
98-
p,
99-
Val(iip);
91+
uf, linsolve, J, fu2, jac_cache, du = jacobian_caches(alg, f, u, p, Val(iip);
10092
linsolve_kwargs)
10193
alpha = convert(eltype(u), alg.alpha_initial)
10294
res_norm = internalnorm(fu1)
10395

10496
return PseudoTransientCache{iip}(f, alg, u, fu1, fu2, du, p, alpha, res_norm, uf,
105-
linsolve, J,
106-
jac_cache, false, maxiters, internalnorm, ReturnCode.Default, abstol, prob,
107-
NLStats(1, 0, 0, 0, 0))
97+
linsolve, J, jac_cache, false, maxiters, internalnorm, ReturnCode.Default, abstol,
98+
prob, NLStats(1, 0, 0, 0, 0))
10899
end
109100

110101
function perform_step!(cache::PseudoTransientCache{true})

src/raphson.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function perform_step!(cache::NewtonRaphsonCache{true})
9797

9898
# Line Search
9999
α = perform_linesearch!(cache.lscache, u, du)
100-
axpy!(α, du, u)
100+
axpy!(-α, du, u)
101101
f(cache.fu1, u, p)
102102

103103
cache.internalnorm(fu1) < cache.abstol && (cache.force_stop = true)

src/trustRegion.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,8 @@ function trust_region_step!(cache::TrustRegionCache)
419419
cache.loss_new = get_loss(fu_new)
420420

421421
# Compute the ratio of the actual reduction to the predicted reduction.
422-
cache.r = -(loss - cache.loss_new) / (dot(_vec(du), _vec(g)) + dot(_vec(du), H, _vec(du)) / 2)
422+
cache.r = -(loss - cache.loss_new) /
423+
(dot(_vec(du), _vec(g)) + dot(_vec(du), H, _vec(du)) / 2)
423424
@unpack r = cache
424425

425426
if radius_update_scheme === RadiusUpdateSchemes.Simple

src/utils.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ end
7474
@inline _vec(v::Number) = v
7575
@inline _vec(v::AbstractVector) = v
7676

77-
@inline _restructure(y,x) = restructure(y,x)
78-
@inline _restructure(y::Number,x::Number) = x
77+
@inline _restructure(y, x) = restructure(y, x)
78+
@inline _restructure(y::Number, x::Number) = x
7979

8080
DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, cachedata) = nothing, nothing
8181

@@ -220,4 +220,4 @@ end
220220
function __init_identity_jacobian(u::StaticArray, fu)
221221
return convert(MArray{Tuple{length(fu), length(u)}},
222222
Matrix{eltype(u)}(I, length(fu), length(u)))
223-
end
223+
end

test/matrix_resizing.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
using NonlinearSolve, Test
22

33
ff(u, p) = u .* u .- p
4-
u0 = rand(2,2)
4+
u0 = rand(2, 2)
55
p = 2.0
66
vecprob = NonlinearProblem(ff, vec(u0), p)
77
prob = NonlinearProblem(ff, u0, p)
88

9-
for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg())
9+
for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(),
10+
RobustMultiNewton(), FastShortcutNonlinearPolyalg(), GeneralBroyden())
1011
@test vec(solve(prob, alg).u) == solve(vecprob, alg).u
1112
end
1213

1314
fiip(du, u, p) = (du .= u .* u .- p)
14-
u0 = rand(2,2)
15+
u0 = rand(2, 2)
1516
p = 2.0
1617
vecprob = NonlinearProblem(fiip, vec(u0), p)
1718
prob = NonlinearProblem(fiip, u0, p)
1819

19-
for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg())
20+
for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(),
21+
RobustMultiNewton(), FastShortcutNonlinearPolyalg(), GeneralBroyden())
2022
@test vec(solve(prob, alg).u) == solve(vecprob, alg).u
21-
end
23+
end

0 commit comments

Comments
 (0)