|
1 | 1 | """ |
2 | | - SimpleMuller() |
| 2 | + Muller() |
3 | 3 |
|
4 | 4 | Muller's method for determining a root of a univariate, scalar function. The |
5 | 5 | algorithm, described in Sec. 9.5.2 of |
6 | 6 | [Press et al. (2007)](https://numerical.recipes/book.html), requires three |
7 | 7 | initial guesses `(xᵢ₋₂, xᵢ₋₁, xᵢ)` for the root. |
8 | 8 | """ |
9 | | -struct SimpleMuller <: AbstractSimpleNonlinearSolveAlgorithm end |
| 9 | +struct Muller <: AbstractBracketingAlgorithm end |
10 | 10 |
|
11 | | -function SciMLBase.solve(prob::NonlinearProblem, alg::SimpleMuller, args...; |
12 | | - abstol = 1e-3, maxiters = 1000, kwargs...) |
13 | | - @assert !isinplace(prob) "`SimpleMuller` only supports OOP problems." |
14 | | - @assert length(prob.u0) == 3 "`SimpleMuller` requires three initial guesses." |
15 | | - xᵢ₋₂, xᵢ₋₁, xᵢ = prob.u0 |
| 11 | +function CommonSolve.solve(prob::IntervalNonlinearProblem, alg::Muller, args...; |
| 12 | + abstol = nothing, maxiters = 1000, kwargs...) |
| 13 | + @assert !SciMLBase.isinplace(prob) "`Muller` only supports out-of-place problems." |
| 14 | + xᵢ₋₂, xᵢ = prob.tspan |
| 15 | + xᵢ₋₁ = (xᵢ₋₂ + xᵢ) / 2 # Use midpoint for middle guess |
16 | 16 | xᵢ₋₂, xᵢ₋₁, xᵢ = promote(xᵢ₋₂, xᵢ₋₁, xᵢ) |
17 | 17 | @assert xᵢ₋₂ ≠ xᵢ₋₁ ≠ xᵢ ≠ xᵢ₋₂ |
18 | 18 | f = Base.Fix2(prob.f, prob.p) |
19 | 19 | fxᵢ₋₂, fxᵢ₋₁, fxᵢ = f(xᵢ₋₂), f(xᵢ₋₁), f(xᵢ) |
20 | 20 |
|
21 | 21 | xᵢ₊₁, fxᵢ₊₁ = xᵢ₋₂, fxᵢ₋₂ |
22 | 22 |
|
| 23 | + abstol = NonlinearSolveBase.get_tolerance( |
| 24 | + xᵢ₋₂, abstol, promote_type(eltype(xᵢ₋₂), eltype(xᵢ))) |
| 25 | + |
23 | 26 | for _ ∈ 1:maxiters |
24 | 27 | q = (xᵢ - xᵢ₋₁)/(xᵢ₋₁ - xᵢ₋₂) |
25 | 28 | A = q*fxᵢ - q*(1 + q)*fxᵢ₋₁ + q^2*fxᵢ₋₂ |
|
0 commit comments