Skip to content

Commit bcf05af

Browse files
committed
Add functionality to specify middle guess
1 parent f75cee5 commit bcf05af

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

lib/BracketingNonlinearSolve/src/muller.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
"""
2-
Muller()
2+
Muller(; middle = nothing)
33
44
Muller's method for determining a root of a univariate, scalar function. The
55
algorithm, described in Sec. 9.5.2 of
66
[Press et al. (2007)](https://numerical.recipes/book.html), requires three
7-
initial guesses `(xᵢ₋₂, xᵢ₋₁, xᵢ)` for the root.
7+
initial guesses `(left, middle, right)` for the root.
8+
9+
### Keyword Arguments
10+
11+
- `middle`: the initial guess for the middle point. If not provided, the
12+
midpoint of the interval `(left, right)` is used.
813
"""
9-
struct Muller <: AbstractBracketingAlgorithm end
14+
struct Muller{T} <: AbstractBracketingAlgorithm
15+
middle::T
16+
end
17+
18+
Muller() = Muller(nothing)
1019

1120
function CommonSolve.solve(prob::IntervalNonlinearProblem, alg::Muller, args...;
1221
abstol = nothing, maxiters = 1000, kwargs...)
1322
@assert !SciMLBase.isinplace(prob) "`Muller` only supports out-of-place problems."
1423
xᵢ₋₂, xᵢ = prob.tspan
15-
xᵢ₋₁ = (xᵢ₋₂ + xᵢ) / 2 # Use midpoint for middle guess
24+
xᵢ₋₁ = isnothing(alg.middle) ? (xᵢ₋₂ + xᵢ) / 2 : alg.middle
1625
xᵢ₋₂, xᵢ₋₁, xᵢ = promote(xᵢ₋₂, xᵢ₋₁, xᵢ)
1726
@assert xᵢ₋₂ xᵢ₋₁ xᵢ xᵢ₋₂
1827
f = Base.Fix2(prob.f, prob.p)
Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
@testitem "Muller" begin
2-
@testset "Quadratic function" begin
3-
f(u, p) = u^2 - p
2+
f(u, p) = u^2 - p
3+
g(u, p) = sin(u)
4+
h(u, p) = exp(-u)*sin(u)
5+
i(u, p) = u^3 - 1
46

7+
@testset "Quadratic function" begin
58
tspan = (10.0, 30.0)
69
p = 612.0
710
prob = IntervalNonlinearProblem{false}(f, tspan, p)
@@ -17,56 +20,77 @@
1720
end
1821

1922
@testset "Sine function" begin
20-
f(u, p) = sin(u)
21-
2223
tspan = (1.0, 3.0)
23-
prob = IntervalNonlinearProblem{false}(f, tspan)
24+
prob = IntervalNonlinearProblem{false}(g, tspan)
2425
sol = solve(prob, Muller())
2526

2627
@test sol.u π
2728

2829
tspan = (2.0, 6.0)
29-
prob = IntervalNonlinearProblem{false}(f, tspan)
30+
prob = IntervalNonlinearProblem{false}(g, tspan)
3031
sol = solve(prob, Muller())
3132

3233
@test sol.u 2*π
3334
end
3435

3536
@testset "Exponential-sine function" begin
36-
f(u, p) = exp(-u)*sin(u)
37-
3837
tspan = (-2.0, -4.0)
39-
prob = IntervalNonlinearProblem{false}(f, tspan)
38+
prob = IntervalNonlinearProblem{false}(h, tspan)
4039
sol = solve(prob, Muller())
4140

4241
@test sol.u -π
4342

4443
tspan = (-3.0, 1.0)
45-
prob = IntervalNonlinearProblem{false}(f, tspan)
44+
prob = IntervalNonlinearProblem{false}(h, tspan)
4645
sol = solve(prob, Muller())
4746

4847
@test sol.u 0 atol = 1e-15
4948

5049
tspan = (-1.0, 1.0)
51-
prob = IntervalNonlinearProblem{false}(f, tspan)
50+
prob = IntervalNonlinearProblem{false}(h, tspan)
5251
sol = solve(prob, Muller())
5352

5453
@test sol.u π
5554
end
5655

5756
@testset "Complex roots" begin
58-
f(u, p) = u^3 - 1
59-
6057
tspan = (-1.0, 1.0*im)
61-
prob = IntervalNonlinearProblem{false}(f, tspan)
58+
prob = IntervalNonlinearProblem{false}(i, tspan)
6259
sol = solve(prob, Muller())
6360

6461
@test sol.u (-1 + 3*im)/2
6562

6663
tspan = (-1.0, -1.0*im)
67-
prob = IntervalNonlinearProblem{false}(f, tspan)
64+
prob = IntervalNonlinearProblem{false}(i, tspan)
6865
sol = solve(prob, Muller())
6966

7067
@test sol.u (-1 - 3*im)/2
7168
end
69+
70+
@testset "Middle" begin
71+
tspan = (10.0, 30.0)
72+
p = 612.0
73+
prob = IntervalNonlinearProblem{false}(f, tspan, p)
74+
sol = solve(prob, Muller(20.0))
75+
76+
@test sol.u 612
77+
78+
tspan = (1.0, 3.0)
79+
prob = IntervalNonlinearProblem{false}(g, tspan)
80+
sol = solve(prob, Muller(2.0))
81+
82+
@test sol.u π
83+
84+
tspan = (-2.0, -4.0)
85+
prob = IntervalNonlinearProblem{false}(h, tspan)
86+
sol = solve(prob, Muller(-3.0))
87+
88+
@test sol.u -π
89+
90+
tspan = (-1.0, 1.0*im)
91+
prob = IntervalNonlinearProblem{false}(i, tspan)
92+
sol = solve(prob, Muller(0.0))
93+
94+
@test sol.u (-1 + 3*im)/2
95+
end
7296
end

0 commit comments

Comments
 (0)