From 6ca2e82c66a7e73026fce0e92319c6025d2abb20 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Dec 2023 16:12:00 -0500 Subject: [PATCH 01/24] Aggregate Single Shooting Improvements from https://github.com/SciML/BoundaryValueDiffEq.jl/pull/150 --- .JuliaFormatter.toml | 1 + Project.toml | 13 +- ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl | 49 ++- src/BoundaryValueDiffEq.jl | 1 + src/adaptivity.jl | 12 +- src/algorithms.jl | 111 +++---- src/solve/single_shooting.jl | 74 +++-- src/sparse_jacobians.jl | 8 +- src/types.jl | 25 ++ src/utils.jl | 124 ++++++++ test/runtests.jl | 21 +- test/shooting/basic_tests.jl | 324 ++++++++++++++++++++ test/shooting/nonlinear_least_squares.jl | 50 ++- test/shooting/orbital.jl | 217 +++++++------ test/shooting/ray_tracing.jl | 134 -------- test/shooting/shooting_tests.jl | 175 ----------- 16 files changed, 765 insertions(+), 574 deletions(-) create mode 100644 test/shooting/basic_tests.jl delete mode 100644 test/shooting/ray_tracing.jl delete mode 100644 test/shooting/shooting_tests.jl diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 16f5cb2b..f1d23682 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -1,3 +1,4 @@ style = "sciml" annotate_untyped_fields_with_any = false format_markdown = true +format_docstrings = true diff --git a/Project.toml b/Project.toml index a1f4c4f5..4dbb133c 100644 --- a/Project.toml +++ b/Project.toml @@ -10,6 +10,7 @@ BandedMatrices = "aae01518-5342-5314-be14-df237901396f" ConcreteStructs = "2569d6c7-a4a2-43d3-a901-331e8e4be471" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" +FastClosures = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" @@ -38,12 +39,13 @@ BoundaryValueDiffEqOrdinaryDiffEqExt = "OrdinaryDiffEq" [compat] ADTypes = "0.2" Adapt = "3, 4" -Aqua = "0.7" +Aqua = "0.8" ArrayInterface = "7" BandedMatrices = "1" ConcreteStructs = "0.2" DiffEqBase = "6.145" FastAlmostBandedMatrices = "0.1" +FastClosures = "0.3" ForwardDiff = "0.10" LinearAlgebra = "1.9" LinearSolve = "2.20" @@ -53,12 +55,16 @@ OrdinaryDiffEq = "6" PreallocationTools = "0.4" PrecompileTools = "1" Preferences = "1" +Random = "1" RecursiveArrayTools = "2.38.10, 3" Reexport = "0.2, 1.0" -SciMLBase = "2.6.2" +SafeTestsets = "0.1" +SciMLBase = "2.12" Setfield = "1" SparseArrays = "1.9" SparseDiffTools = "2.9" +StaticArrays = "1.8.1" +Test = "1" Tricks = "0.1" TruncatedStacktraces = "1" UnPack = "1" @@ -71,9 +77,10 @@ LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["StaticArrays", "Random", "DiffEqDevTools", "OrdinaryDiffEq", "Test", "SafeTestsets", "ODEInterface", "Aqua", "LinearSolve"] +test = ["StaticArrays", "Random", "DiffEqDevTools", "OrdinaryDiffEq", "Test", "SafeTestsets", "ODEInterface", "Aqua", "LinearSolve", "RecursiveArrayTools"] diff --git a/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl b/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl index b03d47b5..3c59832d 100644 --- a/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl +++ b/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl @@ -35,25 +35,25 @@ end bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) probs = [ - BVProblem(f1!, bc1!, u0, tspan), - BVProblem(f1, bc1, u0, tspan), - TwoPointBVProblem(f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype), - TwoPointBVProblem(f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype) + BVProblem(BVPFunction{true}(f1!, bc1!), u0, tspan; nlls = Val(false)), + BVProblem(BVPFunction{false}(f1, bc1), u0, tspan; nlls = Val(false)), + BVProblem(BVPFunction{true}(f1!, (bc1_a!, bc1_b!); bcresid_prototype, + twopoint = Val(true)), u0, tspan; nlls = Val(false)), + BVProblem(BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, + twopoint = Val(true)), u0, tspan; nlls = Val(false)), ] algs = [] - if load_preference(BoundaryValueDiffEq, "PrecompileShooting", false) + if load_preference(BoundaryValueDiffEq, "PrecompileShooting", true) push!(algs, Shooting(Tsit5(); nlsolve = NewtonRaphson(), jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))) end - if load_preference(BoundaryValueDiffEq, "PrecompileMultipleShooting", false) + if load_preference(BoundaryValueDiffEq, "PrecompileMultipleShooting", true) push!(algs, - MultipleShooting(10, - Tsit5(); - nlsolve = NewtonRaphson(; autodiff = AutoForwardDiff(chunksize = 2)), + MultipleShooting(10, Tsit5(); nlsolve = NewtonRaphson(), jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 2), nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))) @@ -94,39 +94,38 @@ end bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) probs = [ - BVProblem(BVPFunction(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), - u0, tspan), - BVProblem(BVPFunction(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), - u0, tspan), - TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, tspan; - bcresid_prototype = bcresid_prototype2), - TwoPointBVProblem(f1_nlls, (bc1_nlls_a, bc1_nlls_b), u0, tspan; - bcresid_prototype = bcresid_prototype2) + BVProblem(BVPFunction{true}(f1_nlls!, bc1_nlls!; + bcresid_prototype = bcresid_prototype1), u0, tspan; nlls = Val(true)), + BVProblem(BVPFunction{false}(f1_nlls, bc1_nlls; + bcresid_prototype = bcresid_prototype1), u0, tspan; nlls = Val(true)), + BVProblem(BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); + bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), u0, tspan; + nlls = Val(true)), + BVProblem(BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); + bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), u0, tspan; + nlls = Val(true)), ] algs = [] - if load_preference(BoundaryValueDiffEq, "PrecompileShootingNLLS", false) + if load_preference(BoundaryValueDiffEq, "PrecompileShootingNLLS", true) append!(algs, [ - Shooting(Tsit5(); nlsolve = LevenbergMarquardt(), + Shooting(Tsit5(); nlsolve = TrustRegion(), jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5(); nlsolve = GaussNewton(), jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))) ]) end - if load_preference(BoundaryValueDiffEq, "PrecompileMultipleShootingNLLS", false) + if load_preference(BoundaryValueDiffEq, "PrecompileMultipleShootingNLLS", true) append!(algs, [ - MultipleShooting(10, Tsit5(); - nlsolve = LevenbergMarquardt(; - autodiff = AutoForwardDiff(chunksize = 2)), + MultipleShooting(10, Tsit5(); nlsolve = TrustRegion(), jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 2), nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5(); - nlsolve = GaussNewton(; autodiff = AutoForwardDiff(chunksize = 2)), + MultipleShooting(10, Tsit5(); nlsolve = GaussNewton(), jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 2), nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))) diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index 9a5cdb91..fadc9b49 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -16,6 +16,7 @@ import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidat parameterless_type, undefmatrix, fast_scalar_indexing import ConcreteStructs: @concrete import DiffEqBase: solve + import FastClosures: @closure import ForwardDiff: pickchunksize import RecursiveArrayTools: ArrayPartition, DiffEqArray import SciMLBase: AbstractDiffEqInterpolation, StandardBVProblem, __solve, _unwrap_val diff --git a/src/adaptivity.jl b/src/adaptivity.jl index a1e96133..d2d08a2a 100644 --- a/src/adaptivity.jl +++ b/src/adaptivity.jl @@ -259,14 +259,16 @@ end return z, z′ end +""" + interp_weights(τ, alg + +interp_weights: solver-specified interpolation weights and its first derivative +""" +function interp_weights end + for order in (2, 3, 4, 5, 6) alg = Symbol("MIRK$(order)") @eval begin - """ - interp_weights(τ, alg) - - interp_weights: solver-specified interpolation weights and its first derivative - """ function interp_weights(τ::T, ::$(alg)) where {T} if $(order == 2) w = [0, τ * (1 - τ / 2), τ^2 / 2] diff --git a/src/algorithms.jl b/src/algorithms.jl index 00cb80f8..0cc01ad1 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -2,8 +2,15 @@ abstract type BoundaryValueDiffEqAlgorithm <: SciMLBase.AbstractBVPAlgorithm end abstract type AbstractMIRK <: BoundaryValueDiffEqAlgorithm end +## Disable the ugly verbose printing by default +function Base.show(io::IO, alg::BoundaryValueDiffEqAlgorithm) + print(io, "$(nameof(typeof(alg)))()") +end + """ - Shooting(ode_alg = nothing; nlsolve = nothing, jac_alg = BVPJacobianAlgorithm()) + Shooting(ode_alg; kwargs...) + Shooting(ode_alg, nlsolve; kwargs...) + Shooting(; ode_alg = nothing, nlsolve = nothing, jac_alg = nothing) Single shooting method, reduces BVP to an initial value problem and solves the IVP. @@ -12,55 +19,41 @@ Single shooting method, reduces BVP to an initial value problem and solves the I - `ode_alg`: ODE algorithm to use for solving the IVP. Any solver which conforms to the SciML `ODEProblem` interface can be used! (Defaults to `nothing` which will use poly-algorithm if `DifferentialEquations.jl` is loaded else this must be supplied) - -## Keyword Arguments - - `nlsolve`: Internal Nonlinear solver. Any solver which conforms to the SciML `NonlinearProblem` interface can be used. Note that any autodiff argument for the solver will be ignored and a custom jacobian algorithm will be used. - - `jac_alg`: Jacobian Algorithm used for the nonlinear solver. Defaults to - `BVPJacobianAlgorithm()`, which automatically decides the best algorithm to use based - on the input types and problem type. Only `diffmode` is used (defaults to - `AutoForwardDiff` if possible else `AutoFiniteDiff`). - -!!! note - For type-stability, the chunksizes for ForwardDiff ADTypes in `BVPJacobianAlgorithm` - must be provided. + - `jac_alg`: Jacobian Algorithm used for the Nonlinear Solver. If this is not set, we + check if `nlsolve.ad` exists and is not nothing. If it is, we use that to construct + the jacobian. If not, we try to use the best algorithm based on the input types + and problem type. If `BVPJacobianAlgorithm` is provided, only `diffmode` is used + (defaults to `AutoForwardDiff` if possible else `AutoFiniteDiff`). """ -struct Shooting{O, N, L <: BVPJacobianAlgorithm} <: BoundaryValueDiffEqAlgorithm - ode_alg::O - nlsolve::N - jac_alg::L +@concrete struct Shooting{J <: BVPJacobianAlgorithm} <: BoundaryValueDiffEqAlgorithm + ode_alg + nlsolve + jac_alg::J end -function concretize_jacobian_algorithm(alg::Shooting, prob) - jac_alg = alg.jac_alg - diffmode = jac_alg.diffmode === nothing ? __default_nonsparse_ad(prob.u0) : - jac_alg.diffmode - return Shooting(alg.ode_alg, alg.nlsolve, BVPJacobianAlgorithm(diffmode)) +function Shooting(; ode_alg = nothing, nlsolve = nothing, jac_alg = nothing) + return Shooting(ode_alg, nlsolve, __materialize_jacobian_algorithm(nlsolve, jac_alg)) end - -function Shooting(ode_alg = nothing; nlsolve = nothing, jac_alg = nothing) - jac_alg === nothing && (jac_alg = __propagate_nlsolve_ad_to_jac_alg(nlsolve)) - return Shooting(ode_alg, nlsolve, jac_alg) +@inline Shooting(ode_alg; kwargs...) = Shooting(; ode_alg, kwargs...) +@inline Shooting(ode_alg, nlsolve; kwargs...) = Shooting(; ode_alg, nlsolve, kwargs...) + +function Base.show(io::IO, alg::Shooting) + print(io, "Shooting(") + modifiers = String[] + alg.nlsolve !== nothing && push!(modifiers, "nlsolve = $(alg.nlsolve)") + alg.jac_alg !== nothing && push!(modifiers, "jac_alg = $(alg.jac_alg)") + alg.ode_alg !== nothing && push!(modifiers, "ode_alg = $(__nameof(alg.ode_alg))()") + print(io, join(modifiers, ", ")) + print(io, ")") end -Shooting(ode_alg, nlsolve; jac_alg = nothing) = Shooting(ode_alg; nlsolve, jac_alg) - -# This is a deprecation path. We forward the `ad` from nonlinear solver to `jac_alg`. -# We will drop this function in -function __propagate_nlsolve_ad_to_jac_alg(nlsolve::N) where {N} - # Defaults so no depwarn - nlsolve === nothing && return BVPJacobianAlgorithm() - ad = hasfield(N, :ad) ? nlsolve.ad : nothing - ad === nothing && return BVPJacobianAlgorithm() - - Base.depwarn( - "Setting autodiff to the nonlinear solver in Shooting has been deprecated \ - and will have no effect from the next major release. Update to use \ - `BVPJacobianAlgorithm` directly", - :Shooting) - return BVPJacobianAlgorithm(ad) +@inline function concretize_jacobian_algorithm(alg::Shooting, prob) + alg.jac_alg.diffmode === nothing && + (return @set alg.jac_alg.diffmode = __default_nonsparse_ad(prob.u0)) + return alg end """ @@ -82,27 +75,31 @@ Significantly more stable than Single Shooting. - `nlsolve`: Internal Nonlinear solver. Any solver which conforms to the SciML `NonlinearProblem` interface can be used. Note that any autodiff argument for the solver will be ignored and a custom jacobian algorithm will be used. + - `jac_alg`: Jacobian Algorithm used for the nonlinear solver. Defaults to `BVPJacobianAlgorithm()`, which automatically decides the best algorithm to use based on the input types and problem type. - - For `TwoPointBVProblem`, only `diffmode` is used (defaults to - `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`). - - For `BVProblem`, `bc_diffmode` and `nonbc_diffmode` are used. For `nonbc_diffmode` - defaults to `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`. For - `bc_diffmode`, defaults to `AutoForwardDiff` if possible else `AutoFiniteDiff`. + + + For `TwoPointBVProblem`, only `diffmode` is used (defaults to + `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`). + + For `BVProblem`, `bc_diffmode` and `nonbc_diffmode` are used. For `nonbc_diffmode` + defaults to `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`. For + `bc_diffmode`, defaults to `AutoForwardDiff` if possible else `AutoFiniteDiff`. - `grid_coarsening`: Coarsening the multiple-shooting grid to generate a stable IVP solution. Possible Choices: - - `true`: Halve the grid size, till we reach a grid size of 1. - - `false`: Do not coarsen the grid. Solve a Multiple Shooting Problem and finally - solve a Single Shooting Problem. - - `AbstractVector{<:Int}` or `Ntuple{N, <:Integer}`: Use the provided grid coarsening. - For example, if `nshoots = 10` and `grid_coarsening = [5, 2]`, then the grid will be - coarsened to `[5, 2]`. Note that `1` should not be present in the grid coarsening. - - `Function`: Takes the current number of shooting points and returns the next number - of shooting points. For example, if `nshoots = 10` and - `grid_coarsening = n -> n ÷ 2`, then the grid will be coarsened to `[5, 2]`. + + + `true`: Halve the grid size, till we reach a grid size of 1. + + `false`: Do not coarsen the grid. Solve a Multiple Shooting Problem and finally + solve a Single Shooting Problem. + + `AbstractVector{<:Int}` or `Ntuple{N, <:Integer}`: Use the provided grid coarsening. + For example, if `nshoots = 10` and `grid_coarsening = [5, 2]`, then the grid will be + coarsened to `[5, 2]`. Note that `1` should not be present in the grid coarsening. + + `Function`: Takes the current number of shooting points and returns the next number + of shooting points. For example, if `nshoots = 10` and + `grid_coarsening = n -> n ÷ 2`, then the grid will be coarsened to `[5, 2]`. !!! note + For type-stability, the chunksizes for ForwardDiff ADTypes in `BVPJacobianAlgorithm` must be provided. """ @@ -213,10 +210,12 @@ Fortran code for solving two-point boundary value problems. For detailed documen singular term. !!! warning + Only supports inplace two-point boundary value problems, with very limited forms of input structures! !!! note + Only available if the `ODEInterface` package is loaded. """ Base.@kwdef struct BVPM2{S} <: BoundaryValueDiffEqAlgorithm @@ -251,10 +250,12 @@ For detailed documentation, see - `odesolver`: Either `nothing` or ode-solver(dopri5, dop853, seulex, etc.). !!! warning + Only supports inplace two-point boundary value problems, with very limited forms of input structures! !!! note + Only available if the `ODEInterface` package is loaded. """ Base.@kwdef struct BVPSOL{O} <: BoundaryValueDiffEqAlgorithm diff --git a/src/solve/single_shooting.jl b/src/solve/single_shooting.jl index 758ae9ae..74f3d6f9 100644 --- a/src/solve/single_shooting.jl +++ b/src/solve/single_shooting.jl @@ -1,8 +1,13 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), nlsolve_kwargs = (;), verbose = true, kwargs...) - ig, T, N, _, u0 = __extract_problem_details(prob; dt = 0.1) - _unwrap_val(ig) && verbose && - @warn "Initial guess provided, but will be ignored for Shooting!" + # Setup the problem + if prob.u0 isa AbstractArray{<:Number} + u0 = prob.u0 + else + verbose && @warn "Initial guess provided, but will be ignored for Shooting." + u0 = __extract_u0(prob.u0, prob.p, first(prob.tspan)) + end + T, N = eltype(u0), length(u0) alg = concretize_jacobian_algorithm(alg_, prob) @@ -11,26 +16,32 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), resid_prototype = __vec(bcresid_prototype) # Construct the residual function - ode_kwargs = (; kwargs..., verbose, odesolve_kwargs...) + actual_ode_kwargs = (; kwargs..., verbose, odesolve_kwargs...) + # For TwoPointBVPs we don't need to save every step + if prob.problem_type isa TwoPointBVProblem + ode_kwargs = (; save_everystep = false, actual_ode_kwargs...) + else + ode_kwargs = (; actual_ode_kwargs...) + end internal_prob = ODEProblem{iip}(prob.f, u0, prob.tspan, prob.p) ode_cache_loss_fn = SciMLBase.__init(internal_prob, alg.ode_alg; ode_kwargs...) loss_fn = if iip - (du, u, p) -> __single_shooting_loss!(du, u, p, ode_cache_loss_fn, bc, u0_size, - prob.problem_type, resid_size) + @closure (du, u, p) -> __single_shooting_loss!(du, u, p, ode_cache_loss_fn, bc, + u0_size, prob.problem_type, resid_size) else - (u, p) -> __single_shooting_loss(u, p, ode_cache_loss_fn, bc, u0_size, + @closure (u, p) -> __single_shooting_loss(u, p, ode_cache_loss_fn, bc, u0_size, prob.problem_type) end - # Construct the jacobian function - # NOTE: We pass in a separate Jacobian Function because that allows us to cache the - # the internal ode solve cache. This cache needs to be distinct from the regular - # residual function cache sd = alg.jac_alg.diffmode isa AbstractSparseADType ? SymbolicsSparsityDetection() : NoSparsityDetection() y_ = similar(resid_prototype) + # Construct the jacobian function + # NOTE: We pass in a separate Jacobian Function because that allows us to cache the + # the internal ode solve cache. This cache needs to be distinct from the regular + # residual function cache jac_cache = if iip sparse_jacobian_cache(alg.jac_alg.diffmode, sd, nothing, y_, vec(u0)) else @@ -43,35 +54,34 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), jac_prototype = init_jacobian(jac_cache) loss_fnₚ = if iip - (du, u) -> __single_shooting_loss!(du, u, prob.p, ode_cache_jac_fn, bc, u0_size, - prob.problem_type, resid_size) + @closure (du, u) -> __single_shooting_loss!(du, u, prob.p, ode_cache_jac_fn, bc, + u0_size, prob.problem_type, resid_size) else - (u) -> __single_shooting_loss(u, prob.p, ode_cache_jac_fn, bc, u0_size, + @closure (u) -> __single_shooting_loss(u, prob.p, ode_cache_jac_fn, bc, u0_size, prob.problem_type) end jac_fn = if iip - (J, u, p) -> __single_shooting_jacobian!(J, u, jac_cache, alg.jac_alg.diffmode, - loss_fnₚ, y_) + @closure (J, u, p) -> __single_shooting_jacobian!(J, u, jac_cache, + alg.jac_alg.diffmode, loss_fnₚ, y_) else - (u, p) -> __single_shooting_jacobian(jac_prototype, u, jac_cache, + @closure (u, p) -> __single_shooting_jacobian(jac_prototype, u, jac_cache, alg.jac_alg.diffmode, loss_fnₚ) end - nlf = NonlinearFunction{iip}(loss_fn; jac_prototype, resid_prototype, jac = jac_fn) - nlprob = if length(resid_prototype) == length(u0) - NonlinearProblem(nlf, vec(u0), prob.p) - else - NonlinearLeastSquaresProblem(nlf, vec(u0), prob.p) - end + nlf = __unsafe_nonlinearfunction{iip}(loss_fn; jac_prototype, resid_prototype, + jac = jac_fn) + nlprob = __internal_nlsolve_problem(prob, resid_prototype, u0, nlf, vec(u0), prob.p) opt = __solve(nlprob, alg.nlsolve; nlsolve_kwargs..., verbose, kwargs...) - SciMLBase.reinit!(ode_cache_loss_fn, reshape(opt.u, u0_size)) - sol = solve!(ode_cache_loss_fn) + # There is no way to reinit with the same cache with different cache. But not saving + # the internal values gives a significant speedup. So we just create a new cache + internal_prob_final = ODEProblem{iip}(prob.f, reshape(opt.u, u0_size), prob.tspan, + prob.p) + sol = __solve(internal_prob_final, alg.ode_alg; actual_ode_kwargs...) - !SciMLBase.successful_retcode(opt) && - return SciMLBase.solution_new_retcode(sol, ReturnCode.Failure) - return sol + retcode = SciMLBase.successful_retcode(opt) ? sol.retcode : opt.retcode + return BVPSolution(sol; original = opt, retcode) end function __single_shooting_loss!(resid_, u0_, p, cache, bc::BC, u0_size, @@ -103,7 +113,7 @@ end function __single_shooting_loss(u, p, cache, bc::BC, u0_size, pt) where {BC} SciMLBase.reinit!(cache, reshape(u, u0_size)) odesol = solve!(cache) - return __safe_vec(eval_bc_residual(pt, bc, odesol, p)) + return __vec(eval_bc_residual(pt, bc, odesol, p)) end function __single_shooting_jacobian!(J, u, jac_cache, diffmode, loss_fn::L, fu) where {L} @@ -117,8 +127,7 @@ function __single_shooting_jacobian(J, u, jac_cache, diffmode, loss_fn::L) where end function __single_shooting_jacobian_ode_cache(prob, jac_cache, alg, u0, ode_alg; kwargs...) - prob_ = remake(prob; u0) - return SciMLBase.__init(prob_, ode_alg; kwargs...) + return SciMLBase.__init(remake(prob; u0), ode_alg; kwargs...) end function __single_shooting_jacobian_ode_cache(prob, jac_cache, @@ -130,6 +139,7 @@ function __single_shooting_jacobian_ode_cache(prob, jac_cache, xduals = cache.t end fill!(xduals, 0) - prob_ = remake(prob; u0 = reshape(xduals, size(u0))) + prob_ = remake(prob; u0 = reshape(xduals, size(u0)), + tspan = eltype(xduals).(prob.tspan)) return SciMLBase.__init(prob_, ode_alg; kwargs...) end diff --git a/src/sparse_jacobians.jl b/src/sparse_jacobians.jl index 1983d010..577d6e4b 100644 --- a/src/sparse_jacobians.jl +++ b/src/sparse_jacobians.jl @@ -82,10 +82,10 @@ end Returns a 3-Tuple: -* Entire Jacobian Prototype (if Two-Point Problem) else `nothing`. -* Sparse Non-BC Part Jacobian Prototype along with the column and row color vectors. -* Sparse BC Part Jacobian Prototype along with the column and row color vectors (if - Two-Point Problem) else `nothing`. + - Entire Jacobian Prototype (if Two-Point Problem) else `nothing`. + - Sparse Non-BC Part Jacobian Prototype along with the column and row color vectors. + - Sparse BC Part Jacobian Prototype along with the column and row color vectors (if + Two-Point Problem) else `nothing`. """ function __generate_sparse_jacobian_prototype(::MultipleShooting, ::StandardBVProblem, bcresid_prototype, u0, N::Int, nshoots::Int) diff --git a/src/types.jl b/src/types.jl index 0eb3db9b..098949d4 100644 --- a/src/types.jl +++ b/src/types.jl @@ -39,6 +39,31 @@ end diffmode end +@inline __materialize_jacobian_algorithm(_, alg::BVPJacobianAlgorithm) = alg +@inline __materialize_jacobian_algorithm(_, alg::ADTypes.AbstractADType) = BVPJacobianAlgorithm(alg) +@inline __materialize_jacobian_algorithm(::Nothing, ::Nothing) = BVPJacobianAlgorithm() +@inline function __materialize_jacobian_algorithm(nlsolve::N, ::Nothing) where {N} + ad = hasfield(N, :ad) ? nlsolve.ad : missing + return BVPJacobianAlgorithm(ad) +end + +function Base.show(io::IO, alg::BVPJacobianAlgorithm) + print(io, "BVPJacobianAlgorithm(") + modifiers = String[] + if alg.diffmode !== nothing && alg.diffmode !== missing + push!(modifiers, "diffmode = $(__nameof(alg.diffmode))()") + else + if alg.nonbc_diffmode !== missing && alg.nonbc_diffmode !== nothing + push!(modifiers, "nonbc_diffmode = $(__nameof(alg.nonbc_diffmode))()") + end + if alg.bc_diffmode !== missing && alg.bc_diffmode !== nothing + push!(modifiers, "bc_diffmode = $(__nameof(alg.bc_diffmode))()") + end + end + print(io, join(modifiers, ", ")) + print(io, ")") +end + __any_sparse_ad(ad) = ad isa AbstractSparseADType function __any_sparse_ad(jac_alg::BVPJacobianAlgorithm) __any_sparse_ad(jac_alg.bc_diffmode) || __any_sparse_ad(jac_alg.nonbc_diffmode) || diff --git a/src/utils.jl b/src/utils.jl index 8d872bc2..5c2a5d27 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -252,3 +252,127 @@ function __restructure_sol(sol::Vector{<:AbstractArray}, u_size) end # TODO: Add dispatch for a ODESolution Type as well + +# Override the checks for NonlinearFunction +struct __unsafe_nonlinearfunction{iip} end + +@inline function __unsafe_nonlinearfunction{iip}(f::F; jac::J = nothing, + jac_prototype::JP = nothing, colorvec::CV = nothing, + resid_prototype::RP = nothing) where {iip, F, J, JP, CV, RP} + return NonlinearFunction{iip, SciMLBase.FullSpecialize, F, Nothing, Nothing, Nothing, + J, Nothing, Nothing, JP, Nothing, Nothing, Nothing, Nothing, Nothing, CV, Nothing, + RP}(f, nothing, nothing, nothing, jac, nothing, nothing, jac_prototype, nothing, + nothing, nothing, nothing, nothing, colorvec, nothing, resid_prototype) +end + +@inline __nameof(::T) where {T} = nameof(T) +@inline __nameof(::Type{T}) where {T} = nameof(T) + +# Construct the internal NonlinearProblem +@inline function __internal_nlsolve_problem(::BVProblem{uType, tType, iip, nlls}, + resid_prototype, u0, args...; kwargs...) where {uType, tType, iip, nlls} + if nlls + return NonlinearLeastSquaresProblem(args...; kwargs...) + else + return NonlinearProblem(args...; kwargs...) + end +end + +@inline function __internal_nlsolve_problem(bvp::BVProblem{uType, tType, iip, Nothing}, + resid_prototype, u0, args...; kwargs...) where {uType, tType, iip} + return __internal_nlsolve_problem(bvp, length(resid_prototype), length(u0), args...; + kwargs...) +end + +@inline function __internal_nlsolve_problem(::BVProblem{uType, tType, iip, Nothing}, + l1::Int, l2::Int, args...; kwargs...) where {uType, tType, iip} + if l1 != l2 + return NonlinearLeastSquaresProblem(args...; kwargs...) + else + return NonlinearProblem(args...; kwargs...) + end +end + +# Handling Initial Guesses +""" + __extract_u0(u₀, t₀) + +Takes the input initial guess and returns the value at the starting mesh point. +""" +@inline __extract_u0(u₀::AbstractVector{<:AbstractArray}, p, t₀) = u₀[1] +@inline __extract_u0(u₀::VectorOfArray, p, t₀) = u₀[:, 1] +@inline __extract_u0(u₀::DiffEqArray, p, t₀) = u₀.u[1] +@inline __extract_u0(u₀::F, p, t₀) where {F <: Function} = __initial_guess(u₀, p, t₀) +@inline __extract_u0(u₀::AbstractArray, p, t₀) = u₀ +@inline __extract_u0(u₀::T, p, t₀) where {T} = error("`prob.u0::$(T)` is not supported.") + +""" + __extract_mesh(u₀, t₀, t₁, n) + +Takes the input initial guess and returns the mesh. +""" +@inline __extract_mesh(u₀, t₀, t₁, n::Int) = collect(range(t₀; stop = t₁, length = n + 1)) +@inline __extract_mesh(u₀, t₀, t₁, dt::Number) = collect(t₀:dt:t₁) +@inline __extract_mesh(u₀::DiffEqArray, t₀, t₁, n) = u₀.t + +""" + __has_initial_guess(u₀) -> Bool + +Returns `true` if the input has an initial guess. +""" +@inline __has_initial_guess(u₀::AbstractVector{<:AbstractArray}) = true +@inline __has_initial_guess(u₀::VectorOfArray) = true +@inline __has_initial_guess(u₀::DiffEqArray) = true +@inline __has_initial_guess(u₀::F) where {F} = true +@inline __has_initial_guess(u₀::AbstractArray) = false + +""" + __initial_guess_length(u₀) -> Int + +Returns the length of the initial guess. If the initial guess is a function or no initial +guess is supplied, it returns `-1`. +""" +@inline __initial_guess_length(u₀::AbstractVector{<:AbstractArray}) = length(u₀) +@inline __initial_guess_length(u₀::VectorOfArray) = length(u₀) +@inline __initial_guess_length(u₀::DiffEqArray) = length(u₀.t) +@inline __initial_guess_length(u₀::F) where {F} = -1 +@inline __initial_guess_length(u₀::AbstractArray) = -1 + +""" + __flatten_initial_guess(u₀) -> Union{AbstractMatrix, AbstractVector, Nothing} + +Flattens the initial guess into a matrix. For a function `u₀`, it returns `nothing`. For no +initial guess, it returns `vec(u₀)`. +""" +@inline __flatten_initial_guess(u₀::AbstractVector{<:AbstractArray}) = mapreduce(vec, + hcat, u₀) +@inline __flatten_initial_guess(u₀::VectorOfArray) = mapreduce(vec, hcat, u₀.u) +@inline __flatten_initial_guess(u₀::DiffEqArray) = mapreduce(vec, hcat, u₀.u) +@inline __flatten_initial_guess(u₀::AbstractArray) = vec(u₀) +@inline __flatten_initial_guess(u₀::F) where {F} = nothing + +""" + __initial_guess_on_mesh(u₀, mesh, p, alias_u0::Bool) + +Returns the initial guess on the mesh. For `DiffEqArray` assumes that the mesh is the same +as the mesh of the `DiffEqArray`. + +If `alias_u0` is set to `true`, we try our best to minimize copies. This means that `u₀` +or parts of it will get mutated. +""" +@inline function __initial_guess_on_mesh(u₀::AbstractVector{<:AbstractArray}, _, p, + alias_u0::Bool) + return alias_u0 ? vec.(u₀) : [copy(vec(u)) for u in u₀] +end +@inline function __initial_guess_on_mesh(u₀::VectorOfArray, _, p, alias_u0::Bool) + return alias_u0 ? u₀.u : [copy(vec(u)) for u in u₀.u] +end +@inline function __initial_guess_on_mesh(u₀::DiffEqArray, mesh, p, alias_u0::Bool) + return alias_u0 ? u₀.u : [copy(vec(u)) for u in u₀.u] +end +@inline function __initial_guess_on_mesh(u₀::AbstractArray, mesh, p, alias_u0::Bool) + return [copy(vec(u₀)) for _ in mesh] +end +@inline function __initial_guess_on_mesh(u₀::F, mesh, p, alias_u0::Bool) where {F} + return [vec(__initial_guess(u₀, p, t)) for t in mesh] +end diff --git a/test/runtests.jl b/test/runtests.jl index efd5464a..4b9d674a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,21 +5,14 @@ const GROUP = uppercase(get(ENV, "GROUP", "ALL")) @testset "Boundary Value Problem Tests" begin if GROUP == "ALL" || GROUP == "SHOOTING" @time @testset "Shooting Method Tests" begin - @time @safetestset "Shooting Tests" begin - include("shooting/shooting_tests.jl") + @time @safetestset "Basic Problems" begin + include("shooting/basic_problems.jl") end - @time @safetestset "Ray Tracing BVP" begin - include("shooting/ray_tracing.jl") + @time @safetestset "Orbital" begin + include("shooting/orbital.jl") end - if VERSION ≥ v"1.10-" - @time @safetestset "Orbital" begin - include("shooting/orbital.jl") - end - end - if VERSION ≥ v"1.10-" - @time @safetestset "Shooting NLLS Tests" begin - include("shooting/nonlinear_least_squares.jl") - end + @time @safetestset "Shooting NLLS Tests" begin + include("shooting/nonlinear_least_squares.jl") end end end @@ -68,4 +61,4 @@ const GROUP = uppercase(get(ENV, "GROUP", "ALL")) end end end -end +end \ No newline at end of file diff --git a/test/shooting/basic_tests.jl b/test/shooting/basic_tests.jl new file mode 100644 index 00000000..8f99d115 --- /dev/null +++ b/test/shooting/basic_tests.jl @@ -0,0 +1,324 @@ +using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test + +@testset "Basic Shooting Tests" begin + SOLVERS = [Shooting(Tsit5()), MultipleShooting(10, Tsit5())] + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] + + # Inplace + function f1!(du, u, p, t) + du[1] = u[2] + du[2] = -u[1] + return nothing + end + + function bc1!(resid, sol, p, t) + t₀, t₁ = first(t), last(t) + resid[1] = sol(t₀)[1] + resid[2] = sol(t₁)[1] - 1 + return nothing + end + + @info "Basic MP Shooting IIP" + + bvp1 = BVProblem(f1!, bc1!, u0, tspan) + @test SciMLBase.isinplace(bvp1) + for solver in SOLVERS + @info "Solver: $solver" + resid_f = Array{Float64}(undef, 2) + sol = @time solve(bvp1, solver; abstol = 1e-13, reltol = 1e-13, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) + @test SciMLBase.successful_retcode(sol) + bc1!(resid_f, sol, nothing, sol.t) + @test norm(resid_f, Inf) < 1e-12 + end + + # Out of Place + f1(u, p, t) = [u[2], -u[1]] + + function bc1(sol, p, t) + t₀, t₁ = first(t), last(t) + return [sol(t₀)[1], sol(t₁)[1] - 1] + end + + @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1!, bc1, u0, tspan) + @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1, bc1!, u0, tspan) + + @info "Basic MP Shooting OOP" + + bvp2 = BVProblem(f1, bc1, u0, tspan) + @test !SciMLBase.isinplace(bvp2) + for solver in SOLVERS + @info "Solver: $solver" + sol = @time solve(bvp2, solver; abstol = 1e-13, reltol = 1e-13, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) + @test SciMLBase.successful_retcode(sol) + resid_f = bc1(sol, nothing, sol.t) + @test norm(resid_f, Inf) < 1e-12 + end + + # Inplace + bc2a!(resid, ua, p) = (resid[1] = ua[1]) + bc2b!(resid, ub, p) = (resid[1] = ub[1] - 1) + + @info "Basic TP Shooting IIP" + + bvp3 = TwoPointBVProblem(f1!, (bc2a!, bc2b!), u0, tspan; + bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1))) + @test SciMLBase.isinplace(bvp3) + for solver in SOLVERS + @info "Solver: $solver" + sol = @time solve(bvp3, solver; abstol = 1e-13, reltol = 1e-13, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) + @test SciMLBase.successful_retcode(sol) + resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) + bc2a!(resid_f[1], sol(tspan[1]), nothing) + bc2b!(resid_f[2], sol(tspan[2]), nothing) + @test norm(reduce(vcat, resid_f), Inf) < 1e-12 + end + + # Out of Place + bc2a(ua, p) = [ua[1]] + bc2b(ub, p) = [ub[1] - 1] + + @info "Basic TP Shooting OOP" + + bvp4 = TwoPointBVProblem(f1, (bc2a, bc2b), u0, tspan) + @test !SciMLBase.isinplace(bvp4) + for solver in SOLVERS + @info "Solver: $solver" + sol = @time solve(bvp4, solver; abstol = 1e-13, reltol = 1e-13, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) + @test SciMLBase.successful_retcode(sol) + resid_f = reduce(vcat, (bc2a(sol(tspan[1]), nothing), bc2b(sol(tspan[2]), nothing))) + @test norm(resid_f, Inf) < 1e-12 + end +end + +@testset "Shooting with Complex Values" begin + function f1!(du, u, p, t) + du[1] = u[2] + du[2] = -u[1] + return nothing + end + + function bc1!(resid, sol, p, t) + t₀, t₁ = first(t), last(t) + resid[1] = sol(t₀)[1] + resid[2] = sol(t₁)[1] - 1 + return nothing + end + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] .+ 1im + bvp = BVProblem(f1!, bc1!, u0, tspan) + resid_f = Array{ComplexF64}(undef, 2) + + @info "Shooting with Complex Values" + + for solver in [Shooting(Vern7()), MultipleShooting(10, Vern7())] + @info "Solver: $solver" + sol = @time solve(bvp, solver; abstol = 1e-13, reltol = 1e-13, + odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-8)) + @test SciMLBase.successful_retcode(sol) + bc1!(resid_f, sol, nothing, sol.t) + @test norm(resid_f, Inf) < 1e-12 + end +end + +@testset "Flow In a Channel" begin + function flow_in_a_channel!(du, u, p, t) + R, P = p + A, f′′, f′, f, h′, h, θ′, θ = u + du[1] = 0 + du[2] = R * (f′^2 - f * f′′) - R * A + du[3] = f′′ + du[4] = f′ + du[5] = -R * f * h′ - 1 + du[6] = h′ + du[7] = -P * f * θ′ + du[8] = θ′ + end + + function bc_flow!(resid, sol, p, tspan) + t₁, t₂ = extrema(tspan) + solₜ₁ = sol(t₁) + solₜ₂ = sol(t₂) + resid[1] = solₜ₁[4] + resid[2] = solₜ₁[3] + resid[3] = solₜ₂[4] - 1 + resid[4] = solₜ₂[3] + resid[5] = solₜ₁[6] + resid[6] = solₜ₂[6] + resid[7] = solₜ₁[8] + resid[8] = solₜ₂[8] - 1 + end + + tspan = (0.0, 1.0) + p = [10.0, 7.0] + u0 = zeros(8) + + flow_bvp = BVProblem{true}(flow_in_a_channel!, bc_flow!, u0, tspan, p) + + @info "Flow in a Channel" + + for solver in [ + Shooting(AutoTsit5(Rosenbrock23())), + MultipleShooting(10, AutoTsit5(Rosenbrock23())), + ] + @info "Solver: $solver" + sol = @time solve(flow_bvp, solver; abstol = 1e-13, reltol = 1e-13, + odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-8)) + @test SciMLBase.successful_retcode(sol) + resid = zeros(8) + bc_flow!(resid, sol, p, sol.t) + @test norm(resid, Inf) < 1e-6 + end +end + +@testset "Ray Tracing" begin + @inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) + @inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) + @inline uy(x, y, z, p) = p[2] * cos(p[2] * y) + @inline uz(x, y, z, p) = p[3] * sin(p[3] * z) + + function ray_tracing(u, p, t) + du = similar(u) + ray_tracing!(du, u, p, t) + return du + end + + function ray_tracing!(du, u, p, t) + x, y, z, ξ, η, ζ, T, S = u + + nu = v(x, y, z, p) # Velocity of a sound wave, function of space; + μx = ux(x, y, z, p) # ∂(slowness)/∂x, function of space + μy = uy(x, y, z, p) # ∂(slowness)/∂y, function of space + μz = uz(x, y, z, p) # ∂(slowness)/∂z, function of space + + du[1] = S * nu * ξ + du[2] = S * nu * η + du[3] = S * nu * ζ + + du[4] = S * μx + du[5] = S * μy + du[6] = S * μz + + du[7] = S / nu + du[8] = 0 + + return nothing + end + + function ray_tracing_bc(sol, p, t) + res = similar(first(sol)) + ray_tracing_bc!(res, sol, p, t) + return res + end + + function ray_tracing_bc!(res, sol, p, t) + ua = sol(0.0) + ub = sol(1.0) + nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; + + res[1] = ua[1] - p[4] + res[2] = ua[2] - p[5] + res[3] = ua[3] - p[6] + res[4] = ua[7] # T(0) = 0 + res[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 + res[6] = ub[1] - p[7] + res[7] = ub[2] - p[8] + res[8] = ub[3] - p[9] + return nothing + end + + function ray_tracing_bc_a(ua, p) + resa = similar(ua, 5) + ray_tracing_bc_a!(resa, ua, p) + return resa + end + + function ray_tracing_bc_a!(resa, ua, p) + nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; + + resa[1] = ua[1] - p[4] + resa[2] = ua[2] - p[5] + resa[3] = ua[3] - p[5] + resa[4] = ua[7] + resa[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 + + return nothing + end + + function ray_tracing_bc_b(ub, p) + resb = similar(ub, 3) + ray_tracing_bc_b!(resb, ub, p) + return resb + end + + function ray_tracing_bc_b!(resb, ub, p) + resb[1] = ub[1] - p[7] + resb[2] = ub[2] - p[8] + resb[3] = ub[3] - p[9] + return nothing + end + + p = [0, 1, 2, 0, 0, 0, 4, 3, 2.0] + + dx = p[7] - p[4] + dy = p[8] - p[5] + dz = p[9] - p[6] + + u0 = zeros(8) + u0[1:3] .= 0 # position + u0[4] = dx / v(p[4], p[5], p[6], p) + u0[5] = dy / v(p[4], p[5], p[6], p) + u0[6] = dz / v(p[4], p[5], p[6], p) + u0[8] = 1 + + tspan = (0.0, 1.0) + + prob_oop = BVProblem(BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; + nlls = Val(false)) + prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; + nlls = Val(true)) + prob_tp_oop = BVProblem(BVPFunction{false}(ray_tracing, + (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; + nlls = Val(true)) + prob_tp_iip = BVProblem(BVPFunction{true}(ray_tracing!, + (ray_tracing_bc_a!, ray_tracing_bc_b!); + bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; + nlls = Val(true)) + + @info "Ray Tracing: Multiple Shooting" + + alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, + nlsolve = TrustRegion(), + jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), + nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 8))) + alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, + nlsolve = TrustRegion(), + jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), + nonbc_diffmode = AutoForwardDiff(; chunksize = 8))) + alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) + + for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), + (alg_sp, alg_dense, alg_default)) + @info "Solver: $alg" + @time sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, + odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-5)) + @test SciMLBase.successful_retcode(sol.retcode) + + if prob.problem_type isa TwoPointBVProblem + resida, residb = zeros(5), zeros(3) + ray_tracing_bc_a!(resida, sol.u[1], p) + ray_tracing_bc_b!(residb, sol.u[end], p) + @test norm(vcat(resida, residb), Inf) < 1e-6 + else + resid = zeros(8) + ray_tracing_bc!(resid, sol, p, sol.t) + @test norm(resid, Inf) < 1e-6 + end + end +end \ No newline at end of file diff --git a/test/shooting/nonlinear_least_squares.jl b/test/shooting/nonlinear_least_squares.jl index d1142d46..7fac9eb3 100644 --- a/test/shooting/nonlinear_least_squares.jl +++ b/test/shooting/nonlinear_least_squares.jl @@ -1,4 +1,4 @@ -using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test +using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test @testset "Overconstrained BVP" begin SOLVERS = [ @@ -9,6 +9,8 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test MultipleShooting(10, Tsit5(); nlsolve = GaussNewton()), MultipleShooting(10, Tsit5(); nlsolve = TrustRegion())] + @info "Solving Overconstrained BVPs" + # OOP MP-BVP f1(u, p, t) = [u[2], -u[1]] @@ -24,11 +26,14 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test tspan = (0.0, 100.0) u0 = [0.0, 1.0] - bvp1 = BVProblem(BVPFunction{false}(f1, bc1; bcresid_prototype = zeros(4)), u0, tspan) + bvp1 = BVProblem(BVPFunction{false}(f1, bc1; bcresid_prototype = zeros(4)), u0, tspan; + nlls = Val(true)) for solver in SOLVERS - sol = @time solve(bvp1, solver; verbose = false) - @test norm(bc1(sol, nothing, sol.t), Inf) < 1e-4 + @info "Testing $solver" + sol = @time solve(bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.005 end # IIP MP-BVP @@ -51,46 +56,39 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test return nothing end - bvp2 = BVProblem(BVPFunction{true}(f1!, bc1!; bcresid_prototype = zeros(4)), u0, tspan) + bvp2 = BVProblem(BVPFunction{true}(f1!, bc1!; bcresid_prototype = zeros(4)), u0, tspan; + nlls = Val(true)) for solver in SOLVERS - sol = @time solve(bvp2, solver; verbose = false) - resid_f = Array{Float64}(undef, 4) - bc1!(resid_f, sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-4 + @info "Testing $solver" + sol = @time solve(bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.005 end # OOP TP-BVP bc1a(ua, p) = [ua[1]] bc1b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - bvp3 = TwoPointBVProblem( - BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), - bcresid_prototype = (zeros(1), zeros(2))), - u0, - tspan) + bvp3 = BVProblem(BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), + bcresid_prototype = (zeros(1), zeros(2))), u0, tspan; nlls = Val(true)) for solver in SOLVERS + @info "Testing $solver" sol = @time solve(bvp3, solver; verbose = false) - @test norm(vcat(bc1a(sol(0.0), nothing), bc1b(sol(100.0), nothing)), Inf) < 1e-4 + @test norm(sol.resid, Inf) < 1e-4 end # IIP TP-BVP bc1a!(resid, ua, p) = (resid[1] = ua[1]) bc1b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - bvp4 = TwoPointBVProblem( - BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), - bcresid_prototype = (zeros(1), zeros(2))), - u0, - tspan) + bvp4 = BVProblem(BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), + bcresid_prototype = (zeros(1), zeros(2))), u0, tspan; nlls = Val(true)) for solver in SOLVERS + @info "Testing $solver" sol = @time solve(bvp4, solver; verbose = false) - resida = Array{Float64}(undef, 1) - residb = Array{Float64}(undef, 2) - bc1a!(resida, sol(0.0), nothing) - bc1b!(residb, sol(100.0), nothing) - @test norm(vcat(resida, residb), Inf) < 1e-4 + @test norm(sol.resid, Inf) < 1e-4 end -end +end \ No newline at end of file diff --git a/test/shooting/orbital.jl b/test/shooting/orbital.jl index ff4337d9..552e809c 100644 --- a/test/shooting/orbital.jl +++ b/test/shooting/orbital.jl @@ -1,112 +1,127 @@ # Lambert's Problem using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test -y0 = [ - -4.7763169762853989E+06, - -3.8386398704441520E+05, - -5.3500183933132319E+06, - -5528.612564911408, - 1216.8442360202787, - 4845.114446429901 -] -init_val = [ - -4.7763169762853989E+06, - -3.8386398704441520E+05, - -5.3500183933132319E+06, - 7.0526926403748598E+06, - -7.9650476230388973E+05, - -1.1911128863666430E+06 -] -J2 = 1.08262668E-3 -req = 6378137 -myu = 398600.4418E+9 -t0 = 86400 * 2.3577475462484435E+04 -t1 = 86400 * 2.3577522023524125E+04 -tspan = (t0, t1) +@testset "Lambert's Problem" begin + y0 = [ + -4.7763169762853989E+06, + -3.8386398704441520E+05, + -5.3500183933132319E+06, + -5528.612564911408, + 1216.8442360202787, + 4845.114446429901, + ] + init_val = [ + -4.7763169762853989E+06, + -3.8386398704441520E+05, + -5.3500183933132319E+06, + 7.0526926403748598E+06, + -7.9650476230388973E+05, + -1.1911128863666430E+06, + ] + J2 = 1.08262668E-3 + req = 6378137 + myu = 398600.4418E+9 + t0 = 86400 * 2.3577475462484435E+04 + t1 = 86400 * 2.3577522023524125E+04 + tspan = (t0, t1) -# ODE solver -function orbital!(dy, y, p, t) - r2 = (y[1]^2 + y[2]^2 + y[3]^2) - r3 = r2^(3 / 2) - w = 1 + 1.5J2 * (req * req / r2) * (1 - 5y[3] * y[3] / r2) - w2 = 1 + 1.5J2 * (req * req / r2) * (3 - 5y[3] * y[3] / r2) - dy[1] = y[4] - dy[2] = y[5] - dy[3] = y[6] - dy[4] = -myu * y[1] * w / r3 - dy[5] = -myu * y[2] * w / r3 - dy[6] = -myu * y[3] * w2 / r3 -end + # ODE solver + function orbital!(dy, y, p, t) + r2 = (y[1]^2 + y[2]^2 + y[3]^2) + r3 = r2^(3 / 2) + w = 1 + 1.5J2 * (req * req / r2) * (1 - 5y[3] * y[3] / r2) + w2 = 1 + 1.5J2 * (req * req / r2) * (3 - 5y[3] * y[3] / r2) + dy[1] = y[4] + dy[2] = y[5] + dy[3] = y[6] + dy[4] = -myu * y[1] * w / r3 + dy[5] = -myu * y[2] * w / r3 + dy[6] = -myu * y[3] * w2 / r3 + end -function bc!_generator(resid, sol, init_val) - resid[1] = sol(t0)[1] - init_val[1] - resid[2] = sol(t0)[2] - init_val[2] - resid[3] = sol(t0)[3] - init_val[3] - resid[4] = sol(t1)[1] - init_val[4] - resid[5] = sol(t1)[2] - init_val[5] - resid[6] = sol(t1)[3] - init_val[6] -end + function bc!_generator(resid, sol, init_val) + resid[1] = sol(t0)[1] - init_val[1] + resid[2] = sol(t0)[2] - init_val[2] + resid[3] = sol(t0)[3] - init_val[3] + resid[4] = sol(t1)[1] - init_val[4] + resid[5] = sol(t1)[2] - init_val[5] + resid[6] = sol(t1)[3] - init_val[6] + end -function bc!_generator_2p_a(resid0, ua, init_val) - resid0[1] = ua[1] - init_val[1] - resid0[2] = ua[2] - init_val[2] - resid0[3] = ua[3] - init_val[3] -end -function bc!_generator_2p_b(resid1, ub, init_val) - resid1[1] = ub[1] - init_val[4] - resid1[2] = ub[2] - init_val[5] - resid1[3] = ub[3] - init_val[6] -end + function bc!_generator_2p_a(resid0, ua, init_val) + resid0[1] = ua[1] - init_val[1] + resid0[2] = ua[2] - init_val[2] + resid0[3] = ua[3] - init_val[3] + end + function bc!_generator_2p_b(resid1, ub, init_val) + resid1[1] = ub[1] - init_val[4] + resid1[2] = ub[2] - init_val[5] + resid1[3] = ub[3] - init_val[6] + end -cur_bc! = (resid, sol, p, t) -> bc!_generator(resid, sol, init_val) -cur_bc_2point_a! = (resid, sol, p) -> bc!_generator_2p_a(resid, sol, init_val) -cur_bc_2point_b! = (resid, sol, p) -> bc!_generator_2p_b(resid, sol, init_val) -resid_f = Array{Float64}(undef, 6) -resid_f_2p = (Array{Float64, 1}(undef, 3), Array{Float64, 1}(undef, 3)) + cur_bc! = (resid, sol, p, t) -> bc!_generator(resid, sol, init_val) + cur_bc_2point_a! = (resid, sol, p) -> bc!_generator_2p_a(resid, sol, init_val) + cur_bc_2point_b! = (resid, sol, p) -> bc!_generator_2p_b(resid, sol, init_val) + resid_f = Array{Float64}(undef, 6) + resid_f_2p = (Array{Float64, 1}(undef, 3), Array{Float64, 1}(undef, 3)) -### Now use the BVP solver to get closer -bvp = BVProblem(orbital!, cur_bc!, y0, tspan) -for autodiff in ( - AutoForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:central)), - AutoSparseForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:forward)), - AutoSparseFiniteDiff()) - nlsolve = TrustRegion(; autodiff) - @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-13, - reltol = 1e-13, verbose = false) - cur_bc!(resid_f, sol, nothing, sol.t) - @info "Single Shooting Lambert's Problem: $(norm(resid_f, Inf))" - @test norm(resid_f, Inf) < 0.005 + @info "Solving Lambert's Problem in Multi Point BVP Form" - # Older versions take too long on the first run - jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff) - @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); - force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false) - cur_bc!(resid_f, sol, nothing, sol.t) - @info "Multiple Shooting Lambert's Problem: $(norm(resid_f, Inf))" - @test norm(resid_f, Inf) < 0.005 -end + bvp = BVProblem(orbital!, cur_bc!, y0, tspan; nlls = Val(false)) + for autodiff in (AutoForwardDiff(; chunksize = 6), + AutoFiniteDiff(; fdtype = Val(:central)), AutoSparseForwardDiff(; chunksize = 6), + AutoFiniteDiff(; fdtype = Val(:forward)), AutoSparseFiniteDiff()) + nlsolve = TrustRegion(; autodiff) + @info "Single Shooting Lambert's Problem: $(autodiff)" + @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, + reltol = 1e-6, verbose = false, + odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + cur_bc!(resid_f, sol, nothing, sol.t) + @info "Single Shooting Lambert's Problem: $(norm(resid_f, Inf))" + @test SciMLBase.successful_retcode(sol) + @test norm(resid_f, Inf) < 1e-6 -### Using the TwoPoint BVP Structure -bvp = TwoPointBVProblem(orbital!, (cur_bc_2point_a!, cur_bc_2point_b!), y0, tspan; - bcresid_prototype = (Array{Float64}(undef, 3), Array{Float64}(undef, 3))) -for autodiff in ( - AutoForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:central)), - AutoSparseForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:forward)), - AutoSparseFiniteDiff()) - nlsolve = TrustRegion(; autodiff) - @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-13, - reltol = 1e-13, verbose = false) - cur_bc_2point_a!(resid_f_2p[1], sol(t0), nothing) - cur_bc_2point_b!(resid_f_2p[2], sol(t1), nothing) - @info "Single Shooting Lambert's Problem: $(norm(reduce(vcat, resid_f_2p), Inf))" - @test norm(reduce(vcat, resid_f_2p), Inf) < 0.005 + @info "Multiple Shooting Lambert's Problem: $(autodiff)" + jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, + bc_diffmode = BoundaryValueDiffEq.__get_non_sparse_ad(autodiff)) + @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); + force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, + odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + cur_bc!(resid_f, sol, nothing, sol.t) + @info "Multiple Shooting Lambert's Problem: $(norm(resid_f, Inf))" + @test SciMLBase.successful_retcode(sol) + @test norm(resid_f, Inf) < 1e-6 + end - # Older versions take too long on the first run - jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, bc_diffmode = autodiff) - @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); - force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false) - cur_bc_2point_a!(resid_f_2p[1], sol(t0), nothing) - cur_bc_2point_b!(resid_f_2p[2], sol(t1), nothing) - @info "Multiple Shooting Lambert's Problem: $(norm(reduce(vcat, resid_f_2p), Inf))" - @test norm(reduce(vcat, resid_f_2p), Inf) < 0.005 -end + println() + @info "Solving Lambert's Problem in Two Point BVP Form" + + bvp = TwoPointBVProblem(orbital!, (cur_bc_2point_a!, cur_bc_2point_b!), y0, tspan; + bcresid_prototype = (Array{Float64}(undef, 3), Array{Float64}(undef, 3)), + nlls = Val(false)) + for autodiff in (AutoForwardDiff(; chunksize = 6), AutoSparseFiniteDiff(), + AutoFiniteDiff(; fdtype = Val(:central)), AutoFiniteDiff(; fdtype = Val(:forward)), + AutoSparseForwardDiff(; chunksize = 6)) + nlsolve = TrustRegion(; autodiff) + @info "Single Shooting Lambert's Problem: $(autodiff)" + @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, + reltol = 1e-6, verbose = false, + odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + cur_bc_2point_a!(resid_f_2p[1], sol(t0), nothing) + cur_bc_2point_b!(resid_f_2p[2], sol(t1), nothing) + @info "Single Shooting Lambert's Problem: $(norm(reduce(vcat, resid_f_2p), Inf))" + @test SciMLBase.successful_retcode(sol) + @test norm(reduce(vcat, resid_f_2p), Inf) < 1e-6 + + @info "Multiple Shooting Lambert's Problem: $(autodiff)" + jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, bc_diffmode = autodiff) + @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); + force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, + odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + cur_bc_2point_a!(resid_f_2p[1], sol(t0), nothing) + cur_bc_2point_b!(resid_f_2p[2], sol(t1), nothing) + @info "Multiple Shooting Lambert's Problem: $(norm(reduce(vcat, resid_f_2p), Inf))" + @test SciMLBase.successful_retcode(sol) + @test norm(reduce(vcat, resid_f_2p), Inf) < 1e-6 + end +end \ No newline at end of file diff --git a/test/shooting/ray_tracing.jl b/test/shooting/ray_tracing.jl deleted file mode 100644 index d913c6f6..00000000 --- a/test/shooting/ray_tracing.jl +++ /dev/null @@ -1,134 +0,0 @@ -using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test - -@inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) -@inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) -@inline uy(x, y, z, p) = p[2] * cos(p[2] * y) -@inline uz(x, y, z, p) = p[3] * sin(p[3] * z) - -function ray_tracing(u, p, t) - du = similar(u) - ray_tracing!(du, u, p, t) - return du -end - -function ray_tracing!(du, u, p, t) - x, y, z, ξ, η, ζ, T, S = u - - nu = v(x, y, z, p) # Velocity of a sound wave, function of space; - μx = ux(x, y, z, p) # ∂(slowness)/∂x, function of space - μy = uy(x, y, z, p) # ∂(slowness)/∂y, function of space - μz = uz(x, y, z, p) # ∂(slowness)/∂z, function of space - - du[1] = S * nu * ξ - du[2] = S * nu * η - du[3] = S * nu * ζ - - du[4] = S * μx - du[5] = S * μy - du[6] = S * μz - - du[7] = S / nu - du[8] = 0 - - return nothing -end - -function ray_tracing_bc(sol, p, t) - res = similar(first(sol)) - ray_tracing_bc!(res, sol, p, t) - return res -end - -function ray_tracing_bc!(res, sol, p, t) - ua = sol(0.0) - ub = sol(1.0) - nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; - - res[1] = ua[1] - p[4] - res[2] = ua[2] - p[5] - res[3] = ua[3] - p[6] - res[4] = ua[7] # T(0) = 0 - res[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 - res[6] = ub[1] - p[7] - res[7] = ub[2] - p[8] - res[8] = ub[3] - p[9] - return nothing -end - -function ray_tracing_bc_a(ua, p) - resa = similar(ua, 5) - ray_tracing_bc_a!(resa, ua, p) - return resa -end - -function ray_tracing_bc_a!(resa, ua, p) - nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; - - resa[1] = ua[1] - p[4] - resa[2] = ua[2] - p[5] - resa[3] = ua[3] - p[5] - resa[4] = ua[7] - resa[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 - - return nothing -end - -function ray_tracing_bc_b(ub, p) - resb = similar(ub, 3) - ray_tracing_bc_b!(resb, ub, p) - return resb -end - -function ray_tracing_bc_b!(resb, ub, p) - resb[1] = ub[1] - p[7] - resb[2] = ub[2] - p[8] - resb[3] = ub[3] - p[9] - return nothing -end - -p = [0, 1, 2, 0, 0, 0, 4, 3, 2.0] - -dx = p[7] - p[4] -dy = p[8] - p[5] -dz = p[9] - p[6] - -u0 = zeros(8) -u0[1:3] .= 0 # position -u0[4] = dx / v(p[4], p[5], p[6], p) -u0[5] = dy / v(p[4], p[5], p[6], p) -u0[6] = dz / v(p[4], p[5], p[6], p) -u0[8] = 1 - -tspan = (0.0, 1.0) - -prob_oop = BVProblem{false}(ray_tracing, ray_tracing_bc, u0, tspan, p) -prob_iip = BVProblem{true}(ray_tracing!, ray_tracing_bc!, u0, tspan, p) -prob_tp_oop = TwoPointBVProblem{false}(ray_tracing, (ray_tracing_bc_a, ray_tracing_bc_b), - u0, tspan, p) -prob_tp_iip = TwoPointBVProblem{true}(ray_tracing!, (ray_tracing_bc_a!, ray_tracing_bc_b!), - u0, tspan, p; bcresid_prototype = (zeros(5), zeros(3))) - -alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, - jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(), - nonbc_diffmode = AutoSparseForwardDiff())) -alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, - jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(), - nonbc_diffmode = AutoForwardDiff())) -alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) - -for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), - (alg_sp, alg_dense, alg_default)) - @time sol = solve(prob, alg; abstol = 1e-9, reltol = 1e-9, maxiters = 1000) - @test SciMLBase.successful_retcode(sol.retcode) - - if prob.problem_type isa TwoPointBVProblem - resida, residb = zeros(5), zeros(3) - ray_tracing_bc_a!(resida, sol.u[1], p) - ray_tracing_bc_b!(residb, sol.u[end], p) - @test norm(vcat(resida, residb), Inf) < 5e-5 - else - resid = zeros(8) - ray_tracing_bc!(resid, sol, p, sol.t) - @test norm(resid, Inf) < 5e-5 - end -end diff --git a/test/shooting/shooting_tests.jl b/test/shooting/shooting_tests.jl deleted file mode 100644 index 10f58978..00000000 --- a/test/shooting/shooting_tests.jl +++ /dev/null @@ -1,175 +0,0 @@ -using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test - -@testset "Basic Shooting Tests" begin - SOLVERS = [Shooting(Tsit5()), MultipleShooting(10, Tsit5())] - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] - - # Inplace - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - return nothing - end - - function bc1!(resid, sol, p, t) - t₀, t₁ = first(t), last(t) - resid[1] = sol(t₀)[1] - resid[2] = sol(t₁)[1] - 1 - return nothing - end - - bvp1 = BVProblem(f1!, bc1!, u0, tspan) - @test SciMLBase.isinplace(bvp1) - for solver in SOLVERS - resid_f = Array{Float64}(undef, 2) - sol = solve(bvp1, solver; abstol = 1e-13, reltol = 1e-13) - @test SciMLBase.successful_retcode(sol) - bc1!(resid_f, sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-12 - end - - # Out of Place - f1(u, p, t) = [u[2], -u[1]] - - function bc1(sol, p, t) - t₀, t₁ = first(t), last(t) - return [sol(t₀)[1], sol(t₁)[1] - 1] - end - - @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1!, bc1, u0, tspan) - @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1, bc1!, u0, tspan) - - bvp2 = BVProblem(f1, bc1, u0, tspan) - @test !SciMLBase.isinplace(bvp2) - for solver in SOLVERS - sol = solve(bvp2, solver; abstol = 1e-13, reltol = 1e-13) - @test SciMLBase.successful_retcode(sol) - resid_f = bc1(sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-12 - end - - # Inplace - bc2a!(resid, ua, p) = (resid[1] = ua[1]) - bc2b!(resid, ub, p) = (resid[1] = ub[1] - 1) - - bvp3 = TwoPointBVProblem(f1!, (bc2a!, bc2b!), u0, tspan; - bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1))) - @test SciMLBase.isinplace(bvp3) - for solver in SOLVERS - sol = solve(bvp3, solver; abstol = 1e-13, reltol = 1e-13) - @test SciMLBase.successful_retcode(sol) - resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) - bc2a!(resid_f[1], sol(tspan[1]), nothing) - bc2b!(resid_f[2], sol(tspan[2]), nothing) - @test norm(reduce(vcat, resid_f), Inf) < 1e-12 - end - - # Out of Place - bc2a(ua, p) = [ua[1]] - bc2b(ub, p) = [ub[1] - 1] - - bvp4 = TwoPointBVProblem(f1, (bc2a, bc2b), u0, tspan) - @test !SciMLBase.isinplace(bvp4) - for solver in SOLVERS - sol = solve(bvp4, solver; abstol = 1e-13, reltol = 1e-13) - @test SciMLBase.successful_retcode(sol) - resid_f = reduce(vcat, (bc2a(sol(tspan[1]), nothing), bc2b(sol(tspan[2]), nothing))) - @test norm(resid_f, Inf) < 1e-12 - end -end - -@testset "Shooting with Complex Values" begin - # Test for complex values - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - return nothing - end - - function bc1!(resid, sol, p, t) - t₀, t₁ = first(t), last(t) - resid[1] = sol(t₀)[1] - resid[2] = sol(t₁)[1] - 1 - return nothing - end - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] .+ 1im - bvp = BVProblem(f1!, bc1!, u0, tspan) - resid_f = Array{ComplexF64}(undef, 2) - - # We will automatically use FiniteDiff if we can't use dual numbers - # Auto Selecting default solvers for Complex Valued Problems supported by a version of - # NonlinearSolve that is not yet compatible with BoundaryValueDiffEq - for solver in [Shooting(Tsit5(), NewtonRaphson()), - MultipleShooting(10, Tsit5(), nlsolve = NewtonRaphson())] - sol = solve(bvp, solver; abstol = 1e-13, reltol = 1e-13) - @test SciMLBase.successful_retcode(sol) - bc1!(resid_f, sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-12 - end -end - -@testset "Flow In a Channel" begin - function flow_in_a_channel!(du, u, p, t) - R, P = p - A, f′′, f′, f, h′, h, θ′, θ = u - du[1] = 0 - du[2] = R * (f′^2 - f * f′′) - R * A - du[3] = f′′ - du[4] = f′ - du[5] = -R * f * h′ - 1 - du[6] = h′ - du[7] = -P * f * θ′ - du[8] = θ′ - end - - function bc_flow!(resid, sol, p, tspan) - t₁, t₂ = extrema(tspan) - solₜ₁ = sol(t₁) - solₜ₂ = sol(t₂) - resid[1] = solₜ₁[4] - resid[2] = solₜ₁[3] - resid[3] = solₜ₂[4] - 1 - resid[4] = solₜ₂[3] - resid[5] = solₜ₁[6] - resid[6] = solₜ₂[6] - resid[7] = solₜ₁[8] - resid[8] = solₜ₂[8] - 1 - end - - tspan = (0.0, 1.0) - p = [10.0, 7.0] - u0 = zeros(8) - - flow_bvp = BVProblem{true}(flow_in_a_channel!, bc_flow!, u0, tspan, p) - - sol_shooting = solve(flow_bvp, - Shooting(AutoTsit5(Rosenbrock23()), NewtonRaphson()); - maxiters = 100) - @test SciMLBase.successful_retcode(sol_shooting) - - resid = zeros(8) - bc_flow!(resid, sol_shooting, p, sol_shooting.t) - @test norm(resid, Inf) < 1e-6 - - sol_msshooting = solve(flow_bvp, - MultipleShooting(10, AutoTsit5(Rosenbrock23()); nlsolve = NewtonRaphson()); - maxiters = 100) - @test SciMLBase.successful_retcode(sol_msshooting) - - resid = zeros(8) - bc_flow!(resid, sol_msshooting, p, sol_msshooting.t) - @test norm(resid, Inf) < 1e-6 -end - -@testset "Testing Deprecations" begin - @test_deprecated Shooting(Tsit5(); - nlsolve = NewtonRaphson(; autodiff = AutoForwardDiff(chunksize = 2))) - - alg = Shooting(Tsit5(); - nlsolve = NewtonRaphson(; autodiff = AutoForwardDiff(chunksize = 2))) - @test alg.jac_alg.diffmode == AutoForwardDiff(chunksize = 2) -end From 24b68bbcb48b5f62db9cf032f2c4c12c62c0ca89 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Dec 2023 16:48:19 -0500 Subject: [PATCH 02/24] Aggregate the ODEInterface improvements --- Manifest.toml | 1026 +++++++++++++++++++++ ext/BoundaryValueDiffEqODEInterfaceExt.jl | 157 +++- src/algorithms.jl | 86 +- test/misc/odeinterface.jl | 100 ++ 4 files changed, 1294 insertions(+), 75 deletions(-) create mode 100644 Manifest.toml create mode 100644 test/misc/odeinterface.jl diff --git a/Manifest.toml b/Manifest.toml new file mode 100644 index 00000000..6d6134b8 --- /dev/null +++ b/Manifest.toml @@ -0,0 +1,1026 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.0-rc2" +manifest_format = "2.0" +project_hash = "caa3a84a29ae467d2583d2084e7f50dd07a4148f" + +[[deps.ADTypes]] +git-tree-sha1 = "332e5d7baeff8497b923b730b994fa480601efc7" +uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" +version = "0.2.5" + +[[deps.Adapt]] +deps = ["LinearAlgebra", "Requires"] +git-tree-sha1 = "cde29ddf7e5726c9fb511f340244ea3481267608" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "3.7.2" +weakdeps = ["StaticArrays"] + + [deps.Adapt.extensions] + AdaptStaticArraysExt = "StaticArrays" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.1" + +[[deps.ArnoldiMethod]] +deps = ["LinearAlgebra", "Random", "StaticArrays"] +git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae" +uuid = "ec485272-7323-5ecc-a04f-4719b315124d" +version = "0.2.0" + +[[deps.ArrayInterface]] +deps = ["Adapt", "LinearAlgebra", "Requires", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "bbec08a37f8722786d87bedf84eae19c020c4efa" +uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" +version = "7.7.0" + + [deps.ArrayInterface.extensions] + ArrayInterfaceBandedMatricesExt = "BandedMatrices" + ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" + ArrayInterfaceCUDAExt = "CUDA" + ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" + ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" + ArrayInterfaceTrackerExt = "Tracker" + + [deps.ArrayInterface.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" + StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + +[[deps.ArrayLayouts]] +deps = ["FillArrays", "LinearAlgebra"] +git-tree-sha1 = "b08a4043e1c14096ef8efe4dd97e07de5cacf240" +uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" +version = "1.4.5" +weakdeps = ["SparseArrays"] + + [deps.ArrayLayouts.extensions] + ArrayLayoutsSparseArraysExt = "SparseArrays" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.BandedMatrices]] +deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "PrecompileTools"] +git-tree-sha1 = "27baf04c642465b4289179f29bb7127f0673d4f1" +uuid = "aae01518-5342-5314-be14-df237901396f" +version = "1.4.0" +weakdeps = ["SparseArrays"] + + [deps.BandedMatrices.extensions] + BandedMatricesSparseArraysExt = "SparseArrays" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.BitTwiddlingConvenienceFunctions]] +deps = ["Static"] +git-tree-sha1 = "0c5f81f47bbbcf4aea7b2959135713459170798b" +uuid = "62783981-4cbd-42fc-bca8-16325de8dc4b" +version = "0.1.5" + +[[deps.CPUSummary]] +deps = ["CpuId", "IfElse", "PrecompileTools", "Static"] +git-tree-sha1 = "601f7e7b3d36f18790e2caf83a882d88e9b71ff1" +uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" +version = "0.2.4" + +[[deps.CloseOpenIntervals]] +deps = ["Static", "StaticArrayInterface"] +git-tree-sha1 = "70232f82ffaab9dc52585e0dd043b5e0c6b714f1" +uuid = "fb6a15b2-703c-40df-9091-08a04967cfa9" +version = "0.1.12" + +[[deps.CommonSolve]] +git-tree-sha1 = "0eee5eb66b1cf62cd6ad1b460238e60e4b09400c" +uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" +version = "0.2.4" + +[[deps.CommonSubexpressions]] +deps = ["MacroTools", "Test"] +git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7" +uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" +version = "0.3.0" + +[[deps.Compat]] +deps = ["UUIDs"] +git-tree-sha1 = "886826d76ea9e72b35fcd000e535588f7b60f21d" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.10.1" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.0.5+1" + +[[deps.ConcreteStructs]] +git-tree-sha1 = "f749037478283d372048690eb3b5f92a79432b34" +uuid = "2569d6c7-a4a2-43d3-a901-331e8e4be471" +version = "0.2.3" + +[[deps.ConstructionBase]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "c53fc348ca4d40d7b371e71fd52251839080cbc9" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.5.4" + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseStaticArraysExt = "StaticArrays" + + [deps.ConstructionBase.weakdeps] + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.CpuId]] +deps = ["Markdown"] +git-tree-sha1 = "fcbb72b032692610bfbdb15018ac16a36cf2e406" +uuid = "adafc99b-e345-5852-983c-f28acb93d879" +version = "0.3.1" + +[[deps.DataAPI]] +git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.15.0" + +[[deps.DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.15" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.DiffEqBase]] +deps = ["ArrayInterface", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces"] +git-tree-sha1 = "8775b80752e9656000ab3800adad8ee22c9cb8f6" +uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" +version = "6.145.0" + + [deps.DiffEqBase.extensions] + DiffEqBaseChainRulesCoreExt = "ChainRulesCore" + DiffEqBaseDistributionsExt = "Distributions" + DiffEqBaseEnzymeExt = ["ChainRulesCore", "Enzyme"] + DiffEqBaseGeneralizedGeneratedExt = "GeneralizedGenerated" + DiffEqBaseMPIExt = "MPI" + DiffEqBaseMeasurementsExt = "Measurements" + DiffEqBaseMonteCarloMeasurementsExt = "MonteCarloMeasurements" + DiffEqBaseReverseDiffExt = "ReverseDiff" + DiffEqBaseTrackerExt = "Tracker" + DiffEqBaseUnitfulExt = "Unitful" + + [deps.DiffEqBase.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + GeneralizedGenerated = "6b9d7cbe-bcb9-11e9-073f-15a7a543e2eb" + MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.DiffResults]] +deps = ["StaticArraysCore"] +git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" +uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" +version = "1.1.0" + +[[deps.DiffRules]] +deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"] +git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272" +uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" +version = "1.15.1" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.EnumX]] +git-tree-sha1 = "bdb1942cd4c45e3c678fd11569d5cccd80976237" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.4" + +[[deps.EnzymeCore]] +deps = ["Adapt"] +git-tree-sha1 = "2efe862de93cd87f620ad6ac9c9e3f83f1b2841b" +uuid = "f151be2c-9106-41f4-ab19-57ee4f262869" +version = "0.6.4" + +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + +[[deps.FastAlmostBandedMatrices]] +deps = ["ArrayInterface", "ArrayLayouts", "BandedMatrices", "ConcreteStructs", "LazyArrays", "LinearAlgebra", "MatrixFactorizations", "PrecompileTools", "Reexport"] +git-tree-sha1 = "178316d87f883f0702e79d9c83a8049484c9f619" +uuid = "9d29842c-ecb8-4973-b1e9-a27b1157504e" +version = "0.1.0" + +[[deps.FastBroadcast]] +deps = ["ArrayInterface", "LinearAlgebra", "Polyester", "Static", "StaticArrayInterface", "StrideArraysCore"] +git-tree-sha1 = "a6e756a880fc419c8b41592010aebe6a5ce09136" +uuid = "7034ab61-46d4-4ed7-9d0f-46aef9175898" +version = "0.2.8" + +[[deps.FastClosures]] +git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" +uuid = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a" +version = "0.3.2" + +[[deps.FastLapackInterface]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "b12f05108e405dadcc2aff0008db7f831374e051" +uuid = "29a986be-02c6-4525-aec4-84b980013641" +version = "2.0.0" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" + +[[deps.FillArrays]] +deps = ["LinearAlgebra", "Random"] +git-tree-sha1 = "5b93957f6dcd33fc343044af3d48c215be2562f1" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.9.3" + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" + + [deps.FillArrays.weakdeps] + PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[deps.FiniteDiff]] +deps = ["ArrayInterface", "LinearAlgebra", "Requires", "Setfield", "SparseArrays"] +git-tree-sha1 = "c6e4a1fbe73b31a3dea94b1da449503b8830c306" +uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" +version = "2.21.1" + + [deps.FiniteDiff.extensions] + FiniteDiffBandedMatricesExt = "BandedMatrices" + FiniteDiffBlockBandedMatricesExt = "BlockBandedMatrices" + FiniteDiffStaticArraysExt = "StaticArrays" + + [deps.FiniteDiff.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.ForwardDiff]] +deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] +git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad" +uuid = "f6369f11-7733-5829-9624-2563aa707210" +version = "0.10.36" +weakdeps = ["StaticArrays"] + + [deps.ForwardDiff.extensions] + ForwardDiffStaticArraysExt = "StaticArrays" + +[[deps.FunctionWrappers]] +git-tree-sha1 = "d62485945ce5ae9c0c48f124a84998d755bae00e" +uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e" +version = "1.1.3" + +[[deps.FunctionWrappersWrappers]] +deps = ["FunctionWrappers"] +git-tree-sha1 = "b104d487b34566608f8b4e1c39fb0b10aa279ff8" +uuid = "77dc65aa-8811-40c2-897b-53d922fa7daf" +version = "0.1.3" + +[[deps.Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" + +[[deps.GPUArraysCore]] +deps = ["Adapt"] +git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0" +uuid = "46192b85-c4d5-4398-a991-12ede77f4527" +version = "0.1.5" + +[[deps.Graphs]] +deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] +git-tree-sha1 = "899050ace26649433ef1af25bc17a815b3db52b7" +uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" +version = "1.9.0" + +[[deps.HostCPUFeatures]] +deps = ["BitTwiddlingConvenienceFunctions", "IfElse", "Libdl", "Static"] +git-tree-sha1 = "eb8fed28f4994600e29beef49744639d985a04b2" +uuid = "3e5b6fbb-0976-4d2c-9146-d79de83f2fb0" +version = "0.1.16" + +[[deps.IfElse]] +git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1" +uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" +version = "0.1.1" + +[[deps.Inflate]] +git-tree-sha1 = "ea8031dea4aff6bd41f1df8f2fdfb25b33626381" +uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" +version = "0.1.4" + +[[deps.IntelOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "5fdf2fe6724d8caabf43b557b84ce53f3b7e2f6b" +uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" +version = "2024.0.2+0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.2" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.5.0" + +[[deps.KLU]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] +git-tree-sha1 = "884c2968c2e8e7e6bf5956af88cb46aa745c854b" +uuid = "ef3ab10e-7fda-4108-b977-705223b18434" +version = "0.4.1" + +[[deps.Krylov]] +deps = ["LinearAlgebra", "Printf", "SparseArrays"] +git-tree-sha1 = "8a6837ec02fe5fb3def1abc907bb802ef11a0729" +uuid = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7" +version = "0.9.5" + +[[deps.LayoutPointers]] +deps = ["ArrayInterface", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface"] +git-tree-sha1 = "62edfee3211981241b57ff1cedf4d74d79519277" +uuid = "10f19ff3-798f-405d-979b-55457f8fc047" +version = "0.1.15" + +[[deps.Lazy]] +deps = ["MacroTools"] +git-tree-sha1 = "1370f8202dac30758f3c345f9909b97f53d87d3f" +uuid = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0" +version = "0.15.1" + +[[deps.LazyArrays]] +deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "MacroTools", "MatrixFactorizations", "SparseArrays"] +git-tree-sha1 = "9cfca23ab83b0dfac93cb1a1ef3331ab9fe596a5" +uuid = "5078a376-72f3-5289-bfd5-ec5146d43c02" +version = "1.8.3" +weakdeps = ["StaticArrays"] + + [deps.LazyArrays.extensions] + LazyArraysStaticArraysExt = "StaticArrays" + +[[deps.LazyArtifacts]] +deps = ["Artifacts", "Pkg"] +uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.4.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.LineSearches]] +deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"] +git-tree-sha1 = "7bbea35cec17305fc70a0e5b4641477dc0789d9d" +uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255" +version = "7.2.0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.LinearSolve]] +deps = ["ArrayInterface", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "Requires", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] +git-tree-sha1 = "ebdc72aa2f1ccbb9f9dd1e85698145024b762ac3" +uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" +version = "2.21.2" + + [deps.LinearSolve.extensions] + LinearSolveBandedMatricesExt = "BandedMatrices" + LinearSolveBlockDiagonalsExt = "BlockDiagonals" + LinearSolveCUDAExt = "CUDA" + LinearSolveEnzymeExt = ["Enzyme", "EnzymeCore"] + LinearSolveFastAlmostBandedMatricesExt = ["FastAlmostBandedMatrices"] + LinearSolveHYPREExt = "HYPRE" + LinearSolveIterativeSolversExt = "IterativeSolvers" + LinearSolveKernelAbstractionsExt = "KernelAbstractions" + LinearSolveKrylovKitExt = "KrylovKit" + LinearSolveMetalExt = "Metal" + LinearSolvePardisoExt = "Pardiso" + LinearSolveRecursiveArrayToolsExt = "RecursiveArrayTools" + + [deps.LinearSolve.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockDiagonals = "0a1fb500-61f7-11e9-3c65-f5ef3456f9f0" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" + HYPRE = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" + IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153" + KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" + KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" + Pardiso = "46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" + RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "7d6dd4e9212aebaeed356de34ccf262a3cd415aa" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.3.26" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.LoopVectorization]] +deps = ["ArrayInterface", "CPUSummary", "CloseOpenIntervals", "DocStringExtensions", "HostCPUFeatures", "IfElse", "LayoutPointers", "LinearAlgebra", "OffsetArrays", "PolyesterWeave", "PrecompileTools", "SIMDTypes", "SLEEFPirates", "Static", "StaticArrayInterface", "ThreadingUtilities", "UnPack", "VectorizationBase"] +git-tree-sha1 = "0f5648fbae0d015e3abe5867bca2b362f67a5894" +uuid = "bdcacae8-1622-11e9-2a5c-532679323890" +version = "0.12.166" + + [deps.LoopVectorization.extensions] + ForwardDiffExt = ["ChainRulesCore", "ForwardDiff"] + SpecialFunctionsExt = "SpecialFunctions" + + [deps.LoopVectorization.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" + +[[deps.MKL_jll]] +deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl"] +git-tree-sha1 = "72dc3cf284559eb8f53aa593fe62cb33f83ed0c0" +uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" +version = "2024.0.0+0" + +[[deps.MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "b211c553c199c111d998ecdaf7623d1b89b69f93" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.12" + +[[deps.ManualMemory]] +git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd" +uuid = "d125e4d3-2237-4719-b19c-fa641b8a4667" +version = "0.1.8" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MatrixFactorizations]] +deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"] +git-tree-sha1 = "78f6e33434939b0ac9ba1df81e6d005ee85a7396" +uuid = "a3b82374-2e81-5b9e-98ce-41277c0e4c87" +version = "2.1.0" + +[[deps.MaybeInplace]] +deps = ["ArrayInterface", "LinearAlgebra", "MacroTools", "SparseArrays"] +git-tree-sha1 = "a85c6a98c9e5a2a7046bc1bb89f28a3241e1de4d" +uuid = "bb5d69b7-63fc-4a16-80bd-7e42200c7bdb" +version = "0.1.1" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.2+1" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.1.10" + +[[deps.MuladdMacro]] +git-tree-sha1 = "cac9cc5499c25554cba55cd3c30543cff5ca4fab" +uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" +version = "0.2.4" + +[[deps.NLSolversBase]] +deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"] +git-tree-sha1 = "a0b464d183da839699f4c79e7606d9d186ec172c" +uuid = "d41bc354-129a-5804-8e4c-c37616107c6c" +version = "7.8.3" + +[[deps.NaNMath]] +deps = ["OpenLibm_jll"] +git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "1.0.2" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.NonlinearSolve]] +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "EnumX", "FastBroadcast", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] +git-tree-sha1 = "e61a283ef89110668b83db24cd7de8868fb8133e" +uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" +version = "3.3.0" + + [deps.NonlinearSolve.extensions] + NonlinearSolveBandedMatricesExt = "BandedMatrices" + NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt" + NonlinearSolveFixedPointAccelerationExt = "FixedPointAcceleration" + NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" + NonlinearSolveMINPACKExt = "MINPACK" + NonlinearSolveNLsolveExt = "NLsolve" + NonlinearSolveSpeedMappingExt = "SpeedMapping" + NonlinearSolveSymbolicsExt = "Symbolics" + NonlinearSolveZygoteExt = "Zygote" + + [deps.NonlinearSolve.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce" + FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176" + LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" + MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" + NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" + SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" + Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.OffsetArrays]] +git-tree-sha1 = "6a731f2b5c03157418a20c12195eb4b74c8f8621" +uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +version = "1.13.0" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.23+2" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.1+2" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.5+0" + +[[deps.OrderedCollections]] +git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.6.3" + +[[deps.PackageExtensionCompat]] +git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" +uuid = "65ce6f38-6b18-4e1d-a461-8949797d7930" +version = "1.0.2" +weakdeps = ["Requires", "TOML"] + +[[deps.Parameters]] +deps = ["OrderedCollections", "UnPack"] +git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" +uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" +version = "0.12.3" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.10.0" + +[[deps.Polyester]] +deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Requires", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"] +git-tree-sha1 = "fca25670784a1ae44546bcb17288218310af2778" +uuid = "f517fe37-dbe3-4b94-8317-1923a5111588" +version = "0.7.9" + +[[deps.PolyesterWeave]] +deps = ["BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "Static", "ThreadingUtilities"] +git-tree-sha1 = "240d7170f5ffdb285f9427b92333c3463bf65bf6" +uuid = "1d0040c9-8b98-4ee7-8388-3f51789ca0ad" +version = "0.2.1" + +[[deps.PreallocationTools]] +deps = ["Adapt", "ArrayInterface", "ForwardDiff", "Requires"] +git-tree-sha1 = "01ac95fca7daabe77a9cb705862bd87016af9ddb" +uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" +version = "0.4.13" + + [deps.PreallocationTools.extensions] + PreallocationToolsReverseDiffExt = "ReverseDiff" + + [deps.PreallocationTools.weakdeps] + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.0" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.1" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.RecipesBase]] +deps = ["PrecompileTools"] +git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.3.4" + +[[deps.RecursiveArrayTools]] +deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "Requires", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] +git-tree-sha1 = "96fdc4a33fa4282e6f3ed54de6be569b1aa43972" +uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" +version = "3.2.6" + + [deps.RecursiveArrayTools.extensions] + RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" + RecursiveArrayToolsMeasurementsExt = "Measurements" + RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" + RecursiveArrayToolsTrackerExt = "Tracker" + RecursiveArrayToolsZygoteExt = "Zygote" + + [deps.RecursiveArrayTools.weakdeps] + FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.RecursiveFactorization]] +deps = ["LinearAlgebra", "LoopVectorization", "Polyester", "PrecompileTools", "StrideArraysCore", "TriangularSolve"] +git-tree-sha1 = "8bc86c78c7d8e2a5fe559e3721c0f9c9e303b2ed" +uuid = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" +version = "0.2.21" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.0" + +[[deps.RuntimeGeneratedFunctions]] +deps = ["ExprTools", "SHA", "Serialization"] +git-tree-sha1 = "6aacc5eefe8415f47b3e34214c1d79d2674a0ba2" +uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47" +version = "0.5.12" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.SIMDTypes]] +git-tree-sha1 = "330289636fb8107c5f32088d2741e9fd7a061a5c" +uuid = "94e857df-77ce-4151-89e5-788b33177be4" +version = "0.1.0" + +[[deps.SLEEFPirates]] +deps = ["IfElse", "Static", "VectorizationBase"] +git-tree-sha1 = "3aac6d68c5e57449f5b9b865c9ba50ac2970c4cf" +uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa" +version = "0.6.42" + +[[deps.SciMLBase]] +deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FillArrays", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables", "TruncatedStacktraces"] +git-tree-sha1 = "50f2e6905c201e1212871824da13a802804835d8" +repo-rev = "ap/nlls_bvp" +repo-url = "https://github.com/SciML/SciMLBase.jl.git" +uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" +version = "2.12.0" + + [deps.SciMLBase.extensions] + SciMLBaseChainRulesCoreExt = "ChainRulesCore" + SciMLBasePartialFunctionsExt = "PartialFunctions" + SciMLBasePyCallExt = "PyCall" + SciMLBasePythonCallExt = "PythonCall" + SciMLBaseRCallExt = "RCall" + SciMLBaseZygoteExt = "Zygote" + + [deps.SciMLBase.weakdeps] + ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b" + PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" + PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" + RCall = "6f49c342-dc21-5d91-9882-a32aef131414" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.SciMLOperators]] +deps = ["ArrayInterface", "DocStringExtensions", "Lazy", "LinearAlgebra", "Setfield", "SparseArrays", "StaticArraysCore", "Tricks"] +git-tree-sha1 = "51ae235ff058a64815e0a2c34b1db7578a06813d" +uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" +version = "0.3.7" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.Setfield]] +deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"] +git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac" +uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46" +version = "1.1.1" + +[[deps.SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + +[[deps.SimpleNonlinearSolve]] +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] +git-tree-sha1 = "1a467a5767d712863e2108e86f7ab103f6d54b13" +uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" +version = "1.0.4" + +[[deps.SimpleTraits]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" +uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +version = "0.9.4" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.10.0" + +[[deps.SparseDiffTools]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "PackageExtensionCompat", "Random", "Reexport", "SciMLOperators", "Setfield", "SparseArrays", "StaticArrayInterface", "StaticArrays", "Tricks", "UnPack", "VertexSafeGraphs"] +git-tree-sha1 = "c281e11db4eacb36a292a054bac83c5a0aca2a26" +uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" +version = "2.15.0" + + [deps.SparseDiffTools.extensions] + SparseDiffToolsEnzymeExt = "Enzyme" + SparseDiffToolsSymbolicsExt = "Symbolics" + SparseDiffToolsZygoteExt = "Zygote" + + [deps.SparseDiffTools.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.Sparspak]] +deps = ["Libdl", "LinearAlgebra", "Logging", "OffsetArrays", "Printf", "SparseArrays", "Test"] +git-tree-sha1 = "342cf4b449c299d8d1ceaf00b7a49f4fbc7940e7" +uuid = "e56a9233-b9d6-4f03-8d0f-1825330902ac" +version = "0.3.9" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.3.1" + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + + [deps.SpecialFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + +[[deps.Static]] +deps = ["IfElse"] +git-tree-sha1 = "f295e0a1da4ca425659c57441bcb59abb035a4bc" +uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" +version = "0.8.8" + +[[deps.StaticArrayInterface]] +deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "PrecompileTools", "Requires", "SparseArrays", "Static", "SuiteSparse"] +git-tree-sha1 = "5d66818a39bb04bf328e92bc933ec5b4ee88e436" +uuid = "0d7ed370-da01-4f52-bd93-41d350b8b718" +version = "1.5.0" +weakdeps = ["OffsetArrays", "StaticArrays"] + + [deps.StaticArrayInterface.extensions] + StaticArrayInterfaceOffsetArraysExt = "OffsetArrays" + StaticArrayInterfaceStaticArraysExt = "StaticArrays" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "fba11dbe2562eecdfcac49a05246af09ee64d055" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.8.1" + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" + + [deps.StaticArrays.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.2" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.10.0" + +[[deps.StrideArraysCore]] +deps = ["ArrayInterface", "CloseOpenIntervals", "IfElse", "LayoutPointers", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface", "ThreadingUtilities"] +git-tree-sha1 = "d6415f66f3d89c615929af907fdc6a3e17af0d8c" +uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da" +version = "0.5.2" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "7.2.1+1" + +[[deps.SymbolicIndexingInterface]] +git-tree-sha1 = "65f4ed0f9e3125e0836df12c231cea3dd98bb165" +uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" +version = "0.3.0" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.11.1" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.ThreadingUtilities]] +deps = ["ManualMemory"] +git-tree-sha1 = "eda08f7e9818eb53661b3deb74e3159460dfbc27" +uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" +version = "0.5.2" + +[[deps.TriangularSolve]] +deps = ["CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "LoopVectorization", "Polyester", "Static", "VectorizationBase"] +git-tree-sha1 = "fadebab77bf3ae041f77346dd1c290173da5a443" +uuid = "d5829a12-d9aa-46ab-831f-fb7c9ab06edf" +version = "0.1.20" + +[[deps.Tricks]] +git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f" +uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" +version = "0.1.8" + +[[deps.TruncatedStacktraces]] +deps = ["InteractiveUtils", "MacroTools", "Preferences"] +git-tree-sha1 = "ea3e54c2bdde39062abf5a9758a23735558705e1" +uuid = "781d530d-4396-4725-bb49-402e4bee1e77" +version = "1.4.0" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.UnPack]] +git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" +uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" +version = "1.0.2" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.VectorizationBase]] +deps = ["ArrayInterface", "CPUSummary", "HostCPUFeatures", "IfElse", "LayoutPointers", "Libdl", "LinearAlgebra", "SIMDTypes", "Static", "StaticArrayInterface"] +git-tree-sha1 = "7209df901e6ed7489fe9b7aa3e46fb788e15db85" +uuid = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f" +version = "0.21.65" + +[[deps.VertexSafeGraphs]] +deps = ["Graphs"] +git-tree-sha1 = "8351f8d73d7e880bfc042a8b6922684ebeafb35c" +uuid = "19fa3120-7c27-5ec5-8db8-b0b0aa330d6f" +version = "0.2.0" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.8.0+1" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.52.0+1" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 298b34e8..2f78d2f5 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -1,6 +1,8 @@ module BoundaryValueDiffEqODEInterfaceExt -using SciMLBase, BoundaryValueDiffEq, ODEInterface +using SciMLBase, BoundaryValueDiffEq, ODEInterface, RecursiveArrayTools +import BoundaryValueDiffEq: __extract_u0, __flatten_initial_guess, + __extract_mesh, __initial_guess_length, __initial_guess, __has_initial_guess import SciMLBase: __solve import ODEInterface: OptionsODE, OPT_ATOL, OPT_RTOL, OPT_METHODCHOICE, OPT_DIAGNOSTICOUTPUT, OPT_ERRORCONTROL, OPT_SINGULARTERM, OPT_MAXSTEPS, OPT_BVPCLASS, @@ -11,6 +13,7 @@ import ODEInterface: Bvpm2, bvpm2_init, bvpm2_solve, bvpm2_destroy, bvpm2_get_x import ODEInterface: bvpsol import ODEInterface: colnew +import FastClosures: @closure import ForwardDiff function _test_bvpm2_bvpsol_colnew_problem_criteria( @@ -24,38 +27,66 @@ end #------ # BVPM2 #------ -## TODO: We can specify Drhs using forwarddiff if we want to -function SciMLBase.__solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs...) - _test_bvpm2_bvpsol_colnew_problem_criteria(prob, prob.problem_type, :BVPM2) - - has_initial_guess = prob.u0 isa AbstractVector{<:AbstractArray} - no_odes, n, u0 = if has_initial_guess - length(first(prob.u0)), (length(prob.u0) - 1), reduce(hcat, prob.u0) - else - dt ≤ 0 && throw(ArgumentError("dt must be positive")) - length(prob.u0), Int(cld((prob.tspan[2] - prob.tspan[1]), dt)), prob.u0 +function __solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs...) + if !(prob.problem_type isa TwoPointBVProblem) + throw(ArgumentError("`BVPM2` only supports `TwoPointBVProblem!`")) end - mesh = collect(range(prob.tspan[1], stop = prob.tspan[2], length = n + 1)) + t₀, t₁ = prob.tspan + u0_ = __extract_u0(prob.u0, prob.p, t₀) + u0_size = size(u0_) + n = __initial_guess_length(prob.u0) + + n == -1 && dt ≤ 0 && throw(ArgumentError("`dt` must be positive.")) - no_left_bc = length(first(prob.f.bcresid_prototype.x)) + mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n)) + n = length(mesh) - 1 + no_odes = length(u0_) - initial_guess = Bvpm2() - bvpm2_init(initial_guess, no_odes, no_left_bc, mesh, u0, eltype(u0)[], - alg.max_num_subintervals) + if prob.f.bcresid_prototype !== nothing + left_bc, right_bc = prob.f.bcresid_prototype.x + left_bc_size, right_bc_size = size(left_bc), size(right_bc) + no_left_bc = length(left_bc) + else + left_bc = prob.f.bc[1](u0_, prob.p) # Guaranteed to be out of place here + no_left_bc = length(left_bc) + end + + obj = Bvpm2() + if prob.u0 isa Function + guess_function = @closure (x, y) -> (y .= vec(__initial_guess(prob.u0, prob.p, x))) + bvpm2_init(obj, no_odes, no_left_bc, mesh, guess_function, eltype(u0_)[], + alg.max_num_subintervals, prob.u0) + else + u0 = __flatten_initial_guess(prob.u0) + bvpm2_init(obj, no_odes, no_left_bc, mesh, u0, eltype(u0)[], + alg.max_num_subintervals) + end - bvp2m_f(t, u, du) = prob.f(du, u, prob.p, t) - function bvp2m_bc(ya, yb, bca, bcb) - prob.f.bc[1](bca, ya, prob.p) - prob.f.bc[2](bcb, yb, prob.p) - return nothing + bvp2m_f = if isinplace(prob) + @closure (t, u, du) -> prob.f(reshape(du, u0_size), reshape(u, u0_size), prob.p, t) + else + @closure (t, u, du) -> du .= vec(prob.f(reshape(u, u0_size), prob.p, t)) + end + bvp2m_bc = if isinplace(prob) + @closure (ya, yb, bca, bcb) -> begin + prob.f.bc[1](reshape(bca, left_bc_size), reshape(ya, u0_size), prob.p) + prob.f.bc[2](reshape(bcb, right_bc_size), reshape(yb, u0_size), prob.p) + return nothing + end + else + @closure (ya, yb, bca, bcb) -> begin + bca .= vec(prob.f.bc[1](reshape(ya, u0_size), prob.p)) + bcb .= vec(prob.f.bc[2](reshape(yb, u0_size), prob.p)) + return nothing + end end opt = OptionsODE(OPT_RTOL => reltol, OPT_METHODCHOICE => alg.method_choice, OPT_DIAGNOSTICOUTPUT => alg.diagnostic_output, OPT_SINGULARTERM => alg.singular_term, OPT_ERRORCONTROL => alg.error_control) - sol, retcode, stats = bvpm2_solve(initial_guess, bvp2m_f, bvp2m_bc, opt) + sol, retcode, stats = bvpm2_solve(obj, bvp2m_f, bvp2m_bc, opt) retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure destats = SciMLBase.DEStats( stats["no_rhs_calls"], 0, 0, 0, stats["no_jac_calls"], 0, 0, 0, 0, 0, 0, 0, 0) @@ -63,41 +94,76 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, x_mesh = bvpm2_get_x(sol) evalsol = evalSolution(sol, x_mesh) sol_final = DiffEqBase.build_solution(prob, alg, x_mesh, - collect(Vector{eltype(evalsol)}, eachcol(evalsol)); retcode, stats = destats) + map(x -> reshape(convert(Vector{eltype(evalsol)}, x), u0_size), eachcol(evalsol)); + retcode, stats = destats) - bvpm2_destroy(initial_guess) + bvpm2_destroy(obj) bvpm2_destroy(sol) - return sol_final + return BVPSolution(sol_final) end #------- # BVPSOL #------- -function SciMLBase.__solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, - dt = 0.0, verbose = true, kwargs...) - _test_bvpm2_bvpsol_colnew_problem_criteria(prob, prob.problem_type, :BVPSOL) - @assert isa(prob.p, SciMLBase.NullParameters) "BVPSOL only supports NullParameters!" - @assert isa(prob.u0, AbstractVector{<:AbstractArray}) "BVPSOL requires a vector of initial guesses!" - n, u0 = (length(prob.u0) - 1), reduce(hcat, prob.u0) - mesh = collect(range(prob.tspan[1], stop = prob.tspan[2], length = n + 1)) +function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, dt = 0.0, + verbose = true, kwargs...) + if !(prob.problem_type isa TwoPointBVProblem) + throw(ArgumentError("`BVPSOL` only supports `TwoPointBVProblem!`")) + end + if !__has_initial_guess(prob.u0) + throw(ArgumentError("Initial Guess is required for `BVPSOL`")) + end + + t₀, t₁ = prob.tspan + u0_ = __extract_u0(prob.u0, prob.p, t₀) + u0_size = size(u0_) + n = __initial_guess_length(prob.u0) + + n == -1 && dt ≤ 0 && throw(ArgumentError("`dt` must be positive.")) + u0 = __flatten_initial_guess(prob.u0) + mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n)) + if u0 === nothing + # initial_guess function was provided + u0 = mapreduce(@closure(t->vec(__initial_guess(prob.u0, prob.p, t))), hcat, mesh) + end + + if prob.f.bcresid_prototype !== nothing + left_bc, right_bc = prob.f.bcresid_prototype.x + left_bc_size, right_bc_size = size(left_bc), size(right_bc) + no_left_bc = length(left_bc) + else + left_bc = prob.f.bc[1](u0_, prob.p) # Guaranteed to be out of place here + no_left_bc = length(left_bc) + end opt = OptionsODE(OPT_RTOL => reltol, OPT_MAXSTEPS => maxiters, OPT_BVPCLASS => alg.bvpclass, OPT_SOLMETHOD => alg.sol_method, OPT_RHS_CALLMODE => RHS_CALL_INSITU) - f!(t, u, du) = prob.f(du, u, prob.p, t) - function bc!(ya, yb, r) - ra = first(prob.f.bcresid_prototype.x) - rb = last(prob.f.bcresid_prototype.x) - prob.f.bc[1](ra, ya, prob.p) - prob.f.bc[2](rb, yb, prob.p) - r[1:length(ra)] .= ra - r[(length(ra) + 1):(length(ra) + length(rb))] .= rb - return r + bvpsol_f = if isinplace(prob) + @closure (t, u, du) -> prob.f(reshape(du, u0_size), reshape(u, u0_size), prob.p, t) + else + @closure (t, u, du) -> du .= vec(prob.f(reshape(u, u0_size), prob.p, t)) + end + + bvpsol_bc = if isinplace(prob) + @closure (ya, yb, r) -> begin + left_bc = reshape(@view(r[1:no_left_bc]), left_bc_size) + right_bc = reshape(@view(r[(no_left_bc + 1):end]), right_bc_size) + prob.f.bc[1](left_bc, reshape(ya, u0_size), prob.p) + prob.f.bc[2](right_bc, reshape(yb, u0_size), prob.p) + return nothing + end + else + @closure (ya, yb, r) -> begin + r[1:no_left_bc] .= vec(prob.f.bc[1](reshape(ya, u0_size), prob.p)) + r[(no_left_bc + 1):end] .= vec(prob.f.bc[2](reshape(yb, u0_size), prob.p)) + return nothing + end end - sol_t, sol_x, retcode, stats = bvpsol(f!, bc!, mesh, u0, alg.odesolver, opt) + sol_t, sol_x, retcode, stats = bvpsol(bvpsol_f, bvpsol_bc, mesh, u0, alg.odesolver, opt) if verbose if retcode == -3 @@ -122,15 +188,15 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol end return DiffEqBase.build_solution(prob, alg, sol_t, - collect(Vector{eltype(sol_x)}, eachcol(sol_x)); + map(x -> reshape(convert(Vector{eltype(u0_)}, x), u0_size), eachcol(sol_x)); retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, stats) end #------- # COLNEW #------- -function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, - reltol = 1e-4, dt = 0.0, verbose = true, kwargs...) +#= TODO: FIX this +function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, reltol=1e-4, dt = 0.0, verbose = true, kwargs...) _test_bvpm2_bvpsol_colnew_problem_criteria(prob, prob.problem_type, :COLNEW) has_initial_guess = prob.u0 isa AbstractVector{<:AbstractArray} dt ≤ 0 && throw(ArgumentError("dt must be positive")) @@ -237,5 +303,6 @@ function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, retcode = retcode > 0 ? ReturnCode.Success : ReturnCode.Failure, stats = destats) end +=# end diff --git a/src/algorithms.jl b/src/algorithms.jl index 0cc01ad1..81794496 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -209,28 +209,38 @@ Fortran code for solving two-point boundary value problems. For detailed documen - `singular_term`: either nothing if the ODEs have no singular terms at the left boundary or a constant (d,d) matrix for the singular term. -!!! warning - - Only supports inplace two-point boundary value problems, with very limited forms of - input structures! - !!! note Only available if the `ODEInterface` package is loaded. """ -Base.@kwdef struct BVPM2{S} <: BoundaryValueDiffEqAlgorithm - max_num_subintervals::Int = 3000 - method_choice::Int = 4 - diagnostic_output::Int = -1 - error_control::Int = 1 - singular_term::S = nothing +struct BVPM2{S} <: BoundaryValueDiffEqAlgorithm + max_num_subintervals::Int + method_choice::Int + diagnostic_output::Int + error_control::Int + singular_term::S + + function BVPM2(max_num_subintervals::Int, method_choice::Int, diagnostic_output::Int, + error_control::Int, singular_term::Union{Nothing, AbstractMatrix}) + if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing + error("BVPM2 requires ODEInterface.jl to be loaded") + end + return new{typeof(singular_term)}(max_num_subintervals, method_choice, + diagnostic_output, error_control, singular_term) + end +end + +function BVPM2(; max_num_subintervals::Int = 3000, method_choice::Int = 4, + diagnostic_output::Int = -1, error_control::Int = 1, singular_term = nothing) + return BVPM2(max_num_subintervals, method_choice, diagnostic_output, error_control, + singular_term) end """ BVPSOL(; bvpclass = 2, sol_method = 0, odesolver = nothing) BVPSOL(bvpclass::Int, sol_methods::Int, odesolver) -A FORTRAN77 code which solves highly nonlinear two point boundary value problems using a +A FORTRAN77 code which solves highly nonlinear **two point boundary value problems** using a local linear solver (condensing algorithm) or a global sparse linear solver for the solution of the arising linear subproblems, by Peter Deuflhard, Georg Bader, Lutz Weimann. For detailed documentation, see @@ -249,24 +259,28 @@ For detailed documentation, see - `1`: Use global sparse linear solver. - `odesolver`: Either `nothing` or ode-solver(dopri5, dop853, seulex, etc.). -!!! warning - - Only supports inplace two-point boundary value problems, with very limited forms of - input structures! - !!! note Only available if the `ODEInterface` package is loaded. """ -Base.@kwdef struct BVPSOL{O} <: BoundaryValueDiffEqAlgorithm - bvpclass::Int = 2 - sol_method::Int = 0 - odesolver::O = nothing +struct BVPSOL{O} <: BoundaryValueDiffEqAlgorithm + bvpclass::Int + sol_method::Int + odesolver::O + + function BVPSOL(bvpclass::Int, sol_method::Int, odesolver) + if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing + error("BVPSOL requires ODEInterface.jl to be loaded") + end + return new{typeof(odesolver)}(bvpclass, sol_method, odesolver) + end end """ - COLNEW(; bvpclass = 2, collocationpts = 7, autodiff = :central) - COLNEW(bvpclass::Int, collocationpts::Int, autodiff) + COLNEW(; bvpclass = 1, collocationpts = 7, diagnostic_output = 1, + max_num_subintervals = 3000) + COLNEW(bvpclass::Int, collocationpts::Int, diagnostic_output::Int, + max_num_subintervals::Int) ## Keyword Arguments: @@ -285,8 +299,8 @@ end - `1`: No printout. - `max_num_subintervals`: Number of maximal subintervals, default as 3000. -A Fortran77 code solves a multi-points boundary value problems for a mixed order system of ODEs. -It incorporates a new basis representation replacing b-splines, and improvements for +A Fortran77 code solves a multi-points boundary value problems for a mixed order system of +ODEs. It incorporates a new basis representation replacing b-splines, and improvements for the linear and nonlinear algebraic equation solvers. !!! warning @@ -295,9 +309,21 @@ the linear and nonlinear algebraic equation solvers. !!! note Only available if the `ODEInterface` package is loaded. """ -Base.@kwdef struct COLNEW <: BoundaryValueDiffEqAlgorithm - bvpclass::Int = 1 - collocationpts::Int = 7 - diagnostic_output::Int = 1 - max_num_subintervals::Int = 3000 +struct COLNEW <: BoundaryValueDiffEqAlgorithm + bvpclass::Int + collocationpts::Int + diagnostic_output::Int + max_num_subintervals::Int + + function COLNEW(; bvpclass::Int = 1, collocationpts::Int = 7, + diagnostic_output::Int = 1, max_num_subintervals::Int = 3000) + return COLNEW(bvpclass, collocationpts, diagnostic_output, max_num_subintervals) + end + function COLNEW(bvpclass::Int, collocationpts::Int, diagnostic_output::Int, + max_num_subintervals::Int) + if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing + error("COLNEW requires ODEInterface.jl to be loaded") + end + return new(bvpclass, collocationpts, diagnostic_output, max_num_subintervals) + end end diff --git a/test/misc/odeinterface.jl b/test/misc/odeinterface.jl new file mode 100644 index 00000000..42e61f86 --- /dev/null +++ b/test/misc/odeinterface.jl @@ -0,0 +1,100 @@ +using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, RecursiveArrayTools + +# Adaptation of https://github.com/luchr/ODEInterface.jl/blob/958b6023d1dabf775033d0b89c5401b33100bca3/examples/BasicExamples/ex7.jl +function ex7_f!(du, u, p, t) + ϵ = p[1] + u₁, λ = u + du[1] = (sin(t)^2 + λ * sin(t)^4 / u₁) / ϵ + du[2] = 0 + return nothing +end + +function ex7_2pbc1!(resa, ua, p) + resa[1] = ua[1] - 1 + return nothing +end + +function ex7_2pbc2!(resb, ub, p) + resb[1] = ub[1] - 1 + return nothing +end + +u0 = [0.5, 1.0] +p = [0.1] +tspan = (-π / 2, π / 2) + +tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, p; + bcresid_prototype = (zeros(1), zeros(1))) +sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) + +@testset "BVPM2" begin + @info "Testing BVPM2" + + sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) + @test SciMLBase.successful_retcode(sol_bvpm2) + resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) + ex7_2pbc1!(resid_f[1], sol_bvpm2(tspan[1]), nothing) + ex7_2pbc2!(resid_f[2], sol_bvpm2(tspan[2]), nothing) + @test norm(resid_f, Inf) < 1e-6 +end + +# Just test that it runs. BVPSOL only works with linearly separable BCs. +@testset "BVPSOL" begin + @info "Testing BVPSOL" + + @info "BVPSOL with Vector{<:AbstractArray}" + + initial_u0 = [sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + bcresid_prototype = (zeros(1), zeros(1))) + + # Just test that it runs. BVPSOL only works with linearly separable BCs. + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + + @info "BVPSOL with VectorOfArray" + + initial_u0 = VectorOfArray([sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + bcresid_prototype = (zeros(1), zeros(1))) + + # Just test that it runs. BVPSOL only works with linearly separable BCs. + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + + @info "BVPSOL with DiffEqArray" + + ts = collect(tspan[1]:(π / 20):tspan[2]) + initial_u0 = DiffEqArray([sol_bvpm2(t) .+ rand() for t in ts], ts) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + bcresid_prototype = (zeros(1), zeros(1))) + + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + + @info "BVPSOL with initial guess function" + + initial_u0 = (p, t) -> sol_bvpm2(t) .+ rand() + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; + bcresid_prototype = (zeros(1), zeros(1))) + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) +end + +#= +@info "COLNEW" + +function f!(du, u, p, t) + du[1] = u[2] + du[2] = u[1] +end +function bca!(resid_a, u_a, p) + resid_a[1] = u_a[1] - 1 +end +function bcb!(resid_b, u_b, p) + resid_b[1] = u_b[1] +end + +fun = BVPFunction(f!, (bca!, bcb!), bcresid_prototype = (zeros(1), zeros(1)), twopoint = Val(true)) +tspan = (0.0, 1.0) + +prob = TwoPointBVProblem(fun, [1.0, 0.0], tspan) +sol_colnew = solve(prob, COLNEW(), dt = 0.01) +@test SciMLBase.successful_retcode(sol_colnew) +=# From d365029a36778fca2803b5df9d668f3d42315749 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Dec 2023 18:00:12 -0500 Subject: [PATCH 03/24] Add JET Tests and disable Multiple Shooting tests for now --- Manifest.toml | 16 +- Project.toml | 5 +- src/algorithms.jl | 81 ++--- src/solve/single_shooting.jl | 9 +- test/misc/odeinterface.jl | 100 ------ test/misc/odeinterface_wrapper.jl | 69 +++-- test/runtests.jl | 2 +- test/shooting/basic_problems.jl | 378 +++++++++++++++++++++++ test/shooting/basic_tests.jl | 324 ------------------- test/shooting/nonlinear_least_squares.jl | 2 +- test/shooting/orbital.jl | 2 +- 11 files changed, 492 insertions(+), 496 deletions(-) delete mode 100644 test/misc/odeinterface.jl create mode 100644 test/shooting/basic_problems.jl delete mode 100644 test/shooting/basic_tests.jl diff --git a/Manifest.toml b/Manifest.toml index 6d6134b8..2464fce9 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,12 +2,12 @@ julia_version = "1.10.0-rc2" manifest_format = "2.0" -project_hash = "caa3a84a29ae467d2583d2084e7f50dd07a4148f" +project_hash = "0ac16cb78a3540d2a0e82de32da74fda24f340a4" [[deps.ADTypes]] -git-tree-sha1 = "332e5d7baeff8497b923b730b994fa480601efc7" +git-tree-sha1 = "41c37aa88889c171f1300ceac1313c06e891d245" uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" -version = "0.2.5" +version = "0.2.6" [[deps.Adapt]] deps = ["LinearAlgebra", "Requires"] @@ -587,10 +587,10 @@ uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" version = "1.2.0" [[deps.NonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "EnumX", "FastBroadcast", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] -git-tree-sha1 = "e61a283ef89110668b83db24cd7de8868fb8133e" +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "EnumX", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] +git-tree-sha1 = "72b036b728461272ae1b1c3f7096cb4c319d8793" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.3.0" +version = "3.4.0" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" @@ -599,6 +599,7 @@ version = "3.3.0" NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" NonlinearSolveMINPACKExt = "MINPACK" NonlinearSolveNLsolveExt = "NLsolve" + NonlinearSolveSIAMFANLEquationsExt = "SIAMFANLEquations" NonlinearSolveSpeedMappingExt = "SpeedMapping" NonlinearSolveSymbolicsExt = "Symbolics" NonlinearSolveZygoteExt = "Zygote" @@ -610,6 +611,7 @@ version = "3.3.0" LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" + SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" @@ -775,7 +777,7 @@ version = "0.6.42" [[deps.SciMLBase]] deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FillArrays", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables", "TruncatedStacktraces"] -git-tree-sha1 = "50f2e6905c201e1212871824da13a802804835d8" +git-tree-sha1 = "b8f7a0807314cce87bf846ba5fd12c1b0ef512b7" repo-rev = "ap/nlls_bvp" repo-url = "https://github.com/SciML/SciMLBase.jl.git" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" diff --git a/Project.toml b/Project.toml index 4dbb133c..a3132353 100644 --- a/Project.toml +++ b/Project.toml @@ -44,9 +44,11 @@ ArrayInterface = "7" BandedMatrices = "1" ConcreteStructs = "0.2" DiffEqBase = "6.145" +DiffEqDevTools = "2.44" FastAlmostBandedMatrices = "0.1" FastClosures = "0.3" ForwardDiff = "0.10" +JET = "0.8" LinearAlgebra = "1.9" LinearSolve = "2.20" NonlinearSolve = "2.6.1, 3" @@ -74,6 +76,7 @@ julia = "1.9" Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" +JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -83,4 +86,4 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["StaticArrays", "Random", "DiffEqDevTools", "OrdinaryDiffEq", "Test", "SafeTestsets", "ODEInterface", "Aqua", "LinearSolve", "RecursiveArrayTools"] +test = ["StaticArrays", "Random", "DiffEqDevTools", "OrdinaryDiffEq", "Test", "SafeTestsets", "ODEInterface", "Aqua", "LinearSolve", "RecursiveArrayTools", "JET"] diff --git a/src/algorithms.jl b/src/algorithms.jl index 81794496..12aaa6fc 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -1,10 +1,24 @@ # Algorithms abstract type BoundaryValueDiffEqAlgorithm <: SciMLBase.AbstractBVPAlgorithm end +abstract type AbstractShooting <: BoundaryValueDiffEqAlgorithm end abstract type AbstractMIRK <: BoundaryValueDiffEqAlgorithm end ## Disable the ugly verbose printing by default +@inline __modifier_text!(list, fieldname, field) = push!(list, "$fieldname = $(field)") +@inline __modifier_text!(list, fieldname, ::Nothing) = list +@inline __modifier_text!(list, fieldname, ::Missing) = list +@inline function __modifier_text!(list, fieldname, field::SciMLBase.AbstractODEAlgorithm) + push!(list, "$fieldname = $(__nameof(field))()") +end + function Base.show(io::IO, alg::BoundaryValueDiffEqAlgorithm) - print(io, "$(nameof(typeof(alg)))()") + print(io, "$(__nameof(alg))(") + modifiers = String[] + for field in fieldnames(typeof(alg)) + __modifier_text!(modifiers, field, getfield(alg, field)) + end + print(io, join(modifiers, ", ")) + print(io, ")") end """ @@ -28,7 +42,7 @@ Single shooting method, reduces BVP to an initial value problem and solves the I and problem type. If `BVPJacobianAlgorithm` is provided, only `diffmode` is used (defaults to `AutoForwardDiff` if possible else `AutoFiniteDiff`). """ -@concrete struct Shooting{J <: BVPJacobianAlgorithm} <: BoundaryValueDiffEqAlgorithm +@concrete struct Shooting{J <: BVPJacobianAlgorithm} <: AbstractShooting ode_alg nlsolve jac_alg::J @@ -40,25 +54,17 @@ end @inline Shooting(ode_alg; kwargs...) = Shooting(; ode_alg, kwargs...) @inline Shooting(ode_alg, nlsolve; kwargs...) = Shooting(; ode_alg, nlsolve, kwargs...) -function Base.show(io::IO, alg::Shooting) - print(io, "Shooting(") - modifiers = String[] - alg.nlsolve !== nothing && push!(modifiers, "nlsolve = $(alg.nlsolve)") - alg.jac_alg !== nothing && push!(modifiers, "jac_alg = $(alg.jac_alg)") - alg.ode_alg !== nothing && push!(modifiers, "ode_alg = $(__nameof(alg.ode_alg))()") - print(io, join(modifiers, ", ")) - print(io, ")") -end - @inline function concretize_jacobian_algorithm(alg::Shooting, prob) alg.jac_alg.diffmode === nothing && (return @set alg.jac_alg.diffmode = __default_nonsparse_ad(prob.u0)) return alg end - """ - MultipleShooting(nshoots::Int, ode_alg = nothing; nlsolve = nothing, - grid_coarsening = true, jac_alg = BVPJacobianAlgorithm()) + MultipleShooting(; nshoots::Int, ode_alg = nothing, nlsolve = nothing, + grid_coarsening = true, jac_alg = nothing) + MultipleShooting(nshoots::Int; kwargs...) + MultipleShooting(nshoots::Int, ode_alg; kwargs...) + MultipleShooting(nshoots::Int, ode_alg, nlsolve; kwargs...) Multiple Shooting method, reduces BVP to an initial value problem and solves the IVP. Significantly more stable than Single Shooting. @@ -66,16 +72,12 @@ Significantly more stable than Single Shooting. ## Arguments - `nshoots`: Number of shooting points. + - `ode_alg`: ODE algorithm to use for solving the IVP. Any solver which conforms to the SciML `ODEProblem` interface can be used! (Defaults to `nothing` which will use poly-algorithm if `DifferentialEquations.jl` is loaded else this must be supplied) - -## Keyword Arguments - - `nlsolve`: Internal Nonlinear solver. Any solver which conforms to the SciML - `NonlinearProblem` interface can be used. Note that any autodiff argument for the solver - will be ignored and a custom jacobian algorithm will be used. - + `NonlinearProblem` interface can be used. - `jac_alg`: Jacobian Algorithm used for the nonlinear solver. Defaults to `BVPJacobianAlgorithm()`, which automatically decides the best algorithm to use based on the input types and problem type. @@ -83,8 +85,8 @@ Significantly more stable than Single Shooting. + For `TwoPointBVProblem`, only `diffmode` is used (defaults to `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`). + For `BVProblem`, `bc_diffmode` and `nonbc_diffmode` are used. For `nonbc_diffmode` - defaults to `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`. For - `bc_diffmode`, defaults to `AutoForwardDiff` if possible else `AutoFiniteDiff`. + we default to `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`. For + `bc_diffmode`, we default to `AutoForwardDiff` if possible else `AutoFiniteDiff`. - `grid_coarsening`: Coarsening the multiple-shooting grid to generate a stable IVP solution. Possible Choices: @@ -97,13 +99,8 @@ Significantly more stable than Single Shooting. + `Function`: Takes the current number of shooting points and returns the next number of shooting points. For example, if `nshoots = 10` and `grid_coarsening = n -> n ÷ 2`, then the grid will be coarsened to `[5, 2]`. - -!!! note - - For type-stability, the chunksizes for ForwardDiff ADTypes in `BVPJacobianAlgorithm` - must be provided. """ -@concrete struct MultipleShooting{J <: BVPJacobianAlgorithm} +@concrete struct MultipleShooting{J <: BVPJacobianAlgorithm} <: AbstractShooting ode_alg nlsolve jac_alg::J @@ -111,6 +108,16 @@ Significantly more stable than Single Shooting. grid_coarsening end +# function Base.show(io::IO, alg::MultipleShooting) +# print(io, "MultipleShooting(") +# modifiers = String[] +# alg.nlsolve !== nothing && push!(modifiers, "nlsolve = $(alg.nlsolve)") +# alg.jac_alg !== nothing && push!(modifiers, "jac_alg = $(alg.jac_alg)") +# alg.ode_alg !== nothing && push!(modifiers, "ode_alg = $(__nameof(alg.ode_alg))()") +# print(io, join(modifiers, ", ")) +# print(io, ")") +# end + function concretize_jacobian_algorithm(alg::MultipleShooting, prob) jac_alg = concrete_jacobian_algorithm(alg.jac_alg, prob, alg) return MultipleShooting(alg.ode_alg, alg.nlsolve, jac_alg, alg.nshoots, @@ -122,18 +129,22 @@ function update_nshoots(alg::MultipleShooting, nshoots::Int) alg.grid_coarsening) end -function MultipleShooting(nshoots::Int, ode_alg = nothing; nlsolve = nothing, - grid_coarsening = true, jac_alg = BVPJacobianAlgorithm()) - @assert grid_coarsening isa Bool || grid_coarsening isa Function || - grid_coarsening isa AbstractVector{<:Integer} || - grid_coarsening isa NTuple{N, <:Integer} where {N} +function MultipleShooting(; nshoots::Int, ode_alg = nothing, nlsolve = nothing, + grid_coarsening::Union{Bool, Function, <:AbstractVector{<:Integer}, + Tuple{Vararg{Integer}}} = true, jac_alg = nothing) grid_coarsening isa Tuple && (grid_coarsening = Vector(grid_coarsening...)) if grid_coarsening isa AbstractVector sort!(grid_coarsening; rev = true) @assert all(grid_coarsening .> 0) && 1 ∉ grid_coarsening end - return MultipleShooting(ode_alg, nlsolve, jac_alg, nshoots, grid_coarsening) + return MultipleShooting(ode_alg, nlsolve, + __materialize_jacobian_algorithm(nlsolve, jac_alg), nshoots, grid_coarsening) end +@inline MultipleShooting(nshoots::Int; kwargs...) = MultipleShooting(; nshoots, kwargs...) +@inline MultipleShooting(nshoots::Int, ode_alg; kwargs...) = MultipleShooting(; + nshoots, ode_alg, kwargs...) +@inline MultipleShooting(nshoots::Int, ode_alg, nlsolve; kwargs...) = MultipleShooting(; + nshoots, ode_alg, nlsolve, kwargs...) for order in (2, 3, 4, 5, 6) alg = Symbol("MIRK$(order)") diff --git a/src/solve/single_shooting.jl b/src/solve/single_shooting.jl index 74f3d6f9..46fffb30 100644 --- a/src/solve/single_shooting.jl +++ b/src/solve/single_shooting.jl @@ -72,16 +72,15 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), nlf = __unsafe_nonlinearfunction{iip}(loss_fn; jac_prototype, resid_prototype, jac = jac_fn) nlprob = __internal_nlsolve_problem(prob, resid_prototype, u0, nlf, vec(u0), prob.p) - opt = __solve(nlprob, alg.nlsolve; nlsolve_kwargs..., verbose, kwargs...) + nlsol = __solve(nlprob, alg.nlsolve; nlsolve_kwargs..., verbose, kwargs...) # There is no way to reinit with the same cache with different cache. But not saving # the internal values gives a significant speedup. So we just create a new cache - internal_prob_final = ODEProblem{iip}(prob.f, reshape(opt.u, u0_size), prob.tspan, + internal_prob_final = ODEProblem{iip}(prob.f, reshape(nlsol.u, u0_size), prob.tspan, prob.p) - sol = __solve(internal_prob_final, alg.ode_alg; actual_ode_kwargs...) + odesol = __solve(internal_prob_final, alg.ode_alg; actual_ode_kwargs...) - retcode = SciMLBase.successful_retcode(opt) ? sol.retcode : opt.retcode - return BVPSolution(sol; original = opt, retcode) + return SciMLBase.build_solution(prob, odesol, nlsol) end function __single_shooting_loss!(resid_, u0_, p, cache, bc::BC, u0_size, diff --git a/test/misc/odeinterface.jl b/test/misc/odeinterface.jl deleted file mode 100644 index 42e61f86..00000000 --- a/test/misc/odeinterface.jl +++ /dev/null @@ -1,100 +0,0 @@ -using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, RecursiveArrayTools - -# Adaptation of https://github.com/luchr/ODEInterface.jl/blob/958b6023d1dabf775033d0b89c5401b33100bca3/examples/BasicExamples/ex7.jl -function ex7_f!(du, u, p, t) - ϵ = p[1] - u₁, λ = u - du[1] = (sin(t)^2 + λ * sin(t)^4 / u₁) / ϵ - du[2] = 0 - return nothing -end - -function ex7_2pbc1!(resa, ua, p) - resa[1] = ua[1] - 1 - return nothing -end - -function ex7_2pbc2!(resb, ub, p) - resb[1] = ub[1] - 1 - return nothing -end - -u0 = [0.5, 1.0] -p = [0.1] -tspan = (-π / 2, π / 2) - -tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) -sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) - -@testset "BVPM2" begin - @info "Testing BVPM2" - - sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) - @test SciMLBase.successful_retcode(sol_bvpm2) - resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) - ex7_2pbc1!(resid_f[1], sol_bvpm2(tspan[1]), nothing) - ex7_2pbc2!(resid_f[2], sol_bvpm2(tspan[2]), nothing) - @test norm(resid_f, Inf) < 1e-6 -end - -# Just test that it runs. BVPSOL only works with linearly separable BCs. -@testset "BVPSOL" begin - @info "Testing BVPSOL" - - @info "BVPSOL with Vector{<:AbstractArray}" - - initial_u0 = [sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; - bcresid_prototype = (zeros(1), zeros(1))) - - # Just test that it runs. BVPSOL only works with linearly separable BCs. - sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) - - @info "BVPSOL with VectorOfArray" - - initial_u0 = VectorOfArray([sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; - bcresid_prototype = (zeros(1), zeros(1))) - - # Just test that it runs. BVPSOL only works with linearly separable BCs. - sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) - - @info "BVPSOL with DiffEqArray" - - ts = collect(tspan[1]:(π / 20):tspan[2]) - initial_u0 = DiffEqArray([sol_bvpm2(t) .+ rand() for t in ts], ts) - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; - bcresid_prototype = (zeros(1), zeros(1))) - - sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) - - @info "BVPSOL with initial guess function" - - initial_u0 = (p, t) -> sol_bvpm2(t) .+ rand() - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) - sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) -end - -#= -@info "COLNEW" - -function f!(du, u, p, t) - du[1] = u[2] - du[2] = u[1] -end -function bca!(resid_a, u_a, p) - resid_a[1] = u_a[1] - 1 -end -function bcb!(resid_b, u_b, p) - resid_b[1] = u_b[1] -end - -fun = BVPFunction(f!, (bca!, bcb!), bcresid_prototype = (zeros(1), zeros(1)), twopoint = Val(true)) -tspan = (0.0, 1.0) - -prob = TwoPointBVProblem(fun, [1.0, 0.0], tspan) -sol_colnew = solve(prob, COLNEW(), dt = 0.01) -@test SciMLBase.successful_retcode(sol_colnew) -=# diff --git a/test/misc/odeinterface_wrapper.jl b/test/misc/odeinterface_wrapper.jl index ead00b84..aa747a1e 100644 --- a/test/misc/odeinterface_wrapper.jl +++ b/test/misc/odeinterface_wrapper.jl @@ -1,4 +1,4 @@ -using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random +using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, RecursiveArrayTools # Adaptation of https://github.com/luchr/ODEInterface.jl/blob/958b6023d1dabf775033d0b89c5401b33100bca3/examples/BasicExamples/ex7.jl function ex7_f!(du, u, p, t) @@ -25,33 +25,59 @@ tspan = (-π / 2, π / 2) tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) - -@info "BVPM2" - sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) -@test SciMLBase.successful_retcode(sol_bvpm2) -resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) -ex7_2pbc1!(resid_f[1], sol_bvpm2(tspan[1]), nothing) -ex7_2pbc2!(resid_f[2], sol_bvpm2(tspan[2]), nothing) -@test norm(resid_f, Inf) < 1e-6 -function ex7_f2!(du, u, p, t) - u₁, λ = u - du[1] = (sin(t)^2 + λ * sin(t)^4 / u₁) / 0.1 - du[2] = 0 - return nothing +@testset "BVPM2" begin + @info "Testing BVPM2" + + sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) + @test SciMLBase.successful_retcode(sol_bvpm2) + resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) + ex7_2pbc1!(resid_f[1], sol_bvpm2(tspan[1]), nothing) + ex7_2pbc2!(resid_f[2], sol_bvpm2(tspan[2]), nothing) + @test norm(resid_f, Inf) < 1e-6 end -@info "BVPSOL" +# Just test that it runs. BVPSOL only works with linearly separable BCs. +@testset "BVPSOL" begin + @info "Testing BVPSOL" -initial_u0 = [sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] -tpprob = TwoPointBVProblem(ex7_f2!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; - bcresid_prototype = (zeros(1), zeros(1))) + @info "BVPSOL with Vector{<:AbstractArray}" -# Just test that it runs. BVPSOL only works with linearly separable BCs. -# TODO: Implement appolo reentry example from ODEInterface.jl -sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + initial_u0 = [sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + bcresid_prototype = (zeros(1), zeros(1))) + + # Just test that it runs. BVPSOL only works with linearly separable BCs. + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + + @info "BVPSOL with VectorOfArray" + + initial_u0 = VectorOfArray([sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + bcresid_prototype = (zeros(1), zeros(1))) + + # Just test that it runs. BVPSOL only works with linearly separable BCs. + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + + @info "BVPSOL with DiffEqArray" + + ts = collect(tspan[1]:(π / 20):tspan[2]) + initial_u0 = DiffEqArray([sol_bvpm2(t) .+ rand() for t in ts], ts) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + bcresid_prototype = (zeros(1), zeros(1))) + + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + + @info "BVPSOL with initial guess function" + + initial_u0 = (p, t) -> sol_bvpm2(t) .+ rand() + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; + bcresid_prototype = (zeros(1), zeros(1))) + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) +end +#= @info "COLNEW" function f!(du, u, p, t) @@ -72,3 +98,4 @@ tspan = (0.0, 1.0) prob = TwoPointBVProblem(fun, [1.0, 0.0], tspan) sol_colnew = solve(prob, COLNEW(), dt = 0.01) @test SciMLBase.successful_retcode(sol_colnew) +=# diff --git a/test/runtests.jl b/test/runtests.jl index 4b9d674a..3366d4eb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -61,4 +61,4 @@ const GROUP = uppercase(get(ENV, "GROUP", "ALL")) end end end -end \ No newline at end of file +end diff --git a/test/shooting/basic_problems.jl b/test/shooting/basic_problems.jl new file mode 100644 index 00000000..fb4950ca --- /dev/null +++ b/test/shooting/basic_problems.jl @@ -0,0 +1,378 @@ +using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET + +# FIXME: Reenable the Multiple Shooting Tests + +@testset "Basic Shooting Tests" begin + SOLVERS = [ + Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), + Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5()), + # MultipleShooting(10, Tsit5(), + # NewtonRaphson(; autodiff = AutoFiniteDiff())), + # MultipleShooting(10, Tsit5(), + # NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), + # MultipleShooting(10, Tsit5()), + ] + JET_SKIP = [false, false, true, false, false, true] + JET_BROKEN = [false, false, false, false, false, false] + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] + + # Inplace + function f1!(du, u, p, t) + du[1] = u[2] + du[2] = -u[1] + return nothing + end + + function bc1!(resid, sol, p, t) + t₀, t₁ = first(t), last(t) + resid[1] = sol(t₀)[1] + resid[2] = sol(t₁)[1] - 1 + return nothing + end + + @info "Basic MP Shooting IIP" + + bvp1 = BVProblem(f1!, bc1!, u0, tspan) + @test SciMLBase.isinplace(bvp1) + + for (i, solver) in enumerate(SOLVERS) + @info "Solver: $solver" + sol = @time solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) + + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-8 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + end + + # Out of Place + f1(u, p, t) = [u[2], -u[1]] + + function bc1(sol, p, t) + t₀, t₁ = first(t), last(t) + return [sol(t₀)[1], sol(t₁)[1] - 1] + end + + @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1!, bc1, u0, tspan) + @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1, bc1!, u0, tspan) + + @info "Basic MP Shooting OOP" + + bvp2 = BVProblem(f1, bc1, u0, tspan) + @test !SciMLBase.isinplace(bvp2) + + for (i, solver) in enumerate(SOLVERS) + @info "Solver: $solver" + sol = @time solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) + + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-8 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + end + + # Inplace + bc2a!(resid, ua, p) = (resid[1] = ua[1]) + bc2b!(resid, ub, p) = (resid[1] = ub[1] - 1) + + @info "Basic TP Shooting IIP" + + bvp3 = TwoPointBVProblem(f1!, (bc2a!, bc2b!), u0, tspan; + bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1))) + @test SciMLBase.isinplace(bvp3) + + for (i, solver) in enumerate(SOLVERS) + @info "Solver: $solver" + sol = @time solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) + + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-8 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + end + + # Out of Place + bc2a(ua, p) = [ua[1]] + bc2b(ub, p) = [ub[1] - 1] + + @info "Basic TP Shooting OOP" + + bvp4 = TwoPointBVProblem(f1, (bc2a, bc2b), u0, tspan) + @test !SciMLBase.isinplace(bvp4) + + for (i, solver) in enumerate(SOLVERS) + @info "Solver: $solver" + sol = @time solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) + + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-8 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] + end +end + +@testset "Shooting with Complex Values" begin + SOLVERS = [ + Shooting(Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), + Shooting(Vern7()), + # MultipleShooting(10, Vern7(), + # NewtonRaphson(; autodiff = AutoFiniteDiff())), + # MultipleShooting(10, Vern7()), + ] + JET_SKIP = [false, true, false, true] + JET_BROKEN = [false, false, false, false] + + function f1!(du, u, p, t) + du[1] = u[2] + du[2] = -u[1] + return nothing + end + + function bc1!(resid, sol, p, t) + t₀, t₁ = first(t), last(t) + resid[1] = sol(t₀)[1] + resid[2] = sol(t₁)[1] - 1 + return nothing + end + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] .+ 1im + bvp = BVProblem(f1!, bc1!, u0, tspan) + + @info "Shooting with Complex Values" + + for (i, solver) in enumerate(SOLVERS) + @info "Solver: $solver" + sol = @time solve(bvp, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) + + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-8 + end +end + +@testset "Flow In a Channel" begin + function flow_in_a_channel!(du, u, p, t) + R, P = p + A, f′′, f′, f, h′, h, θ′, θ = u + du[1] = 0 + du[2] = R * (f′^2 - f * f′′) - R * A + du[3] = f′′ + du[4] = f′ + du[5] = -R * f * h′ - 1 + du[6] = h′ + du[7] = -P * f * θ′ + du[8] = θ′ + end + + function bc_flow!(resid, sol, p, tspan) + t₁, t₂ = extrema(tspan) + solₜ₁ = sol(t₁) + solₜ₂ = sol(t₂) + resid[1] = solₜ₁[4] + resid[2] = solₜ₁[3] + resid[3] = solₜ₂[4] - 1 + resid[4] = solₜ₂[3] + resid[5] = solₜ₁[6] + resid[6] = solₜ₂[6] + resid[7] = solₜ₁[8] + resid[8] = solₜ₂[8] - 1 + end + + tspan = (0.0, 1.0) + p = [10.0, 7.0] + u0 = zeros(8) + + flow_bvp = BVProblem{true}(flow_in_a_channel!, bc_flow!, u0, tspan, p) + + @info "Flow in a Channel" + + for solver in [ + Shooting(AutoTsit5(Rosenbrock23())), + # MultipleShooting(10, AutoTsit5(Rosenbrock23())), + ] + @info "Solver: $solver" + sol = @time solve(flow_bvp, solver; abstol = 1e-8, reltol = 1e-8, + odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-8)) + + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-8 + end +end + +# @testset "Ray Tracing" begin +# @inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) +# @inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) +# @inline uy(x, y, z, p) = p[2] * cos(p[2] * y) +# @inline uz(x, y, z, p) = p[3] * sin(p[3] * z) + +# function ray_tracing(u, p, t) +# du = similar(u) +# ray_tracing!(du, u, p, t) +# return du +# end + +# function ray_tracing!(du, u, p, t) +# x, y, z, ξ, η, ζ, T, S = u + +# nu = v(x, y, z, p) # Velocity of a sound wave, function of space; +# μx = ux(x, y, z, p) # ∂(slowness)/∂x, function of space +# μy = uy(x, y, z, p) # ∂(slowness)/∂y, function of space +# μz = uz(x, y, z, p) # ∂(slowness)/∂z, function of space + +# du[1] = S * nu * ξ +# du[2] = S * nu * η +# du[3] = S * nu * ζ + +# du[4] = S * μx +# du[5] = S * μy +# du[6] = S * μz + +# du[7] = S / nu +# du[8] = 0 + +# return nothing +# end + +# function ray_tracing_bc(sol, p, t) +# res = similar(first(sol)) +# ray_tracing_bc!(res, sol, p, t) +# return res +# end + +# function ray_tracing_bc!(res, sol, p, t) +# ua = sol(0.0) +# ub = sol(1.0) +# nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; + +# res[1] = ua[1] - p[4] +# res[2] = ua[2] - p[5] +# res[3] = ua[3] - p[6] +# res[4] = ua[7] # T(0) = 0 +# res[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 +# res[6] = ub[1] - p[7] +# res[7] = ub[2] - p[8] +# res[8] = ub[3] - p[9] +# return nothing +# end + +# function ray_tracing_bc_a(ua, p) +# resa = similar(ua, 5) +# ray_tracing_bc_a!(resa, ua, p) +# return resa +# end + +# function ray_tracing_bc_a!(resa, ua, p) +# nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; + +# resa[1] = ua[1] - p[4] +# resa[2] = ua[2] - p[5] +# resa[3] = ua[3] - p[5] +# resa[4] = ua[7] +# resa[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 + +# return nothing +# end + +# function ray_tracing_bc_b(ub, p) +# resb = similar(ub, 3) +# ray_tracing_bc_b!(resb, ub, p) +# return resb +# end + +# function ray_tracing_bc_b!(resb, ub, p) +# resb[1] = ub[1] - p[7] +# resb[2] = ub[2] - p[8] +# resb[3] = ub[3] - p[9] +# return nothing +# end + +# p = [0, 1, 2, 0, 0, 0, 4, 3, 2.0] + +# dx = p[7] - p[4] +# dy = p[8] - p[5] +# dz = p[9] - p[6] + +# u0 = zeros(8) +# u0[1:3] .= 0 # position +# u0[4] = dx / v(p[4], p[5], p[6], p) +# u0[5] = dy / v(p[4], p[5], p[6], p) +# u0[6] = dz / v(p[4], p[5], p[6], p) +# u0[8] = 1 + +# tspan = (0.0, 1.0) + +# prob_oop = BVProblem(BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; +# nlls = Val(false)) +# prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; +# nlls = Val(true)) +# prob_tp_oop = BVProblem(BVPFunction{false}(ray_tracing, +# (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; +# nlls = Val(true)) +# prob_tp_iip = BVProblem(BVPFunction{true}(ray_tracing!, +# (ray_tracing_bc_a!, ray_tracing_bc_b!); +# bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; +# nlls = Val(true)) + +# @info "Ray Tracing: Multiple Shooting" + +# alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, +# nlsolve = TrustRegion(), +# jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), +# nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 8))) +# alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, +# nlsolve = TrustRegion(), +# jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), +# nonbc_diffmode = AutoForwardDiff(; chunksize = 8))) +# alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) + +# for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), +# (alg_sp, alg_dense, alg_default)) +# @info "Solver: $alg" +# @time sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, +# odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-5)) +# @test SciMLBase.successful_retcode(sol.retcode) + +# if prob.problem_type isa TwoPointBVProblem +# resida, residb = zeros(5), zeros(3) +# ray_tracing_bc_a!(resida, sol.u[1], p) +# ray_tracing_bc_b!(residb, sol.u[end], p) +# @test norm(vcat(resida, residb), Inf) < 1e-6 +# else +# resid = zeros(8) +# ray_tracing_bc!(resid, sol, p, sol.t) +# @test norm(resid, Inf) < 1e-6 +# end +# end +# end diff --git a/test/shooting/basic_tests.jl b/test/shooting/basic_tests.jl deleted file mode 100644 index 8f99d115..00000000 --- a/test/shooting/basic_tests.jl +++ /dev/null @@ -1,324 +0,0 @@ -using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test - -@testset "Basic Shooting Tests" begin - SOLVERS = [Shooting(Tsit5()), MultipleShooting(10, Tsit5())] - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] - - # Inplace - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - return nothing - end - - function bc1!(resid, sol, p, t) - t₀, t₁ = first(t), last(t) - resid[1] = sol(t₀)[1] - resid[2] = sol(t₁)[1] - 1 - return nothing - end - - @info "Basic MP Shooting IIP" - - bvp1 = BVProblem(f1!, bc1!, u0, tspan) - @test SciMLBase.isinplace(bvp1) - for solver in SOLVERS - @info "Solver: $solver" - resid_f = Array{Float64}(undef, 2) - sol = @time solve(bvp1, solver; abstol = 1e-13, reltol = 1e-13, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) - @test SciMLBase.successful_retcode(sol) - bc1!(resid_f, sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-12 - end - - # Out of Place - f1(u, p, t) = [u[2], -u[1]] - - function bc1(sol, p, t) - t₀, t₁ = first(t), last(t) - return [sol(t₀)[1], sol(t₁)[1] - 1] - end - - @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1!, bc1, u0, tspan) - @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1, bc1!, u0, tspan) - - @info "Basic MP Shooting OOP" - - bvp2 = BVProblem(f1, bc1, u0, tspan) - @test !SciMLBase.isinplace(bvp2) - for solver in SOLVERS - @info "Solver: $solver" - sol = @time solve(bvp2, solver; abstol = 1e-13, reltol = 1e-13, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) - @test SciMLBase.successful_retcode(sol) - resid_f = bc1(sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-12 - end - - # Inplace - bc2a!(resid, ua, p) = (resid[1] = ua[1]) - bc2b!(resid, ub, p) = (resid[1] = ub[1] - 1) - - @info "Basic TP Shooting IIP" - - bvp3 = TwoPointBVProblem(f1!, (bc2a!, bc2b!), u0, tspan; - bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1))) - @test SciMLBase.isinplace(bvp3) - for solver in SOLVERS - @info "Solver: $solver" - sol = @time solve(bvp3, solver; abstol = 1e-13, reltol = 1e-13, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) - @test SciMLBase.successful_retcode(sol) - resid_f = (Array{Float64, 1}(undef, 1), Array{Float64, 1}(undef, 1)) - bc2a!(resid_f[1], sol(tspan[1]), nothing) - bc2b!(resid_f[2], sol(tspan[2]), nothing) - @test norm(reduce(vcat, resid_f), Inf) < 1e-12 - end - - # Out of Place - bc2a(ua, p) = [ua[1]] - bc2b(ub, p) = [ub[1] - 1] - - @info "Basic TP Shooting OOP" - - bvp4 = TwoPointBVProblem(f1, (bc2a, bc2b), u0, tspan) - @test !SciMLBase.isinplace(bvp4) - for solver in SOLVERS - @info "Solver: $solver" - sol = @time solve(bvp4, solver; abstol = 1e-13, reltol = 1e-13, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) - @test SciMLBase.successful_retcode(sol) - resid_f = reduce(vcat, (bc2a(sol(tspan[1]), nothing), bc2b(sol(tspan[2]), nothing))) - @test norm(resid_f, Inf) < 1e-12 - end -end - -@testset "Shooting with Complex Values" begin - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - return nothing - end - - function bc1!(resid, sol, p, t) - t₀, t₁ = first(t), last(t) - resid[1] = sol(t₀)[1] - resid[2] = sol(t₁)[1] - 1 - return nothing - end - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] .+ 1im - bvp = BVProblem(f1!, bc1!, u0, tspan) - resid_f = Array{ComplexF64}(undef, 2) - - @info "Shooting with Complex Values" - - for solver in [Shooting(Vern7()), MultipleShooting(10, Vern7())] - @info "Solver: $solver" - sol = @time solve(bvp, solver; abstol = 1e-13, reltol = 1e-13, - odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-8)) - @test SciMLBase.successful_retcode(sol) - bc1!(resid_f, sol, nothing, sol.t) - @test norm(resid_f, Inf) < 1e-12 - end -end - -@testset "Flow In a Channel" begin - function flow_in_a_channel!(du, u, p, t) - R, P = p - A, f′′, f′, f, h′, h, θ′, θ = u - du[1] = 0 - du[2] = R * (f′^2 - f * f′′) - R * A - du[3] = f′′ - du[4] = f′ - du[5] = -R * f * h′ - 1 - du[6] = h′ - du[7] = -P * f * θ′ - du[8] = θ′ - end - - function bc_flow!(resid, sol, p, tspan) - t₁, t₂ = extrema(tspan) - solₜ₁ = sol(t₁) - solₜ₂ = sol(t₂) - resid[1] = solₜ₁[4] - resid[2] = solₜ₁[3] - resid[3] = solₜ₂[4] - 1 - resid[4] = solₜ₂[3] - resid[5] = solₜ₁[6] - resid[6] = solₜ₂[6] - resid[7] = solₜ₁[8] - resid[8] = solₜ₂[8] - 1 - end - - tspan = (0.0, 1.0) - p = [10.0, 7.0] - u0 = zeros(8) - - flow_bvp = BVProblem{true}(flow_in_a_channel!, bc_flow!, u0, tspan, p) - - @info "Flow in a Channel" - - for solver in [ - Shooting(AutoTsit5(Rosenbrock23())), - MultipleShooting(10, AutoTsit5(Rosenbrock23())), - ] - @info "Solver: $solver" - sol = @time solve(flow_bvp, solver; abstol = 1e-13, reltol = 1e-13, - odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-8)) - @test SciMLBase.successful_retcode(sol) - resid = zeros(8) - bc_flow!(resid, sol, p, sol.t) - @test norm(resid, Inf) < 1e-6 - end -end - -@testset "Ray Tracing" begin - @inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) - @inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) - @inline uy(x, y, z, p) = p[2] * cos(p[2] * y) - @inline uz(x, y, z, p) = p[3] * sin(p[3] * z) - - function ray_tracing(u, p, t) - du = similar(u) - ray_tracing!(du, u, p, t) - return du - end - - function ray_tracing!(du, u, p, t) - x, y, z, ξ, η, ζ, T, S = u - - nu = v(x, y, z, p) # Velocity of a sound wave, function of space; - μx = ux(x, y, z, p) # ∂(slowness)/∂x, function of space - μy = uy(x, y, z, p) # ∂(slowness)/∂y, function of space - μz = uz(x, y, z, p) # ∂(slowness)/∂z, function of space - - du[1] = S * nu * ξ - du[2] = S * nu * η - du[3] = S * nu * ζ - - du[4] = S * μx - du[5] = S * μy - du[6] = S * μz - - du[7] = S / nu - du[8] = 0 - - return nothing - end - - function ray_tracing_bc(sol, p, t) - res = similar(first(sol)) - ray_tracing_bc!(res, sol, p, t) - return res - end - - function ray_tracing_bc!(res, sol, p, t) - ua = sol(0.0) - ub = sol(1.0) - nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; - - res[1] = ua[1] - p[4] - res[2] = ua[2] - p[5] - res[3] = ua[3] - p[6] - res[4] = ua[7] # T(0) = 0 - res[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 - res[6] = ub[1] - p[7] - res[7] = ub[2] - p[8] - res[8] = ub[3] - p[9] - return nothing - end - - function ray_tracing_bc_a(ua, p) - resa = similar(ua, 5) - ray_tracing_bc_a!(resa, ua, p) - return resa - end - - function ray_tracing_bc_a!(resa, ua, p) - nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; - - resa[1] = ua[1] - p[4] - resa[2] = ua[2] - p[5] - resa[3] = ua[3] - p[5] - resa[4] = ua[7] - resa[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 - - return nothing - end - - function ray_tracing_bc_b(ub, p) - resb = similar(ub, 3) - ray_tracing_bc_b!(resb, ub, p) - return resb - end - - function ray_tracing_bc_b!(resb, ub, p) - resb[1] = ub[1] - p[7] - resb[2] = ub[2] - p[8] - resb[3] = ub[3] - p[9] - return nothing - end - - p = [0, 1, 2, 0, 0, 0, 4, 3, 2.0] - - dx = p[7] - p[4] - dy = p[8] - p[5] - dz = p[9] - p[6] - - u0 = zeros(8) - u0[1:3] .= 0 # position - u0[4] = dx / v(p[4], p[5], p[6], p) - u0[5] = dy / v(p[4], p[5], p[6], p) - u0[6] = dz / v(p[4], p[5], p[6], p) - u0[8] = 1 - - tspan = (0.0, 1.0) - - prob_oop = BVProblem(BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; - nlls = Val(false)) - prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; - nlls = Val(true)) - prob_tp_oop = BVProblem(BVPFunction{false}(ray_tracing, - (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; - nlls = Val(true)) - prob_tp_iip = BVProblem(BVPFunction{true}(ray_tracing!, - (ray_tracing_bc_a!, ray_tracing_bc_b!); - bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; - nlls = Val(true)) - - @info "Ray Tracing: Multiple Shooting" - - alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, - nlsolve = TrustRegion(), - jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), - nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 8))) - alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, - nlsolve = TrustRegion(), - jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), - nonbc_diffmode = AutoForwardDiff(; chunksize = 8))) - alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) - - for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), - (alg_sp, alg_dense, alg_default)) - @info "Solver: $alg" - @time sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, - odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-5)) - @test SciMLBase.successful_retcode(sol.retcode) - - if prob.problem_type isa TwoPointBVProblem - resida, residb = zeros(5), zeros(3) - ray_tracing_bc_a!(resida, sol.u[1], p) - ray_tracing_bc_b!(residb, sol.u[end], p) - @test norm(vcat(resida, residb), Inf) < 1e-6 - else - resid = zeros(8) - ray_tracing_bc!(resid, sol, p, sol.t) - @test norm(resid, Inf) < 1e-6 - end - end -end \ No newline at end of file diff --git a/test/shooting/nonlinear_least_squares.jl b/test/shooting/nonlinear_least_squares.jl index 7fac9eb3..304cc805 100644 --- a/test/shooting/nonlinear_least_squares.jl +++ b/test/shooting/nonlinear_least_squares.jl @@ -91,4 +91,4 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test sol = @time solve(bvp4, solver; verbose = false) @test norm(sol.resid, Inf) < 1e-4 end -end \ No newline at end of file +end diff --git a/test/shooting/orbital.jl b/test/shooting/orbital.jl index 552e809c..8e2d5067 100644 --- a/test/shooting/orbital.jl +++ b/test/shooting/orbital.jl @@ -124,4 +124,4 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test @test SciMLBase.successful_retcode(sol) @test norm(reduce(vcat, resid_f_2p), Inf) < 1e-6 end -end \ No newline at end of file +end From 0cc2f22f5d1ea057aa4d909cf99ee2cecc8b2db7 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Dec 2023 18:21:23 -0500 Subject: [PATCH 04/24] Minor fix --- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 2f78d2f5..65dd335b 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -93,14 +93,14 @@ function __solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs... x_mesh = bvpm2_get_x(sol) evalsol = evalSolution(sol, x_mesh) - sol_final = DiffEqBase.build_solution(prob, alg, x_mesh, + ivpsol = SciMLBase.build_solution(prob, alg, x_mesh, map(x -> reshape(convert(Vector{eltype(evalsol)}, x), u0_size), eachcol(evalsol)); retcode, stats = destats) bvpm2_destroy(obj) bvpm2_destroy(sol) - return BVPSolution(sol_final) + return SciMLBase.build_solution(prob, ivpsol) end #------- @@ -187,9 +187,11 @@ function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, d end end - return DiffEqBase.build_solution(prob, alg, sol_t, + ivpsol = SciMLBase.build_solution(prob, alg, sol_t, map(x -> reshape(convert(Vector{eltype(u0_)}, x), u0_size), eachcol(sol_x)); retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, stats) + + return SciMLBase.build_solution(prob, ivpsol) end #------- From ecfa77d5022a093d46a5c125ec3cde3dc8e278e2 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Dec 2023 18:45:55 -0500 Subject: [PATCH 05/24] Handle Dynamic Dispatches in Multiple Shooting --- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 4 +- src/algorithms.jl | 10 - src/solve/multiple_shooting.jl | 63 +++-- test/shooting/basic_problems.jl | 305 +++++++++++----------- test/shooting/nonlinear_least_squares.jl | 69 ++++- test/shooting/orbital.jl | 31 +-- 6 files changed, 248 insertions(+), 234 deletions(-) diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 65dd335b..e023f95f 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -100,7 +100,7 @@ function __solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs... bvpm2_destroy(obj) bvpm2_destroy(sol) - return SciMLBase.build_solution(prob, ivpsol) + return SciMLBase.build_solution(prob, ivpsol, nothing) end #------- @@ -191,7 +191,7 @@ function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, d map(x -> reshape(convert(Vector{eltype(u0_)}, x), u0_size), eachcol(sol_x)); retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, stats) - return SciMLBase.build_solution(prob, ivpsol) + return SciMLBase.build_solution(prob, ivpsol, nothing) end #------- diff --git a/src/algorithms.jl b/src/algorithms.jl index 12aaa6fc..738ce066 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -108,16 +108,6 @@ Significantly more stable than Single Shooting. grid_coarsening end -# function Base.show(io::IO, alg::MultipleShooting) -# print(io, "MultipleShooting(") -# modifiers = String[] -# alg.nlsolve !== nothing && push!(modifiers, "nlsolve = $(alg.nlsolve)") -# alg.jac_alg !== nothing && push!(modifiers, "jac_alg = $(alg.jac_alg)") -# alg.ode_alg !== nothing && push!(modifiers, "ode_alg = $(__nameof(alg.ode_alg))()") -# print(io, join(modifiers, ", ")) -# print(io, ")") -# end - function concretize_jacobian_algorithm(alg::MultipleShooting, prob) jac_alg = concrete_jacobian_algorithm(alg.jac_alg, prob, alg) return MultipleShooting(alg.ode_alg, alg.nlsolve, jac_alg, alg.nshoots, diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index 565e56fe..7defa28f 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -1,8 +1,11 @@ function __solve(prob::BVProblem, _alg::MultipleShooting; odesolve_kwargs = (;), nlsolve_kwargs = (;), ensemblealg = EnsembleThreads(), verbose = true, kwargs...) - @unpack f, tspan = prob + (; f, tspan) = prob - @assert (ensemblealg isa EnsembleSerial)||(ensemblealg isa EnsembleThreads) "Currently MultipleShooting only supports `EnsembleSerial` and `EnsembleThreads`!" + if !(ensemblealg isa EnsembleSerial) && !(ensemblealg isa EnsembleThreads) + throw(ArgumentError("Currently MultipleShooting only supports `EnsembleSerial` and \ + `EnsembleThreads`!")) + end ig, T, N, Nig, u0 = __extract_problem_details(prob; dt = 0.1) has_initial_guess = _unwrap_val(ig) @@ -30,11 +33,9 @@ function __solve(prob::BVProblem, _alg::MultipleShooting; odesolve_kwargs = (;), internal_ode_kwargs = (; verbose, kwargs..., odesolve_kwargs..., save_end = true) - function solve_internal_odes!(resid_nodes::T1, us::T2, p::T3, cur_nshoot::Int, - nodes::T4, odecache::C) where {T1, T2, T3, T4, C} - return __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoot, - odecache, nodes, u0_size, N, ensemblealg) - end + solve_internal_odes! = @closure (resid_nodes, us, p, cur_nshoot, nodes, + odecache) -> __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoot, + odecache, nodes, u0_size, N, ensemblealg, tspan) # This gets all the nshoots except the final SingleShooting case all_nshoots = __get_all_nshoots(alg.grid_coarsening, nshoots) @@ -98,7 +99,7 @@ function __solve_nlproblem!(::TwoPointBVProblem, alg::MultipleShooting, bcresid_ resid_prototype = vcat(bcresid_prototype[1], similar(u_at_nodes, cur_nshoot * N), bcresid_prototype[2]) - loss_fn = (du, u, p) -> __multiple_shooting_2point_loss!(du, u, p, cur_nshoot, + loss_fn = @closure (du, u, p) -> __multiple_shooting_2point_loss!(du, u, p, cur_nshoot, nodes, prob, solve_internal_odes!, resida_len, residb_len, N, bca, bcb, ode_cache_loss_fn) @@ -114,19 +115,18 @@ function __solve_nlproblem!(::TwoPointBVProblem, alg::MultipleShooting, bcresid_ jac_cache, alg.jac_alg.diffmode, alg.ode_alg, cur_nshoot, u0; internal_ode_kwargs...) - loss_fnₚ = (du, u) -> __multiple_shooting_2point_loss!(du, u, prob.p, cur_nshoot, - nodes, prob, solve_internal_odes!, resida_len, residb_len, N, bca, bcb, + loss_fnₚ = @closure (du, u) -> __multiple_shooting_2point_loss!(du, u, prob.p, + cur_nshoot, nodes, prob, solve_internal_odes!, resida_len, residb_len, N, bca, bcb, ode_cache_jac_fn) - jac_fn = (J, u, p) -> __multiple_shooting_2point_jacobian!(J, u, p, jac_cache, + jac_fn = @closure (J, u, p) -> __multiple_shooting_2point_jacobian!(J, u, p, jac_cache, loss_fnₚ, resid_prototype_cached, alg) - loss_function! = NonlinearFunction{true}(loss_fn; resid_prototype, jac = jac_fn, - jac_prototype) + loss_function! = __unsafe_nonlinearfunction{true}(loss_fn; resid_prototype, + jac = jac_fn, jac_prototype) # NOTE: u_at_nodes is updated inplace - nlprob = (M != N ? NonlinearLeastSquaresProblem : NonlinearProblem)(loss_function!, - u_at_nodes, prob.p) + nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) return nothing @@ -146,7 +146,7 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ resid_nodes = __maybe_allocate_diffcache(__resid_nodes, pickchunksize((cur_nshoot + 1) * N), alg.jac_alg.bc_diffmode) - loss_fn = (du, u, p) -> __multiple_shooting_mpoint_loss!(du, u, p, cur_nshoot, + loss_fn = @closure (du, u, p) -> __multiple_shooting_mpoint_loss!(du, u, p, cur_nshoot, nodes, prob, solve_internal_odes!, resid_len, N, f, bc, u0_size, prob.tspan, alg.ode_alg, u0, ode_cache_loss_fn) @@ -171,23 +171,21 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ jac_prototype = vcat(init_jacobian(bc_jac_cache), init_jacobian(ode_jac_cache)) # Define the functions now - ode_fn = (du, u) -> solve_internal_odes!(du, u, prob.p, cur_nshoot, nodes, + ode_fn = @closure (du, u) -> solve_internal_odes!(du, u, prob.p, cur_nshoot, nodes, ode_cache_ode_jac_fn) - bc_fn = (du, u) -> __multiple_shooting_mpoint_loss_bc!( - du, u, prob.p, cur_nshoot, nodes, - prob, solve_internal_odes!, N, f, bc, u0_size, prob.tspan, alg.ode_alg, u0, - ode_cache_bc_jac_fn) + bc_fn = @closure (du, u) -> __multiple_shooting_mpoint_loss_bc!(du, u, prob.p, + cur_nshoot, nodes, prob, solve_internal_odes!, N, f, bc, u0_size, prob.tspan, + alg.ode_alg, u0, ode_cache_bc_jac_fn) - jac_fn = (J, u, p) -> __multiple_shooting_mpoint_jacobian!(J, u, p, + jac_fn = @closure (J, u, p) -> __multiple_shooting_mpoint_jacobian!(J, u, p, similar(bcresid_prototype), resid_nodes, ode_jac_cache, bc_jac_cache, ode_fn, bc_fn, alg, N, M) - loss_function! = NonlinearFunction{true}(loss_fn; resid_prototype, jac = jac_fn, - jac_prototype) + loss_function! = __unsafe_nonlinearfunction{true}(loss_fn; resid_prototype, + jac_prototype, jac = jac_fn) # NOTE: u_at_nodes is updated inplace - nlprob = (M != N ? NonlinearLeastSquaresProblem : NonlinearProblem)(loss_function!, - u_at_nodes, prob.p) + nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) return nothing @@ -227,7 +225,7 @@ end # Not using `EnsembleProblem` since it is hard to initialize the cache and stuff function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots::Int, - odecache, nodes, u0_size, N::Int, ::EnsembleSerial) + odecache, nodes, u0_size, N::Int, ::EnsembleSerial, tspan) ts_ = Vector{Vector{typeof(first(tspan))}}(undef, cur_nshoots) us_ = Vector{Vector{typeof(us)}}(undef, cur_nshoots) @@ -245,7 +243,7 @@ function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots:: end function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots::Int, - odecache::Vector, nodes, u0_size, N::Int, ::EnsembleThreads) + odecache::Vector, nodes, u0_size, N::Int, ::EnsembleThreads, tspan) ts_ = Vector{Vector{typeof(first(tspan))}}(undef, cur_nshoots) us_ = Vector{Vector{typeof(us)}}(undef, cur_nshoots) @@ -369,7 +367,7 @@ end # NOTE: We don't check `u0 isa Function` since `u0` in-principle can be a callable # struct - u0_ = u0 isa AbstractArray ? u0 : [__initial_guess(u0, prob.p, t) for t in nodes] + u0_ = u0 isa VectorOfArray ? u0 : [__initial_guess(u0, prob.p, t) for t in nodes] N = length(first(u0_)) u_at_nodes = similar(first(u0_), (nshoots + 1) * N) @@ -404,14 +402,13 @@ end sol = solve!(odecache) if SciMLBase.successful_retcode(sol) - res = sol(nodes).u for i in 1:length(nodes) - u_at_nodes[(i - 1) * N .+ (1:N)] .= vec(res[i]) + u_at_nodes[(i - 1) * N .+ (1:N)] .= vec(sol(nodes[i])) end else @warn "Initialization using odesolve failed. Initializing using 0s. It is \ recommended to provide an initial guess function via \ - `u0 = (p, t)` or `u0 = (t)` in this case." + `u0 = (p, t)` in this case." fill!(u_at_nodes, 0) end @@ -483,4 +480,4 @@ end end @assert !(1 in nshoots_vec) return nshoots_vec -end +end \ No newline at end of file diff --git a/test/shooting/basic_problems.jl b/test/shooting/basic_problems.jl index fb4950ca..5fd51adc 100644 --- a/test/shooting/basic_problems.jl +++ b/test/shooting/basic_problems.jl @@ -1,17 +1,14 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET -# FIXME: Reenable the Multiple Shooting Tests - @testset "Basic Shooting Tests" begin SOLVERS = [ Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5()), - # MultipleShooting(10, Tsit5(), - # NewtonRaphson(; autodiff = AutoFiniteDiff())), - # MultipleShooting(10, Tsit5(), - # NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), - # MultipleShooting(10, Tsit5()), + MultipleShooting(10, Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), + MultipleShooting(10, Tsit5(), + NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5()), ] JET_SKIP = [false, false, true, false, false, true] JET_BROKEN = [false, false, false, false, false, false] @@ -146,12 +143,9 @@ end SOLVERS = [ Shooting(Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), Shooting(Vern7()), - # MultipleShooting(10, Vern7(), - # NewtonRaphson(; autodiff = AutoFiniteDiff())), - # MultipleShooting(10, Vern7()), + MultipleShooting(10, Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), + MultipleShooting(10, Vern7()), ] - JET_SKIP = [false, true, false, true] - JET_BROKEN = [false, false, false, false] function f1!(du, u, p, t) du[1] = u[2] @@ -219,8 +213,10 @@ end @info "Flow in a Channel" for solver in [ - Shooting(AutoTsit5(Rosenbrock23())), - # MultipleShooting(10, AutoTsit5(Rosenbrock23())), + Shooting(AutoTsit5(Rosenbrock23()), + NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))), + MultipleShooting(10, AutoTsit5(Rosenbrock23()), + NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))), ] @info "Solver: $solver" sol = @time solve(flow_bvp, solver; abstol = 1e-8, reltol = 1e-8, @@ -231,148 +227,139 @@ end end end -# @testset "Ray Tracing" begin -# @inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) -# @inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) -# @inline uy(x, y, z, p) = p[2] * cos(p[2] * y) -# @inline uz(x, y, z, p) = p[3] * sin(p[3] * z) - -# function ray_tracing(u, p, t) -# du = similar(u) -# ray_tracing!(du, u, p, t) -# return du -# end - -# function ray_tracing!(du, u, p, t) -# x, y, z, ξ, η, ζ, T, S = u - -# nu = v(x, y, z, p) # Velocity of a sound wave, function of space; -# μx = ux(x, y, z, p) # ∂(slowness)/∂x, function of space -# μy = uy(x, y, z, p) # ∂(slowness)/∂y, function of space -# μz = uz(x, y, z, p) # ∂(slowness)/∂z, function of space - -# du[1] = S * nu * ξ -# du[2] = S * nu * η -# du[3] = S * nu * ζ - -# du[4] = S * μx -# du[5] = S * μy -# du[6] = S * μz - -# du[7] = S / nu -# du[8] = 0 - -# return nothing -# end - -# function ray_tracing_bc(sol, p, t) -# res = similar(first(sol)) -# ray_tracing_bc!(res, sol, p, t) -# return res -# end - -# function ray_tracing_bc!(res, sol, p, t) -# ua = sol(0.0) -# ub = sol(1.0) -# nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; - -# res[1] = ua[1] - p[4] -# res[2] = ua[2] - p[5] -# res[3] = ua[3] - p[6] -# res[4] = ua[7] # T(0) = 0 -# res[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 -# res[6] = ub[1] - p[7] -# res[7] = ub[2] - p[8] -# res[8] = ub[3] - p[9] -# return nothing -# end - -# function ray_tracing_bc_a(ua, p) -# resa = similar(ua, 5) -# ray_tracing_bc_a!(resa, ua, p) -# return resa -# end - -# function ray_tracing_bc_a!(resa, ua, p) -# nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; - -# resa[1] = ua[1] - p[4] -# resa[2] = ua[2] - p[5] -# resa[3] = ua[3] - p[5] -# resa[4] = ua[7] -# resa[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 - -# return nothing -# end - -# function ray_tracing_bc_b(ub, p) -# resb = similar(ub, 3) -# ray_tracing_bc_b!(resb, ub, p) -# return resb -# end - -# function ray_tracing_bc_b!(resb, ub, p) -# resb[1] = ub[1] - p[7] -# resb[2] = ub[2] - p[8] -# resb[3] = ub[3] - p[9] -# return nothing -# end - -# p = [0, 1, 2, 0, 0, 0, 4, 3, 2.0] - -# dx = p[7] - p[4] -# dy = p[8] - p[5] -# dz = p[9] - p[6] - -# u0 = zeros(8) -# u0[1:3] .= 0 # position -# u0[4] = dx / v(p[4], p[5], p[6], p) -# u0[5] = dy / v(p[4], p[5], p[6], p) -# u0[6] = dz / v(p[4], p[5], p[6], p) -# u0[8] = 1 - -# tspan = (0.0, 1.0) - -# prob_oop = BVProblem(BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; -# nlls = Val(false)) -# prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; -# nlls = Val(true)) -# prob_tp_oop = BVProblem(BVPFunction{false}(ray_tracing, -# (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; -# nlls = Val(true)) -# prob_tp_iip = BVProblem(BVPFunction{true}(ray_tracing!, -# (ray_tracing_bc_a!, ray_tracing_bc_b!); -# bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; -# nlls = Val(true)) - -# @info "Ray Tracing: Multiple Shooting" - -# alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, -# nlsolve = TrustRegion(), -# jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), -# nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 8))) -# alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, -# nlsolve = TrustRegion(), -# jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), -# nonbc_diffmode = AutoForwardDiff(; chunksize = 8))) -# alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) - -# for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), -# (alg_sp, alg_dense, alg_default)) -# @info "Solver: $alg" -# @time sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, -# odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-5)) -# @test SciMLBase.successful_retcode(sol.retcode) - -# if prob.problem_type isa TwoPointBVProblem -# resida, residb = zeros(5), zeros(3) -# ray_tracing_bc_a!(resida, sol.u[1], p) -# ray_tracing_bc_b!(residb, sol.u[end], p) -# @test norm(vcat(resida, residb), Inf) < 1e-6 -# else -# resid = zeros(8) -# ray_tracing_bc!(resid, sol, p, sol.t) -# @test norm(resid, Inf) < 1e-6 -# end -# end -# end +@testset "Ray Tracing" begin + @inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) + @inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) + @inline uy(x, y, z, p) = p[2] * cos(p[2] * y) + @inline uz(x, y, z, p) = p[3] * sin(p[3] * z) + + function ray_tracing(u, p, t) + du = similar(u) + ray_tracing!(du, u, p, t) + return du + end + + function ray_tracing!(du, u, p, t) + x, y, z, ξ, η, ζ, T, S = u + + nu = v(x, y, z, p) # Velocity of a sound wave, function of space; + μx = ux(x, y, z, p) # ∂(slowness)/∂x, function of space + μy = uy(x, y, z, p) # ∂(slowness)/∂y, function of space + μz = uz(x, y, z, p) # ∂(slowness)/∂z, function of space + + du[1] = S * nu * ξ + du[2] = S * nu * η + du[3] = S * nu * ζ + + du[4] = S * μx + du[5] = S * μy + du[6] = S * μz + + du[7] = S / nu + du[8] = 0 + + return nothing + end + + function ray_tracing_bc(sol, p, t) + res = similar(first(sol)) + ray_tracing_bc!(res, sol, p, t) + return res + end + + function ray_tracing_bc!(res, sol, p, t) + ua = sol(0.0) + ub = sol(1.0) + nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; + + res[1] = ua[1] - p[4] + res[2] = ua[2] - p[5] + res[3] = ua[3] - p[6] + res[4] = ua[7] # T(0) = 0 + res[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 + res[6] = ub[1] - p[7] + res[7] = ub[2] - p[8] + res[8] = ub[3] - p[9] + return nothing + end + + function ray_tracing_bc_a(ua, p) + resa = similar(ua, 5) + ray_tracing_bc_a!(resa, ua, p) + return resa + end + + function ray_tracing_bc_a!(resa, ua, p) + nu = v(ua[1], ua[2], ua[3], p) # Velocity of a sound wave, function of space; + + resa[1] = ua[1] - p[4] + resa[2] = ua[2] - p[5] + resa[3] = ua[3] - p[5] + resa[4] = ua[7] + resa[5] = ua[4]^2 + ua[5]^2 + ua[6]^2 - 1 / nu^2 + + return nothing + end + + function ray_tracing_bc_b(ub, p) + resb = similar(ub, 3) + ray_tracing_bc_b!(resb, ub, p) + return resb + end + + function ray_tracing_bc_b!(resb, ub, p) + resb[1] = ub[1] - p[7] + resb[2] = ub[2] - p[8] + resb[3] = ub[3] - p[9] + return nothing + end + + p = [0, 1, 2, 0, 0, 0, 4, 3, 2.0] + + dx = p[7] - p[4] + dy = p[8] - p[5] + dz = p[9] - p[6] + + u0 = zeros(8) + u0[1:3] .= 0 # position + u0[4] = dx / v(p[4], p[5], p[6], p) + u0[5] = dy / v(p[4], p[5], p[6], p) + u0[6] = dz / v(p[4], p[5], p[6], p) + u0[8] = 1 + + tspan = (0.0, 1.0) + + prob_oop = BVProblem(BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; + nlls = Val(false)) + prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; + nlls = Val(true)) + prob_tp_oop = BVProblem(BVPFunction{false}(ray_tracing, + (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; + nlls = Val(true)) + prob_tp_iip = BVProblem(BVPFunction{true}(ray_tracing!, + (ray_tracing_bc_a!, ray_tracing_bc_b!); + bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; + nlls = Val(true)) + + @info "Ray Tracing: Multiple Shooting" + + alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, + nlsolve = TrustRegion(), + jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), + nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 8))) + alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, + nlsolve = TrustRegion(), + jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), + nonbc_diffmode = AutoForwardDiff(; chunksize = 8))) + alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) + + for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), + (alg_sp, alg_dense, alg_default)) + @info "Solver: $alg" + @time sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, + odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-5)) + + @test SciMLBase.successful_retcode(sol.retcode) + @test norm(sol.resid, Inf) < 1e-6 + end +end diff --git a/test/shooting/nonlinear_least_squares.jl b/test/shooting/nonlinear_least_squares.jl index 304cc805..1b60d831 100644 --- a/test/shooting/nonlinear_least_squares.jl +++ b/test/shooting/nonlinear_least_squares.jl @@ -1,13 +1,22 @@ -using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test +using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET @testset "Overconstrained BVP" begin SOLVERS = [ Shooting(Tsit5()), - Shooting(Tsit5(); nlsolve = GaussNewton()), - Shooting(Tsit5(); nlsolve = TrustRegion()), + Shooting(Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), + Shooting(Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), MultipleShooting(10, Tsit5()), - MultipleShooting(10, Tsit5(); nlsolve = GaussNewton()), - MultipleShooting(10, Tsit5(); nlsolve = TrustRegion())] + MultipleShooting(10, Tsit5(), + GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), + MultipleShooting(10, Tsit5(), + TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), + ] + JET_SKIP = [true, false, false, false, false, true, false, false, false, false] + JET_BROKEN = [false, false, false, false, false, false, false, false, false, false] @info "Solving Overconstrained BVPs" @@ -29,11 +38,19 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test bvp1 = BVProblem(BVPFunction{false}(f1, bc1; bcresid_prototype = zeros(4)), u0, tspan; nlls = Val(true)) - for solver in SOLVERS + for (i, solver) in enumerate(SOLVERS) @info "Testing $solver" sol = @time solve(bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) @test norm(sol.resid, Inf) < 0.005 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp1, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp1, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] end # IIP MP-BVP @@ -59,11 +76,19 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test bvp2 = BVProblem(BVPFunction{true}(f1!, bc1!; bcresid_prototype = zeros(4)), u0, tspan; nlls = Val(true)) - for solver in SOLVERS + for (i, solver) in enumerate(SOLVERS) @info "Testing $solver" sol = @time solve(bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) @test norm(sol.resid, Inf) < 0.005 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp2, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp2, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] end # OOP TP-BVP @@ -73,10 +98,19 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test bvp3 = BVProblem(BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), bcresid_prototype = (zeros(1), zeros(2))), u0, tspan; nlls = Val(true)) - for solver in SOLVERS + for (i, solver) in enumerate(SOLVERS) @info "Testing $solver" - sol = @time solve(bvp3, solver; verbose = false) - @test norm(sol.resid, Inf) < 1e-4 + sol = @time solve(bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.009 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp3, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp3, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] end # IIP TP-BVP @@ -86,9 +120,18 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test bvp4 = BVProblem(BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), bcresid_prototype = (zeros(1), zeros(2))), u0, tspan; nlls = Val(true)) - for solver in SOLVERS + for (i, solver) in enumerate(SOLVERS) @info "Testing $solver" - sol = @time solve(bvp4, solver; verbose = false) - @test norm(sol.resid, Inf) < 1e-4 + sol = @time solve(bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.009 + + JET_SKIP[i] && continue + @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp4, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, + BoundaryValueDiffEq) solve(bvp4, solver; verbose = false, abstol = 1e-6, + reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] end end diff --git a/test/shooting/orbital.jl b/test/shooting/orbital.jl index 8e2d5067..f1f8899c 100644 --- a/test/shooting/orbital.jl +++ b/test/shooting/orbital.jl @@ -62,8 +62,6 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test cur_bc! = (resid, sol, p, t) -> bc!_generator(resid, sol, init_val) cur_bc_2point_a! = (resid, sol, p) -> bc!_generator_2p_a(resid, sol, init_val) cur_bc_2point_b! = (resid, sol, p) -> bc!_generator_2p_b(resid, sol, init_val) - resid_f = Array{Float64}(undef, 6) - resid_f_2p = (Array{Float64, 1}(undef, 3), Array{Float64, 1}(undef, 3)) @info "Solving Lambert's Problem in Multi Point BVP Form" @@ -72,14 +70,15 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test AutoFiniteDiff(; fdtype = Val(:central)), AutoSparseForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:forward)), AutoSparseFiniteDiff()) nlsolve = TrustRegion(; autodiff) + @info "Single Shooting Lambert's Problem: $(autodiff)" @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - cur_bc!(resid_f, sol, nothing, sol.t) - @info "Single Shooting Lambert's Problem: $(norm(resid_f, Inf))" + + @info "Single Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) - @test norm(resid_f, Inf) < 1e-6 + @test norm(sol.resid, Inf) < 1e-6 @info "Multiple Shooting Lambert's Problem: $(autodiff)" jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, @@ -87,13 +86,12 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - cur_bc!(resid_f, sol, nothing, sol.t) - @info "Multiple Shooting Lambert's Problem: $(norm(resid_f, Inf))" + + @info "Multiple Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) - @test norm(resid_f, Inf) < 1e-6 + @test norm(sol.resid, Inf) < 1e-6 end - println() @info "Solving Lambert's Problem in Two Point BVP Form" bvp = TwoPointBVProblem(orbital!, (cur_bc_2point_a!, cur_bc_2point_b!), y0, tspan; @@ -103,25 +101,24 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test AutoFiniteDiff(; fdtype = Val(:central)), AutoFiniteDiff(; fdtype = Val(:forward)), AutoSparseForwardDiff(; chunksize = 6)) nlsolve = TrustRegion(; autodiff) + @info "Single Shooting Lambert's Problem: $(autodiff)" @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - cur_bc_2point_a!(resid_f_2p[1], sol(t0), nothing) - cur_bc_2point_b!(resid_f_2p[2], sol(t1), nothing) - @info "Single Shooting Lambert's Problem: $(norm(reduce(vcat, resid_f_2p), Inf))" + + @info "Single Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) - @test norm(reduce(vcat, resid_f_2p), Inf) < 1e-6 + @test norm(sol.resid, Inf) < 1e-6 @info "Multiple Shooting Lambert's Problem: $(autodiff)" jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, bc_diffmode = autodiff) @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - cur_bc_2point_a!(resid_f_2p[1], sol(t0), nothing) - cur_bc_2point_b!(resid_f_2p[2], sol(t1), nothing) - @info "Multiple Shooting Lambert's Problem: $(norm(reduce(vcat, resid_f_2p), Inf))" + + @info "Multiple Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) - @test norm(reduce(vcat, resid_f_2p), Inf) < 1e-6 + @test norm(sol.resid, Inf) < 1e-6 end end From 0cbd20d07dcfecae66b6c15b450031ec2ff1c489 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Dec 2023 19:43:06 -0500 Subject: [PATCH 06/24] Fix ODEInterface tests --- .github/workflows/CI.yml | 1 - .github/workflows/CompatHelper.yml | 2 +- Manifest.toml | 121 +++++++++++++--------- Project.toml | 6 +- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 4 +- src/solve/multiple_shooting.jl | 4 +- src/utils.jl | 3 +- test/misc/odeinterface_wrapper.jl | 30 +++--- 8 files changed, 99 insertions(+), 72 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e6d309af..b60283ad 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,7 +23,6 @@ jobs: - Others version: - '1' - - '~1.10.0-0' steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml index 46670d75..0fe6c374 100644 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - julia-version: [1.5.0] + julia-version: [1] julia-arch: [x86] os: [ubuntu-latest] steps: diff --git a/Manifest.toml b/Manifest.toml index 2464fce9..cfb98313 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,8 +1,8 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.0-rc2" +julia_version = "1.10.0" manifest_format = "2.0" -project_hash = "0ac16cb78a3540d2a0e82de32da74fda24f340a4" +project_hash = "d7c3c48e84b3bd6db2d27ce714362096378baf8a" [[deps.ADTypes]] git-tree-sha1 = "41c37aa88889c171f1300ceac1313c06e891d245" @@ -11,9 +11,9 @@ version = "0.2.6" [[deps.Adapt]] deps = ["LinearAlgebra", "Requires"] -git-tree-sha1 = "cde29ddf7e5726c9fb511f340244ea3481267608" +git-tree-sha1 = "0fb305e0253fd4e833d486914367a2ee2c2e78d0" uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "3.7.2" +version = "4.0.1" weakdeps = ["StaticArrays"] [deps.Adapt.extensions] @@ -53,9 +53,9 @@ version = "7.7.0" [[deps.ArrayLayouts]] deps = ["FillArrays", "LinearAlgebra"] -git-tree-sha1 = "b08a4043e1c14096ef8efe4dd97e07de5cacf240" +git-tree-sha1 = "a45ec4acc9d905f94b47243cff666820bb107789" uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "1.4.5" +version = "1.5.2" weakdeps = ["SparseArrays"] [deps.ArrayLayouts.extensions] @@ -107,10 +107,10 @@ uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" version = "0.3.0" [[deps.Compat]] -deps = ["UUIDs"] -git-tree-sha1 = "886826d76ea9e72b35fcd000e535588f7b60f21d" +deps = ["TOML", "UUIDs"] +git-tree-sha1 = "75bd5b6fc5089df449b5d35fa501c846c9b6549b" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.10.1" +version = "4.12.0" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -147,15 +147,15 @@ uuid = "adafc99b-e345-5852-983c-f28acb93d879" version = "0.3.1" [[deps.DataAPI]] -git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" +git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.15.0" +version = "1.16.0" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d" +git-tree-sha1 = "ac67408d9ddf207de5cfa9a97e114352430f01ed" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.15" +version = "0.18.16" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -168,9 +168,9 @@ uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" [[deps.DiffEqBase]] deps = ["ArrayInterface", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces"] -git-tree-sha1 = "8775b80752e9656000ab3800adad8ee22c9cb8f6" +git-tree-sha1 = "6af33c2eb7478db06bcf5c810e6f3dda53aac2ac" uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.145.0" +version = "6.146.0" [deps.DiffEqBase.extensions] DiffEqBaseChainRulesCoreExt = "ChainRulesCore" @@ -229,10 +229,13 @@ uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" version = "1.0.4" [[deps.EnzymeCore]] -deps = ["Adapt"] -git-tree-sha1 = "2efe862de93cd87f620ad6ac9c9e3f83f1b2841b" +git-tree-sha1 = "59c44d8fbc651c0395d8a6eda64b05ce316f58b4" uuid = "f151be2c-9106-41f4-ab19-57ee4f262869" -version = "0.6.4" +version = "0.6.5" +weakdeps = ["Adapt"] + + [deps.EnzymeCore.extensions] + AdaptExt = "Adapt" [[deps.ExprTools]] git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" @@ -258,9 +261,9 @@ version = "0.3.2" [[deps.FastLapackInterface]] deps = ["LinearAlgebra"] -git-tree-sha1 = "b12f05108e405dadcc2aff0008db7f831374e051" +git-tree-sha1 = "d576a29bf8bcabf4b1deb9abe88a3d7f78306ab5" uuid = "29a986be-02c6-4525-aec4-84b980013641" -version = "2.0.0" +version = "2.0.1" [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" @@ -283,9 +286,9 @@ version = "1.9.3" [[deps.FiniteDiff]] deps = ["ArrayInterface", "LinearAlgebra", "Requires", "Setfield", "SparseArrays"] -git-tree-sha1 = "c6e4a1fbe73b31a3dea94b1da449503b8830c306" +git-tree-sha1 = "73d1214fec245096717847c62d389a5d2ac86504" uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" -version = "2.21.1" +version = "2.22.0" [deps.FiniteDiff.extensions] FiniteDiffBandedMatricesExt = "BandedMatrices" @@ -324,9 +327,9 @@ uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" [[deps.GPUArraysCore]] deps = ["Adapt"] -git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0" +git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950" uuid = "46192b85-c4d5-4398-a991-12ede77f4527" -version = "0.1.5" +version = "0.1.6" [[deps.Graphs]] deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] @@ -452,10 +455,10 @@ deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LinearSolve]] -deps = ["ArrayInterface", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "Requires", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] -git-tree-sha1 = "ebdc72aa2f1ccbb9f9dd1e85698145024b762ac3" +deps = ["ArrayInterface", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] +git-tree-sha1 = "6f8e084deabe3189416c4e505b1c53e1b590cae8" uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "2.21.2" +version = "2.22.1" [deps.LinearSolve.extensions] LinearSolveBandedMatricesExt = "BandedMatrices" @@ -528,9 +531,9 @@ version = "2024.0.0+0" [[deps.MacroTools]] deps = ["Markdown", "Random"] -git-tree-sha1 = "b211c553c199c111d998ecdaf7623d1b89b69f93" +git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.12" +version = "0.5.13" [[deps.ManualMemory]] git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd" @@ -587,10 +590,10 @@ uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" version = "1.2.0" [[deps.NonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "EnumX", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] -git-tree-sha1 = "72b036b728461272ae1b1c3f7096cb4c319d8793" +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] +git-tree-sha1 = "323d2a61f4adc4dfe404bf332b59690253b4f4f2" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.4.0" +version = "3.5.3" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" @@ -676,10 +679,10 @@ uuid = "1d0040c9-8b98-4ee7-8388-3f51789ca0ad" version = "0.2.1" [[deps.PreallocationTools]] -deps = ["Adapt", "ArrayInterface", "ForwardDiff", "Requires"] -git-tree-sha1 = "01ac95fca7daabe77a9cb705862bd87016af9ddb" +deps = ["Adapt", "ArrayInterface", "ForwardDiff"] +git-tree-sha1 = "64bb68f76f789f5fe5930a80af310f19cdafeaed" uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" -version = "0.4.13" +version = "0.4.17" [deps.PreallocationTools.extensions] PreallocationToolsReverseDiffExt = "ReverseDiff" @@ -718,15 +721,16 @@ uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" version = "1.3.4" [[deps.RecursiveArrayTools]] -deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "Requires", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "96fdc4a33fa4282e6f3ed54de6be569b1aa43972" +deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] +git-tree-sha1 = "5a904ad526cc9a2c5b464f6642ce9dd230fd69b6" uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "3.2.6" +version = "3.7.0" [deps.RecursiveArrayTools.extensions] RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" RecursiveArrayToolsMeasurementsExt = "Measurements" RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" + RecursiveArrayToolsReverseDiffExt = ["ReverseDiff", "Zygote"] RecursiveArrayToolsTrackerExt = "Tracker" RecursiveArrayToolsZygoteExt = "Zygote" @@ -734,6 +738,7 @@ version = "3.2.6" FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" @@ -777,11 +782,11 @@ version = "0.6.42" [[deps.SciMLBase]] deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FillArrays", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables", "TruncatedStacktraces"] -git-tree-sha1 = "b8f7a0807314cce87bf846ba5fd12c1b0ef512b7" +git-tree-sha1 = "40642998c5edee0d229a18c29084f656b690e464" repo-rev = "ap/nlls_bvp" repo-url = "https://github.com/SciML/SciMLBase.jl.git" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "2.12.0" +version = "2.22.0" [deps.SciMLBase.extensions] SciMLBaseChainRulesCoreExt = "ChainRulesCore" @@ -820,10 +825,18 @@ deps = ["Distributed", "Mmap", "Random", "Serialization"] uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" [[deps.SimpleNonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] -git-tree-sha1 = "1a467a5767d712863e2108e86f7ab103f6d54b13" +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] +git-tree-sha1 = "470c5f97af31fa35926b45eb01e53a46c8d7d35f" uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" -version = "1.0.4" +version = "1.3.1" + + [deps.SimpleNonlinearSolve.extensions] + SimpleNonlinearSolvePolyesterForwardDiffExt = "PolyesterForwardDiff" + SimpleNonlinearSolveStaticArraysExt = "StaticArrays" + + [deps.SimpleNonlinearSolve.weakdeps] + PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" [[deps.SimpleTraits]] deps = ["InteractiveUtils", "MacroTools"] @@ -841,17 +854,19 @@ version = "1.10.0" [[deps.SparseDiffTools]] deps = ["ADTypes", "Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "PackageExtensionCompat", "Random", "Reexport", "SciMLOperators", "Setfield", "SparseArrays", "StaticArrayInterface", "StaticArrays", "Tricks", "UnPack", "VertexSafeGraphs"] -git-tree-sha1 = "c281e11db4eacb36a292a054bac83c5a0aca2a26" +git-tree-sha1 = "3b38ae7a1cbe9b8b1344359599753957644b03d4" uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -version = "2.15.0" +version = "2.16.0" [deps.SparseDiffTools.extensions] SparseDiffToolsEnzymeExt = "Enzyme" + SparseDiffToolsPolyesterForwardDiffExt = "PolyesterForwardDiff" SparseDiffToolsSymbolicsExt = "Symbolics" SparseDiffToolsZygoteExt = "Zygote" [deps.SparseDiffTools.weakdeps] Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" @@ -892,9 +907,9 @@ weakdeps = ["OffsetArrays", "StaticArrays"] [[deps.StaticArrays]] deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] -git-tree-sha1 = "fba11dbe2562eecdfcac49a05246af09ee64d055" +git-tree-sha1 = "7b0e9c14c624e435076d19aea1e5cbdec2b9ca37" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.8.1" +version = "1.9.2" [deps.StaticArrays.extensions] StaticArraysChainRulesCoreExt = "ChainRulesCore" @@ -925,14 +940,14 @@ deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" [[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" version = "7.2.1+1" [[deps.SymbolicIndexingInterface]] -git-tree-sha1 = "65f4ed0f9e3125e0836df12c231cea3dd98bb165" +git-tree-sha1 = "b3103f4f50a3843e66297a2456921377c78f5e31" uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" -version = "0.3.0" +version = "0.3.5" [[deps.TOML]] deps = ["Dates"] @@ -966,6 +981,12 @@ git-tree-sha1 = "eda08f7e9818eb53661b3deb74e3159460dfbc27" uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" version = "0.5.2" +[[deps.TimerOutputs]] +deps = ["ExprTools", "Printf"] +git-tree-sha1 = "f548a9e9c490030e545f72074a41edfd0e5bcdd7" +uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" +version = "0.5.23" + [[deps.TriangularSolve]] deps = ["CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "LoopVectorization", "Polyester", "Static", "VectorizationBase"] git-tree-sha1 = "fadebab77bf3ae041f77346dd1c290173da5a443" diff --git a/Project.toml b/Project.toml index a3132353..739a961f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BoundaryValueDiffEq" uuid = "764a87c0-6b3e-53db-9096-fe964310641d" -version = "5.6.3" +version = "5.7.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" @@ -51,7 +51,7 @@ ForwardDiff = "0.10" JET = "0.8" LinearAlgebra = "1.9" LinearSolve = "2.20" -NonlinearSolve = "2.6.1, 3" +NonlinearSolve = "3.5" ODEInterface = "0.5" OrdinaryDiffEq = "6" PreallocationTools = "0.4" @@ -70,7 +70,7 @@ Test = "1" Tricks = "0.1" TruncatedStacktraces = "1" UnPack = "1" -julia = "1.9" +julia = "1.10" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index e023f95f..6fb28799 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -39,7 +39,7 @@ function __solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs... n == -1 && dt ≤ 0 && throw(ArgumentError("`dt` must be positive.")) - mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n)) + mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n - 1)) n = length(mesh) - 1 no_odes = length(u0_) @@ -122,7 +122,7 @@ function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, d n == -1 && dt ≤ 0 && throw(ArgumentError("`dt` must be positive.")) u0 = __flatten_initial_guess(prob.u0) - mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n)) + mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n - 1)) if u0 === nothing # initial_guess function was provided u0 = mapreduce(@closure(t->vec(__initial_guess(prob.u0, prob.p, t))), hcat, mesh) diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index 7defa28f..13bda8db 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -34,7 +34,7 @@ function __solve(prob::BVProblem, _alg::MultipleShooting; odesolve_kwargs = (;), internal_ode_kwargs = (; verbose, kwargs..., odesolve_kwargs..., save_end = true) solve_internal_odes! = @closure (resid_nodes, us, p, cur_nshoot, nodes, - odecache) -> __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoot, + odecache) -> __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoot, odecache, nodes, u0_size, N, ensemblealg, tspan) # This gets all the nshoots except the final SingleShooting case @@ -480,4 +480,4 @@ end end @assert !(1 in nshoots_vec) return nshoots_vec -end \ No newline at end of file +end diff --git a/src/utils.jl b/src/utils.jl index 5c2a5d27..08ddcf7c 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -313,7 +313,8 @@ Takes the input initial guess and returns the mesh. """ @inline __extract_mesh(u₀, t₀, t₁, n::Int) = collect(range(t₀; stop = t₁, length = n + 1)) @inline __extract_mesh(u₀, t₀, t₁, dt::Number) = collect(t₀:dt:t₁) -@inline __extract_mesh(u₀::DiffEqArray, t₀, t₁, n) = u₀.t +@inline __extract_mesh(u₀::DiffEqArray, t₀, t₁, ::Int) = u₀.t +@inline __extract_mesh(u₀::DiffEqArray, t₀, t₁, ::Number) = u₀.t """ __has_initial_guess(u₀) -> Bool diff --git a/test/misc/odeinterface_wrapper.jl b/test/misc/odeinterface_wrapper.jl index aa747a1e..0ee307b6 100644 --- a/test/misc/odeinterface_wrapper.jl +++ b/test/misc/odeinterface_wrapper.jl @@ -1,4 +1,5 @@ -using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, RecursiveArrayTools +using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, OrdinaryDiffEq, + RecursiveArrayTools # Adaptation of https://github.com/luchr/ODEInterface.jl/blob/958b6023d1dabf775033d0b89c5401b33100bca3/examples/BasicExamples/ex7.jl function ex7_f!(du, u, p, t) @@ -25,7 +26,6 @@ tspan = (-π / 2, π / 2) tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) -sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) @testset "BVPM2" begin @info "Testing BVPM2" @@ -38,14 +38,19 @@ sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) @test norm(resid_f, Inf) < 1e-6 end +# Just generate a solution for bvpsol +sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); + dt = π / 20, abstol = 1e-5, maxiters = 1000, + odesolve_kwargs = (; adaptive = false, dt = 0.01, abstol = 1e-6, maxiters = 1000)) + # Just test that it runs. BVPSOL only works with linearly separable BCs. @testset "BVPSOL" begin @info "Testing BVPSOL" @info "BVPSOL with Vector{<:AbstractArray}" - initial_u0 = [sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + initial_u0 = [sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) # Just test that it runs. BVPSOL only works with linearly separable BCs. @@ -53,8 +58,8 @@ end @info "BVPSOL with VectorOfArray" - initial_u0 = VectorOfArray([sol_bvpm2(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + initial_u0 = VectorOfArray([sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) # Just test that it runs. BVPSOL only works with linearly separable BCs. @@ -63,18 +68,19 @@ end @info "BVPSOL with DiffEqArray" ts = collect(tspan[1]:(π / 20):tspan[2]) - initial_u0 = DiffEqArray([sol_bvpm2(t) .+ rand() for t in ts], ts) - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan; + initial_u0 = DiffEqArray([sol_ms(t) .+ rand() for t in ts], ts) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) @info "BVPSOL with initial guess function" - initial_u0 = (p, t) -> sol_bvpm2(t) .+ rand() - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) - sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) + initial_u0 = (p, t) -> sol_ms(t) .+ rand() + # FIXME: Upstream fix + # tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; + # bcresid_prototype = (zeros(1), zeros(1))) + # sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) end #= From 54397882984ef889cf90fe3457e355e808689fae Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Fri, 2 Feb 2024 07:36:08 -0500 Subject: [PATCH 07/24] Fix MS and SS --- src/solve/single_shooting.jl | 2 +- src/types.jl | 2 +- src/utils.jl | 15 +++++++++++++++ test/shooting/nonlinear_least_squares.jl | 14 +++++++++++--- test/shooting/orbital.jl | 1 - 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/solve/single_shooting.jl b/src/solve/single_shooting.jl index 46fffb30..7e95fdd6 100644 --- a/src/solve/single_shooting.jl +++ b/src/solve/single_shooting.jl @@ -80,7 +80,7 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), prob.p) odesol = __solve(internal_prob_final, alg.ode_alg; actual_ode_kwargs...) - return SciMLBase.build_solution(prob, odesol, nlsol) + return __build_solution(prob, odesol, nlsol) end function __single_shooting_loss!(resid_, u0_, p, cache, bc::BC, u0_size, diff --git a/src/types.jl b/src/types.jl index 098949d4..9948dcc5 100644 --- a/src/types.jl +++ b/src/types.jl @@ -43,7 +43,7 @@ end @inline __materialize_jacobian_algorithm(_, alg::ADTypes.AbstractADType) = BVPJacobianAlgorithm(alg) @inline __materialize_jacobian_algorithm(::Nothing, ::Nothing) = BVPJacobianAlgorithm() @inline function __materialize_jacobian_algorithm(nlsolve::N, ::Nothing) where {N} - ad = hasfield(N, :ad) ? nlsolve.ad : missing + ad = hasfield(N, :jacobian_ad) ? nlsolve.jacobian_ad : missing return BVPJacobianAlgorithm(ad) end diff --git a/src/utils.jl b/src/utils.jl index 08ddcf7c..67debb51 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -377,3 +377,18 @@ end @inline function __initial_guess_on_mesh(u₀::F, mesh, p, alias_u0::Bool) where {F} return [vec(__initial_guess(u₀, p, t)) for t in mesh] end + +# Construct BVP Solution +function __build_solution(prob::BVProblem, odesol, nlsol) + retcode = ifelse(SciMLBase.successful_retcode(nlsol), odesol.retcode, nlsol.retcode) + return __solution_new_original_retcode(odesol, nlsol, retcode, nlsol.resid) +end + +function __solution_new_original_retcode(sol::ODESolution{T, N}, original, retcode, + resid) where {T, N} + return ODESolution{T, N, typeof(sol.u), typeof(sol.u_analytic), typeof(sol.errors), + typeof(sol.t), typeof(sol.k), typeof(sol.prob), typeof(sol.alg), typeof(sol.interp), + typeof(sol.stats), typeof(sol.alg_choice), typeof(resid), typeof(original)}(sol.u, + sol.u_analytic, sol.errors, sol.t, sol.k, sol.prob, sol.alg, sol.interp, sol.dense, + sol.tslocation, sol.stats, sol.alg_choice, retcode, resid, original) +end diff --git a/test/shooting/nonlinear_least_squares.jl b/test/shooting/nonlinear_least_squares.jl index 1b60d831..3b07e4d8 100644 --- a/test/shooting/nonlinear_least_squares.jl +++ b/test/shooting/nonlinear_least_squares.jl @@ -1,13 +1,21 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET +# NOTE: The nonlinear solve polyalgorithm for NLLS is currently broken because of Bastin +# Jv & Jᵀv computation with the cached ODE solve @testset "Overconstrained BVP" begin SOLVERS = [ - Shooting(Tsit5()), + # Shooting(Tsit5()), + Shooting(Tsit5(), + LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), Shooting(Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), Shooting(Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), - MultipleShooting(10, Tsit5()), + # MultipleShooting(10, Tsit5()), + MultipleShooting(10, Tsit5(), + LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), @@ -15,7 +23,7 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), ] - JET_SKIP = [true, false, false, false, false, true, false, false, false, false] + JET_SKIP = [false, false, false, false, false, false, false, false, false, false] JET_BROKEN = [false, false, false, false, false, false, false, false, false, false] @info "Solving Overconstrained BVPs" diff --git a/test/shooting/orbital.jl b/test/shooting/orbital.jl index f1f8899c..509d1c59 100644 --- a/test/shooting/orbital.jl +++ b/test/shooting/orbital.jl @@ -1,4 +1,3 @@ -# Lambert's Problem using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test @testset "Lambert's Problem" begin From 5e6022395b6385908f5663f4c1f7c9cca2b5e39e Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Wed, 20 Mar 2024 13:06:57 -0400 Subject: [PATCH 08/24] Format --- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 3 +- ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl | 42 ++++++++++++++------- src/algorithms.jl | 2 + test/misc/odeinterface_wrapper.jl | 2 +- test/shooting/basic_problems.jl | 22 +++++++---- test/shooting/nonlinear_least_squares.jl | 18 ++++++--- test/shooting/orbital.jl | 4 +- 7 files changed, 64 insertions(+), 29 deletions(-) diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 6fb28799..5d0bf92b 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -2,7 +2,8 @@ module BoundaryValueDiffEqODEInterfaceExt using SciMLBase, BoundaryValueDiffEq, ODEInterface, RecursiveArrayTools import BoundaryValueDiffEq: __extract_u0, __flatten_initial_guess, - __extract_mesh, __initial_guess_length, __initial_guess, __has_initial_guess + __extract_mesh, __initial_guess_length, __initial_guess, + __has_initial_guess import SciMLBase: __solve import ODEInterface: OptionsODE, OPT_ATOL, OPT_RTOL, OPT_METHODCHOICE, OPT_DIAGNOSTICOUTPUT, OPT_ERRORCONTROL, OPT_SINGULARTERM, OPT_MAXSTEPS, OPT_BVPCLASS, diff --git a/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl b/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl index 3c59832d..9f4b3f49 100644 --- a/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl +++ b/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl @@ -37,10 +37,16 @@ end probs = [ BVProblem(BVPFunction{true}(f1!, bc1!), u0, tspan; nlls = Val(false)), BVProblem(BVPFunction{false}(f1, bc1), u0, tspan; nlls = Val(false)), - BVProblem(BVPFunction{true}(f1!, (bc1_a!, bc1_b!); bcresid_prototype, - twopoint = Val(true)), u0, tspan; nlls = Val(false)), - BVProblem(BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, - twopoint = Val(true)), u0, tspan; nlls = Val(false)), + BVProblem( + BVPFunction{true}(f1!, (bc1_a!, bc1_b!); bcresid_prototype, + twopoint = Val(true)), + u0, + tspan; + nlls = Val(false)), + BVProblem( + BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, + twopoint = Val(true)), + u0, tspan; nlls = Val(false)) ] algs = [] @@ -94,16 +100,26 @@ end bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) probs = [ - BVProblem(BVPFunction{true}(f1_nlls!, bc1_nlls!; - bcresid_prototype = bcresid_prototype1), u0, tspan; nlls = Val(true)), - BVProblem(BVPFunction{false}(f1_nlls, bc1_nlls; - bcresid_prototype = bcresid_prototype1), u0, tspan; nlls = Val(true)), - BVProblem(BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); - bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), u0, tspan; - nlls = Val(true)), - BVProblem(BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); - bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), u0, tspan; + BVProblem( + BVPFunction{true}(f1_nlls!, bc1_nlls!; + bcresid_prototype = bcresid_prototype1), + u0, tspan; nlls = Val(true)), + BVProblem( + BVPFunction{false}(f1_nlls, bc1_nlls; + bcresid_prototype = bcresid_prototype1), + u0, tspan; nlls = Val(true)), + BVProblem( + BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); + bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), + u0, + tspan; nlls = Val(true)), + BVProblem( + BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); + bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), + u0, + tspan; + nlls = Val(true)) ] algs = [] diff --git a/src/algorithms.jl b/src/algorithms.jl index 738ce066..4d7250a5 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -305,9 +305,11 @@ ODEs. It incorporates a new basis representation replacing b-splines, and improv the linear and nonlinear algebraic equation solvers. !!! warning + Only supports two-point boundary value problems. !!! note + Only available if the `ODEInterface` package is loaded. """ struct COLNEW <: BoundaryValueDiffEqAlgorithm diff --git a/test/misc/odeinterface_wrapper.jl b/test/misc/odeinterface_wrapper.jl index 0ee307b6..84c2fee8 100644 --- a/test/misc/odeinterface_wrapper.jl +++ b/test/misc/odeinterface_wrapper.jl @@ -1,5 +1,5 @@ using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, OrdinaryDiffEq, - RecursiveArrayTools + RecursiveArrayTools # Adaptation of https://github.com/luchr/ODEInterface.jl/blob/958b6023d1dabf775033d0b89c5401b33100bca3/examples/BasicExamples/ex7.jl function ex7_f!(du, u, p, t) diff --git a/test/shooting/basic_problems.jl b/test/shooting/basic_problems.jl index 5fd51adc..83f426fe 100644 --- a/test/shooting/basic_problems.jl +++ b/test/shooting/basic_problems.jl @@ -8,7 +8,7 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET MultipleShooting(10, Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), MultipleShooting(10, Tsit5(), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5()), + MultipleShooting(10, Tsit5()) ] JET_SKIP = [false, false, true, false, false, true] JET_BROKEN = [false, false, false, false, false, false] @@ -144,7 +144,7 @@ end Shooting(Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), Shooting(Vern7()), MultipleShooting(10, Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), - MultipleShooting(10, Vern7()), + MultipleShooting(10, Vern7()) ] function f1!(du, u, p, t) @@ -216,7 +216,7 @@ end Shooting(AutoTsit5(Rosenbrock23()), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))), MultipleShooting(10, AutoTsit5(Rosenbrock23()), - NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))), + NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))) ] @info "Solver: $solver" sol = @time solve(flow_bvp, solver; abstol = 1e-8, reltol = 1e-8, @@ -333,12 +333,20 @@ end nlls = Val(false)) prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; nlls = Val(true)) - prob_tp_oop = BVProblem(BVPFunction{false}(ray_tracing, - (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; + prob_tp_oop = BVProblem( + BVPFunction{false}(ray_tracing, + (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), + u0, + tspan, + p; nlls = Val(true)) - prob_tp_iip = BVProblem(BVPFunction{true}(ray_tracing!, + prob_tp_iip = BVProblem( + BVPFunction{true}(ray_tracing!, (ray_tracing_bc_a!, ray_tracing_bc_b!); - bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; + bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), + u0, + tspan, + p; nlls = Val(true)) @info "Ray Tracing: Multiple Shooting" diff --git a/test/shooting/nonlinear_least_squares.jl b/test/shooting/nonlinear_least_squares.jl index 3b07e4d8..f073043b 100644 --- a/test/shooting/nonlinear_least_squares.jl +++ b/test/shooting/nonlinear_least_squares.jl @@ -21,7 +21,7 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), + MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())) ] JET_SKIP = [false, false, false, false, false, false, false, false, false, false] JET_BROKEN = [false, false, false, false, false, false, false, false, false, false] @@ -103,8 +103,12 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET bc1a(ua, p) = [ua[1]] bc1b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - bvp3 = BVProblem(BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), - bcresid_prototype = (zeros(1), zeros(2))), u0, tspan; nlls = Val(true)) + bvp3 = BVProblem( + BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), + bcresid_prototype = (zeros(1), zeros(2))), + u0, + tspan; + nlls = Val(true)) for (i, solver) in enumerate(SOLVERS) @info "Testing $solver" @@ -125,8 +129,12 @@ using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET bc1a!(resid, ua, p) = (resid[1] = ua[1]) bc1b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - bvp4 = BVProblem(BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), - bcresid_prototype = (zeros(1), zeros(2))), u0, tspan; nlls = Val(true)) + bvp4 = BVProblem( + BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), + bcresid_prototype = (zeros(1), zeros(2))), + u0, + tspan; + nlls = Val(true)) for (i, solver) in enumerate(SOLVERS) @info "Testing $solver" diff --git a/test/shooting/orbital.jl b/test/shooting/orbital.jl index 509d1c59..3785eb52 100644 --- a/test/shooting/orbital.jl +++ b/test/shooting/orbital.jl @@ -7,7 +7,7 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test -5.3500183933132319E+06, -5528.612564911408, 1216.8442360202787, - 4845.114446429901, + 4845.114446429901 ] init_val = [ -4.7763169762853989E+06, @@ -15,7 +15,7 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test -5.3500183933132319E+06, 7.0526926403748598E+06, -7.9650476230388973E+05, - -1.1911128863666430E+06, + -1.1911128863666430E+06 ] J2 = 1.08262668E-3 req = 6378137 From b456de433b19a1ac707730cfcd58b7b9480486b5 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Wed, 20 Mar 2024 13:59:53 -0400 Subject: [PATCH 09/24] Move some of the tests --- .JuliaFormatter.toml | 1 + .github/workflows/CI.yml | 8 +- Manifest.toml | 206 ++++++---- Project.toml | 20 +- README.md | 4 +- benchmark/simple_pendulum.jl | 18 +- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 28 +- ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl | 158 -------- src/BoundaryValueDiffEq.jl | 363 ++++++++++++------ src/adaptivity.jl | 81 ++-- src/algorithms.jl | 31 +- src/collocation.jl | 16 +- src/interpolation.jl | 12 +- src/solve/mirk.jl | 131 ++++--- src/solve/multiple_shooting.jl | 223 ++++++----- src/solve/single_shooting.jl | 45 +-- src/sparse_jacobians.jl | 12 +- src/types.jl | 35 +- src/utils.jl | 77 ++-- test/mirk/ensemble.jl | 4 +- test/mirk/interpolation_test.jl | 8 +- test/mirk/mirk_convergence_tests.jl | 36 +- test/mirk/nonlinear_least_squares.jl | 4 +- test/mirk/vectorofvector_initials.jl | 3 +- test/misc/non_vector_inputs.jl | 6 +- test/misc/odeinterface_wrapper.jl | 16 +- test/runtests.jl | 65 +--- ...ic_problems.jl => basic_problems_tests.jl} | 138 +++---- test/shooting/nlls_tests.jl | 154 ++++++++ test/shooting/nonlinear_least_squares.jl | 153 -------- .../shooting/{orbital.jl => orbital_tests.jl} | 69 ++-- 31 files changed, 1010 insertions(+), 1115 deletions(-) delete mode 100644 ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl rename test/shooting/{basic_problems.jl => basic_problems_tests.jl} (71%) create mode 100644 test/shooting/nlls_tests.jl delete mode 100644 test/shooting/nonlinear_least_squares.jl rename test/shooting/{orbital.jl => orbital_tests.jl} (53%) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index f1d23682..0cd5f15f 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -2,3 +2,4 @@ style = "sciml" annotate_untyped_fields_with_any = false format_markdown = true format_docstrings = true +join_lines_based_on_source = false diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b60283ad..16bbaea1 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,10 +17,6 @@ jobs: strategy: fail-fast: false matrix: - group: - - Shooting - - MIRK - - Others version: - '1' steps: @@ -41,7 +37,9 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 env: - GROUP: ${{ matrix.group }} + GROUP: "CPU" + RETESTITEMS_NWORKERS: 4 + RETESTITEMS_NWORKER_THREADS: 2 - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v4 with: diff --git a/Manifest.toml b/Manifest.toml index cfb98313..e3102b94 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,19 +1,19 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.0" +julia_version = "1.10.2" manifest_format = "2.0" -project_hash = "d7c3c48e84b3bd6db2d27ce714362096378baf8a" +project_hash = "057fc02bc93810bdc11a7df500e348b3fae4963b" [[deps.ADTypes]] -git-tree-sha1 = "41c37aa88889c171f1300ceac1313c06e891d245" +git-tree-sha1 = "016833eb52ba2d6bea9fcb50ca295980e728ee24" uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" -version = "0.2.6" +version = "0.2.7" [[deps.Adapt]] deps = ["LinearAlgebra", "Requires"] -git-tree-sha1 = "0fb305e0253fd4e833d486914367a2ee2c2e78d0" +git-tree-sha1 = "6a55b747d1812e699320963ffde36f1ebdda4099" uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "4.0.1" +version = "4.0.4" weakdeps = ["StaticArrays"] [deps.Adapt.extensions] @@ -30,16 +30,18 @@ uuid = "ec485272-7323-5ecc-a04f-4719b315124d" version = "0.2.0" [[deps.ArrayInterface]] -deps = ["Adapt", "LinearAlgebra", "Requires", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "bbec08a37f8722786d87bedf84eae19c020c4efa" +deps = ["Adapt", "LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "44691067188f6bd1b2289552a23e4b7572f4528d" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "7.7.0" +version = "7.9.0" [deps.ArrayInterface.extensions] ArrayInterfaceBandedMatricesExt = "BandedMatrices" ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" ArrayInterfaceCUDAExt = "CUDA" + ArrayInterfaceChainRulesExt = "ChainRules" ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" + ArrayInterfaceReverseDiffExt = "ReverseDiff" ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" ArrayInterfaceTrackerExt = "Tracker" @@ -47,15 +49,17 @@ version = "7.7.0" BandedMatrices = "aae01518-5342-5314-be14-df237901396f" BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" [[deps.ArrayLayouts]] deps = ["FillArrays", "LinearAlgebra"] -git-tree-sha1 = "a45ec4acc9d905f94b47243cff666820bb107789" +git-tree-sha1 = "2aeaeaff72cdedaa0b5f30dfb8c1f16aefdac65d" uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "1.5.2" +version = "1.7.0" weakdeps = ["SparseArrays"] [deps.ArrayLayouts.extensions] @@ -66,9 +70,9 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [[deps.BandedMatrices]] deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "PrecompileTools"] -git-tree-sha1 = "27baf04c642465b4289179f29bb7127f0673d4f1" +git-tree-sha1 = "c946c5014cf4cdbfacacb363b110e7bffba3e742" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "1.4.0" +version = "1.6.1" weakdeps = ["SparseArrays"] [deps.BandedMatrices.extensions] @@ -89,6 +93,16 @@ git-tree-sha1 = "601f7e7b3d36f18790e2caf83a882d88e9b71ff1" uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" version = "0.2.4" +[[deps.ChainRulesCore]] +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "575cd02e080939a33b6df6c5853d14924c08e35b" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "1.23.0" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" + [[deps.CloseOpenIntervals]] deps = ["Static", "StaticArrayInterface"] git-tree-sha1 = "70232f82ffaab9dc52585e0dd043b5e0c6b714f1" @@ -108,9 +122,9 @@ version = "0.3.0" [[deps.Compat]] deps = ["TOML", "UUIDs"] -git-tree-sha1 = "75bd5b6fc5089df449b5d35fa501c846c9b6549b" +git-tree-sha1 = "c955881e3c981181362ae4088b35995446298b80" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.12.0" +version = "4.14.0" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -119,7 +133,7 @@ weakdeps = ["Dates", "LinearAlgebra"] [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.0.5+1" +version = "1.1.0+0" [[deps.ConcreteStructs]] git-tree-sha1 = "f749037478283d372048690eb3b5f92a79432b34" @@ -128,9 +142,9 @@ version = "0.2.3" [[deps.ConstructionBase]] deps = ["LinearAlgebra"] -git-tree-sha1 = "c53fc348ca4d40d7b371e71fd52251839080cbc9" +git-tree-sha1 = "260fd2400ed2dab602a7c15cf10c1933c59930a2" uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" -version = "1.5.4" +version = "1.5.5" [deps.ConstructionBase.extensions] ConstructionBaseIntervalSetsExt = "IntervalSets" @@ -153,9 +167,9 @@ version = "1.16.0" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "ac67408d9ddf207de5cfa9a97e114352430f01ed" +git-tree-sha1 = "0f4b5d62a88d8f59003e43c25a8a90de9eb76317" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.16" +version = "0.18.18" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -168,9 +182,9 @@ uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" [[deps.DiffEqBase]] deps = ["ArrayInterface", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces"] -git-tree-sha1 = "6af33c2eb7478db06bcf5c810e6f3dda53aac2ac" +git-tree-sha1 = "b19b2bb1ecd1271334e4b25d605e50f75e68fcae" uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.146.0" +version = "6.148.0" [deps.DiffEqBase.extensions] DiffEqBaseChainRulesCoreExt = "ChainRulesCore" @@ -237,6 +251,12 @@ weakdeps = ["Adapt"] [deps.EnzymeCore.extensions] AdaptExt = "Adapt" +[[deps.ExponentialUtilities]] +deps = ["Adapt", "ArrayInterface", "GPUArraysCore", "GenericSchur", "LinearAlgebra", "PrecompileTools", "Printf", "SparseArrays", "libblastrampoline_jll"] +git-tree-sha1 = "8e18940a5ba7f4ddb41fe2b79b6acaac50880a86" +uuid = "d4d017d3-3776-5f7e-afef-a10c40355c18" +version = "1.26.1" + [[deps.ExprTools]] git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" @@ -261,9 +281,9 @@ version = "0.3.2" [[deps.FastLapackInterface]] deps = ["LinearAlgebra"] -git-tree-sha1 = "d576a29bf8bcabf4b1deb9abe88a3d7f78306ab5" +git-tree-sha1 = "0a59c7d1002f3131de53dc4568a47d15a44daef7" uuid = "29a986be-02c6-4525-aec4-84b980013641" -version = "2.0.1" +version = "2.0.2" [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" @@ -286,9 +306,9 @@ version = "1.9.3" [[deps.FiniteDiff]] deps = ["ArrayInterface", "LinearAlgebra", "Requires", "Setfield", "SparseArrays"] -git-tree-sha1 = "73d1214fec245096717847c62d389a5d2ac86504" +git-tree-sha1 = "bc0c5092d6caaea112d3c8e3b238d61563c58d5f" uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" -version = "2.22.0" +version = "2.23.0" [deps.FiniteDiff.extensions] FiniteDiffBandedMatricesExt = "BandedMatrices" @@ -331,6 +351,12 @@ git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950" uuid = "46192b85-c4d5-4398-a991-12ede77f4527" version = "0.1.6" +[[deps.GenericSchur]] +deps = ["LinearAlgebra", "Printf"] +git-tree-sha1 = "fb69b2a645fa69ba5f474af09221b9308b160ce6" +uuid = "c145ed77-6b09-5dd9-b285-bf645a82121e" +version = "0.5.3" + [[deps.Graphs]] deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] git-tree-sha1 = "899050ace26649433ef1af25bc17a815b3db52b7" @@ -381,9 +407,9 @@ version = "1.5.0" [[deps.KLU]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] -git-tree-sha1 = "884c2968c2e8e7e6bf5956af88cb46aa745c854b" +git-tree-sha1 = "07649c499349dad9f08dde4243a4c597064663e9" uuid = "ef3ab10e-7fda-4108-b977-705223b18434" -version = "0.4.1" +version = "0.6.0" [[deps.Krylov]] deps = ["LinearAlgebra", "Printf", "SparseArrays"] @@ -397,12 +423,6 @@ git-tree-sha1 = "62edfee3211981241b57ff1cedf4d74d79519277" uuid = "10f19ff3-798f-405d-979b-55457f8fc047" version = "0.1.15" -[[deps.Lazy]] -deps = ["MacroTools"] -git-tree-sha1 = "1370f8202dac30758f3c345f9909b97f53d87d3f" -uuid = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0" -version = "0.15.1" - [[deps.LazyArrays]] deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "MacroTools", "MatrixFactorizations", "SparseArrays"] git-tree-sha1 = "9cfca23ab83b0dfac93cb1a1ef3331ab9fe596a5" @@ -455,10 +475,10 @@ deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LinearSolve]] -deps = ["ArrayInterface", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] -git-tree-sha1 = "6f8e084deabe3189416c4e505b1c53e1b590cae8" +deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] +git-tree-sha1 = "73d8f61f8d27f279edfbafc93faaea93ea447e94" uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "2.22.1" +version = "2.27.0" [deps.LinearSolve.extensions] LinearSolveBandedMatricesExt = "BandedMatrices" @@ -491,9 +511,9 @@ version = "2.22.1" [[deps.LogExpFunctions]] deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "7d6dd4e9212aebaeed356de34ccf262a3cd415aa" +git-tree-sha1 = "18144f3e9cbe9b15b070288eef858f71b291ce37" uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.26" +version = "0.3.27" [deps.LogExpFunctions.extensions] LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -513,16 +533,12 @@ deps = ["ArrayInterface", "CPUSummary", "CloseOpenIntervals", "DocStringExtensio git-tree-sha1 = "0f5648fbae0d015e3abe5867bca2b362f67a5894" uuid = "bdcacae8-1622-11e9-2a5c-532679323890" version = "0.12.166" +weakdeps = ["ChainRulesCore", "ForwardDiff", "SpecialFunctions"] [deps.LoopVectorization.extensions] ForwardDiffExt = ["ChainRulesCore", "ForwardDiff"] SpecialFunctionsExt = "SpecialFunctions" - [deps.LoopVectorization.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" - [[deps.MKL_jll]] deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl"] git-tree-sha1 = "72dc3cf284559eb8f53aa593fe62cb33f83ed0c0" @@ -591,9 +607,9 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "323d2a61f4adc4dfe404bf332b59690253b4f4f2" +git-tree-sha1 = "d52bac2b94358b4b960cbfb896d5193d67f3ff09" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.5.3" +version = "3.8.0" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" @@ -601,6 +617,7 @@ version = "3.5.3" NonlinearSolveFixedPointAccelerationExt = "FixedPointAcceleration" NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" NonlinearSolveMINPACKExt = "MINPACK" + NonlinearSolveNLSolversExt = "NLSolvers" NonlinearSolveNLsolveExt = "NLsolve" NonlinearSolveSIAMFANLEquationsExt = "SIAMFANLEquations" NonlinearSolveSpeedMappingExt = "SpeedMapping" @@ -613,6 +630,7 @@ version = "3.5.3" FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176" LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" + NLSolvers = "337daf1e-9722-11e9-073e-8b9effe078ba" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" @@ -631,7 +649,7 @@ weakdeps = ["Adapt"] [[deps.OpenBLAS_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.23+2" +version = "0.3.23+4" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] @@ -649,6 +667,12 @@ git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" version = "1.6.3" +[[deps.OrdinaryDiffEq]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastBroadcast", "FastClosures", "FillArrays", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "IfElse", "InteractiveUtils", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "MacroTools", "MuladdMacro", "NonlinearSolve", "Polyester", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SimpleUnPack", "SparseArrays", "SparseDiffTools", "StaticArrayInterface", "StaticArrays", "TruncatedStacktraces"] +git-tree-sha1 = "287159684e32db56c82dbf545004a7884c6e5198" +uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +version = "6.74.0" + [[deps.PackageExtensionCompat]] git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" uuid = "65ce6f38-6b18-4e1d-a461-8949797d7930" @@ -668,9 +692,9 @@ version = "1.10.0" [[deps.Polyester]] deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Requires", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"] -git-tree-sha1 = "fca25670784a1ae44546bcb17288218310af2778" +git-tree-sha1 = "8df43bbe60029526dd628af7e9951f5af680d4d7" uuid = "f517fe37-dbe3-4b94-8317-1923a5111588" -version = "0.7.9" +version = "0.7.10" [[deps.PolyesterWeave]] deps = ["BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "Static", "ThreadingUtilities"] @@ -680,9 +704,9 @@ version = "0.2.1" [[deps.PreallocationTools]] deps = ["Adapt", "ArrayInterface", "ForwardDiff"] -git-tree-sha1 = "64bb68f76f789f5fe5930a80af310f19cdafeaed" +git-tree-sha1 = "b6665214f2d0739f2d09a17474dd443b9139784a" uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" -version = "0.4.17" +version = "0.4.20" [deps.PreallocationTools.extensions] PreallocationToolsReverseDiffExt = "ReverseDiff" @@ -692,15 +716,15 @@ version = "0.4.17" [[deps.PrecompileTools]] deps = ["Preferences"] -git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.2.0" +version = "1.2.1" [[deps.Preferences]] deps = ["TOML"] -git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.1" +version = "1.4.3" [[deps.Printf]] deps = ["Unicode"] @@ -722,12 +746,13 @@ version = "1.3.4" [[deps.RecursiveArrayTools]] deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "5a904ad526cc9a2c5b464f6642ce9dd230fd69b6" +git-tree-sha1 = "a94d22ca9ad49a7a169ecbc5419c59b9793937cc" uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "3.7.0" +version = "3.12.0" [deps.RecursiveArrayTools.extensions] RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" + RecursiveArrayToolsForwardDiffExt = "ForwardDiff" RecursiveArrayToolsMeasurementsExt = "Measurements" RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" RecursiveArrayToolsReverseDiffExt = ["ReverseDiff", "Zygote"] @@ -736,6 +761,7 @@ version = "3.7.0" [deps.RecursiveArrayTools.weakdeps] FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" @@ -781,15 +807,16 @@ uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa" version = "0.6.42" [[deps.SciMLBase]] -deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FillArrays", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables", "TruncatedStacktraces"] -git-tree-sha1 = "40642998c5edee0d229a18c29084f656b690e464" +deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] +git-tree-sha1 = "0e4fca3dd5de4d4a82c0ffae1e51ab6234af4df0" repo-rev = "ap/nlls_bvp" repo-url = "https://github.com/SciML/SciMLBase.jl.git" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "2.22.0" +version = "2.30.1" [deps.SciMLBase.extensions] SciMLBaseChainRulesCoreExt = "ChainRulesCore" + SciMLBaseMakieExt = "Makie" SciMLBasePartialFunctionsExt = "PartialFunctions" SciMLBasePyCallExt = "PyCall" SciMLBasePythonCallExt = "PythonCall" @@ -799,6 +826,7 @@ version = "2.22.0" [deps.SciMLBase.weakdeps] ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b" PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" @@ -806,10 +834,15 @@ version = "2.22.0" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.SciMLOperators]] -deps = ["ArrayInterface", "DocStringExtensions", "Lazy", "LinearAlgebra", "Setfield", "SparseArrays", "StaticArraysCore", "Tricks"] -git-tree-sha1 = "51ae235ff058a64815e0a2c34b1db7578a06813d" +deps = ["ArrayInterface", "DocStringExtensions", "LinearAlgebra", "MacroTools", "Setfield", "SparseArrays", "StaticArraysCore"] +git-tree-sha1 = "10499f619ef6e890f3f4a38914481cc868689cd5" uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" -version = "0.3.7" +version = "0.3.8" + +[[deps.SciMLStructures]] +git-tree-sha1 = "5833c10ce83d690c124beedfe5f621b50b02ba4d" +uuid = "53ae85a6-f571-4167-b2af-e1d143709226" +version = "1.1.0" [[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -825,18 +858,26 @@ deps = ["Distributed", "Mmap", "Random", "Serialization"] uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" [[deps.SimpleNonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] -git-tree-sha1 = "470c5f97af31fa35926b45eb01e53a46c8d7d35f" +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "DiffResults", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] +git-tree-sha1 = "a535ae5083708f59e75d5bb3042c36d1be9bc778" uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" -version = "1.3.1" +version = "1.6.0" [deps.SimpleNonlinearSolve.extensions] + SimpleNonlinearSolveChainRulesCoreExt = "ChainRulesCore" SimpleNonlinearSolvePolyesterForwardDiffExt = "PolyesterForwardDiff" + SimpleNonlinearSolveReverseDiffExt = "ReverseDiff" SimpleNonlinearSolveStaticArraysExt = "StaticArrays" + SimpleNonlinearSolveTrackerExt = "Tracker" + SimpleNonlinearSolveZygoteExt = "Zygote" [deps.SimpleNonlinearSolve.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.SimpleTraits]] deps = ["InteractiveUtils", "MacroTools"] @@ -844,6 +885,11 @@ git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" version = "0.9.4" +[[deps.SimpleUnPack]] +git-tree-sha1 = "58e6353e72cde29b90a69527e56df1b5c3d8c437" +uuid = "ce78b400-467f-4804-87d8-8f486da07d0a" +version = "1.1.0" + [[deps.Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" @@ -854,18 +900,20 @@ version = "1.10.0" [[deps.SparseDiffTools]] deps = ["ADTypes", "Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "PackageExtensionCompat", "Random", "Reexport", "SciMLOperators", "Setfield", "SparseArrays", "StaticArrayInterface", "StaticArrays", "Tricks", "UnPack", "VertexSafeGraphs"] -git-tree-sha1 = "3b38ae7a1cbe9b8b1344359599753957644b03d4" +git-tree-sha1 = "a616ac46c38da60ac05cecf52064d44732edd05e" uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -version = "2.16.0" +version = "2.17.0" [deps.SparseDiffTools.extensions] SparseDiffToolsEnzymeExt = "Enzyme" + SparseDiffToolsPolyesterExt = "Polyester" SparseDiffToolsPolyesterForwardDiffExt = "PolyesterForwardDiff" SparseDiffToolsSymbolicsExt = "Symbolics" SparseDiffToolsZygoteExt = "Zygote" [deps.SparseDiffTools.weakdeps] Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" @@ -881,18 +929,16 @@ deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_j git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" version = "2.3.1" +weakdeps = ["ChainRulesCore"] [deps.SpecialFunctions.extensions] SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" - [deps.SpecialFunctions.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - [[deps.Static]] deps = ["IfElse"] -git-tree-sha1 = "f295e0a1da4ca425659c57441bcb59abb035a4bc" +git-tree-sha1 = "d2fdac9ff3906e27f7a618d47b676941baa6c80c" uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" -version = "0.8.8" +version = "0.8.10" [[deps.StaticArrayInterface]] deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "PrecompileTools", "Requires", "SparseArrays", "Static", "SuiteSparse"] @@ -907,18 +953,15 @@ weakdeps = ["OffsetArrays", "StaticArrays"] [[deps.StaticArrays]] deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] -git-tree-sha1 = "7b0e9c14c624e435076d19aea1e5cbdec2b9ca37" +git-tree-sha1 = "bf074c045d3d5ffd956fa0a461da38a44685d6b2" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.9.2" +version = "1.9.3" +weakdeps = ["ChainRulesCore", "Statistics"] [deps.StaticArrays.extensions] StaticArraysChainRulesCoreExt = "ChainRulesCore" StaticArraysStatisticsExt = "Statistics" - [deps.StaticArrays.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" - [[deps.StaticArraysCore]] git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" @@ -945,9 +988,10 @@ uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" version = "7.2.1+1" [[deps.SymbolicIndexingInterface]] -git-tree-sha1 = "b3103f4f50a3843e66297a2456921377c78f5e31" +deps = ["MacroTools", "RuntimeGeneratedFunctions"] +git-tree-sha1 = "f7b1fc9fc2bc938436b7684c243be7d317919056" uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" -version = "0.3.5" +version = "0.3.11" [[deps.TOML]] deps = ["Dates"] diff --git a/Project.toml b/Project.toml index 739a961f..20919913 100644 --- a/Project.toml +++ b/Project.toml @@ -15,6 +15,7 @@ ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" +OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" Preferences = "21216c6a-2e73-6563-6e65-726566657250" @@ -24,21 +25,17 @@ SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -Tricks = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" -TruncatedStacktraces = "781d530d-4396-4725-bb49-402e4bee1e77" UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" [weakdeps] ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" [extensions] BoundaryValueDiffEqODEInterfaceExt = "ODEInterface" -BoundaryValueDiffEqOrdinaryDiffEqExt = "OrdinaryDiffEq" [compat] ADTypes = "0.2" -Adapt = "3, 4" +Adapt = "4" Aqua = "0.8" ArrayInterface = "7" BandedMatrices = "1" @@ -58,32 +55,29 @@ PreallocationTools = "0.4" PrecompileTools = "1" Preferences = "1" Random = "1" -RecursiveArrayTools = "2.38.10, 3" -Reexport = "0.2, 1.0" -SafeTestsets = "0.1" +RecursiveArrayTools = "3" +Reexport = "1.0" SciMLBase = "2.12" Setfield = "1" SparseArrays = "1.9" SparseDiffTools = "2.9" StaticArrays = "1.8.1" Test = "1" -Tricks = "0.1" -TruncatedStacktraces = "1" UnPack = "1" julia = "1.10" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d" -LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" -SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["StaticArrays", "Random", "DiffEqDevTools", "OrdinaryDiffEq", "Test", "SafeTestsets", "ODEInterface", "Aqua", "LinearSolve", "RecursiveArrayTools", "JET"] +test = ["Aqua", "DiffEqDevTools", "JET", "LinearSolve", "ODEInterface", "OrdinaryDiffEq", "Random", "ReTestItems", "RecursiveArrayTools", "StaticArrays", "Test"] diff --git a/README.md b/README.md index 873ac7d9..5cef548d 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ To set these preferences before loading the package, do the following (replacing ```julia using Preferences, UUIDs -Preferences.set_preferences!(UUID("764a87c0-6b3e-53db-9096-fe964310641d"), - "PrecompileShooting" => false) +Preferences.set_preferences!( + UUID("764a87c0-6b3e-53db-9096-fe964310641d"), "PrecompileShooting" => false) ``` ## Running Benchmarks Locally diff --git a/benchmark/simple_pendulum.jl b/benchmark/simple_pendulum.jl index 8e9df3d0..ce09f1f0 100644 --- a/benchmark/simple_pendulum.jl +++ b/benchmark/simple_pendulum.jl @@ -44,42 +44,36 @@ function create_simple_pendulum_benchmark() if @isdefined(MultipleShooting) iip_suite["MultipleShooting(100, Tsit5; grid_coarsening = true)"] = @benchmarkable solve( - $SimplePendulumBenchmark.prob_iip, - $MultipleShooting(100, Tsit5())) + $SimplePendulumBenchmark.prob_iip, $MultipleShooting(100, Tsit5())) iip_suite["MultipleShooting(100, Tsit5; grid_coarsening = false)"] = @benchmarkable solve( $SimplePendulumBenchmark.prob_iip, $MultipleShooting(100, Tsit5(); grid_coarsening = false)) iip_suite["MultipleShooting(10, Tsit5; grid_coarsening = true)"] = @benchmarkable solve( - $SimplePendulumBenchmark.prob_iip, - $MultipleShooting(10, Tsit5())) + $SimplePendulumBenchmark.prob_iip, $MultipleShooting(10, Tsit5())) iip_suite["MultipleShooting(10, Tsit5; grid_coarsening = false)"] = @benchmarkable solve( $SimplePendulumBenchmark.prob_iip, $MultipleShooting(10, Tsit5(); grid_coarsening = false)) end if @isdefined(Shooting) iip_suite["Shooting(Tsit5())"] = @benchmarkable solve( - $SimplePendulumBenchmark.prob_iip, - $Shooting(Tsit5())) + $SimplePendulumBenchmark.prob_iip, $Shooting(Tsit5())) end if @isdefined(MultipleShooting) oop_suite["MultipleShooting(100, Tsit5; grid_coarsening = true)"] = @benchmarkable solve( - $SimplePendulumBenchmark.prob_oop, - $MultipleShooting(100, Tsit5())) + $SimplePendulumBenchmark.prob_oop, $MultipleShooting(100, Tsit5())) oop_suite["MultipleShooting(100, Tsit5; grid_coarsening = false)"] = @benchmarkable solve( $SimplePendulumBenchmark.prob_oop, $MultipleShooting(100, Tsit5(); grid_coarsening = false)) oop_suite["MultipleShooting(10, Tsit5; grid_coarsening = true)"] = @benchmarkable solve( - $SimplePendulumBenchmark.prob_oop, - $MultipleShooting(10, Tsit5())) + $SimplePendulumBenchmark.prob_oop, $MultipleShooting(10, Tsit5())) oop_suite["MultipleShooting(10, Tsit5; grid_coarsening = false)"] = @benchmarkable solve( $SimplePendulumBenchmark.prob_oop, $MultipleShooting(10, Tsit5(); grid_coarsening = false)) end if @isdefined(Shooting) oop_suite["Shooting(Tsit5())"] = @benchmarkable solve( - $SimplePendulumBenchmark.prob_oop, - $Shooting(Tsit5())) + $SimplePendulumBenchmark.prob_oop, $Shooting(Tsit5())) end return suite diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 5d0bf92b..95241775 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -1,15 +1,13 @@ module BoundaryValueDiffEqODEInterfaceExt using SciMLBase, BoundaryValueDiffEq, ODEInterface, RecursiveArrayTools -import BoundaryValueDiffEq: __extract_u0, __flatten_initial_guess, - __extract_mesh, __initial_guess_length, __initial_guess, - __has_initial_guess +import BoundaryValueDiffEq: __extract_u0, __flatten_initial_guess, __extract_mesh, + __initial_guess_length, __initial_guess, __has_initial_guess import SciMLBase: __solve import ODEInterface: OptionsODE, OPT_ATOL, OPT_RTOL, OPT_METHODCHOICE, OPT_DIAGNOSTICOUTPUT, OPT_ERRORCONTROL, OPT_SINGULARTERM, OPT_MAXSTEPS, OPT_BVPCLASS, - OPT_SOLMETHOD, - OPT_RHS_CALLMODE, OPT_COLLOCATIONPTS, OPT_MAXSUBINTERVALS, - RHS_CALL_INSITU, evalSolution + OPT_SOLMETHOD, OPT_RHS_CALLMODE, OPT_COLLOCATIONPTS, + OPT_MAXSUBINTERVALS, RHS_CALL_INSITU, evalSolution import ODEInterface: Bvpm2, bvpm2_init, bvpm2_solve, bvpm2_destroy, bvpm2_get_x import ODEInterface: bvpsol import ODEInterface: colnew @@ -56,12 +54,12 @@ function __solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs... obj = Bvpm2() if prob.u0 isa Function guess_function = @closure (x, y) -> (y .= vec(__initial_guess(prob.u0, prob.p, x))) - bvpm2_init(obj, no_odes, no_left_bc, mesh, guess_function, eltype(u0_)[], - alg.max_num_subintervals, prob.u0) + bvpm2_init(obj, no_odes, no_left_bc, mesh, guess_function, + eltype(u0_)[], alg.max_num_subintervals, prob.u0) else u0 = __flatten_initial_guess(prob.u0) - bvpm2_init(obj, no_odes, no_left_bc, mesh, u0, eltype(u0)[], - alg.max_num_subintervals) + bvpm2_init( + obj, no_odes, no_left_bc, mesh, u0, eltype(u0)[], alg.max_num_subintervals) end bvp2m_f = if isinplace(prob) @@ -107,8 +105,8 @@ end #------- # BVPSOL #------- -function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, dt = 0.0, - verbose = true, kwargs...) +function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, + reltol = 1e-3, dt = 0.0, verbose = true, kwargs...) if !(prob.problem_type isa TwoPointBVProblem) throw(ArgumentError("`BVPSOL` only supports `TwoPointBVProblem!`")) end @@ -138,9 +136,9 @@ function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, d no_left_bc = length(left_bc) end - opt = OptionsODE(OPT_RTOL => reltol, OPT_MAXSTEPS => maxiters, - OPT_BVPCLASS => alg.bvpclass, OPT_SOLMETHOD => alg.sol_method, - OPT_RHS_CALLMODE => RHS_CALL_INSITU) + opt = OptionsODE( + OPT_RTOL => reltol, OPT_MAXSTEPS => maxiters, OPT_BVPCLASS => alg.bvpclass, + OPT_SOLMETHOD => alg.sol_method, OPT_RHS_CALLMODE => RHS_CALL_INSITU) bvpsol_f = if isinplace(prob) @closure (t, u, du) -> prob.f(reshape(du, u0_size), reshape(u, u0_size), prob.p, t) diff --git a/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl b/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl deleted file mode 100644 index 9f4b3f49..00000000 --- a/ext/BoundaryValueDiffEqOrdinaryDiffEqExt.jl +++ /dev/null @@ -1,158 +0,0 @@ -module BoundaryValueDiffEqOrdinaryDiffEqExt - -# This extension doesn't add any new feature atm but is used to precompile some common -# shooting workflows - -# We can't use @load_preference since this is a different module -import Preferences: load_preference -import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidations - -@recompile_invalidations begin - using BoundaryValueDiffEq, OrdinaryDiffEq -end - -@setup_workload begin - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = 0 - end - f1(u, p, t) = [u[2], 0] - - function bc1!(residual, u, p, t) - residual[1] = u(0.0)[1] - 5 - residual[2] = u(5.0)[1] - end - bc1(u, p, t) = [u(0.0)[1] - 5, u(5.0)[1]] - - bc1_a!(residual, ua, p) = (residual[1] = ua[1] - 5) - bc1_b!(residual, ub, p) = (residual[1] = ub[1]) - - bc1_a(ua, p) = [ua[1] - 5] - bc1_b(ub, p) = [ub[1]] - - tspan = (0.0, 5.0) - u0 = [5.0, -3.5] - bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) - - probs = [ - BVProblem(BVPFunction{true}(f1!, bc1!), u0, tspan; nlls = Val(false)), - BVProblem(BVPFunction{false}(f1, bc1), u0, tspan; nlls = Val(false)), - BVProblem( - BVPFunction{true}(f1!, (bc1_a!, bc1_b!); bcresid_prototype, - twopoint = Val(true)), - u0, - tspan; - nlls = Val(false)), - BVProblem( - BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, - twopoint = Val(true)), - u0, tspan; nlls = Val(false)) - ] - - algs = [] - - if load_preference(BoundaryValueDiffEq, "PrecompileShooting", true) - push!(algs, - Shooting(Tsit5(); nlsolve = NewtonRaphson(), - jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))) - end - - if load_preference(BoundaryValueDiffEq, "PrecompileMultipleShooting", true) - push!(algs, - MultipleShooting(10, Tsit5(); nlsolve = NewtonRaphson(), - jac_alg = BVPJacobianAlgorithm(; - bc_diffmode = AutoForwardDiff(; chunksize = 2), - nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))) - end - - @compile_workload begin - for prob in probs, alg in algs - solve(prob, alg) - end - end - - function f1_nlls!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - end - - f1_nlls(u, p, t) = [u[2], -u[1]] - - function bc1_nlls!(resid, sol, p, t) - solₜ₁ = sol(0.0) - solₜ₂ = sol(100.0) - resid[1] = solₜ₁[1] - resid[2] = solₜ₂[1] - 1 - resid[3] = solₜ₂[2] + 1.729109 - return nothing - end - bc1_nlls(sol, p, t) = [sol(0.0)[1], sol(100.0)[1] - 1, sol(1.0)[2] + 1.729109] - - bc1_nlls_a!(resid, ua, p) = (resid[1] = ua[1]) - bc1_nlls_b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - - bc1_nlls_a(ua, p) = [ua[1]] - bc1_nlls_b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] - bcresid_prototype1 = Array{Float64}(undef, 3) - bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) - - probs = [ - BVProblem( - BVPFunction{true}(f1_nlls!, bc1_nlls!; - bcresid_prototype = bcresid_prototype1), - u0, tspan; nlls = Val(true)), - BVProblem( - BVPFunction{false}(f1_nlls, bc1_nlls; - bcresid_prototype = bcresid_prototype1), - u0, tspan; nlls = Val(true)), - BVProblem( - BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); - bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), - u0, - tspan; - nlls = Val(true)), - BVProblem( - BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); - bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), - u0, - tspan; - nlls = Val(true)) - ] - - algs = [] - - if load_preference(BoundaryValueDiffEq, "PrecompileShootingNLLS", true) - append!(algs, - [ - Shooting(Tsit5(); nlsolve = TrustRegion(), - jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), - Shooting(Tsit5(); nlsolve = GaussNewton(), - jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))) - ]) - end - - if load_preference(BoundaryValueDiffEq, "PrecompileMultipleShootingNLLS", true) - append!(algs, - [ - MultipleShooting(10, Tsit5(); nlsolve = TrustRegion(), - jac_alg = BVPJacobianAlgorithm(; - bc_diffmode = AutoForwardDiff(; chunksize = 2), - nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5(); nlsolve = GaussNewton(), - jac_alg = BVPJacobianAlgorithm(; - bc_diffmode = AutoForwardDiff(; chunksize = 2), - nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))) - ]) - end - - @compile_workload begin - for prob in probs, alg in algs - solve(prob, alg) - end - end -end - -end diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index fadc9b49..e445252d 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -4,16 +4,15 @@ import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidat @recompile_invalidations begin using ADTypes, Adapt, DiffEqBase, ForwardDiff, LinearAlgebra, NonlinearSolve, - PreallocationTools, Preferences, RecursiveArrayTools, Reexport, SciMLBase, - Setfield, - SparseDiffTools, Tricks + OrdinaryDiffEq, PreallocationTools, Preferences, RecursiveArrayTools, Reexport, + SciMLBase, Setfield, SparseDiffTools # Special Matrix Types using BandedMatrices, FastAlmostBandedMatrices, SparseArrays import ADTypes: AbstractADType - import ArrayInterface: matrix_colors, - parameterless_type, undefmatrix, fast_scalar_indexing + import ArrayInterface: matrix_colors, parameterless_type, undefmatrix, + fast_scalar_indexing import ConcreteStructs: @concrete import DiffEqBase: solve import FastClosures: @closure @@ -21,11 +20,11 @@ import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidat import RecursiveArrayTools: ArrayPartition, DiffEqArray import SciMLBase: AbstractDiffEqInterpolation, StandardBVProblem, __solve, _unwrap_val import SparseDiffTools: AbstractSparseADType - import TruncatedStacktraces: @truncate_stacktrace import UnPack: @unpack end -@reexport using ADTypes, DiffEqBase, NonlinearSolve, SparseDiffTools, SciMLBase +@reexport using ADTypes, DiffEqBase, NonlinearSolve, OrdinaryDiffEq, SparseDiffTools, + SciMLBase include("types.jl") include("utils.jl") @@ -50,118 +49,252 @@ function __solve(prob::BVProblem, alg::BoundaryValueDiffEqAlgorithm, args...; kw end @setup_workload begin - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = 0 - end - f1(u, p, t) = [u[2], 0] - - function bc1!(residual, u, p, t) - residual[1] = u[1][1] - 5 - residual[2] = u[end][1] - end - bc1(u, p, t) = [u[1][1] - 5, u[end][1]] - - bc1_a!(residual, ua, p) = (residual[1] = ua[1] - 5) - bc1_b!(residual, ub, p) = (residual[1] = ub[1]) - - bc1_a(ua, p) = [ua[1] - 5] - bc1_b(ub, p) = [ub[1]] - - tspan = (0.0, 5.0) - u0 = [5.0, -3.5] - bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) - - probs = [ - BVProblem(f1!, bc1!, u0, tspan), - BVProblem(f1, bc1, u0, tspan), - TwoPointBVProblem(f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype), - TwoPointBVProblem(f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype) - ] - - algs = [] - - jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) - - if Preferences.@load_preference("PrecompileMIRK", true) - append!(algs, - [MIRK2(; jac_alg), MIRK3(; jac_alg), MIRK4(; jac_alg), - MIRK5(; jac_alg), MIRK6(; jac_alg)]) - end - - @compile_workload begin - for prob in probs, alg in algs - solve(prob, alg; dt = 0.2) - end - end - - function f1_nlls!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - end - - f1_nlls(u, p, t) = [u[2], -u[1]] - - function bc1_nlls!(resid, sol, p, t) - solₜ₁ = sol[1] - solₜ₂ = sol[end] - resid[1] = solₜ₁[1] - resid[2] = solₜ₂[1] - 1 - resid[3] = solₜ₂[2] + 1.729109 - return nothing - end - bc1_nlls(sol, p, t) = [sol[1][1], sol[end][1] - 1, sol[end][2] + 1.729109] - - bc1_nlls_a!(resid, ua, p) = (resid[1] = ua[1]) - bc1_nlls_b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - - bc1_nlls_a(ua, p) = [ua[1]] - bc1_nlls_b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] - bcresid_prototype1 = Array{Float64}(undef, 3) - bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) - - probs = [ - BVProblem(BVPFunction(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), - u0, tspan), - BVProblem(BVPFunction(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), - u0, tspan), - TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, tspan; - bcresid_prototype = bcresid_prototype2), - TwoPointBVProblem(f1_nlls, (bc1_nlls_a, bc1_nlls_b), u0, tspan; - bcresid_prototype = bcresid_prototype2) - ] - - jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) - - nlsolvers = [LevenbergMarquardt(), GaussNewton()] - - algs = [] - - if Preferences.@load_preference("PrecompileMIRKNLLS", false) - for nlsolve in nlsolvers - append!(algs, - [ - MIRK2(; jac_alg, nlsolve), MIRK3(; jac_alg, nlsolve), - MIRK4(; jac_alg, nlsolve), MIRK5(; jac_alg, nlsolve), - MIRK6(; jac_alg, nlsolve) - ]) - end - end - - @compile_workload begin - for prob in probs, alg in algs - solve(prob, alg; dt = 0.2) - end - end + # function f1!(du, u, p, t) + # du[1] = u[2] + # du[2] = 0 + # end + # f1(u, p, t) = [u[2], 0] + + # function bc1!(residual, u, p, t) + # residual[1] = u[1][1] - 5 + # residual[2] = u[end][1] + # end + # bc1(u, p, t) = [u[1][1] - 5, u[end][1]] + + # bc1_a!(residual, ua, p) = (residual[1] = ua[1] - 5) + # bc1_b!(residual, ub, p) = (residual[1] = ub[1]) + + # bc1_a(ua, p) = [ua[1] - 5] + # bc1_b(ub, p) = [ub[1]] + + # tspan = (0.0, 5.0) + # u0 = [5.0, -3.5] + # bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) + + # probs = [BVProblem(f1!, bc1!, u0, tspan), BVProblem(f1, bc1, u0, tspan), + # TwoPointBVProblem(f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype), + # TwoPointBVProblem(f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype)] + + # algs = [] + + # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) + + # if Preferences.@load_preference("PrecompileMIRK", true) + # append!(algs, + # [MIRK2(; jac_alg), MIRK3(; jac_alg), MIRK4(; jac_alg), + # MIRK5(; jac_alg), MIRK6(; jac_alg)]) + # end + + # @compile_workload begin + # for prob in probs, alg in algs + # solve(prob, alg; dt = 0.2) + # end + # end + + # function f1_nlls!(du, u, p, t) + # du[1] = u[2] + # du[2] = -u[1] + # end + + # f1_nlls(u, p, t) = [u[2], -u[1]] + + # function bc1_nlls!(resid, sol, p, t) + # solₜ₁ = sol[1] + # solₜ₂ = sol[end] + # resid[1] = solₜ₁[1] + # resid[2] = solₜ₂[1] - 1 + # resid[3] = solₜ₂[2] + 1.729109 + # return nothing + # end + # bc1_nlls(sol, p, t) = [sol[1][1], sol[end][1] - 1, sol[end][2] + 1.729109] + + # bc1_nlls_a!(resid, ua, p) = (resid[1] = ua[1]) + # bc1_nlls_b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) + + # bc1_nlls_a(ua, p) = [ua[1]] + # bc1_nlls_b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] + + # tspan = (0.0, 100.0) + # u0 = [0.0, 1.0] + # bcresid_prototype1 = Array{Float64}(undef, 3) + # bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) + + # probs = [ + # BVProblem(BVPFunction(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), + # u0, tspan), + # BVProblem(BVPFunction(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), + # u0, tspan), + # TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, + # tspan; bcresid_prototype = bcresid_prototype2), + # TwoPointBVProblem(f1_nlls, (bc1_nlls_a, bc1_nlls_b), u0, tspan; + # bcresid_prototype = bcresid_prototype2)] + + # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) + + # nlsolvers = [LevenbergMarquardt(), GaussNewton()] + + # algs = [] + + # if Preferences.@load_preference("PrecompileMIRKNLLS", false) + # for nlsolve in nlsolvers + # append!(algs, + # [MIRK2(; jac_alg, nlsolve), MIRK3(; jac_alg, nlsolve), + # MIRK4(; jac_alg, nlsolve), MIRK5(; jac_alg, nlsolve), + # MIRK6(; jac_alg, nlsolve)]) + # end + # end + + # @compile_workload begin + # for prob in probs, alg in algs + # solve(prob, alg; dt = 0.2) + # end + # end + + # function f1!(du, u, p, t) + # du[1] = u[2] + # du[2] = 0 + # end + # f1(u, p, t) = [u[2], 0] + + # function bc1!(residual, u, p, t) + # residual[1] = u(0.0)[1] - 5 + # residual[2] = u(5.0)[1] + # end + # bc1(u, p, t) = [u(0.0)[1] - 5, u(5.0)[1]] + + # bc1_a!(residual, ua, p) = (residual[1] = ua[1] - 5) + # bc1_b!(residual, ub, p) = (residual[1] = ub[1]) + + # bc1_a(ua, p) = [ua[1] - 5] + # bc1_b(ub, p) = [ub[1]] + + # tspan = (0.0, 5.0) + # u0 = [5.0, -3.5] + # bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) + + # probs = [BVProblem(BVPFunction{true}(f1!, bc1!), u0, tspan; nlls = Val(false)), + # BVProblem(BVPFunction{false}(f1, bc1), u0, tspan; nlls = Val(false)), + # BVProblem( + # BVPFunction{true}( + # f1!, (bc1_a!, bc1_b!); bcresid_prototype, twopoint = Val(true)), + # u0, + # tspan; + # nlls = Val(false)), + # BVProblem( + # BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, twopoint = Val(true)), + # u0, tspan; nlls = Val(false))] + + # algs = [] + + # if @load_preference("PrecompileShooting", true) + # push!(algs, + # Shooting(Tsit5(); nlsolve = NewtonRaphson(), + # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))) + # end + + # if @load_preference("PrecompileMultipleShooting", true) + # push!(algs, + # MultipleShooting(10, + # Tsit5(); + # nlsolve = NewtonRaphson(), + # jac_alg = BVPJacobianAlgorithm(; + # bc_diffmode = AutoForwardDiff(; chunksize = 2), + # nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))) + # end + + # @compile_workload begin + # for prob in probs, alg in algs + # solve(prob, alg) + # end + # end + + # function f1_nlls!(du, u, p, t) + # du[1] = u[2] + # du[2] = -u[1] + # end + + # f1_nlls(u, p, t) = [u[2], -u[1]] + + # function bc1_nlls!(resid, sol, p, t) + # solₜ₁ = sol(0.0) + # solₜ₂ = sol(100.0) + # resid[1] = solₜ₁[1] + # resid[2] = solₜ₂[1] - 1 + # resid[3] = solₜ₂[2] + 1.729109 + # return nothing + # end + # bc1_nlls(sol, p, t) = [sol(0.0)[1], sol(100.0)[1] - 1, sol(1.0)[2] + 1.729109] + + # bc1_nlls_a!(resid, ua, p) = (resid[1] = ua[1]) + # bc1_nlls_b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) + + # bc1_nlls_a(ua, p) = [ua[1]] + # bc1_nlls_b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] + + # tspan = (0.0, 100.0) + # u0 = [0.0, 1.0] + # bcresid_prototype1 = Array{Float64}(undef, 3) + # bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) + + # probs = [ + # BVProblem( + # BVPFunction{true}(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), + # u0, tspan; nlls = Val(true)), + # BVProblem( + # BVPFunction{false}(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), + # u0, tspan; nlls = Val(true)), + # BVProblem( + # BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); + # bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), + # u0, + # tspan; + # nlls = Val(true)), + # BVProblem( + # BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); + # bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), + # u0, + # tspan; + # nlls = Val(true))] + + # algs = [] + + # if @load_preference("PrecompileShootingNLLS", true) + # append!(algs, + # [ + # Shooting(Tsit5(); nlsolve = TrustRegion(), + # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), + # Shooting(Tsit5(); nlsolve = GaussNewton(), + # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))]) + # end + + # if @load_preference("PrecompileMultipleShootingNLLS", true) + # append!(algs, + # [ + # MultipleShooting(10, + # Tsit5(); + # nlsolve = TrustRegion(), + # jac_alg = BVPJacobianAlgorithm(; + # bc_diffmode = AutoForwardDiff(; chunksize = 2), + # nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))), + # MultipleShooting(10, + # Tsit5(); + # nlsolve = GaussNewton(), + # jac_alg = BVPJacobianAlgorithm(; + # bc_diffmode = AutoForwardDiff(; chunksize = 2), + # nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))]) + # end + + # @compile_workload begin + # for prob in probs, alg in algs + # solve(prob, alg) + # end + # end end export Shooting, MultipleShooting export MIRK2, MIRK3, MIRK4, MIRK5, MIRK6 +export BVPM2, BVPSOL, COLNEW # From ODEInterface.jl + export MIRKJacobianComputationAlgorithm, BVPJacobianAlgorithm -# From ODEInterface.jl -export BVPM2, BVPSOL, COLNEW end diff --git a/src/adaptivity.jl b/src/adaptivity.jl index d2d08a2a..761fc176 100644 --- a/src/adaptivity.jl +++ b/src/adaptivity.jl @@ -83,8 +83,8 @@ end Generate a new mesh based on the `ŝ`. """ -function redistribute!(cache::MIRKCache{iip, T}, Nsub_star, ŝ, mesh, - mesh_dt) where {iip, T} +function redistribute!( + cache::MIRKCache{iip, T}, Nsub_star, ŝ, mesh, mesh_dt) where {iip, T} N = length(mesh) ζ = sum(ŝ .* mesh_dt) / Nsub_star k, i = 1, 0 @@ -201,8 +201,8 @@ Here, the ki_interp is the stages in one subinterval. end if r > 1 for j in eachindex(k_interp) - __maybe_matmul!(new_stages[j], k_interp[j][:, 1:(r - 1)], x_star[idx₂], - T(1), T(1)) + __maybe_matmul!( + new_stages[j], k_interp[j][:, 1:(r - 1)], x_star[idx₂], T(1), T(1)) end end for i in eachindex(new_stages) @@ -235,8 +235,8 @@ function sum_stages!(z::AbstractArray, cache::MIRKCache, w, i::Int, dt = cache.m z .= zero(z) __maybe_matmul!(z, k_discrete[i].du[:, 1:stage], w[1:stage]) - __maybe_matmul!(z, k_interp[i][:, 1:(s_star - stage)], - w[(stage + 1):s_star], true, true) + __maybe_matmul!( + z, k_interp[i][:, 1:(s_star - stage)], w[(stage + 1):s_star], true, true) z .= z .* dt .+ cache.y₀[i] return z @@ -248,12 +248,12 @@ end z .= zero(z) __maybe_matmul!(z, k_discrete[i].du[:, 1:stage], w[1:stage]) - __maybe_matmul!(z, k_interp[i][:, 1:(s_star - stage)], - w[(stage + 1):s_star], true, true) + __maybe_matmul!( + z, k_interp[i][:, 1:(s_star - stage)], w[(stage + 1):s_star], true, true) z′ .= zero(z′) __maybe_matmul!(z′, k_discrete[i].du[:, 1:stage], w′[1:stage]) - __maybe_matmul!(z′, k_interp[i][:, 1:(s_star - stage)], - w′[(stage + 1):s_star], true, true) + __maybe_matmul!( + z′, k_interp[i][:, 1:(s_star - stage)], w′[(stage + 1):s_star], true, true) z .= z .* dt[1] .+ cache.y₀[i] return z, z′ @@ -278,14 +278,12 @@ for order in (2, 3, 4, 5, 6) wp = [0, 1 - τ, τ] elseif $(order == 3) w = [τ / 4.0 * (2.0 * τ^2 - 5.0 * τ + 4.0), - -3.0 / 4.0 * τ^2 * (2.0 * τ - 3.0), - τ^2 * (τ - 1.0)] + -3.0 / 4.0 * τ^2 * (2.0 * τ - 3.0), τ^2 * (τ - 1.0)] # Derivative polynomials. wp = [3.0 / 2.0 * (τ - 2.0 / 3.0) * (τ - 1.0), - -9.0 / 2.0 * τ * (τ - 1.0), - 3.0 * τ * (τ - 2.0 / 3.0)] + -9.0 / 2.0 * τ * (τ - 1.0), 3.0 * τ * (τ - 2.0 / 3.0)] elseif $(order == 4) t2 = τ * τ tm1 = τ - 1.0 @@ -299,48 +297,37 @@ for order in (2, 3, 4, 5, 6) # Derivative polynomials - wp = [-tm1 * t4m3 * t2m1 / 3.0, - τ * t2m1 * t4m3, - 4.0 * τ * t4m3 * tm1, - -32.0 * τ * t2m1 * tm1 / 3.0] + wp = [-tm1 * t4m3 * t2m1 / 3.0, τ * t2m1 * t4m3, + 4.0 * τ * t4m3 * tm1, -32.0 * τ * t2m1 * tm1 / 3.0] elseif $(order == 5) w = [ τ * (22464.0 - 83910.0 * τ + 143041.0 * τ^2 - 113808.0 * τ^3 + 33256.0 * τ^4) / 22464.0, - τ^2 * (-2418.0 + 12303.0 * τ - 19512.0 * τ^2 + 10904.0 * τ^3) / - 3360.0, + τ^2 * (-2418.0 + 12303.0 * τ - 19512.0 * τ^2 + 10904.0 * τ^3) / 3360.0, -8 / 81 * τ^2 * (-78.0 + 209.0 * τ - 204.0 * τ^2 + 8.0 * τ^3), - -25 / 1134 * τ^2 * - (-390.0 + 1045.0 * τ - 1020.0 * τ^2 + 328.0 * τ^3), - -25 / 5184 * τ^2 * - (390.0 + 255.0 * τ - 1680.0 * τ^2 + 2072.0 * τ^3), - 279841 / 168480 * τ^2 * - (-6.0 + 21.0 * τ - 24.0 * τ^2 + 8.0 * τ^3)] + -25 / 1134 * τ^2 * (-390.0 + 1045.0 * τ - 1020.0 * τ^2 + 328.0 * τ^3), + -25 / 5184 * τ^2 * (390.0 + 255.0 * τ - 1680.0 * τ^2 + 2072.0 * τ^3), + 279841 / 168480 * τ^2 * (-6.0 + 21.0 * τ - 24.0 * τ^2 + 8.0 * τ^3)] # Derivative polynomials wp = [ - 1.0 - 13985 // 1872 * τ + 143041 // 7488 * τ^2 - - 2371 // 117 * τ^3 + + 1.0 - 13985 // 1872 * τ + 143041 // 7488 * τ^2 - 2371 // 117 * τ^3 + 20785 // 2808 * τ^4, -403 // 280 * τ + 12303 // 1120 * τ^2 - 813 // 35 * τ^3 + 1363 // 84 * τ^4, - 416 // 27 * τ - 1672 // 27 * τ^2 + 2176 // 27 * τ^3 - - 320 // 81 * τ^4, + 416 // 27 * τ - 1672 // 27 * τ^2 + 2176 // 27 * τ^3 - 320 // 81 * τ^4, 3250 // 189 * τ - 26125 // 378 * τ^2 + 17000 // 189 * τ^3 - 20500 // 567 * τ^4, -1625 // 432 * τ - 2125 // 576 * τ^2 + 875 // 27 * τ^3 - 32375 // 648 * τ^4, - -279841 // 14040 * τ + 1958887 // 18720 * τ^2 - - 279841 // 1755 * τ^3 + + -279841 // 14040 * τ + 1958887 // 18720 * τ^2 - 279841 // 1755 * τ^3 + 279841 // 4212 * τ^4] elseif $(order == 6) w = [ τ - 28607 // 7434 * τ^2 - 166210 // 33453 * τ^3 + - 334780 // 11151 * τ^4 - - 1911296 // 55755 * τ^5 + 406528 // 33453 * τ^6, - 777 // 590 * τ^2 - 2534158 // 234171 * τ^3 + - 2088580 // 78057 * τ^4 - + 334780 // 11151 * τ^4 - 1911296 // 55755 * τ^5 + 406528 // 33453 * τ^6, + 777 // 590 * τ^2 - 2534158 // 234171 * τ^3 + 2088580 // 78057 * τ^4 - 10479104 // 390285 * τ^5 + 11328512 // 1170855 * τ^6, -1008 // 59 * τ^2 + 222176 // 1593 * τ^3 - 180032 // 531 * τ^4 + 876544 // 2655 * τ^5 - 180224 // 1593 * τ^6, @@ -349,22 +336,20 @@ for order in (2, 3, 4, 5, 6) -378 // 59 * τ^2 + 27772 // 531 * τ^3 - 22504 // 177 * τ^4 + 109568 // 885 * τ^5 - 22528 // 531 * τ^6, -95232 // 413 * τ^2 + 62384128 // 33453 * τ^3 - - 49429504 // 11151 * τ^4 + - 46759936 // 11151 * τ^5 - 46661632 // 33453 * τ^6, - 896 // 5 * τ^2 - 4352 // 3 * τ^3 + 3456 * τ^4 - - 16384 // 5 * τ^5 + + 49429504 // 11151 * τ^4 + 46759936 // 11151 * τ^5 - + 46661632 // 33453 * τ^6, + 896 // 5 * τ^2 - 4352 // 3 * τ^3 + 3456 * τ^4 - 16384 // 5 * τ^5 + 16384 // 15 * τ^6, 50176 // 531 * τ^2 - 179554304 // 234171 * τ^3 + - 143363072 // 78057 * τ^4 - - 136675328 // 78057 * τ^5 + 137363456 // 234171 * τ^6, + 143363072 // 78057 * τ^4 - 136675328 // 78057 * τ^5 + + 137363456 // 234171 * τ^6, 16384 // 441 * τ^3 - 16384 // 147 * τ^4 + 16384 // 147 * τ^5 - 16384 // 441 * τ^6] # Derivative polynomials. wp = [ - 1 - 28607 // 3717 * τ - 166210 // 11151 * τ^2 + - 1339120 // 11151 * τ^3 - + 1 - 28607 // 3717 * τ - 166210 // 11151 * τ^2 + 1339120 // 11151 * τ^3 - 1911296 // 11151 * τ^4 + 813056 // 11151 * τ^5, 777 // 295 * τ - 2534158 // 78057 * τ^2 + 8354320 // 78057 * τ^3 - 10479104 // 78057 * τ^4 + 22657024 // 390285 * τ^5, @@ -375,13 +360,13 @@ for order in (2, 3, 4, 5, 6) -756 // 59 * τ + 27772 // 177 * τ^2 - 90016 // 177 * τ^3 + 109568 // 177 * τ^4 - 45056 // 177 * τ^5, -190464 // 413 * τ + 62384128 // 11151 * τ^2 - - 197718016 // 11151 * τ^3 + - 233799680 // 11151 * τ^4 - 93323264 // 11151 * τ^5, + 197718016 // 11151 * τ^3 + 233799680 // 11151 * τ^4 - + 93323264 // 11151 * τ^5, 1792 // 5 * τ - 4352 * τ^2 + 13824 * τ^3 - 16384 * τ^4 + 32768 // 5 * τ^5, 100352 // 531 * τ - 179554304 // 78057 * τ^2 + - 573452288 // 78057 * τ^3 - - 683376640 // 78057 * τ^4 + 274726912 // 78057 * τ^5, + 573452288 // 78057 * τ^3 - 683376640 // 78057 * τ^4 + + 274726912 // 78057 * τ^5, 16384 // 147 * τ^2 - 65536 // 147 * τ^3 + 81920 // 147 * τ^4 - 32768 // 147 * τ^5] end diff --git a/src/algorithms.jl b/src/algorithms.jl index 4d7250a5..42de4594 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -59,6 +59,7 @@ end (return @set alg.jac_alg.diffmode = __default_nonsparse_ad(prob.u0)) return alg end + """ MultipleShooting(; nshoots::Int, ode_alg = nothing, nlsolve = nothing, grid_coarsening = true, jac_alg = nothing) @@ -110,25 +111,29 @@ end function concretize_jacobian_algorithm(alg::MultipleShooting, prob) jac_alg = concrete_jacobian_algorithm(alg.jac_alg, prob, alg) - return MultipleShooting(alg.ode_alg, alg.nlsolve, jac_alg, alg.nshoots, - alg.grid_coarsening) + return MultipleShooting( + alg.ode_alg, alg.nlsolve, jac_alg, alg.nshoots, alg.grid_coarsening) end function update_nshoots(alg::MultipleShooting, nshoots::Int) - return MultipleShooting(alg.ode_alg, alg.nlsolve, alg.jac_alg, nshoots, - alg.grid_coarsening) + return MultipleShooting( + alg.ode_alg, alg.nlsolve, alg.jac_alg, nshoots, alg.grid_coarsening) end -function MultipleShooting(; nshoots::Int, ode_alg = nothing, nlsolve = nothing, - grid_coarsening::Union{Bool, Function, <:AbstractVector{<:Integer}, - Tuple{Vararg{Integer}}} = true, jac_alg = nothing) +function MultipleShooting(; nshoots::Int, + ode_alg = nothing, + nlsolve = nothing, + grid_coarsening::Union{ + Bool, Function, <:AbstractVector{<:Integer}, Tuple{Vararg{Integer}}} = true, + jac_alg = nothing) grid_coarsening isa Tuple && (grid_coarsening = Vector(grid_coarsening...)) if grid_coarsening isa AbstractVector sort!(grid_coarsening; rev = true) @assert all(grid_coarsening .> 0) && 1 ∉ grid_coarsening end - return MultipleShooting(ode_alg, nlsolve, - __materialize_jacobian_algorithm(nlsolve, jac_alg), nshoots, grid_coarsening) + return MultipleShooting( + ode_alg, nlsolve, __materialize_jacobian_algorithm(nlsolve, jac_alg), + nshoots, grid_coarsening) end @inline MultipleShooting(nshoots::Int; kwargs...) = MultipleShooting(; nshoots, kwargs...) @inline MultipleShooting(nshoots::Int, ode_alg; kwargs...) = MultipleShooting(; @@ -233,8 +238,8 @@ end function BVPM2(; max_num_subintervals::Int = 3000, method_choice::Int = 4, diagnostic_output::Int = -1, error_control::Int = 1, singular_term = nothing) - return BVPM2(max_num_subintervals, method_choice, diagnostic_output, error_control, - singular_term) + return BVPM2(max_num_subintervals, method_choice, + diagnostic_output, error_control, singular_term) end """ @@ -322,8 +327,8 @@ struct COLNEW <: BoundaryValueDiffEqAlgorithm diagnostic_output::Int = 1, max_num_subintervals::Int = 3000) return COLNEW(bvpclass, collocationpts, diagnostic_output, max_num_subintervals) end - function COLNEW(bvpclass::Int, collocationpts::Int, diagnostic_output::Int, - max_num_subintervals::Int) + function COLNEW(bvpclass::Int, collocationpts::Int, + diagnostic_output::Int, max_num_subintervals::Int) if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing error("COLNEW requires ODEInterface.jl to be loaded") end diff --git a/src/collocation.jl b/src/collocation.jl index 879a9b38..27406a48 100644 --- a/src/collocation.jl +++ b/src/collocation.jl @@ -1,10 +1,10 @@ function Φ!(residual, cache::MIRKCache, y, u, p = cache.p) - return Φ!(residual, cache.fᵢ_cache, cache.k_discrete, cache.f, cache.TU, - y, u, p, cache.mesh, cache.mesh_dt, cache.stage) + return Φ!(residual, cache.fᵢ_cache, cache.k_discrete, cache.f, + cache.TU, y, u, p, cache.mesh, cache.mesh_dt, cache.stage) end -@views function Φ!(residual, fᵢ_cache, k_discrete, f!, TU::MIRKTableau, y, u, p, - mesh, mesh_dt, stage::Int) +@views function Φ!(residual, fᵢ_cache, k_discrete, f!, TU::MIRKTableau, + y, u, p, mesh, mesh_dt, stage::Int) @unpack c, v, x, b = TU tmp = get_tmp(fᵢ_cache, u) @@ -30,12 +30,12 @@ end end function Φ(cache::MIRKCache, y, u, p = cache.p) - return Φ(cache.fᵢ_cache, cache.k_discrete, cache.f, cache.TU, y, u, p, cache.mesh, - cache.mesh_dt, cache.stage) + return Φ(cache.fᵢ_cache, cache.k_discrete, cache.f, cache.TU, + y, u, p, cache.mesh, cache.mesh_dt, cache.stage) end -@views function Φ(fᵢ_cache, k_discrete, f, TU::MIRKTableau, y, u, p, mesh, mesh_dt, - stage::Int) +@views function Φ( + fᵢ_cache, k_discrete, f, TU::MIRKTableau, y, u, p, mesh, mesh_dt, stage::Int) @unpack c, v, x, b = TU residuals = [similar(yᵢ) for yᵢ in y[1:(end - 1)]] tmp = get_tmp(fᵢ_cache, u) diff --git a/src/interpolation.jl b/src/interpolation.jl index 49e284db..eb9b6794 100644 --- a/src/interpolation.jl +++ b/src/interpolation.jl @@ -18,8 +18,8 @@ end # FIXME: Fix the interpolation outside the tspan -@inline function interpolation(tvals, id::I, idxs, deriv::D, p, - continuity::Symbol = :left) where {I, D} +@inline function interpolation( + tvals, id::I, idxs, deriv::D, p, continuity::Symbol = :left) where {I, D} @unpack t, u, cache = id tdir = sign(t[end] - t[1]) idx = sortperm(tvals, rev = tdir < 0) @@ -40,8 +40,8 @@ end return DiffEqArray(vals, tvals) end -@inline function interpolation!(vals, tvals, id::I, idxs, deriv::D, p, - continuity::Symbol = :left) where {I, D} +@inline function interpolation!( + vals, tvals, id::I, idxs, deriv::D, p, continuity::Symbol = :left) where {I, D} @unpack t, cache = id tdir = sign(t[end] - t[1]) idx = sortperm(tvals, rev = tdir < 0) @@ -53,8 +53,8 @@ end end end -@inline function interpolation(tval::Number, id::I, idxs, deriv::D, p, - continuity::Symbol = :left) where {I, D} +@inline function interpolation( + tval::Number, id::I, idxs, deriv::D, p, continuity::Symbol = :left) where {I, D} z = similar(id.cache.fᵢ₂_cache) interp_eval!(z, id.cache, tval, id.cache.mesh, id.cache.mesh_dt) return z diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 37721222..3d86fdb7 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -103,9 +103,10 @@ function SciMLBase.__init(prob::BVProblem, alg::AbstractMIRK; dt = 0.0, prob_ = !(prob.u0 isa AbstractArray) ? remake(prob; u0 = X) : prob - return MIRKCache{iip, T}(alg_order(alg), stage, M, size(X), f, bc, prob_, - prob.problem_type, prob.p, alg, TU, ITU, bcresid_prototype, mesh, mesh_dt, - k_discrete, k_interp, y, y₀, residual, fᵢ_cache, fᵢ₂_cache, defect, new_stages, + return MIRKCache{iip, T}( + alg_order(alg), stage, M, size(X), f, bc, prob_, prob.problem_type, + prob.p, alg, TU, ITU, bcresid_prototype, mesh, mesh_dt, k_discrete, + k_interp, y, y₀, residual, fᵢ_cache, fᵢ₂_cache, defect, new_stages, resid₁_size, (; defect_threshold, MxNsub, abstol, dt, adaptive, kwargs...)) end @@ -127,10 +128,10 @@ function __expand_cache!(cache::MIRKCache) return cache end -function __split_mirk_kwargs(; defect_threshold, MxNsub, abstol, dt, adaptive = true, - kwargs...) - return ((defect_threshold, MxNsub, abstol, adaptive, dt), - (; abstol, adaptive, kwargs...)) +function __split_mirk_kwargs(; + defect_threshold, MxNsub, abstol, dt, adaptive = true, kwargs...) + return ( + (defect_threshold, MxNsub, abstol, adaptive, dt), (; abstol, adaptive, kwargs...)) end function SciMLBase.solve!(cache::MIRKCache) @@ -183,8 +184,8 @@ function SciMLBase.solve!(cache::MIRKCache) end u = [reshape(y, cache.in_size) for y in cache.y₀] - return DiffEqBase.build_solution(prob, alg, cache.mesh, - u; interp = MIRKInterpolation(cache.mesh, u, cache), retcode = info) + return DiffEqBase.build_solution(prob, alg, cache.mesh, u; + interp = MIRKInterpolation(cache.mesh, u, cache), retcode = info) end # Constructing the Nonlinear Problem @@ -198,15 +199,15 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y::AbstractVector) where { end loss_collocation = if iip - (du, u, p) -> __mirk_loss_collocation!(du, u, p, cache.y, cache.mesh, - cache.residual, cache) + (du, u, p) -> __mirk_loss_collocation!( + du, u, p, cache.y, cache.mesh, cache.residual, cache) else (u, p) -> __mirk_loss_collocation(u, p, cache.y, cache.mesh, cache.residual, cache) end loss = if iip - (du, u, p) -> __mirk_loss!(du, u, p, cache.y, pt, cache.bc, cache.residual, - cache.mesh, cache) + (du, u, p) -> __mirk_loss!( + du, u, p, cache.y, pt, cache.bc, cache.residual, cache.mesh, cache) else (u, p) -> __mirk_loss(u, p, cache.y, pt, cache.bc, cache.mesh, cache) end @@ -214,8 +215,8 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y::AbstractVector) where { return __construct_nlproblem(cache, y, loss_bc, loss_collocation, loss, pt) end -function __mirk_loss!(resid, u, p, y, pt::StandardBVProblem, bc!::BC, residual, mesh, - cache) where {BC} +function __mirk_loss!( + resid, u, p, y, pt::StandardBVProblem, bc!::BC, residual, mesh, cache) where {BC} y_ = recursive_unflatten!(y, u) resids = [get_tmp(r, u) for r in residual] eval_bc_residual!(resids[1], pt, bc!, y_, p, mesh) @@ -224,9 +225,8 @@ function __mirk_loss!(resid, u, p, y, pt::StandardBVProblem, bc!::BC, residual, return nothing end -function __mirk_loss!( - resid, u, p, y, pt::TwoPointBVProblem, bc!::Tuple{BC1, BC2}, residual, - mesh, cache) where {BC1, BC2} +function __mirk_loss!(resid, u, p, y, pt::TwoPointBVProblem, bc!::Tuple{BC1, BC2}, + residual, mesh, cache) where {BC1, BC2} y_ = recursive_unflatten!(y, u) resids = [get_tmp(r, u) for r in residual] resida = @view resids[1][1:prod(cache.resid_size[1])] @@ -244,8 +244,8 @@ function __mirk_loss(u, p, y, pt::StandardBVProblem, bc::BC, mesh, cache) where return vcat(resid_bc, mapreduce(vec, vcat, resid_co)) end -function __mirk_loss(u, p, y, pt::TwoPointBVProblem, bc::Tuple{BC1, BC2}, mesh, - cache) where {BC1, BC2} +function __mirk_loss( + u, p, y, pt::TwoPointBVProblem, bc::Tuple{BC1, BC2}, mesh, cache) where {BC1, BC2} y_ = recursive_unflatten!(y, u) resid_bca, resid_bcb = eval_bc_residual(pt, bc, y_, p, mesh) resid_co = Φ(cache, y_, u, p) @@ -292,29 +292,31 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collo sd_bc = jac_alg.bc_diffmode isa AbstractSparseADType ? SymbolicsSparsityDetection() : NoSparsityDetection() - cache_bc = __sparse_jacobian_cache(Val(iip), jac_alg.bc_diffmode, sd_bc, loss_bcₚ, - resid_bc, y) + cache_bc = __sparse_jacobian_cache( + Val(iip), jac_alg.bc_diffmode, sd_bc, loss_bcₚ, resid_bc, y) sd_collocation = if jac_alg.nonbc_diffmode isa AbstractSparseADType if L < cache.M # For underdetermined problems we use sparse since we don't have banded qr - colored_matrix = __generate_sparse_jacobian_prototype(cache, - cache.problem_type, y, y, cache.M, N) + colored_matrix = __generate_sparse_jacobian_prototype( + cache, cache.problem_type, y, y, cache.M, N) J_full_band = nothing - __sparsity_detection_alg(ColoredMatrix(sparse(colored_matrix.M), - colored_matrix.row_colorvec, colored_matrix.col_colorvec)) + __sparsity_detection_alg(ColoredMatrix( + sparse(colored_matrix.M), colored_matrix.row_colorvec, + colored_matrix.col_colorvec)) else J_full_band = BandedMatrix(Ones{eltype(y)}(L + cache.M * (N - 1), cache.M * N), (L + 1, cache.M + max(cache.M - L, 0))) - __sparsity_detection_alg(__generate_sparse_jacobian_prototype(cache, - cache.problem_type, y, y, cache.M, N)) + __sparsity_detection_alg(__generate_sparse_jacobian_prototype( + cache, cache.problem_type, y, y, cache.M, N)) end else J_full_band = nothing NoSparsityDetection() end - cache_collocation = __sparse_jacobian_cache(Val(iip), jac_alg.nonbc_diffmode, - sd_collocation, loss_collocationₚ, resid_collocation, y) + cache_collocation = __sparse_jacobian_cache( + Val(iip), jac_alg.nonbc_diffmode, sd_collocation, + loss_collocationₚ, resid_collocation, y) J_bc = init_jacobian(cache_bc) J_c = init_jacobian(cache_collocation) @@ -325,53 +327,53 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collo end jac = if iip - (J, u, p) -> __mirk_mpoint_jacobian!(J, J_c, u, jac_alg.bc_diffmode, - jac_alg.nonbc_diffmode, cache_bc, cache_collocation, loss_bcₚ, - loss_collocationₚ, resid_bc, resid_collocation, L) + (J, u, p) -> __mirk_mpoint_jacobian!( + J, J_c, u, jac_alg.bc_diffmode, jac_alg.nonbc_diffmode, cache_bc, + cache_collocation, loss_bcₚ, loss_collocationₚ, resid_bc, resid_collocation, L) else - (u, p) -> __mirk_mpoint_jacobian(jac_prototype, J_c, u, jac_alg.bc_diffmode, - jac_alg.nonbc_diffmode, cache_bc, cache_collocation, loss_bcₚ, - loss_collocationₚ, L) + (u, p) -> __mirk_mpoint_jacobian( + jac_prototype, J_c, u, jac_alg.bc_diffmode, jac_alg.nonbc_diffmode, + cache_bc, cache_collocation, loss_bcₚ, loss_collocationₚ, L) end - nlf = NonlinearFunction{iip}(loss; resid_prototype = vcat(resid_bc, resid_collocation), - jac, jac_prototype) + nlf = NonlinearFunction{iip}( + loss; resid_prototype = vcat(resid_bc, resid_collocation), jac, jac_prototype) return (L == cache.M ? NonlinearProblem : NonlinearLeastSquaresProblem)(nlf, y, cache.p) end -function __mirk_mpoint_jacobian!(J, _, x, bc_diffmode, nonbc_diffmode, bc_diffcache, - nonbc_diffcache, loss_bc::BC, loss_collocation::C, resid_bc, resid_collocation, - L::Int) where {BC, C} +function __mirk_mpoint_jacobian!( + J, _, x, bc_diffmode, nonbc_diffmode, bc_diffcache, nonbc_diffcache, loss_bc::BC, + loss_collocation::C, resid_bc, resid_collocation, L::Int) where {BC, C} sparse_jacobian!(@view(J[1:L, :]), bc_diffmode, bc_diffcache, loss_bc, resid_bc, x) - sparse_jacobian!(@view(J[(L + 1):end, :]), nonbc_diffmode, nonbc_diffcache, - loss_collocation, resid_collocation, x) + sparse_jacobian!(@view(J[(L + 1):end, :]), nonbc_diffmode, + nonbc_diffcache, loss_collocation, resid_collocation, x) return nothing end -function __mirk_mpoint_jacobian!( - J::AlmostBandedMatrix, J_c, x, bc_diffmode, nonbc_diffmode, - bc_diffcache, nonbc_diffcache, loss_bc::BC, loss_collocation::C, resid_bc, - resid_collocation, L::Int) where {BC, C} +function __mirk_mpoint_jacobian!(J::AlmostBandedMatrix, J_c, x, bc_diffmode, nonbc_diffmode, + bc_diffcache, nonbc_diffcache, loss_bc::BC, loss_collocation::C, + resid_bc, resid_collocation, L::Int) where {BC, C} J_bc = fillpart(J) sparse_jacobian!(J_bc, bc_diffmode, bc_diffcache, loss_bc, resid_bc, x) - sparse_jacobian!(J_c, nonbc_diffmode, nonbc_diffcache, - loss_collocation, resid_collocation, x) + sparse_jacobian!( + J_c, nonbc_diffmode, nonbc_diffcache, loss_collocation, resid_collocation, x) exclusive_bandpart(J) .= J_c finish_part_setindex!(J) return nothing end -function __mirk_mpoint_jacobian(J, _, x, bc_diffmode, nonbc_diffmode, bc_diffcache, - nonbc_diffcache, loss_bc::BC, loss_collocation::C, L::Int) where {BC, C} +function __mirk_mpoint_jacobian( + J, _, x, bc_diffmode, nonbc_diffmode, bc_diffcache, nonbc_diffcache, + loss_bc::BC, loss_collocation::C, L::Int) where {BC, C} sparse_jacobian!(@view(J[1:L, :]), bc_diffmode, bc_diffcache, loss_bc, x) - sparse_jacobian!(@view(J[(L + 1):end, :]), nonbc_diffmode, nonbc_diffcache, - loss_collocation, x) + sparse_jacobian!( + @view(J[(L + 1):end, :]), nonbc_diffmode, nonbc_diffcache, loss_collocation, x) return J end -function __mirk_mpoint_jacobian(J::AlmostBandedMatrix, J_c, x, bc_diffmode, nonbc_diffmode, - bc_diffcache, nonbc_diffcache, loss_bc::BC, loss_collocation::C, - L::Int) where {BC, C} +function __mirk_mpoint_jacobian( + J::AlmostBandedMatrix, J_c, x, bc_diffmode, nonbc_diffmode, bc_diffcache, + nonbc_diffcache, loss_bc::BC, loss_collocation::C, L::Int) where {BC, C} J_bc = fillpart(J) sparse_jacobian!(J_bc, bc_diffmode, bc_diffcache, loss_bc, x) sparse_jacobian!(J_c, nonbc_diffmode, nonbc_diffcache, loss_collocation, x) @@ -393,10 +395,11 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collo L = length(cache.bcresid_prototype) sd = if jac_alg.diffmode isa AbstractSparseADType - __sparsity_detection_alg(__generate_sparse_jacobian_prototype(cache, - cache.problem_type, @view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), - @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), cache.M, - N)) + __sparsity_detection_alg(__generate_sparse_jacobian_prototype( + cache, cache.problem_type, + @view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), + @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), + cache.M, N)) else NoSparsityDetection() end @@ -404,11 +407,11 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collo jac_prototype = init_jacobian(diffcache) jac = if iip - (J, u, p) -> __mirk_2point_jacobian!(J, u, jac_alg.diffmode, diffcache, lossₚ, - resid) + (J, u, p) -> __mirk_2point_jacobian!( + J, u, jac_alg.diffmode, diffcache, lossₚ, resid) else - (u, p) -> __mirk_2point_jacobian(u, jac_prototype, jac_alg.diffmode, diffcache, - lossₚ) + (u, p) -> __mirk_2point_jacobian( + u, jac_prototype, jac_alg.diffmode, diffcache, lossₚ) end nlf = NonlinearFunction{iip}(loss; resid_prototype = copy(resid), jac, jac_prototype) diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index 13bda8db..e8534508 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -33,39 +33,37 @@ function __solve(prob::BVProblem, _alg::MultipleShooting; odesolve_kwargs = (;), internal_ode_kwargs = (; verbose, kwargs..., odesolve_kwargs..., save_end = true) - solve_internal_odes! = @closure (resid_nodes, us, p, cur_nshoot, nodes, - odecache) -> __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoot, - odecache, nodes, u0_size, N, ensemblealg, tspan) + solve_internal_odes! = @closure (resid_nodes, us, p, cur_nshoot, nodes, odecache) -> __multiple_shooting_solve_internal_odes!( + resid_nodes, us, cur_nshoot, odecache, nodes, u0_size, N, ensemblealg, tspan) # This gets all the nshoots except the final SingleShooting case all_nshoots = __get_all_nshoots(alg.grid_coarsening, nshoots) u_at_nodes, nodes = similar(u0, 0), typeof(first(tspan))[] - ode_cache_loss_fn = __multiple_shooting_init_odecache(ensemblealg, prob, - alg.ode_alg, u0, maximum(all_nshoots); internal_ode_kwargs...) + ode_cache_loss_fn = __multiple_shooting_init_odecache( + ensemblealg, prob, alg.ode_alg, u0, maximum(all_nshoots); internal_ode_kwargs...) for (i, cur_nshoot) in enumerate(all_nshoots) if i == 1 - u_at_nodes = __multiple_shooting_initialize!(nodes, prob, alg, ig, nshoots, - ode_cache_loss_fn; kwargs..., verbose, odesolve_kwargs...) + u_at_nodes = __multiple_shooting_initialize!( + nodes, prob, alg, ig, nshoots, ode_cache_loss_fn; + kwargs..., verbose, odesolve_kwargs...) else - u_at_nodes = __multiple_shooting_initialize!(nodes, u_at_nodes, prob, alg, - cur_nshoot, all_nshoots[i - 1], ig, ode_cache_loss_fn, u0; kwargs..., - verbose, odesolve_kwargs...) + u_at_nodes = __multiple_shooting_initialize!( + nodes, u_at_nodes, prob, alg, cur_nshoot, all_nshoots[i - 1], ig, + ode_cache_loss_fn, u0; kwargs..., verbose, odesolve_kwargs...) end if prob.problem_type isa TwoPointBVProblem - __solve_nlproblem!( - prob.problem_type, alg, bcresid_prototype, u_at_nodes, nodes, - cur_nshoot, M, N, resida_len, residb_len, solve_internal_odes!, bc[1], - bc[2], prob, u0, ode_cache_loss_fn, ensemblealg, internal_ode_kwargs; - verbose, kwargs..., nlsolve_kwargs...) + __solve_nlproblem!(prob.problem_type, alg, bcresid_prototype, u_at_nodes, nodes, + cur_nshoot, M, N, resida_len, residb_len, solve_internal_odes!, + bc[1], bc[2], prob, u0, ode_cache_loss_fn, ensemblealg, + internal_ode_kwargs; verbose, kwargs..., nlsolve_kwargs...) else - __solve_nlproblem!( - prob.problem_type, alg, bcresid_prototype, u_at_nodes, nodes, - cur_nshoot, M, N, prod(resid_size), solve_internal_odes!, bc, prob, f, - u0_size, u0, ode_cache_loss_fn, ensemblealg, internal_ode_kwargs; verbose, - kwargs..., nlsolve_kwargs...) + __solve_nlproblem!(prob.problem_type, alg, bcresid_prototype, u_at_nodes, nodes, + cur_nshoot, M, N, prod(resid_size), solve_internal_odes!, + bc, prob, f, u0_size, u0, ode_cache_loss_fn, ensemblealg, + internal_ode_kwargs; verbose, kwargs..., nlsolve_kwargs...) end end @@ -74,12 +72,12 @@ function __solve(prob::BVProblem, _alg::MultipleShooting; odesolve_kwargs = (;), else diffmode_shooting = __get_non_sparse_ad(alg.jac_alg.bc_diffmode) end - shooting_alg = Shooting(alg.ode_alg, alg.nlsolve, - BVPJacobianAlgorithm(diffmode_shooting)) + shooting_alg = Shooting( + alg.ode_alg, alg.nlsolve, BVPJacobianAlgorithm(diffmode_shooting)) single_shooting_prob = remake(prob; u0 = reshape(u_at_nodes[1:N], u0_size)) - return __solve(single_shooting_prob, shooting_alg; odesolve_kwargs, nlsolve_kwargs, - verbose, kwargs...) + return __solve(single_shooting_prob, shooting_alg; odesolve_kwargs, + nlsolve_kwargs, verbose, kwargs...) end # TODO: We can save even more memory by hoisting the preallocated caches for the ODEs @@ -87,43 +85,44 @@ end # TODO: But we can do it another day. Currently the gains here are quite high to justify # TODO: waiting. -function __solve_nlproblem!(::TwoPointBVProblem, alg::MultipleShooting, bcresid_prototype, - u_at_nodes, nodes, cur_nshoot::Int, M::Int, N::Int, resida_len::Int, - residb_len::Int, solve_internal_odes!::S, bca::B1, bcb::B2, prob, u0, - ode_cache_loss_fn, ensemblealg, internal_ode_kwargs; kwargs...) where {B1, B2, S} +function __solve_nlproblem!( + ::TwoPointBVProblem, alg::MultipleShooting, bcresid_prototype, u_at_nodes, + nodes, cur_nshoot::Int, M::Int, N::Int, resida_len::Int, residb_len::Int, + solve_internal_odes!::S, bca::B1, bcb::B2, prob, u0, ode_cache_loss_fn, + ensemblealg, internal_ode_kwargs; kwargs...) where {B1, B2, S} if __any_sparse_ad(alg.jac_alg) - J_proto = __generate_sparse_jacobian_prototype(alg, prob.problem_type, - bcresid_prototype, u0, N, cur_nshoot) + J_proto = __generate_sparse_jacobian_prototype( + alg, prob.problem_type, bcresid_prototype, u0, N, cur_nshoot) end - resid_prototype = vcat(bcresid_prototype[1], - similar(u_at_nodes, cur_nshoot * N), bcresid_prototype[2]) + resid_prototype = vcat( + bcresid_prototype[1], similar(u_at_nodes, cur_nshoot * N), bcresid_prototype[2]) - loss_fn = @closure (du, u, p) -> __multiple_shooting_2point_loss!(du, u, p, cur_nshoot, - nodes, prob, solve_internal_odes!, resida_len, residb_len, N, bca, bcb, - ode_cache_loss_fn) + loss_fn = @closure (du, u, p) -> __multiple_shooting_2point_loss!( + du, u, p, cur_nshoot, nodes, prob, solve_internal_odes!, + resida_len, residb_len, N, bca, bcb, ode_cache_loss_fn) sd_bvp = alg.jac_alg.diffmode isa AbstractSparseADType ? __sparsity_detection_alg(J_proto) : NoSparsityDetection() resid_prototype_cached = similar(resid_prototype) - jac_cache = sparse_jacobian_cache(alg.jac_alg.diffmode, sd_bvp, nothing, - resid_prototype_cached, u_at_nodes) + jac_cache = sparse_jacobian_cache( + alg.jac_alg.diffmode, sd_bvp, nothing, resid_prototype_cached, u_at_nodes) jac_prototype = init_jacobian(jac_cache) - ode_cache_jac_fn = __multiple_shooting_init_jacobian_odecache(ensemblealg, prob, - jac_cache, alg.jac_alg.diffmode, alg.ode_alg, cur_nshoot, u0; - internal_ode_kwargs...) + ode_cache_jac_fn = __multiple_shooting_init_jacobian_odecache( + ensemblealg, prob, jac_cache, alg.jac_alg.diffmode, + alg.ode_alg, cur_nshoot, u0; internal_ode_kwargs...) - loss_fnₚ = @closure (du, u) -> __multiple_shooting_2point_loss!(du, u, prob.p, - cur_nshoot, nodes, prob, solve_internal_odes!, resida_len, residb_len, N, bca, bcb, - ode_cache_jac_fn) + loss_fnₚ = @closure (du, u) -> __multiple_shooting_2point_loss!( + du, u, prob.p, cur_nshoot, nodes, prob, solve_internal_odes!, + resida_len, residb_len, N, bca, bcb, ode_cache_jac_fn) - jac_fn = @closure (J, u, p) -> __multiple_shooting_2point_jacobian!(J, u, p, jac_cache, - loss_fnₚ, resid_prototype_cached, alg) + jac_fn = @closure (J, u, p) -> __multiple_shooting_2point_jacobian!( + J, u, p, jac_cache, loss_fnₚ, resid_prototype_cached, alg) - loss_function! = __unsafe_nonlinearfunction{true}(loss_fn; resid_prototype, - jac = jac_fn, jac_prototype) + loss_function! = __unsafe_nonlinearfunction{true}( + loss_fn; resid_prototype, jac = jac_fn, jac_prototype) # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) @@ -137,52 +136,52 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ solve_internal_odes!::S, bc::BC, prob, f::F, u0_size, u0, ode_cache_loss_fn, ensemblealg, internal_ode_kwargs; kwargs...) where {BC, F, S} if __any_sparse_ad(alg.jac_alg) - J_proto = __generate_sparse_jacobian_prototype(alg, prob.problem_type, - bcresid_prototype, u0, N, cur_nshoot) + J_proto = __generate_sparse_jacobian_prototype( + alg, prob.problem_type, bcresid_prototype, u0, N, cur_nshoot) end resid_prototype = vcat(bcresid_prototype, similar(u_at_nodes, cur_nshoot * N)) __resid_nodes = resid_prototype[(end - cur_nshoot * N + 1):end] - resid_nodes = __maybe_allocate_diffcache(__resid_nodes, - pickchunksize((cur_nshoot + 1) * N), alg.jac_alg.bc_diffmode) + resid_nodes = __maybe_allocate_diffcache( + __resid_nodes, pickchunksize((cur_nshoot + 1) * N), alg.jac_alg.bc_diffmode) - loss_fn = @closure (du, u, p) -> __multiple_shooting_mpoint_loss!(du, u, p, cur_nshoot, - nodes, prob, solve_internal_odes!, resid_len, N, f, bc, u0_size, prob.tspan, - alg.ode_alg, u0, ode_cache_loss_fn) + loss_fn = @closure (du, u, p) -> __multiple_shooting_mpoint_loss!( + du, u, p, cur_nshoot, nodes, prob, solve_internal_odes!, resid_len, + N, f, bc, u0_size, prob.tspan, alg.ode_alg, u0, ode_cache_loss_fn) # ODE Part sd_ode = alg.jac_alg.nonbc_diffmode isa AbstractSparseADType ? __sparsity_detection_alg(J_proto) : NoSparsityDetection() - ode_jac_cache = sparse_jacobian_cache(alg.jac_alg.nonbc_diffmode, sd_ode, - nothing, similar(u_at_nodes, cur_nshoot * N), u_at_nodes) - ode_cache_ode_jac_fn = __multiple_shooting_init_jacobian_odecache(ensemblealg, prob, - ode_jac_cache, alg.jac_alg.nonbc_diffmode, alg.ode_alg, cur_nshoot, u0; - internal_ode_kwargs...) + ode_jac_cache = sparse_jacobian_cache(alg.jac_alg.nonbc_diffmode, sd_ode, nothing, + similar(u_at_nodes, cur_nshoot * N), u_at_nodes) + ode_cache_ode_jac_fn = __multiple_shooting_init_jacobian_odecache( + ensemblealg, prob, ode_jac_cache, alg.jac_alg.nonbc_diffmode, + alg.ode_alg, cur_nshoot, u0; internal_ode_kwargs...) # BC Part sd_bc = alg.jac_alg.bc_diffmode isa AbstractSparseADType ? SymbolicsSparsityDetection() : NoSparsityDetection() - bc_jac_cache = sparse_jacobian_cache(alg.jac_alg.bc_diffmode, - sd_bc, nothing, similar(bcresid_prototype), u_at_nodes) - ode_cache_bc_jac_fn = __multiple_shooting_init_jacobian_odecache(ensemblealg, prob, - bc_jac_cache, alg.jac_alg.bc_diffmode, alg.ode_alg, cur_nshoot, u0; - internal_ode_kwargs...) + bc_jac_cache = sparse_jacobian_cache( + alg.jac_alg.bc_diffmode, sd_bc, nothing, similar(bcresid_prototype), u_at_nodes) + ode_cache_bc_jac_fn = __multiple_shooting_init_jacobian_odecache( + ensemblealg, prob, bc_jac_cache, alg.jac_alg.bc_diffmode, + alg.ode_alg, cur_nshoot, u0; internal_ode_kwargs...) jac_prototype = vcat(init_jacobian(bc_jac_cache), init_jacobian(ode_jac_cache)) # Define the functions now - ode_fn = @closure (du, u) -> solve_internal_odes!(du, u, prob.p, cur_nshoot, nodes, - ode_cache_ode_jac_fn) - bc_fn = @closure (du, u) -> __multiple_shooting_mpoint_loss_bc!(du, u, prob.p, - cur_nshoot, nodes, prob, solve_internal_odes!, N, f, bc, u0_size, prob.tspan, - alg.ode_alg, u0, ode_cache_bc_jac_fn) + ode_fn = @closure (du, u) -> solve_internal_odes!( + du, u, prob.p, cur_nshoot, nodes, ode_cache_ode_jac_fn) + bc_fn = @closure (du, u) -> __multiple_shooting_mpoint_loss_bc!( + du, u, prob.p, cur_nshoot, nodes, prob, solve_internal_odes!, N, + f, bc, u0_size, prob.tspan, alg.ode_alg, u0, ode_cache_bc_jac_fn) - jac_fn = @closure (J, u, p) -> __multiple_shooting_mpoint_jacobian!(J, u, p, - similar(bcresid_prototype), resid_nodes, ode_jac_cache, bc_jac_cache, - ode_fn, bc_fn, alg, N, M) + jac_fn = @closure (J, u, p) -> __multiple_shooting_mpoint_jacobian!( + J, u, p, similar(bcresid_prototype), resid_nodes, + ode_jac_cache, bc_jac_cache, ode_fn, bc_fn, alg, N, M) - loss_function! = __unsafe_nonlinearfunction{true}(loss_fn; resid_prototype, - jac_prototype, jac = jac_fn) + loss_function! = __unsafe_nonlinearfunction{true}( + loss_fn; resid_prototype, jac_prototype, jac = jac_fn) # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) @@ -191,23 +190,22 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ return nothing end -function __multiple_shooting_init_odecache(::EnsembleSerial, prob, alg, u0, nshoots; - kwargs...) +function __multiple_shooting_init_odecache( + ::EnsembleSerial, prob, alg, u0, nshoots; kwargs...) odeprob = ODEProblem{isinplace(prob)}(prob.f, u0, prob.tspan, prob.p) return SciMLBase.__init(odeprob, alg; kwargs...) end -function __multiple_shooting_init_odecache(::EnsembleThreads, prob, alg, u0, nshoots; - kwargs...) +function __multiple_shooting_init_odecache( + ::EnsembleThreads, prob, alg, u0, nshoots; kwargs...) odeprob = ODEProblem{isinplace(prob)}(prob.f, u0, prob.tspan, prob.p) return [SciMLBase.__init(odeprob, alg; kwargs...) for _ in 1:min(Threads.nthreads(), nshoots)] end -function __multiple_shooting_init_jacobian_odecache(ensemblealg, prob, jac_cache, ad, alg, - nshoots, u; kwargs...) - return __multiple_shooting_init_odecache(ensemblealg, prob, alg, u, nshoots; - kwargs...) +function __multiple_shooting_init_jacobian_odecache( + ensemblealg, prob, jac_cache, ad, alg, nshoots, u; kwargs...) + return __multiple_shooting_init_odecache(ensemblealg, prob, alg, u, nshoots; kwargs...) end function __multiple_shooting_init_jacobian_odecache(ensemblealg, prob, jac_cache, @@ -219,13 +217,14 @@ function __multiple_shooting_init_jacobian_odecache(ensemblealg, prob, jac_cache xduals = reshape(cache.t[1:length(u)], size(u)) end fill!(xduals, 0) - return __multiple_shooting_init_odecache(ensemblealg, prob, alg, xduals, nshoots; - kwargs...) + return __multiple_shooting_init_odecache( + ensemblealg, prob, alg, xduals, nshoots; kwargs...) end # Not using `EnsembleProblem` since it is hard to initialize the cache and stuff -function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots::Int, - odecache, nodes, u0_size, N::Int, ::EnsembleSerial, tspan) +function __multiple_shooting_solve_internal_odes!( + resid_nodes, us, cur_nshoots::Int, odecache, + nodes, u0_size, N::Int, ::EnsembleSerial, tspan) ts_ = Vector{Vector{typeof(first(tspan))}}(undef, cur_nshoots) us_ = Vector{Vector{typeof(us)}}(undef, cur_nshoots) @@ -242,8 +241,9 @@ function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots:: return reduce(vcat, us_), reduce(vcat, ts_) end -function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots::Int, - odecache::Vector, nodes, u0_size, N::Int, ::EnsembleThreads, tspan) +function __multiple_shooting_solve_internal_odes!( + resid_nodes, us, cur_nshoots::Int, odecache::Vector, + nodes, u0_size, N::Int, ::EnsembleThreads, tspan) ts_ = Vector{Vector{typeof(first(tspan))}}(undef, cur_nshoots) us_ = Vector{Vector{typeof(us)}}(undef, cur_nshoots) @@ -258,8 +258,7 @@ function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots:: Threads.@threads for idx in 1:length(data_partition) cache = odecache[idx] for i in data_partition[idx] - SciMLBase.reinit!( - cache, reshape(@view(us[((i - 1) * N + 1):(i * N)]), u0_size); + SciMLBase.reinit!(cache, reshape(@view(us[((i - 1) * N + 1):(i * N)]), u0_size); t0 = nodes[i], tf = nodes[i + 1]) sol = solve!(cache) us_[i] = deepcopy(sol.u) @@ -272,28 +271,28 @@ function __multiple_shooting_solve_internal_odes!(resid_nodes, us, cur_nshoots:: return reduce(vcat, us_), reduce(vcat, ts_) end -function __multiple_shooting_2point_jacobian!(J, us, p, jac_cache, loss_fn::F, resid, - alg::MultipleShooting) where {F} +function __multiple_shooting_2point_jacobian!( + J, us, p, jac_cache, loss_fn::F, resid, alg::MultipleShooting) where {F} sparse_jacobian!(J, alg.jac_alg.diffmode, jac_cache, loss_fn, resid, us) return nothing end -function __multiple_shooting_mpoint_jacobian!(J, us, p, resid_bc, resid_nodes, - ode_jac_cache, bc_jac_cache, ode_fn::F1, bc_fn::F2, alg::MultipleShooting, - N::Int, M::Int) where {F1, F2} +function __multiple_shooting_mpoint_jacobian!( + J, us, p, resid_bc, resid_nodes, ode_jac_cache, bc_jac_cache, ode_fn::F1, + bc_fn::F2, alg::MultipleShooting, N::Int, M::Int) where {F1, F2} J_bc = @view(J[1:M, :]) J_c = @view(J[(M + 1):end, :]) - sparse_jacobian!(J_c, alg.jac_alg.nonbc_diffmode, ode_jac_cache, ode_fn, - resid_nodes.du, us) + sparse_jacobian!( + J_c, alg.jac_alg.nonbc_diffmode, ode_jac_cache, ode_fn, resid_nodes.du, us) sparse_jacobian!(J_bc, alg.jac_alg.bc_diffmode, bc_jac_cache, bc_fn, resid_bc, us) return nothing end -@views function __multiple_shooting_2point_loss!(resid, us, p, cur_nshoots::Int, nodes, - prob, solve_internal_odes!::S, resida_len, residb_len, N, bca::BCA, bcb::BCB, - ode_cache) where {S, BCA, BCB} +@views function __multiple_shooting_2point_loss!( + resid, us, p, cur_nshoots::Int, nodes, prob, solve_internal_odes!::S, + resida_len, residb_len, N, bca::BCA, bcb::BCB, ode_cache) where {S, BCA, BCB} resid_ = resid[(resida_len + 1):(end - residb_len)] solve_internal_odes!(resid_, us, p, cur_nshoots, nodes, ode_cache) @@ -314,9 +313,9 @@ end return nothing end -@views function __multiple_shooting_mpoint_loss_bc!(resid_bc, us, p, cur_nshoots::Int, - nodes, prob, solve_internal_odes!::S, N, f::F, bc::BC, u0_size, tspan, - ode_alg, u0, ode_cache) where {S, F, BC} +@views function __multiple_shooting_mpoint_loss_bc!( + resid_bc, us, p, cur_nshoots::Int, nodes, prob, solve_internal_odes!::S, + N, f::F, bc::BC, u0_size, tspan, ode_alg, u0, ode_cache) where {S, F, BC} iip = isinplace(prob) _resid_nodes = similar(us, cur_nshoots * N) @@ -335,9 +334,9 @@ end return nothing end -@views function __multiple_shooting_mpoint_loss!(resid, us, p, cur_nshoots::Int, nodes, - prob, solve_internal_odes!::S, resid_len, N, f::F, bc::BC, u0_size, tspan, - ode_alg, u0, ode_cache) where {S, F, BC} +@views function __multiple_shooting_mpoint_loss!( + resid, us, p, cur_nshoots::Int, nodes, prob, solve_internal_odes!::S, resid_len, + N, f::F, bc::BC, u0_size, tspan, ode_alg, u0, ode_cache) where {S, F, BC} iip = isinplace(prob) resid_bc = resid[1:resid_len] resid_nodes = resid[(resid_len + 1):end] @@ -358,8 +357,7 @@ end # Problem has initial guess @views function __multiple_shooting_initialize!( - nodes, prob, alg, ::Val{true}, nshoots::Int, - odecache; kwargs...) + nodes, prob, alg, ::Val{true}, nshoots::Int, odecache; kwargs...) @unpack u0, tspan = prob resize!(nodes, nshoots + 1) @@ -377,8 +375,9 @@ end end # No initial guess -@views function __multiple_shooting_initialize!(nodes, prob, alg::MultipleShooting, - ::Val{false}, nshoots::Int, odecache_; verbose, kwargs...) +@views function __multiple_shooting_initialize!( + nodes, prob, alg::MultipleShooting, ::Val{false}, + nshoots::Int, odecache_; verbose, kwargs...) @unpack f, u0, tspan, p = prob @unpack ode_alg = alg @@ -416,8 +415,8 @@ end end # Grid coarsening -@views function __multiple_shooting_initialize!(nodes, u_at_nodes_prev, prob, alg, - nshoots, old_nshoots, ig, odecache_, u0; kwargs...) +@views function __multiple_shooting_initialize!(nodes, u_at_nodes_prev, prob, alg, nshoots, + old_nshoots, ig, odecache_, u0; kwargs...) @unpack f, tspan, p = prob prev_nodes = copy(nodes) odecache = odecache_ isa Vector ? first(odecache_) : odecache_ diff --git a/src/solve/single_shooting.jl b/src/solve/single_shooting.jl index 7e95fdd6..04e40fc9 100644 --- a/src/solve/single_shooting.jl +++ b/src/solve/single_shooting.jl @@ -27,11 +27,11 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), ode_cache_loss_fn = SciMLBase.__init(internal_prob, alg.ode_alg; ode_kwargs...) loss_fn = if iip - @closure (du, u, p) -> __single_shooting_loss!(du, u, p, ode_cache_loss_fn, bc, - u0_size, prob.problem_type, resid_size) + @closure (du, u, p) -> __single_shooting_loss!( + du, u, p, ode_cache_loss_fn, bc, u0_size, prob.problem_type, resid_size) else - @closure (u, p) -> __single_shooting_loss(u, p, ode_cache_loss_fn, bc, u0_size, - prob.problem_type) + @closure (u, p) -> __single_shooting_loss( + u, p, ode_cache_loss_fn, bc, u0_size, prob.problem_type) end sd = alg.jac_alg.diffmode isa AbstractSparseADType ? SymbolicsSparsityDetection() : @@ -48,36 +48,36 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), sparse_jacobian_cache(alg.jac_alg.diffmode, sd, nothing, vec(u0); fx = y_) end - ode_cache_jac_fn = __single_shooting_jacobian_ode_cache(internal_prob, jac_cache, - alg.jac_alg.diffmode, u0, alg.ode_alg; ode_kwargs...) + ode_cache_jac_fn = __single_shooting_jacobian_ode_cache( + internal_prob, jac_cache, alg.jac_alg.diffmode, u0, alg.ode_alg; ode_kwargs...) jac_prototype = init_jacobian(jac_cache) loss_fnₚ = if iip - @closure (du, u) -> __single_shooting_loss!(du, u, prob.p, ode_cache_jac_fn, bc, - u0_size, prob.problem_type, resid_size) + @closure (du, u) -> __single_shooting_loss!( + du, u, prob.p, ode_cache_jac_fn, bc, u0_size, prob.problem_type, resid_size) else - @closure (u) -> __single_shooting_loss(u, prob.p, ode_cache_jac_fn, bc, u0_size, - prob.problem_type) + @closure (u) -> __single_shooting_loss( + u, prob.p, ode_cache_jac_fn, bc, u0_size, prob.problem_type) end jac_fn = if iip - @closure (J, u, p) -> __single_shooting_jacobian!(J, u, jac_cache, - alg.jac_alg.diffmode, loss_fnₚ, y_) + @closure (J, u, p) -> __single_shooting_jacobian!( + J, u, jac_cache, alg.jac_alg.diffmode, loss_fnₚ, y_) else - @closure (u, p) -> __single_shooting_jacobian(jac_prototype, u, jac_cache, - alg.jac_alg.diffmode, loss_fnₚ) + @closure (u, p) -> __single_shooting_jacobian( + jac_prototype, u, jac_cache, alg.jac_alg.diffmode, loss_fnₚ) end - nlf = __unsafe_nonlinearfunction{iip}(loss_fn; jac_prototype, resid_prototype, - jac = jac_fn) + nlf = __unsafe_nonlinearfunction{iip}( + loss_fn; jac_prototype, resid_prototype, jac = jac_fn) nlprob = __internal_nlsolve_problem(prob, resid_prototype, u0, nlf, vec(u0), prob.p) nlsol = __solve(nlprob, alg.nlsolve; nlsolve_kwargs..., verbose, kwargs...) # There is no way to reinit with the same cache with different cache. But not saving # the internal values gives a significant speedup. So we just create a new cache - internal_prob_final = ODEProblem{iip}(prob.f, reshape(nlsol.u, u0_size), prob.tspan, - prob.p) + internal_prob_final = ODEProblem{iip}( + prob.f, reshape(nlsol.u, u0_size), prob.tspan, prob.p) odesol = __solve(internal_prob_final, alg.ode_alg; actual_ode_kwargs...) return __build_solution(prob, odesol, nlsol) @@ -129,8 +129,9 @@ function __single_shooting_jacobian_ode_cache(prob, jac_cache, alg, u0, ode_alg; return SciMLBase.__init(remake(prob; u0), ode_alg; kwargs...) end -function __single_shooting_jacobian_ode_cache(prob, jac_cache, - ::Union{AutoForwardDiff, AutoSparseForwardDiff}, u0, ode_alg; kwargs...) +function __single_shooting_jacobian_ode_cache( + prob, jac_cache, ::Union{AutoForwardDiff, AutoSparseForwardDiff}, + u0, ode_alg; kwargs...) cache = jac_cache.cache if cache isa ForwardDiff.JacobianConfig xduals = cache.duals isa Tuple ? cache.duals[2] : cache.duals @@ -138,7 +139,7 @@ function __single_shooting_jacobian_ode_cache(prob, jac_cache, xduals = cache.t end fill!(xduals, 0) - prob_ = remake(prob; u0 = reshape(xduals, size(u0)), - tspan = eltype(xduals).(prob.tspan)) + prob_ = remake( + prob; u0 = reshape(xduals, size(u0)), tspan = eltype(xduals).(prob.tspan)) return SciMLBase.__init(prob_, ode_alg; kwargs...) end diff --git a/src/sparse_jacobians.jl b/src/sparse_jacobians.jl index 577d6e4b..27939969 100644 --- a/src/sparse_jacobians.jl +++ b/src/sparse_jacobians.jl @@ -32,8 +32,8 @@ Base.eltype(M::ColoredMatrix) = eltype(M.M) ColoredMatrix() = ColoredMatrix(nothing, nothing, nothing) function __sparsity_detection_alg(M::ColoredMatrix) - return PrecomputedJacobianColorvec(; jac_prototype = M.M, M.row_colorvec, - M.col_colorvec) + return PrecomputedJacobianColorvec(; + jac_prototype = M.M, M.row_colorvec, M.col_colorvec) end __sparsity_detection_alg(::ColoredMatrix{Nothing}) = NoSparsityDetection() @@ -53,16 +53,16 @@ function __generate_sparse_jacobian_prototype(cache::MIRKCache, ya, yb, M, N) return __generate_sparse_jacobian_prototype(cache, cache.problem_type, ya, yb, M, N) end -function __generate_sparse_jacobian_prototype(::MIRKCache, ::StandardBVProblem, ya, yb, M, - N) +function __generate_sparse_jacobian_prototype( + ::MIRKCache, ::StandardBVProblem, ya, yb, M, N) fast_scalar_indexing(ya) || error("Sparse Jacobians are only supported for Fast Scalar Index-able Arrays") J_c = BandedMatrix(Ones{eltype(ya)}(M * (N - 1), M * N), (1, 2M - 1)) return ColoredMatrix(J_c, matrix_colors(J_c'), matrix_colors(J_c)) end -function __generate_sparse_jacobian_prototype(::MIRKCache, ::TwoPointBVProblem, - ya, yb, M, N) +function __generate_sparse_jacobian_prototype( + ::MIRKCache, ::TwoPointBVProblem, ya, yb, M, N) fast_scalar_indexing(ya) || error("Sparse Jacobians are only supported for Fast Scalar Index-able Arrays") J₁ = length(ya) + length(yb) + M * (N - 1) diff --git a/src/types.jl b/src/types.jl index 9948dcc5..bc45b43f 100644 --- a/src/types.jl +++ b/src/types.jl @@ -13,8 +13,6 @@ struct MIRKTableau{sType, cType, vType, bType, xType} end end -@truncate_stacktrace MIRKTableau 1 - struct MIRKInterpTableau{s, c, v, x, τ} s_star::s c_star::c @@ -24,14 +22,12 @@ struct MIRKInterpTableau{s, c, v, x, τ} function MIRKInterpTableau(s_star, c_star, v_star, x_star, τ_star) @assert eltype(c_star) == eltype(v_star) == eltype(x_star) - return new{typeof(s_star), typeof(c_star), typeof(v_star), typeof(x_star), - typeof(τ_star)}(s_star, - c_star, v_star, x_star, τ_star) + return new{ + typeof(s_star), typeof(c_star), typeof(v_star), typeof(x_star), typeof(τ_star)}( + s_star, c_star, v_star, x_star, τ_star) end end -@truncate_stacktrace MIRKInterpTableau 1 - # Sparsity Detection @concrete struct BVPJacobianAlgorithm bc_diffmode @@ -66,12 +62,13 @@ end __any_sparse_ad(ad) = ad isa AbstractSparseADType function __any_sparse_ad(jac_alg::BVPJacobianAlgorithm) - __any_sparse_ad(jac_alg.bc_diffmode) || __any_sparse_ad(jac_alg.nonbc_diffmode) || + __any_sparse_ad(jac_alg.bc_diffmode) || + __any_sparse_ad(jac_alg.nonbc_diffmode) || __any_sparse_ad(jac_alg.diffmode) end -function BVPJacobianAlgorithm(diffmode = missing; nonbc_diffmode = missing, - bc_diffmode = missing) +function BVPJacobianAlgorithm( + diffmode = missing; nonbc_diffmode = missing, bc_diffmode = missing) if diffmode !== missing bc_diffmode = bc_diffmode === missing ? diffmode : bc_diffmode nonbc_diffmode = nonbc_diffmode === missing ? diffmode : nonbc_diffmode @@ -99,8 +96,8 @@ function concrete_jacobian_algorithm(jac_alg::BVPJacobianAlgorithm, prob::BVProb return concrete_jacobian_algorithm(jac_alg, prob.problem_type, prob, alg) end -function concrete_jacobian_algorithm(jac_alg::BVPJacobianAlgorithm, prob_type, - prob::BVProblem, alg) +function concrete_jacobian_algorithm( + jac_alg::BVPJacobianAlgorithm, prob_type, prob::BVProblem, alg) u0 = prob.u0 isa AbstractArray ? prob.u0 : __initial_guess(prob.u0, prob.p, first(prob.tspan)) diffmode = jac_alg.diffmode === nothing ? __default_sparse_ad(u0) : jac_alg.diffmode @@ -146,19 +143,15 @@ function concretize_jacobian_algorithm(alg, prob) return alg end -function MIRKJacobianComputationAlgorithm(diffmode = missing; - collocation_diffmode = missing, bc_diffmode = missing) - Base.depwarn("`MIRKJacobianComputationAlgorithm` has been deprecated in favor of \ - `BVPJacobianAlgorithm`. Replace `collocation_diffmode` with `nonbc_diffmode", - :MIRKJacobianComputationAlgorithm) - return BVPJacobianAlgorithm(diffmode; nonbc_diffmode = collocation_diffmode, - bc_diffmode) -end +Base.@deprecate MIRKJacobianComputationAlgorithm( + diffmode = missing; collocation_diffmode = missing, bc_diffmode = missing) BVPJacobianAlgorithm( + diffmode; nonbc_diffmode = collocation_diffmode, bc_diffmode) __needs_diffcache(::Union{AutoForwardDiff, AutoSparseForwardDiff}) = true __needs_diffcache(_) = false function __needs_diffcache(jac_alg::BVPJacobianAlgorithm) - return __needs_diffcache(jac_alg.diffmode) || __needs_diffcache(jac_alg.bc_diffmode) || + return __needs_diffcache(jac_alg.diffmode) || + __needs_diffcache(jac_alg.bc_diffmode) || __needs_diffcache(jac_alg.nonbc_diffmode) end diff --git a/src/utils.jl b/src/utils.jl index 67debb51..041f2c34 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -15,8 +15,8 @@ end end return y end -@views function recursive_flatten_twopoint!(y::AbstractVector, x::Vector{<:AbstractArray}, - sizes) +@views function recursive_flatten_twopoint!( + y::AbstractVector, x::Vector{<:AbstractArray}, sizes) x_, xiter = Iterators.peel(x) copyto!(y[1:prod(sizes[1])], x_[1:prod(sizes[1])]) i = prod(sizes[1]) @@ -85,16 +85,16 @@ function eval_bc_residual!(resid, pt, bc!::BC, sol, p) where {BC} return eval_bc_residual!(resid, pt, bc!, sol, p, sol.t) end eval_bc_residual!(resid, _, bc!::BC, sol, p, t) where {BC} = bc!(resid, sol, p, t) -@views function eval_bc_residual!(resid, ::TwoPointBVProblem, (bca!, bcb!)::BC, sol, p, - t) where {BC} +@views function eval_bc_residual!( + resid, ::TwoPointBVProblem, (bca!, bcb!)::BC, sol, p, t) where {BC} ua = sol isa AbstractVector ? sol[1] : sol(first(t)) ub = sol isa AbstractVector ? sol[end] : sol(last(t)) bca!(resid.resida, ua, p) bcb!(resid.residb, ub, p) return resid end -@views function eval_bc_residual!(resid::Tuple, ::TwoPointBVProblem, (bca!, bcb!)::BC, sol, - p, t) where {BC} +@views function eval_bc_residual!( + resid::Tuple, ::TwoPointBVProblem, (bca!, bcb!)::BC, sol, p, t) where {BC} ua = sol isa AbstractVector ? sol[1] : sol(first(t)) ub = sol isa AbstractVector ? sol[end] : sol(last(t)) bca!(resid[1], ua, p) @@ -132,15 +132,15 @@ function __extract_problem_details(prob, u0::AbstractVector{<:AbstractArray}; kw _u0 = first(u0) return Val(true), eltype(_u0), length(_u0), (length(u0) - 1), _u0 end -function __extract_problem_details(prob, u0::AbstractArray; dt = 0.0, - check_positive_dt::Bool = false) +function __extract_problem_details( + prob, u0::AbstractArray; dt = 0.0, check_positive_dt::Bool = false) # Problem does not have Initial Guess check_positive_dt && dt ≤ 0 && throw(ArgumentError("dt must be positive")) t₀, t₁ = prob.tspan return Val(false), eltype(u0), length(u0), Int(cld(t₁ - t₀, dt)), prob.u0 end -function __extract_problem_details(prob, f::F; dt = 0.0, - check_positive_dt::Bool = false) where {F <: Function} +function __extract_problem_details( + prob, f::F; dt = 0.0, check_positive_dt::Bool = false) where {F <: Function} # Problem passes in a initial guess function check_positive_dt && dt ≤ 0 && throw(ArgumentError("dt must be positive")) u0 = __initial_guess(f, prob.p, prob.tspan[1]) @@ -149,9 +149,9 @@ function __extract_problem_details(prob, f::F; dt = 0.0, end function __initial_guess(f::F, p::P, t::T) where {F, P, T} - if static_hasmethod(f, Tuple{P, T}) + if hasmethod(f, Tuple{P, T}) return f(p, t) - elseif static_hasmethod(f, Tuple{T}) + elseif hasmethod(f, Tuple{T}) Base.depwarn("initial guess function must take 2 inputs `(p, t)` instead of just \ `t`. The single argument version has been deprecated and will be \ removed in the next major release of SciMLBase.", @@ -256,12 +256,13 @@ end # Override the checks for NonlinearFunction struct __unsafe_nonlinearfunction{iip} end -@inline function __unsafe_nonlinearfunction{iip}(f::F; jac::J = nothing, - jac_prototype::JP = nothing, colorvec::CV = nothing, +@inline function __unsafe_nonlinearfunction{iip}( + f::F; jac::J = nothing, jac_prototype::JP = nothing, colorvec::CV = nothing, resid_prototype::RP = nothing) where {iip, F, J, JP, CV, RP} - return NonlinearFunction{iip, SciMLBase.FullSpecialize, F, Nothing, Nothing, Nothing, - J, Nothing, Nothing, JP, Nothing, Nothing, Nothing, Nothing, Nothing, CV, Nothing, - RP}(f, nothing, nothing, nothing, jac, nothing, nothing, jac_prototype, nothing, + return NonlinearFunction{ + iip, SciMLBase.FullSpecialize, F, Nothing, Nothing, Nothing, J, Nothing, + Nothing, JP, Nothing, Nothing, Nothing, Nothing, Nothing, CV, Nothing, RP}( + f, nothing, nothing, nothing, jac, nothing, nothing, jac_prototype, nothing, nothing, nothing, nothing, nothing, colorvec, nothing, resid_prototype) end @@ -269,8 +270,9 @@ end @inline __nameof(::Type{T}) where {T} = nameof(T) # Construct the internal NonlinearProblem -@inline function __internal_nlsolve_problem(::BVProblem{uType, tType, iip, nlls}, - resid_prototype, u0, args...; kwargs...) where {uType, tType, iip, nlls} +@inline function __internal_nlsolve_problem( + ::BVProblem{uType, tType, iip, nlls}, resid_prototype, + u0, args...; kwargs...) where {uType, tType, iip, nlls} if nlls return NonlinearLeastSquaresProblem(args...; kwargs...) else @@ -278,14 +280,16 @@ end end end -@inline function __internal_nlsolve_problem(bvp::BVProblem{uType, tType, iip, Nothing}, - resid_prototype, u0, args...; kwargs...) where {uType, tType, iip} - return __internal_nlsolve_problem(bvp, length(resid_prototype), length(u0), args...; - kwargs...) +@inline function __internal_nlsolve_problem( + bvp::BVProblem{uType, tType, iip, Nothing}, resid_prototype, + u0, args...; kwargs...) where {uType, tType, iip} + return __internal_nlsolve_problem( + bvp, length(resid_prototype), length(u0), args...; kwargs...) end -@inline function __internal_nlsolve_problem(::BVProblem{uType, tType, iip, Nothing}, - l1::Int, l2::Int, args...; kwargs...) where {uType, tType, iip} +@inline function __internal_nlsolve_problem( + ::BVProblem{uType, tType, iip, Nothing}, l1::Int, + l2::Int, args...; kwargs...) where {uType, tType, iip} if l1 != l2 return NonlinearLeastSquaresProblem(args...; kwargs...) else @@ -345,8 +349,8 @@ guess is supplied, it returns `-1`. Flattens the initial guess into a matrix. For a function `u₀`, it returns `nothing`. For no initial guess, it returns `vec(u₀)`. """ -@inline __flatten_initial_guess(u₀::AbstractVector{<:AbstractArray}) = mapreduce(vec, - hcat, u₀) +@inline __flatten_initial_guess(u₀::AbstractVector{<:AbstractArray}) = mapreduce( + vec, hcat, u₀) @inline __flatten_initial_guess(u₀::VectorOfArray) = mapreduce(vec, hcat, u₀.u) @inline __flatten_initial_guess(u₀::DiffEqArray) = mapreduce(vec, hcat, u₀.u) @inline __flatten_initial_guess(u₀::AbstractArray) = vec(u₀) @@ -361,8 +365,8 @@ as the mesh of the `DiffEqArray`. If `alias_u0` is set to `true`, we try our best to minimize copies. This means that `u₀` or parts of it will get mutated. """ -@inline function __initial_guess_on_mesh(u₀::AbstractVector{<:AbstractArray}, _, p, - alias_u0::Bool) +@inline function __initial_guess_on_mesh( + u₀::AbstractVector{<:AbstractArray}, _, p, alias_u0::Bool) return alias_u0 ? vec.(u₀) : [copy(vec(u)) for u in u₀] end @inline function __initial_guess_on_mesh(u₀::VectorOfArray, _, p, alias_u0::Bool) @@ -384,11 +388,12 @@ function __build_solution(prob::BVProblem, odesol, nlsol) return __solution_new_original_retcode(odesol, nlsol, retcode, nlsol.resid) end -function __solution_new_original_retcode(sol::ODESolution{T, N}, original, retcode, - resid) where {T, N} - return ODESolution{T, N, typeof(sol.u), typeof(sol.u_analytic), typeof(sol.errors), - typeof(sol.t), typeof(sol.k), typeof(sol.prob), typeof(sol.alg), typeof(sol.interp), - typeof(sol.stats), typeof(sol.alg_choice), typeof(resid), typeof(original)}(sol.u, - sol.u_analytic, sol.errors, sol.t, sol.k, sol.prob, sol.alg, sol.interp, sol.dense, - sol.tslocation, sol.stats, sol.alg_choice, retcode, resid, original) +function __solution_new_original_retcode( + sol::ODESolution{T, N}, original, retcode, resid) where {T, N} + return ODESolution{ + T, N, typeof(sol.u), typeof(sol.u_analytic), typeof(sol.errors), typeof(sol.t), + typeof(sol.k), typeof(sol.prob), typeof(sol.alg), typeof(sol.interp), + typeof(sol.stats), typeof(sol.alg_choice), typeof(resid), typeof(original)}( + sol.u, sol.u_analytic, sol.errors, sol.t, sol.k, sol.prob, sol.alg, sol.interp, + sol.dense, sol.tslocation, sol.stats, sol.alg_choice, retcode, resid, original) end diff --git a/test/mirk/ensemble.jl b/test/mirk/ensemble.jl index 5d9151b0..17cbde25 100644 --- a/test/mirk/ensemble.jl +++ b/test/mirk/ensemble.jl @@ -20,8 +20,8 @@ ensemble_prob = EnsembleProblem(bvp; prob_func) @testset "$(solver)" for solver in (MIRK2, MIRK3, MIRK4, MIRK5, MIRK6) jac_algs = [BVPJacobianAlgorithm(), - BVPJacobianAlgorithm(; bc_diffmode = AutoFiniteDiff(), - nonbc_diffmode = AutoSparseFiniteDiff())] + BVPJacobianAlgorithm(; + bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff())] for jac_alg in jac_algs sol = solve(ensemble_prob, solver(; jac_alg); trajectories = 10, dt = 0.1) @test sol.converged diff --git a/test/mirk/interpolation_test.jl b/test/mirk/interpolation_test.jl index be4d852d..2c445055 100644 --- a/test/mirk/interpolation_test.jl +++ b/test/mirk/interpolation_test.jl @@ -14,11 +14,11 @@ function prob_bvp_linear_bc!(res, u, p, t) res[1] = u[1][1] - 1 res[2] = u[end][1] end -prob_bvp_linear_function = ODEFunction(prob_bvp_linear_f!, - analytic = prob_bvp_linear_analytic) +prob_bvp_linear_function = ODEFunction( + prob_bvp_linear_f!, analytic = prob_bvp_linear_analytic) prob_bvp_linear_tspan = (0.0, 1.0) -prob_bvp_linear = BVProblem(prob_bvp_linear_function, prob_bvp_linear_bc!, - [1.0, 0.0], prob_bvp_linear_tspan, λ) +prob_bvp_linear = BVProblem( + prob_bvp_linear_function, prob_bvp_linear_bc!, [1.0, 0.0], prob_bvp_linear_tspan, λ) testTol = 1e-6 for order in (2, 3, 4, 5, 6) diff --git a/test/mirk/mirk_convergence_tests.jl b/test/mirk/mirk_convergence_tests.jl index c93b11b6..ce5a326d 100644 --- a/test/mirk/mirk_convergence_tests.jl +++ b/test/mirk/mirk_convergence_tests.jl @@ -42,34 +42,28 @@ odef1 = ODEFunction(f1, analytic = (u0, p, t) -> [5 - t, -1]) odef2! = ODEFunction(f2!, analytic = (u0, p, t) -> [ - 5 * (cos(t) - cot(5) * sin(t)), - 5 * (-cos(t) * cot(5) - sin(t)) - ]) + 5 * (cos(t) - cot(5) * sin(t)), 5 * (-cos(t) * cot(5) - sin(t))]) odef2 = ODEFunction(f2, analytic = (u0, p, t) -> [ - 5 * (cos(t) - cot(5) * sin(t)), - 5 * (-cos(t) * cot(5) - sin(t)) - ]) + 5 * (cos(t) - cot(5) * sin(t)), 5 * (-cos(t) * cot(5) - sin(t))]) bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) tspan = (0.0, 5.0) u0 = [5.0, -3.5] -probArr = [ - BVProblem(odef1!, boundary!, u0, tspan), +probArr = [BVProblem(odef1!, boundary!, u0, tspan), BVProblem(odef1, boundary, u0, tspan), BVProblem(odef2!, boundary!, u0, tspan), BVProblem(odef2, boundary, u0, tspan), - TwoPointBVProblem(odef1!, (boundary_two_point_a!, boundary_two_point_b!), u0, tspan; - bcresid_prototype), - TwoPointBVProblem(odef1, (boundary_two_point_a, boundary_two_point_b), u0, tspan; - bcresid_prototype), - TwoPointBVProblem(odef2!, (boundary_two_point_a!, boundary_two_point_b!), u0, tspan; - bcresid_prototype), - TwoPointBVProblem(odef2, (boundary_two_point_a, boundary_two_point_b), u0, tspan; - bcresid_prototype) -]; + TwoPointBVProblem(odef1!, (boundary_two_point_a!, boundary_two_point_b!), + u0, tspan; bcresid_prototype), + TwoPointBVProblem( + odef1, (boundary_two_point_a, boundary_two_point_b), u0, tspan; bcresid_prototype), + TwoPointBVProblem(odef2!, (boundary_two_point_a!, boundary_two_point_b!), + u0, tspan; bcresid_prototype), + TwoPointBVProblem( + odef2, (boundary_two_point_a, boundary_two_point_b), u0, tspan; bcresid_prototype)]; testTol = 0.2 affineTol = 1e-2 @@ -89,8 +83,8 @@ end @testset "Problem: $i" for i in (3, 4, 7, 8) prob = probArr[i] @testset "MIRK$order" for (i, order) in enumerate((2, 3, 4, 5, 6)) - @time sim = test_convergence(dts, prob, mirk_solver(Val(order)); - abstol = 1e-8, reltol = 1e-8) + @time sim = test_convergence( + dts, prob, mirk_solver(Val(order)); abstol = 1e-8, reltol = 1e-8) @test sim.𝒪est[:final]≈order atol=testTol end end @@ -115,8 +109,8 @@ end u0 = MVector{2}([pi / 2, pi / 2]) bvp1 = BVProblem(simplependulum!, bc_pendulum!, u0, tspan) -jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoFiniteDiff(), - nonbc_diffmode = AutoSparseFiniteDiff()) +jac_alg = BVPJacobianAlgorithm(; + bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff()) # Using ForwardDiff might lead to Cache expansion warnings @test_nowarn solve(bvp1, MIRK2(; jac_alg); dt = 0.005) diff --git a/test/mirk/nonlinear_least_squares.jl b/test/mirk/nonlinear_least_squares.jl index d3a69aa5..d50d4633 100644 --- a/test/mirk/nonlinear_least_squares.jl +++ b/test/mirk/nonlinear_least_squares.jl @@ -76,8 +76,8 @@ using BoundaryValueDiffEq, LinearAlgebra, Test tspan) for solver in SOLVERS - @time sol = solve(bvp3, solver; verbose = false, dt = 1.0, abstol = 1e-3, - reltol = 1e-3) + @time sol = solve( + bvp3, solver; verbose = false, dt = 1.0, abstol = 1e-3, reltol = 1e-3) resida = Array{Float64}(undef, 1) residb = Array{Float64}(undef, 2) bc1a!(resida, sol(0.0), nothing) diff --git a/test/mirk/vectorofvector_initials.jl b/test/mirk/vectorofvector_initials.jl index 79df5db7..ec46f4dc 100644 --- a/test/mirk/vectorofvector_initials.jl +++ b/test/mirk/vectorofvector_initials.jl @@ -21,7 +21,8 @@ qht = 2.5 #System functions function f(v, h, r) - -(glb * (v - el) + gnab * (1 / (1 + exp(-(v + 37) / 7)))^3 * h * (v - ena) + + -(glb * (v - el) + + gnab * (1 / (1 + exp(-(v + 37) / 7)))^3 * h * (v - ena) + gkb * (0.75 * (1 - h))^4 * (v - ek) + gtb * (1 / (1 + exp(-(v + 60) / 6.2)))^2 * r * (v - et)) - gex * ss * (v - vex) - gsyn * sj * (v - vsyn) + iext diff --git a/test/misc/non_vector_inputs.jl b/test/misc/non_vector_inputs.jl index 101ea232..3ea5ff5d 100644 --- a/test/misc/non_vector_inputs.jl +++ b/test/misc/non_vector_inputs.jl @@ -35,13 +35,11 @@ boundary_b = (ub, p) -> [ub[1, 1]] tspan = (0.0, 5.0) u0 = [5.0 -3.5] -probs = [ - BVProblem(f1!, boundary!, u0, tspan), +probs = [BVProblem(f1!, boundary!, u0, tspan), TwoPointBVProblem(f1!, (boundary_a!, boundary_b!), u0, tspan; bcresid_prototype = (Array{Float64}(undef, 1, 1), Array{Float64}(undef, 1, 1))), BVProblem(f1, boundary, u0, tspan), - TwoPointBVProblem(f1, (boundary_a, boundary_b), u0, tspan) -]; + TwoPointBVProblem(f1, (boundary_a, boundary_b), u0, tspan)]; @testset "Affineness" begin @testset "MIRK$order" for order in (2, 3, 4, 5, 6) diff --git a/test/misc/odeinterface_wrapper.jl b/test/misc/odeinterface_wrapper.jl index 84c2fee8..78bc00c7 100644 --- a/test/misc/odeinterface_wrapper.jl +++ b/test/misc/odeinterface_wrapper.jl @@ -24,8 +24,8 @@ u0 = [0.5, 1.0] p = [0.1] tspan = (-π / 2, π / 2) -tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) +tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, + p; bcresid_prototype = (zeros(1), zeros(1))) @testset "BVPM2" begin @info "Testing BVPM2" @@ -50,8 +50,8 @@ sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); @info "BVPSOL with Vector{<:AbstractArray}" initial_u0 = [sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, + tspan, p; bcresid_prototype = (zeros(1), zeros(1))) # Just test that it runs. BVPSOL only works with linearly separable BCs. sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) @@ -59,8 +59,8 @@ sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); @info "BVPSOL with VectorOfArray" initial_u0 = VectorOfArray([sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, + tspan, p; bcresid_prototype = (zeros(1), zeros(1))) # Just test that it runs. BVPSOL only works with linearly separable BCs. sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) @@ -69,8 +69,8 @@ sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); ts = collect(tspan[1]:(π / 20):tspan[2]) initial_u0 = DiffEqArray([sol_ms(t) .+ rand() for t in ts], ts) - tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; - bcresid_prototype = (zeros(1), zeros(1))) + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, + tspan, p; bcresid_prototype = (zeros(1), zeros(1))) sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) diff --git a/test/runtests.jl b/test/runtests.jl index 3366d4eb..8ba7978a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,64 +1,3 @@ -using Test, SafeTestsets +using ReTestItems -const GROUP = uppercase(get(ENV, "GROUP", "ALL")) - -@testset "Boundary Value Problem Tests" begin - if GROUP == "ALL" || GROUP == "SHOOTING" - @time @testset "Shooting Method Tests" begin - @time @safetestset "Basic Problems" begin - include("shooting/basic_problems.jl") - end - @time @safetestset "Orbital" begin - include("shooting/orbital.jl") - end - @time @safetestset "Shooting NLLS Tests" begin - include("shooting/nonlinear_least_squares.jl") - end - end - end - - if GROUP == "ALL" || GROUP == "MIRK" - @time @testset "Collocation Method (MIRK) Tests" begin - @time @safetestset "Ensemble" begin - include("mirk/ensemble.jl") - end - @time @safetestset "MIRK Convergence Tests" begin - include("mirk/mirk_convergence_tests.jl") - end - @time @safetestset "Vector of Vector" begin - include("mirk/vectorofvector_initials.jl") - end - @time @safetestset "Interpolation Tests" begin - include("mirk/interpolation_test.jl") - end - if VERSION ≥ v"1.10-" - @time @safetestset "MIRK NLLS Tests" begin - include("mirk/nonlinear_least_squares.jl") - end - end - end - end - - if GROUP == "ALL" || GROUP == "OTHERS" - @time @testset "Miscelleneous" begin - @time @safetestset "Non Vector Inputs" begin - include("misc/non_vector_inputs.jl") - end - @time @safetestset "Type Stability" begin - include("misc/type_stability.jl") - end - @time @safetestset "ODE Interface Tests" begin - include("misc/odeinterface_wrapper.jl") - end - @time @safetestset "Initial Guess Function" begin - include("misc/initial_guess.jl") - end - @time @safetestset "Affine Geodesic" begin - include("misc/affine_geodesic.jl") - end - @time @safetestset "Aqua: Quality Assurance" begin - include("misc/aqua.jl") - end - end - end -end +ReTestItems.runtests(@__DIR__) diff --git a/test/shooting/basic_problems.jl b/test/shooting/basic_problems_tests.jl similarity index 71% rename from test/shooting/basic_problems.jl rename to test/shooting/basic_problems_tests.jl index 83f426fe..60c1d265 100644 --- a/test/shooting/basic_problems.jl +++ b/test/shooting/basic_problems_tests.jl @@ -1,21 +1,18 @@ -using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET +@testitem "Basic Shooting" begin + using LinearAlgebra, LinearSolve, JET -@testset "Basic Shooting Tests" begin - SOLVERS = [ - Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), + SOLVERS = [Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), Shooting(Tsit5(), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5()), MultipleShooting(10, Tsit5(), NewtonRaphson(; autodiff = AutoFiniteDiff())), - MultipleShooting(10, Tsit5(), - NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5()) - ] + MultipleShooting( + 10, Tsit5(), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5())] JET_SKIP = [false, false, true, false, false, true] JET_BROKEN = [false, false, false, false, false, false] tspan = (0.0, 100.0) u0 = [0.0, 1.0] - # Inplace function f1!(du, u, p, t) du[1] = u[2] @@ -30,25 +27,24 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET return nothing end - @info "Basic MP Shooting IIP" - bvp1 = BVProblem(f1!, bc1!, u0, tspan) @test SciMLBase.isinplace(bvp1) for (i, solver) in enumerate(SOLVERS) - @info "Solver: $solver" - sol = @time solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, + sol = solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-8 JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp1, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp1, solver; abstol = 1e-8, reltol = 1e-8, + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp1, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] end @@ -63,25 +59,24 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1!, bc1, u0, tspan) @test_throws SciMLBase.NonconformingFunctionsError BVProblem(f1, bc1!, u0, tspan) - @info "Basic MP Shooting OOP" - bvp2 = BVProblem(f1, bc1, u0, tspan) @test !SciMLBase.isinplace(bvp2) for (i, solver) in enumerate(SOLVERS) - @info "Solver: $solver" - sol = @time solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, + sol = solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-8 JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp2, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp2, solver; abstol = 1e-8, reltol = 1e-8, + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp2, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] end @@ -89,26 +84,25 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET bc2a!(resid, ua, p) = (resid[1] = ua[1]) bc2b!(resid, ub, p) = (resid[1] = ub[1] - 1) - @info "Basic TP Shooting IIP" - bvp3 = TwoPointBVProblem(f1!, (bc2a!, bc2b!), u0, tspan; bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1))) @test SciMLBase.isinplace(bvp3) for (i, solver) in enumerate(SOLVERS) - @info "Solver: $solver" - sol = @time solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, + sol = solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-8 JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp3, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp3, solver; abstol = 1e-8, reltol = 1e-8, + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp3, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] end @@ -116,36 +110,35 @@ using BoundaryValueDiffEq, LinearAlgebra, LinearSolve, OrdinaryDiffEq, Test, JET bc2a(ua, p) = [ua[1]] bc2b(ub, p) = [ub[1] - 1] - @info "Basic TP Shooting OOP" - bvp4 = TwoPointBVProblem(f1, (bc2a, bc2b), u0, tspan) @test !SciMLBase.isinplace(bvp4) for (i, solver) in enumerate(SOLVERS) - @info "Solver: $solver" - sol = @time solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, + sol = solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-8 JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp4, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp4, solver; abstol = 1e-8, reltol = 1e-8, + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp4, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3)) broken=JET_BROKEN[i] end end -@testset "Shooting with Complex Values" begin +@testitem "Shooting with Complex Values" begin + using LinearAlgebra, LinearSolve + SOLVERS = [ - Shooting(Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), - Shooting(Vern7()), + Shooting(Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), Shooting(Vern7()), MultipleShooting(10, Vern7(), NewtonRaphson(; autodiff = AutoFiniteDiff())), - MultipleShooting(10, Vern7()) - ] + MultipleShooting(10, Vern7())] function f1!(du, u, p, t) du[1] = u[2] @@ -164,11 +157,8 @@ end u0 = [0.0, 1.0] .+ 1im bvp = BVProblem(f1!, bc1!, u0, tspan) - @info "Shooting with Complex Values" - for (i, solver) in enumerate(SOLVERS) - @info "Solver: $solver" - sol = @time solve(bvp, solver; abstol = 1e-8, reltol = 1e-8, + sol = solve(bvp, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-3), maxiters = 10000) @test SciMLBase.successful_retcode(sol) @@ -176,7 +166,9 @@ end end end -@testset "Flow In a Channel" begin +@testitem "Flow in a Channel" begin + using LinearAlgebra, LinearSolve + function flow_in_a_channel!(du, u, p, t) R, P = p A, f′′, f′, f, h′, h, θ′, θ = u @@ -210,16 +202,12 @@ end flow_bvp = BVProblem{true}(flow_in_a_channel!, bc_flow!, u0, tspan, p) - @info "Flow in a Channel" - for solver in [ Shooting(AutoTsit5(Rosenbrock23()), NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))), MultipleShooting(10, AutoTsit5(Rosenbrock23()), - NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8))) - ] - @info "Solver: $solver" - sol = @time solve(flow_bvp, solver; abstol = 1e-8, reltol = 1e-8, + NewtonRaphson(; autodiff = AutoForwardDiff(; chunksize = 8)))] + sol = solve(flow_bvp, solver; abstol = 1e-8, reltol = 1e-8, odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-8)) @test SciMLBase.successful_retcode(sol) @@ -227,7 +215,9 @@ end end end -@testset "Ray Tracing" begin +@testitem "Ray Tracing" begin + using LinearAlgebra, LinearSolve + @inline v(x, y, z, p) = 1 / (4 + cos(p[1] * x) + sin(p[2] * y) - cos(p[3] * z)) @inline ux(x, y, z, p) = -p[1] * sin(p[1] * x) @inline uy(x, y, z, p) = p[2] * cos(p[2] * y) @@ -329,42 +319,42 @@ end tspan = (0.0, 1.0) - prob_oop = BVProblem(BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; - nlls = Val(false)) - prob_iip = BVProblem(BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; - nlls = Val(true)) + prob_oop = BVProblem( + BVPFunction{false}(ray_tracing, ray_tracing_bc), u0, tspan, p; nlls = Val(false)) + prob_iip = BVProblem( + BVPFunction{true}(ray_tracing!, ray_tracing_bc!), u0, tspan, p; nlls = Val(true)) prob_tp_oop = BVProblem( - BVPFunction{false}(ray_tracing, - (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), + BVPFunction{false}( + ray_tracing, (ray_tracing_bc_a, ray_tracing_bc_b); twopoint = Val(true)), u0, tspan, p; nlls = Val(true)) prob_tp_iip = BVProblem( - BVPFunction{true}(ray_tracing!, - (ray_tracing_bc_a!, ray_tracing_bc_b!); + BVPFunction{true}(ray_tracing!, (ray_tracing_bc_a!, ray_tracing_bc_b!); bcresid_prototype = (zeros(5), zeros(3)), twopoint = Val(true)), u0, tspan, p; nlls = Val(true)) - @info "Ray Tracing: Multiple Shooting" - - alg_sp = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, + alg_sp = MultipleShooting(10, + AutoVern7(Rodas4P()); + grid_coarsening = true, nlsolve = TrustRegion(), jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 8))) - alg_dense = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true, + alg_dense = MultipleShooting(10, + AutoVern7(Rodas4P()); + grid_coarsening = true, nlsolve = TrustRegion(), jac_alg = BVPJacobianAlgorithm(; bc_diffmode = AutoForwardDiff(; chunksize = 8), nonbc_diffmode = AutoForwardDiff(; chunksize = 8))) alg_default = MultipleShooting(10, AutoVern7(Rodas4P()); grid_coarsening = true) - for (prob, alg) in Iterators.product((prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), - (alg_sp, alg_dense, alg_default)) - @info "Solver: $alg" - @time sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, + for (prob, alg) in Iterators.product( + (prob_oop, prob_iip, prob_tp_oop, prob_tp_iip), (alg_sp, alg_dense, alg_default)) + sol = solve(prob, alg; abstol = 1e-6, reltol = 1e-6, maxiters = 1000, odesolve_kwargs = (; abstol = 1e-8, reltol = 1e-5)) @test SciMLBase.successful_retcode(sol.retcode) diff --git a/test/shooting/nlls_tests.jl b/test/shooting/nlls_tests.jl new file mode 100644 index 00000000..620a15c3 --- /dev/null +++ b/test/shooting/nlls_tests.jl @@ -0,0 +1,154 @@ +# FIXME: The nonlinear solve polyalgorithm for NLLS is currently broken because of Bastin +# Jv & Jᵀv computation with the cached ODE solve +@testitem "Overconstrained BVP" begin + using LinearAlgebra, JET + + SOLVERS = [ + # Shooting(Tsit5()), + Shooting( + Tsit5(), LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting( + Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), + Shooting(Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), + Shooting(Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), + # MultipleShooting(10, Tsit5()), + MultipleShooting( + 10, Tsit5(), LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), MultipleShooting( + 10, Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), + MultipleShooting( + 10, Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), + MultipleShooting( + 10, Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff()))] + JET_SKIP = fill(false, length(SOLVERS)) + JET_BROKEN = fill(false, length(SOLVERS)) + + # OOP MP-BVP + f1(u, p, t) = [u[2], -u[1]] + + function bc1(sol, p, t) + t₁, t₂ = extrema(t) + solₜ₁ = sol(t₁) + solₜ₂ = sol(t₂) + solₜ₃ = sol((t₁ + t₂) / 2) + # We know that this overconstrained system has a solution + return [solₜ₁[1], solₜ₂[1] - 1, solₜ₃[1] - 0.51735, solₜ₃[2] + 1.92533] + end + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] + + bvp1 = BVProblem(BVPFunction{false}(f1, bc1; bcresid_prototype = zeros(4)), + u0, tspan; nlls = Val(true)) + + for (i, solver) in enumerate(SOLVERS) + sol = solve(bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.005 + + JET_SKIP[i] && continue + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + end + + # IIP MP-BVP + function f1!(du, u, p, t) + du[1] = u[2] + du[2] = -u[1] + return nothing + end + + function bc1!(resid, sol, p, t) + (t₁, t₂) = extrema(t) + solₜ₁ = sol(t₁) + solₜ₂ = sol(t₂) + solₜ₃ = sol((t₁ + t₂) / 2) + # We know that this overconstrained system has a solution + resid[1] = solₜ₁[1] + resid[2] = solₜ₂[1] - 1 + resid[3] = solₜ₃[1] - 0.51735 + resid[4] = solₜ₃[2] + 1.92533 + return nothing + end + + bvp2 = BVProblem(BVPFunction{true}(f1!, bc1!; bcresid_prototype = zeros(4)), + u0, tspan; nlls = Val(true)) + + for (i, solver) in enumerate(SOLVERS) + sol = solve(bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.005 + + JET_SKIP[i] && continue + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + end + + # OOP TP-BVP + bc1a(ua, p) = [ua[1]] + bc1b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] + + bvp3 = BVProblem( + BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), + bcresid_prototype = (zeros(1), zeros(2))), + u0, + tspan; + nlls = Val(true)) + + for (i, solver) in enumerate(SOLVERS) + sol = solve(bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.009 + + JET_SKIP[i] && continue + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + end + + # IIP TP-BVP + bc1a!(resid, ua, p) = (resid[1] = ua[1]) + bc1b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) + + bvp4 = BVProblem( + BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), + bcresid_prototype = (zeros(1), zeros(2))), + u0, + tspan; + nlls = Val(true)) + + for (i, solver) in enumerate(SOLVERS) + sol = solve(bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) + @test norm(sol.resid, Inf) < 0.009 + + JET_SKIP[i] && continue + @test_opt target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + @test_call target_modules=( + SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( + bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + end +end diff --git a/test/shooting/nonlinear_least_squares.jl b/test/shooting/nonlinear_least_squares.jl deleted file mode 100644 index f073043b..00000000 --- a/test/shooting/nonlinear_least_squares.jl +++ /dev/null @@ -1,153 +0,0 @@ -using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test, JET - -# NOTE: The nonlinear solve polyalgorithm for NLLS is currently broken because of Bastin -# Jv & Jᵀv computation with the cached ODE solve -@testset "Overconstrained BVP" begin - SOLVERS = [ - # Shooting(Tsit5()), - Shooting(Tsit5(), - LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), - Shooting(Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), - Shooting(Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), - Shooting(Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), - Shooting(Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), - Shooting(Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), - # MultipleShooting(10, Tsit5()), - MultipleShooting(10, Tsit5(), - LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), - MultipleShooting(10, Tsit5(), - GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), - MultipleShooting(10, Tsit5(), - TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), - MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())) - ] - JET_SKIP = [false, false, false, false, false, false, false, false, false, false] - JET_BROKEN = [false, false, false, false, false, false, false, false, false, false] - - @info "Solving Overconstrained BVPs" - - # OOP MP-BVP - f1(u, p, t) = [u[2], -u[1]] - - function bc1(sol, p, t) - t₁, t₂ = extrema(t) - solₜ₁ = sol(t₁) - solₜ₂ = sol(t₂) - solₜ₃ = sol((t₁ + t₂) / 2) - # We know that this overconstrained system has a solution - return [solₜ₁[1], solₜ₂[1] - 1, solₜ₃[1] - 0.51735, solₜ₃[2] + 1.92533] - end - - tspan = (0.0, 100.0) - u0 = [0.0, 1.0] - - bvp1 = BVProblem(BVPFunction{false}(f1, bc1; bcresid_prototype = zeros(4)), u0, tspan; - nlls = Val(true)) - - for (i, solver) in enumerate(SOLVERS) - @info "Testing $solver" - sol = @time solve(bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) - @test norm(sol.resid, Inf) < 0.005 - - JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp1, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp1, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - end - - # IIP MP-BVP - function f1!(du, u, p, t) - du[1] = u[2] - du[2] = -u[1] - return nothing - end - - function bc1!(resid, sol, p, t) - (t₁, t₂) = extrema(t) - solₜ₁ = sol(t₁) - solₜ₂ = sol(t₂) - solₜ₃ = sol((t₁ + t₂) / 2) - # We know that this overconstrained system has a solution - resid[1] = solₜ₁[1] - resid[2] = solₜ₂[1] - 1 - resid[3] = solₜ₃[1] - 0.51735 - resid[4] = solₜ₃[2] + 1.92533 - return nothing - end - - bvp2 = BVProblem(BVPFunction{true}(f1!, bc1!; bcresid_prototype = zeros(4)), u0, tspan; - nlls = Val(true)) - - for (i, solver) in enumerate(SOLVERS) - @info "Testing $solver" - sol = @time solve(bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) - @test norm(sol.resid, Inf) < 0.005 - - JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp2, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp2, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - end - - # OOP TP-BVP - bc1a(ua, p) = [ua[1]] - bc1b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - - bvp3 = BVProblem( - BVPFunction{false}(f1, (bc1a, bc1b); twopoint = Val(true), - bcresid_prototype = (zeros(1), zeros(2))), - u0, - tspan; - nlls = Val(true)) - - for (i, solver) in enumerate(SOLVERS) - @info "Testing $solver" - sol = @time solve(bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) - @test norm(sol.resid, Inf) < 0.009 - - JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp3, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp3, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - end - - # IIP TP-BVP - bc1a!(resid, ua, p) = (resid[1] = ua[1]) - bc1b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - - bvp4 = BVProblem( - BVPFunction{true}(f1!, (bc1a!, bc1b!); twopoint = Val(true), - bcresid_prototype = (zeros(1), zeros(2))), - u0, - tspan; - nlls = Val(true)) - - for (i, solver) in enumerate(SOLVERS) - @info "Testing $solver" - sol = @time solve(bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) - @test norm(sol.resid, Inf) < 0.009 - - JET_SKIP[i] && continue - @test_opt target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp4, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - @test_call target_modules=(SciMLBase, DiffEqBase, NonlinearSolve, - BoundaryValueDiffEq) solve(bvp4, solver; verbose = false, abstol = 1e-6, - reltol = 1e-6, odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] - end -end diff --git a/test/shooting/orbital.jl b/test/shooting/orbital_tests.jl similarity index 53% rename from test/shooting/orbital.jl rename to test/shooting/orbital_tests.jl index 3785eb52..26cf2f86 100644 --- a/test/shooting/orbital.jl +++ b/test/shooting/orbital_tests.jl @@ -1,22 +1,10 @@ -using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test +@testitem "Lambert's Problem" begin + using LinearAlgebra -@testset "Lambert's Problem" begin - y0 = [ - -4.7763169762853989E+06, - -3.8386398704441520E+05, - -5.3500183933132319E+06, - -5528.612564911408, - 1216.8442360202787, - 4845.114446429901 - ] - init_val = [ - -4.7763169762853989E+06, - -3.8386398704441520E+05, - -5.3500183933132319E+06, - 7.0526926403748598E+06, - -7.9650476230388973E+05, - -1.1911128863666430E+06 - ] + y0 = [-4.7763169762853989E+06, -3.8386398704441520E+05, -5.3500183933132319E+06, + -5528.612564911408, 1216.8442360202787, 4845.114446429901] + init_val = [-4.7763169762853989E+06, -3.8386398704441520E+05, -5.3500183933132319E+06, + 7.0526926403748598E+06, -7.9650476230388973E+05, -1.1911128863666430E+06] J2 = 1.08262668E-3 req = 6378137 myu = 398600.4418E+9 @@ -62,61 +50,50 @@ using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test cur_bc_2point_a! = (resid, sol, p) -> bc!_generator_2p_a(resid, sol, init_val) cur_bc_2point_b! = (resid, sol, p) -> bc!_generator_2p_b(resid, sol, init_val) - @info "Solving Lambert's Problem in Multi Point BVP Form" - bvp = BVProblem(orbital!, cur_bc!, y0, tspan; nlls = Val(false)) - for autodiff in (AutoForwardDiff(; chunksize = 6), - AutoFiniteDiff(; fdtype = Val(:central)), AutoSparseForwardDiff(; chunksize = 6), + for autodiff in ( + AutoForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:central)), + AutoSparseForwardDiff(; chunksize = 6), AutoFiniteDiff(; fdtype = Val(:forward)), AutoSparseFiniteDiff()) nlsolve = TrustRegion(; autodiff) - @info "Single Shooting Lambert's Problem: $(autodiff)" - @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, - reltol = 1e-6, verbose = false, - odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + sol = solve( + bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, reltol = 1e-6, + verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - @info "Single Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-6 - @info "Multiple Shooting Lambert's Problem: $(autodiff)" jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, bc_diffmode = BoundaryValueDiffEq.__get_non_sparse_ad(autodiff)) - @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); - force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, - odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); + force_dtmin = true, abstol = 1e-6, reltol = 1e-6, + verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - @info "Multiple Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-6 end - @info "Solving Lambert's Problem in Two Point BVP Form" - bvp = TwoPointBVProblem(orbital!, (cur_bc_2point_a!, cur_bc_2point_b!), y0, tspan; bcresid_prototype = (Array{Float64}(undef, 3), Array{Float64}(undef, 3)), nlls = Val(false)) for autodiff in (AutoForwardDiff(; chunksize = 6), AutoSparseFiniteDiff(), - AutoFiniteDiff(; fdtype = Val(:central)), AutoFiniteDiff(; fdtype = Val(:forward)), - AutoSparseForwardDiff(; chunksize = 6)) + AutoFiniteDiff(; fdtype = Val(:central)), + AutoFiniteDiff(; fdtype = Val(:forward)), AutoSparseForwardDiff(; chunksize = 6)) nlsolve = TrustRegion(; autodiff) - @info "Single Shooting Lambert's Problem: $(autodiff)" - @time sol = solve(bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, - reltol = 1e-6, verbose = false, - odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + sol = solve( + bvp, Shooting(DP5(); nlsolve); force_dtmin = true, abstol = 1e-6, reltol = 1e-6, + verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - @info "Single Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-6 - @info "Multiple Shooting Lambert's Problem: $(autodiff)" jac_alg = BVPJacobianAlgorithm(; nonbc_diffmode = autodiff, bc_diffmode = autodiff) - @time sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); - force_dtmin = true, abstol = 1e-6, reltol = 1e-6, verbose = false, - odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) + sol = solve(bvp, MultipleShooting(10, DP5(); nlsolve, jac_alg); + force_dtmin = true, abstol = 1e-6, reltol = 1e-6, + verbose = false, odesolve_kwargs = (abstol = 1e-6, reltol = 1e-3)) - @info "Multiple Shooting Lambert's Problem: $(norm(sol.resid, Inf))" @test SciMLBase.successful_retcode(sol) @test norm(sol.resid, Inf) < 1e-6 end From 09569853f0c32f1aabb3d9310e33b1ccb71084a5 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Wed, 20 Mar 2024 18:12:52 -0400 Subject: [PATCH 10/24] fixing... --- Manifest.toml | 8 +- Project.toml | 3 +- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 5 +- src/BoundaryValueDiffEq.jl | 1 - src/adaptivity.jl | 22 +-- src/algorithms.jl | 72 +++++--- src/collocation.jl | 4 +- src/interpolation.jl | 4 +- src/solve/mirk.jl | 205 ++++++++++++---------- src/solve/multiple_shooting.jl | 14 +- src/utils.jl | 28 ++- test/mirk/mirk_convergence_tests.jl | 92 +++++----- test/misc/aqua.jl | 6 - test/misc/qa_tests.jl | 6 + 14 files changed, 251 insertions(+), 219 deletions(-) delete mode 100644 test/misc/aqua.jl create mode 100644 test/misc/qa_tests.jl diff --git a/Manifest.toml b/Manifest.toml index e3102b94..58c0999d 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.10.2" manifest_format = "2.0" -project_hash = "057fc02bc93810bdc11a7df500e348b3fae4963b" +project_hash = "a953673b82afa1e31012434ca17ab0a1861c936d" [[deps.ADTypes]] git-tree-sha1 = "016833eb52ba2d6bea9fcb50ca295980e728ee24" @@ -607,7 +607,7 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "d52bac2b94358b4b960cbfb896d5193d67f3ff09" +path = "../NonlinearSolve.jl" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" version = "3.8.0" @@ -808,9 +808,7 @@ version = "0.6.42" [[deps.SciMLBase]] deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "0e4fca3dd5de4d4a82c0ffae1e51ab6234af4df0" -repo-rev = "ap/nlls_bvp" -repo-url = "https://github.com/SciML/SciMLBase.jl.git" +path = "../SciMLBase.jl" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" version = "2.30.1" diff --git a/Project.toml b/Project.toml index 20919913..2307c8d6 100644 --- a/Project.toml +++ b/Project.toml @@ -25,7 +25,6 @@ SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" [weakdeps] ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" @@ -55,6 +54,7 @@ PreallocationTools = "0.4" PrecompileTools = "1" Preferences = "1" Random = "1" +ReTestItems = "1.23.1" RecursiveArrayTools = "3" Reexport = "1.0" SciMLBase = "2.12" @@ -63,7 +63,6 @@ SparseArrays = "1.9" SparseDiffTools = "2.9" StaticArrays = "1.8.1" Test = "1" -UnPack = "1" julia = "1.10" [extras] diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 95241775..06fb822d 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -3,7 +3,6 @@ module BoundaryValueDiffEqODEInterfaceExt using SciMLBase, BoundaryValueDiffEq, ODEInterface, RecursiveArrayTools import BoundaryValueDiffEq: __extract_u0, __flatten_initial_guess, __extract_mesh, __initial_guess_length, __initial_guess, __has_initial_guess -import SciMLBase: __solve import ODEInterface: OptionsODE, OPT_ATOL, OPT_RTOL, OPT_METHODCHOICE, OPT_DIAGNOSTICOUTPUT, OPT_ERRORCONTROL, OPT_SINGULARTERM, OPT_MAXSTEPS, OPT_BVPCLASS, OPT_SOLMETHOD, OPT_RHS_CALLMODE, OPT_COLLOCATIONPTS, @@ -26,7 +25,7 @@ end #------ # BVPM2 #------ -function __solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs...) +function SciMLBase.__solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, kwargs...) if !(prob.problem_type isa TwoPointBVProblem) throw(ArgumentError("`BVPM2` only supports `TwoPointBVProblem!`")) end @@ -105,7 +104,7 @@ end #------- # BVPSOL #------- -function __solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, +function SciMLBase.__solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, reltol = 1e-3, dt = 0.0, verbose = true, kwargs...) if !(prob.problem_type isa TwoPointBVProblem) throw(ArgumentError("`BVPSOL` only supports `TwoPointBVProblem!`")) diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index e445252d..67f2d8ce 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -20,7 +20,6 @@ import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidat import RecursiveArrayTools: ArrayPartition, DiffEqArray import SciMLBase: AbstractDiffEqInterpolation, StandardBVProblem, __solve, _unwrap_val import SparseDiffTools: AbstractSparseADType - import UnPack: @unpack end @reexport using ADTypes, DiffEqBase, NonlinearSolve, OrdinaryDiffEq, SparseDiffTools, diff --git a/src/adaptivity.jl b/src/adaptivity.jl index 761fc176..3665c896 100644 --- a/src/adaptivity.jl +++ b/src/adaptivity.jl @@ -27,7 +27,7 @@ end Generate new mesh based on the defect. """ @views function mesh_selector!(cache::MIRKCache{iip, T}) where {iip, T} - @unpack M, order, defect, mesh, mesh_dt = cache + (; M, order, defect, mesh, mesh_dt) = cache (_, MxNsub, abstol, _, _), kwargs = __split_mirk_kwargs(; cache.kwargs...) N = length(cache.mesh) @@ -144,8 +144,8 @@ the RK method in 'k_discrete', plus some new stages in 'k_interp' to construct an interpolant """ @views function defect_estimate!(cache::MIRKCache{iip, T}) where {iip, T} - @unpack M, stage, f, alg, mesh, mesh_dt, defect = cache - @unpack s_star, τ_star = cache.ITU + (; M, stage, f, alg, mesh, mesh_dt, defect) = cache + (; s_star, τ_star) = cache.ITU # Evaluate at the first sample point w₁, w₁′ = interp_weights(τ_star, alg) @@ -190,8 +190,8 @@ end Here, the ki_interp is the stages in one subinterval. """ @views function interp_setup!(cache::MIRKCache{iip, T}) where {iip, T} - @unpack x_star, s_star, c_star, v_star = cache.ITU - @unpack k_interp, k_discrete, f, stage, new_stages, y, p, mesh, mesh_dt = cache + (; x_star, s_star, c_star, v_star) = cache.ITU + (; k_interp, k_discrete, f, stage, new_stages, y, p, mesh, mesh_dt) = cache for r in 1:(s_star - stage) idx₁ = ((1:stage) .- 1) .* (s_star - stage) .+ r @@ -230,8 +230,8 @@ function sum_stages!(cache::MIRKCache, w, w′, i::Int, dt = cache.mesh_dt[i]) end function sum_stages!(z::AbstractArray, cache::MIRKCache, w, i::Int, dt = cache.mesh_dt[i]) - @unpack M, stage, mesh, k_discrete, k_interp, mesh_dt = cache - @unpack s_star = cache.ITU + (; M, stage, mesh, k_discrete, k_interp, mesh_dt) = cache + (; s_star) = cache.ITU z .= zero(z) __maybe_matmul!(z, k_discrete[i].du[:, 1:stage], w[1:stage]) @@ -243,8 +243,8 @@ function sum_stages!(z::AbstractArray, cache::MIRKCache, w, i::Int, dt = cache.m end @views function sum_stages!(z, z′, cache::MIRKCache, w, w′, i::Int, dt = cache.mesh_dt[i]) - @unpack M, stage, mesh, k_discrete, k_interp, mesh_dt = cache - @unpack s_star = cache.ITU + (; M, stage, mesh, k_discrete, k_interp, mesh_dt) = cache + (; s_star) = cache.ITU z .= zero(z) __maybe_matmul!(z, k_discrete[i].du[:, 1:stage], w[1:stage]) @@ -260,7 +260,7 @@ end end """ - interp_weights(τ, alg + interp_weights(τ, alg) interp_weights: solver-specified interpolation weights and its first derivative """ @@ -376,7 +376,7 @@ for order in (2, 3, 4, 5, 6) end function sol_eval(cache::MIRKCache{T}, t::T) where {T} - @unpack M, mesh, mesh_dt, alg, k_discrete, k_interp, y = cache + (; M, mesh, mesh_dt, alg, k_discrete, k_interp, y) = cache @assert mesh[1] ≤ t ≤ mesh[end] i = interval(mesh, t) diff --git a/src/algorithms.jl b/src/algorithms.jl index 42de4594..edfdade2 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -146,7 +146,8 @@ for order in (2, 3, 4, 5, 6) @eval begin """ - $($alg)(; nlsolve = NewtonRaphson(), jac_alg = BVPJacobianAlgorithm()) + $($alg)(; nlsolve = NewtonRaphson(), jac_alg = BVPJacobianAlgorithm(), + defect_threshold = 0.1, max_num_subintervals = 3000) $($order)th order Monotonic Implicit Runge Kutta method. @@ -164,6 +165,8 @@ for order in (2, 3, 4, 5, 6) `nonbc_diffmode` defaults to `AutoSparseForwardDiff` if possible else `AutoSparseFiniteDiff`. For `bc_diffmode`, defaults to `AutoForwardDiff` if possible else `AutoFiniteDiff`. + - `defect_threshold`: Threshold for defect control. + - `max_num_subintervals`: Number of maximal subintervals, default as 3000. !!! note For type-stability, the chunksizes for ForwardDiff ADTypes in @@ -171,6 +174,7 @@ for order in (2, 3, 4, 5, 6) ## References + ```bibtex @article{Enright1996RungeKuttaSW, title={Runge-Kutta Software with Defect Control for Boundary Value ODEs}, author={Wayne H. Enright and Paul H. Muir}, @@ -179,10 +183,13 @@ for order in (2, 3, 4, 5, 6) volume={17}, pages={479-497} } + ``` """ - Base.@kwdef struct $(alg){N, J <: BVPJacobianAlgorithm} <: AbstractMIRK + @kwdef struct $(alg){N, J <: BVPJacobianAlgorithm, T} <: AbstractMIRK nlsolve::N = nothing jac_alg::J = BVPJacobianAlgorithm() + defect_threshold::T = 0.1 + max_num_subintervals::Int = 3000 end end end @@ -199,20 +206,24 @@ Fortran code for solving two-point boundary value problems. For detailed documen ## Keyword Arguments: - `max_num_subintervals`: Number of maximal subintervals, default as 3000. - - `method_choice`: Choice for IVP-solvers, default as Runge-Kutta method of order 4, available choices: + - `method_choice`: Choice for IVP-solvers, default as Runge-Kutta method of order 4, + available choices: - `2`: Runge-Kutta method of order 2. - `4`: Runge-Kutta method of order 4. - `6`: Runge-Kutta method of order 6. - - `diagnostic_output`: Diagnostic output for BVPM2, default as non printout, available choices: + - `diagnostic_output`: Diagnostic output for BVPM2, default as non printout, available + choices: - `-1`: Full diagnostic printout. - `0`: Selected printout. - `1`: No printout. - - `error_control`: Determines the error-estimation for which RTOL is used, default as defect control, available choices: + - `error_control`: Determines the error-estimation for which RTOL is used, default as + defect control, available choices: - `1`: Defect control. - `2`: Global error control. - `3`: Defect and then global error control. - `4`: Linear combination of defect and global error control. - - `singular_term`: either nothing if the ODEs have no singular terms at the left boundary or a constant (d,d) matrix for the + - `singular_term`: either nothing if the ODEs have no singular terms at the left + boundary or a constant (d,d) matrix for the singular term. !!! note @@ -229,7 +240,7 @@ struct BVPM2{S} <: BoundaryValueDiffEqAlgorithm function BVPM2(max_num_subintervals::Int, method_choice::Int, diagnostic_output::Int, error_control::Int, singular_term::Union{Nothing, AbstractMatrix}) if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing - error("BVPM2 requires ODEInterface.jl to be loaded") + error("`BVPM2` requires `ODEInterface.jl` to be loaded") end return new{typeof(singular_term)}(max_num_subintervals, method_choice, diagnostic_output, error_control, singular_term) @@ -254,13 +265,15 @@ For detailed documentation, see ## Keyword Arguments - - `bvpclass`: Boundary value problem classification, default as highly nonlinear with bad initial data, available choices: + - `bvpclass`: Boundary value problem classification, default as highly nonlinear with + bad initial data, available choices: - `0`: Linear boundary value problem. - `1`: Nonlinear with good initial data. - `2`: Highly Nonlinear with bad initial data. - - `3`: Highly nonlinear with bad initial data and initial rank reduction to seperable - linear boundary conditions. - - `sol_method`: Switch for solution methods, default as local linear solver with condensing algorithm, available choices: + - `3`: Highly nonlinear with bad initial data and initial rank reduction to + seperable linear boundary conditions. + - `sol_method`: Switch for solution methods, default as local linear solver with + condensing algorithm, available choices: - `0`: Use local linear solver with condensing algorithm. - `1`: Use global sparse linear solver. - `odesolver`: Either `nothing` or ode-solver(dopri5, dop853, seulex, etc.). @@ -276,7 +289,7 @@ struct BVPSOL{O} <: BoundaryValueDiffEqAlgorithm function BVPSOL(bvpclass::Int, sol_method::Int, odesolver) if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing - error("BVPSOL requires ODEInterface.jl to be loaded") + error("`BVPSOL` requires `ODEInterface.jl` to be loaded") end return new{typeof(odesolver)}(bvpclass, sol_method, odesolver) end @@ -290,20 +303,25 @@ end ## Keyword Arguments: - - `bvpclass`: Boundary value problem classification, default as nonlinear and "extra sensitive", available choices: - - `0`: Linear boundary value problem. - - `1`: Nonlinear and regular. - - `2`: Nonlinear and "extra sensitive" (first relax factor is rstart and the - nonlinear iteration does not rely on past convergence). - - `3`: fail-early: return immediately upon: - (a) two successive non-convergences. - (b) after obtaining an error estimate for the first time. - - `collocationpts`: Number of collocation points per subinterval. Require orders[i] ≤ k ≤ 7, default as 7 - - `diagnostic_output`: Diagnostic output for COLNEW, default as no printout, available choices: - - `-1`: Full diagnostic printout. - - `0`: Selected printout. - - `1`: No printout. - - `max_num_subintervals`: Number of maximal subintervals, default as 3000. + - `bvpclass`: Boundary value problem classification, default as nonlinear and + "extra sensitive", available choices: + + + `0`: Linear boundary value problem. + + `1`: Nonlinear and regular. + + `2`: Nonlinear and "extra sensitive" (first relax factor is rstart and the + nonlinear iteration does not rely on past convergence). + + `3`: fail-early: return immediately upon: a) two successive non-convergences. + b) after obtaining an error estimate for the first time. + + - `collocationpts`: Number of collocation points per subinterval. Require + orders[i] ≤ k ≤ 7, default as 7 + - `diagnostic_output`: Diagnostic output for COLNEW, default as no printout, available + choices: + + + `-1`: Full diagnostic printout. + + `0`: Selected printout. + + `1`: No printout. + - `max_num_subintervals`: Number of maximal subintervals, default as 3000. A Fortran77 code solves a multi-points boundary value problems for a mixed order system of ODEs. It incorporates a new basis representation replacing b-splines, and improvements for @@ -330,7 +348,7 @@ struct COLNEW <: BoundaryValueDiffEqAlgorithm function COLNEW(bvpclass::Int, collocationpts::Int, diagnostic_output::Int, max_num_subintervals::Int) if Base.get_extension(@__MODULE__, :BoundaryValueDiffEqODEInterfaceExt) === nothing - error("COLNEW requires ODEInterface.jl to be loaded") + error("`COLNEW` requires `ODEInterface.jl` to be loaded") end return new(bvpclass, collocationpts, diagnostic_output, max_num_subintervals) end diff --git a/src/collocation.jl b/src/collocation.jl index 27406a48..2ac85538 100644 --- a/src/collocation.jl +++ b/src/collocation.jl @@ -5,7 +5,7 @@ end @views function Φ!(residual, fᵢ_cache, k_discrete, f!, TU::MIRKTableau, y, u, p, mesh, mesh_dt, stage::Int) - @unpack c, v, x, b = TU + (; c, v, x, b) = TU tmp = get_tmp(fᵢ_cache, u) T = eltype(u) @@ -36,7 +36,7 @@ end @views function Φ( fᵢ_cache, k_discrete, f, TU::MIRKTableau, y, u, p, mesh, mesh_dt, stage::Int) - @unpack c, v, x, b = TU + (; c, v, x, b) = TU residuals = [similar(yᵢ) for yᵢ in y[1:(end - 1)]] tmp = get_tmp(fᵢ_cache, u) T = eltype(u) diff --git a/src/interpolation.jl b/src/interpolation.jl index eb9b6794..8ca5abf9 100644 --- a/src/interpolation.jl +++ b/src/interpolation.jl @@ -20,7 +20,7 @@ end @inline function interpolation( tvals, id::I, idxs, deriv::D, p, continuity::Symbol = :left) where {I, D} - @unpack t, u, cache = id + (; t, u, cache) = id tdir = sign(t[end] - t[1]) idx = sortperm(tvals, rev = tdir < 0) @@ -42,7 +42,7 @@ end @inline function interpolation!( vals, tvals, id::I, idxs, deriv::D, p, continuity::Symbol = :left) where {I, D} - @unpack t, cache = id + (; t, cache) = id tdir = sign(t[end] - t[1]) idx = sortperm(tvals, rev = tdir < 0) diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 3d86fdb7..5b5072e0 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -36,31 +36,31 @@ function SciMLBase.__init(prob::BVProblem, alg::AbstractMIRK; dt = 0.0, @set! alg.jac_alg = concrete_jacobian_algorithm(alg.jac_alg, prob, alg) iip = isinplace(prob) - _, T, M, n, X = __extract_problem_details(prob; dt, check_positive_dt = true) - # NOTE: Assumes the user provided initial guess is on a uniform mesh - mesh = collect(range(prob.tspan[1], stop = prob.tspan[2], length = n + 1)) + t₀, t₁ = prob.tspan + ig, T, N, Nig, X = __extract_problem_details(prob; dt, check_positive_dt = true) + mesh = __extract_mesh(prob.u0, t₀, t₁, Nig) mesh_dt = diff(mesh) - chunksize = pickchunksize(M * (n + 1)) - - __alloc = x -> __maybe_allocate_diffcache(vec(x), chunksize, alg.jac_alg) + chunksize = pickchunksize(N * (Nig - 1)) + __alloc = @closure x -> __maybe_allocate_diffcache(vec(x), chunksize, alg.jac_alg) fᵢ_cache = __alloc(similar(X)) fᵢ₂_cache = vec(similar(X)) - defect_threshold = T(0.1) # TODO: Allow user to specify these - MxNsub = 3000 # TODO: Allow user to specify these + defect_threshold = T(alg.defect_threshold) + MxNsub = alg.max_num_subintervals # Don't flatten this here, since we need to expand it later if needed - y₀ = __initial_state_from_prob(prob, mesh) + y₀ = __initial_guess_on_mesh(prob.u0, mesh, prob.p, false) + y = __alloc.(copy.(y₀)) TU, ITU = constructMIRK(alg, T) stage = alg_stage(alg) - k_discrete = [__maybe_allocate_diffcache(similar(X, M, stage), chunksize, alg.jac_alg) - for _ in 1:n] - k_interp = [similar(X, ifelse(adaptive, M, 0), ifelse(adaptive, ITU.s_star - stage, 0)) - for _ in 1:n] + k_discrete = [__maybe_allocate_diffcache(similar(X, N, stage), chunksize, alg.jac_alg) + for _ in 1:Nig] + k_interp = [similar(X, ifelse(adaptive, N, 0), ifelse(adaptive, ITU.s_star - stage, 0)) + for _ in 1:Nig] bcresid_prototype, resid₁_size = __get_bcresid_prototype(prob.problem_type, prob, X) @@ -74,29 +74,32 @@ function SciMLBase.__init(prob::BVProblem, alg::AbstractMIRK; dt = 0.0, nothing end - defect = [similar(X, ifelse(adaptive, M, 0)) for _ in 1:n] - new_stages = [similar(X, ifelse(adaptive, M, 0)) for _ in 1:n] + defect = [similar(X, ifelse(adaptive, N, 0)) for _ in 1:Nig] + new_stages = [similar(X, ifelse(adaptive, N, 0)) for _ in 1:Nig] # Transform the functions to handle non-vector inputs bcresid_prototype = __vec(bcresid_prototype) f, bc = if X isa AbstractVector prob.f, prob.f.bc elseif iip - vecf! = (du, u, p, t) -> __vec_f!(du, u, p, t, prob.f, size(X)) + vecf! = @closure (du, u, p, t) -> __vec_f!(du, u, p, t, prob.f, size(X)) vecbc! = if !(prob.problem_type isa TwoPointBVProblem) - (r, u, p, t) -> __vec_bc!(r, u, p, t, prob.f.bc, resid₁_size, size(X)) + @closure (r, u, p, t) -> __vec_bc!(r, u, p, t, prob.f.bc, resid₁_size, size(X)) else - ((r, u, p) -> __vec_bc!(r, u, p, prob.f.bc[1], resid₁_size[1], size(X)), - (r, u, p) -> __vec_bc!(r, u, p, prob.f.bc[2], resid₁_size[2], size(X))) + ( + @closure((r, u, p)->__vec_bc!( + r, u, p, first(prob.f.bc), resid₁_size[1], size(X))), + @closure((r, u, p)->__vec_bc!( + r, u, p, last(prob.f.bc), resid₁_size[2], size(X)))) end vecf!, vecbc! else - vecf = (u, p, t) -> __vec_f(u, p, t, prob.f, size(X)) + vecf = @closure (u, p, t) -> __vec_f(u, p, t, prob.f, size(X)) vecbc = if !(prob.problem_type isa TwoPointBVProblem) - (u, p, t) -> __vec_bc(u, p, t, prob.f.bc, size(X)) + @closure (u, p, t) -> __vec_bc(u, p, t, prob.f.bc, size(X)) else - ((u, p) -> __vec_bc(u, p, prob.f.bc[1], size(X))), - (u, p) -> __vec_bc(u, p, prob.f.bc[2], size(X)) + (@closure((u, p)->__vec_bc(u, p, first(prob.f.bc), size(X))), + @closure((u, p)->__vec_bc(u, p, last(prob.f.bc), size(X)))) end vecf, vecbc end @@ -104,7 +107,7 @@ function SciMLBase.__init(prob::BVProblem, alg::AbstractMIRK; dt = 0.0, prob_ = !(prob.u0 isa AbstractArray) ? remake(prob; u0 = X) : prob return MIRKCache{iip, T}( - alg_order(alg), stage, M, size(X), f, bc, prob_, prob.problem_type, + alg_order(alg), stage, N, size(X), f, bc, prob_, prob.problem_type, prob.p, alg, TU, ITU, bcresid_prototype, mesh, mesh_dt, k_discrete, k_interp, y, y₀, residual, fᵢ_cache, fᵢ₂_cache, defect, new_stages, resid₁_size, (; defect_threshold, MxNsub, abstol, dt, adaptive, kwargs...)) @@ -137,15 +140,20 @@ end function SciMLBase.solve!(cache::MIRKCache) (defect_threshold, MxNsub, abstol, adaptive, _), kwargs = __split_mirk_kwargs(; cache.kwargs...) - @unpack y, y₀, prob, alg, mesh, mesh_dt, TU, ITU = cache + (; y, y₀, prob, alg, mesh, mesh_dt, TU, ITU) = cache info::ReturnCode.T = ReturnCode.Success defect_norm = 2 * abstol while SciMLBase.successful_retcode(info) && defect_norm > abstol nlprob = __construct_nlproblem(cache, recursive_flatten(y₀)) - sol_nlprob = __solve(nlprob, alg.nlsolve; abstol, kwargs...) + sol_nlprob = solve(nlprob, alg.nlsolve; abstol, kwargs..., + alias_u0 = false) # __default_alias_u0(alg.nlsolve)) + + error(111) recursive_unflatten!(cache.y₀, sol_nlprob.u) + error(2) + info = sol_nlprob.retcode !adaptive && break @@ -193,29 +201,30 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y::AbstractVector) where { pt = cache.problem_type loss_bc = if iip - (du, u, p) -> __mirk_loss_bc!(du, u, p, pt, cache.bc, cache.y, cache.mesh) + @closure (du, u, p) -> __mirk_loss_bc!(du, u, p, pt, cache.bc, cache.y, cache.mesh) else - (u, p) -> __mirk_loss_bc(u, p, pt, cache.bc, cache.y, cache.mesh) + @closure (u, p) -> __mirk_loss_bc(u, p, pt, cache.bc, cache.y, cache.mesh) end loss_collocation = if iip - (du, u, p) -> __mirk_loss_collocation!( + @closure (du, u, p) -> __mirk_loss_collocation!( du, u, p, cache.y, cache.mesh, cache.residual, cache) else - (u, p) -> __mirk_loss_collocation(u, p, cache.y, cache.mesh, cache.residual, cache) + @closure (u, p) -> __mirk_loss_collocation( + u, p, cache.y, cache.mesh, cache.residual, cache) end loss = if iip - (du, u, p) -> __mirk_loss!( + @closure (du, u, p) -> __mirk_loss!( du, u, p, cache.y, pt, cache.bc, cache.residual, cache.mesh, cache) else - (u, p) -> __mirk_loss(u, p, cache.y, pt, cache.bc, cache.mesh, cache) + @closure (u, p) -> __mirk_loss(u, p, cache.y, pt, cache.bc, cache.mesh, cache) end return __construct_nlproblem(cache, y, loss_bc, loss_collocation, loss, pt) end -function __mirk_loss!( +@views function __mirk_loss!( resid, u, p, y, pt::StandardBVProblem, bc!::BC, residual, mesh, cache) where {BC} y_ = recursive_unflatten!(y, u) resids = [get_tmp(r, u) for r in residual] @@ -225,26 +234,26 @@ function __mirk_loss!( return nothing end -function __mirk_loss!(resid, u, p, y, pt::TwoPointBVProblem, bc!::Tuple{BC1, BC2}, +@views function __mirk_loss!(resid, u, p, y, pt::TwoPointBVProblem, bc!::Tuple{BC1, BC2}, residual, mesh, cache) where {BC1, BC2} y_ = recursive_unflatten!(y, u) resids = [get_tmp(r, u) for r in residual] - resida = @view resids[1][1:prod(cache.resid_size[1])] - residb = @view resids[1][(prod(cache.resid_size[1]) + 1):end] + resida = resids[1][1:prod(cache.resid_size[1])] + residb = resids[1][(prod(cache.resid_size[1]) + 1):end] eval_bc_residual!((resida, residb), pt, bc!, y_, p, mesh) Φ!(resids[2:end], cache, y_, u, p) recursive_flatten_twopoint!(resid, resids, cache.resid_size) return nothing end -function __mirk_loss(u, p, y, pt::StandardBVProblem, bc::BC, mesh, cache) where {BC} +@views function __mirk_loss(u, p, y, pt::StandardBVProblem, bc::BC, mesh, cache) where {BC} y_ = recursive_unflatten!(y, u) resid_bc = eval_bc_residual(pt, bc, y_, p, mesh) resid_co = Φ(cache, y_, u, p) return vcat(resid_bc, mapreduce(vec, vcat, resid_co)) end -function __mirk_loss( +@views function __mirk_loss( u, p, y, pt::TwoPointBVProblem, bc::Tuple{BC1, BC2}, mesh, cache) where {BC1, BC2} y_ = recursive_unflatten!(y, u) resid_bca, resid_bcb = eval_bc_residual(pt, bc, y_, p, mesh) @@ -252,18 +261,18 @@ function __mirk_loss( return vcat(resid_bca, mapreduce(vec, vcat, resid_co), resid_bcb) end -function __mirk_loss_bc!(resid, u, p, pt, bc!::BC, y, mesh) where {BC} +@views function __mirk_loss_bc!(resid, u, p, pt, bc!::BC, y, mesh) where {BC} y_ = recursive_unflatten!(y, u) eval_bc_residual!(resid, pt, bc!, y_, p, mesh) return nothing end -function __mirk_loss_bc(u, p, pt, bc!::BC, y, mesh) where {BC} +@views function __mirk_loss_bc(u, p, pt, bc!::BC, y, mesh) where {BC} y_ = recursive_unflatten!(y, u) return eval_bc_residual(pt, bc!, y_, p, mesh) end -function __mirk_loss_collocation!(resid, u, p, y, mesh, residual, cache) +@views function __mirk_loss_collocation!(resid, u, p, y, mesh, residual, cache) y_ = recursive_unflatten!(y, u) resids = [get_tmp(r, u) for r in residual[2:end]] Φ!(resids, cache, y_, u, p) @@ -271,7 +280,7 @@ function __mirk_loss_collocation!(resid, u, p, y, mesh, residual, cache) return nothing end -function __mirk_loss_collocation(u, p, y, mesh, residual, cache) +@views function __mirk_loss_collocation(u, p, y, mesh, residual, cache) y_ = recursive_unflatten!(y, u) resids = Φ(cache, y_, u, p) return mapreduce(vec, vcat, resids) @@ -279,16 +288,15 @@ end function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collocation::C, loss::LF, ::StandardBVProblem) where {iip, BC, C, LF} - @unpack nlsolve, jac_alg = cache.alg + (; nlsolve, jac_alg) = cache.alg N = length(cache.mesh) resid_bc = cache.bcresid_prototype L = length(resid_bc) resid_collocation = similar(y, cache.M * (N - 1)) - loss_bcₚ = iip ? ((du, u) -> loss_bc(du, u, cache.p)) : (u -> loss_bc(u, cache.p)) - loss_collocationₚ = iip ? ((du, u) -> loss_collocation(du, u, cache.p)) : - (u -> loss_collocation(u, cache.p)) + loss_bcₚ = (iip ? __Fix3 : Base.Fix2)(loss_bc, cache.p) + loss_collocationₚ = (iip ? __Fix3 : Base.Fix2)(loss_collocation, cache.p) sd_bc = jac_alg.bc_diffmode isa AbstractSparseADType ? SymbolicsSparsityDetection() : NoSparsityDetection() @@ -327,18 +335,21 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collo end jac = if iip - (J, u, p) -> __mirk_mpoint_jacobian!( + @closure (J, u, p) -> __mirk_mpoint_jacobian!( J, J_c, u, jac_alg.bc_diffmode, jac_alg.nonbc_diffmode, cache_bc, cache_collocation, loss_bcₚ, loss_collocationₚ, resid_bc, resid_collocation, L) else - (u, p) -> __mirk_mpoint_jacobian( + @closure (u, p) -> __mirk_mpoint_jacobian( jac_prototype, J_c, u, jac_alg.bc_diffmode, jac_alg.nonbc_diffmode, cache_bc, cache_collocation, loss_bcₚ, loss_collocationₚ, L) end - nlf = NonlinearFunction{iip}( - loss; resid_prototype = vcat(resid_bc, resid_collocation), jac, jac_prototype) - return (L == cache.M ? NonlinearProblem : NonlinearLeastSquaresProblem)(nlf, y, cache.p) + @show size(resid_bc), size(resid_collocation), size(y), size(jac_prototype) + + resid_prototype = vcat(resid_bc, resid_collocation) + nlf = __unsafe_nonlinearfunction{iip}(loss; resid_prototype, jac, jac_prototype) + + return __internal_nlsolve_problem(cache.prob, resid_prototype, y, nlf, y, cache.p) end function __mirk_mpoint_jacobian!( @@ -382,49 +393,49 @@ function __mirk_mpoint_jacobian( return J end -function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collocation::C, - loss::LF, ::TwoPointBVProblem) where {iip, BC, C, LF} - @unpack nlsolve, jac_alg = cache.alg - N = length(cache.mesh) - - lossₚ = iip ? ((du, u) -> loss(du, u, cache.p)) : (u -> loss(u, cache.p)) - - resid = vcat(@view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), - similar(y, cache.M * (N - 1)), - @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end])) - L = length(cache.bcresid_prototype) - - sd = if jac_alg.diffmode isa AbstractSparseADType - __sparsity_detection_alg(__generate_sparse_jacobian_prototype( - cache, cache.problem_type, - @view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), - @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), - cache.M, N)) - else - NoSparsityDetection() - end - diffcache = __sparse_jacobian_cache(Val(iip), jac_alg.diffmode, sd, lossₚ, resid, y) - jac_prototype = init_jacobian(diffcache) - - jac = if iip - (J, u, p) -> __mirk_2point_jacobian!( - J, u, jac_alg.diffmode, diffcache, lossₚ, resid) - else - (u, p) -> __mirk_2point_jacobian( - u, jac_prototype, jac_alg.diffmode, diffcache, lossₚ) - end - - nlf = NonlinearFunction{iip}(loss; resid_prototype = copy(resid), jac, jac_prototype) - - return (L == cache.M ? NonlinearProblem : NonlinearLeastSquaresProblem)(nlf, y, cache.p) -end - -function __mirk_2point_jacobian!(J, x, diffmode, diffcache, loss_fn::L, resid) where {L} - sparse_jacobian!(J, diffmode, diffcache, loss_fn, resid, x) - return J -end - -function __mirk_2point_jacobian(x, J, diffmode, diffcache, loss_fn::L) where {L} - sparse_jacobian!(J, diffmode, diffcache, loss_fn, x) - return J -end +# function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collocation::C, +# loss::LF, ::TwoPointBVProblem) where {iip, BC, C, LF} +# (; nlsolve, jac_alg ) = cache.alg +# N = length(cache.mesh) + +# lossₚ = iip ? ((du, u) -> loss(du, u, cache.p)) : (u -> loss(u, cache.p)) + +# resid = vcat(@view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), +# similar(y, cache.M * (N - 1)), +# @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end])) +# L = length(cache.bcresid_prototype) + +# sd = if jac_alg.diffmode isa AbstractSparseADType +# __sparsity_detection_alg(__generate_sparse_jacobian_prototype( +# cache, cache.problem_type, +# @view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), +# @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), +# cache.M, N)) +# else +# NoSparsityDetection() +# end +# diffcache = __sparse_jacobian_cache(Val(iip), jac_alg.diffmode, sd, lossₚ, resid, y) +# jac_prototype = init_jacobian(diffcache) + +# jac = if iip +# (J, u, p) -> __mirk_2point_jacobian!( +# J, u, jac_alg.diffmode, diffcache, lossₚ, resid) +# else +# (u, p) -> __mirk_2point_jacobian( +# u, jac_prototype, jac_alg.diffmode, diffcache, lossₚ) +# end + +# nlf = NonlinearFunction{iip}(loss; resid_prototype = copy(resid), jac, jac_prototype) + +# return (L == cache.M ? NonlinearProblem : NonlinearLeastSquaresProblem)(nlf, y, cache.p) +# end + +# function __mirk_2point_jacobian!(J, x, diffmode, diffcache, loss_fn::L, resid) where {L} +# sparse_jacobian!(J, diffmode, diffcache, loss_fn, resid, x) +# return J +# end + +# function __mirk_2point_jacobian(x, J, diffmode, diffcache, loss_fn::L) where {L} +# sparse_jacobian!(J, diffmode, diffcache, loss_fn, x) +# return J +# end diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index e8534508..fcf99c0a 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -126,6 +126,7 @@ function __solve_nlproblem!( # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) + # FIXME: This is not safe for polyalgorithms __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) return nothing @@ -185,6 +186,7 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) + # FIXME: This is not safe for polyalgorithms __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) return nothing @@ -255,7 +257,7 @@ function __multiple_shooting_solve_internal_odes!( return first:1:last end - Threads.@threads for idx in 1:length(data_partition) + Threads.@threads for idx in eachindex(data_partition) cache = odecache[idx] for i in data_partition[idx] SciMLBase.reinit!(cache, reshape(@view(us[((i - 1) * N + 1):(i * N)]), u0_size); @@ -358,7 +360,7 @@ end # Problem has initial guess @views function __multiple_shooting_initialize!( nodes, prob, alg, ::Val{true}, nshoots::Int, odecache; kwargs...) - @unpack u0, tspan = prob + (; u0, tspan) = prob resize!(nodes, nshoots + 1) nodes .= range(tspan[1], tspan[2]; length = nshoots + 1) @@ -378,8 +380,8 @@ end @views function __multiple_shooting_initialize!( nodes, prob, alg::MultipleShooting, ::Val{false}, nshoots::Int, odecache_; verbose, kwargs...) - @unpack f, u0, tspan, p = prob - @unpack ode_alg = alg + (; f, u0, tspan, p) = prob + (; ode_alg) = alg resize!(nodes, nshoots + 1) nodes .= range(tspan[1], tspan[2]; length = nshoots + 1) @@ -401,7 +403,7 @@ end sol = solve!(odecache) if SciMLBase.successful_retcode(sol) - for i in 1:length(nodes) + for i in eachindex(nodes) u_at_nodes[(i - 1) * N .+ (1:N)] .= vec(sol(nodes[i])) end else @@ -417,7 +419,7 @@ end # Grid coarsening @views function __multiple_shooting_initialize!(nodes, u_at_nodes_prev, prob, alg, nshoots, old_nshoots, ig, odecache_, u0; kwargs...) - @unpack f, tspan, p = prob + (; f, tspan, p) = prob prev_nodes = copy(nodes) odecache = odecache_ isa Vector ? first(odecache_) : odecache_ diff --git a/src/utils.jl b/src/utils.jl index 041f2c34..2a0f5340 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -162,19 +162,6 @@ function __initial_guess(f::F, p::P, t::T) where {F, P, T} end end -function __initial_state_from_prob(prob::BVProblem, mesh) - return __initial_state_from_prob(prob, prob.u0, mesh) -end -function __initial_state_from_prob(::BVProblem, u0::AbstractArray, mesh) - return [copy(vec(u0)) for _ in mesh] -end -function __initial_state_from_prob(::BVProblem, u0::AbstractVector{<:AbstractVector}, _) - return [copy(vec(u)) for u in u0] -end -function __initial_state_from_prob(prob::BVProblem, f::F, mesh) where {F} - return [__initial_guess(f, prob.p, t) for t in mesh] -end - function __get_bcresid_prototype(prob::BVProblem, u) return __get_bcresid_prototype(prob.problem_type, prob, u) end @@ -251,8 +238,6 @@ function __restructure_sol(sol::Vector{<:AbstractArray}, u_size) return map(Base.Fix2(reshape, u_size), sol) end -# TODO: Add dispatch for a ODESolution Type as well - # Override the checks for NonlinearFunction struct __unsafe_nonlinearfunction{iip} end @@ -397,3 +382,16 @@ function __solution_new_original_retcode( sol.u, sol.u_analytic, sol.errors, sol.t, sol.k, sol.prob, sol.alg, sol.interp, sol.dense, sol.tslocation, sol.stats, sol.alg_choice, retcode, resid, original) end + +# Fix3 +@concrete struct __Fix3 + f + x +end + +@inline (f::__Fix3{F})(a, b) where {F} = f.f(a, b, f.x) + +# Aliasing +@inline __default_alias_u0(::Nothing) = false +@inline __default_alias_u0(::NonlinearSolvePolyAlgorithm) = false +@inline __default_alias_u0(::Any) = true diff --git a/test/mirk/mirk_convergence_tests.jl b/test/mirk/mirk_convergence_tests.jl index ce5a326d..2833f9b5 100644 --- a/test/mirk/mirk_convergence_tests.jl +++ b/test/mirk/mirk_convergence_tests.jl @@ -1,4 +1,6 @@ -using BoundaryValueDiffEq, DiffEqBase, DiffEqDevTools, LinearAlgebra, Test +@testsetup module MIRKConvergenceTests + +using BoundaryValueDiffEq for order in (2, 3, 4, 5, 6) s = Symbol("MIRK$(order)") @@ -63,13 +65,19 @@ probArr = [BVProblem(odef1!, boundary!, u0, tspan), TwoPointBVProblem(odef2!, (boundary_two_point_a!, boundary_two_point_b!), u0, tspan; bcresid_prototype), TwoPointBVProblem( - odef2, (boundary_two_point_a, boundary_two_point_b), u0, tspan; bcresid_prototype)]; + odef2, (boundary_two_point_a, boundary_two_point_b), u0, tspan; bcresid_prototype)] testTol = 0.2 affineTol = 1e-2 dts = 1 .// 2 .^ (3:-1:1) -@testset "Affineness" begin +export probArr, testTol, affineTol, dts, mirk_solver + +end + +@testitem "Affineness" setup=[MIRKConvergenceTests] begin + using LinearAlgebra + @testset "Problem: $i" for i in (1, 2, 5, 6) prob = probArr[i] @testset "MIRK$order" for order in (2, 3, 4, 5, 6) @@ -79,42 +87,42 @@ dts = 1 .// 2 .^ (3:-1:1) end end -@testset "Convergence on Linear" begin - @testset "Problem: $i" for i in (3, 4, 7, 8) - prob = probArr[i] - @testset "MIRK$order" for (i, order) in enumerate((2, 3, 4, 5, 6)) - @time sim = test_convergence( - dts, prob, mirk_solver(Val(order)); abstol = 1e-8, reltol = 1e-8) - @test sim.𝒪est[:final]≈order atol=testTol - end - end -end - -# Simple Pendulum -using StaticArrays - -tspan = (0.0, π / 2) -function simplependulum!(du, u, p, t) - g, L, θ, dθ = 9.81, 1.0, u[1], u[2] - du[1] = dθ - du[2] = -(g / L) * sin(θ) -end - -# FIXME: This is a really bad test. Needs interpolation -function bc_pendulum!(residual, u, p, t) - residual[1] = u[end ÷ 2][1] + π / 2 # the solution at the middle of the time span should be -pi/2 - residual[2] = u[end][1] - π / 2 # the solution at the end of the time span should be pi/2 -end - -u0 = MVector{2}([pi / 2, pi / 2]) -bvp1 = BVProblem(simplependulum!, bc_pendulum!, u0, tspan) - -jac_alg = BVPJacobianAlgorithm(; - bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff()) - -# Using ForwardDiff might lead to Cache expansion warnings -@test_nowarn solve(bvp1, MIRK2(; jac_alg); dt = 0.005) -@test_nowarn solve(bvp1, MIRK3(; jac_alg); dt = 0.005) -@test_nowarn solve(bvp1, MIRK4(; jac_alg); dt = 0.05) -@test_nowarn solve(bvp1, MIRK5(; jac_alg); dt = 0.05) -@test_nowarn solve(bvp1, MIRK6(; jac_alg); dt = 0.05) +# @testset "Convergence on Linear" begin +# @testset "Problem: $i" for i in (3, 4, 7, 8) +# prob = probArr[i] +# @testset "MIRK$order" for (i, order) in enumerate((2, 3, 4, 5, 6)) +# @time sim = test_convergence( +# dts, prob, mirk_solver(Val(order)); abstol = 1e-8, reltol = 1e-8) +# @test sim.𝒪est[:final]≈order atol=testTol +# end +# end +# end + +# # Simple Pendulum +# using StaticArrays + +# tspan = (0.0, π / 2) +# function simplependulum!(du, u, p, t) +# g, L, θ, dθ = 9.81, 1.0, u[1], u[2] +# du[1] = dθ +# du[2] = -(g / L) * sin(θ) +# end + +# # FIXME: This is a really bad test. Needs interpolation +# function bc_pendulum!(residual, u, p, t) +# residual[1] = u[end ÷ 2][1] + π / 2 # the solution at the middle of the time span should be -pi/2 +# residual[2] = u[end][1] - π / 2 # the solution at the end of the time span should be pi/2 +# end + +# u0 = MVector{2}([pi / 2, pi / 2]) +# bvp1 = BVProblem(simplependulum!, bc_pendulum!, u0, tspan) + +# jac_alg = BVPJacobianAlgorithm(; +# bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff()) + +# # Using ForwardDiff might lead to Cache expansion warnings +# @test_nowarn solve(bvp1, MIRK2(; jac_alg); dt = 0.005) +# @test_nowarn solve(bvp1, MIRK3(; jac_alg); dt = 0.005) +# @test_nowarn solve(bvp1, MIRK4(; jac_alg); dt = 0.05) +# @test_nowarn solve(bvp1, MIRK5(; jac_alg); dt = 0.05) +# @test_nowarn solve(bvp1, MIRK6(; jac_alg); dt = 0.05) diff --git a/test/misc/aqua.jl b/test/misc/aqua.jl deleted file mode 100644 index 45a931bd..00000000 --- a/test/misc/aqua.jl +++ /dev/null @@ -1,6 +0,0 @@ -using Aqua, BoundaryValueDiffEq, Test - -@testset "All Tests (except Ambiguities)" begin - # Ambiguities are from downstream pacakges - Aqua.test_all(BoundaryValueDiffEq; ambiguities = false) -end diff --git a/test/misc/qa_tests.jl b/test/misc/qa_tests.jl new file mode 100644 index 00000000..e8ef3e30 --- /dev/null +++ b/test/misc/qa_tests.jl @@ -0,0 +1,6 @@ +@testitem "Quality Assurance" begin + using Aqua + + Aqua.test_all(BoundaryValueDiffEq; ambiguities = false) + Aqua.test_ambiguities(BoundaryValueDiffEq; recursive = false) +end From cddbdbc072665507ae03944a7e22a038132e77d3 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Wed, 20 Mar 2024 19:29:16 -0400 Subject: [PATCH 11/24] Update the manifest --- Manifest.toml | 12 ++- src/solve/mirk.jl | 100 ++++++++---------- ...interpolation_test.jl => interpolation.jl} | 0 test/mirk/mirk_convergence_tests.jl | 81 +++++++------- 4 files changed, 97 insertions(+), 96 deletions(-) rename test/mirk/{interpolation_test.jl => interpolation.jl} (100%) diff --git a/Manifest.toml b/Manifest.toml index 58c0999d..7c6f1df9 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -264,9 +264,11 @@ version = "0.1.10" [[deps.FastAlmostBandedMatrices]] deps = ["ArrayInterface", "ArrayLayouts", "BandedMatrices", "ConcreteStructs", "LazyArrays", "LinearAlgebra", "MatrixFactorizations", "PrecompileTools", "Reexport"] -git-tree-sha1 = "178316d87f883f0702e79d9c83a8049484c9f619" +git-tree-sha1 = "9dc913faf8552fd09b92a0d7fcc25f1d5609d795" +repo-rev = "main" +repo-url = "https://github.com/SciML/FastAlmostBandedMatrices.jl" uuid = "9d29842c-ecb8-4973-b1e9-a27b1157504e" -version = "0.1.0" +version = "0.1.1" [[deps.FastBroadcast]] deps = ["ArrayInterface", "LinearAlgebra", "Polyester", "Static", "StaticArrayInterface", "StrideArraysCore"] @@ -607,7 +609,7 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -path = "../NonlinearSolve.jl" +git-tree-sha1 = "d52bac2b94358b4b960cbfb896d5193d67f3ff09" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" version = "3.8.0" @@ -808,7 +810,9 @@ version = "0.6.42" [[deps.SciMLBase]] deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -path = "../SciMLBase.jl" +git-tree-sha1 = "0e4fca3dd5de4d4a82c0ffae1e51ab6234af4df0" +repo-rev = "ap/nlls_bvp" +repo-url = "https://github.com/SciML/SciMLBase.jl.git" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" version = "2.30.1" diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 5b5072e0..08c2d7fa 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -147,13 +147,9 @@ function SciMLBase.solve!(cache::MIRKCache) while SciMLBase.successful_retcode(info) && defect_norm > abstol nlprob = __construct_nlproblem(cache, recursive_flatten(y₀)) sol_nlprob = solve(nlprob, alg.nlsolve; abstol, kwargs..., - alias_u0 = false) # __default_alias_u0(alg.nlsolve)) - - error(111) + alias_u0 = __default_alias_u0(alg.nlsolve)) recursive_unflatten!(cache.y₀, sol_nlprob.u) - error(2) - info = sol_nlprob.retcode !adaptive && break @@ -344,8 +340,6 @@ function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collo cache_bc, cache_collocation, loss_bcₚ, loss_collocationₚ, L) end - @show size(resid_bc), size(resid_collocation), size(y), size(jac_prototype) - resid_prototype = vcat(resid_bc, resid_collocation) nlf = __unsafe_nonlinearfunction{iip}(loss; resid_prototype, jac, jac_prototype) @@ -393,49 +387,49 @@ function __mirk_mpoint_jacobian( return J end -# function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collocation::C, -# loss::LF, ::TwoPointBVProblem) where {iip, BC, C, LF} -# (; nlsolve, jac_alg ) = cache.alg -# N = length(cache.mesh) - -# lossₚ = iip ? ((du, u) -> loss(du, u, cache.p)) : (u -> loss(u, cache.p)) - -# resid = vcat(@view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), -# similar(y, cache.M * (N - 1)), -# @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end])) -# L = length(cache.bcresid_prototype) - -# sd = if jac_alg.diffmode isa AbstractSparseADType -# __sparsity_detection_alg(__generate_sparse_jacobian_prototype( -# cache, cache.problem_type, -# @view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), -# @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), -# cache.M, N)) -# else -# NoSparsityDetection() -# end -# diffcache = __sparse_jacobian_cache(Val(iip), jac_alg.diffmode, sd, lossₚ, resid, y) -# jac_prototype = init_jacobian(diffcache) - -# jac = if iip -# (J, u, p) -> __mirk_2point_jacobian!( -# J, u, jac_alg.diffmode, diffcache, lossₚ, resid) -# else -# (u, p) -> __mirk_2point_jacobian( -# u, jac_prototype, jac_alg.diffmode, diffcache, lossₚ) -# end - -# nlf = NonlinearFunction{iip}(loss; resid_prototype = copy(resid), jac, jac_prototype) - -# return (L == cache.M ? NonlinearProblem : NonlinearLeastSquaresProblem)(nlf, y, cache.p) -# end - -# function __mirk_2point_jacobian!(J, x, diffmode, diffcache, loss_fn::L, resid) where {L} -# sparse_jacobian!(J, diffmode, diffcache, loss_fn, resid, x) -# return J -# end - -# function __mirk_2point_jacobian(x, J, diffmode, diffcache, loss_fn::L) where {L} -# sparse_jacobian!(J, diffmode, diffcache, loss_fn, x) -# return J -# end +function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collocation::C, + loss::LF, ::TwoPointBVProblem) where {iip, BC, C, LF} + (; nlsolve, jac_alg ) = cache.alg + N = length(cache.mesh) + + lossₚ = iip ? ((du, u) -> loss(du, u, cache.p)) : (u -> loss(u, cache.p)) + + resid = vcat(@view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), + similar(y, cache.M * (N - 1)), + @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end])) + L = length(cache.bcresid_prototype) + + sd = if jac_alg.diffmode isa AbstractSparseADType + __sparsity_detection_alg(__generate_sparse_jacobian_prototype( + cache, cache.problem_type, + @view(cache.bcresid_prototype[1:prod(cache.resid_size[1])]), + @view(cache.bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), + cache.M, N)) + else + NoSparsityDetection() + end + diffcache = __sparse_jacobian_cache(Val(iip), jac_alg.diffmode, sd, lossₚ, resid, y) + jac_prototype = init_jacobian(diffcache) + + jac = if iip + @closure (J, u, p) -> __mirk_2point_jacobian!( + J, u, jac_alg.diffmode, diffcache, lossₚ, resid) + else + @closure (u, p) -> __mirk_2point_jacobian( + u, jac_prototype, jac_alg.diffmode, diffcache, lossₚ) + end + + resid_prototype = copy(resid) + nlf = __unsafe_nonlinearfunction{iip}(loss; resid_prototype, jac, jac_prototype) + return __internal_nlsolve_problem(cache.prob, resid_prototype, y, nlf, y, cache.p) +end + +function __mirk_2point_jacobian!(J, x, diffmode, diffcache, loss_fn::L, resid) where {L} + sparse_jacobian!(J, diffmode, diffcache, loss_fn, resid, x) + return J +end + +function __mirk_2point_jacobian(x, J, diffmode, diffcache, loss_fn::L) where {L} + sparse_jacobian!(J, diffmode, diffcache, loss_fn, x) + return J +end diff --git a/test/mirk/interpolation_test.jl b/test/mirk/interpolation.jl similarity index 100% rename from test/mirk/interpolation_test.jl rename to test/mirk/interpolation.jl diff --git a/test/mirk/mirk_convergence_tests.jl b/test/mirk/mirk_convergence_tests.jl index 2833f9b5..e2ddc855 100644 --- a/test/mirk/mirk_convergence_tests.jl +++ b/test/mirk/mirk_convergence_tests.jl @@ -87,42 +87,45 @@ end end end -# @testset "Convergence on Linear" begin -# @testset "Problem: $i" for i in (3, 4, 7, 8) -# prob = probArr[i] -# @testset "MIRK$order" for (i, order) in enumerate((2, 3, 4, 5, 6)) -# @time sim = test_convergence( -# dts, prob, mirk_solver(Val(order)); abstol = 1e-8, reltol = 1e-8) -# @test sim.𝒪est[:final]≈order atol=testTol -# end -# end -# end - -# # Simple Pendulum -# using StaticArrays - -# tspan = (0.0, π / 2) -# function simplependulum!(du, u, p, t) -# g, L, θ, dθ = 9.81, 1.0, u[1], u[2] -# du[1] = dθ -# du[2] = -(g / L) * sin(θ) -# end - -# # FIXME: This is a really bad test. Needs interpolation -# function bc_pendulum!(residual, u, p, t) -# residual[1] = u[end ÷ 2][1] + π / 2 # the solution at the middle of the time span should be -pi/2 -# residual[2] = u[end][1] - π / 2 # the solution at the end of the time span should be pi/2 -# end - -# u0 = MVector{2}([pi / 2, pi / 2]) -# bvp1 = BVProblem(simplependulum!, bc_pendulum!, u0, tspan) - -# jac_alg = BVPJacobianAlgorithm(; -# bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff()) - -# # Using ForwardDiff might lead to Cache expansion warnings -# @test_nowarn solve(bvp1, MIRK2(; jac_alg); dt = 0.005) -# @test_nowarn solve(bvp1, MIRK3(; jac_alg); dt = 0.005) -# @test_nowarn solve(bvp1, MIRK4(; jac_alg); dt = 0.05) -# @test_nowarn solve(bvp1, MIRK5(; jac_alg); dt = 0.05) -# @test_nowarn solve(bvp1, MIRK6(; jac_alg); dt = 0.05) +@testitem "Convergence on Linear" setup=[MIRKConvergenceTests] begin + using LinearAlgebra, DiffEqDevTools + + @testset "Problem: $i" for i in (3, 4, 7, 8) + prob = probArr[i] + @testset "MIRK$order" for (i, order) in enumerate((2, 3, 4, 5, 6)) + @time sim = test_convergence( + dts, prob, mirk_solver(Val(order)); abstol = 1e-8, reltol = 1e-8) + @test sim.𝒪est[:final]≈order atol=testTol + end + end +end + +# FIXME: This is a really bad test. Needs interpolation +@testitem "Simple Pendulum" begin + using StaticArrays + + tspan = (0.0, π / 2) + function simplependulum!(du, u, p, t) + g, L, θ, dθ = 9.81, 1.0, u[1], u[2] + du[1] = dθ + du[2] = -(g / L) * sin(θ) + end + + function bc_pendulum!(residual, u, p, t) + residual[1] = u[end ÷ 2][1] + π / 2 # the solution at the middle of the time span should be -pi/2 + residual[2] = u[end][1] - π / 2 # the solution at the end of the time span should be pi/2 + end + + u0 = MVector{2}([pi / 2, pi / 2]) + bvp1 = BVProblem(simplependulum!, bc_pendulum!, u0, tspan) + + jac_alg = BVPJacobianAlgorithm(; + bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff()) + + # Using ForwardDiff might lead to Cache expansion warnings + @test_nowarn solve(bvp1, MIRK2(; jac_alg); dt = 0.005) + @test_nowarn solve(bvp1, MIRK3(; jac_alg); dt = 0.005) + @test_nowarn solve(bvp1, MIRK4(; jac_alg); dt = 0.05) + @test_nowarn solve(bvp1, MIRK5(; jac_alg); dt = 0.05) + @test_nowarn solve(bvp1, MIRK6(; jac_alg); dt = 0.05) +end From 160ee01392662f8ca00276e639e9d21e4a469351 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Wed, 20 Mar 2024 20:45:28 -0400 Subject: [PATCH 12/24] Add more tests --- src/solve/mirk.jl | 2 +- test/mirk/ensemble.jl | 29 --------- test/mirk/ensemble_tests.jl | 31 ++++++++++ test/mirk/interpolation.jl | 34 ----------- test/mirk/interpolation_tests.jl | 36 +++++++++++ test/mirk/mirk_convergence_tests.jl | 4 +- test/mirk/vectorofvector_initials.jl | 71 ---------------------- test/mirk/vectorofvector_initials_tests.jl | 71 ++++++++++++++++++++++ 8 files changed, 141 insertions(+), 137 deletions(-) delete mode 100644 test/mirk/ensemble.jl create mode 100644 test/mirk/ensemble_tests.jl delete mode 100644 test/mirk/interpolation.jl create mode 100644 test/mirk/interpolation_tests.jl delete mode 100644 test/mirk/vectorofvector_initials.jl create mode 100644 test/mirk/vectorofvector_initials_tests.jl diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 08c2d7fa..89a22027 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -389,7 +389,7 @@ end function __construct_nlproblem(cache::MIRKCache{iip}, y, loss_bc::BC, loss_collocation::C, loss::LF, ::TwoPointBVProblem) where {iip, BC, C, LF} - (; nlsolve, jac_alg ) = cache.alg + (; nlsolve, jac_alg) = cache.alg N = length(cache.mesh) lossₚ = iip ? ((du, u) -> loss(du, u, cache.p)) : (u -> loss(u, cache.p)) diff --git a/test/mirk/ensemble.jl b/test/mirk/ensemble.jl deleted file mode 100644 index 17cbde25..00000000 --- a/test/mirk/ensemble.jl +++ /dev/null @@ -1,29 +0,0 @@ -using BoundaryValueDiffEq, Random, Test - -function ode!(du, u, p, t) - du[1] = u[2] - du[2] = -p[1] * u[1] -end - -function bc!(residual, u, p, t) - residual[1] = u[1][1] - 1.0 - residual[2] = u[end][1] -end - -prob_func(prob, i, repeat) = remake(prob, p = [rand()]) - -u0 = [0.0, 1.0] -tspan = (0, pi / 2) -p = [rand()] -bvp = BVProblem(ode!, bc!, u0, tspan, p) -ensemble_prob = EnsembleProblem(bvp; prob_func) - -@testset "$(solver)" for solver in (MIRK2, MIRK3, MIRK4, MIRK5, MIRK6) - jac_algs = [BVPJacobianAlgorithm(), - BVPJacobianAlgorithm(; - bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff())] - for jac_alg in jac_algs - sol = solve(ensemble_prob, solver(; jac_alg); trajectories = 10, dt = 0.1) - @test sol.converged - end -end diff --git a/test/mirk/ensemble_tests.jl b/test/mirk/ensemble_tests.jl new file mode 100644 index 00000000..5c4bee54 --- /dev/null +++ b/test/mirk/ensemble_tests.jl @@ -0,0 +1,31 @@ +@testitem "EnsembleProblem" begin + using Random + + function ode!(du, u, p, t) + du[1] = u[2] + du[2] = -p[1] * u[1] + end + + function bc!(residual, u, p, t) + residual[1] = u[1][1] - 1.0 + residual[2] = u[end][1] + end + + prob_func(prob, i, repeat) = remake(prob, p = [rand()]) + + u0 = [0.0, 1.0] + tspan = (0, pi / 2) + p = [rand()] + bvp = BVProblem(ode!, bc!, u0, tspan, p) + ensemble_prob = EnsembleProblem(bvp; prob_func) + + @testset "$(solver)" for solver in (MIRK2, MIRK3, MIRK4, MIRK5, MIRK6) + jac_algs = [BVPJacobianAlgorithm(), + BVPJacobianAlgorithm(; + bc_diffmode = AutoFiniteDiff(), nonbc_diffmode = AutoSparseFiniteDiff())] + for jac_alg in jac_algs + sol = solve(ensemble_prob, solver(; jac_alg); trajectories = 10, dt = 0.1) + @test sol.converged + end + end +end diff --git a/test/mirk/interpolation.jl b/test/mirk/interpolation.jl deleted file mode 100644 index 2c445055..00000000 --- a/test/mirk/interpolation.jl +++ /dev/null @@ -1,34 +0,0 @@ -using BoundaryValueDiffEq, DiffEqBase, DiffEqDevTools, LinearAlgebra, Test - -λ = 1 -function prob_bvp_linear_analytic(u, λ, t) - a = 1 / sqrt(λ) - [(exp(-a * t) - exp((t - 2) * a)) / (1 - exp(-2 * a)), - (-a * exp(-t * a) - a * exp((t - 2) * a)) / (1 - exp(-2 * a))] -end -function prob_bvp_linear_f!(du, u, p, t) - du[1] = u[2] - du[2] = 1 / p * u[1] -end -function prob_bvp_linear_bc!(res, u, p, t) - res[1] = u[1][1] - 1 - res[2] = u[end][1] -end -prob_bvp_linear_function = ODEFunction( - prob_bvp_linear_f!, analytic = prob_bvp_linear_analytic) -prob_bvp_linear_tspan = (0.0, 1.0) -prob_bvp_linear = BVProblem( - prob_bvp_linear_function, prob_bvp_linear_bc!, [1.0, 0.0], prob_bvp_linear_tspan, λ) -testTol = 1e-6 - -for order in (2, 3, 4, 5, 6) - s = Symbol("MIRK$(order)") - @eval mirk_solver(::Val{$order}) = $(s)() -end - -@testset "Interpolation" begin - @testset "MIRK$order" for order in (2, 3, 4, 5, 6) - @time sol = solve(prob_bvp_linear, mirk_solver(Val(order)); dt = 0.001) - @test sol(0.001)≈[0.998687464, -1.312035941] atol=testTol - end -end diff --git a/test/mirk/interpolation_tests.jl b/test/mirk/interpolation_tests.jl new file mode 100644 index 00000000..a5a8efd6 --- /dev/null +++ b/test/mirk/interpolation_tests.jl @@ -0,0 +1,36 @@ +@testitem "MIRK Interpolation" begin + using LinearAlgebra + + λ = 1 + function prob_bvp_linear_analytic(u, λ, t) + a = 1 / sqrt(λ) + return [(exp(-a * t) - exp((t - 2) * a)) / (1 - exp(-2 * a)), + (-a * exp(-t * a) - a * exp((t - 2) * a)) / (1 - exp(-2 * a))] + end + + function prob_bvp_linear_f!(du, u, p, t) + du[1] = u[2] + du[2] = 1 / p * u[1] + end + function prob_bvp_linear_bc!(res, u, p, t) + res[1] = u[1][1] - 1 + res[2] = u[end][1] + end + + prob_bvp_linear_function = ODEFunction( + prob_bvp_linear_f!, analytic = prob_bvp_linear_analytic) + prob_bvp_linear_tspan = (0.0, 1.0) + prob_bvp_linear = BVProblem( + prob_bvp_linear_function, prob_bvp_linear_bc!, [1.0, 0.0], prob_bvp_linear_tspan, λ) + testTol = 1e-6 + + for order in (2, 3, 4, 5, 6) + s = Symbol("MIRK$(order)") + @eval mirk_solver(::Val{$order}) = $(s)() + end + + @testset "MIRK$order" for order in (2, 3, 4, 5, 6) + sol = solve(prob_bvp_linear, mirk_solver(Val(order)); dt = 0.001) + @test sol(0.001)≈[0.998687464, -1.312035941] atol=testTol + end +end diff --git a/test/mirk/mirk_convergence_tests.jl b/test/mirk/mirk_convergence_tests.jl index e2ddc855..1f21ad37 100644 --- a/test/mirk/mirk_convergence_tests.jl +++ b/test/mirk/mirk_convergence_tests.jl @@ -81,7 +81,7 @@ end @testset "Problem: $i" for i in (1, 2, 5, 6) prob = probArr[i] @testset "MIRK$order" for order in (2, 3, 4, 5, 6) - @time sol = solve(prob, mirk_solver(Val(order)); dt = 0.2) + sol = solve(prob, mirk_solver(Val(order)); dt = 0.2) @test norm(diff(first.(sol.u)) .+ 0.2, Inf) + abs(sol[1][1] - 5) < affineTol end end @@ -93,7 +93,7 @@ end @testset "Problem: $i" for i in (3, 4, 7, 8) prob = probArr[i] @testset "MIRK$order" for (i, order) in enumerate((2, 3, 4, 5, 6)) - @time sim = test_convergence( + sim = test_convergence( dts, prob, mirk_solver(Val(order)); abstol = 1e-8, reltol = 1e-8) @test sim.𝒪est[:final]≈order atol=testTol end diff --git a/test/mirk/vectorofvector_initials.jl b/test/mirk/vectorofvector_initials.jl deleted file mode 100644 index ec46f4dc..00000000 --- a/test/mirk/vectorofvector_initials.jl +++ /dev/null @@ -1,71 +0,0 @@ -using BoundaryValueDiffEq, Test, OrdinaryDiffEq - -#System Constants -ss = 1 #excitatory parameter -sj = 0 #inhibitory parameter -glb = 0.05 -el = -70 -gnab = 3 -ena = 50 -gkb = 5 -ek = -90 -gtb = 2 -et = 90 -gex = 0.1 -vex = 0 -gsyn = 0.13 -vsyn = -85 -iext = 0.41 -eps = 1 -qht = 2.5 - -#System functions -function f(v, h, r) - -(glb * (v - el) + - gnab * (1 / (1 + exp(-(v + 37) / 7)))^3 * h * (v - ena) + - gkb * (0.75 * (1 - h))^4 * (v - ek) + - gtb * (1 / (1 + exp(-(v + 60) / 6.2)))^2 * r * (v - et)) - gex * ss * (v - vex) - - gsyn * sj * (v - vsyn) + iext -end - -function g(v, h) - eps * ((1 / (1 + exp((v + 41) / 4))) - h) / - (1 / ((0.128 * exp(-(v + 46) / 18)) + (4 / (1 + exp(-(v + 23) / 5))))) -end - -function k(v, r) - qht * ((1 / (1 + exp((v + 84) / 4))) - r) / ((28 + exp(-(v + 25) / 10.5))) -end - -#Dynamical System -function TC!(du, u, p, t) - v, h, r = u - - du[1] = dv = f(v, h, r) - du[2] = dh = g(v, h) - du[3] = dr = k(v, r) -end - -#Finding initial guesses by forward integration -T = 7.588145762136627 #orbit length -u0 = [-40.296570996984855, 0.7298857398191566, 0.0011680534089275774] -tspan = (0.0, T) -prob = ODEProblem(TC!, u0, tspan, dt = 0.01) -sol = solve(prob, Rodas4P(), reltol = 1e-12, abstol = 1e-12, saveat = 0.5) - -# The BVP set up -# This is not really kind of Two-Point BVP we support. -function bc_po!(residual, u, p, t) - residual[1] = u[1][1] - u[end][1] - residual[2] = u[1][2] - u[end][2] - residual[3] = u[1][3] - u[end][3] -end - -#This is the part of the code that has problems -bvp1 = BVProblem(TC!, bc_po!, sol.u, tspan) -sol6 = solve(bvp1, MIRK6(); dt = 0.5) -@test SciMLBase.successful_retcode(sol6.retcode) - -bvp1 = BVProblem(TC!, bc_po!, zero(first(sol.u)), tspan) -sol6 = solve(bvp1, MIRK6(); dt = 0.1, abstol = 1e-15) -@test SciMLBase.successful_retcode(sol6.retcode) diff --git a/test/mirk/vectorofvector_initials_tests.jl b/test/mirk/vectorofvector_initials_tests.jl new file mode 100644 index 00000000..3c75b01b --- /dev/null +++ b/test/mirk/vectorofvector_initials_tests.jl @@ -0,0 +1,71 @@ +@testitem "VectorOfVector Initial Condition" begin + #System Constants + ss = 1 #excitatory parameter + sj = 0 #inhibitory parameter + glb = 0.05 + el = -70 + gnab = 3 + ena = 50 + gkb = 5 + ek = -90 + gtb = 2 + et = 90 + gex = 0.1 + vex = 0 + gsyn = 0.13 + vsyn = -85 + iext = 0.41 + eps = 1 + qht = 2.5 + + #System functions + function f(v, h, r) + -(glb * (v - el) + + gnab * (1 / (1 + exp(-(v + 37) / 7)))^3 * h * (v - ena) + + gkb * (0.75 * (1 - h))^4 * (v - ek) + + gtb * (1 / (1 + exp(-(v + 60) / 6.2)))^2 * r * (v - et)) - gex * ss * (v - vex) - + gsyn * sj * (v - vsyn) + iext + end + + function g(v, h) + eps * ((1 / (1 + exp((v + 41) / 4))) - h) / + (1 / ((0.128 * exp(-(v + 46) / 18)) + (4 / (1 + exp(-(v + 23) / 5))))) + end + + function k(v, r) + qht * ((1 / (1 + exp((v + 84) / 4))) - r) / ((28 + exp(-(v + 25) / 10.5))) + end + + #Dynamical System + function TC!(du, u, p, t) + v, h, r = u + + du[1] = dv = f(v, h, r) + du[2] = dh = g(v, h) + du[3] = dr = k(v, r) + end + + #Finding initial guesses by forward integration + T = 7.588145762136627 #orbit length + u0 = [-40.296570996984855, 0.7298857398191566, 0.0011680534089275774] + tspan = (0.0, T) + prob = ODEProblem(TC!, u0, tspan, dt = 0.01) + sol = solve(prob, Rodas4P(), reltol = 1e-12, abstol = 1e-12, saveat = 0.5) + + # The BVP set up + # This is not really kind of Two-Point BVP we support. + function bc_po!(residual, u, p, t) + residual[1] = u[1][1] - u[end][1] + residual[2] = u[1][2] - u[end][2] + residual[3] = u[1][3] - u[end][3] + end + + #This is the part of the code that has problems + bvp1 = BVProblem(TC!, bc_po!, sol.u, tspan) + sol6 = solve(bvp1, MIRK6(); dt = 0.5) + @test SciMLBase.successful_retcode(sol6.retcode) + + bvp1 = BVProblem(TC!, bc_po!, zero(first(sol.u)), tspan) + sol6 = solve(bvp1, MIRK6(); dt = 0.1, abstol = 1e-15) + @test SciMLBase.successful_retcode(sol6.retcode) +end From ea48380b0316d6b9ac5e76da694fb4abdcfc0235 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Thu, 21 Mar 2024 14:15:09 -0400 Subject: [PATCH 13/24] Reactivate NLLS Tests --- Manifest.toml | 4 +- src/solve/mirk.jl | 3 +- ...nlinear_least_squares.jl => nlls_tests.jl} | 46 +++++++++---------- 3 files changed, 26 insertions(+), 27 deletions(-) rename test/mirk/{nonlinear_least_squares.jl => nlls_tests.jl} (80%) diff --git a/Manifest.toml b/Manifest.toml index 7c6f1df9..1c6ad73a 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -671,9 +671,9 @@ version = "1.6.3" [[deps.OrdinaryDiffEq]] deps = ["ADTypes", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastBroadcast", "FastClosures", "FillArrays", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "IfElse", "InteractiveUtils", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "MacroTools", "MuladdMacro", "NonlinearSolve", "Polyester", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SimpleUnPack", "SparseArrays", "SparseDiffTools", "StaticArrayInterface", "StaticArrays", "TruncatedStacktraces"] -git-tree-sha1 = "287159684e32db56c82dbf545004a7884c6e5198" +git-tree-sha1 = "91079af18db922354197eeae2a17b177079e24c1" uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -version = "6.74.0" +version = "6.74.1" [[deps.PackageExtensionCompat]] git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 89a22027..4f3de3db 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -146,7 +146,7 @@ function SciMLBase.solve!(cache::MIRKCache) while SciMLBase.successful_retcode(info) && defect_norm > abstol nlprob = __construct_nlproblem(cache, recursive_flatten(y₀)) - sol_nlprob = solve(nlprob, alg.nlsolve; abstol, kwargs..., + sol_nlprob = __solve(nlprob, alg.nlsolve; abstol, kwargs..., alias_u0 = __default_alias_u0(alg.nlsolve)) recursive_unflatten!(cache.y₀, sol_nlprob.u) @@ -188,6 +188,7 @@ function SciMLBase.solve!(cache::MIRKCache) end u = [reshape(y, cache.in_size) for y in cache.y₀] + # TODO: Return `nlsol` as original return DiffEqBase.build_solution(prob, alg, cache.mesh, u; interp = MIRKInterpolation(cache.mesh, u, cache), retcode = info) end diff --git a/test/mirk/nonlinear_least_squares.jl b/test/mirk/nlls_tests.jl similarity index 80% rename from test/mirk/nonlinear_least_squares.jl rename to test/mirk/nlls_tests.jl index d50d4633..a2576b0f 100644 --- a/test/mirk/nonlinear_least_squares.jl +++ b/test/mirk/nlls_tests.jl @@ -1,9 +1,9 @@ -using BoundaryValueDiffEq, LinearAlgebra, Test +@testitem "Overconstrained BVP" begin + using LinearAlgebra -@testset "Overconstrained BVP" begin SOLVERS = [mirk(; nlsolve) for mirk in (MIRK4, MIRK5, MIRK6), - nlsolve in (LevenbergMarquardt(), GaussNewton(), nothing)] + nlsolve in (LevenbergMarquardt(), GaussNewton(), TrustRegion(), nothing)] # OOP MP-BVP f1(u, p, t) = [u[2], -u[1]] @@ -20,7 +20,7 @@ using BoundaryValueDiffEq, LinearAlgebra, Test bvp1 = BVProblem(BVPFunction{false}(f1, bc1; bcresid_prototype = zeros(3)), u0, tspan) for solver in SOLVERS - @time sol = solve(bvp1, solver; verbose = false, dt = 1.0) + sol = solve(bvp1, solver; verbose = false, dt = 1.0) @test norm(bc1(sol, nothing, tspan), Inf) < 1e-2 end @@ -44,7 +44,7 @@ using BoundaryValueDiffEq, LinearAlgebra, Test bvp2 = BVProblem(BVPFunction{true}(f1!, bc1!; bcresid_prototype = zeros(3)), u0, tspan) for solver in SOLVERS - @time sol = solve(bvp2, solver; verbose = false, dt = 1.0) + sol = solve(bvp2, solver; verbose = false, dt = 1.0) resid_f = Array{Float64}(undef, 3) bc1!(resid_f, sol, nothing, sol.t) @test norm(resid_f, Inf) < 1e-2 @@ -61,7 +61,7 @@ using BoundaryValueDiffEq, LinearAlgebra, Test tspan) for solver in SOLVERS - @time sol = solve(bvp3, solver; verbose = false, dt = 1.0) + sol = solve(bvp3, solver; verbose = false, dt = 1.0) @test norm(vcat(bc1a(sol[1], nothing), bc1b(sol[end], nothing)), Inf) < 1e-2 end @@ -76,8 +76,7 @@ using BoundaryValueDiffEq, LinearAlgebra, Test tspan) for solver in SOLVERS - @time sol = solve( - bvp3, solver; verbose = false, dt = 1.0, abstol = 1e-3, reltol = 1e-3) + sol = solve(bvp3, solver; verbose = false, dt = 1.0, abstol = 1e-3, reltol = 1e-3) resida = Array{Float64}(undef, 1) residb = Array{Float64}(undef, 2) bc1a!(resida, sol(0.0), nothing) @@ -88,17 +87,18 @@ end # This is not a very meaningful problem, but it tests that our solvers are not throwing an # error -# These tests are taking far too long currently and failing -#= -@testset "Underconstrained BVP: Rod BVP" begin +@testitem "Underconstrained BVP: Rod BVP" begin + using LinearAlgebra + # Force normal form for GN - SOLVERS = [mirk(; nlsolve) for mirk in (MIRK4, MIRK5, MIRK6), - nlsolve in (TrustRegion(), GaussNewton(), nothing)] + SOLVERS = [mirk(; nlsolve) + for mirk in (MIRK4, MIRK5, MIRK6), + nlsolve in (TrustRegion(), GaussNewton(), LevenbergMarquardt(), nothing)] function hat(y) return [0 -y[3] y[2] - y[3] 0 -y[1] - -y[2] y[1] 0] + y[3] 0 -y[1] + -y[2] y[1] 0] end function inv_hat(skew) @@ -186,18 +186,16 @@ end rod_ode!(dy, y, p, t) = rod_ode!(dy, y, p, t, inv(Kse), inv(Kbt), rho, A, g) y0 = vcat(p0, R0, zeros(6)) p = vcat(p0, R0, pL, RL) - prob_tp = TwoPointBVProblem(rod_ode!, (bc_a!, bc_b!), y0, tspan, p, - bcresid_prototype = (zeros(6), zeros(6))) - prob = BVProblem(BVPFunction(rod_ode!, bc!; bcresid_prototype = zeros(12)), y0, tspan, - p) + prob_tp = TwoPointBVProblem( + rod_ode!, (bc_a!, bc_b!), y0, tspan, p, bcresid_prototype = (zeros(6), zeros(6))) + prob = BVProblem( + BVPFunction(rod_ode!, bc!; bcresid_prototype = zeros(12)), y0, tspan, p) for solver in SOLVERS - @time sol = solve(prob_tp, solver; verbose = false, dt = 0.1, abstol = 1e-3, - reltol = 1e-3) + sol = solve( + prob_tp, solver; verbose = false, dt = 0.1, abstol = 1e-3, reltol = 1e-3) @test SciMLBase.successful_retcode(sol.retcode) - @time sol = solve(prob, solver; verbose = false, dt = 0.1, abstol = 1e-3, - reltol = 1e-3) + sol = solve(prob, solver; verbose = false, dt = 0.1, abstol = 1e-3, reltol = 1e-3) @test SciMLBase.successful_retcode(sol.retcode) end end -=# From 35d01ce1a3e6944ecc6e420c0aa01409e4d02a6a Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Thu, 21 Mar 2024 18:02:32 -0400 Subject: [PATCH 14/24] simd the loop --- Manifest.toml | 6 ++++-- src/solve/mirk.jl | 3 +-- src/solve/multiple_shooting.jl | 1 - src/utils.jl | 11 +++-------- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 1c6ad73a..a490a1ff 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -609,9 +609,11 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "d52bac2b94358b4b960cbfb896d5193d67f3ff09" +git-tree-sha1 = "13232c70f50a05f98c7206190ab33dd48fa39c5b" +repo-rev = "ap/reliable_aliasing" +repo-url = "https://github.com/SciML/NonlinearSolve.jl.git" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.8.0" +version = "3.8.1" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 4f3de3db..603ea123 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -146,8 +146,7 @@ function SciMLBase.solve!(cache::MIRKCache) while SciMLBase.successful_retcode(info) && defect_norm > abstol nlprob = __construct_nlproblem(cache, recursive_flatten(y₀)) - sol_nlprob = __solve(nlprob, alg.nlsolve; abstol, kwargs..., - alias_u0 = __default_alias_u0(alg.nlsolve)) + sol_nlprob = __solve(nlprob, alg.nlsolve; abstol, kwargs..., alias_u0 = true) recursive_unflatten!(cache.y₀, sol_nlprob.u) info = sol_nlprob.retcode diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index fcf99c0a..7906f37d 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -126,7 +126,6 @@ function __solve_nlproblem!( # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) - # FIXME: This is not safe for polyalgorithms __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) return nothing diff --git a/src/utils.jl b/src/utils.jl index 2a0f5340..0576e9e4 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -63,9 +63,9 @@ end # `w` to the GPU too many times. Instead if we iterate of w and w′ we save # that cost. Our main cost is anyways going to be due to a large `u0` and # we are going to use GPUs for that -function __maybe_matmul!(z, A, b, α = eltype(z)(1), β = eltype(z)(0)) - for j in eachindex(b) - z .= α .* A[:, j] .* b[j] .+ β .* z +@views function __maybe_matmul!(z, A, b, α = eltype(z)(1), β = eltype(z)(0)) + @simd ivdep for j in eachindex(b) + @inbounds @. z = α * A[:, j] * b[j] + β * z end return z end @@ -390,8 +390,3 @@ end end @inline (f::__Fix3{F})(a, b) where {F} = f.f(a, b, f.x) - -# Aliasing -@inline __default_alias_u0(::Nothing) = false -@inline __default_alias_u0(::NonlinearSolvePolyAlgorithm) = false -@inline __default_alias_u0(::Any) = true From 4aa8a4cb59bd3d09f0fe88ee110b820c364f084e Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Fri, 22 Mar 2024 12:21:14 -0400 Subject: [PATCH 15/24] Lower the convergence tolerance --- test/mirk/nlls_tests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/mirk/nlls_tests.jl b/test/mirk/nlls_tests.jl index a2576b0f..37c5e6c3 100644 --- a/test/mirk/nlls_tests.jl +++ b/test/mirk/nlls_tests.jl @@ -193,9 +193,9 @@ end for solver in SOLVERS sol = solve( - prob_tp, solver; verbose = false, dt = 0.1, abstol = 1e-3, reltol = 1e-3) + prob_tp, solver; verbose = false, dt = 0.1, abstol = 1e-1, reltol = 1e-1) @test SciMLBase.successful_retcode(sol.retcode) - sol = solve(prob, solver; verbose = false, dt = 0.1, abstol = 1e-3, reltol = 1e-3) + sol = solve(prob, solver; verbose = false, dt = 0.1, abstol = 1e-1, reltol = 1e-1) @test SciMLBase.successful_retcode(sol.retcode) end end From 9192bd0d6734d272ac8b31d843844f4162a4b4e9 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Fri, 22 Mar 2024 14:14:51 -0400 Subject: [PATCH 16/24] Disable Preallocation Tools warnings --- Manifest.toml | 8 +++----- Project.toml | 1 + src/BoundaryValueDiffEq.jl | 9 ++++++--- src/types.jl | 12 ++++++++++-- test/mirk/vectorofvector_initials_tests.jl | 6 +++--- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index a490a1ff..a6574ebf 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.10.2" manifest_format = "2.0" -project_hash = "a953673b82afa1e31012434ca17ab0a1861c936d" +project_hash = "ad2f92b76844532cf3e0a4abe6a85be7751b1309" [[deps.ADTypes]] git-tree-sha1 = "016833eb52ba2d6bea9fcb50ca295980e728ee24" @@ -609,11 +609,9 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "13232c70f50a05f98c7206190ab33dd48fa39c5b" -repo-rev = "ap/reliable_aliasing" -repo-url = "https://github.com/SciML/NonlinearSolve.jl.git" +git-tree-sha1 = "d52bac2b94358b4b960cbfb896d5193d67f3ff09" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.8.1" +version = "3.8.0" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" diff --git a/Project.toml b/Project.toml index 2307c8d6..51e98aaa 100644 --- a/Project.toml +++ b/Project.toml @@ -14,6 +14,7 @@ FastClosures = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index 67f2d8ce..4e3d9e57 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -4,8 +4,10 @@ import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidat @recompile_invalidations begin using ADTypes, Adapt, DiffEqBase, ForwardDiff, LinearAlgebra, NonlinearSolve, - OrdinaryDiffEq, PreallocationTools, Preferences, RecursiveArrayTools, Reexport, - SciMLBase, Setfield, SparseDiffTools + OrdinaryDiffEq, Preferences, RecursiveArrayTools, Reexport, SciMLBase, Setfield, + SparseDiffTools + + using PreallocationTools: PreallocationTools, DiffCache # Special Matrix Types using BandedMatrices, FastAlmostBandedMatrices, SparseArrays @@ -16,7 +18,8 @@ import PrecompileTools: @compile_workload, @setup_workload, @recompile_invalidat import ConcreteStructs: @concrete import DiffEqBase: solve import FastClosures: @closure - import ForwardDiff: pickchunksize + import ForwardDiff: ForwardDiff, pickchunksize + import Logging import RecursiveArrayTools: ArrayPartition, DiffEqArray import SciMLBase: AbstractDiffEqInterpolation, StandardBVProblem, __solve, _unwrap_val import SparseDiffTools: AbstractSparseADType diff --git a/src/types.jl b/src/types.jl index bc45b43f..c09e2922 100644 --- a/src/types.jl +++ b/src/types.jl @@ -166,6 +166,14 @@ end __maybe_allocate_diffcache(x::DiffCache, chunksize) = DiffCache(similar(x.du), chunksize) __maybe_allocate_diffcache(x::FakeDiffCache, _) = FakeDiffCache(similar(x.du)) -PreallocationTools.get_tmp(dc::FakeDiffCache, _) = dc.du - const MaybeDiffCache = Union{DiffCache, FakeDiffCache} + +## get_tmp shows a warning as it should on cache exapansion, this behavior however is +## expected for adaptive BVP solvers so we write our own `get_tmp` and drop the warning logs +@inline get_tmp(dc::FakeDiffCache, u) = dc.du + +@inline function get_tmp(dc, u) + return Logging.with_logger(Logging.NullLogger()) do + PreallocationTools.get_tmp(dc, u) + end +end diff --git a/test/mirk/vectorofvector_initials_tests.jl b/test/mirk/vectorofvector_initials_tests.jl index 3c75b01b..7a2be9a7 100644 --- a/test/mirk/vectorofvector_initials_tests.jl +++ b/test/mirk/vectorofvector_initials_tests.jl @@ -21,9 +21,9 @@ #System functions function f(v, h, r) -(glb * (v - el) + - gnab * (1 / (1 + exp(-(v + 37) / 7)))^3 * h * (v - ena) + - gkb * (0.75 * (1 - h))^4 * (v - ek) + - gtb * (1 / (1 + exp(-(v + 60) / 6.2)))^2 * r * (v - et)) - gex * ss * (v - vex) - + gnab * (1 / (1 + exp(-(v + 37) / 7)))^3 * h * (v - ena) + + gkb * (0.75 * (1 - h))^4 * (v - ek) + + gtb * (1 / (1 + exp(-(v + 60) / 6.2)))^2 * r * (v - et)) - gex * ss * (v - vex) - gsyn * sj * (v - vsyn) + iext end From 0effc0139fc902669ec70192d8eb57387af3e6f0 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Fri, 22 Mar 2024 16:25:56 -0400 Subject: [PATCH 17/24] Add JET tests for MIRK --- Manifest.toml | 14 ++--- Project.toml | 41 +++++++------- src/interpolation.jl | 9 +-- test/mirk/interpolation_tests.jl | 36 ------------ ...nvergence_tests.jl => mirk_basic_tests.jl} | 55 ++++++++++++++++++- test/misc/affine_geodesic.jl | 3 +- 6 files changed, 89 insertions(+), 69 deletions(-) delete mode 100644 test/mirk/interpolation_tests.jl rename test/mirk/{mirk_convergence_tests.jl => mirk_basic_tests.jl} (68%) diff --git a/Manifest.toml b/Manifest.toml index a6574ebf..ab514172 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.10.2" manifest_format = "2.0" -project_hash = "ad2f92b76844532cf3e0a4abe6a85be7751b1309" +project_hash = "5a9701ab315469eb074470e987a001fa3e379b21" [[deps.ADTypes]] git-tree-sha1 = "016833eb52ba2d6bea9fcb50ca295980e728ee24" @@ -57,9 +57,9 @@ version = "7.9.0" [[deps.ArrayLayouts]] deps = ["FillArrays", "LinearAlgebra"] -git-tree-sha1 = "2aeaeaff72cdedaa0b5f30dfb8c1f16aefdac65d" +git-tree-sha1 = "6404a564c24a994814106c374bec893195e19bac" uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "1.7.0" +version = "1.8.0" weakdeps = ["SparseArrays"] [deps.ArrayLayouts.extensions] @@ -265,8 +265,6 @@ version = "0.1.10" [[deps.FastAlmostBandedMatrices]] deps = ["ArrayInterface", "ArrayLayouts", "BandedMatrices", "ConcreteStructs", "LazyArrays", "LinearAlgebra", "MatrixFactorizations", "PrecompileTools", "Reexport"] git-tree-sha1 = "9dc913faf8552fd09b92a0d7fcc25f1d5609d795" -repo-rev = "main" -repo-url = "https://github.com/SciML/FastAlmostBandedMatrices.jl" uuid = "9d29842c-ecb8-4973-b1e9-a27b1157504e" version = "0.1.1" @@ -609,9 +607,11 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "d52bac2b94358b4b960cbfb896d5193d67f3ff09" +git-tree-sha1 = "0e464ca0e5d44a88c91f394c3f9a9448523e378b" +repo-rev = "ap/tstable_findmin" +repo-url = "https://github.com/SciML/NonlinearSolve.jl.git" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.8.0" +version = "3.8.2" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" diff --git a/Project.toml b/Project.toml index 51e98aaa..e9c3e455 100644 --- a/Project.toml +++ b/Project.toml @@ -34,36 +34,37 @@ ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" BoundaryValueDiffEqODEInterfaceExt = "ODEInterface" [compat] -ADTypes = "0.2" +ADTypes = "0.2.6" Adapt = "4" Aqua = "0.8" -ArrayInterface = "7" -BandedMatrices = "1" -ConcreteStructs = "0.2" -DiffEqBase = "6.145" +ArrayInterface = "7.7" +BandedMatrices = "1.4" +ConcreteStructs = "0.2.3" +DiffEqBase = "6.146" DiffEqDevTools = "2.44" -FastAlmostBandedMatrices = "0.1" +FastAlmostBandedMatrices = "0.1.1" FastClosures = "0.3" -ForwardDiff = "0.10" +ForwardDiff = "0.10.36" JET = "0.8" -LinearAlgebra = "1.9" -LinearSolve = "2.20" -NonlinearSolve = "3.5" +LinearAlgebra = "1.10" +LinearSolve = "2.21" +Logging = "1.10" +NonlinearSolve = "3.8.1" ODEInterface = "0.5" -OrdinaryDiffEq = "6" +OrdinaryDiffEq = "6.63" PreallocationTools = "0.4" -PrecompileTools = "1" -Preferences = "1" -Random = "1" +PrecompileTools = "1.2" +Preferences = "1.4" +Random = "1.10" ReTestItems = "1.23.1" -RecursiveArrayTools = "3" -Reexport = "1.0" -SciMLBase = "2.12" +RecursiveArrayTools = "3.4" +Reexport = "1.2" +SciMLBase = "2.19" Setfield = "1" -SparseArrays = "1.9" -SparseDiffTools = "2.9" +SparseArrays = "1.10" +SparseDiffTools = "2.14" StaticArrays = "1.8.1" -Test = "1" +Test = "1.10" julia = "1.10" [extras] diff --git a/src/interpolation.jl b/src/interpolation.jl index 8ca5abf9..d94b13f5 100644 --- a/src/interpolation.jl +++ b/src/interpolation.jl @@ -1,6 +1,6 @@ -struct MIRKInterpolation{T1, T2} <: AbstractDiffEqInterpolation - t::T1 - u::T2 +@concrete struct MIRKInterpolation <: AbstractDiffEqInterpolation + t + u cache end @@ -9,11 +9,12 @@ function DiffEqBase.interp_summary(interp::MIRKInterpolation) end function (id::MIRKInterpolation)(tvals, idxs, deriv, p, continuity::Symbol = :left) - interpolation(tvals, id, idxs, deriv, p, continuity) + return interpolation(tvals, id, idxs, deriv, p, continuity) end function (id::MIRKInterpolation)(val, tvals, idxs, deriv, p, continuity::Symbol = :left) interpolation!(val, tvals, id, idxs, deriv, p, continuity) + return end # FIXME: Fix the interpolation outside the tspan diff --git a/test/mirk/interpolation_tests.jl b/test/mirk/interpolation_tests.jl deleted file mode 100644 index a5a8efd6..00000000 --- a/test/mirk/interpolation_tests.jl +++ /dev/null @@ -1,36 +0,0 @@ -@testitem "MIRK Interpolation" begin - using LinearAlgebra - - λ = 1 - function prob_bvp_linear_analytic(u, λ, t) - a = 1 / sqrt(λ) - return [(exp(-a * t) - exp((t - 2) * a)) / (1 - exp(-2 * a)), - (-a * exp(-t * a) - a * exp((t - 2) * a)) / (1 - exp(-2 * a))] - end - - function prob_bvp_linear_f!(du, u, p, t) - du[1] = u[2] - du[2] = 1 / p * u[1] - end - function prob_bvp_linear_bc!(res, u, p, t) - res[1] = u[1][1] - 1 - res[2] = u[end][1] - end - - prob_bvp_linear_function = ODEFunction( - prob_bvp_linear_f!, analytic = prob_bvp_linear_analytic) - prob_bvp_linear_tspan = (0.0, 1.0) - prob_bvp_linear = BVProblem( - prob_bvp_linear_function, prob_bvp_linear_bc!, [1.0, 0.0], prob_bvp_linear_tspan, λ) - testTol = 1e-6 - - for order in (2, 3, 4, 5, 6) - s = Symbol("MIRK$(order)") - @eval mirk_solver(::Val{$order}) = $(s)() - end - - @testset "MIRK$order" for order in (2, 3, 4, 5, 6) - sol = solve(prob_bvp_linear, mirk_solver(Val(order)); dt = 0.001) - @test sol(0.001)≈[0.998687464, -1.312035941] atol=testTol - end -end diff --git a/test/mirk/mirk_convergence_tests.jl b/test/mirk/mirk_basic_tests.jl similarity index 68% rename from test/mirk/mirk_convergence_tests.jl rename to test/mirk/mirk_basic_tests.jl index 1f21ad37..6e153990 100644 --- a/test/mirk/mirk_convergence_tests.jl +++ b/test/mirk/mirk_basic_tests.jl @@ -4,7 +4,7 @@ using BoundaryValueDiffEq for order in (2, 3, 4, 5, 6) s = Symbol("MIRK$(order)") - @eval mirk_solver(::Val{$order}) = $(s)() + @eval mirk_solver(::Val{$order}, args...; kwargs...) = $(s)(args...; kwargs...) end # First order test @@ -87,6 +87,22 @@ end end end +@testitem "JET: Runtime Dispatches" setup=[MIRKConvergenceTests] begin + using JET + + @testset "Problem: $i" for i in 1:8 + prob = probArr[i] + @testset "MIRK$order" for order in (2, 3, 4, 5, 6) + solver = mirk_solver(Val(order); + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))) + @test_opt target_modules=(NonlinearSolve, BoundaryValueDiffEq) solve( + prob, solver; dt = 0.2) + @test_call target_modules=(NonlinearSolve, BoundaryValueDiffEq) solve( + prob, solver; dt = 0.2) + end + end +end + @testitem "Convergence on Linear" setup=[MIRKConvergenceTests] begin using LinearAlgebra, DiffEqDevTools @@ -129,3 +145,40 @@ end @test_nowarn solve(bvp1, MIRK5(; jac_alg); dt = 0.05) @test_nowarn solve(bvp1, MIRK6(; jac_alg); dt = 0.05) end + +@testitem "Interpolation" begin + using LinearAlgebra + + λ = 1 + function prob_bvp_linear_analytic(u, λ, t) + a = 1 / sqrt(λ) + return [(exp(-a * t) - exp((t - 2) * a)) / (1 - exp(-2 * a)), + (-a * exp(-t * a) - a * exp((t - 2) * a)) / (1 - exp(-2 * a))] + end + + function prob_bvp_linear_f!(du, u, p, t) + du[1] = u[2] + du[2] = 1 / p * u[1] + end + function prob_bvp_linear_bc!(res, u, p, t) + res[1] = u[1][1] - 1 + res[2] = u[end][1] + end + + prob_bvp_linear_function = ODEFunction( + prob_bvp_linear_f!, analytic = prob_bvp_linear_analytic) + prob_bvp_linear_tspan = (0.0, 1.0) + prob_bvp_linear = BVProblem( + prob_bvp_linear_function, prob_bvp_linear_bc!, [1.0, 0.0], prob_bvp_linear_tspan, λ) + testTol = 1e-6 + + for order in (2, 3, 4, 5, 6) + s = Symbol("MIRK$(order)") + @eval mirk_solver(::Val{$order}) = $(s)() + end + + @testset "MIRK$order" for order in (2, 3, 4, 5, 6) + sol = solve(prob_bvp_linear, mirk_solver(Val(order)); dt = 0.001) + @test sol(0.001)≈[0.998687464, -1.312035941] atol=testTol + end +end diff --git a/test/misc/affine_geodesic.jl b/test/misc/affine_geodesic.jl index 69fcc938..2543e891 100644 --- a/test/misc/affine_geodesic.jl +++ b/test/misc/affine_geodesic.jl @@ -27,7 +27,8 @@ tspan = (0.0, 1.0) function bc1!(residual, u, p, t) mid = div(length(u[1]), 2) residual[1:mid] = u[1][1:mid] - a1 - return residual[(mid + 1):end] = u[end][1:mid] - a2 + residual[(mid + 1):end] = u[end][1:mid] - a2 + return end function chart_log_problem!(du, u, params, t) From 7f41f1c4b6a26fb48d8d4c79fd853d1cf4e5e638 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Fri, 22 Mar 2024 18:34:11 -0400 Subject: [PATCH 18/24] Better handling of PolyAlgs --- src/BoundaryValueDiffEq.jl | 2 + src/default_nlsolve.jl | 49 +++++++++++++++ src/solve/mirk.jl | 95 +++++++++++++++++------------ src/solve/multiple_shooting.jl | 9 ++- src/solve/single_shooting.jl | 3 +- test/mirk/mirk_basic_tests.jl | 53 ++++++++++++---- test/misc/affine_geodesic.jl | 52 ---------------- test/misc/initial_guess.jl | 82 ------------------------- test/misc/manifolds_tests.jl | 83 +++++++++++++++++++++++++ test/misc/non_vector_input_tests.jl | 71 +++++++++++++++++++++ test/misc/non_vector_inputs.jl | 60 ------------------ 11 files changed, 310 insertions(+), 249 deletions(-) create mode 100644 src/default_nlsolve.jl delete mode 100644 test/misc/affine_geodesic.jl delete mode 100644 test/misc/initial_guess.jl create mode 100644 test/misc/manifolds_tests.jl create mode 100644 test/misc/non_vector_input_tests.jl delete mode 100644 test/misc/non_vector_inputs.jl diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index 4e3d9e57..2afa73dc 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -45,6 +45,8 @@ include("sparse_jacobians.jl") include("adaptivity.jl") include("interpolation.jl") +include("default_nlsolve.jl") + function __solve(prob::BVProblem, alg::BoundaryValueDiffEqAlgorithm, args...; kwargs...) cache = init(prob, alg, args...; kwargs...) return solve!(cache) diff --git a/src/default_nlsolve.jl b/src/default_nlsolve.jl new file mode 100644 index 00000000..baa2b8de --- /dev/null +++ b/src/default_nlsolve.jl @@ -0,0 +1,49 @@ +# Currently there are some problems with the default NonlinearSolver selection for +# BoundaryValueDiffEq +# See https://github.com/SciML/BoundaryValueDiffEq.jl/issues/175 +# and https://github.com/SciML/BoundaryValueDiffEq.jl/issues/163 +# These are not meant to be user facing and we should delete these once those issues are +# resolved +function __FastShortcutBVPCompatibleNLLSPolyalg( + ::Type{T} = Float64; concrete_jac = nothing, linsolve = nothing, + precs = NonlinearSolve.DEFAULT_PRECS, autodiff = nothing, kwargs...) where {T} + if NonlinearSolve.__is_complex(T) + algs = (GaussNewton(; concrete_jac, linsolve, precs, autodiff, kwargs...), + LevenbergMarquardt(; + linsolve, precs, autodiff, disable_geodesic = Val(true), kwargs...), + LevenbergMarquardt(; linsolve, precs, autodiff, kwargs...)) + else + algs = (GaussNewton(; concrete_jac, linsolve, precs, autodiff, kwargs...), + LevenbergMarquardt(; + linsolve, precs, disable_geodesic = Val(true), autodiff, kwargs...), + TrustRegion(; concrete_jac, linsolve, precs, autodiff, kwargs...), + GaussNewton(; concrete_jac, linsolve, precs, + linesearch = LineSearchesJL(; method = BackTracking()), + autodiff, kwargs...), + LevenbergMarquardt(; linsolve, precs, autodiff, kwargs...)) + end + return NonlinearSolvePolyAlgorithm(algs, Val(:NLLS)) +end + +function __FastShortcutBVPCompatibleNonlinearPolyalg( + ::Type{T} = Float64; concrete_jac = nothing, linsolve = nothing, + precs = NonlinearSolve.DEFAULT_PRECS, autodiff = nothing) where {T} + if NonlinearSolve.__is_complex(T) + algs = (NewtonRaphson(; concrete_jac, linsolve, precs, autodiff),) + else + algs = (NewtonRaphson(; concrete_jac, linsolve, precs, autodiff), + NewtonRaphson(; concrete_jac, linsolve, precs, + linesearch = LineSearchesJL(; method = BackTracking()), autodiff), + TrustRegion(; concrete_jac, linsolve, precs, autodiff)) + end + return NonlinearSolvePolyAlgorithm(algs, Val(:NLS)) +end + +@inline __concrete_nonlinearsolve_algorithm(prob, alg) = alg +@inline function __concrete_nonlinearsolve_algorithm(prob, ::Nothing) + if prob isa NonlinearLeastSquaresProblem + return __FastShortcutBVPCompatibleNLLSPolyalg(eltype(prob.u0)) + else + return __FastShortcutBVPCompatibleNonlinearPolyalg(eltype(prob.u0)) + end +end diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 603ea123..7736f207 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -138,58 +138,73 @@ function __split_mirk_kwargs(; end function SciMLBase.solve!(cache::MIRKCache) - (defect_threshold, MxNsub, abstol, adaptive, _), kwargs = __split_mirk_kwargs(; - cache.kwargs...) - (; y, y₀, prob, alg, mesh, mesh_dt, TU, ITU) = cache + (_, _, abstol, adaptive, _), kwargs = __split_mirk_kwargs(; cache.kwargs...) info::ReturnCode.T = ReturnCode.Success - defect_norm = 2 * abstol - while SciMLBase.successful_retcode(info) && defect_norm > abstol - nlprob = __construct_nlproblem(cache, recursive_flatten(y₀)) - sol_nlprob = __solve(nlprob, alg.nlsolve; abstol, kwargs..., alias_u0 = true) - recursive_unflatten!(cache.y₀, sol_nlprob.u) + # We do the first iteration outside the loop to preserve type-stability of the + # `original` field of the solution + sol_nlprob, info, defect_norm = __perform_mirk_iteration( + cache, abstol, adaptive; kwargs...) - info = sol_nlprob.retcode + if adaptive + while SciMLBase.successful_retcode(info) && defect_norm > abstol + sol_nlprob, info, defect_norm = __perform_mirk_iteration( + cache, abstol, adaptive; kwargs...) + end + end - !adaptive && break + u = [reshape(y, cache.in_size) for y in cache.y₀] - if info == ReturnCode.Success - defect_norm = defect_estimate!(cache) - # The defect is greater than 10%, the solution is not acceptable - defect_norm > defect_threshold && (info = ReturnCode.Failure) - end + odesol = DiffEqBase.build_solution(cache.prob, cache.alg, cache.mesh, u; + interp = MIRKInterpolation(cache.mesh, u, cache), retcode = info) + return __build_solution(cache.prob, odesol, sol_nlprob) +end + +function __perform_mirk_iteration(cache::MIRKCache, abstol, adaptive; kwargs...) + nlprob = __construct_nlproblem(cache, recursive_flatten(cache.y₀)) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(nlprob, cache.alg.nlsolve) + sol_nlprob = __solve(nlprob, nlsolve_alg; abstol, kwargs..., alias_u0 = true) + recursive_unflatten!(cache.y₀, sol_nlprob.u) + + defect_norm = 2 * abstol - if info == ReturnCode.Success - if defect_norm > abstol - # We construct a new mesh to equidistribute the defect - mesh, mesh_dt, _, info = mesh_selector!(cache) - if info == ReturnCode.Success - __append_similar!(cache.y₀, length(cache.mesh), cache.M) - for (i, m) in enumerate(cache.mesh) - interp_eval!(cache.y₀[i], cache, m, mesh, mesh_dt) - end - __expand_cache!(cache) + # Early terminate if non-adaptive + adaptive || return sol_nlprob, sol_nlprob.retcode, defect_norm + + info = sol_nlprob.retcode + + if info == ReturnCode.Success # Nonlinear Solve was successful + defect_norm = defect_estimate!(cache) + # The defect is greater than 10%, the solution is not acceptable + defect_norm > cache.alg.defect_threshold && (info = ReturnCode.Failure) + end + + if info == ReturnCode.Success # Nonlinear Solve Successful and defect norm is acceptable + if defect_norm > abstol + # We construct a new mesh to equidistribute the defect + mesh, mesh_dt, _, info = mesh_selector!(cache) + if info == ReturnCode.Success + __append_similar!(cache.y₀, length(cache.mesh), cache.M) + for (i, m) in enumerate(cache.mesh) + interp_eval!(cache.y₀[i], cache, m, mesh, mesh_dt) end - end - else - # We cannot obtain a solution for the current mesh - if 2 * (length(cache.mesh) - 1) > MxNsub - # New mesh would be too large - info = ReturnCode.Failure - else - half_mesh!(cache) __expand_cache!(cache) - recursive_fill!(cache.y₀, 0) - info = ReturnCode.Success # Force a restart - defect_norm = 2 * abstol end end + else # Something bad happened + # We cannot obtain a solution for the current mesh + if 2 * (length(cache.mesh) - 1) > cache.alg.max_num_subintervals + # New mesh would be too large + info = ReturnCode.Failure + else + half_mesh!(cache) + __expand_cache!(cache) + recursive_fill!(cache.y₀, 0) + info = ReturnCode.Success # Force a restart + end end - u = [reshape(y, cache.in_size) for y in cache.y₀] - # TODO: Return `nlsol` as original - return DiffEqBase.build_solution(prob, alg, cache.mesh, u; - interp = MIRKInterpolation(cache.mesh, u, cache), retcode = info) + return sol_nlprob, info, defect_norm end # Constructing the Nonlinear Problem diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index 7906f37d..2b37c5c7 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -10,6 +10,8 @@ function __solve(prob::BVProblem, _alg::MultipleShooting; odesolve_kwargs = (;), ig, T, N, Nig, u0 = __extract_problem_details(prob; dt = 0.1) has_initial_guess = _unwrap_val(ig) + @assert u0 isa AbstractVector "Non-Vector Inputs for Multiple-Shooting hasn't been implemented yet!" + bcresid_prototype, resid_size = __get_bcresid_prototype(prob, u0) iip, bc, u0, u0_size = isinplace(prob), prob.f.bc, deepcopy(u0), size(u0) @@ -126,7 +128,8 @@ function __solve_nlproblem!( # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) - __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(prob, alg.nlsolve) + __solve(nlprob, nlsolve_alg; kwargs..., alias_u0 = true) return nothing end @@ -185,8 +188,8 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) - # FIXME: This is not safe for polyalgorithms - __solve(nlprob, alg.nlsolve; kwargs..., alias_u0 = true) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(prob, alg.nlsolve) + __solve(nlprob, nlsolve_alg; kwargs..., alias_u0 = true) return nothing end diff --git a/src/solve/single_shooting.jl b/src/solve/single_shooting.jl index 04e40fc9..abdff56e 100644 --- a/src/solve/single_shooting.jl +++ b/src/solve/single_shooting.jl @@ -72,7 +72,8 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), nlf = __unsafe_nonlinearfunction{iip}( loss_fn; jac_prototype, resid_prototype, jac = jac_fn) nlprob = __internal_nlsolve_problem(prob, resid_prototype, u0, nlf, vec(u0), prob.p) - nlsol = __solve(nlprob, alg.nlsolve; nlsolve_kwargs..., verbose, kwargs...) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(prob, alg.nlsolve) + nlsol = __solve(nlprob, nlsolve_alg; nlsolve_kwargs..., verbose, kwargs...) # There is no way to reinit with the same cache with different cache. But not saving # the internal values gives a significant speedup. So we just create a new cache diff --git a/test/mirk/mirk_basic_tests.jl b/test/mirk/mirk_basic_tests.jl index 6e153990..1fcf4cc4 100644 --- a/test/mirk/mirk_basic_tests.jl +++ b/test/mirk/mirk_basic_tests.jl @@ -54,18 +54,18 @@ bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) tspan = (0.0, 5.0) u0 = [5.0, -3.5] -probArr = [BVProblem(odef1!, boundary!, u0, tspan), - BVProblem(odef1, boundary, u0, tspan), - BVProblem(odef2!, boundary!, u0, tspan), - BVProblem(odef2, boundary, u0, tspan), +probArr = [BVProblem(odef1!, boundary!, u0, tspan, nlls = Val(false)), + BVProblem(odef1, boundary, u0, tspan, nlls = Val(false)), + BVProblem(odef2!, boundary!, u0, tspan, nlls = Val(false)), + BVProblem(odef2, boundary, u0, tspan, nlls = Val(false)), TwoPointBVProblem(odef1!, (boundary_two_point_a!, boundary_two_point_b!), - u0, tspan; bcresid_prototype), - TwoPointBVProblem( - odef1, (boundary_two_point_a, boundary_two_point_b), u0, tspan; bcresid_prototype), + u0, tspan; bcresid_prototype, nlls = Val(false)), + TwoPointBVProblem(odef1, (boundary_two_point_a, boundary_two_point_b), + u0, tspan; bcresid_prototype, nlls = Val(false)), TwoPointBVProblem(odef2!, (boundary_two_point_a!, boundary_two_point_b!), - u0, tspan; bcresid_prototype), - TwoPointBVProblem( - odef2, (boundary_two_point_a, boundary_two_point_b), u0, tspan; bcresid_prototype)] + u0, tspan; bcresid_prototype, nlls = Val(false)), + TwoPointBVProblem(odef2, (boundary_two_point_a, boundary_two_point_b), + u0, tspan; bcresid_prototype, nlls = Val(false))] testTol = 0.2 affineTol = 1e-2 @@ -93,7 +93,7 @@ end @testset "Problem: $i" for i in 1:8 prob = probArr[i] @testset "MIRK$order" for order in (2, 3, 4, 5, 6) - solver = mirk_solver(Val(order); + solver = mirk_solver(Val(order); nlsolve = NewtonRaphson(), jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))) @test_opt target_modules=(NonlinearSolve, BoundaryValueDiffEq) solve( prob, solver; dt = 0.2) @@ -182,3 +182,34 @@ end @test sol(0.001)≈[0.998687464, -1.312035941] atol=testTol end end + +@testitem "Swirling Flow III" begin + # Reported in https://github.com/SciML/BoundaryValueDiffEq.jl/issues/153 + eps = 0.01 + function swirling_flow!(du, u, p, t) + eps = p + du[1] = u[2] + du[2] = (u[1] * u[4] - u[3] * u[2]) / eps + du[3] = u[4] + du[4] = u[5] + du[5] = u[6] + du[6] = (-u[3] * u[6] - u[1] * u[2]) / eps + return + end + + function swirling_flow_bc!(res, u, p, t) + res[1] = u[1][1] + 1.0 + res[2] = u[1][3] + res[3] = u[1][4] + res[4] = u[end][1] - 1.0 + res[5] = u[end][3] + res[6] = u[end][4] + return + end + + tspan = (0.0, 1.0) + u0 = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + prob = BVProblem(swirling_flow!, swirling_flow_bc!, u0, tspan, eps) + + @test_nowarn solve(prob, MIRK4(); dt = 0.01) +end diff --git a/test/misc/affine_geodesic.jl b/test/misc/affine_geodesic.jl deleted file mode 100644 index 2543e891..00000000 --- a/test/misc/affine_geodesic.jl +++ /dev/null @@ -1,52 +0,0 @@ -using BoundaryValueDiffEq - -struct EmbeddedTorus - R::Float64 - r::Float64 -end - -function affine_connection!(M::EmbeddedTorus, Zc, i, a, Xc, Yc) - θ = a[1] .+ i[1] - sinθ, cosθ = sincos(θ) - Γ¹₂₂ = (M.R + M.r * cosθ) * sinθ / M.r - Γ²₁₂ = -M.r * sinθ / (M.R + M.r * cosθ) - - Zc[1] = Xc[2] * Γ¹₂₂ * Yc[2] - Zc[2] = Γ²₁₂ * (Xc[1] * Yc[2] + Xc[2] * Yc[1]) - return Zc -end - -M = EmbeddedTorus(3, 2) -a1 = [0.5, -1.2] -a2 = [-0.5, 0.3] -i = (0, 0) -solver = MIRK4() -dt = 0.05 -tspan = (0.0, 1.0) - -function bc1!(residual, u, p, t) - mid = div(length(u[1]), 2) - residual[1:mid] = u[1][1:mid] - a1 - residual[(mid + 1):end] = u[end][1:mid] - a2 - return -end - -function chart_log_problem!(du, u, params, t) - M, i = params - mid = div(length(u), 2) - a = u[1:mid] - dx = u[(mid + 1):end] - ddx = similar(dx) - affine_connection!(M, ddx, i, a, dx, dx) - ddx .*= -1 - du[1:mid] .= dx - du[(mid + 1):end] .= ddx - return du -end - -@testset "successful convergence" begin - u0 = [vcat(a1, zero(a1)), vcat(a2, zero(a1))] - bvp1 = BVProblem(chart_log_problem!, bc1!, u0, tspan, (M, i)) - sol1 = solve(bvp1, solver, dt = dt) - @test SciMLBase.successful_retcode(sol1.retcode) -end diff --git a/test/misc/initial_guess.jl b/test/misc/initial_guess.jl deleted file mode 100644 index c20284c0..00000000 --- a/test/misc/initial_guess.jl +++ /dev/null @@ -1,82 +0,0 @@ -using BoundaryValueDiffEq, OrdinaryDiffEq, Test, LinearAlgebra - -@testset "Initial Guess" begin - # Problem taken from https://github.com/SciML/BoundaryValueDiffEq.jl/issues/117#issuecomment-1780981510 - function affine_connection(a, Xc, Yc) - MR = 3.0 - Mr = 2.0 - Zc = similar(Xc) - θ = a[1] - sinθ, cosθ = sincos(θ) - Γ¹₂₂ = (MR + Mr * cosθ) * sinθ / Mr - Γ²₁₂ = -Mr * sinθ / (MR + Mr * cosθ) - - Zc[1] = Xc[2] * Γ¹₂₂ * Yc[2] - Zc[2] = Γ²₁₂ * (Xc[1] * Yc[2] + Xc[2] * Yc[1]) - return Zc - end - - function chart_log_problem!(du, u, p, t) - mid = div(length(u), 2) - a = u[1:mid] - dx = u[(mid + 1):end] - ddx = -affine_connection(a, dx, dx) - du[1:mid] .= dx - du[(mid + 1):end] .= ddx - return du - end - - function bc1!(residual, u, p, t) - a1, a2 = p[1:2], p[3:4] - mid = div(length(u[1]), 2) - residual[1:mid] = u[1][1:mid] - a1 - residual[(mid + 1):end] = u[end][1:mid] - a2 - return residual - end - - function initial_guess_1(p, t) - a1, a2 = p[1:2], p[3:4] - return vcat(t * a1 + (1 - t) * a2, zero(a1)) - end - - function initial_guess_2(t) - a1, a2 = [0.5, -1.2], [-0.5, 0.3] - return vcat(t * a1 + (1 - t) * a2, zero(a1)) - end - - dt = 0.05 - p = [0.5, -1.2, -0.5, 0.3] - tspan = (0.0, 1.0) - - bvp1 = BVProblem(chart_log_problem!, bc1!, initial_guess_1, tspan, p) - - algs = [Shooting(Tsit5()), MultipleShooting(10, Tsit5()), MIRK4(), MIRK5(), MIRK6()] - - for alg in algs - if alg isa Shooting || alg isa MultipleShooting - sol = solve(bvp1, alg) - else - sol = solve(bvp1, alg; dt) - end - @test SciMLBase.successful_retcode(sol) - resid = zeros(4) - bc1!(resid, sol, p, sol.t) - @test norm(resid, Inf) < 1e-10 - end - - bvp2 = BVProblem(chart_log_problem!, bc1!, initial_guess_2, tspan, p) - - for alg in algs - if alg isa Shooting || alg isa MultipleShooting - sol = solve(bvp2, alg) - @test_deprecated solve(bvp2, alg) - else - sol = solve(bvp2, alg; dt) - @test_deprecated solve(bvp2, alg; dt) - end - @test SciMLBase.successful_retcode(sol) - resid = zeros(4) - bc1!(resid, sol, p, sol.t) - @test norm(resid, Inf) < 1e-10 - end -end diff --git a/test/misc/manifolds_tests.jl b/test/misc/manifolds_tests.jl new file mode 100644 index 00000000..fbc532c2 --- /dev/null +++ b/test/misc/manifolds_tests.jl @@ -0,0 +1,83 @@ +@testitem "Manifolds.jl Integration" begin + using LinearAlgebra + + struct EmbeddedTorus + R::Float64 + r::Float64 + end + + function affine_connection!(M::EmbeddedTorus, Zc, i, a, Xc, Yc) + θ = a[1] .+ i[1] + sinθ, cosθ = sincos(θ) + Γ¹₂₂ = (M.R + M.r * cosθ) * sinθ / M.r + Γ²₁₂ = -M.r * sinθ / (M.R + M.r * cosθ) + + Zc[1] = Xc[2] * Γ¹₂₂ * Yc[2] + Zc[2] = Γ²₁₂ * (Xc[1] * Yc[2] + Xc[2] * Yc[1]) + return Zc + end + + M = EmbeddedTorus(3, 2) + a1 = [0.5, -1.2] + a2 = [-0.5, 0.3] + i = (0, 0) + solver = MIRK4() + dt = 0.05 + tspan = (0.0, 1.0) + + function bc1!(residual, u, params, t) + M, i, a1, a2 = params + mid = div(length(u[1]), 2) + residual[1:mid] = u[1][1:mid] - a1 + residual[(mid + 1):end] = u[end][1:mid] - a2 + return + end + + function chart_log_problem!(du, u, params, t) + M, i, a1, a2 = params + mid = div(length(u), 2) + a = u[1:mid] + dx = u[(mid + 1):end] + ddx = similar(dx) + affine_connection!(M, ddx, i, a, dx, dx) + ddx .*= -1 + du[1:mid] .= dx + du[(mid + 1):end] .= ddx + return du + end + + @testset "Successful Convergence" begin + u0 = [vcat(a1, zero(a1)), vcat(a2, zero(a1))] + bvp1 = BVProblem(chart_log_problem!, bc1!, u0, tspan, (M, i, a1, a2)) + sol1 = solve(bvp1, solver, dt = dt) + @test SciMLBase.successful_retcode(sol1.retcode) + end + + function initial_guess_1(p, t) + _, _, a1, a2 = p + return vcat(t * a1 + (1 - t) * a2, zero(a1)) + end + + function initial_guess_2(t) + a1, a2 = [0.5, -1.2], [-0.5, 0.3] + return vcat(t * a1 + (1 - t) * a2, zero(a1)) + end + + algs = [Shooting(Tsit5()), MultipleShooting(10, Tsit5()), MIRK4(), MIRK5(), MIRK6()] + + @testset "Initial Guess Functions: $(u0)" for u0 in (initial_guess_1, initial_guess_2) + bvp = BVProblem(chart_log_problem!, bc1!, u0, tspan, (M, i, a1, a2)) + + for alg in algs + if alg isa Shooting || alg isa MultipleShooting + sol = solve(bvp, alg) + else + sol = solve(bvp, alg; dt) + end + @test SciMLBase.successful_retcode(sol) + resid = zeros(4) + bc1!(resid, sol, (M, i, a1, a2), sol.t) + @test norm(resid, Inf) < 1e-10 + end + end +end diff --git a/test/misc/non_vector_input_tests.jl b/test/misc/non_vector_input_tests.jl new file mode 100644 index 00000000..a0ddcb06 --- /dev/null +++ b/test/misc/non_vector_input_tests.jl @@ -0,0 +1,71 @@ +@testitem "Non-Vector Inputs" begin + using LinearAlgebra + + for order in (2, 3, 4, 5, 6) + s = Symbol("MIRK$(order)") + @eval mirk_solver(::Val{$order}) = $(s)() + end + + function f1!(du, u, p, t) + du[1, 1] = u[1, 2] + du[1, 2] = 0 + end + + function f1(u, p, t) + return [u[1, 2] 0] + end + + function boundary!(residual, u, p, t) + residual[1, 1] = u[1][1, 1] - 5 + residual[1, 2] = u[end][1, 1] + end + + function boundary_a!(resida, ua, p) + resida[1, 1] = ua[1, 1] - 5 + end + function boundary_b!(residb, ub, p) + residb[1, 1] = ub[1, 1] + end + + function boundary(u, p, t) + return [u[1][1, 1] - 5 u[end][1, 1]] + end + + boundary_a = (ua, p) -> [ua[1, 1] - 5] + boundary_b = (ub, p) -> [ub[1, 1]] + + tspan = (0.0, 5.0) + u0 = [5.0 -3.5] + probs = [BVProblem(f1!, boundary!, u0, tspan; nlls = Val(false)), + TwoPointBVProblem(f1!, (boundary_a!, boundary_b!), u0, tspan; + bcresid_prototype = (Array{Float64}(undef, 1, 1), Array{Float64}(undef, 1, 1)), + nlls = Val(false)), + BVProblem(f1, boundary, u0, tspan; nlls = Val(false)), + TwoPointBVProblem(f1, (boundary_a, boundary_b), u0, tspan; nlls = Val(false))] + + @testset "Affineness" begin + @testset "MIRK$order" for order in (2, 3, 4, 5, 6) + for prob in probs + sol = solve(prob, mirk_solver(Val(order)); dt = 0.2) + @test norm(boundary(sol, prob.p, nothing), Inf) < 0.01 + end + end + + @testset "Single Shooting" begin + for prob in probs + sol = solve(prob, Shooting(Tsit5())) + @test norm(boundary(sol, prob.p, nothing), Inf) < 0.01 + end + end + + # FIXME: Add Multiple Shooting here once it supports non-vector inputs + @testset "Multiple Shooting" begin + for prob in probs + @test_broken begin + sol = solve(prob, MultipleShooting(5, Tsit5())) + norm(boundary(sol, prob.p, nothing), Inf) < 0.01 + end + end + end + end +end diff --git a/test/misc/non_vector_inputs.jl b/test/misc/non_vector_inputs.jl deleted file mode 100644 index 3ea5ff5d..00000000 --- a/test/misc/non_vector_inputs.jl +++ /dev/null @@ -1,60 +0,0 @@ -using BoundaryValueDiffEq, LinearAlgebra, OrdinaryDiffEq, Test - -for order in (2, 3, 4, 5, 6) - s = Symbol("MIRK$(order)") - @eval mirk_solver(::Val{$order}) = $(s)() -end - -function f1!(du, u, p, t) - du[1, 1] = u[1, 2] - du[1, 2] = 0 -end - -function f1(u, p, t) - return [u[1, 2] 0] -end - -function boundary!(residual, u, p, t) - residual[1, 1] = u[1][1, 1] - 5 - residual[1, 2] = u[end][1, 1] -end - -function boundary_a!(resida, ua, p) - resida[1, 1] = ua[1, 1] - 5 -end -function boundary_b!(residb, ub, p) - residb[1, 1] = ub[1, 1] -end - -function boundary(u, p, t) - return [u[1][1, 1] - 5 u[end][1, 1]] -end - -boundary_a = (ua, p) -> [ua[1, 1] - 5] -boundary_b = (ub, p) -> [ub[1, 1]] - -tspan = (0.0, 5.0) -u0 = [5.0 -3.5] -probs = [BVProblem(f1!, boundary!, u0, tspan), - TwoPointBVProblem(f1!, (boundary_a!, boundary_b!), u0, tspan; - bcresid_prototype = (Array{Float64}(undef, 1, 1), Array{Float64}(undef, 1, 1))), - BVProblem(f1, boundary, u0, tspan), - TwoPointBVProblem(f1, (boundary_a, boundary_b), u0, tspan)]; - -@testset "Affineness" begin - @testset "MIRK$order" for order in (2, 3, 4, 5, 6) - for prob in probs - @time sol = solve(prob, mirk_solver(Val(order)); dt = 0.2) - @test norm(diff(first.(sol.u)) .+ 0.2, Inf) + abs(sol[1][1] - 5) < 0.01 - end - end - - @testset "Single Shooting" begin - for prob in probs - @time sol = solve(prob, Shooting(Tsit5())) - @test norm(boundary(sol, prob.p, nothing), Inf) < 0.01 - end - end - - # FIXME: Add Multiple Shooting here once it supports non-vector inputs -end From 1c1eef594406737e9bcba527940b48f96d77c33f Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Sun, 24 Mar 2024 00:04:27 -0400 Subject: [PATCH 19/24] Fix the dispatch on polyalg --- Manifest.toml | 16 +++++++--------- src/solve/multiple_shooting.jl | 4 ++-- src/solve/single_shooting.jl | 2 +- test/shooting/nlls_tests.jl | 34 +++++++++++++++++----------------- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index ab514172..23df17cd 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -353,9 +353,9 @@ version = "0.1.6" [[deps.GenericSchur]] deps = ["LinearAlgebra", "Printf"] -git-tree-sha1 = "fb69b2a645fa69ba5f474af09221b9308b160ce6" +git-tree-sha1 = "af49a0851f8113fcfae2ef5027c6d49d0acec39b" uuid = "c145ed77-6b09-5dd9-b285-bf645a82121e" -version = "0.5.3" +version = "0.5.4" [[deps.Graphs]] deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] @@ -475,10 +475,10 @@ deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LinearSolve]] -deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] -git-tree-sha1 = "73d8f61f8d27f279edfbafc93faaea93ea447e94" +deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "LazyArrays", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] +git-tree-sha1 = "775e5e5d9ace42ef8deeb236587abc69e70dc455" uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "2.27.0" +version = "2.28.0" [deps.LinearSolve.extensions] LinearSolveBandedMatricesExt = "BandedMatrices" @@ -607,11 +607,9 @@ version = "1.2.0" [[deps.NonlinearSolve]] deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "0e464ca0e5d44a88c91f394c3f9a9448523e378b" -repo-rev = "ap/tstable_findmin" -repo-url = "https://github.com/SciML/NonlinearSolve.jl.git" +git-tree-sha1 = "1638addfc31707aea26333ff822afcf9d2e6f7de" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.8.2" +version = "3.8.3" [deps.NonlinearSolve.extensions] NonlinearSolveBandedMatricesExt = "BandedMatrices" diff --git a/src/solve/multiple_shooting.jl b/src/solve/multiple_shooting.jl index 2b37c5c7..dbf76dfd 100644 --- a/src/solve/multiple_shooting.jl +++ b/src/solve/multiple_shooting.jl @@ -128,7 +128,7 @@ function __solve_nlproblem!( # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) - nlsolve_alg = __concrete_nonlinearsolve_algorithm(prob, alg.nlsolve) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(nlprob, alg.nlsolve) __solve(nlprob, nlsolve_alg; kwargs..., alias_u0 = true) return nothing @@ -188,7 +188,7 @@ function __solve_nlproblem!(::StandardBVProblem, alg::MultipleShooting, bcresid_ # NOTE: u_at_nodes is updated inplace nlprob = __internal_nlsolve_problem(prob, M, N, loss_function!, u_at_nodes, prob.p) - nlsolve_alg = __concrete_nonlinearsolve_algorithm(prob, alg.nlsolve) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(nlprob, alg.nlsolve) __solve(nlprob, nlsolve_alg; kwargs..., alias_u0 = true) return nothing diff --git a/src/solve/single_shooting.jl b/src/solve/single_shooting.jl index abdff56e..c969284b 100644 --- a/src/solve/single_shooting.jl +++ b/src/solve/single_shooting.jl @@ -72,7 +72,7 @@ function __solve(prob::BVProblem, alg_::Shooting; odesolve_kwargs = (;), nlf = __unsafe_nonlinearfunction{iip}( loss_fn; jac_prototype, resid_prototype, jac = jac_fn) nlprob = __internal_nlsolve_problem(prob, resid_prototype, u0, nlf, vec(u0), prob.p) - nlsolve_alg = __concrete_nonlinearsolve_algorithm(prob, alg.nlsolve) + nlsolve_alg = __concrete_nonlinearsolve_algorithm(nlprob, alg.nlsolve) nlsol = __solve(nlprob, nlsolve_alg; nlsolve_kwargs..., verbose, kwargs...) # There is no way to reinit with the same cache with different cache. But not saving diff --git a/test/shooting/nlls_tests.jl b/test/shooting/nlls_tests.jl index 620a15c3..21aab1a9 100644 --- a/test/shooting/nlls_tests.jl +++ b/test/shooting/nlls_tests.jl @@ -1,21 +1,20 @@ -# FIXME: The nonlinear solve polyalgorithm for NLLS is currently broken because of Bastin -# Jv & Jᵀv computation with the cached ODE solve @testitem "Overconstrained BVP" begin using LinearAlgebra, JET SOLVERS = [ - # Shooting(Tsit5()), + Shooting(Tsit5(); jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), Shooting( - Tsit5(), LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting( - Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), + Tsit5(), LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), Shooting(Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), Shooting(Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff())), - # MultipleShooting(10, Tsit5()), MultipleShooting( - 10, Tsit5(), LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), MultipleShooting( - 10, Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), + 10, Tsit5(); jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), + MultipleShooting( + 10, Tsit5(), LevenbergMarquardt(; autodiff = AutoForwardDiff(; chunksize = 2))), + MultipleShooting(10, Tsit5(), LevenbergMarquardt(; autodiff = AutoFiniteDiff())), MultipleShooting( 10, Tsit5(), GaussNewton(; autodiff = AutoForwardDiff(; chunksize = 2))), MultipleShooting(10, Tsit5(), GaussNewton(; autodiff = AutoFiniteDiff())), @@ -23,7 +22,8 @@ 10, Tsit5(), TrustRegion(; autodiff = AutoForwardDiff(; chunksize = 2))), MultipleShooting(10, Tsit5(), TrustRegion(; autodiff = AutoFiniteDiff()))] JET_SKIP = fill(false, length(SOLVERS)) - JET_BROKEN = fill(false, length(SOLVERS)) + JET_OPT_BROKEN = fill(false, length(SOLVERS)) + JET_CALL_BROKEN = fill(false, length(SOLVERS)) # OOP MP-BVP f1(u, p, t) = [u[2], -u[1]] @@ -52,11 +52,11 @@ @test_opt target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_OPT_BROKEN[i] @test_call target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp1, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_CALL_BROKEN[i] end # IIP MP-BVP @@ -91,11 +91,11 @@ @test_opt target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_OPT_BROKEN[i] @test_call target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp2, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_CALL_BROKEN[i] end # OOP TP-BVP @@ -118,11 +118,11 @@ @test_opt target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_OPT_BROKEN[i] @test_call target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp3, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_CALL_BROKEN[i] end # IIP TP-BVP @@ -145,10 +145,10 @@ @test_opt target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_OPT_BROKEN[i] @test_call target_modules=( SciMLBase, DiffEqBase, NonlinearSolve, BoundaryValueDiffEq) solve( bvp4, solver; verbose = false, abstol = 1e-6, reltol = 1e-6, - odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_BROKEN[i] + odesolve_kwargs = (; abstol = 1e-6, reltol = 1e-6)) broken=JET_CALL_BROKEN[i] end end From 094e02e20134232b08946115b2583ad2b803174e Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Sun, 24 Mar 2024 12:03:36 -0400 Subject: [PATCH 20/24] Add type stability tests and precompilation --- .github/workflows/CI.yml | 6 +- README.md | 10 +- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 5 +- src/BoundaryValueDiffEq.jl | 455 ++++++++++------------ src/solve/mirk.jl | 6 +- test/misc/type_stability.jl | 62 --- test/misc/type_stability_tests.jl | 70 ++++ 7 files changed, 302 insertions(+), 312 deletions(-) delete mode 100644 test/misc/type_stability.jl create mode 100644 test/misc/type_stability_tests.jl diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 16bbaea1..7e8d929a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -13,10 +13,14 @@ concurrency: cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} jobs: test: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest version: - '1' steps: diff --git a/README.md b/README.md index 5cef548d..2a7f13c0 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,11 @@ For the list of available solvers, please refer to the [DifferentialEquations.jl Precompilation can be controlled via `Preferences.jl` - `PrecompileMIRK` -- Precompile the MIRK2 - MIRK6 algorithms (default: `true`). - - `PrecompileShooting` -- Precompile the single shooting algorithms (default: `false`). This is triggered when `OrdinaryDiffEq` is loaded. - - `PrecompileMultipleShooting` -- Precompile the multiple shooting algorithms (default: `false`). This is triggered when `OrdinaryDiffEq` is loaded. - - `PrecompileMIRKNLLS` -- Precompile the MIRK2 - MIRK6 algorithms for under-determined and over-determined BVPs (default: `false`). - - `PrecompileShootingNLLS` -- Precompile the single shooting algorithms for under-determined and over-determined BVPs (default: `false`). This is triggered when `OrdinaryDiffEq` is loaded. - - `PrecompileMultipleShootingNLLS` -- Precompile the multiple shooting algorithms for under-determined and over-determined BVPs (default: `false` ). This is triggered when `OrdinaryDiffEq` is loaded. + - `PrecompileShooting` -- Precompile the single shooting algorithms (default: `true`). + - `PrecompileMultipleShooting` -- Precompile the multiple shooting algorithms (default: `true`). + - `PrecompileMIRKNLLS` -- Precompile the MIRK2 - MIRK6 algorithms for under-determined and over-determined BVPs (default: `true`). + - `PrecompileShootingNLLS` -- Precompile the single shooting algorithms for under-determined and over-determined BVPs (default: `true`). + - `PrecompileMultipleShootingNLLS` -- Precompile the multiple shooting algorithms for under-determined and over-determined BVPs (default: `true` ). To set these preferences before loading the package, do the following (replacing `PrecompileShooting` with the preference you want to set, or pass in multiple pairs to set them together): diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index 06fb822d..a601bef2 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -93,7 +93,7 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, evalsol = evalSolution(sol, x_mesh) ivpsol = SciMLBase.build_solution(prob, alg, x_mesh, map(x -> reshape(convert(Vector{eltype(evalsol)}, x), u0_size), eachcol(evalsol)); - retcode, stats = destats) + retcode, stats = destats, original = (sol, retcode, stats)) bvpm2_destroy(obj) bvpm2_destroy(sol) @@ -187,7 +187,8 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, ivpsol = SciMLBase.build_solution(prob, alg, sol_t, map(x -> reshape(convert(Vector{eltype(u0_)}, x), u0_size), eachcol(sol_x)); - retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, stats) + retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, stats, + original = (sol_t, sol_x, retcode, stats)) return SciMLBase.build_solution(prob, ivpsol, nothing) end diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index 2afa73dc..fde4f655 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -53,246 +53,221 @@ function __solve(prob::BVProblem, alg::BoundaryValueDiffEqAlgorithm, args...; kw end @setup_workload begin - # function f1!(du, u, p, t) - # du[1] = u[2] - # du[2] = 0 - # end - # f1(u, p, t) = [u[2], 0] - - # function bc1!(residual, u, p, t) - # residual[1] = u[1][1] - 5 - # residual[2] = u[end][1] - # end - # bc1(u, p, t) = [u[1][1] - 5, u[end][1]] - - # bc1_a!(residual, ua, p) = (residual[1] = ua[1] - 5) - # bc1_b!(residual, ub, p) = (residual[1] = ub[1]) - - # bc1_a(ua, p) = [ua[1] - 5] - # bc1_b(ub, p) = [ub[1]] - - # tspan = (0.0, 5.0) - # u0 = [5.0, -3.5] - # bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) - - # probs = [BVProblem(f1!, bc1!, u0, tspan), BVProblem(f1, bc1, u0, tspan), - # TwoPointBVProblem(f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype), - # TwoPointBVProblem(f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype)] - - # algs = [] - - # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) - - # if Preferences.@load_preference("PrecompileMIRK", true) - # append!(algs, - # [MIRK2(; jac_alg), MIRK3(; jac_alg), MIRK4(; jac_alg), - # MIRK5(; jac_alg), MIRK6(; jac_alg)]) - # end - - # @compile_workload begin - # for prob in probs, alg in algs - # solve(prob, alg; dt = 0.2) - # end - # end - - # function f1_nlls!(du, u, p, t) - # du[1] = u[2] - # du[2] = -u[1] - # end - - # f1_nlls(u, p, t) = [u[2], -u[1]] - - # function bc1_nlls!(resid, sol, p, t) - # solₜ₁ = sol[1] - # solₜ₂ = sol[end] - # resid[1] = solₜ₁[1] - # resid[2] = solₜ₂[1] - 1 - # resid[3] = solₜ₂[2] + 1.729109 - # return nothing - # end - # bc1_nlls(sol, p, t) = [sol[1][1], sol[end][1] - 1, sol[end][2] + 1.729109] - - # bc1_nlls_a!(resid, ua, p) = (resid[1] = ua[1]) - # bc1_nlls_b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - - # bc1_nlls_a(ua, p) = [ua[1]] - # bc1_nlls_b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - - # tspan = (0.0, 100.0) - # u0 = [0.0, 1.0] - # bcresid_prototype1 = Array{Float64}(undef, 3) - # bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) - - # probs = [ - # BVProblem(BVPFunction(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), - # u0, tspan), - # BVProblem(BVPFunction(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), - # u0, tspan), - # TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, - # tspan; bcresid_prototype = bcresid_prototype2), - # TwoPointBVProblem(f1_nlls, (bc1_nlls_a, bc1_nlls_b), u0, tspan; - # bcresid_prototype = bcresid_prototype2)] - - # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) - - # nlsolvers = [LevenbergMarquardt(), GaussNewton()] - - # algs = [] - - # if Preferences.@load_preference("PrecompileMIRKNLLS", false) - # for nlsolve in nlsolvers - # append!(algs, - # [MIRK2(; jac_alg, nlsolve), MIRK3(; jac_alg, nlsolve), - # MIRK4(; jac_alg, nlsolve), MIRK5(; jac_alg, nlsolve), - # MIRK6(; jac_alg, nlsolve)]) - # end - # end - - # @compile_workload begin - # for prob in probs, alg in algs - # solve(prob, alg; dt = 0.2) - # end - # end - - # function f1!(du, u, p, t) - # du[1] = u[2] - # du[2] = 0 - # end - # f1(u, p, t) = [u[2], 0] - - # function bc1!(residual, u, p, t) - # residual[1] = u(0.0)[1] - 5 - # residual[2] = u(5.0)[1] - # end - # bc1(u, p, t) = [u(0.0)[1] - 5, u(5.0)[1]] - - # bc1_a!(residual, ua, p) = (residual[1] = ua[1] - 5) - # bc1_b!(residual, ub, p) = (residual[1] = ub[1]) - - # bc1_a(ua, p) = [ua[1] - 5] - # bc1_b(ub, p) = [ub[1]] - - # tspan = (0.0, 5.0) - # u0 = [5.0, -3.5] - # bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) - - # probs = [BVProblem(BVPFunction{true}(f1!, bc1!), u0, tspan; nlls = Val(false)), - # BVProblem(BVPFunction{false}(f1, bc1), u0, tspan; nlls = Val(false)), - # BVProblem( - # BVPFunction{true}( - # f1!, (bc1_a!, bc1_b!); bcresid_prototype, twopoint = Val(true)), - # u0, - # tspan; - # nlls = Val(false)), - # BVProblem( - # BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, twopoint = Val(true)), - # u0, tspan; nlls = Val(false))] - - # algs = [] - - # if @load_preference("PrecompileShooting", true) - # push!(algs, - # Shooting(Tsit5(); nlsolve = NewtonRaphson(), - # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))) - # end - - # if @load_preference("PrecompileMultipleShooting", true) - # push!(algs, - # MultipleShooting(10, - # Tsit5(); - # nlsolve = NewtonRaphson(), - # jac_alg = BVPJacobianAlgorithm(; - # bc_diffmode = AutoForwardDiff(; chunksize = 2), - # nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))) - # end - - # @compile_workload begin - # for prob in probs, alg in algs - # solve(prob, alg) - # end - # end - - # function f1_nlls!(du, u, p, t) - # du[1] = u[2] - # du[2] = -u[1] - # end - - # f1_nlls(u, p, t) = [u[2], -u[1]] - - # function bc1_nlls!(resid, sol, p, t) - # solₜ₁ = sol(0.0) - # solₜ₂ = sol(100.0) - # resid[1] = solₜ₁[1] - # resid[2] = solₜ₂[1] - 1 - # resid[3] = solₜ₂[2] + 1.729109 - # return nothing - # end - # bc1_nlls(sol, p, t) = [sol(0.0)[1], sol(100.0)[1] - 1, sol(1.0)[2] + 1.729109] - - # bc1_nlls_a!(resid, ua, p) = (resid[1] = ua[1]) - # bc1_nlls_b!(resid, ub, p) = (resid[1] = ub[1] - 1; resid[2] = ub[2] + 1.729109) - - # bc1_nlls_a(ua, p) = [ua[1]] - # bc1_nlls_b(ub, p) = [ub[1] - 1, ub[2] + 1.729109] - - # tspan = (0.0, 100.0) - # u0 = [0.0, 1.0] - # bcresid_prototype1 = Array{Float64}(undef, 3) - # bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) - - # probs = [ - # BVProblem( - # BVPFunction{true}(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), - # u0, tspan; nlls = Val(true)), - # BVProblem( - # BVPFunction{false}(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), - # u0, tspan; nlls = Val(true)), - # BVProblem( - # BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); - # bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), - # u0, - # tspan; - # nlls = Val(true)), - # BVProblem( - # BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); - # bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), - # u0, - # tspan; - # nlls = Val(true))] - - # algs = [] - - # if @load_preference("PrecompileShootingNLLS", true) - # append!(algs, - # [ - # Shooting(Tsit5(); nlsolve = TrustRegion(), - # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), - # Shooting(Tsit5(); nlsolve = GaussNewton(), - # jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))]) - # end - - # if @load_preference("PrecompileMultipleShootingNLLS", true) - # append!(algs, - # [ - # MultipleShooting(10, - # Tsit5(); - # nlsolve = TrustRegion(), - # jac_alg = BVPJacobianAlgorithm(; - # bc_diffmode = AutoForwardDiff(; chunksize = 2), - # nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))), - # MultipleShooting(10, - # Tsit5(); - # nlsolve = GaussNewton(), - # jac_alg = BVPJacobianAlgorithm(; - # bc_diffmode = AutoForwardDiff(; chunksize = 2), - # nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))]) - # end - - # @compile_workload begin - # for prob in probs, alg in algs - # solve(prob, alg) - # end - # end + f1! = @closure (du, u, p, t) -> begin + du[1] = u[2] + du[2] = 0 + end + f1 = @closure (u, p, t) -> [u[2], 0] + + bc1! = @closure (residual, u, p, t) -> begin + residual[1] = u[1][1] - 5 + residual[2] = u[lastindex(u)][1] + end + + bc1 = @closure (u, p, t) -> [u[1][1] - 5, u[lastindex(u)][1]] + + bc1_a! = @closure (residual, ua, p) -> (residual[1] = ua[1] - 5) + bc1_b! = @closure (residual, ub, p) -> (residual[1] = ub[1]) + + bc1_a = @closure (ua, p) -> [ua[1] - 5] + bc1_b = @closure (ub, p) -> [ub[1]] + + tspan = (0.0, 5.0) + u0 = [5.0, -3.5] + bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) + + probs = [BVProblem(f1!, bc1!, u0, tspan; nlls=Val(false)), + BVProblem(f1, bc1, u0, tspan; nlls=Val(false)), + TwoPointBVProblem(f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype, nlls=Val(false)), + TwoPointBVProblem(f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype, nlls=Val(false))] + + algs = [] + + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) + + if Preferences.@load_preference("PrecompileMIRK", true) + append!(algs, [MIRK2(; jac_alg), MIRK4(; jac_alg), MIRK6(; jac_alg)]) + end + + @compile_workload begin + for prob in probs, alg in algs + solve(prob, alg; dt = 0.2) + end + end + + f1_nlls! = @closure (du, u, p, t) -> begin + du[1] = u[2] + du[2] = -u[1] + end + + f1_nlls = @closure (u, p, t) -> [u[2], -u[1]] + + bc1_nlls! = @closure (resid, sol, p, t) -> begin + solₜ₁ = sol[1] + solₜ₂ = sol[lastindex(sol)] + resid[1] = solₜ₁[1] + resid[2] = solₜ₂[1] - 1 + resid[3] = solₜ₂[2] + 1.729109 + return nothing + end + bc1_nlls = @closure (sol, p, t) -> [ + sol[1][1], sol[lastindex(sol)][1] - 1, sol[lastindex(sol)][2] + 1.729109] + + bc1_nlls_a! = @closure (resid, ua, p) -> (resid[1] = ua[1]) + bc1_nlls_b! = @closure (resid, ub, p) -> (resid[1] = ub[1] - 1; + resid[2] = ub[2] + 1.729109) + + bc1_nlls_a = @closure (ua, p) -> [ua[1]] + bc1_nlls_b = @closure (ub, p) -> [ub[1] - 1, ub[2] + 1.729109] + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] + bcresid_prototype1 = Array{Float64}(undef, 3) + bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) + + probs = [ + BVProblem(BVPFunction(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), + u0, tspan, nlls = Val(true)), + BVProblem(BVPFunction(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), + u0, tspan, nlls = Val(true)), + TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, + tspan; bcresid_prototype = bcresid_prototype2, nlls = Val(true)), + TwoPointBVProblem(f1_nlls, (bc1_nlls_a, bc1_nlls_b), u0, tspan; + bcresid_prototype = bcresid_prototype2, nlls = Val(true))] + + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) + + nlsolvers = [LevenbergMarquardt(; disable_geodesic = Val(true)), GaussNewton()] + + algs = [] + + if Preferences.@load_preference("PrecompileMIRKNLLS", false) + for nlsolve in nlsolvers + append!(algs, [MIRK2(; jac_alg, nlsolve), MIRK6(; jac_alg, nlsolve)]) + end + end + + @compile_workload begin + for prob in probs, alg in algs + solve(prob, alg; dt = 0.2, abstol = 1e-2) + end + end + + bc1! = @closure (residual, u, p, t) -> begin + residual[1] = u(0.0)[1] - 5 + residual[2] = u(5.0)[1] + end + bc1 = @closure (u, p, t) -> [u(0.0)[1] - 5, u(5.0)[1]] + + tspan = (0.0, 5.0) + u0 = [5.0, -3.5] + bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) + + probs = [BVProblem(BVPFunction{true}(f1!, bc1!), u0, tspan; nlls = Val(false)), + BVProblem(BVPFunction{false}(f1, bc1), u0, tspan; nlls = Val(false)), + BVProblem( + BVPFunction{true}( + f1!, (bc1_a!, bc1_b!); bcresid_prototype, twopoint = Val(true)), + u0, + tspan; + nlls = Val(false)), + BVProblem( + BVPFunction{false}(f1, (bc1_a, bc1_b); bcresid_prototype, twopoint = Val(true)), + u0, tspan; nlls = Val(false))] + + algs = [] + + if @load_preference("PrecompileShooting", true) + push!(algs, + Shooting(Tsit5(); nlsolve = NewtonRaphson(), + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))) + end + + if @load_preference("PrecompileMultipleShooting", true) + push!(algs, + MultipleShooting(10, + Tsit5(); + nlsolve = NewtonRaphson(), + jac_alg = BVPJacobianAlgorithm(; + bc_diffmode = AutoForwardDiff(; chunksize = 2), + nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))) + end + + @compile_workload begin + for prob in probs, alg in algs + solve(prob, alg) + end + end + + bc1_nlls! = @closure (resid, sol, p, t) -> begin + solₜ₁ = sol(0.0) + solₜ₂ = sol(100.0) + resid[1] = solₜ₁[1] + resid[2] = solₜ₂[1] - 1 + resid[3] = solₜ₂[2] + 1.729109 + return nothing + end + bc1_nlls = @closure (sol, p, t) -> [ + sol(0.0)[1], sol(100.0)[1] - 1, sol(1.0)[2] + 1.729109] + + tspan = (0.0, 100.0) + u0 = [0.0, 1.0] + bcresid_prototype1 = Array{Float64}(undef, 3) + bcresid_prototype2 = (Array{Float64}(undef, 1), Array{Float64}(undef, 2)) + + probs = [ + BVProblem( + BVPFunction{true}(f1_nlls!, bc1_nlls!; bcresid_prototype = bcresid_prototype1), + u0, tspan; nlls = Val(true)), + BVProblem( + BVPFunction{false}(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), + u0, tspan; nlls = Val(true)), + BVProblem( + BVPFunction{true}(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!); + bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), + u0, + tspan; + nlls = Val(true)), + BVProblem( + BVPFunction{false}(f1_nlls, (bc1_nlls_a, bc1_nlls_b); + bcresid_prototype = bcresid_prototype2, twopoint = Val(true)), + u0, + tspan; + nlls = Val(true))] + + algs = [] + + if @load_preference("PrecompileShootingNLLS", true) + append!(algs, + [ + Shooting(Tsit5(); nlsolve = LevenbergMarquardt(; disable_geodesic = Val(true)), + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), + Shooting(Tsit5(); nlsolve = GaussNewton(), + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))]) + end + + if @load_preference("PrecompileMultipleShootingNLLS", true) + append!(algs, + [ + MultipleShooting(10, + Tsit5(); + nlsolve = LevenbergMarquardt(; disable_geodesic = Val(true)), + jac_alg = BVPJacobianAlgorithm(; + bc_diffmode = AutoForwardDiff(; chunksize = 2), + nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2))), + MultipleShooting(10, + Tsit5(); + nlsolve = GaussNewton(), + jac_alg = BVPJacobianAlgorithm(; + bc_diffmode = AutoForwardDiff(; chunksize = 2), + nonbc_diffmode = AutoSparseForwardDiff(; chunksize = 2)))]) + end + + @compile_workload begin + for prob in probs, alg in algs + solve(prob, alg; nlsolve_kwargs = (; abstol = 1e-2)) + end + end end export Shooting, MultipleShooting diff --git a/src/solve/mirk.jl b/src/solve/mirk.jl index 7736f207..8d82633e 100644 --- a/src/solve/mirk.jl +++ b/src/solve/mirk.jl @@ -160,10 +160,12 @@ function SciMLBase.solve!(cache::MIRKCache) return __build_solution(cache.prob, odesol, sol_nlprob) end -function __perform_mirk_iteration(cache::MIRKCache, abstol, adaptive; kwargs...) +function __perform_mirk_iteration( + cache::MIRKCache, abstol, adaptive; nlsolve_kwargs = (;), kwargs...) nlprob = __construct_nlproblem(cache, recursive_flatten(cache.y₀)) nlsolve_alg = __concrete_nonlinearsolve_algorithm(nlprob, cache.alg.nlsolve) - sol_nlprob = __solve(nlprob, nlsolve_alg; abstol, kwargs..., alias_u0 = true) + sol_nlprob = __solve( + nlprob, nlsolve_alg; abstol, kwargs..., nlsolve_kwargs..., alias_u0 = true) recursive_unflatten!(cache.y₀, sol_nlprob.u) defect_norm = 2 * abstol diff --git a/test/misc/type_stability.jl b/test/misc/type_stability.jl deleted file mode 100644 index ef20e632..00000000 --- a/test/misc/type_stability.jl +++ /dev/null @@ -1,62 +0,0 @@ -using BoundaryValueDiffEq, OrdinaryDiffEq, LinearAlgebra, Test - -f(u, p, t) = [p[1] * u[1] - p[2] * u[1] * u[2], p[3] * u[1] * u[2] - p[4] * u[2]] -function f!(du, u, p, t) - du[1] = p[1] * u[1] - p[2] * u[1] * u[2] - du[2] = p[3] * u[1] * u[2] - p[4] * u[2] -end - -bc(sol, p, t) = [sol[1][1] - 1, sol[end][2] - 2] -function bc!(res, sol, p, t) - res[1] = sol[1][1] - 1 - res[2] = sol[end][2] - 2 -end -twobc_a(ua, p) = [ua[1] - 1] -twobc_b(ub, p) = [ub[2] - 2] -twobc_a!(resa, ua, p) = (resa[1] = ua[1] - 1) -twobc_b!(resb, ub, p) = (resb[1] = ub[2] - 2) - -u0 = Float64[0, 0] -tspan = (0.0, 1.0) -p = [1.0, 1.0, 1.0, 1.0] -bcresid_prototype = (zeros(1), zeros(1)) - -# Multi-Point BVP -@testset "Multi-Point BVP" begin - mpbvp_iip = BVProblem(f!, bc!, u0, tspan, p) - mpbvp_oop = BVProblem(f, bc, u0, tspan, p) - - @testset "Shooting Methods" begin - @inferred solve(mpbvp_iip, Shooting(Tsit5())) - @inferred solve(mpbvp_oop, Shooting(Tsit5())) - @inferred solve(mpbvp_iip, MultipleShooting(5, Tsit5())) - @inferred solve(mpbvp_oop, MultipleShooting(5, Tsit5())) - end - - @testset "MIRK Methods" begin - for solver in (MIRK2(), MIRK3(), MIRK4(), MIRK5(), MIRK6()) - @inferred solve(mpbvp_iip, solver; dt = 0.2) - @inferred solve(mpbvp_oop, solver; dt = 0.2) - end - end -end - -# Two-Point BVP -@testset "Two-Point BVP" begin - tpbvp_iip = TwoPointBVProblem(f!, (twobc_a!, twobc_b!), u0, tspan, p; bcresid_prototype) - tpbvp_oop = TwoPointBVProblem(f, (twobc_a, twobc_b), u0, tspan, p) - - @testset "Shooting Methods" begin - @inferred solve(tpbvp_iip, Shooting(Tsit5())) - @inferred solve(tpbvp_oop, Shooting(Tsit5())) - @inferred solve(tpbvp_iip, MultipleShooting(5, Tsit5())) - @inferred solve(tpbvp_oop, MultipleShooting(5, Tsit5())) - end - - @testset "MIRK Methods" begin - for solver in (MIRK2(), MIRK3(), MIRK4(), MIRK5(), MIRK6()) - @inferred solve(tpbvp_iip, solver; dt = 0.2) - @inferred solve(tpbvp_oop, solver; dt = 0.2) - end - end -end diff --git a/test/misc/type_stability_tests.jl b/test/misc/type_stability_tests.jl new file mode 100644 index 00000000..f05b1063 --- /dev/null +++ b/test/misc/type_stability_tests.jl @@ -0,0 +1,70 @@ +@testitem "Type Stability" begin + using LinearAlgebra + + f(u, p, t) = [p[1] * u[1] - p[2] * u[1] * u[2], p[3] * u[1] * u[2] - p[4] * u[2]] + function f!(du, u, p, t) + du[1] = p[1] * u[1] - p[2] * u[1] * u[2] + du[2] = p[3] * u[1] * u[2] - p[4] * u[2] + end + + bc(sol, p, t) = [sol[1][1] - 1, sol[end][2] - 2] + function bc!(res, sol, p, t) + res[1] = sol[1][1] - 1 + res[2] = sol[end][2] - 2 + end + twobc_a(ua, p) = [ua[1] - 1] + twobc_b(ub, p) = [ub[2] - 2] + twobc_a!(resa, ua, p) = (resa[1] = ua[1] - 1) + twobc_b!(resb, ub, p) = (resb[1] = ub[2] - 2) + + u0 = Float64[0, 0] + tspan = (0.0, 1.0) + p = [1.0, 1.0, 1.0, 1.0] + bcresid_prototype = (zeros(1), zeros(1)) + + jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)) + + # Multi-Point BVP + @testset "Multi-Point BVP" begin + mpbvp_iip = BVProblem(f!, bc!, u0, tspan, p; nlls = Val(false)) + mpbvp_oop = BVProblem(f, bc, u0, tspan, p; nlls = Val(false)) + + @testset "Shooting Methods" begin + @inferred solve(mpbvp_iip, Shooting(Tsit5(); jac_alg)) + @inferred solve(mpbvp_oop, Shooting(Tsit5(); jac_alg)) + @inferred solve(mpbvp_iip, MultipleShooting(5, Tsit5(); jac_alg)) + @inferred solve(mpbvp_oop, MultipleShooting(5, Tsit5(); jac_alg)) + end + + @testset "MIRK Methods" begin + for solver in (MIRK2(; jac_alg), MIRK3(; jac_alg), MIRK4(; jac_alg), + MIRK5(; jac_alg), MIRK6(; jac_alg)) + @inferred solve(mpbvp_iip, solver; dt = 0.2) + @inferred solve(mpbvp_oop, solver; dt = 0.2) + end + end + end + + # Two-Point BVP + @testset "Two-Point BVP" begin + tpbvp_iip = TwoPointBVProblem( + f!, (twobc_a!, twobc_b!), u0, tspan, p; bcresid_prototype, nlls = Val(false)) + tpbvp_oop = TwoPointBVProblem( + f, (twobc_a, twobc_b), u0, tspan, p; nlls = Val(false)) + + @testset "Shooting Methods" begin + @inferred solve(tpbvp_iip, Shooting(Tsit5(); jac_alg)) + @inferred solve(tpbvp_oop, Shooting(Tsit5(); jac_alg)) + @inferred solve(tpbvp_iip, MultipleShooting(5, Tsit5(); jac_alg)) + @inferred solve(tpbvp_oop, MultipleShooting(5, Tsit5(); jac_alg)) + end + + @testset "MIRK Methods" begin + for solver in (MIRK2(; jac_alg), MIRK3(; jac_alg), MIRK4(; jac_alg), + MIRK5(; jac_alg), MIRK6(; jac_alg)) + @inferred solve(tpbvp_iip, solver; dt = 0.2) + @inferred solve(tpbvp_oop, solver; dt = 0.2) + end + end + end +end From 61dda98369a14ebc4dcbd6d0cec3e349469f1f38 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Sun, 24 Mar 2024 14:18:08 -0400 Subject: [PATCH 21/24] ODE Interface fixes --- Manifest.toml | 2 +- ext/BoundaryValueDiffEqODEInterfaceExt.jl | 104 ++++++++++-------- src/algorithms.jl | 4 + .../odeinterface_tests.jl} | 88 +++++++-------- 4 files changed, 109 insertions(+), 89 deletions(-) rename test/{misc/odeinterface_wrapper.jl => wrappers/odeinterface_tests.jl} (59%) diff --git a/Manifest.toml b/Manifest.toml index 23df17cd..974c3141 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -808,7 +808,7 @@ version = "0.6.42" [[deps.SciMLBase]] deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "0e4fca3dd5de4d4a82c0ffae1e51ab6234af4df0" +git-tree-sha1 = "3fbd6a361ec965a89f1ec64320a8b8a80b7409c3" repo-rev = "ap/nlls_bvp" repo-url = "https://github.com/SciML/SciMLBase.jl.git" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" diff --git a/ext/BoundaryValueDiffEqODEInterfaceExt.jl b/ext/BoundaryValueDiffEqODEInterfaceExt.jl index a601bef2..9e7a76ab 100644 --- a/ext/BoundaryValueDiffEqODEInterfaceExt.jl +++ b/ext/BoundaryValueDiffEqODEInterfaceExt.jl @@ -14,14 +14,6 @@ import ODEInterface: colnew import FastClosures: @closure import ForwardDiff -function _test_bvpm2_bvpsol_colnew_problem_criteria( - _, ::SciMLBase.StandardBVProblem, alg::Symbol) - throw(ArgumentError("$(alg) does not support standard BVProblem. Only TwoPointBVProblem is supported.")) -end -function _test_bvpm2_bvpsol_colnew_problem_criteria(prob, ::TwoPointBVProblem, alg::Symbol) - @assert isinplace(prob) "$(alg) only supports inplace TwoPointBVProblem!" -end - #------ # BVPM2 #------ @@ -54,7 +46,7 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, if prob.u0 isa Function guess_function = @closure (x, y) -> (y .= vec(__initial_guess(prob.u0, prob.p, x))) bvpm2_init(obj, no_odes, no_left_bc, mesh, guess_function, - eltype(u0_)[], alg.max_num_subintervals, prob.u0) + eltype(u0_)[], alg.max_num_subintervals) else u0 = __flatten_initial_guess(prob.u0) bvpm2_init( @@ -98,7 +90,7 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPM2; dt = 0.0, reltol = 1e-3, bvpm2_destroy(obj) bvpm2_destroy(sol) - return SciMLBase.build_solution(prob, ivpsol, nothing) + return ivpsol end #------- @@ -171,9 +163,9 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, elseif retcode == -5 @warn "Given initial values inconsistent with separable linear bc" elseif retcode == -6 - @warn """Iterative refinement faild to converge for `sol_method=0` - Termination since multiple shooting condition or - condition of Jacobian is too bad for `sol_method=1`""" + @warn "Iterative refinement faild to converge for `sol_method=0` \ + Termination since multiple shooting condition or \ + condition of Jacobian is too bad for `sol_method=1`" elseif retcode == -8 @warn "Condensing algorithm for linear block system fails, try `sol_method=1`" elseif retcode == -9 @@ -187,68 +179,92 @@ function SciMLBase.__solve(prob::BVProblem, alg::BVPSOL; maxiters = 1000, ivpsol = SciMLBase.build_solution(prob, alg, sol_t, map(x -> reshape(convert(Vector{eltype(u0_)}, x), u0_size), eachcol(sol_x)); - retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, stats, - original = (sol_t, sol_x, retcode, stats)) + retcode = retcode ≥ 0 ? ReturnCode.Success : ReturnCode.Failure, + stats, original = (sol_t, sol_x, retcode, stats)) - return SciMLBase.build_solution(prob, ivpsol, nothing) + return ivpsol end #------- # COLNEW #------- -#= TODO: FIX this -function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, reltol=1e-4, dt = 0.0, verbose = true, kwargs...) - _test_bvpm2_bvpsol_colnew_problem_criteria(prob, prob.problem_type, :COLNEW) - has_initial_guess = prob.u0 isa AbstractVector{<:AbstractArray} - dt ≤ 0 && throw(ArgumentError("dt must be positive")) - no_odes, n, u0 = if has_initial_guess - length(first(prob.u0)), (length(prob.u0) - 1), reduce(hcat, prob.u0) - else - length(prob.u0), Int(cld((prob.tspan[2] - prob.tspan[1]), dt)), prob.u0 +function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, + reltol = 1e-3, dt = 0.0, verbose = true, kwargs...) + # FIXME: COLNEW does support MP-BVPs but in a very clunky way + if !(prob.problem_type isa TwoPointBVProblem) + throw(ArgumentError("`COLNEW` only supports `TwoPointBVProblem!`")) end + + dt ≤ 0 && throw(ArgumentError("`dt` must be positive")) + + t₀, t₁ = prob.tspan + u0_ = __extract_u0(prob.u0, prob.p, t₀) + u0_size = size(u0_) + n = __initial_guess_length(prob.u0) + + u0 = __flatten_initial_guess(prob.u0) + mesh = __extract_mesh(prob.u0, t₀, t₁, ifelse(n == -1, dt, n - 1)) + if u0 === nothing + # initial_guess function was provided + u0 = mapreduce(@closure(t->vec(__initial_guess(prob.u0, prob.p, t))), hcat, mesh) + end + + no_odes = length(u0_) + + # has_initial_guess = prob.u0 isa AbstractVector{<:AbstractArray} + # dt ≤ 0 && throw(ArgumentError("dt must be positive")) + # no_odes, n, u0 = if has_initial_guess + # length(first(prob.u0)), (length(prob.u0) - 1), reduce(hcat, prob.u0) + # else + # length(prob.u0), Int(cld((prob.tspan[2] - prob.tspan[1]), dt)), prob.u0 + # end + T = eltype(u0) - mesh = collect(range(prob.tspan[1], stop = prob.tspan[2], length = n + 1)) - opt = OptionsODE( - OPT_BVPCLASS => alg.bvpclass, OPT_COLLOCATIONPTS => alg.collocationpts, + # mesh = collect(range(prob.tspan[1], stop = prob.tspan[2], length = n + 1)) + opt = OptionsODE(OPT_BVPCLASS => alg.bvpclass, OPT_COLLOCATIONPTS => alg.collocationpts, OPT_MAXSTEPS => maxiters, OPT_DIAGNOSTICOUTPUT => alg.diagnostic_output, OPT_MAXSUBINTERVALS => alg.max_num_subintervals, OPT_RTOL => reltol) orders = ones(Int, no_odes) _tspan = [prob.tspan[1], prob.tspan[2]] iip = SciMLBase.isinplace(prob) - rhs(t, u, du) = + rhs = @closure (t, u, du) -> begin if iip prob.f(du, u, prob.p, t) else (du .= prob.f(u, prob.p, t)) end + end if prob.f.jac === nothing if iip - jac = function (df, u, p, t) + jac = (df, u, p, t) -> begin _du = similar(u) prob.f(_du, u, p, t) - _f = (du, u) -> prob.f(du, u, p, t) + _f = @closure (du, u) -> prob.f(du, u, p, t) ForwardDiff.jacobian!(df, _f, _du, u) + return end else - jac = function (df, u, p, t) + jac = (df, u, p, t) -> begin _du = prob.f(u, p, t) - _f = (du, u) -> (du .= prob.f(u, p, t)) + _f = @closure (du, u) -> (du .= prob.f(u, p, t)) ForwardDiff.jacobian!(df, _f, _du, u) + return end end else jac = prob.f.jac end - Drhs(t, u, df) = jac(df, u, prob.p, t) + Drhs = @closure (t, u, df) -> jac(df, u, prob.p, t) - #TODO: Fix bc and bcjac for multi-points BVP + bcresid_prototype, _ = BoundaryValueDiffEq.__get_bcresid_prototype( + prob.problem_type, prob, u0) - n_bc_a = length(first(prob.f.bcresid_prototype.x)) - n_bc_b = length(last(prob.f.bcresid_prototype.x)) + n_bc_a = length(first(bcresid_prototype)) + n_bc_b = length(last(bcresid_prototype)) zeta = vcat(fill(first(prob.tspan), n_bc_a), fill(last(prob.tspan), n_bc_b)) - bc = function (i, z, resid) + bc = @closure (i, z, resid) -> begin tmpa = copy(z) tmpb = copy(z) tmp_resid_a = zeros(T, n_bc_a) @@ -268,7 +284,7 @@ function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, reltol end end - Dbc = function (i, z, dbc) + Dbc = @closure (i, z, dbc) -> begin for j in 1:n_bc_a if i == j dbc[i] = 1.0 @@ -287,7 +303,8 @@ function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, reltol if retcode == 0 @warn "Collocation matrix is singular" elseif retcode == -1 - @warn "The expected no. of subintervals exceeds storage(try to increase `OPT_MAXSUBINTERVALS`)" + @warn "The expected no. of subintervals exceeds storage(try to increase \ + `OPT_MAXSUBINTERVALS`)" elseif retcode == -2 @warn "The nonlinear iteration has not converged" elseif retcode == -3 @@ -299,11 +316,10 @@ function SciMLBase.__solve(prob::BVProblem, alg::COLNEW; maxiters = 1000, reltol destats = SciMLBase.DEStats( stats["no_rhs_calls"], 0, 0, 0, stats["no_jac_calls"], 0, 0, 0, 0, 0, 0, 0, 0) - return DiffEqBase.build_solution(prob, alg, mesh, - collect(Vector{eltype(evalsol)}, eachrow(evalsol)); + return DiffEqBase.build_solution( + prob, alg, mesh, collect(Vector{eltype(evalsol)}, eachrow(evalsol)); retcode = retcode > 0 ? ReturnCode.Success : ReturnCode.Failure, - stats = destats) + stats = destats, original = (sol, retcode, stats)) end -=# end diff --git a/src/algorithms.jl b/src/algorithms.jl index edfdade2..4caf2aaf 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -295,6 +295,10 @@ struct BVPSOL{O} <: BoundaryValueDiffEqAlgorithm end end +function BVPSOL(; bvpclass = 2, sol_method = 0, odesolver = nothing) + return BVPSOL(bvpclass, sol_method, odesolver) +end + """ COLNEW(; bvpclass = 1, collocationpts = 7, diagnostic_output = 1, max_num_subintervals = 3000) diff --git a/test/misc/odeinterface_wrapper.jl b/test/wrappers/odeinterface_tests.jl similarity index 59% rename from test/misc/odeinterface_wrapper.jl rename to test/wrappers/odeinterface_tests.jl index 78bc00c7..2e253737 100644 --- a/test/misc/odeinterface_wrapper.jl +++ b/test/wrappers/odeinterface_tests.jl @@ -1,5 +1,6 @@ -using Test, BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, OrdinaryDiffEq, - RecursiveArrayTools +@testsetup module ODEInterfaceWrapperTestSetup + +using BoundaryValueDiffEq, LinearAlgebra, ODEInterface, Random, RecursiveArrayTools # Adaptation of https://github.com/luchr/ODEInterface.jl/blob/958b6023d1dabf775033d0b89c5401b33100bca3/examples/BasicExamples/ex7.jl function ex7_f!(du, u, p, t) @@ -27,8 +28,16 @@ tspan = (-π / 2, π / 2) tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) -@testset "BVPM2" begin - @info "Testing BVPM2" +# Just generate a solution for bvpsol +sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); + dt = π / 20, abstol = 1e-5, maxiters = 1000, adaptive = false) + +export ex7_f!, ex7_2pbc1!, ex7_2pbc2!, u0, p, tspan, tpprob, sol_ms + +end + +@testitem "BVPM2" setup=[ODEInterfaceWrapperTestSetup] begin + using ODEInterface, RecursiveArrayTools sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) @test SciMLBase.successful_retcode(sol_bvpm2) @@ -38,70 +47,61 @@ tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, @test norm(resid_f, Inf) < 1e-6 end -# Just generate a solution for bvpsol -sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); - dt = π / 20, abstol = 1e-5, maxiters = 1000, - odesolve_kwargs = (; adaptive = false, dt = 0.01, abstol = 1e-6, maxiters = 1000)) - # Just test that it runs. BVPSOL only works with linearly separable BCs. -@testset "BVPSOL" begin - @info "Testing BVPSOL" - - @info "BVPSOL with Vector{<:AbstractArray}" +@testitem "BVPSOL" setup=[ODEInterfaceWrapperTestSetup] begin + using ODEInterface, RecursiveArrayTools initial_u0 = [sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) - # Just test that it runs. BVPSOL only works with linearly separable BCs. sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) - @info "BVPSOL with VectorOfArray" + @test sol_bvpsol isa SciMLBase.ODESolution initial_u0 = VectorOfArray([sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]]) tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) - # Just test that it runs. BVPSOL only works with linearly separable BCs. sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) - @info "BVPSOL with DiffEqArray" + @test sol_bvpsol isa SciMLBase.ODESolution ts = collect(tspan[1]:(π / 20):tspan[2]) initial_u0 = DiffEqArray([sol_ms(t) .+ rand() for t in ts], ts) tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) - sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) - @info "BVPSOL with initial guess function" + @test sol_bvpsol isa SciMLBase.ODESolution initial_u0 = (p, t) -> sol_ms(t) .+ rand() - # FIXME: Upstream fix - # tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; - # bcresid_prototype = (zeros(1), zeros(1))) - # sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) -end - -#= -@info "COLNEW" + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, + tspan, p; bcresid_prototype = (zeros(1), zeros(1))) + sol_bvpsol = solve(tpprob, BVPSOL(); dt = π / 20) -function f!(du, u, p, t) - du[1] = u[2] - du[2] = u[1] -end -function bca!(resid_a, u_a, p) - resid_a[1] = u_a[1] - 1 -end -function bcb!(resid_b, u_b, p) - resid_b[1] = u_b[1] + @test sol_bvpsol isa SciMLBase.ODESolution end -fun = BVPFunction( - f!, (bca!, bcb!), bcresid_prototype = (zeros(1), zeros(1)), twopoint = Val(true)) -tspan = (0.0, 1.0) - -prob = TwoPointBVProblem(fun, [1.0, 0.0], tspan) -sol_colnew = solve(prob, COLNEW(), dt = 0.01) -@test SciMLBase.successful_retcode(sol_colnew) -=# +@testitem "COLNEW" setup=[ODEInterfaceWrapperTestSetup] begin + using ODEInterface, RecursiveArrayTools + + function f!(du, u, p, t) + du[1] = u[2] + du[2] = u[1] + end + function bca!(resid_a, u_a, p) + resid_a[1] = u_a[1] - 1 + end + function bcb!(resid_b, u_b, p) + resid_b[1] = u_b[1] + end + + fun = BVPFunction( + f!, (bca!, bcb!), bcresid_prototype = (zeros(1), zeros(1)), twopoint = Val(true)) + tspan = (0.0, 1.0) + + prob = TwoPointBVProblem(fun, [1.0, 0.0], tspan) + sol_colnew = solve(prob, COLNEW(), dt = 0.01) + @test SciMLBase.successful_retcode(sol_colnew) +end From 20c400472f5b846b6fa737bde621152aa539decf Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Sun, 24 Mar 2024 14:56:12 -0400 Subject: [PATCH 22/24] Continuation test --- README.md | 2 +- src/BoundaryValueDiffEq.jl | 17 +++++++------ src/types.jl | 3 +-- src/utils.jl | 6 +++++ test/mirk/mirk_basic_tests.jl | 37 +++++++++++++++++++++++++++++ test/runtests.jl | 7 +++++- test/wrappers/odeinterface_tests.jl | 21 +++++++++------- 7 files changed, 73 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 2a7f13c0..523d1883 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ functionality should check out [DifferentialEquations.jl](https://github.com/Jul ## API -BoundaryValueDiffEq.jl is part of the JuliaDiffEq common interface, but can be used independently of DifferentialEquations.jl. The only requirement is that the user passes a BoundaryValueDiffEq.jl algorithm to solve. For example, we can solve the [BVP tutorial from the documentation](https://docs.sciml.ai/DiffEqDocs/stable/tutorials/bvp_example/) using the `MIRK4()` algorithm: +BoundaryValueDiffEq.jl is part of the SciML common interface, but can be used independently of DifferentialEquations.jl. The only requirement is that the user passes a BoundaryValueDiffEq.jl algorithm to solve. For example, we can solve the [BVP tutorial from the documentation](https://docs.sciml.ai/DiffEqDocs/stable/tutorials/bvp_example/) using the `MIRK4()` algorithm: ```julia using BoundaryValueDiffEq diff --git a/src/BoundaryValueDiffEq.jl b/src/BoundaryValueDiffEq.jl index fde4f655..3710ae6a 100644 --- a/src/BoundaryValueDiffEq.jl +++ b/src/BoundaryValueDiffEq.jl @@ -76,10 +76,12 @@ end u0 = [5.0, -3.5] bcresid_prototype = (Array{Float64}(undef, 1), Array{Float64}(undef, 1)) - probs = [BVProblem(f1!, bc1!, u0, tspan; nlls=Val(false)), - BVProblem(f1, bc1, u0, tspan; nlls=Val(false)), - TwoPointBVProblem(f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype, nlls=Val(false)), - TwoPointBVProblem(f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype, nlls=Val(false))] + probs = [BVProblem(f1!, bc1!, u0, tspan; nlls = Val(false)), + BVProblem(f1, bc1, u0, tspan; nlls = Val(false)), + TwoPointBVProblem( + f1!, (bc1_a!, bc1_b!), u0, tspan; bcresid_prototype, nlls = Val(false)), + TwoPointBVProblem( + f1, (bc1_a, bc1_b), u0, tspan; bcresid_prototype, nlls = Val(false))] algs = [] @@ -130,8 +132,8 @@ end u0, tspan, nlls = Val(true)), BVProblem(BVPFunction(f1_nlls, bc1_nlls; bcresid_prototype = bcresid_prototype1), u0, tspan, nlls = Val(true)), - TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, - tspan; bcresid_prototype = bcresid_prototype2, nlls = Val(true)), + TwoPointBVProblem(f1_nlls!, (bc1_nlls_a!, bc1_nlls_b!), u0, tspan; + bcresid_prototype = bcresid_prototype2, nlls = Val(true)), TwoPointBVProblem(f1_nlls, (bc1_nlls_a, bc1_nlls_b), u0, tspan; bcresid_prototype = bcresid_prototype2, nlls = Val(true))] @@ -240,7 +242,8 @@ end if @load_preference("PrecompileShootingNLLS", true) append!(algs, [ - Shooting(Tsit5(); nlsolve = LevenbergMarquardt(; disable_geodesic = Val(true)), + Shooting( + Tsit5(); nlsolve = LevenbergMarquardt(; disable_geodesic = Val(true)), jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2))), Shooting(Tsit5(); nlsolve = GaussNewton(), jac_alg = BVPJacobianAlgorithm(AutoForwardDiff(; chunksize = 2)))]) diff --git a/src/types.jl b/src/types.jl index c09e2922..d0982fed 100644 --- a/src/types.jl +++ b/src/types.jl @@ -98,8 +98,7 @@ end function concrete_jacobian_algorithm( jac_alg::BVPJacobianAlgorithm, prob_type, prob::BVProblem, alg) - u0 = prob.u0 isa AbstractArray ? prob.u0 : - __initial_guess(prob.u0, prob.p, first(prob.tspan)) + u0 = __extract_u0(prob.u0, prob.p, first(prob.tspan)) diffmode = jac_alg.diffmode === nothing ? __default_sparse_ad(u0) : jac_alg.diffmode bc_diffmode = jac_alg.bc_diffmode === nothing ? (prob_type isa TwoPointBVProblem ? __default_sparse_ad : diff --git a/src/utils.jl b/src/utils.jl index 0576e9e4..bfa2d101 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -132,6 +132,12 @@ function __extract_problem_details(prob, u0::AbstractVector{<:AbstractArray}; kw _u0 = first(u0) return Val(true), eltype(_u0), length(_u0), (length(u0) - 1), _u0 end +function __extract_problem_details( + prob, u0::RecursiveArrayTools.AbstractVectorOfArray; kwargs...) + # Problem has Initial Guess + _u0 = first(u0.u) + return Val(true), eltype(_u0), length(_u0), (length(u0.u) - 1), _u0 +end function __extract_problem_details( prob, u0::AbstractArray; dt = 0.0, check_positive_dt::Bool = false) # Problem does not have Initial Guess diff --git a/test/mirk/mirk_basic_tests.jl b/test/mirk/mirk_basic_tests.jl index 1fcf4cc4..c80e380b 100644 --- a/test/mirk/mirk_basic_tests.jl +++ b/test/mirk/mirk_basic_tests.jl @@ -213,3 +213,40 @@ end @test_nowarn solve(prob, MIRK4(); dt = 0.01) end + +@testitem "Solve using Continuation" begin + using RecursiveArrayTools + + g = 9.81 + L = 1.0 + tspan = (0.0, pi / 2) + function simplependulum!(du, u, p, t) + θ = u[1] + dθ = u[2] + du[1] = dθ + du[2] = -(g / L) * sin(θ) + end + + function bc2a!(resid_a, u_a, p) # u_a is at the beginning of the time span + x0 = p + resid_a[1] = u_a[1] - x0 # the solution at the beginning of the time span should be -pi/2 + end + function bc2b!(resid_b, u_b, p) # u_b is at the ending of the time span + x0 = p + resid_b[1] = u_b[1] - pi / 2 # the solution at the end of the time span should be pi/2 + end + + bvp3 = TwoPointBVProblem( + simplependulum!, (bc2a!, bc2b!), [pi / 2, pi / 2], (pi / 4, pi / 2), + -pi / 2; bcresid_prototype = (zeros(1), zeros(1))) + sol3 = solve(bvp3, MIRK4(), dt = 0.05) + + # Needs a SciMLBase fix + bvp4 = TwoPointBVProblem(simplependulum!, (bc2a!, bc2b!), sol3, (0, pi / 2), + pi / 2; bcresid_prototype = (zeros(1), zeros(1))) + @test_broken solve(bvp4, MIRK4(), dt = 0.05) isa SciMLBase.ODESolution + + bvp5 = TwoPointBVProblem(simplependulum!, (bc2a!, bc2b!), DiffEqArray(sol3.u, sol3.t), + (0, pi / 2), pi / 2; bcresid_prototype = (zeros(1), zeros(1))) + @test SciMLBase.successful_retcode(solve(bvp5, MIRK4(), dt = 0.05).retcode) +end diff --git a/test/runtests.jl b/test/runtests.jl index 8ba7978a..68469e0f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,8 @@ using ReTestItems -ReTestItems.runtests(@__DIR__) +ReTestItems.runtests(joinpath(@__DIR__, "mirk/")) +ReTestItems.runtests(joinpath(@__DIR__, "misc/")) +ReTestItems.runtests(joinpath(@__DIR__, "shooting/")) + +# Wrappers like ODEInterface don't support parallel testing +ReTestItems.runtests(joinpath(@__DIR__, "wrappers/"); nworkers = 0) diff --git a/test/wrappers/odeinterface_tests.jl b/test/wrappers/odeinterface_tests.jl index 2e253737..e6c5b680 100644 --- a/test/wrappers/odeinterface_tests.jl +++ b/test/wrappers/odeinterface_tests.jl @@ -25,19 +25,15 @@ u0 = [0.5, 1.0] p = [0.1] tspan = (-π / 2, π / 2) -tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, - p; bcresid_prototype = (zeros(1), zeros(1))) - -# Just generate a solution for bvpsol -sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); - dt = π / 20, abstol = 1e-5, maxiters = 1000, adaptive = false) - -export ex7_f!, ex7_2pbc1!, ex7_2pbc2!, u0, p, tspan, tpprob, sol_ms +export ex7_f!, ex7_2pbc1!, ex7_2pbc2!, u0, p, tspan end @testitem "BVPM2" setup=[ODEInterfaceWrapperTestSetup] begin - using ODEInterface, RecursiveArrayTools + using ODEInterface, RecursiveArrayTools, LinearAlgebra + + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, + p; bcresid_prototype = (zeros(1), zeros(1))) sol_bvpm2 = solve(tpprob, BVPM2(); dt = π / 20) @test SciMLBase.successful_retcode(sol_bvpm2) @@ -51,6 +47,13 @@ end @testitem "BVPSOL" setup=[ODEInterfaceWrapperTestSetup] begin using ODEInterface, RecursiveArrayTools + tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), u0, tspan, + p; bcresid_prototype = (zeros(1), zeros(1))) + + # Just generate a solution for bvpsol + sol_ms = solve(tpprob, MultipleShooting(10, DP5(), NewtonRaphson()); + dt = π / 20, abstol = 1e-5, maxiters = 1000, adaptive = false) + initial_u0 = [sol_ms(t) .+ rand() for t in tspan[1]:(π / 20):tspan[2]] tpprob = TwoPointBVProblem(ex7_f!, (ex7_2pbc1!, ex7_2pbc2!), initial_u0, tspan, p; bcresid_prototype = (zeros(1), zeros(1))) From d6232c82a1011a6e5e5664098ceafd3952155685 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Mar 2024 11:16:29 -0400 Subject: [PATCH 23/24] Remove Manifest --- Manifest.toml | 1093 ------------------------------------------------- Project.toml | 2 +- 2 files changed, 1 insertion(+), 1094 deletions(-) delete mode 100644 Manifest.toml diff --git a/Manifest.toml b/Manifest.toml deleted file mode 100644 index 974c3141..00000000 --- a/Manifest.toml +++ /dev/null @@ -1,1093 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -julia_version = "1.10.2" -manifest_format = "2.0" -project_hash = "5a9701ab315469eb074470e987a001fa3e379b21" - -[[deps.ADTypes]] -git-tree-sha1 = "016833eb52ba2d6bea9fcb50ca295980e728ee24" -uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" -version = "0.2.7" - -[[deps.Adapt]] -deps = ["LinearAlgebra", "Requires"] -git-tree-sha1 = "6a55b747d1812e699320963ffde36f1ebdda4099" -uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "4.0.4" -weakdeps = ["StaticArrays"] - - [deps.Adapt.extensions] - AdaptStaticArraysExt = "StaticArrays" - -[[deps.ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" -version = "1.1.1" - -[[deps.ArnoldiMethod]] -deps = ["LinearAlgebra", "Random", "StaticArrays"] -git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae" -uuid = "ec485272-7323-5ecc-a04f-4719b315124d" -version = "0.2.0" - -[[deps.ArrayInterface]] -deps = ["Adapt", "LinearAlgebra", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "44691067188f6bd1b2289552a23e4b7572f4528d" -uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "7.9.0" - - [deps.ArrayInterface.extensions] - ArrayInterfaceBandedMatricesExt = "BandedMatrices" - ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" - ArrayInterfaceCUDAExt = "CUDA" - ArrayInterfaceChainRulesExt = "ChainRules" - ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" - ArrayInterfaceReverseDiffExt = "ReverseDiff" - ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" - ArrayInterfaceTrackerExt = "Tracker" - - [deps.ArrayInterface.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" - CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" - ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" - GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - -[[deps.ArrayLayouts]] -deps = ["FillArrays", "LinearAlgebra"] -git-tree-sha1 = "6404a564c24a994814106c374bec893195e19bac" -uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "1.8.0" -weakdeps = ["SparseArrays"] - - [deps.ArrayLayouts.extensions] - ArrayLayoutsSparseArraysExt = "SparseArrays" - -[[deps.Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" - -[[deps.BandedMatrices]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "PrecompileTools"] -git-tree-sha1 = "c946c5014cf4cdbfacacb363b110e7bffba3e742" -uuid = "aae01518-5342-5314-be14-df237901396f" -version = "1.6.1" -weakdeps = ["SparseArrays"] - - [deps.BandedMatrices.extensions] - BandedMatricesSparseArraysExt = "SparseArrays" - -[[deps.Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[deps.BitTwiddlingConvenienceFunctions]] -deps = ["Static"] -git-tree-sha1 = "0c5f81f47bbbcf4aea7b2959135713459170798b" -uuid = "62783981-4cbd-42fc-bca8-16325de8dc4b" -version = "0.1.5" - -[[deps.CPUSummary]] -deps = ["CpuId", "IfElse", "PrecompileTools", "Static"] -git-tree-sha1 = "601f7e7b3d36f18790e2caf83a882d88e9b71ff1" -uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" -version = "0.2.4" - -[[deps.ChainRulesCore]] -deps = ["Compat", "LinearAlgebra"] -git-tree-sha1 = "575cd02e080939a33b6df6c5853d14924c08e35b" -uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "1.23.0" -weakdeps = ["SparseArrays"] - - [deps.ChainRulesCore.extensions] - ChainRulesCoreSparseArraysExt = "SparseArrays" - -[[deps.CloseOpenIntervals]] -deps = ["Static", "StaticArrayInterface"] -git-tree-sha1 = "70232f82ffaab9dc52585e0dd043b5e0c6b714f1" -uuid = "fb6a15b2-703c-40df-9091-08a04967cfa9" -version = "0.1.12" - -[[deps.CommonSolve]] -git-tree-sha1 = "0eee5eb66b1cf62cd6ad1b460238e60e4b09400c" -uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" -version = "0.2.4" - -[[deps.CommonSubexpressions]] -deps = ["MacroTools", "Test"] -git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7" -uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" -version = "0.3.0" - -[[deps.Compat]] -deps = ["TOML", "UUIDs"] -git-tree-sha1 = "c955881e3c981181362ae4088b35995446298b80" -uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.14.0" -weakdeps = ["Dates", "LinearAlgebra"] - - [deps.Compat.extensions] - CompatLinearAlgebraExt = "LinearAlgebra" - -[[deps.CompilerSupportLibraries_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.1.0+0" - -[[deps.ConcreteStructs]] -git-tree-sha1 = "f749037478283d372048690eb3b5f92a79432b34" -uuid = "2569d6c7-a4a2-43d3-a901-331e8e4be471" -version = "0.2.3" - -[[deps.ConstructionBase]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "260fd2400ed2dab602a7c15cf10c1933c59930a2" -uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" -version = "1.5.5" - - [deps.ConstructionBase.extensions] - ConstructionBaseIntervalSetsExt = "IntervalSets" - ConstructionBaseStaticArraysExt = "StaticArrays" - - [deps.ConstructionBase.weakdeps] - IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - -[[deps.CpuId]] -deps = ["Markdown"] -git-tree-sha1 = "fcbb72b032692610bfbdb15018ac16a36cf2e406" -uuid = "adafc99b-e345-5852-983c-f28acb93d879" -version = "0.3.1" - -[[deps.DataAPI]] -git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" -uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.16.0" - -[[deps.DataStructures]] -deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "0f4b5d62a88d8f59003e43c25a8a90de9eb76317" -uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.18" - -[[deps.DataValueInterfaces]] -git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" -uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" -version = "1.0.0" - -[[deps.Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[deps.DiffEqBase]] -deps = ["ArrayInterface", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces"] -git-tree-sha1 = "b19b2bb1ecd1271334e4b25d605e50f75e68fcae" -uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.148.0" - - [deps.DiffEqBase.extensions] - DiffEqBaseChainRulesCoreExt = "ChainRulesCore" - DiffEqBaseDistributionsExt = "Distributions" - DiffEqBaseEnzymeExt = ["ChainRulesCore", "Enzyme"] - DiffEqBaseGeneralizedGeneratedExt = "GeneralizedGenerated" - DiffEqBaseMPIExt = "MPI" - DiffEqBaseMeasurementsExt = "Measurements" - DiffEqBaseMonteCarloMeasurementsExt = "MonteCarloMeasurements" - DiffEqBaseReverseDiffExt = "ReverseDiff" - DiffEqBaseTrackerExt = "Tracker" - DiffEqBaseUnitfulExt = "Unitful" - - [deps.DiffEqBase.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - GeneralizedGenerated = "6b9d7cbe-bcb9-11e9-073f-15a7a543e2eb" - MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" - Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" - MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" - -[[deps.DiffResults]] -deps = ["StaticArraysCore"] -git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" -uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" -version = "1.1.0" - -[[deps.DiffRules]] -deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"] -git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272" -uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" -version = "1.15.1" - -[[deps.Distributed]] -deps = ["Random", "Serialization", "Sockets"] -uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" - -[[deps.DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.3" - -[[deps.Downloads]] -deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -version = "1.6.0" - -[[deps.EnumX]] -git-tree-sha1 = "bdb1942cd4c45e3c678fd11569d5cccd80976237" -uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" -version = "1.0.4" - -[[deps.EnzymeCore]] -git-tree-sha1 = "59c44d8fbc651c0395d8a6eda64b05ce316f58b4" -uuid = "f151be2c-9106-41f4-ab19-57ee4f262869" -version = "0.6.5" -weakdeps = ["Adapt"] - - [deps.EnzymeCore.extensions] - AdaptExt = "Adapt" - -[[deps.ExponentialUtilities]] -deps = ["Adapt", "ArrayInterface", "GPUArraysCore", "GenericSchur", "LinearAlgebra", "PrecompileTools", "Printf", "SparseArrays", "libblastrampoline_jll"] -git-tree-sha1 = "8e18940a5ba7f4ddb41fe2b79b6acaac50880a86" -uuid = "d4d017d3-3776-5f7e-afef-a10c40355c18" -version = "1.26.1" - -[[deps.ExprTools]] -git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" -uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" -version = "0.1.10" - -[[deps.FastAlmostBandedMatrices]] -deps = ["ArrayInterface", "ArrayLayouts", "BandedMatrices", "ConcreteStructs", "LazyArrays", "LinearAlgebra", "MatrixFactorizations", "PrecompileTools", "Reexport"] -git-tree-sha1 = "9dc913faf8552fd09b92a0d7fcc25f1d5609d795" -uuid = "9d29842c-ecb8-4973-b1e9-a27b1157504e" -version = "0.1.1" - -[[deps.FastBroadcast]] -deps = ["ArrayInterface", "LinearAlgebra", "Polyester", "Static", "StaticArrayInterface", "StrideArraysCore"] -git-tree-sha1 = "a6e756a880fc419c8b41592010aebe6a5ce09136" -uuid = "7034ab61-46d4-4ed7-9d0f-46aef9175898" -version = "0.2.8" - -[[deps.FastClosures]] -git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" -uuid = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a" -version = "0.3.2" - -[[deps.FastLapackInterface]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "0a59c7d1002f3131de53dc4568a47d15a44daef7" -uuid = "29a986be-02c6-4525-aec4-84b980013641" -version = "2.0.2" - -[[deps.FileWatching]] -uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" - -[[deps.FillArrays]] -deps = ["LinearAlgebra", "Random"] -git-tree-sha1 = "5b93957f6dcd33fc343044af3d48c215be2562f1" -uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "1.9.3" - - [deps.FillArrays.extensions] - FillArraysPDMatsExt = "PDMats" - FillArraysSparseArraysExt = "SparseArrays" - FillArraysStatisticsExt = "Statistics" - - [deps.FillArrays.weakdeps] - PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" - -[[deps.FiniteDiff]] -deps = ["ArrayInterface", "LinearAlgebra", "Requires", "Setfield", "SparseArrays"] -git-tree-sha1 = "bc0c5092d6caaea112d3c8e3b238d61563c58d5f" -uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" -version = "2.23.0" - - [deps.FiniteDiff.extensions] - FiniteDiffBandedMatricesExt = "BandedMatrices" - FiniteDiffBlockBandedMatricesExt = "BlockBandedMatrices" - FiniteDiffStaticArraysExt = "StaticArrays" - - [deps.FiniteDiff.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - -[[deps.ForwardDiff]] -deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] -git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad" -uuid = "f6369f11-7733-5829-9624-2563aa707210" -version = "0.10.36" -weakdeps = ["StaticArrays"] - - [deps.ForwardDiff.extensions] - ForwardDiffStaticArraysExt = "StaticArrays" - -[[deps.FunctionWrappers]] -git-tree-sha1 = "d62485945ce5ae9c0c48f124a84998d755bae00e" -uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e" -version = "1.1.3" - -[[deps.FunctionWrappersWrappers]] -deps = ["FunctionWrappers"] -git-tree-sha1 = "b104d487b34566608f8b4e1c39fb0b10aa279ff8" -uuid = "77dc65aa-8811-40c2-897b-53d922fa7daf" -version = "0.1.3" - -[[deps.Future]] -deps = ["Random"] -uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" - -[[deps.GPUArraysCore]] -deps = ["Adapt"] -git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950" -uuid = "46192b85-c4d5-4398-a991-12ede77f4527" -version = "0.1.6" - -[[deps.GenericSchur]] -deps = ["LinearAlgebra", "Printf"] -git-tree-sha1 = "af49a0851f8113fcfae2ef5027c6d49d0acec39b" -uuid = "c145ed77-6b09-5dd9-b285-bf645a82121e" -version = "0.5.4" - -[[deps.Graphs]] -deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] -git-tree-sha1 = "899050ace26649433ef1af25bc17a815b3db52b7" -uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" -version = "1.9.0" - -[[deps.HostCPUFeatures]] -deps = ["BitTwiddlingConvenienceFunctions", "IfElse", "Libdl", "Static"] -git-tree-sha1 = "eb8fed28f4994600e29beef49744639d985a04b2" -uuid = "3e5b6fbb-0976-4d2c-9146-d79de83f2fb0" -version = "0.1.16" - -[[deps.IfElse]] -git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1" -uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" -version = "0.1.1" - -[[deps.Inflate]] -git-tree-sha1 = "ea8031dea4aff6bd41f1df8f2fdfb25b33626381" -uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" -version = "0.1.4" - -[[deps.IntelOpenMP_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "5fdf2fe6724d8caabf43b557b84ce53f3b7e2f6b" -uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" -version = "2024.0.2+0" - -[[deps.InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[deps.IrrationalConstants]] -git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" -uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" -version = "0.2.2" - -[[deps.IteratorInterfaceExtensions]] -git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" -uuid = "82899510-4779-5014-852e-03e436cf321d" -version = "1.0.0" - -[[deps.JLLWrappers]] -deps = ["Artifacts", "Preferences"] -git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" -uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.5.0" - -[[deps.KLU]] -deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] -git-tree-sha1 = "07649c499349dad9f08dde4243a4c597064663e9" -uuid = "ef3ab10e-7fda-4108-b977-705223b18434" -version = "0.6.0" - -[[deps.Krylov]] -deps = ["LinearAlgebra", "Printf", "SparseArrays"] -git-tree-sha1 = "8a6837ec02fe5fb3def1abc907bb802ef11a0729" -uuid = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7" -version = "0.9.5" - -[[deps.LayoutPointers]] -deps = ["ArrayInterface", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface"] -git-tree-sha1 = "62edfee3211981241b57ff1cedf4d74d79519277" -uuid = "10f19ff3-798f-405d-979b-55457f8fc047" -version = "0.1.15" - -[[deps.LazyArrays]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "MacroTools", "MatrixFactorizations", "SparseArrays"] -git-tree-sha1 = "9cfca23ab83b0dfac93cb1a1ef3331ab9fe596a5" -uuid = "5078a376-72f3-5289-bfd5-ec5146d43c02" -version = "1.8.3" -weakdeps = ["StaticArrays"] - - [deps.LazyArrays.extensions] - LazyArraysStaticArraysExt = "StaticArrays" - -[[deps.LazyArtifacts]] -deps = ["Artifacts", "Pkg"] -uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" - -[[deps.LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.4" - -[[deps.LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "8.4.0+0" - -[[deps.LibGit2]] -deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[deps.LibGit2_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] -uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.6.4+0" - -[[deps.LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "MbedTLS_jll"] -uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.11.0+1" - -[[deps.Libdl]] -uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" - -[[deps.LineSearches]] -deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"] -git-tree-sha1 = "7bbea35cec17305fc70a0e5b4641477dc0789d9d" -uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255" -version = "7.2.0" - -[[deps.LinearAlgebra]] -deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - -[[deps.LinearSolve]] -deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "LazyArrays", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] -git-tree-sha1 = "775e5e5d9ace42ef8deeb236587abc69e70dc455" -uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "2.28.0" - - [deps.LinearSolve.extensions] - LinearSolveBandedMatricesExt = "BandedMatrices" - LinearSolveBlockDiagonalsExt = "BlockDiagonals" - LinearSolveCUDAExt = "CUDA" - LinearSolveEnzymeExt = ["Enzyme", "EnzymeCore"] - LinearSolveFastAlmostBandedMatricesExt = ["FastAlmostBandedMatrices"] - LinearSolveHYPREExt = "HYPRE" - LinearSolveIterativeSolversExt = "IterativeSolvers" - LinearSolveKernelAbstractionsExt = "KernelAbstractions" - LinearSolveKrylovKitExt = "KrylovKit" - LinearSolveMetalExt = "Metal" - LinearSolvePardisoExt = "Pardiso" - LinearSolveRecursiveArrayToolsExt = "RecursiveArrayTools" - - [deps.LinearSolve.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - BlockDiagonals = "0a1fb500-61f7-11e9-3c65-f5ef3456f9f0" - CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" - FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" - HYPRE = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" - IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153" - KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" - KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" - Metal = "dde4c033-4e86-420c-a63e-0dd931031962" - Pardiso = "46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" - RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" - -[[deps.LogExpFunctions]] -deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "18144f3e9cbe9b15b070288eef858f71b291ce37" -uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.27" - - [deps.LogExpFunctions.extensions] - LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" - LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" - LogExpFunctionsInverseFunctionsExt = "InverseFunctions" - - [deps.LogExpFunctions.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" - InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" - -[[deps.Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[deps.LoopVectorization]] -deps = ["ArrayInterface", "CPUSummary", "CloseOpenIntervals", "DocStringExtensions", "HostCPUFeatures", "IfElse", "LayoutPointers", "LinearAlgebra", "OffsetArrays", "PolyesterWeave", "PrecompileTools", "SIMDTypes", "SLEEFPirates", "Static", "StaticArrayInterface", "ThreadingUtilities", "UnPack", "VectorizationBase"] -git-tree-sha1 = "0f5648fbae0d015e3abe5867bca2b362f67a5894" -uuid = "bdcacae8-1622-11e9-2a5c-532679323890" -version = "0.12.166" -weakdeps = ["ChainRulesCore", "ForwardDiff", "SpecialFunctions"] - - [deps.LoopVectorization.extensions] - ForwardDiffExt = ["ChainRulesCore", "ForwardDiff"] - SpecialFunctionsExt = "SpecialFunctions" - -[[deps.MKL_jll]] -deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl"] -git-tree-sha1 = "72dc3cf284559eb8f53aa593fe62cb33f83ed0c0" -uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" -version = "2024.0.0+0" - -[[deps.MacroTools]] -deps = ["Markdown", "Random"] -git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" -uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.13" - -[[deps.ManualMemory]] -git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd" -uuid = "d125e4d3-2237-4719-b19c-fa641b8a4667" -version = "0.1.8" - -[[deps.Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[deps.MatrixFactorizations]] -deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"] -git-tree-sha1 = "78f6e33434939b0ac9ba1df81e6d005ee85a7396" -uuid = "a3b82374-2e81-5b9e-98ce-41277c0e4c87" -version = "2.1.0" - -[[deps.MaybeInplace]] -deps = ["ArrayInterface", "LinearAlgebra", "MacroTools", "SparseArrays"] -git-tree-sha1 = "a85c6a98c9e5a2a7046bc1bb89f28a3241e1de4d" -uuid = "bb5d69b7-63fc-4a16-80bd-7e42200c7bdb" -version = "0.1.1" - -[[deps.MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.2+1" - -[[deps.Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" - -[[deps.MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2023.1.10" - -[[deps.MuladdMacro]] -git-tree-sha1 = "cac9cc5499c25554cba55cd3c30543cff5ca4fab" -uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" -version = "0.2.4" - -[[deps.NLSolversBase]] -deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"] -git-tree-sha1 = "a0b464d183da839699f4c79e7606d9d186ec172c" -uuid = "d41bc354-129a-5804-8e4c-c37616107c6c" -version = "7.8.3" - -[[deps.NaNMath]] -deps = ["OpenLibm_jll"] -git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" -uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" -version = "1.0.2" - -[[deps.NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.2.0" - -[[deps.NonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "TimerOutputs"] -git-tree-sha1 = "1638addfc31707aea26333ff822afcf9d2e6f7de" -uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "3.8.3" - - [deps.NonlinearSolve.extensions] - NonlinearSolveBandedMatricesExt = "BandedMatrices" - NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt" - NonlinearSolveFixedPointAccelerationExt = "FixedPointAcceleration" - NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" - NonlinearSolveMINPACKExt = "MINPACK" - NonlinearSolveNLSolversExt = "NLSolvers" - NonlinearSolveNLsolveExt = "NLsolve" - NonlinearSolveSIAMFANLEquationsExt = "SIAMFANLEquations" - NonlinearSolveSpeedMappingExt = "SpeedMapping" - NonlinearSolveSymbolicsExt = "Symbolics" - NonlinearSolveZygoteExt = "Zygote" - - [deps.NonlinearSolve.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce" - FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176" - LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" - MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" - NLSolvers = "337daf1e-9722-11e9-073e-8b9effe078ba" - NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" - SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" - SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" - Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.OffsetArrays]] -git-tree-sha1 = "6a731f2b5c03157418a20c12195eb4b74c8f8621" -uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.13.0" -weakdeps = ["Adapt"] - - [deps.OffsetArrays.extensions] - OffsetArraysAdaptExt = "Adapt" - -[[deps.OpenBLAS_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] -uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.23+4" - -[[deps.OpenLibm_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+2" - -[[deps.OpenSpecFun_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" -uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" -version = "0.5.5+0" - -[[deps.OrderedCollections]] -git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" -uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.6.3" - -[[deps.OrdinaryDiffEq]] -deps = ["ADTypes", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastBroadcast", "FastClosures", "FillArrays", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "IfElse", "InteractiveUtils", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "MacroTools", "MuladdMacro", "NonlinearSolve", "Polyester", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SimpleUnPack", "SparseArrays", "SparseDiffTools", "StaticArrayInterface", "StaticArrays", "TruncatedStacktraces"] -git-tree-sha1 = "91079af18db922354197eeae2a17b177079e24c1" -uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -version = "6.74.1" - -[[deps.PackageExtensionCompat]] -git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" -uuid = "65ce6f38-6b18-4e1d-a461-8949797d7930" -version = "1.0.2" -weakdeps = ["Requires", "TOML"] - -[[deps.Parameters]] -deps = ["OrderedCollections", "UnPack"] -git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" -uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" -version = "0.12.3" - -[[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.10.0" - -[[deps.Polyester]] -deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Requires", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"] -git-tree-sha1 = "8df43bbe60029526dd628af7e9951f5af680d4d7" -uuid = "f517fe37-dbe3-4b94-8317-1923a5111588" -version = "0.7.10" - -[[deps.PolyesterWeave]] -deps = ["BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "Static", "ThreadingUtilities"] -git-tree-sha1 = "240d7170f5ffdb285f9427b92333c3463bf65bf6" -uuid = "1d0040c9-8b98-4ee7-8388-3f51789ca0ad" -version = "0.2.1" - -[[deps.PreallocationTools]] -deps = ["Adapt", "ArrayInterface", "ForwardDiff"] -git-tree-sha1 = "b6665214f2d0739f2d09a17474dd443b9139784a" -uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" -version = "0.4.20" - - [deps.PreallocationTools.extensions] - PreallocationToolsReverseDiffExt = "ReverseDiff" - - [deps.PreallocationTools.weakdeps] - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - -[[deps.PrecompileTools]] -deps = ["Preferences"] -git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" -uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.2.1" - -[[deps.Preferences]] -deps = ["TOML"] -git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" -uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.3" - -[[deps.Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[deps.Random]] -deps = ["SHA"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[deps.RecipesBase]] -deps = ["PrecompileTools"] -git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" -uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" -version = "1.3.4" - -[[deps.RecursiveArrayTools]] -deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "a94d22ca9ad49a7a169ecbc5419c59b9793937cc" -uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "3.12.0" - - [deps.RecursiveArrayTools.extensions] - RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" - RecursiveArrayToolsForwardDiffExt = "ForwardDiff" - RecursiveArrayToolsMeasurementsExt = "Measurements" - RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" - RecursiveArrayToolsReverseDiffExt = ["ReverseDiff", "Zygote"] - RecursiveArrayToolsTrackerExt = "Tracker" - RecursiveArrayToolsZygoteExt = "Zygote" - - [deps.RecursiveArrayTools.weakdeps] - FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" - MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.RecursiveFactorization]] -deps = ["LinearAlgebra", "LoopVectorization", "Polyester", "PrecompileTools", "StrideArraysCore", "TriangularSolve"] -git-tree-sha1 = "8bc86c78c7d8e2a5fe559e3721c0f9c9e303b2ed" -uuid = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" -version = "0.2.21" - -[[deps.Reexport]] -git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" -uuid = "189a3867-3050-52da-a836-e630ba90ab69" -version = "1.2.2" - -[[deps.Requires]] -deps = ["UUIDs"] -git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" -uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.3.0" - -[[deps.RuntimeGeneratedFunctions]] -deps = ["ExprTools", "SHA", "Serialization"] -git-tree-sha1 = "6aacc5eefe8415f47b3e34214c1d79d2674a0ba2" -uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47" -version = "0.5.12" - -[[deps.SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" -version = "0.7.0" - -[[deps.SIMDTypes]] -git-tree-sha1 = "330289636fb8107c5f32088d2741e9fd7a061a5c" -uuid = "94e857df-77ce-4151-89e5-788b33177be4" -version = "0.1.0" - -[[deps.SLEEFPirates]] -deps = ["IfElse", "Static", "VectorizationBase"] -git-tree-sha1 = "3aac6d68c5e57449f5b9b865c9ba50ac2970c4cf" -uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa" -version = "0.6.42" - -[[deps.SciMLBase]] -deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "3fbd6a361ec965a89f1ec64320a8b8a80b7409c3" -repo-rev = "ap/nlls_bvp" -repo-url = "https://github.com/SciML/SciMLBase.jl.git" -uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "2.30.1" - - [deps.SciMLBase.extensions] - SciMLBaseChainRulesCoreExt = "ChainRulesCore" - SciMLBaseMakieExt = "Makie" - SciMLBasePartialFunctionsExt = "PartialFunctions" - SciMLBasePyCallExt = "PyCall" - SciMLBasePythonCallExt = "PythonCall" - SciMLBaseRCallExt = "RCall" - SciMLBaseZygoteExt = "Zygote" - - [deps.SciMLBase.weakdeps] - ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b" - PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" - PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" - RCall = "6f49c342-dc21-5d91-9882-a32aef131414" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.SciMLOperators]] -deps = ["ArrayInterface", "DocStringExtensions", "LinearAlgebra", "MacroTools", "Setfield", "SparseArrays", "StaticArraysCore"] -git-tree-sha1 = "10499f619ef6e890f3f4a38914481cc868689cd5" -uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" -version = "0.3.8" - -[[deps.SciMLStructures]] -git-tree-sha1 = "5833c10ce83d690c124beedfe5f621b50b02ba4d" -uuid = "53ae85a6-f571-4167-b2af-e1d143709226" -version = "1.1.0" - -[[deps.Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[deps.Setfield]] -deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"] -git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac" -uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46" -version = "1.1.1" - -[[deps.SharedArrays]] -deps = ["Distributed", "Mmap", "Random", "Serialization"] -uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" - -[[deps.SimpleNonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "DiffResults", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] -git-tree-sha1 = "a535ae5083708f59e75d5bb3042c36d1be9bc778" -uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" -version = "1.6.0" - - [deps.SimpleNonlinearSolve.extensions] - SimpleNonlinearSolveChainRulesCoreExt = "ChainRulesCore" - SimpleNonlinearSolvePolyesterForwardDiffExt = "PolyesterForwardDiff" - SimpleNonlinearSolveReverseDiffExt = "ReverseDiff" - SimpleNonlinearSolveStaticArraysExt = "StaticArrays" - SimpleNonlinearSolveTrackerExt = "Tracker" - SimpleNonlinearSolveZygoteExt = "Zygote" - - [deps.SimpleNonlinearSolve.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.SimpleTraits]] -deps = ["InteractiveUtils", "MacroTools"] -git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" -uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" -version = "0.9.4" - -[[deps.SimpleUnPack]] -git-tree-sha1 = "58e6353e72cde29b90a69527e56df1b5c3d8c437" -uuid = "ce78b400-467f-4804-87d8-8f486da07d0a" -version = "1.1.0" - -[[deps.Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[deps.SparseArrays]] -deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] -uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -version = "1.10.0" - -[[deps.SparseDiffTools]] -deps = ["ADTypes", "Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "PackageExtensionCompat", "Random", "Reexport", "SciMLOperators", "Setfield", "SparseArrays", "StaticArrayInterface", "StaticArrays", "Tricks", "UnPack", "VertexSafeGraphs"] -git-tree-sha1 = "a616ac46c38da60ac05cecf52064d44732edd05e" -uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -version = "2.17.0" - - [deps.SparseDiffTools.extensions] - SparseDiffToolsEnzymeExt = "Enzyme" - SparseDiffToolsPolyesterExt = "Polyester" - SparseDiffToolsPolyesterForwardDiffExt = "PolyesterForwardDiff" - SparseDiffToolsSymbolicsExt = "Symbolics" - SparseDiffToolsZygoteExt = "Zygote" - - [deps.SparseDiffTools.weakdeps] - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" - PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" - Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.Sparspak]] -deps = ["Libdl", "LinearAlgebra", "Logging", "OffsetArrays", "Printf", "SparseArrays", "Test"] -git-tree-sha1 = "342cf4b449c299d8d1ceaf00b7a49f4fbc7940e7" -uuid = "e56a9233-b9d6-4f03-8d0f-1825330902ac" -version = "0.3.9" - -[[deps.SpecialFunctions]] -deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d" -uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.3.1" -weakdeps = ["ChainRulesCore"] - - [deps.SpecialFunctions.extensions] - SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" - -[[deps.Static]] -deps = ["IfElse"] -git-tree-sha1 = "d2fdac9ff3906e27f7a618d47b676941baa6c80c" -uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" -version = "0.8.10" - -[[deps.StaticArrayInterface]] -deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "PrecompileTools", "Requires", "SparseArrays", "Static", "SuiteSparse"] -git-tree-sha1 = "5d66818a39bb04bf328e92bc933ec5b4ee88e436" -uuid = "0d7ed370-da01-4f52-bd93-41d350b8b718" -version = "1.5.0" -weakdeps = ["OffsetArrays", "StaticArrays"] - - [deps.StaticArrayInterface.extensions] - StaticArrayInterfaceOffsetArraysExt = "OffsetArrays" - StaticArrayInterfaceStaticArraysExt = "StaticArrays" - -[[deps.StaticArrays]] -deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] -git-tree-sha1 = "bf074c045d3d5ffd956fa0a461da38a44685d6b2" -uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.9.3" -weakdeps = ["ChainRulesCore", "Statistics"] - - [deps.StaticArrays.extensions] - StaticArraysChainRulesCoreExt = "ChainRulesCore" - StaticArraysStatisticsExt = "Statistics" - -[[deps.StaticArraysCore]] -git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" -uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" -version = "1.4.2" - -[[deps.Statistics]] -deps = ["LinearAlgebra", "SparseArrays"] -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -version = "1.10.0" - -[[deps.StrideArraysCore]] -deps = ["ArrayInterface", "CloseOpenIntervals", "IfElse", "LayoutPointers", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface", "ThreadingUtilities"] -git-tree-sha1 = "d6415f66f3d89c615929af907fdc6a3e17af0d8c" -uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da" -version = "0.5.2" - -[[deps.SuiteSparse]] -deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] -uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" - -[[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] -uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "7.2.1+1" - -[[deps.SymbolicIndexingInterface]] -deps = ["MacroTools", "RuntimeGeneratedFunctions"] -git-tree-sha1 = "f7b1fc9fc2bc938436b7684c243be7d317919056" -uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" -version = "0.3.11" - -[[deps.TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" -version = "1.0.3" - -[[deps.TableTraits]] -deps = ["IteratorInterfaceExtensions"] -git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" -uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" -version = "1.0.1" - -[[deps.Tables]] -deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] -git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d" -uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.11.1" - -[[deps.Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" -version = "1.10.0" - -[[deps.Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[deps.ThreadingUtilities]] -deps = ["ManualMemory"] -git-tree-sha1 = "eda08f7e9818eb53661b3deb74e3159460dfbc27" -uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" -version = "0.5.2" - -[[deps.TimerOutputs]] -deps = ["ExprTools", "Printf"] -git-tree-sha1 = "f548a9e9c490030e545f72074a41edfd0e5bcdd7" -uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" -version = "0.5.23" - -[[deps.TriangularSolve]] -deps = ["CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "LoopVectorization", "Polyester", "Static", "VectorizationBase"] -git-tree-sha1 = "fadebab77bf3ae041f77346dd1c290173da5a443" -uuid = "d5829a12-d9aa-46ab-831f-fb7c9ab06edf" -version = "0.1.20" - -[[deps.Tricks]] -git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f" -uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" -version = "0.1.8" - -[[deps.TruncatedStacktraces]] -deps = ["InteractiveUtils", "MacroTools", "Preferences"] -git-tree-sha1 = "ea3e54c2bdde39062abf5a9758a23735558705e1" -uuid = "781d530d-4396-4725-bb49-402e4bee1e77" -version = "1.4.0" - -[[deps.UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" - -[[deps.UnPack]] -git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" -uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" -version = "1.0.2" - -[[deps.Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[deps.VectorizationBase]] -deps = ["ArrayInterface", "CPUSummary", "HostCPUFeatures", "IfElse", "LayoutPointers", "Libdl", "LinearAlgebra", "SIMDTypes", "Static", "StaticArrayInterface"] -git-tree-sha1 = "7209df901e6ed7489fe9b7aa3e46fb788e15db85" -uuid = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f" -version = "0.21.65" - -[[deps.VertexSafeGraphs]] -deps = ["Graphs"] -git-tree-sha1 = "8351f8d73d7e880bfc042a8b6922684ebeafb35c" -uuid = "19fa3120-7c27-5ec5-8db8-b0b0aa330d6f" -version = "0.2.0" - -[[deps.Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+1" - -[[deps.libblastrampoline_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.8.0+1" - -[[deps.nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.52.0+1" - -[[deps.p7zip_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+2" diff --git a/Project.toml b/Project.toml index e9c3e455..85c9cf6d 100644 --- a/Project.toml +++ b/Project.toml @@ -59,7 +59,7 @@ Random = "1.10" ReTestItems = "1.23.1" RecursiveArrayTools = "3.4" Reexport = "1.2" -SciMLBase = "2.19" +SciMLBase = "2.31" Setfield = "1" SparseArrays = "1.10" SparseDiffTools = "2.14" From 952a75162e103fb6a8629c7bca4fb897973fa676 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 25 Mar 2024 12:15:03 -0400 Subject: [PATCH 24/24] Remove windows ODE Interface tests --- test/runtests.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 68469e0f..88d0e890 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,5 +4,7 @@ ReTestItems.runtests(joinpath(@__DIR__, "mirk/")) ReTestItems.runtests(joinpath(@__DIR__, "misc/")) ReTestItems.runtests(joinpath(@__DIR__, "shooting/")) -# Wrappers like ODEInterface don't support parallel testing -ReTestItems.runtests(joinpath(@__DIR__, "wrappers/"); nworkers = 0) +if !Sys.iswindows() + # Wrappers like ODEInterface don't support parallel testing + ReTestItems.runtests(joinpath(@__DIR__, "wrappers/"); nworkers = 0) +end