diff --git a/Project.toml b/Project.toml index 014e88dd5..a219d92fa 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,7 @@ DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" IteratorInterfaceExtensions = "82899510-4779-5014-852e-03e436cf321d" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index 60e184a8a..aaae47cf9 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -7,6 +7,7 @@ using LinearAlgebra using Statistics using Distributed using StaticArrays +using Markdown import Logging, ArrayInterface import IteratorInterfaceExtensions diff --git a/src/problems/bvp_problems.jl b/src/problems/bvp_problems.jl index eb067092f..77d4450c0 100644 --- a/src/problems/bvp_problems.jl +++ b/src/problems/bvp_problems.jl @@ -3,8 +3,73 @@ $(TYPEDEF) """ struct StandardBVProblem end -""" +@doc doc""" $(TYPEDEF) + +Defines an BVP problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/bvp_types/ + +## Mathematical Specification of a BVP Problem + +To define a BVP Problem, you simply need to give the function ``f`` and the initial +condition ``u₀`` which define an ODE: + +```math +\frac{du}{dt} = f(u,p,t) +``` + +along with an implicit function `bc!` which defines the residual equation, where + +```math +bc(u,p,t) = 0 +``` + +is the manifold on which the solution must live. A common form for this is the +two-point `BVProblem` where the manifold defines the solution at two points: + +```math +u(t_0) = a +u(t_f) = b +``` + +## Problem Type + +### Constructors + +```julia +TwoPointBVProblem{isinplace}(f,bc!,u0,tspan,p=NullParameters();kwargs...) +BVProblem{isinplace}(f,bc!,u0,tspan,p=NullParameters();kwargs...) +``` + +For any BVP problem type, `bc!` is the inplace function: + +```julia +bc!(residual, u, p, t) +``` + +where `residual` computed from the current `u`. `u` is an array of solution values +where `u[i]` is at time `t[i]`, while `p` are the parameters. For a `TwoPointBVProblem`, +`t = tspan`. For the more general `BVProblem`, `u` can be all of the internal +time points, and for shooting type methods `u=sol` the ODE solution. +Note that all features of the `ODESolution` are present in this form. +In both cases, the size of the residual matches the size of the initial condition. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +### Fields + +* `f`: The function for the ODE. +* `bc`: The boundary condition function. +* `u0`: The initial condition. Either the initial condition for the ODE as an + initial value problem, or a `Vector` of values for ``u(t_i)`` for collocation + methods +* `tspan`: The timespan for the problem. +* `p`: The parameters for the problem. Defaults to `NullParameters` +* `kwargs`: The keyword arguments passed onto the solves. """ struct BVProblem{uType,tType,isinplace,P,F,bF,PT,K} <: AbstractBVProblem{uType,tType,isinplace} f::F diff --git a/src/problems/dae_problems.jl b/src/problems/dae_problems.jl index dc8653207..d3c3fdd90 100644 --- a/src/problems/dae_problems.jl +++ b/src/problems/dae_problems.jl @@ -1,6 +1,70 @@ -# f(t,u,du,res) = 0 -""" +@doc doc""" $(TYPEDEF) + +Defines an implicit ordinary differential equation (ODE) or +differential-algebraic equation (DAE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/dae_types/ + +## Mathematical Specification of an DAE Problem + +To define a DAE Problem, you simply need to give the function ``f`` and the initial +condition ``u₀`` which define an ODE: + +```math +0 = f(du,u,p,t) +``` + +`f` should be specified as `f(du,u,p,t)` (or in-place as `f(resid,du,u,p,t)`). +Note that we are not limited to numbers or vectors for `u₀`; one is allowed to +provide `u₀` as arbitrary matrices / higher dimension tensors as well. + +## Problem Type + +### Constructors + +- `DAEProblem(f::DAEFunction,du0,u0,tspan,p=NullParameters();kwargs...)` +- `DAEProblem{isinplace}(f,du0,u0,tspan,p=NullParameters();kwargs...)` : + Defines the DAE with the specified functions. + `isinplace` optionally sets whether the function is inplace or not. This is + determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the +[DiffEqFunctions](@ref performance_overloads) +page. + +### Fields + +* `f`: The function in the ODE. +* `du0`: The initial condition for the derivative. +* `u0`: The initial condition. +* `tspan`: The timespan for the problem. +* `differential_vars`: A logical array which declares which variables are the + differential (non algebraic) vars (i.e. `du'` is in the equations for this + variable). Defaults to nothing. Some solvers may require this be set if an + initial condition needs to be determined. +* `p`: The parameters for the problem. Defaults to `NullParameters` +* `kwargs`: The keyword arguments passed onto the solves. + +## Example Problems + +Examples problems can be found in [DiffEqProblemLibrary.jl](https://github.com/JuliaDiffEq/DiffEqProblemLibrary.jl/blob/master/src/dae_premade_problems.jl). + +To use a sample problem, such as `prob_dae_resrob`, you can do something like: + +```julia +#] add DiffEqProblemLibrary +using DiffEqProblemLibrary.DAEProblemLibrary +# load problems +DAEProblemLibrary.importdaeproblems() +prob = DAEProblemLibrary.prob_dae_resrob +sol = solve(prob,IDA()) +``` """ struct DAEProblem{uType,duType,tType,isinplace,P,F,K,D} <: AbstractDAEProblem{uType,duType,tType,isinplace} f::F diff --git a/src/problems/dde_problems.jl b/src/problems/dde_problems.jl index 1d60be1c8..df729c094 100644 --- a/src/problems/dde_problems.jl +++ b/src/problems/dde_problems.jl @@ -3,8 +3,201 @@ $(TYPEDEF) """ struct StandardDDEProblem end -""" +@doc doc""" $(TYPEDEF) + +Defines a delay differential equation (DDE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/dde_types/ + +## Mathematical Specification of a DDE Problem + +To define a DDE Problem, you simply need to give the function ``f``, the initial +condition ``u_0`` at time point ``t_0``, and the history function ``h`` +which together define a DDE: + +```math +\frac{du}{dt} = f(u,h,p,t) \qquad (t \geq t_0) +``` +```math +u(t_0) = u_0, +``` +```math +u(t) = h(t) \qquad (t < t_0). +``` + +``f`` should be specified as `f(u, h, p, t)` (or in-place as `f(du, u, h, p, t)`), +``u_0`` should be an AbstractArray (or number) whose geometry matches the +desired geometry of `u`, and ``h`` should be specified as described below. The +history function `h` is accessed for all delayed values. Note that we are not +limited to numbers or vectors for ``u_0``; one is allowed to provide ``u_0`` +as arbitrary matrices / higher dimension tensors as well. + +## Functional Forms of the History Function + +The history function `h` can be called in the following ways: + +- `h(p, t)`: out-of-place calculation +- `h(out, p, t)`: in-place calculation +- `h(p, t, deriv::Type{Val{i}})`: out-of-place calculation of the `i`th derivative +- `h(out, p, t, deriv::Type{Val{i}})`: in-place calculation of the `i`th derivative +- `h(args...; idxs)`: calculation of `h(args...)` for indices `idxs` + +Note that a dispatch for the supplied history function of matching form is required +for whichever function forms are used in the user derivative function `f`. + +## Declaring Lags + +Lags are declared separately from their use. One can use any lag by simply using +the interpolant of `h` at that point. However, one should use caution in order +to achieve the best accuracy. When lags are declared, the solvers can more +efficiently be more accurate and thus this is recommended. + +## Neutral and Retarded Delay Differential Equations + +Note that the history function specification can be used to specify general +retarded arguments, i.e. `h(p,α(u,t))`. Neutral delay differential equations +can be specified by using the `deriv` value in the history interpolation. +For example, `h(p,t-τ, Val{1})` returns the first derivative of the history +values at time `t-τ`. + +Note that algebraic equations can be specified by using a singular mass matrix. + +## Problem Type + +### Constructors + +``` +DDEProblem(f[, u0], h, tspan[, p]; ) +DDEProblem{isinplace}(f[, u0], h, tspan[, p]; ) +``` + +Parameter `isinplace` optionally sets whether the function is inplace or not. +This is determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the [DiffEqFunctions](@ref performance_overloads) page. + +### Arguments + +* `f`: The function in the DDE. +* `u0`: The initial condition. Defaults to the value `h(p, first(tspan))` of the history function evaluated at the initial time point. +* `h`: The history function for the DDE before `t0`. +* `tspan`: The timespan for the problem. +* `p`: The parameters with which function `f` is called. Defaults to `NullParameters`. +* `constant_lags`: A collection of constant lags used by the history function `h`. Defaults to `()`. +* `dependent_lags` A tuple of functions `(u, p, t) -> lag` for the state-dependent lags + used by the history function `h`. Defaults to `()`. +* `neutral`: If the DDE is neutral, i.e., if delays appear in derivative terms. +* `order_discontinuity_t0`: The order of the discontinuity at the initial time point. Defaults to `0` if an initial condition `u0` is provided. Otherwise it is forced to be greater or equal than `1`. +* `kwargs`: The keyword arguments passed onto the solves. + +## Dynamical Delay Differential Equations + +Much like [Dynamical ODEs](@ref dynamical_prob), a Dynamical DDE is a Partitioned DDE +of the form: + +```math +\frac{dv}{dt} = f_1(u,t,h) \\ +\frac{du}{dt} = f_2(v,h) \\ +``` + +### Constructors + +``` +DynamicalDDEProblem(f1, f2[, v0, u0], h, tspan[, p]; ) +DynamicalDDEProblem{isinplace}(f1, f2[, v0, u0], h, tspan[, p]; ) +``` +Parameter `isinplace` optionally sets whether the function is inplace or not. +This is determined automatically, but not inferred. + +### Arguments + +* `f`: The function in the DDE. +* `v0` and `u0`: The initial condition. Defaults to the values `h(p, first(tspan))...` of the history function evaluated at the initial time point. +* `h`: The history function for the DDE before `t0`. Must return an object with the indices 1 and 2, with the values of `v` and `u` respectively. +* `tspan`: The timespan for the problem. +* `p`: The parameters with which function `f` is called. Defaults to `NullParameters`. +* `constant_lags`: A collection of constant lags used by the history function `h`. Defaults to `()`. +* `dependent_lags` A tuple of functions `(v, u, p, t) -> lag` for the state-dependent lags + used by the history function `h`. Defaults to `()`. +* `neutral`: If the DDE is neutral, i.e., if delays appear in derivative terms. +* `order_discontinuity_t0`: The order of the discontinuity at the initial time point. Defaults to `0` if an initial condition `u0` is provided. Otherwise it is forced to be greater or equal than `1`. +* `kwargs`: The keyword arguments passed onto the solves. + +The for dynamical and second order DDEs, the history function will return an object with +the indicies 1 and 2 defined, where `h(p, t_prev)[1]` is the value of ``f_2(v, u, h, p, +t_{\mathrm{prev}})`` and `h(p, t_prev)[2]` is the value of ``f_1(v, u, h, p, t_{\mathrm{prev}})`` +(this is for consistency with the ordering of the intitial conditions in the constructor). +The supplied history function must also return such a 2-index object, which can be accomplished +with a tuple `(v,u)` or vector `[v,u]`. + +## 2nd Order Delay Differential Equations + +To define a 2nd Order DDE Problem, you simply need to give the function ``f`` +and the initial condition ``u_0`` which define an DDE: + +```math +u'' = f(u',u,h,p,t) +``` + +`f` should be specified as `f(du,u,p,t)` (or in-place as `f(ddu,du,u,p,t)`), and `u₀` +should be an AbstractArray (or number) whose geometry matches the desired +geometry of `u`. Note that we are not limited to numbers or vectors for `u₀`; +one is allowed to provide `u₀` as arbitrary matrices / higher dimension tensors +as well. + +From this form, a dynamical ODE: + +```math +v' = f(v,u,h,p,t) \\ +u' = v \\ +``` + +### Constructors + +``` +SecondOrderDDEProblem(f, [, du0, u0], h, tspan[, p]; ) +SecondOrderDDEProblem{isinplace}(f, [, du0, u0], h, tspan[, p]; ) +``` + +Parameter `isinplace` optionally sets whether the function is inplace or not. +This is determined automatically, but not inferred. + +### Arguments + +* `f`: The function in the DDE. +* `du0` and `u0`: The initial condition. Defaults to the values `h(p, first(tspan))...` of the history function evaluated at the initial time point. +* `h`: The history function for the DDE before `t0`. Must return an object with the indices 1 and 2, with the values of `v` and `u` respectively. +* `tspan`: The timespan for the problem. +* `p`: The parameters with which function `f` is called. Defaults to `NullParameters`. +* `constant_lags`: A collection of constant lags used by the history function `h`. Defaults to `()`. +* `dependent_lags` A tuple of functions `(v, u, p, t) -> lag` for the state-dependent lags + used by the history function `h`. Defaults to `()`. +* `neutral`: If the DDE is neutral, i.e., if delays appear in derivative terms. +* `order_discontinuity_t0`: The order of the discontinuity at the initial time point. Defaults to `0` if an initial condition `u0` is provided. Otherwise it is forced to be greater or equal than `1`. +* `kwargs`: The keyword arguments passed onto the solves. + +As above, the history function will return an object with indices 1 and 2, with the values of `du` and `u` respectively. The supplied history function must also match this return type, e.g. by returning a 2-element tuple or vector. + +## Example Problems + +Example problems can be found in [DiffEqProblemLibrary.jl](https://github.com/JuliaDiffEq/DiffEqProblemLibrary.jl/tree/master/src/dde). + +To use a sample problem, such as `prob_ode_linear`, you can do something like: + +```julia +#] add DiffEqProblemLibrary +using DiffEqProblemLibrary.ODEProblemLibrary +# load problems +ODEProblemLibrary.importodeproblems() +prob = ODEProblemLibrary.prob_ode_linear +sol = solve(prob) +``` """ struct DDEProblem{uType,tType,lType,lType2,isinplace,P,F,H,K,PT} <: AbstractDDEProblem{uType,tType,lType,isinplace} diff --git a/src/problems/discrete_problems.jl b/src/problems/discrete_problems.jl index 8ecc275f2..f4bb990d5 100644 --- a/src/problems/discrete_problems.jl +++ b/src/problems/discrete_problems.jl @@ -1,14 +1,68 @@ const DISCRETE_INPLACE_DEFAULT = convert(DiscreteFunction{true},(du,u,p,t) -> du.=u) const DISCRETE_OUTOFPLACE_DEFAULT = convert(DiscreteFunction{false},(u,p,t) -> u) -""" +@doc doc""" $(TYPEDEF) -Defines a discrete problem. +Defines a discrete dynamical system problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/discrete_types/ + +## Mathematical Specification of a Discrete Problem + +To define an Discrete Problem, you simply need to give the function ``f`` and the initial +condition ``u₀`` which define a function map: + +```math +u_{n+1} = f(u_{n},p,t_{n+1}) +``` + +`f` should be specified as `f(un,p,t)` (or in-place as `f(unp1,un,p,t)`), and `u₀` should +be an AbstractArray (or number) whose geometry matches the desired geometry of `u`. +Note that we are not limited to numbers or vectors for `u₀`; one is allowed to +provide `u₀` as arbitrary matrices / higher dimension tensors as well. ``u_{n+1}`` only depends on the previous +iteration ``u_{n}`` and ``t_{n+1}``. The default ``t_{n+1}`` of `FunctionMap` is +``t_n = t_0 + n*dt`` (with `dt=1` being the default). For continuous-time Markov chains +this is the time at which the change is occuring. + +Note that if the discrete solver is set to have `scale_by_time=true`, then the problem +is interpreted as the map: + +```math +u_{n+1} = u_n + dt f(u_{n},p,t_{n+1}) +``` -# Fields +## Problem Type + +### Constructors + +- `DiscreteProblem{isinplace}(f::ODEFunction,u0,tspan,p=NullParameters();kwargs...)` : + Defines the discrete problem with the specified functions. +- `DiscreteProblem{isinplace}(f,u0,tspan,p=NullParameters();kwargs...)` : + Defines the discrete problem with the specified functions. +- `DiscreteProblem{isinplace}(u0,tspan,p=NullParameters();kwargs...)` : + Defines the discrete problem with the identity map. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the +[DiffEqFunctions](@ref performance_overloads) +page. + +### Fields $(FIELDS) + +#### Note About Timing + +Note that if no `dt` and not `tstops` is given, it's assumed that `dt=1` and thus +`tspan=(0,n)` will solve for `n` iterations. If in the solver `dt` is given, then +the number of iterations will change. And if `tstops` is not empty, the solver will +revert to the standard behavior of fixed timestep methods, which is "step to each +tstop". """ struct DiscreteProblem{uType,tType,isinplace,P,F,K} <: AbstractDiscreteProblem{uType,tType,isinplace} """The function in the map.""" diff --git a/src/problems/ode_problems.jl b/src/problems/ode_problems.jl index ae5aaf6f9..fe404c110 100644 --- a/src/problems/ode_problems.jl +++ b/src/problems/ode_problems.jl @@ -3,19 +3,72 @@ $(TYPEDEF) """ struct StandardODEProblem end -# Mu' = f -""" +@doc doc""" $(TYPEDEF) -Defines an ODE problem. +Defines an ordinary differential equation (ODE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/ode_types/ + +## Mathematical Specification of an ODE Problem + +To define an ODE Problem, you simply need to give the function ``f`` and the initial +condition ``u₀`` which define an ODE: + +```math +\frac{du}{dt} = f(u,p,t) +``` + +There are two different ways of specifying `f`: +- `f(du,u,p,t)`: in-place. Memory-efficient when avoiding allocations. Best option for most cases unless mutation is not allowed. +- `f(u,p,t)`: returning `du`. Less memory-efficient way, particularly suitable when mutation is not allowed (e.g. with certain automatic differentiation packages such as Zygote). + +`u₀` should be an AbstractArray (or number) whose geometry matches the desired geometry of `u`. +Note that we are not limited to numbers or vectors for `u₀`; one is allowed to +provide `u₀` as arbitrary matrices / higher dimension tensors as well. + +## Problem Type + +### Constructors -# Fields +`ODEProblem` can be constructed by first building an `ODEFunction` or +by simply passing the ODE right-hand side to the constructor. The constructors +are: + +- `ODEProblem(f::ODEFunction,u0,tspan,p=NullParameters();kwargs...)` +- `ODEProblem{isinplace}(f,u0,tspan,p=NullParameters();kwargs...)` : + Defines the ODE with the specified functions. `isinplace` optionally sets whether + the function is inplace or not. This is determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the `ODEFunction` documentation. + +### Fields $(FIELDS) + +## Example Problems + +Example problems can be found in [DiffEqProblemLibrary.jl](https://github.com/JuliaDiffEq/DiffEqProblemLibrary.jl/tree/master/src/ode). + +To use a sample problem, such as `prob_ode_linear`, you can do something like: + +```julia +#] add DiffEqProblemLibrary +using DiffEqProblemLibrary.ODEProblemLibrary +# load problems +ODEProblemLibrary.importodeproblems() +prob = ODEProblemLibrary.prob_ode_linear +sol = solve(prob) +``` """ struct ODEProblem{uType,tType,isinplace,P,F,K,PT} <: AbstractODEProblem{uType,tType,isinplace} - """The ODE is `du/dt = f(u,p,t)`.""" + """The ODE is `du = f(u,p,t)` for out-of-place and f(du,u,p,t) for in-place.""" f::F """The initial condition is `u(tspan[1]) = u0`.""" u0::uType @@ -25,8 +78,8 @@ struct ODEProblem{uType,tType,isinplace,P,F,K,PT} <: p::P """A callback to be applied to every solver which uses the problem.""" kwargs::K - # TODO problem_type::PT + """An internal argument for storing traits about the solving process.""" @add_kwonly function ODEProblem{iip}(f::AbstractODEFunction{iip}, u0,tspan,p=NullParameters(), problem_type=StandardODEProblem(); @@ -99,20 +152,63 @@ function DynamicalODEProblem(f1,f2,du0,u0,tspan,p=NullParameters();kwargs...) ODEProblem(DynamicalODEFunction(f1,f2),ArrayPartition(du0,u0),tspan,p;kwargs...) end -""" - DynamicalODEProblem{isinplace}(f1,f2,v0,u0,tspan,p=NullParameters(),callback=CallbackSet()) +@doc doc""" +$(TYPEDEF) + +Defines an dynamical ordinary differential equation (ODE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/dynamical_types/ + +Dynamical ordinary differential equations, such as those arising from the definition +of a Hamiltonian system or a second order ODE, have a special structure that can be +utilized in the solution of the differential equation. On this page we describe +how to define second order differential equations for their efficient numerical solution. + +## Mathematical Specification of a Dynamical ODE Problem + +These algorithms require a Partitioned ODE of the form: + +```math +\frac{dv}{dt} = f_1(u,t) \\ +\frac{du}{dt} = f_2(v) \\ +``` +This is a Partitioned ODE partitioned into two groups, so the functions should be +specified as `f1(dv,v,u,p,t)` and `f2(du,v,u,p,t)` (in the inplace form), where `f1` +is independent of `v` (unless specified by the solver), and `f2` is independent +of `u` and `t`. This includes discretizations arising from +`SecondOrderODEProblem`s where the velocity is not used in the acceleration function, +and Hamiltonians where the potential is (or can be) time-dependent but the kinetic +energy is only dependent on `v`. -Define a dynamical ODE problem from the two functions `f1` and `f2`. +Note that some methods assume that the integral of `f2` is a quadratic form. That +means that `f2=v'*M*v`, i.e. ``\int f_2 = \frac{1}{2} m v^2``, giving `du = v`. +This is equivalent to saying that the kinetic energy is related to ``v^2``. The +methods which require this assumption will lose accuracy if this assumption is +violated. Methods listed make note of this requirement with "Requires +quadratic kinetic energy". + +### Constructor + +```julia +DynamicalODEProblem(f::DynamicalODEFunction,v0,u0,tspan,p=NullParameters();kwargs...) +DynamicalODEProblem{isinplace}(f1,f2,v0,u0,tspan,p=NullParameters();kwargs...) +``` + +Defines the ODE with the specified functions. `isinplace` optionally sets whether +the function is inplace or not. This is determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +### Fields -# Arguments * `f1` and `f2`: The functions in the ODE. * `v0` and `u0`: The initial conditions. * `tspan`: The timespan for the problem. -* `p`: Parameter values for `f1` and `f2`. -* `callback`: A callback to be applied to every solver which uses the problem. Defaults to nothing. - -`isinplace` optionally sets whether the function is inplace or not. -This is determined automatically, but not inferred. +* `p`: The parameters for the problem. Defaults to `NullParameters` +* `kwargs`: The keyword arguments passed onto the solves. """ function DynamicalODEProblem{iip}(f1,f2,du0,u0,tspan,p=NullParameters();kwargs...) where iip ODEProblem(DynamicalODEFunction{iip}(f1,f2),ArrayPartition(du0,u0),tspan,p,DynamicalODEProblem{iip}();kwargs...) @@ -128,17 +224,52 @@ function SecondOrderODEProblem(f,du0,u0,tspan,p=NullParameters();kwargs...) SecondOrderODEProblem{iip}(f,du0,u0,tspan,p;kwargs...) end -""" - SecondOrderODEProblem{isinplace}(f,du0,u0,tspan,p=NullParameters(),callback=CallbackSet()) +@doc doc""" +$(TYPEDEF) + +Defines a second order ordinary differential equation (ODE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/dynamical_types/ + +## Mathematical Specification of a 2nd Order ODE Problem + +To define a 2nd Order ODE Problem, you simply need to give the function ``f`` +and the initial condition ``u_0`` which define an ODE: + +```math +u'' = f(u',u,p,t) +``` + +`f` should be specified as `f(du,u,p,t)` (or in-place as `f(ddu,du,u,p,t)`), and `u₀` +should be an AbstractArray (or number) whose geometry matches the desired +geometry of `u`. Note that we are not limited to numbers or vectors for `u₀`; +one is allowed to provide `u₀` as arbitrary matrices / higher dimension tensors +as well. + +From this form, a dynamical ODE: + +```math +v' = f(v,u,p,t) \\ +u' = v \\ +``` -Define a second order ODE problem with the specified function. +is generated. + +### Constructors + +```julia +SecondOrderODEProblem{isinplace}(f,du0,u0,tspan,callback=CallbackSet()) +``` + +Defines the ODE with the specified functions. + +### Fields -# Arguments * `f`: The function for the second derivative. * `du0`: The initial derivative. * `u0`: The initial condition. * `tspan`: The timespan for the problem. -* `callback`: A callback to be applied to every solver which uses the problem. Defaults to nothing. +* `callback`: A callback to be applied to every solver which uses the problem. + Defaults to nothing. """ function SecondOrderODEProblem{iip}(f,du0,u0,tspan,p=NullParameters();kwargs...) where iip if iip @@ -189,22 +320,68 @@ function SplitODEProblem(f1,f2,u0,tspan,p=NullParameters();kwargs...) f = SplitFunction(f1,f2) SplitODEProblem(f,u0,tspan,p;kwargs...) end -""" - SplitODEProblem{isinplace}(f1,f2,u0,tspan,p=NullParameters();kwargs...) -Define a split ODE problem from separate functions `f1` and `f2`. +@doc doc""" +$(TYPEDEF) + +Defines a split ordinary differential equation (ODE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/split_ode_types/ + +## Mathematical Specification of a Split ODE Problem + +To define a `SplitODEProblem`, you simply need to give a two functions +``f_1`` and ``f_2`` along with an initial condition ``u₀`` which +define an ODE: + +```math +\frac{du}{dt} = f_1(u,p,t) + f_2(u,p,t) +``` + +`f` should be specified as `f(u,p,t)` (or in-place as `f(du,u,p,t)`), and `u₀` should +be an AbstractArray (or number) whose geometry matches the desired geometry of `u`. +Note that we are not limited to numbers or vectors for `u₀`; one is allowed to +provide `u₀` as arbitrary matrices / higher dimension tensors as well. + +Many splits are at least partially linear. That is the equation: + +```math +\frac{du}{dt} = Au + f_2(u,p,t) +``` + +For how to define a linear function `A`, see the documentation for the [DiffEqOperators](@ref). + +### Constructors + +```julia +SplitODEProblem(f::SplitFunction,u0,tspan,p=NullParameters();kwargs...) +SplitODEProblem{isinplace}(f1,f2,u0,tspan,p=NullParameters();kwargs...) +``` + +The `isinplace` parameter can be omitted and will be determined using the signature of `f2`. +Note that both `f1` and `f2` should support the in-place style if `isinplace` is `true` or they +should both support the out-of-place style if `isinplace` is `false`. You cannot mix up the two styles. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +Under the hood, a `SplitODEProblem` is just a regular `ODEProblem` whose `f` is a `SplitFunction`. +Therefore you can solve a `SplitODEProblem` using the same solvers for `ODEProblem`. For solvers +dedicated to split problems, see [Split ODE Solvers](@ref split_ode_solve). + +For specifying Jacobians and mass matrices, see the +[DiffEqFunctions](@ref performance_overloads) +page. + +### Fields -# Arguments * `f1`, `f2`: The functions in the ODE. * `u0`: The initial condition. * `tspan`: The timespan for the problem. -* `p`: The parameters for the problem. -* `callback`: A callback to be applied to every solver which uses the problem. Defaults to nothing. - -The `isinplace parameter` can be omitted and will be determined using the -signature of `f2`. Note that both `f1` and `f2` should support the in-place style if -`isinplace` is true or they should both support the out-of-place style if -`isinplace` is false. You cannot mix up the two styles. +* `p`: The parameters for the problem. Defaults to `NullParameters` +* `kwargs`: The keyword arguments passed onto the solves. """ function SplitODEProblem{iip}(f1,f2,u0,tspan,p=NullParameters();kwargs...) where iip f = SplitFunction{iip}(f1,f2) diff --git a/src/problems/rode_problems.jl b/src/problems/rode_problems.jl index 9df585b1a..147dea5f0 100644 --- a/src/problems/rode_problems.jl +++ b/src/problems/rode_problems.jl @@ -1,5 +1,55 @@ -""" +@doc doc""" $(TYPEDEF) + +Defines a random ordinary differential equation (RODE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/rode_types/ + +## Mathematical Specification of a RODE Problem + +To define a RODE Problem, you simply need to give the function ``f`` and the initial +condition ``u₀`` which define an ODE: + +```math +\frac{du}{dt} = f(u,p,t,W(t)) +``` + +where `W(t)` is a random process. `f` should be specified as `f(u,p,t,W)` +(or in-place as `f(du,u,p,t,W)`), and `u₀` should be an AbstractArray (or number) +whose geometry matches the desired geometry of `u`. Note that we are not limited +to numbers or vectors for `u₀`; one is allowed to provide `u₀` as arbitrary matrices +/ higher dimension tensors as well. + +### Constructors + +- `RODEProblem(f::RODEFunction,u0,tspan,p=NullParameters();noise=WHITE_NOISE,rand_prototype=nothing,callback=nothing)` +- `RODEProblem{isinplace}(f,u0,tspan,p=NullParameters();noise=WHITE_NOISE,rand_prototype=nothing,callback=nothing,mass_matrix=I)` : + Defines the RODE with the specified functions. The default noise is `WHITE_NOISE`. + `isinplace` optionally sets whether the function is inplace or not. This is + determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the +[DiffEqFunctions](@ref performance_overloads) +page. + +### Fields + +* `f`: The drift function in the SDE. +* `u0`: The initial condition. +* `tspan`: The timespan for the problem. +* `p`: The optional parameters for the problem. Defaults to `NullParameters`. +* `noise`: The noise process applied to the noise upon generation. Defaults to + Gaussian white noise. For information on defining different noise processes, + see [the noise process documentation page](@ref noise_process) +* `rand_prototype`: A prototype type instance for the noise vector. It defaults + to `nothing`, which means the problem should be interpreted as having a noise + vector whose size matches `u0`. +* `kwargs`: The keyword arguments passed onto the solves. """ mutable struct RODEProblem{uType,tType,isinplace,P,NP,F,K,ND} <: AbstractRODEProblem{uType,tType,isinplace,ND} f::F diff --git a/src/problems/sdde_problems.jl b/src/problems/sdde_problems.jl index 66df9ce4d..cafdbf3ec 100644 --- a/src/problems/sdde_problems.jl +++ b/src/problems/sdde_problems.jl @@ -1,5 +1,100 @@ -""" +@doc doc""" $(TYPEDEF) + +Defines a stochastic delay differential equation (SDDE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/sdde_types/ + +## Mathematical Specification of a Stochastic Delay Differential Equation (SDDE) Problem + +To define a SDDE Problem, you simply need to give the drift function ``f``, +the diffusion function `g`, the initial condition ``u_0`` at time point ``t_0``, +and the history function ``h`` which together define a SDDE: + +```math +du = f(u,h,p,t)dt + g(u,h,p,t)dW_t \qquad (t \geq t_0) +``` +```math +u(t_0) = u_0, +``` +```math +u(t) = h(t) \qquad (t < t_0). +``` + +``f`` should be specified as `f(u, h, p, t)` (or in-place as `f(du, u, h, p, t)`) +(and ``g`` should match). ``u_0`` should be an AbstractArray (or number) whose +geometry matches the desired geometry of `u`, and ``h`` should be specified as +described below. The history function `h` is accessed for all delayed values. +Note that we are not limited to numbers or vectors for ``u_0``; one is allowed +to provide ``u_0`` as arbitrary matrices / higher dimension tensors as well. + +Note that this functionality should be considered experimental. + +## Functional Forms of the History Function + +The history function `h` can be called in the following ways: + +- `h(p, t)`: out-of-place calculation +- `h(out, p, t)`: in-place calculation +- `h(p, t, deriv::Type{Val{i}})`: out-of-place calculation of the `i`th derivative +- `h(out, p, t, deriv::Type{Val{i}})`: in-place calculation of the `i`th derivative +- `h(args...; idxs)`: calculation of `h(args...)` for indices `idxs` + +Note that a dispatch for the supplied history function of matching form is required +for whichever function forms are used in the user derivative function `f`. + +## Declaring Lags + +Lags are declared separately from their use. One can use any lag by simply using +the interpolant of `h` at that point. However, one should use caution in order +to achieve the best accuracy. When lags are declared, the solvers can more +efficiently be more accurate and thus this is recommended. + +## Neutral, Retarded, and Algebraic Stochastic Delay Differential Equations + +Note that the history function specification can be used to specify general +retarded arguments, i.e. `h(p,α(u,t))`. Neutral delay differential equations +can be specified by using the `deriv` value in the history interpolation. +For example, `h(p,t-τ, Val{1})` returns the first derivative of the history +values at time `t-τ`. + +Note that algebraic equations can be specified by using a singular mass matrix. + +## Problem Type + +### Constructors + +``` +SDDEProblem(f,g[, u0], h, tspan[, p]; ) +SDDEProblem{isinplace}(f,g[, u0], h, tspan[, p]; ) +``` + +Parameter `isinplace` optionally sets whether the function is inplace or not. +This is determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the [DiffEqFunctions](@ref performance_overloads) page. + +### Arguments + +* `f`: The drift function in the SDDE. +* `g`: The diffusion function in the SDDE. +* `u0`: The initial condition. Defaults to the value `h(p, first(tspan))` of the history function evaluated at the initial time point. +* `h`: The history function for the DDE before `t0`. +* `tspan`: The timespan for the problem. +* `p`: The parameters with which function `f` is called. Defaults to `NullParameters`. +* `constant_lags`: A collection of constant lags used by the history function `h`. Defaults to `()`. +* `dependent_lags` A tuple of functions `(u, p, t) -> lag` for the state-dependent lags + used by the history function `h`. Defaults to `()`. +* `neutral`: If the DDE is neutral, i.e., if delays appear in derivative terms. +* `order_discontinuity_t0`: The order of the discontinuity at the initial time + point. Defaults to `0` if an initial condition `u0` is provided. Otherwise + it is forced to be greater or equal than `1`. +* `kwargs`: The keyword arguments passed onto the solves. """ struct SDDEProblem{uType,tType,lType,lType2,isinplace,P,NP,F,G,H,K,ND} <: AbstractSDDEProblem{uType,tType,lType,isinplace,ND} diff --git a/src/problems/sde_problems.jl b/src/problems/sde_problems.jl index efd2d84dc..88f28787e 100644 --- a/src/problems/sde_problems.jl +++ b/src/problems/sde_problems.jl @@ -3,8 +3,86 @@ $(TYPEDEF) """ struct StandardSDEProblem end -""" +@doc doc""" $(TYPEDEF) + +Defines an stochastic differential equation (SDE) problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/sde_types/ + +## Mathematical Specification of a SDE Problem + +To define an SDE Problem, you simply need to give the forcing function `f`, +the noise function `g`, and the initial condition `u₀` which define an SDE: + +```math +du = f(u,p,t)dt + Σgᵢ(u,p,t)dWⁱ +``` + +`f` and `g` should be specified as `f(u,p,t)` and `g(u,p,t)` respectively, and `u₀` +should be an AbstractArray whose geometry matches the desired geometry of `u`. +Note that we are not limited to numbers or vectors for `u₀`; one is allowed to +provide `u₀` as arbitrary matrices / higher dimension tensors as well. A vector +of `g`s can also be defined to determine an SDE of higher Ito dimension. + +## Problem Type + +Wraps the data which defines an SDE problem + +```math +u = f(u,p,t)dt + Σgᵢ(u,p,t)dWⁱ +``` + +with initial condition `u0`. + +### Constructors + +- `SDEProblem(f::SDEFunction,g,u0,tspan,p=NullParameters();noise=WHITE_NOISE,noise_rate_prototype=nothing)` +- `SDEProblem{isinplace}(f,g,u0,tspan,p=NullParameters();noise=WHITE_NOISE,noise_rate_prototype=nothing)` : + Defines the SDE with the specified functions. The default noise is `WHITE_NOISE`. + `isinplace` optionally sets whether the function is inplace or not. This is + determined automatically, but not inferred. + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the +[DiffEqFunctions](@ref performance_overloads) +page. + +### Fields + +* `f`: The drift function in the SDE. +* `g`: The noise function in the SDE. +* `u0`: The initial condition. +* `tspan`: The timespan for the problem. +* `p`: The optional parameters for the problem. Defaults to `NullParameters`. +* `noise`: The noise process applied to the noise upon generation. Defaults to + Gaussian white noise. For information on defining different noise processes, + see [the noise process documentation page](@ref noise_process) +* `noise_rate_prototype`: A prototype type instance for the noise rates, that + is the output `g`. It can be any type which overloads `A_mul_B!` with itself + being the middle argument. Commonly, this is a matrix or sparse matrix. If + this is not given, it defaults to `nothing`, which means the problem should + be interpreted as having diagonal noise. +* `kwargs`: The keyword arguments passed onto the solves. + +## Example Problems + +Examples problems can be found in [DiffEqProblemLibrary.jl](https://github.com/JuliaDiffEq/DiffEqProblemLibrary.jl/blob/master/src/sde_premade_problems.jl). + +To use a sample problem, such as `prob_sde_linear`, you can do something like: + +```julia +#] add DiffEqProblemLibrary +using DiffEqProblemLibrary.SDEProblemLibrary +# load problems +SDEProblemLibrary.importsdeproblems() +prob = SDEProblemLibrary.prob_sde_linear +sol = solve(prob) +``` """ struct SDEProblem{uType,tType,isinplace,P,NP,F,G,K,ND} <: AbstractSDEProblem{uType,tType,isinplace,ND} f::F diff --git a/src/problems/steady_state_problems.jl b/src/problems/steady_state_problems.jl index fb20a775c..d6eb447ca 100644 --- a/src/problems/steady_state_problems.jl +++ b/src/problems/steady_state_problems.jl @@ -1,12 +1,67 @@ -# Mu' = f -""" +@doc doc""" $(TYPEDEF) -Defines a steady state problem. +Defines an Defines a steady state ODE problem. +Documentation Page: https://diffeq.sciml.ai/stable/types/steady_state_types/ + +## Mathematical Specification of a Steady State Problem + +To define an Steady State Problem, you simply need to give the function ``f`` +which defines the ODE: + +```math +\frac{du}{dt} = f(u,p,t) +``` + +and an initial guess ``u₀`` of where `f(u,p,t)=0`. `f` should be specified as `f(u,p,t)` +(or in-place as `f(du,u,p,t)`), and `u₀` should be an AbstractArray (or number) +whose geometry matches the desired geometry of `u`. Note that we are not limited +to numbers or vectors for `u₀`; one is allowed to provide `u₀` as arbitrary +matrices / higher dimension tensors as well. + +Note that for the steady-state to be defined, we must have that `f` is autonomous, +that is `f` is independent of `t`. But the form which matches the standard ODE +solver should still be used. The steady state solvers interpret the `f` by +fixing `t=0`. + +## Problem Type + +### Constructors + +```julia +SteadyStateProblem(f::ODEFunction,u0,p=NullParameters();kwargs...) +SteadyStateProblem{isinplace}(f,u0,p=NullParameters();kwargs...) +``` + +`isinplace` optionally sets whether the function is inplace or not. This is +determined automatically, but not inferred. Additionally, the constructor from +`ODEProblem`s is provided: + +```julia +SteadyStateProblem(prob::ODEProblem) +``` + +Parameters are optional, and if not given then a `NullParameters()` singleton +will be used which will throw nice errors if you try to index non-existent +parameters. Any extra keyword arguments are passed on to the solvers. For example, +if you set a `callback` in the problem, then that `callback` will be added in +every solve call. + +For specifying Jacobians and mass matrices, see the +[DiffEqFunctions](@ref performance_overloads) +page. + +### Fields + +* `f`: The function in the ODE. +* `u0`: The initial guess for the steady state. +* `p`: The parameters for the problem. Defaults to `NullParameters` +* `kwargs`: The keyword arguments passed onto the solves. -# Fields +## Special Solution Fields -$(FIELDS) +The `SteadyStateSolution` type is different from the other DiffEq solutions because +it does not have temporal information. """ struct SteadyStateProblem{uType,isinplace,P,F,K} <: AbstractSteadyStateProblem{uType,isinplace} """f: The function in the ODE."""