diff --git a/Project.toml b/Project.toml index dc83a7bf..d226a7e7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,10 @@ name = "FractionalDiffEq" uuid = "c7492dd8-6170-483b-af64-cefb6c377d9a" authors = ["Qingyu Qu "] -version = "0.3.1" +version = "0.3.2" [deps] +ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" diff --git a/src/types/problems.jl b/src/types/problems.jl index 8724e77a..cb9a0272 100644 --- a/src/types/problems.jl +++ b/src/types/problems.jl @@ -18,22 +18,87 @@ MultiTermsFODEProblem(parameters, orders, rightfun, u0, T) = MultiTermsFODEProbl #MultiTermsFODEProblem(parameters, orders, rightfun, u0, t0, T) = MultiTermsFODEProblem(parameters, orders, rightfun, nothing, nothing, u0, T) -""" +SciMLBase.isinplace(prob::AbstractFODEProblem{uType, tType, oType, iip}) where {uType, tType, oType, iip} = iip +SciMLBase.isinplace(prob::AbstractFDDEProblem{uType, tType, oType, lType, isinplace}) where {uType, tType, oType, lType, isinplace} = iip - SingleTermFODEProblem(f, α, u0, tspan) +struct StandardFODEProblem end -Define a single term fractional ordinary differential equation, there are only one fractional differential operator in this problem. """ -#= -abstract type AbstractTestProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace} end -=# +Defines an fractional ordinary differential equation (FODE) problem. +Documentation Page: +## Mathematical Specification of an FODE problem -SciMLBase.isinplace(prob::AbstractFODEProblem{uType, tType, oType, iip}) where {uType, tType, oType, iip} = iip -SciMLBase.isinplace(prob::AbstractFDDEProblem{uType, tType, oType, lType, isinplace}) where {uType, tType, oType, lType, isinplace} = iip +To define an FODE Problem, you simply need to given the function ``f`` and the initial condition ``u_0`` which define an FODE: -struct StandardFODEProblem end +```math +\\frac{du^\\alpha}{d^{\\alpha}t} = 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). +- `order`: the fractional order of the differential equations, commensurate and non-commensurate is both supported. +-`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 + +`FODEProblem` can be constructed by first building an `ODEFunction` or +by simply passing the FODE right-hand side to the constructor. The constructors +are: + +- `FODEProblem(f::ODEFunction,u0,tspan,p=NullParameters();kwargs...)` +- `FODEProblem{isinplace,specialize}(f,u0,tspan,p=NullParameters();kwargs...)` : + Defines the FODE with the specified functions. `isinplace` optionally sets whether + the function is inplace or not. This is determined automatically, but not inferred. + `specialize` optionally controls the specialization level. See the + [specialization levels section of the SciMLBase documentation](https://docs.sciml.ai/SciMLBase/stable/interfaces/Problems/#Specialization-Levels) + for more details. The default is `AutoSpecialize`. + +For more details on the in-place and specialization controls, see the ODEFunction +documentation. + +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 + +- `f`: The function in the ODE. +- `order`: The order of the FODE. +- `u0`: The initial condition. +- `tspan`: The timespan for the problem. +- `p`: The parameters. +- `kwargs`: The keyword arguments passed onto the solves. + +## Example Problem + +```julia +using SciMLBase +function lorenz!(du,u,p,t) + du[1] = 10.0(u[2]-u[1]) + du[2] = u[1]*(28.0-u[3]) - u[2] + du[3] = u[1]*u[2] - (8/3)*u[3] +end +order = [0.96;0.96;0.96] +u0 = [1.0;0.0;0.0] +tspan = (0.0,100.0) +prob = FODEProblem(lorenz!,u0,tspan) + +# Test that it worked +using FractionalDiffEq +sol = solve(prob,PIEX()) +using Plots; plot(sol,vars=(1,2,3)) +``` +""" struct FODEProblem{uType, tType, oType, isinplace, P, F, bF, PT, K} <: AbstractFODEProblem{uType, tType, oType, isinplace} f::F @@ -62,7 +127,7 @@ end TruncatedStacktraces.@truncate_stacktrace SingleTermFODEProblem 3 1 2 -function FODEProblem(f::SciMLBase.AbstractODEFunction, order, u0, tspan, args...; kwargs...) +function FODEProblem(f::ODEFunction, order, u0, tspan, args...; kwargs...) FODEProblem{SciMLBase.isinplace(f, 4)}(f, order, u0, tspan, args...; kwargs...) end diff --git a/test/types/problem_building_tests.jl b/test/types/problem_building_tests.jl new file mode 100644 index 00000000..f5cd366b --- /dev/null +++ b/test/types/problem_building_tests.jl @@ -0,0 +1,14 @@ +######################################### FODEProblem ############################################ + +ftoomany(u, p, t, x, y) = 2u +order = 1.5 +u0 = 0.5 +tspan = (0.0, 1.0) +@test_throws SciMLBase.TooManyArgumentsError FODEProblem(ftoomany, order, u0, tspan) + +ftoofew(u, t) = 2u +@test_throws SciMLBase.TooFewArgumentsError FODEProblem(ftoofew, order, u0, tspan) + +fmessedup(u, t) = 2u +fmessedup(u, p, t, x, y) = 2u +@test_throws SciMLBase.FunctionArgumentsError FODEProblem(fmessedup, order, u0, tspan)