DifferentialEquations.jl
DifferentialEquations.jl copied to clipboard
RFC: Move default_algorithm to OrdinaryDiffEq etc.
It would be convenient if we can do solve(prob) without loading the whole DifferentialEquations. I think it can be done with, for example, something like this:
module OrdinaryDiffEq
"""
algorithm(name::Symbol) :: AbstractODEAlgorithm
algorithm(::Val{name}) :: AbstractODEAlgorithm
Get an algorithm constructor given its name.
"""
algorithm(name::Symbol) = algorithm(Val(name)) # for convenience
for alg in [Vern6, Vern7, ...] # list of algorithms in OrdinaryDiffEq
@eval algorithm(::Val{$(nameof(alg))}) = $alg
end
# fallback error handling for better user experience
function algorithm(@nospecialize ::Val{name}) where {name}
downstreams = Dict(
:CVODE_BDF => :Sundials,
...
)
pkg = downstream[name]
error("""
Algorithm $name cannot be used. You need to run:
using $pkg
or
using DifferentialEquations
""")
end
# Same as `DifferentialEquations.default_algorithm` but each
# algorithm constructor `XXX` is replaced with `algorithm(:XXX)`.
function default_algorithm(...)
...
if ...
alg = algorithm(:CVODE_BDF)(linear_solver=:GMRES)
elseif ...
end
...
end
end
module Sundials
OrdinaryDiffEq.algorithm(::Val{:CVODE_BDF}) = CVODE_BDF
end
It would be interesting to do this in DiffEqBase, and instead somehow define algorithm(:X)(args...) = X(args...) generically, then yes we could move the default handling out of DifferentialEquations.jl proper.
do this in DiffEqBase
We can define algorithm(name::Symbol) and algorithm(::Val) (which throws an error to indicate which package to load to use such algorithm) in DiffEqBase. But I think something like
for alg in [Vern6, Vern7, ...] # list of algorithms in OrdinaryDiffEq
@eval algorithm(::Val{$(nameof(alg))}) = $alg
end
needs to go into OrdinaryDiffEq (and similar definitions for all *DiffEq packages).
However, I think it has some downsides:
- The algorithm names are put in the same namespace. We can't have the algorithm of the same name for, say, solving ODE and SDE. But that's probably not going to happen anyway? Also, that's how it works in
DifferentialEquationsnow. - The error-throwing
DiffEqBase.algorithm(::Val)now needs to know all algorithms in all diffeq packages (or we can print a less specific message like "You need to run: using DifferentialEquations"). For example, it has to knowVern6etc. are inOrdinaryDiffEq. We can avoid this if we definealgorithminOrdinaryDiffEqand we only have to record optional packages.
I think this will be more pressing by this summer when our native methods are performing better than BDF even in the asymtopic cases (we are getting close), but until we narrow down the libraries used in the default handling I think it makes sense to require DifferentialEquations.jl, but that makes it not my priority right now (though I'd like to see it)
Well, it's good news for me if it's (likely to) going to happen eventually.