diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index 122d6208d..a34e430c2 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -796,7 +796,7 @@ export SDDEProblem export PDEProblem export IncrementingODEProblem -export BVProblem, TwoPointBVProblem +export BVProblem, TwoPointBVProblem, SecondOrderBVProblem export remake diff --git a/src/problems/bvp_problems.jl b/src/problems/bvp_problems.jl index 0c84fb4b9..86d7763b5 100644 --- a/src/problems/bvp_problems.jl +++ b/src/problems/bvp_problems.jl @@ -233,3 +233,114 @@ function TwoPointBVProblem(f::AbstractODEFunction, bc, initialGuess, tspan::Abst u0 = [initialGuess(i) for i in tspan] return TwoPointBVProblem(f, bc, u0, (tspan[1], tspan[end]), p; kwargs...) end + +""" +$(TYPEDEF) +""" +struct StandardSecondOrderBVProblem end + +@doc doc""" + +Defines a second order BVP problem. +Documentation Page: [https://docs.sciml.ai/DiffEqDocs/stable/types/bvp_types/](https://docs.sciml.ai/DiffEqDocs/stable/types/bvp_types/) + +## Mathematical Specification of a second order BVP Problem + +To define a BVP Problem, you simply need to give the function ``f`` and the initial +condition ``u_0`` which define an ODE: + +```math +\frac{ddu}{dt} = f(du,u,p,t) +``` + +along with an implicit function `bc` which defines the residual equation, where + +```math +bc(du,u,p,t) = 0 +``` + +is the manifold on which the solution must live. + +## Problem Type + +### Constructors + +```julia +SecondOrderBVProblem{isinplace}(f, bc, u0, tspan, p=NullParameters(); kwargs...) +``` + +or if we have an initial guess function `initialGuess(p, t)` for the given BVP, +we can pass the initial guess to the problem constructors: + +```julia +SecondOrderBVProblem{isinplace}(f, bc, initialGuess, tspan, p=NullParameters(); kwargs...) +``` + +For any BVP problem type, `bc` must be inplace if `f` is inplace. Otherwise it must be +out-of-place. + +If the bvp is a StandardSecondOrderBVProblem (also known as a Multi-Point BV Problem) it must define +either of the following functions + +```julia +bc!(residual, du, u, p, t) +residual = bc(du, 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 SecondOrderBVProblem{uType, tType, isinplace, nlls, P, F, PT, K} <: + AbstractBVProblem{uType, tType, isinplace, nlls} + f::F + u0::uType + tspan::tType + p::P + problem_type::PT + kwargs::K + + @add_kwonly function SecondOrderBVProblem{iip}(f::AbstractBVPFunction{iip}, u0, tspan, + p = NullParameters(); problem_type = StandardSecondOrderBVProblem(), nlls = nothing, + kwargs...) where {iip} + _u0 = prepare_initial_state(u0) + _tspan = promote_tspan(tspan) + warn_paramtype(p) + + return new{typeof(_u0), typeof(_tspan), iip, typeof(nlls), typeof(p), typeof(f), + typeof(problem_type), typeof(kwargs)}(f, _u0, _tspan, p, problem_type, kwargs) + end + + function SecondOrderBVProblem{iip}(f, bc, u0, tspan, p = NullParameters(); kwargs...) where {iip} + SecondOrderBVProblem(BVPFunction{iip}(f, bc), u0, tspan, p; kwargs...) + end +end + +function SecondOrderBVProblem(f, bc, u0, tspan, p = NullParameters(); kwargs...) + iip = isinplace(f, 5) + return SecondOrderBVProblem{iip}(BVPFunction{iip}(f, bc), u0, tspan, p; kwargs...) +end + +function SecondOrderBVProblem(f::AbstractBVPFunction, u0, tspan, p = NullParameters(); kwargs...) + return SecondOrderBVProblem{isinplace(f)}(f, u0, tspan, p; kwargs...) +end \ No newline at end of file diff --git a/src/scimlfunctions.jl b/src/scimlfunctions.jl index eba6f8dd9..38faab837 100644 --- a/src/scimlfunctions.jl +++ b/src/scimlfunctions.jl @@ -3751,7 +3751,8 @@ function BVPFunction{iip, specialize, twopoint}(f, bc; end bciip = if !twopoint - isinplace(bc, 4, "bc", iip) + # bc in SecondOrderBVProblem should have 5 arguments + isinplace(f, 5) ? isinplace(bc, 5, "bc", iip) : isinplace(bc, 4, "bc", iip) else @assert length(bc) == 2 bc = Tuple(bc)