Skip to content

Commit

Permalink
Merge branch 'master' into integrands
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisRackauckas authored Sep 21, 2023
2 parents e6a0547 + 434e752 commit a3a09d4
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 127 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SciMLBase"
uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
authors = ["Chris Rackauckas <[email protected]> and contributors"]
version = "1.98.0"
version = "2.0.0"

[deps]
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
Expand Down
6 changes: 3 additions & 3 deletions src/problems/basic_problems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -445,18 +445,18 @@ SampledIntegralProblem(y::AbstractArray, x::AbstractVector; dim=ndims(y), kwargs
The fields match the names of the constructor arguments.
"""
struct SampledIntegralProblem{Y, X, D, K} <: AbstractIntegralProblem{false}
struct SampledIntegralProblem{Y, X, K} <: AbstractIntegralProblem{false}
y::Y
x::X
dim::D
dim::Int
kwargs::K
@add_kwonly function SampledIntegralProblem(y::AbstractArray, x::AbstractVector;
dim = ndims(y),
kwargs...)
@assert dim<=ndims(y) "The integration dimension `dim` is larger than the number of dimensions of the integrand `y`"

Check warning on line 456 in src/problems/basic_problems.jl

View check run for this annotation

Codecov / codecov/patch

src/problems/basic_problems.jl#L456

Added line #L456 was not covered by tests
@assert length(x)==size(y, dim) "The integrand `y` must have the same length as the sampling points `x` along the integrated dimension."
@assert axes(x, 1)==axes(y, dim) "The integrand `y` must obey the same indexing as the sampling points `x` along the integrated dimension."
new{typeof(y), typeof(x), Val{dim}, typeof(kwargs)}(y, x, Val(dim), kwargs)
new{typeof(y), typeof(x), typeof(kwargs)}(y, x, dim, kwargs)
end
end

Expand Down
113 changes: 64 additions & 49 deletions src/problems/bvp_problems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ $(TYPEDEF)
"""
struct StandardBVProblem end

"""
$(TYPEDEF)
"""
struct TwoPointBVProblem end

@doc doc"""
Defines an BVP problem.
Expand All @@ -17,7 +22,7 @@ condition ``u_0`` which define an ODE:
\frac{du}{dt} = f(u,p,t)
```
along with an implicit function `bc!` which defines the residual equation, where
along with an implicit function `bc` which defines the residual equation, where
```math
bc(u,p,t) = 0
Expand All @@ -36,22 +41,27 @@ u(t_f) = b
### Constructors
```julia
TwoPointBVProblem{isinplace}(f,bc!,u0,tspan,p=NullParameters();kwargs...)
BVProblem{isinplace}(f,bc!,u0,tspan,p=NullParameters();kwargs...)
TwoPointBVProblem{isinplace}(f,bc,u0,tspan,p=NullParameters();kwargs...)
BVProblem{isinplace}(f,bc,u0,tspan,p=NullParameters();kwargs...)
```
or if we have an initial guess function `initialGuess(t)` for the given BVP,
we can pass the initial guess to the problem constructors:
```julia
TwoPointBVProblem{isinplace}(f,bc!,initialGuess,tspan,p=NullParameters();kwargs...)
BVProblem{isinplace}(f,bc!,initialGuess,tspan,p=NullParameters();kwargs...)
TwoPointBVProblem{isinplace}(f,bc,initialGuess,tspan,p=NullParameters();kwargs...)
BVProblem{isinplace}(f,bc,initialGuess,tspan,p=NullParameters();kwargs...)
```
For any BVP problem type, `bc!` is the inplace function:
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 StandardBVProblem (also known as a Multi-Point BV Problem) it must define
either of the following functions
```julia
bc!(residual, u, p, t)
residual = bc(u, p, t)
```
where `residual` computed from the current `u`. `u` is an array of solution values
Expand All @@ -61,6 +71,16 @@ 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.
If the bvp is a TwoPointBVProblem it must define either of the following functions
```julia
bc!((resid_a, resid_b), (u_a, u_b), p)
resid_a, resid_b = bc((u_a, u_b), p)
```
where `resid_a` and `resid_b` are the residuals at the two endpoints, `u_a` and `u_b` are
the solution values at the two endpoints, and `p` are the parameters.
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,
Expand Down Expand Up @@ -88,16 +108,20 @@ struct BVProblem{uType, tType, isinplace, P, F, BF, PT, K} <:
problem_type::PT
kwargs::K

@add_kwonly function BVProblem{iip}(f::AbstractBVPFunction{iip}, bc, u0, tspan,
p = NullParameters(),
problem_type = StandardBVProblem();
kwargs...) where {iip}
@add_kwonly function BVProblem{iip}(f::AbstractBVPFunction{iip, TP}, bc, u0, tspan,
p = NullParameters(); problem_type=nothing, kwargs...) where {iip, TP}
_tspan = promote_tspan(tspan)
warn_paramtype(p)
new{typeof(u0), typeof(_tspan), isinplace(f), typeof(p),
typeof(f), typeof(f.bc),
typeof(problem_type), typeof(kwargs)}(f, f.bc, u0, _tspan, p,
problem_type, kwargs)
prob_type = TP ? TwoPointBVProblem() : StandardBVProblem()
# Needed to ensure that `problem_type` doesn't get passed in kwargs
if problem_type === nothing
problem_type = prob_type
else
@assert prob_type === problem_type "This indicates incorrect problem type specification! Users should never pass in `problem_type` kwarg, this exists exclusively for internal use."
end
return new{typeof(u0), typeof(_tspan), iip, typeof(p), typeof(f), typeof(bc),
typeof(problem_type), typeof(kwargs)}(f, bc, u0, _tspan, p, problem_type,
kwargs)
end

function BVProblem{iip}(f, bc, u0, tspan, p = NullParameters(); kwargs...) where {iip}
Expand All @@ -107,52 +131,43 @@ end

TruncatedStacktraces.@truncate_stacktrace BVProblem 3 1 2

function BVProblem(f::AbstractBVPFunction, u0, tspan, p = NullParameters(); kwargs...)
BVProblem{isinplace(f)}(f, f.bc, u0, tspan, p; kwargs...)
function BVProblem(f, bc, u0, tspan, p = NullParameters(); kwargs...)
iip = isinplace(f, 4)
return BVProblem{iip}(BVPFunction{iip}(f, bc), bc, u0, tspan, p; kwargs...)
end

function BVProblem(f, bc, u0, tspan, p = NullParameters(); kwargs...)
BVProblem(BVPFunction(f, bc), u0, tspan, p; kwargs...)
function BVProblem(f::AbstractBVPFunction, u0, tspan, p = NullParameters(); kwargs...)
return BVProblem{isinplace(f)}(f, f.bc, u0, tspan, p; kwargs...)
end

"""
$(TYPEDEF)
"""
struct TwoPointBVPFunction{bF}
bc::bF
# This is mostly a fake stuct and isn't used anywhere
# But we need it for function calls like TwoPointBVProblem{iip}(...) = ...
struct TwoPointBVPFunction{iip} end

@inline TwoPointBVPFunction(args...; kwargs...) = BVPFunction(args...; kwargs..., twopoint=true)
@inline function TwoPointBVPFunction{iip}(args...; kwargs...) where {iip}
return BVPFunction{iip}(args...; kwargs..., twopoint=true)
end
TwoPointBVPFunction(; bc = error("No argument bc")) = TwoPointBVPFunction(bc)
(f::TwoPointBVPFunction)(residual, ua, ub, p) = f.bc(residual, ua, ub, p)
(f::TwoPointBVPFunction)(residual, u, p) = f.bc(residual, u[1], u[end], p)

"""
$(TYPEDEF)
"""
struct TwoPointBVProblem{iip} end
function TwoPointBVProblem(f, bc, u0, tspan, p = NullParameters(); kwargs...)
iip = isinplace(f, 4)
TwoPointBVProblem{iip}(f, bc, u0, tspan, p; kwargs...)
function TwoPointBVProblem(f, bc, u0, tspan, p = NullParameters();
bcresid_prototype=nothing, kwargs...)
return TwoPointBVProblem(TwoPointBVPFunction(f, bc; bcresid_prototype), u0, tspan, p;
kwargs...)
end
function TwoPointBVProblem{iip}(f, bc, u0, tspan, p = NullParameters();
kwargs...) where {iip}
BVProblem{iip}(f, TwoPointBVPFunction(bc), u0, tspan, p; kwargs...)
function TwoPointBVProblem(f::AbstractBVPFunction{iip, twopoint}, u0, tspan,
p = NullParameters(); kwargs...) where {iip, twopoint}
@assert twopoint "`TwoPointBVProblem` can only be used with a `TwoPointBVPFunction`. Instead of using `BVPFunction`, use `TwoPointBVPFunction` or pass a kwarg `twopoint=true` during the construction of the `BVPFunction`."
return BVProblem{iip}(f, f.bc, u0, tspan, p; kwargs...)
end

# Allow previous timeseries solution
function TwoPointBVProblem(f::AbstractODEFunction,
bc,
sol::T,
tspan::Tuple,
p = NullParameters()) where {T <: AbstractTimeseriesSolution}
TwoPointBVProblem(f, bc, sol.u, tspan, p)
function TwoPointBVProblem(f::AbstractODEFunction, bc, sol::T, tspan::Tuple,
p = NullParameters(); kwargs...) where {T <: AbstractTimeseriesSolution}
return TwoPointBVProblem(f, bc, sol.u, tspan, p; kwargs...)
end
# Allow initial guess function for the initial guess
function TwoPointBVProblem(f::AbstractODEFunction,
bc,
initialGuess,
tspan::AbstractVector,
p = NullParameters();
kwargs...)
function TwoPointBVProblem(f::AbstractODEFunction, bc, initialGuess, tspan::AbstractVector,
p = NullParameters(); kwargs...)
u0 = [initialGuess(i) for i in tspan]
TwoPointBVProblem(f, bc, u0, (tspan[1], tspan[end]), p)
return TwoPointBVProblem(f, bc, u0, (tspan[1], tspan[end]), p; kwargs...)
end
Loading

0 comments on commit a3a09d4

Please sign in to comment.