Skip to content

Commit de9e9a2

Browse files
More generic safe similar (#550)
* More generic safe similar * Fix docs failure * Fix typo in docs * Restrict type of T --------- Co-authored-by: Christopher Rackauckas <[email protected]>
1 parent 70ff13e commit de9e9a2

File tree

9 files changed

+39
-36
lines changed

9 files changed

+39
-36
lines changed

docs/src/basics/diagnostics_api.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ solve process. This is controlled by 3 keyword arguments to `solve`:
2020

2121
All the native NonlinearSolve.jl algorithms come with in-built
2222
[TimerOutputs.jl](https://github.com/KristofferC/TimerOutputs.jl) support. However, this
23-
is disabled by default and can be enabled via [`NonlinearSolve.enable_timer_outputs`](@ref).
23+
is disabled by default and can be enabled via [`NonlinearSolveBase.enable_timer_outputs`](@ref).
2424

2525
Note that you will have to restart Julia to disable the timer outputs once enabled.
2626

docs/src/basics/faq.md

+23-23
Original file line numberDiff line numberDiff line change
@@ -71,29 +71,29 @@ differentiate the function based on the input types. However, this function has
7171
`xx = [1.0, 2.0, 3.0, 4.0]` followed by a `xx[1] = var[1] - v_true[1]` where `var` might
7272
be a Dual number. This causes the error. To fix it:
7373

74-
1. Specify the `autodiff` to be `AutoFiniteDiff`
75-
76-
```@example dual_error_faq
77-
sol = solve(prob_oop, LevenbergMarquardt(; autodiff = AutoFiniteDiff());
78-
maxiters = 10000, abstol = 1e-8)
79-
```
80-
81-
This worked but, Finite Differencing is not the recommended approach in any scenario.
82-
83-
2. Rewrite the function to use
84-
[PreallocationTools.jl](https://github.com/SciML/PreallocationTools.jl) or write it as
85-
86-
```@example dual_error_faq
87-
function fff_correct(var, p)
88-
v_true = [1.0, 0.1, 2.0, 0.5]
89-
xx = eltype(var)[1.0, 2.0, 3.0, 4.0]
90-
xx[1] = var[1] - v_true[1]
91-
return xx - v_true
92-
end
93-
94-
prob_oop = NonlinearLeastSquaresProblem{false}(fff_correct, v_init)
95-
sol = solve(prob_oop, LevenbergMarquardt(); maxiters = 10000, abstol = 1e-8)
96-
```
74+
1. Specify the `autodiff` to be `AutoFiniteDiff`
75+
76+
```@example dual_error_faq
77+
sol = solve(prob_oop, LevenbergMarquardt(; autodiff = AutoFiniteDiff());
78+
maxiters = 10000, abstol = 1e-8)
79+
```
80+
81+
This worked but, Finite Differencing is not the recommended approach in any scenario.
82+
83+
2. Rewrite the function to use
84+
[PreallocationTools.jl](https://github.com/SciML/PreallocationTools.jl) or write it as
85+
86+
```@example dual_error_faq
87+
function fff_correct(var, p)
88+
v_true = [1.0, 0.1, 2.0, 0.5]
89+
xx = eltype(var)[1.0, 2.0, 3.0, 4.0]
90+
xx[1] = var[1] - v_true[1]
91+
return xx - v_true
92+
end
93+
94+
prob_oop = NonlinearLeastSquaresProblem{false}(fff_correct, v_init)
95+
sol = solve(prob_oop, LevenbergMarquardt(); maxiters = 10000, abstol = 1e-8)
96+
```
9797
9898
## I thought NonlinearSolve.jl was type-stable and fast. But it isn't, why?
9999

docs/src/tutorials/iterator_interface.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ to iterate the solver.
2020
The iterator interface supports:
2121

2222
```@docs
23-
step!(nlcache::NonlinearSolve.AbstractNonlinearSolveCache, args...; kwargs...)
23+
step!(nlcache::NonlinearSolveBase.AbstractNonlinearSolveCache, args...; kwargs...)
2424
```
2525

2626
We can perform 10 steps of the Newton-Raphson solver with the following:

lib/NonlinearSolveBase/src/NonlinearSolveBase.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ using RecursiveArrayTools: AbstractVectorOfArray, ArrayPartition
1919
using SciMLBase: SciMLBase, ReturnCode, AbstractODEIntegrator, AbstractNonlinearProblem,
2020
AbstractNonlinearAlgorithm, AbstractNonlinearFunction,
2121
NonlinearProblem, NonlinearLeastSquaresProblem, StandardNonlinearProblem,
22-
NonlinearFunction, NullParameters, NLStats, LinearProblem, LinearAliasSpecifier
22+
NonlinearFunction, NullParameters, NLStats, LinearProblem,
23+
LinearAliasSpecifier
2324
using SciMLJacobianOperators: JacobianOperator, StatefulJacobianOperator
2425
using SciMLOperators: AbstractSciMLOperator, IdentityOperator
2526
using SymbolicIndexingInterface: SymbolicIndexingInterface

lib/NonlinearSolveBase/src/jacobian.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function construct_jacobian_cache(
4141
(linsolve === nothing || needs_concrete_A(linsolve)))
4242
needs_jac = linsolve_needs_jac || concrete_jac(alg)
4343

44-
@bb fu_cache = similar(fu)
44+
fu_cache = Utils.safe_similar(fu)
4545

4646
if !has_analytic_jac && needs_jac
4747
if autodiff === nothing
@@ -80,9 +80,9 @@ function construct_jacobian_cache(
8080
end
8181
else
8282
if eltype(f.jac_prototype) <: Bool
83-
similar(f.jac_prototype, promote_type(eltype(fu), eltype(u)))
83+
Utils.safe_similar(f.jac_prototype, promote_type(eltype(fu), eltype(u)))
8484
else
85-
similar(f.jac_prototype)
85+
Utils.safe_similar(f.jac_prototype)
8686
end
8787
end
8888
end

lib/NonlinearSolveBase/src/linear_solve.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ function construct_linear_solver(alg, linsolve, A, b, u; stats, kwargs...)
7474
linprob = LinearProblem(A, b; u0 = u_cache, kwargs...)
7575

7676
# unlias here, we will later use these as caches
77-
lincache = init(linprob, linsolve; alias = LinearAliasSpecifier(alias_A = false, alias_b = false))
77+
lincache = init(
78+
linprob, linsolve; alias = LinearAliasSpecifier(alias_A = false, alias_b = false))
7879
return LinearSolveJLCache(lincache, linsolve, nothing, stats)
7980
end
8081

lib/NonlinearSolveBase/src/utils.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ restructure(y, x) = ArrayInterface.restructure(y, x)
101101

102102
function safe_similar(x, args...; kwargs...)
103103
y = similar(x, args...; kwargs...)
104-
return init_bigfloat_array!!(y)
104+
return init_similar_array!!(y)
105105
end
106106

107-
init_bigfloat_array!!(x) = x
107+
init_similar_array!!(x) = x
108108

109-
function init_bigfloat_array!!(x::AbstractArray{<:BigFloat})
110-
ArrayInterface.can_setindex(x) && fill!(x, BigFloat(0))
109+
function init_similar_array!!(x::AbstractArray{<:T}) where {T <: Number}
110+
ArrayInterface.can_setindex(x) && fill!(x, T(0))
111111
return x
112112
end
113113

lib/SimpleNonlinearSolve/src/utils.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ end
160160

161161
function compute_hvvp(prob, autodiff, _, x::Number, dir::Number)
162162
H = DI.second_derivative(prob.f, autodiff, x, Constant(prob.p))
163-
return H*dir
163+
return H * dir
164164
end
165165
function compute_hvvp(prob, autodiff, fx, x, dir)
166166
jvp_fn = if SciMLBase.isinplace(prob)

test/qa_tests.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
@testitem "Aqua" tags=[:misc] begin
22
using NonlinearSolve, SimpleNonlinearSolve, Aqua
33

4-
Aqua.test_all(NonlinearSolve; ambiguities = false, piracies = false, stale_deps = false, deps_compat = false)
4+
Aqua.test_all(NonlinearSolve; ambiguities = false, piracies = false,
5+
stale_deps = false, deps_compat = false)
56
Aqua.test_ambiguities(NonlinearSolve; recursive = false)
67
Aqua.test_stale_deps(SimpleNonlinearSolve; ignore = [:SciMLJacobianOperators])
78
Aqua.test_deps_compat(SimpleNonlinearSolve; ignore = [:SciMLJacobianOperators])

0 commit comments

Comments
 (0)