diff --git a/Project.toml b/Project.toml index b0dc8ad39..abe799aaa 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SciMLBase" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" authors = ["Chris Rackauckas and contributors"] -version = "2.50.5" +version = "2.52.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/src/alg_traits.jl b/src/alg_traits.jl index 13eefffd3..b429d78e9 100644 --- a/src/alg_traits.jl +++ b/src/alg_traits.jl @@ -263,3 +263,25 @@ function is not a function of `u`. Defaults to false """ requires_additive_noise(alg::AbstractSDEAlgorithm) = false + +EnumX.@enumx AlgorithmInterpretation Ito Stratonovich + +""" + alg_interpretation(alg) + +Integral interpolation for the SDE solver algorithm. SDEs solutions depend on the chosen definition of the stochastic integral. In the Ito calculus, +the left-hand rule is taken, while Stratonovich calculus uses the right-hand rule. Unlike in standard Riemannian integration, these integral rules do +not converge to the same answer. In the context of a stochastic differential equation, the underlying solution (and its mean, variance, etc.) is dependent +on the integral rule that is chosen. This trait describes which interpretation the solver algorithm subscribes to, and thus whether the solution should +be interpreted as the solution to the SDE under the Ito or Stratonovich interpretation. + +For more information, see https://oatml.cs.ox.ac.uk/blog/2022/03/22/ito-strat.html as a good high-level explanation. + +!!! note + + The expected solution statistics are dependent on this output. Solutions from solvers with different + interpretations are expected to have different answers on almost all SDEs without additive noise. +""" +function alg_interpretation(alg::AbstractSciMLAlgorithm) + error("Algorithm interpretation is not defined for this algorithm. It can be either `AlgorithmInterpretation.Ito` or `AlgorithmInterpretation.Stratonovich`") +end diff --git a/src/problems/dae_problems.jl b/src/problems/dae_problems.jl index 12525409a..6e91313fe 100644 --- a/src/problems/dae_problems.jl +++ b/src/problems/dae_problems.jl @@ -2,7 +2,7 @@ Defines an implicit ordinary differential equation (ODE) or differential-algebraic equation (DAE) problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/dae_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/dae_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/dae_types/) ## Mathematical Specification of an DAE Problem diff --git a/src/problems/dde_problems.jl b/src/problems/dde_problems.jl index e31e57ae0..750083975 100644 --- a/src/problems/dde_problems.jl +++ b/src/problems/dde_problems.jl @@ -6,7 +6,7 @@ struct StandardDDEProblem end @doc doc""" Defines a delay differential equation (DDE) problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/dde_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/dde_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/dde_types/) ## Mathematical Specification of a DDE Problem diff --git a/src/problems/discrete_problems.jl b/src/problems/discrete_problems.jl index 9e194504d..8d89e4779 100644 --- a/src/problems/discrete_problems.jl +++ b/src/problems/discrete_problems.jl @@ -4,7 +4,7 @@ const DISCRETE_OUTOFPLACE_DEFAULT = DiscreteFunction{false}((u, p, t) -> u) @doc doc""" Defines a discrete dynamical system problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/discrete_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/discrete_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/discrete_types/) ## Mathematical Specification of a Discrete Problem diff --git a/src/problems/implicit_discrete_problems.jl b/src/problems/implicit_discrete_problems.jl index 314604ca5..4df3e6ea7 100644 --- a/src/problems/implicit_discrete_problems.jl +++ b/src/problems/implicit_discrete_problems.jl @@ -1,7 +1,7 @@ @doc doc""" Defines a discrete dynamical system problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/discrete_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/discrete_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/discrete_types/) ## Mathematical Specification of a ImplicitDiscrete Problem diff --git a/src/problems/integral_problems.jl b/src/problems/integral_problems.jl index e68b764ea..b3087ae4b 100644 --- a/src/problems/integral_problems.jl +++ b/src/problems/integral_problems.jl @@ -1,7 +1,7 @@ @doc doc""" Defines an integral problem. -Documentation Page: https://docs.sciml.ai/Integrals/stable/ +Documentation Page: [https://docs.sciml.ai/Integrals/stable/](https://docs.sciml.ai/Integrals/stable/) ## Mathematical Specification of an Integral Problem diff --git a/src/problems/linear_problems.jl b/src/problems/linear_problems.jl index ebb5e3c97..a723ee3f7 100644 --- a/src/problems/linear_problems.jl +++ b/src/problems/linear_problems.jl @@ -1,7 +1,7 @@ @doc doc""" Defines a linear system problem. -Documentation Page: https://docs.sciml.ai/LinearSolve/stable/basics/LinearProblem/ +Documentation Page: [https://docs.sciml.ai/LinearSolve/stable/basics/LinearProblem/](https://docs.sciml.ai/LinearSolve/stable/basics/LinearProblem/) ## Mathematical Specification of a Linear Problem diff --git a/src/problems/ode_problems.jl b/src/problems/ode_problems.jl index db8ec87b7..bb228e84d 100644 --- a/src/problems/ode_problems.jl +++ b/src/problems/ode_problems.jl @@ -6,7 +6,7 @@ struct StandardODEProblem end @doc doc""" Defines an ordinary differential equation (ODE) problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/ode_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/ode_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/ode_types/) ## Mathematical Specification of an ODE Problem diff --git a/src/problems/optimization_problems.jl b/src/problems/optimization_problems.jl index 0be3f9245..176f9f116 100644 --- a/src/problems/optimization_problems.jl +++ b/src/problems/optimization_problems.jl @@ -3,7 +3,7 @@ @doc doc""" Defines an optimization problem. -Documentation Page: https://docs.sciml.ai/Optimization/stable/API/optimization_problem/ +Documentation Page: [https://docs.sciml.ai/Optimization/stable/API/optimization_problem/](https://docs.sciml.ai/Optimization/stable/API/optimization_problem/) ## Mathematical Specification of an Optimization Problem diff --git a/src/problems/rode_problems.jl b/src/problems/rode_problems.jl index fa0233647..479888f75 100644 --- a/src/problems/rode_problems.jl +++ b/src/problems/rode_problems.jl @@ -1,7 +1,7 @@ @doc doc""" Defines a random ordinary differential equation (RODE) problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/rode_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/rode_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/rode_types/) ## Mathematical Specification of a RODE Problem diff --git a/src/problems/sdde_problems.jl b/src/problems/sdde_problems.jl index 5de0b257c..cfcf1aec5 100644 --- a/src/problems/sdde_problems.jl +++ b/src/problems/sdde_problems.jl @@ -1,7 +1,7 @@ @doc doc""" Defines a stochastic delay differential equation (SDDE) problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/sdde_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/sdde_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/sdde_types/) ## Mathematical Specification of a Stochastic Delay Differential Equation (SDDE) Problem diff --git a/src/problems/sde_problems.jl b/src/problems/sde_problems.jl index a8ad1b982..60017f740 100644 --- a/src/problems/sde_problems.jl +++ b/src/problems/sde_problems.jl @@ -6,7 +6,7 @@ struct StandardSDEProblem end @doc doc""" Defines an stochastic differential equation (SDE) problem. -Documentation Page: https://docs.sciml.ai/DiffEqDocs/stable/types/sde_types/ +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/sde_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/sde_types/) ## Mathematical Specification of a SDE Problem diff --git a/src/solutions/rode_solutions.jl b/src/solutions/rode_solutions.jl index f1fe04972..340cde11a 100644 --- a/src/solutions/rode_solutions.jl +++ b/src/solutions/rode_solutions.jl @@ -51,6 +51,24 @@ struct RODESolution{T, N, uType, uType2, DType, tType, randType, P, A, IType, S, seed::UInt64 end +function ConstructionBase.constructorof(::Type{O}) where {T, N, O <: RODESolution{T, N}} + RODESolution{T, N} +end + +function ConstructionBase.setproperties(sol::RODESolution, patch::NamedTuple) + u = get(patch, :u, sol.u) + N = u === nothing ? 2 : ndims(eltype(u)) + 1 + T = eltype(eltype(u)) + patch = merge(getproperties(sol), patch) + return RODESolution{ + T, N, typeof(patch.u), typeof(patch.u_analytic), typeof(patch.errors), + typeof(patch.t), typeof(patch.W), typeof(patch.prob), typeof(patch.alg), typeof(patch.interp), + typeof(patch.stats), typeof(patch.alg_choice)}( + patch.u, patch.u_analytic, patch.errors, patch.t, patch.W, + patch.prob, patch.alg, patch.interp, patch.dense, patch.tslocation, patch.stats, + patch.alg_choice, patch.retcode, patch.seed) +end + Base.@propagate_inbounds function Base.getproperty(x::AbstractRODESolution, s::Symbol) if s === :destats Base.depwarn("`sol.destats` is deprecated. Use `sol.stats` instead.", "sol.destats") diff --git a/src/utils.jl b/src/utils.jl index c60634a59..ecded5af1 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -216,7 +216,9 @@ function Base.showerror(io::IO, e::FunctionArgumentsError) end """ - isinplace(f, inplace_param_number[,fname="f"]) + isinplace(f, inplace_param_number, fname = "f", iip_preferred = true; + has_two_dispatches = true, + outofplace_param_number = inplace_param_number - 1) isinplace(f::AbstractSciMLFunction[, inplace_param_number]) Check whether a function operates in place by comparing its number of arguments @@ -224,7 +226,8 @@ to the expected number. If `f` is an `AbstractSciMLFunction`, then the type parameter is assumed to be correct and is used. Otherwise `inplace_param_number` is checked against the methods table, where `inplace_param_number` is the number of arguments for the in-place dispatch. The out-of-place dispatch is assumed -to have one less. If neither of these dispatches exist, an error is thrown. +to have `outofplace_param_number` parameters (one less than the inplace version +by default). If neither of these dispatches exist, an error is thrown. If the error is thrown, `fname` is used to tell the user which function has the incorrect dispatches. @@ -241,19 +244,20 @@ form is disabled and the 2-argument signature is ensured to be matched. - [`numargs`](@ref numargs) """ function isinplace(f, inplace_param_number, fname = "f", iip_preferred = true; - has_two_dispatches = true, isoptimization = false) + has_two_dispatches = true, isoptimization = false, + outofplace_param_number = inplace_param_number - 1) nargs = numargs(f) iip_dispatch = any(x -> x == inplace_param_number, nargs) - oop_dispatch = any(x -> x == inplace_param_number - 1, nargs) + oop_dispatch = any(x -> x == outofplace_param_number, nargs) if length(nargs) == 0 throw(NoMethodsError(fname)) end if !iip_dispatch && !oop_dispatch && !isoptimization - if all(x -> x > inplace_param_number, nargs) + if all(>(inplace_param_number), nargs) throw(TooManyArgumentsError(fname, f)) - elseif all(x -> x < inplace_param_number - 1, nargs) && has_two_dispatches + elseif all(<(outofplace_param_number), nargs) && has_two_dispatches # Possible extra safety? # Find if there's a `f(args...)` dispatch # If so, no error diff --git a/test/function_building_error_messages.jl b/test/function_building_error_messages.jl index 3437bf106..ee7ee4af7 100644 --- a/test/function_building_error_messages.jl +++ b/test/function_building_error_messages.jl @@ -24,6 +24,13 @@ f = Foo{1}() (this::Foo{T})(args...) where {T} = 1 @test SciMLBase.isinplace(Foo{Int}(), 4) +@testset "isinplace accepts an out-of-place version with different numbers of parameters " begin + f1(u) = 2 * u + @test !isinplace(f1, 2) + @test_throws SciMLBase.TooFewArgumentsError SciMLBase.isinplace(f1, 4) + @test !isinplace(f1, 4; outofplace_param_number = 1) +end + ## Problem argument tests ftoomany(u, p, t, x, y) = 2u