Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.

Commit 468a204

Browse files
committed
inital commit, started to implement Broyden
1 parent 92b2eb2 commit 468a204

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/SimpleNonlinearSolve.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ using Reexport
44
using FiniteDiff, ForwardDiff
55
using ForwardDiff: Dual
66
using StaticArraysCore
7+
using LinearAlgebra # TODO check if it is ok to add this
78
import ArrayInterfaceCore
89

910
@reexport using SciMLBase
@@ -18,12 +19,13 @@ include("bisection.jl")
1819
include("falsi.jl")
1920
include("raphson.jl")
2021
include("ad.jl")
22+
include("broyden.jl")
2123

2224
import SnoopPrecompile
2325

2426
SnoopPrecompile.@precompile_all_calls begin for T in (Float32, Float64)
2527
prob_no_brack = NonlinearProblem{false}((u, p) -> u .* u .- p, T(0.1), T(2))
26-
for alg in (SimpleNewtonRaphson,)
28+
for alg in (SimpleNewtonRaphson, Broyden)
2729
solve(prob_no_brack, alg(), tol = T(1e-2))
2830
end
2931

@@ -44,6 +46,6 @@ SnoopPrecompile.@precompile_all_calls begin for T in (Float32, Float64)
4446
end end
4547

4648
# DiffEq styled algorithms
47-
export Bisection, Falsi, SimpleNewtonRaphson
49+
export Bisection, Broyden, Falsi, SimpleNewtonRaphson
4850

4951
end # module

src/broyden.jl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# TODO add docstrings
2+
3+
# TODO check what the supertype should be
4+
# TODO check if this should be defined as in raphson.jl
5+
struct Broyden <: AbstractSimpleNonlinearSolveAlgorithm end
6+
7+
function SciMLBase.solve(prob::NonlinearProblem,
8+
alg::Broyden, args...; abstol = nothing,
9+
reltol = nothing,
10+
maxiters = 1000, kwargs...)
11+
f = Base.Fix2(prob.f, prob.p)
12+
xₙ = float(prob.u0)
13+
T = typeof(xₙ)
14+
J⁻¹ = Matrix{T}(I, length(xₙ), length(xₙ))
15+
16+
if SciMLBase.isinplace(prob)
17+
error("Broyden currently only supports out-of-place nonlinear problems")
18+
end
19+
20+
atol = abstol !== nothing ? abstol :
21+
real(oneunit(eltype(T))) * (eps(real(one(eltype(T)))))^(4 // 5)
22+
rtol = reltol !== nothing ? reltol : eps(real(one(eltype(T))))^(4 // 5)
23+
24+
for _ in 1:maxiters
25+
# TODO check if nameing with heavy use of subscrips is ok
26+
fₙ = f(xₙ)
27+
xₙ₊₁ = xₙ + J⁻¹ * fₙ
28+
Δxₙ = xₙ₊₁ - xₙ
29+
Δfₙ = f(xₙ₊₁) - fₙ
30+
J⁻¹ .+= ((Δxₙ .- J⁻¹ * Δfₙ) ./ (Δxₙ' * J⁻¹ * Δfₙ)) * (Δxₙ' * J⁻¹)
31+
32+
iszero(fₙ) &&
33+
return SciMLBase.build_solution(prob, alg, xₙ₊₁, fₙ; retcode = ReturnCode.Success)
34+
35+
if isapprox(xₙ₊₁, xₙ, atol = atol, rtol = rtol)
36+
return SciMLBase.build_solution(prob, alg, xₙ₊₁, fₙ; retcode = ReturnCode.Success)
37+
end
38+
xₙ = xₙ₊₁
39+
end
40+
41+
@show xₙ, fₙ
42+
return SciMLBase.build_solution(prob, alg, xₙ, fₙ; retcode = ReturnCode.MaxIters)
43+
end

test/basictests.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ for alg in [Bisection(), Falsi()]
7777
global g, p
7878
g = function (p)
7979
probN = IntervalNonlinearProblem{false}(f, tspan, p)
80-
sol = solve(probN, Bisection())
80+
sol = solve(probN, Bisection()) # TODO check if "alg" should replace "Bisection()"
8181
return [sol.left]
8282
end
8383

@@ -102,13 +102,15 @@ probN = NonlinearProblem(f, u0)
102102
@test solve(probN, SimpleNewtonRaphson(); immutable = false).u[end] sqrt(2.0)
103103
@test solve(probN, SimpleNewtonRaphson(; autodiff = false)).u[end] sqrt(2.0)
104104
@test solve(probN, SimpleNewtonRaphson(; autodiff = false)).u[end] sqrt(2.0)
105+
# TODO check why the 2 lines above are identical
105106

106107
for u0 in [1.0, [1, 1.0]]
107108
local f, probN, sol
108109
f = (u, p) -> u .* u .- 2.0
109110
probN = NonlinearProblem(f, u0)
110111
sol = sqrt(2) * u0
111112

113+
# TODO check why the two lines below are identical
112114
@test solve(probN, SimpleNewtonRaphson()).u sol
113115
@test solve(probN, SimpleNewtonRaphson()).u sol
114116
@test solve(probN, SimpleNewtonRaphson(; autodiff = false)).u sol

0 commit comments

Comments
 (0)