diff --git a/Project.toml b/Project.toml index 9194b91f37..2410fd74ca 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEq" uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" authors = ["Chris Rackauckas ", "Yingbo Ma "] -version = "6.88.1" +version = "6.89.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/docs/common_first_steps.jl b/docs/common_first_steps.jl new file mode 100644 index 0000000000..a84500e058 --- /dev/null +++ b/docs/common_first_steps.jl @@ -0,0 +1,29 @@ +using Markdown +function first_steps(name, solver) + Markdown.parse("""## Installation + To be able to access the solvers in `$name`, you must first install them use the Julia package manager: + + ```julia + using Pkg + Pkg.add("$name") + ``` + This will only install the solvers listed at the bottom of this page. + If you want to explore other solvers for your problem, + you will need to install some of the other libraries listed in the navigation bar on the left. + + ## Example usage + + ```julia + using $name + + function lorenz!(du, u, p, t) + du[1] = 10.0 * (u[2] - u[1]) + u[2] = u[1] * (28.0 - u[3]) - u[2] + du[3] = u[1] * u[2] - (8 / 3) * u[3] + end + u0 = [1.0; 0.0; 0.0] + tspan = (0.0, 100.0) + prob = ODEProblem(lorenz!, u0, tspan) + sol = solve(prob, $solver()) + ```""") +end diff --git a/docs/make.jl b/docs/make.jl index 6eaf972530..59d6df25d4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -8,54 +8,87 @@ makedocs(sitename = "OrdinaryDiffEq.jl", clean = true, doctest = false, modules = [OrdinaryDiffEq, + OrdinaryDiffEq.OrdinaryDiffEqAdamsBashforthMoulton, + OrdinaryDiffEq.OrdinaryDiffEqBDF, + OrdinaryDiffEq.OrdinaryDiffEqDefault, + OrdinaryDiffEq.OrdinaryDiffEqExplicitRK, + OrdinaryDiffEq.OrdinaryDiffEqExponentialRK, OrdinaryDiffEq.OrdinaryDiffEqExtrapolation, - OrdinaryDiffEq.OrdinaryDiffEqStabilizedRK, - OrdinaryDiffEq.OrdinaryDiffEqStabilizedIRK, - OrdinaryDiffEq.OrdinaryDiffEqLowStorageRK, - OrdinaryDiffEq.OrdinaryDiffEqSSPRK, OrdinaryDiffEq.OrdinaryDiffEqFeagin, - OrdinaryDiffEq.OrdinaryDiffEqSymplecticRK, + OrdinaryDiffEq.OrdinaryDiffEqFIRK, + OrdinaryDiffEq.OrdinaryDiffEqHighOrderRK, + OrdinaryDiffEq.OrdinaryDiffEqIMEXMultistep, + OrdinaryDiffEq.OrdinaryDiffEqLinear, + OrdinaryDiffEq.OrdinaryDiffEqLowOrderRK, + OrdinaryDiffEq.OrdinaryDiffEqLowStorageRK, + OrdinaryDiffEq.OrdinaryDiffEqNordsieck, + OrdinaryDiffEq.OrdinaryDiffEqPDIRK, + OrdinaryDiffEq.OrdinaryDiffEqPRK, + OrdinaryDiffEq.OrdinaryDiffEqQPRK, OrdinaryDiffEq.OrdinaryDiffEqRKN, - OrdinaryDiffEq.OrdinaryDiffEqVerner, + OrdinaryDiffEq.OrdinaryDiffEqRosenbrock, OrdinaryDiffEq.OrdinaryDiffEqSDIRK, - OrdinaryDiffEq.OrdinaryDiffEqBDF, - OrdinaryDiffEq.OrdinaryDiffEqDefault, - OrdinaryDiffEq.OrdinaryDiffEqFIRK], + OrdinaryDiffEq.OrdinaryDiffEqSSPRK, + OrdinaryDiffEq.OrdinaryDiffEqStabilizedIRK, + OrdinaryDiffEq.OrdinaryDiffEqStabilizedRK, + OrdinaryDiffEq.OrdinaryDiffEqSymplecticRK, + OrdinaryDiffEq.OrdinaryDiffEqTsit5, + OrdinaryDiffEq.OrdinaryDiffEqVerner + ], warnonly = [:docs_block, :missing_docs, :eval_block], format = Documenter.HTML(analytics = "UA-90474609-3", assets = ["assets/favicon.ico"], - canonical = "https://ordinarydiffeq.sciml.ai/stable/"), + canonical = "https://ordinarydiffeq.sciml.ai/stable/", + size_threshold_ignore = [joinpath("semiimplicit", "Rosenbrock.md"), + joinpath("massmatrixdae", "Rosenbrock.md")]), pages = [ "OrdinaryDiffEq.jl: ODE solvers and utilities" => "index.md", "Usage" => "usage.md", - "Standard Non-Stiff ODEProblem Solvers" => [ - "nonstiff/explicitrk.md", - "nonstiff/lowstorage_ssprk.md", - "nonstiff/explicit_extrapolation.md", - "nonstiff/nonstiff_multistep.md" + "Explicit Solvers" => [ + "explicit/Tsit5.md", + "explicit/Verner.md", + "explicit/AdamsBashforthMoulton.md", + "explicit/LowStorageRK.md", + "explicit/SSPRK.md", + "explicit/LowOrderRK.md", + "explicit/HighOrderRK.md", + "explicit/Feagin.md", + "explicit/PRK.md", + "explicit/QPRK.md", + "explicit/Extrapolation.md" ], - "Standard Stiff ODEProblem Solvers" => [ - "stiff/firk.md", - "stiff/rosenbrock.md", - "stiff/stabilized_rk.md", - "stiff/sdirk.md", - "stiff/stiff_multistep.md", - "stiff/implicit_extrapolation.md" + "Semi-Implicit Solvers" => [ + "semiimplicit/Rosenbrock.md", + "semiimplicit/StabalizedRK.md", + "semiimplicit/ExponentialRK.md" ], - "Second Order and Dynamical ODE Solvers" => [ - "dynamical/nystrom.md", - "dynamical/symplectic.md" + "Implicit Solvers" => [ + "implicit/SDIRK.md", + "implicit/FIRK.md", + "implicit/BDF.md", + "implicit/Extrapolation.md", + "implicit/PDIRK.md", + "implicit/Nordsieck.md" ], "IMEX Solvers" => [ - "imex/imex_multistep.md", - "imex/imex_sdirk.md" + "imex/IMEXMultistep.md", + "imex/StabalizedIRK.md", + "imex/IMEXBDF.md" + ], + "Dynamical ODE Explicit Solvers" => [ + "dynamicalodeexplicit/RKN.md", + "dynamicalodeexplicit/SymplecticRK.md" ], "Semilinear ODE Solvers" => [ - "semilinear/exponential_rk.md", - "semilinear/magnus.md" + "semilinear/ExponentialRK.md", + "semilinear/Linear.md" + ], + "Mass Matrix DAE Solvers" => [ + "massmatrixdae/Rosenbrock.md", + "massmatrixdae/BDF.md" ], - "DAEProblem Solvers" => [ - "dae/fully_implicit.md" + "Fully Implicit DAE Solvers" => [ + "fullyimplicitdae/BDF.md" ], "Misc Solvers" => [ "misc.md" diff --git a/docs/src/dae/fully_implicit.md b/docs/src/dae/fully_implicit.md deleted file mode 100644 index b9fcb50da9..0000000000 --- a/docs/src/dae/fully_implicit.md +++ /dev/null @@ -1,7 +0,0 @@ -# Methods for Fully Implicit ODEs (DAEProblem) - -```@docs -DImplicitEuler -DABDF2 -DFBDF -``` diff --git a/docs/src/dynamical/nystrom.md b/docs/src/dynamical/nystrom.md deleted file mode 100644 index 7c9567cc49..0000000000 --- a/docs/src/dynamical/nystrom.md +++ /dev/null @@ -1,18 +0,0 @@ -# Runge-Kutta Nystrom Methods - -```@docs -IRKN3 -IRKN4 -Nystrom4 -Nystrom4VelocityIndependent -Nystrom5VelocityIndependent -FineRKN4 -FineRKN5 -DPRKN6 -DPRKN6FM -DPRKN8 -DPRKN12 -ERKN4 -ERKN5 -ERKN7 -``` diff --git a/docs/src/dynamical/symplectic.md b/docs/src/dynamical/symplectic.md deleted file mode 100644 index e423f4f34e..0000000000 --- a/docs/src/dynamical/symplectic.md +++ /dev/null @@ -1,21 +0,0 @@ -# Symplectic Runge-Kutta Methods - -```@docs -SymplecticEuler -VelocityVerlet -VerletLeapfrog -PseudoVerletLeapfrog -McAte2 -Ruth3 -McAte3 -CandyRoz4 -McAte4 -CalvoSanz4 -McAte42 -McAte5 -Yoshida6 -KahanLi6 -McAte8 -KahanLi8 -SofSpa10 -``` diff --git a/docs/src/dynamicalodeexplicit/RKN.md b/docs/src/dynamicalodeexplicit/RKN.md new file mode 100644 index 0000000000..ff8f20bcf8 --- /dev/null +++ b/docs/src/dynamicalodeexplicit/RKN.md @@ -0,0 +1,57 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqRKN + +Second order solvers. + +To be able to access the solvers in `OrdinaryDiffEqRKN`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqRKN") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqOrdinaryDiffEqRKN +function HH_acceleration!(dv, v, u, p, t) + x, y = u + dx, dy = dv + dv[1] = -x - 2x * y + dv[2] = y^2 - y - x^2 +end +initial_positions = [0.0, 0.1] +initial_velocities = [0.5, 0.0] +tspan = (0.0, 1.0) +prob = SecondOrderODEProblem(HH_acceleration!, initial_velocities, initial_positions, tspan) +sol = solve(prob, Nystrom4(), dt = 1 / 10) +``` + +## Full list of solvers + +```@docs +IRKN3 +IRKN4 +Nystrom4 +Nystrom4VelocityIndependent +Nystrom5VelocityIndependent +FineRKN4 +FineRKN5 +DPRKN4 +DPRKN5 +DPRKN6 +DPRKN6FM +DPRKN8 +DPRKN12 +ERKN4 +ERKN5 +ERKN7 +RKN4 +``` diff --git a/docs/src/dynamicalodeexplicit/SymplecticRK.md b/docs/src/dynamicalodeexplicit/SymplecticRK.md new file mode 100644 index 0000000000..cd35b08e1b --- /dev/null +++ b/docs/src/dynamicalodeexplicit/SymplecticRK.md @@ -0,0 +1,64 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqSymplecticRK + +A symplectic integrator is an integrator whose solution resides on a symplectic manifold. +Because of discretization error, when it is solving a Hamiltonian system it doesn't get exactly the correct trajectory on the manifold. +Instead, that trajectory itself is perturbed `O(Δtn)` for the order n from the true trajectory. +Then there's a linear drift due to numerical error of this trajectory over time +Normal integrators tend to have a quadratic (or more) drift, and do not have any good global guarantees about this phase space path (just local). +What means is that symplectic integrators tend to capture the long-time patterns better than normal integrators because of this lack of drift and this almost guarantee of periodicity. + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqSymplecticRK`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqSymplecticRK") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqSymplecticRK +function HH_acceleration!(dv, v, u, p, t) + x, y = u + dx, dy = dv + dv[1] = -x - 2x * y + dv[2] = y^2 - y - x^2 +end +initial_positions = [0.0, 0.1] +initial_velocities = [0.5, 0.0] +tspan = (0.0, 1.0) +prob = SecondOrderODEProblem(HH_acceleration!, initial_velocities, initial_positions, tspan) +sol = solve(prob, KahanLi8(), dt = 1 / 10) +``` + +## Full list of solvers + +```@docs +SymplecticEuler +VelocityVerlet +VerletLeapfrog +PseudoVerletLeapfrog +McAte2 +Ruth3 +McAte3 +CandyRoz4 +McAte4 +CalvoSanz4 +McAte42 +McAte5 +Yoshida6 +KahanLi6 +McAte8 +KahanLi8 +SofSpa10 +``` diff --git a/docs/src/explicit/AdamsBashforthMoulton.md b/docs/src/explicit/AdamsBashforthMoulton.md new file mode 100644 index 0000000000..bef0173cde --- /dev/null +++ b/docs/src/explicit/AdamsBashforthMoulton.md @@ -0,0 +1,37 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqAdamsBashforthMoulton + +Multistep methods, useful for integrating a very expensive to evaluate non-stiff system of differential equations. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqAdamsBashforthMoulton", "VCABM") +``` + +## Full list of solvers + +### Explicit Multistep Methods + +```@docs +AB3 +AB4 +AB5 +``` + +### Predictor-Corrector Methods + +```@docs +ABM32 +ABM43 +ABM54 +VCAB3 +VCAB4 +VCAB5 +VCABM3 +VCABM4 +VCABM5 +VCABM +``` diff --git a/docs/src/explicit/Extrapolation.md b/docs/src/explicit/Extrapolation.md new file mode 100644 index 0000000000..5d80afc833 --- /dev/null +++ b/docs/src/explicit/Extrapolation.md @@ -0,0 +1,24 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqExtrapolation + +Solvers based on within method parallelism, allowing multithreading of the solution across +different values of `f`. +The explicit extrapolation solvers are generally outclassed by other explicit methods. +However, some [stiff extrapolation](@ref StiffExtrapolation) methods perform very well if +the problem is sufficiently stiff. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqExtrapolation", "ExtrapolationMidpointDeuflhard") +``` + +## Full list of solvers + +```@docs +AitkenNeville +ExtrapolationMidpointDeuflhard +ExtrapolationMidpointHairerWanner +``` diff --git a/docs/src/explicit/Feagin.md b/docs/src/explicit/Feagin.md new file mode 100644 index 0000000000..c2f66d9727 --- /dev/null +++ b/docs/src/explicit/Feagin.md @@ -0,0 +1,26 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqFeagin + +Preferred solvers for non-stiff problems at very low tolerance, `<1e-30`. +Best combined with preciser than `Float64` number types for the state, such as the `BigFloat` number type. +Note that the Feagin methods have a less robust error estimator than the Verner methods, and thus even for +very low tolerance problems the Verner methods (`Vern9`) may still be more efficient. In addition, at extremely +low tolerances the explicit extrapolation methods allow for arbitrarily high variable order stepping which will +also outperform the Feagin methods. As such, the Feagin methods may be useful in the Float128 precision range +but should be tested against other algorithms. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqFeagin", "Feagin14") +``` + +## Full list of solvers + +```@docs +Feagin10 +Feagin12 +Feagin14 +``` diff --git a/docs/src/explicit/HighOrderRK.md b/docs/src/explicit/HighOrderRK.md new file mode 100644 index 0000000000..0f7648354f --- /dev/null +++ b/docs/src/explicit/HighOrderRK.md @@ -0,0 +1,22 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqHighOrderRK + +Solvers for non-stiff problems at low tolerance. +However, the solvers in [`OrdinaryDiffEqVerner`](@ref OrdinaryDiffEqVerner) generally perform better at low tolerances. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqHighOrderRK", "DP8") +``` + +## Full list of solvers + +```@docs +TanYam7 +TsitPap8 +DP8 +PFRK87 +``` diff --git a/docs/src/explicit/LowOrderRK.md b/docs/src/explicit/LowOrderRK.md new file mode 100644 index 0000000000..662b67fda3 --- /dev/null +++ b/docs/src/explicit/LowOrderRK.md @@ -0,0 +1,48 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqLowOrderRK + +If [`OrdinaryDiffEqTsit5`](@ref OrdinaryDiffEqTsit5) is not working well for your non-stiff problem at default and higher tolerance, +it can be worthwhile to explore the options in this package. +In particular, when more robust error control is required, [`BS5`](@ref) is a good choice. +If at moderate tolerances and the interpolation error is very important, +consider the [`OwrenZen5`](@ref) method. +For fast solving at higher tolerances, we recommend [`BS3`](@ref), +or [`OwrenZen3`](@ref)if the interpolation error is important. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqLowOrderRK", "BS3") +``` + +## Full list of solvers + +```@docs +Euler +Heun +Ralston +Midpoint +RK4 +BS3 +OwrenZen3 +OwrenZen4 +OwrenZen5 +BS5 +DP5 +Anas5 +RKO65 +FRK65 +RKM +MSRK5 +MSRK6 +PSRK4p7q6 +PSRK3p5q4 +PSRK3p6q5 +Stepanov5 +SIR54 +Alshina2 +Alshina3 +Alshina6 +``` diff --git a/docs/src/explicit/LowStorageRK.md b/docs/src/explicit/LowStorageRK.md new file mode 100644 index 0000000000..563c134554 --- /dev/null +++ b/docs/src/explicit/LowStorageRK.md @@ -0,0 +1,66 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqLowStorageRK + +These methods are designed to have reduced register requirements, allowing for larger sets of ODEs to more +easily fit into RAM. For example, while the 5th order Tsit5 requires around 9 concurrent instantiations of the +ODE state `u`, `RDPK3Sp510` can achieve 5th order with 3 registers, effectively requiring 1/3 of the memory. +However, there are some efficiency trade-offs used in the design of the low-storage RK methods, and thus they +are generally only recommended in situations which are RAM bound, like large-scale PDE discretizations. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqLowStorageRK", "CarpenterKennedy2N54") +``` + +## Full list of solvers + +```@docs +ORK256 +DGLDDRK73_C +CarpenterKennedy2N54 +NDBLSRK124 +NDBLSRK144 +CFRLDDRK64 +TSLDDRK74 +DGLDDRK84_C +DGLDDRK84_F +SHLDDRK64 +RK46NL +ParsaniKetchesonDeconinck3S32 +ParsaniKetchesonDeconinck3S82 +ParsaniKetchesonDeconinck3S53 +ParsaniKetchesonDeconinck3S173 +ParsaniKetchesonDeconinck3S94 +ParsaniKetchesonDeconinck3S184 +ParsaniKetchesonDeconinck3S105 +ParsaniKetchesonDeconinck3S205 +CKLLSRK43_2 +CKLLSRK54_3C +CKLLSRK95_4S +CKLLSRK95_4C +CKLLSRK95_4M +CKLLSRK54_3C_3R +CKLLSRK54_3M_3R +CKLLSRK54_3N_3R +CKLLSRK85_4C_3R +CKLLSRK85_4M_3R +CKLLSRK85_4P_3R +CKLLSRK54_3N_4R +CKLLSRK54_3M_4R +CKLLSRK65_4M_4R +CKLLSRK85_4FM_4R +CKLLSRK75_4M_5R +RDPK3Sp35 +RDPK3SpFSAL35 +RDPK3Sp49 +RDPK3SpFSAL49 +RDPK3Sp510 +RDPK3SpFSAL510 +HSLDDRK64 +NDBLSRK134 +SHLDDRK_2N +SHLDDRK52 +``` diff --git a/docs/src/explicit/PRK.md b/docs/src/explicit/PRK.md new file mode 100644 index 0000000000..f1cf3ed72e --- /dev/null +++ b/docs/src/explicit/PRK.md @@ -0,0 +1,18 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqPRK + +Explicit solvers optimized for a certain number of parallel calls of the system of ordinary differential equations `f`. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqPRK", "KuttaPRK2p5") +``` + +## Full list of solvers + +```@docs +KuttaPRK2p5 +``` diff --git a/docs/src/explicit/QPRK.md b/docs/src/explicit/QPRK.md new file mode 100644 index 0000000000..507f30de38 --- /dev/null +++ b/docs/src/explicit/QPRK.md @@ -0,0 +1,19 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqQPRK + +Explicit solvers optimized for a certain number of parallel calls of the system of ordinary differential equations `f`. +Particularly good at low tolerances, when using quad-precision arithmetic, `Float128`. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqQPRK", "QPRK98") +``` + +## Full list of solvers + +```@docs +QPRK98 +``` diff --git a/docs/src/explicit/SSPRK.md b/docs/src/explicit/SSPRK.md new file mode 100644 index 0000000000..d0fd732d05 --- /dev/null +++ b/docs/src/explicit/SSPRK.md @@ -0,0 +1,41 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqSSPRK + +SSPRK methods are Runge-Kutta methods which support the "strongly preserving property" (SSP). +They are designed for the use in discretizations of hyperbolic partial differential equations and conservation laws +as they have extra stability properties ( e.g., stability with respect to total variation, the maximum norm, or other convex functionals) +when step-size restrictions are respected. +In particular, these properties are granted if the step-size is kept to a level where the CFL coefficients are less than the SSP coefficient. + +Note that for SSPRK methods, a algorithm utility `OrdinaryDiffEqCore.ssp_coefficient(alg)` exists that allows for querying the SSP coefficient for use in step size calculations. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqSSPRK", "SSPRK22") +``` + +## Full list of solvers + +```@docs +SSPRK22 +SSPRK33 +SSPRK53 +KYKSSPRK42 +KYK2014DGSSPRK_3S2 +SSPRK53_2N1 +SSPRK53_2N2 +SSPRK53_H +SSPRK63 +SSPRK73 +SSPRK83 +SSPRK43 +SSPRK432 +SSPRKMSVS43 +SSPRKMSVS32 +SSPRK932 +SSPRK54 +SSPRK104 +``` diff --git a/docs/src/explicit/Tsit5.md b/docs/src/explicit/Tsit5.md new file mode 100644 index 0000000000..921427d667 --- /dev/null +++ b/docs/src/explicit/Tsit5.md @@ -0,0 +1,19 @@ +```@meta +CollapsedDocStrings = true +``` + +# [OrdinaryDiffEqTsit5](@id OrdinaryDiffEqTsit5) + +Recommended solver for most non-stiff problems at default and higher tolerance. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqTsit5", "Tsit5") +``` + +## Full list of solvers + +```@docs +Tsit5 +AutoTsit5 +``` diff --git a/docs/src/explicit/Verner.md b/docs/src/explicit/Verner.md new file mode 100644 index 0000000000..51b1dac276 --- /dev/null +++ b/docs/src/explicit/Verner.md @@ -0,0 +1,31 @@ +```@meta +CollapsedDocStrings = true +``` + +# [OrdinaryDiffEqVerner](@id OrdinaryDiffEqVerner) + +Preferred solvers for non-stiff problems at low tolerance. +`Vern6`, `Vern7`, or `Vern8` are good methods for tolerances between `~1e-8-1e-12`, +and using `Float64` numbers for the state of the differential equation. +For even lower tolerances,`Vern9` should be used, combined with the more precise `BigFloat` number type. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqVerner", "Vern6") +``` + +## Full list of solvers + +```@docs +Vern6 +Vern7 +Vern8 +Vern9 +``` + +```@docs +AutoVern6 +AutoVern7 +AutoVern8 +AutoVern9 +``` diff --git a/docs/src/fullyimplicitdae/BDF.md b/docs/src/fullyimplicitdae/BDF.md new file mode 100644 index 0000000000..5f0c6ae38d --- /dev/null +++ b/docs/src/fullyimplicitdae/BDF.md @@ -0,0 +1,33 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqBDF + +Multistep BDF methods, good for large stiff systems. + +```@eval +using OrdinaryDiffEqBDF + +function f2(out, du, u, p, t) + out[1] = -0.04u[1] + 1e4 * u[2] * u[3] - du[1] + out[2] = +0.04u[1] - 3e7 * u[2]^2 - 1e4 * u[2] * u[3] - du[2] + out[3] = u[1] + u[2] + u[3] - 1.0 +end +u₀ = [1.0, 0, 0] +du₀ = [-0.04, 0.04, 0.0] +tspan = (0.0, 100000.0) +differential_vars = [true, true, false] +prob = DAEProblem(f2, du₀, u₀, tspan, differential_vars = differential_vars) +sol = solve(prob, DFBDF()) +``` + +## Full list of solvers + +### DAE + +```@docs +DImplicitEuler +DABDF2 +DFBDF +``` diff --git a/docs/src/imex/IMEXBDF.md b/docs/src/imex/IMEXBDF.md new file mode 100644 index 0000000000..62a37aef67 --- /dev/null +++ b/docs/src/imex/IMEXBDF.md @@ -0,0 +1,54 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqBDF + +Solvers if your system of ordinary differential equations can be split up into the sum of a +stiff and non-stiff part. These are IMEX extensions of common BDF schemes. + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqBDF`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqBDF") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqBDF +f1 = (u, p, t) -> 2u +f2 = (u, p, t) -> 2u +u0 = 1.0 +tspan = (0.0, 1.0) +prob = SplitODEProblem(f1, f2, u0, tspan) +sol = solve(prob, SBDF2(), dt = 1 / 10) +``` + +## Full list of solvers + +### IMEX Multistep + +```@docs +SBDF +SBDF2 +SBDF3 +SBDF4 +``` + +### IMEX SDIRK + +Note that Implicit Euler is the 1st order BDF method, and is thus implemented here using +the same machinery. + +```@docs +IMEXEuler +IMEXEulerARK +``` diff --git a/docs/src/imex/IMEXMultistep.md b/docs/src/imex/IMEXMultistep.md new file mode 100644 index 0000000000..5fd4803a1b --- /dev/null +++ b/docs/src/imex/IMEXMultistep.md @@ -0,0 +1,41 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqIMEXMultistep + +Solvers if your system of ordinary differential equations can be split up into the sum of a stiff and non-stiff part. +These are "standard" low order IMEX methods common in many naive partial differential +equation applications. + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqIMEXMultistep`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqIMEXMultistep") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqIMEXMultistep +f1 = (u, p, t) -> 2u +f2 = (u, p, t) -> 2u +u0 = 1.0 +tspan = (0.0, 1.0) +prob = SplitODEProblem(f1, f2, u0, tspan) +sol = solve(prob, CNAB2(), dt = 1 / 10) +``` + +## Full list of solvers + +```@docs +CNAB2 +CNLF2 +``` diff --git a/docs/src/imex/StabalizedIRK.md b/docs/src/imex/StabalizedIRK.md new file mode 100644 index 0000000000..5707ef8cac --- /dev/null +++ b/docs/src/imex/StabalizedIRK.md @@ -0,0 +1,57 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqStabalizedIRK + +Stabilized Explicit Runge-Kutta methods, +like Runge-Kutta-Chebyshev methods and ROCK methods +are explicit methods which chain together many stages in a specific way to get large stability regions. +they are made in such a way to converge to a large stability region, +and thus suitable to stiff equations. +However, they converge to having a large stability region in the direction of the negative real axis, +and thus are only stable on a subset of stiff equations which are not dominated by large complex eigenvalues in the Jacobian. + +Stabilized implicit methods try to mitigate this problem by being an IMEX type scheme, +requiring a SplitODEProblem where the splitting is designed to treat the large complex eigenvalues implicitly +while treating the large real eigenvalues using a fast explicit stabilized RK type of method. + +These methods utilize an upper bound on the spectral radius of the Jacobian. +Users can supply an upper bound by specifying the keyword argument `eigen_est`, for example + +```julia +`eigen_est = (integrator) -> integrator.eigen_est = upper_bound` +``` + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqStabalizedIRK`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqStabalizedIRK") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqStabilizedIRK +A = randn(20, 20) +B = randn(20, 20) +f1 = (u, p, t) -> A * u +f2 = (u, p, t) -> B * u +u0 = randn(20, 1) +tspan = (0.0, 1.0) +prob = SplitODEProblem(f1, f2, u0, tspan) +sol = solve(prob, IRKC()) +``` + +## Full list of solvers + +```@docs +IRKC +``` diff --git a/docs/src/imex/imex_multistep.md b/docs/src/imex/imex_multistep.md deleted file mode 100644 index aa87f22b59..0000000000 --- a/docs/src/imex/imex_multistep.md +++ /dev/null @@ -1,10 +0,0 @@ -# IMEX Multistep Methods - -```@docs -CNAB2 -CNLF2 -SBDF -SBDF2 -SBDF3 -SBDF4 -``` diff --git a/docs/src/imex/imex_sdirk.md b/docs/src/imex/imex_sdirk.md deleted file mode 100644 index 24ebaaaa89..0000000000 --- a/docs/src/imex/imex_sdirk.md +++ /dev/null @@ -1,16 +0,0 @@ -# IMEX SDIRK Methods - -```@docs -IMEXEuler -IMEXEulerARK -KenCarp3 -KenCarp4 -KenCarp47 -KenCarp5 -KenCarp58 -ESDIRK54I8L2SA -ESDIRK436L2SA2 -ESDIRK437L2SA -ESDIRK547L2SA2 -ESDIRK659L2SA -``` diff --git a/docs/src/implicit/BDF.md b/docs/src/implicit/BDF.md new file mode 100644 index 0000000000..5dd0c64edb --- /dev/null +++ b/docs/src/implicit/BDF.md @@ -0,0 +1,26 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqBDF + +Multistep methods, good for large stiff systems. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqBDF", "QNDF") +``` + +## Full list of solvers + +```@docs +ABDF2 +QNDF +QNDF1 +QNDF2 +QBDF +QBDF1 +QBDF2 +MEBDF2 +FBDF +``` diff --git a/docs/src/implicit/Extrapolation.md b/docs/src/implicit/Extrapolation.md new file mode 100644 index 0000000000..9d87507a84 --- /dev/null +++ b/docs/src/implicit/Extrapolation.md @@ -0,0 +1,23 @@ +```@meta +CollapsedDocStrings = true +``` + +# [OrdinaryDiffEqExtrapolation](@id StiffExtrapolation) + +Solvers based on within method parallelism. +These solvers perform well for medium sized systems of ordinary differential equations, of about 20 to 500 equations, +at low tolerances. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqExtrapolation", "ImplicitEulerBarycentricExtrapolation") +``` + +## Full list of solvers + +```@docs +ImplicitEulerExtrapolation +ImplicitDeuflhardExtrapolation +ImplicitHairerWannerExtrapolation +ImplicitEulerBarycentricExtrapolation +``` diff --git a/docs/src/implicit/FIRK.md b/docs/src/implicit/FIRK.md new file mode 100644 index 0000000000..535c265c4d --- /dev/null +++ b/docs/src/implicit/FIRK.md @@ -0,0 +1,40 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqFIRK + +FIRK methods are fully implicit Runge-Kutta methods. +They can have special properties, like be symplectic integrators, and can achieve higher order for the same number of stage in comparison to diagonal methods. +However, the fully implicit methods have a larger implicit system to solve and thus have a higher linear algebra cost. +This can be useful in some contexts to promote more parallelism, +but also since the size of the factorization is cubic and the dominant cost for large equations, +multiplying `O(n^3)` operations to `O((sn)^3)` can be a considerable cost increase for FIRK tableaus, +where `s`, the number of stages, is particularly large. +That said, the restriction to diagonal implicitness imposes order restrictions, +such as SDIRK methods having a maximum order of 5, which can restrict the problems best suited for SDIRK methods. + +The most common FIRK method in production are those based on RadauIIA tableaus, +which is an ODE representation of Gaussian collocation. +Like Gaussian collocation, it achieves higher order convergence than its stages, namely order 2s+1 for s stages. +Thus RadauIIA FIRK methods tend to be some of the highest order methods (excluding extrapolation methods). +This means that high order RadauIIA methods are recommended in the same scenarios that high-order explicit Runge-Kutta methods are recommended simply with the restriction of being a stiff equation. +Such scenarios include cases like very low tolerances: RadauIIA methods can be the best performing methods for scenarios where tolerances are `1e-9` and below. +Additionally, for ODE systems of size less than 200, the increased size of the Jacobian is mitigated by improved multithreading, +since BLAS implementations are only good at multithreading LU factorizations after a certain matrix size. +For this reason, RadauIIA methods tend to be recommended in cases where ODE size is small to intermediate and very accurate solutions are required. + +They should be tested against the parallel implicit extrapolation which also specialize in this regime. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqFIRK", "RadauIIA5") +``` + +## Full list of solvers + +```@docs +RadauIIA3 +RadauIIA5 +RadauIIA9 +``` diff --git a/docs/src/implicit/Nordsieck.md b/docs/src/implicit/Nordsieck.md new file mode 100644 index 0000000000..2ec56f837a --- /dev/null +++ b/docs/src/implicit/Nordsieck.md @@ -0,0 +1,30 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqNordsieck + +The Nordsieck form is an alternative representation of multistep methods which, +instead of representing and saving past step values in a history vector, +it uses a derivative list (like a Taylor expansion) for the computation of the next point. +The Nordsieck form was pioneered by early implementations of BDF methods such LSODE, VODE, and finally CVODE. +It can have some advantages in terms of restartability as the full Nordsieck vector can be instantiated given only the information of f and its derivatives after discontinuities, +but the higher derivative representations can also introduce numerical instabilities of their own. + +The Nordsieck implementations here are considered experimental implementations of the LSODE non-fixed leading coefficient form +and are generally considered inferior to the fixed-leading history-based BDF implementation of FBDF, and thus for all standard usage we recommend FBDF. +However, this algorithm is kept for experimental research and development purposes with the possibility of one day becoming a more discontinuity-aware BDF implementation. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqNordsieck", "AN5") +``` + +## Full list of solvers + +```@docs +AN5 +JVODE +JVODE_Adams +JVODE_BDF +``` diff --git a/docs/src/implicit/PDIRK.md b/docs/src/implicit/PDIRK.md new file mode 100644 index 0000000000..4838693e9c --- /dev/null +++ b/docs/src/implicit/PDIRK.md @@ -0,0 +1,34 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqPDIRK + +PDIRK methods are parallel DIRK methods. +SDIRK methods, or singly-diagonally implicit methods, +have to build and solve a factorize a Jacobian of the form `W = I-gammaJ` where `gamma` is dependent on the chosen method. +PDIRK methods use multiple different choices of `gamma`, i.e. `W_i = I-gamma_iJ`, +which are all used in the update process. +There are some advantages to this, +as no SDIRK method can be a higher order than 5, +while DIRK methods generally can have arbitrarily high order and lower error coefficients, +leading to lower errors at larger dt sizes. +With the right construction of the tableau, +these matrices can be factorized and the underlying steps can be computed in parallel, +which is why these are the parallel DIRK methods. + +!!! warning "Experimental" + + `OrdinaryDiffEqPDIRK` is experimental, + as there are no parallel DIRK tableaus that achieve good performance in the literature. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqPDIRK", "PDIRK44") +``` + +## Full list of solvers + +```@docs +PDIRK44 +``` diff --git a/docs/src/implicit/SDIRK.md b/docs/src/implicit/SDIRK.md new file mode 100644 index 0000000000..4d04f1041e --- /dev/null +++ b/docs/src/implicit/SDIRK.md @@ -0,0 +1,51 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqSDIRK + +This article is a stub. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqSDIRK", "PDIRK44") +``` + +## Full list of solvers + +```@docs +ImplicitEuler +ImplicitMidpoint +Trapezoid +TRBDF2 +SDIRK2 +SDIRK22 +SSPSDIRK2 +Kvaerno3 +KenCarp3 +CFNLIRK3 +Cash4 +SFSDIRK4 +SFSDIRK5 +SFSDIRK6 +SFSDIRK7 +SFSDIRK8 +Hairer4 +Hairer42 +Kvaerno4 +Kvaerno5 +``` + +### IMEX SDIRK + +```@docs +KenCarp4 +KenCarp47 +KenCarp5 +KenCarp58 +ESDIRK54I8L2SA +ESDIRK436L2SA2 +ESDIRK437L2SA +ESDIRK547L2SA2 +ESDIRK659L2SA +``` diff --git a/docs/src/index.md b/docs/src/index.md index 6ff9dd7ed6..b2647f8898 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -56,32 +56,19 @@ Pkg.status(; mode = PKGMODE_MANIFEST) # hide ``` -```@raw html -You can also download the -manifest file and the -project file. +link_manifest = "https://github.com/SciML/" * name * ".jl/tree/gh-pages/v" * version * + "/assets/Manifest.toml" +link_project = "https://github.com/SciML/" * name * ".jl/tree/gh-pages/v" * version * + "/assets/Project.toml" +Markdown.parse("""You can also download the +[manifest]($link_manifest) +file and the +[project]($link_project) +file. +""") ``` diff --git a/docs/src/massmatrixdae/BDF.md b/docs/src/massmatrixdae/BDF.md new file mode 100644 index 0000000000..d6d9f600df --- /dev/null +++ b/docs/src/massmatrixdae/BDF.md @@ -0,0 +1,38 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqBDF + +Multistep BDF methods, good for large stiff systems. + +```julia +function rober(du, u, p, t) + y₁, y₂, y₃ = u + k₁, k₂, k₃ = p + du[1] = -k₁ * y₁ + k₃ * y₂ * y₃ + du[2] = k₁ * y₁ - k₃ * y₂ * y₃ - k₂ * y₂^2 + du[3] = y₁ + y₂ + y₃ - 1 + nothing +end +M = [1.0 0 0 + 0 1.0 0 + 0 0 0] +f = ODEFunction(rober, mass_matrix = M) +prob_mm = ODEProblem(f, [1.0, 0.0, 0.0], (0.0, 1e5), (0.04, 3e7, 1e4)) +sol = solve(prob_mm, FBDF(), reltol = 1e-8, abstol = 1e-8) +``` + +## Full list of solvers + +```@docs; canonical=false +ABDF2 +QNDF +QNDF1 +QNDF2 +QBDF +QBDF1 +QBDF2 +MEBDF2 +FBDF +``` diff --git a/docs/src/massmatrixdae/Rosenbrock.md b/docs/src/massmatrixdae/Rosenbrock.md new file mode 100644 index 0000000000..baf5b78914 --- /dev/null +++ b/docs/src/massmatrixdae/Rosenbrock.md @@ -0,0 +1,70 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqRosenbrock + +Methods for small and medium sized stiff systems of differential equations. +At high tolerances, `>1e-2`, `Rosenbrock23` is a good choice. +At medium tolerances `>1e-8` it is recommended you use `Rodas5P` or `Rodas4P`, +the former is more efficient, but the latter is more reliable. +For larger systems look at multistep methods. + +## Example usage + +```julia +function rober(du, u, p, t) + y₁, y₂, y₃ = u + k₁, k₂, k₃ = p + du[1] = -k₁ * y₁ + k₃ * y₂ * y₃ + du[2] = k₁ * y₁ - k₃ * y₂ * y₃ - k₂ * y₂^2 + du[3] = y₁ + y₂ + y₃ - 1 + nothing +end +M = [1.0 0 0 + 0 1.0 0 + 0 0 0] +f = ODEFunction(rober, mass_matrix = M) +prob_mm = ODEProblem(f, [1.0, 0.0, 0.0], (0.0, 1e5), (0.04, 3e7, 1e4)) +sol = solve(prob_mm, Rodas5(), reltol = 1e-8, abstol = 1e-8) +``` + +## Full list of solvers + +```@docs; canonical=false +Rosenbrock23 +Rosenbrock32 +ROS3P +Rodas3 +Rodas23W +Rodas3P +Rodas4 +Rodas42 +Rodas4P +Rodas4P2 +Rodas5 +Rodas5P +Rodas5Pe +Rodas5Pr +RosenbrockW6S4OS +ROS2 +ROS2PR +ROS2S +ROS3 +ROS3PR +Scholz4_7 +ROS34PW1a +ROS34PW1b +ROS34PW2 +ROS34PW3 +ROS34PRw +ROS3PRL +ROS3PRL2 +ROK4a +RosShamp4 +Veldd4 +Velds4 +GRK4T +GRK4A +Ros4LStab +``` diff --git a/docs/src/misc.md b/docs/src/misc.md index 595e0c88f8..bbf99e06f7 100644 --- a/docs/src/misc.md +++ b/docs/src/misc.md @@ -1,6 +1,4 @@ ```@docs -LinearExponential SplitEuler CompositeAlgorithm -PDIRK44 ``` diff --git a/docs/src/nonstiff/explicit_extrapolation.md b/docs/src/nonstiff/explicit_extrapolation.md deleted file mode 100644 index 16a1b27916..0000000000 --- a/docs/src/nonstiff/explicit_extrapolation.md +++ /dev/null @@ -1,7 +0,0 @@ -# Explicit Extrapolation Methods - -```@docs -AitkenNeville -ExtrapolationMidpointDeuflhard -ExtrapolationMidpointHairerWanner -``` diff --git a/docs/src/nonstiff/explicitrk.md b/docs/src/nonstiff/explicitrk.md deleted file mode 100644 index 010a10e11f..0000000000 --- a/docs/src/nonstiff/explicitrk.md +++ /dev/null @@ -1,67 +0,0 @@ -# Explicit Runge-Kutta Methods - -With the help of [FastBroadcast.jl](https://github.com/YingboMa/FastBroadcast.jl), -we can use threaded parallelism to reduce compute time for all of the explicit Runge-Kutta methods! -The `thread` option determines whether internal broadcasting on appropriate CPU arrays should be serial -(`thread = OrdinaryDiffEq.False()`, default) or use multiple threads -(`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. -When we call `solve(prob, alg(thread=OrdinaryDiffEq.True()))`, -we can turn on the multithreading option to achieve acceleration -(for sufficiently large problems). - -## Standard Explicit Runge-Kutta Methods - -```@docs -Heun -Ralston -Midpoint -RK4 -RKM -MSRK5 -MSRK6 -Anas5 -RKO65 -OwrenZen3 -OwrenZen4 -OwrenZen5 -BS3 -DP5 -Tsit5 -DP8 -TanYam7 -TsitPap8 -Feagin10 -Feagin12 -Feagin14 -FRK65 -PFRK87 -Stepanov5 -SIR54 -Alshina2 -Alshina3 -Alshina6 -``` - -## Lazy Interpolation Explicit Runge-Kutta Methods - -```@docs -BS5 -Vern6 -Vern7 -Vern8 -Vern9 -``` - -## Fixed Timestep Only Explicit Runge-Kutta Methods - -```@docs -Euler -RK46NL -ORK256 -``` - -## Parallel Explicit Runge-Kutta Methods - -```@docs -KuttaPRK2p5 -``` diff --git a/docs/src/nonstiff/lowstorage_ssprk.md b/docs/src/nonstiff/lowstorage_ssprk.md deleted file mode 100644 index a8fa854f41..0000000000 --- a/docs/src/nonstiff/lowstorage_ssprk.md +++ /dev/null @@ -1,72 +0,0 @@ -# PDE-Specialized Explicit Runge-Kutta Methods - -## Low Storage Explicit Runge-Kutta Methods - -```@docs -CarpenterKennedy2N54 -SHLDDRK64 -SHLDDRK52 -SHLDDRK_2N -HSLDDRK64 -DGLDDRK73_C -DGLDDRK84_C -DGLDDRK84_F -NDBLSRK124 -NDBLSRK134 -NDBLSRK144 -CFRLDDRK64 -TSLDDRK74 -CKLLSRK43_2 -CKLLSRK54_3C -CKLLSRK95_4S -CKLLSRK95_4C -CKLLSRK95_4M -CKLLSRK54_3C_3R -CKLLSRK54_3M_3R -CKLLSRK54_3N_3R -CKLLSRK85_4C_3R -CKLLSRK85_4M_3R -CKLLSRK85_4P_3R -CKLLSRK54_3N_4R -CKLLSRK54_3M_4R -CKLLSRK65_4M_4R -CKLLSRK85_4FM_4R -CKLLSRK75_4M_5R -ParsaniKetchesonDeconinck3S32 -ParsaniKetchesonDeconinck3S82 -ParsaniKetchesonDeconinck3S53 -ParsaniKetchesonDeconinck3S173 -ParsaniKetchesonDeconinck3S94 -ParsaniKetchesonDeconinck3S184 -ParsaniKetchesonDeconinck3S105 -ParsaniKetchesonDeconinck3S205 -RDPK3Sp35 -RDPK3SpFSAL35 -RDPK3Sp49 -RDPK3SpFSAL49 -RDPK3Sp510 -RDPK3SpFSAL510 -``` - -## SSP Optimized Runge-Kutta Methods - -```@docs -KYK2014DGSSPRK_3S2 -SSPRK22 -SSPRK33 -SSPRK53 -KYKSSPRK42 -SSPRK53_2N1 -SSPRK53_2N2 -SSPRK53_H -SSPRK63 -SSPRK73 -SSPRK83 -SSPRK43 -SSPRK432 -SSPRKMSVS43 -SSPRKMSVS32 -SSPRK932 -SSPRK54 -SSPRK104 -``` diff --git a/docs/src/nonstiff/nonstiff_multistep.md b/docs/src/nonstiff/nonstiff_multistep.md deleted file mode 100644 index bfd1d15d8f..0000000000 --- a/docs/src/nonstiff/nonstiff_multistep.md +++ /dev/null @@ -1,26 +0,0 @@ -# Multistep Methods for Non-Stiff Equations - -## Explicit Multistep Methods - -```@docs -AB3 -AB4 -AB5 -AN5 -``` - -## Predictor-Corrector Methods - -```@docs -ABM32 -ABM43 -ABM54 -VCAB3 -VCAB4 -VCAB5 -VCABM3 -VCABM4 -VCABM5 -VCABM - -``` diff --git a/docs/src/semiimplicit/ExponentialRK.md b/docs/src/semiimplicit/ExponentialRK.md new file mode 100644 index 0000000000..e1f5a788f1 --- /dev/null +++ b/docs/src/semiimplicit/ExponentialRK.md @@ -0,0 +1,58 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqExponentialRK + +Methods for semi-linear differential equations. + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqLinear`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqExponentialRK") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqExponentialRK", "EPIRK5s3") +``` + +## Full list of solvers + +```@docs; canonical=false +LawsonEuler +NorsettEuler +ETD2 +ETDRK2 +ETDRK3 +ETDRK4 +HochOst4 +``` + +### Adaptive Exponential Rosenbrock Methods + +```@docs +Exprb32 +Exprb43 +``` + +### Exponential Propagation Iterative Runge-Kutta Methods (EPIRK) + +```@docs +Exp4 +EPIRK4s3A +EPIRK4s3B +EPIRK5s3 +EXPRB53s3 +EPIRK5P1 +EPIRK5P2 +``` diff --git a/docs/src/semiimplicit/Rosenbrock.md b/docs/src/semiimplicit/Rosenbrock.md new file mode 100644 index 0000000000..782ba30793 --- /dev/null +++ b/docs/src/semiimplicit/Rosenbrock.md @@ -0,0 +1,56 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqRosenbrock + +Methods for small and medium sized stiff systems of differential equations. +At high tolerances, `>1e-2`, `Rosenbrock23` is a good choice. +At medium tolerances `>1e-8` it is recommended you use `Rodas5P` or `Rodas4P`, +the former is more efficient, but the latter is more reliable. +For larger systems look at multistep methods. + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqRosenbrock", "Rodas5P") +``` + +## Full list of solvers + +```@docs +Rosenbrock23 +Rosenbrock32 +ROS3P +Rodas3 +Rodas23W +Rodas3P +Rodas4 +Rodas42 +Rodas4P +Rodas4P2 +Rodas5 +Rodas5P +Rodas5Pe +Rodas5Pr +RosenbrockW6S4OS +ROS2 +ROS2PR +ROS2S +ROS3 +ROS3PR +Scholz4_7 +ROS34PW1a +ROS34PW1b +ROS34PW2 +ROS34PW3 +ROS34PRw +ROS3PRL +ROS3PRL2 +ROK4a +RosShamp4 +Veldd4 +Velds4 +GRK4T +GRK4A +Ros4LStab +``` diff --git a/docs/src/semiimplicit/StabalizedRK.md b/docs/src/semiimplicit/StabalizedRK.md new file mode 100644 index 0000000000..43851e49ea --- /dev/null +++ b/docs/src/semiimplicit/StabalizedRK.md @@ -0,0 +1,28 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqStabalizedRK + +Explicit stabilized methods utilize an upper bound on the spectral radius of the Jacobian. +Users can supply an upper bound by specifying the keyword argument `eigen_est`, for example + +```julia +`eigen_est = (integrator) -> integrator.eigen_est = upper_bound` +``` + +```@eval +first_steps = evalfile("./common_first_steps.jl") +first_steps("OrdinaryDiffEqStabalizedRK", "ROCK4") +``` + +## Full list of solvers + +```@docs +ROCK2 +ROCK4 +RKC +SERK2 +ESERK4 +ESERK5 +``` diff --git a/docs/src/semilinear/ExponentialRK.md b/docs/src/semilinear/ExponentialRK.md new file mode 100644 index 0000000000..a2919c81e7 --- /dev/null +++ b/docs/src/semilinear/ExponentialRK.md @@ -0,0 +1,46 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqExponentialRK + +Methods for semi-linear differential equations. + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqLinear`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqExponentialRK") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqExponentialRK, SciMLOperators +A = [2.0 -1.0; -1.0 2.0] +linnonlin_f1 = MatrixOperator(A) +linnonlin_f2 = (du, u, p, t) -> du .= 1.01 .* u +linnonlin_fun_iip = SplitFunction(linnonlin_f1, linnonlin_f2) +tspan = (0.0, 1.0) +u0 = [0.1, 0.1] +prob = SplitODEProblem(linnonlin_fun_iip, u0, tspan) +sol = solve(prob, ETDRK4(), dt = 1 / 4) +``` + +## Full list of solvers + +```@docs +LawsonEuler +NorsettEuler +ETD2 +ETDRK2 +ETDRK3 +ETDRK4 +HochOst4 +``` diff --git a/docs/src/semilinear/Linear.md b/docs/src/semilinear/Linear.md new file mode 100644 index 0000000000..e797ba1d68 --- /dev/null +++ b/docs/src/semilinear/Linear.md @@ -0,0 +1,78 @@ +```@meta +CollapsedDocStrings = true +``` + +# OrdinaryDiffEqLinear + +Methods for semi-linear differential equations. + +## Installation + +To be able to access the solvers in `OrdinaryDiffEqLinear`, you must first install them use the Julia package manager: + +```julia +using Pkg +Pkg.add("OrdinaryDiffEqLinear") +``` + +This will only install the solvers listed at the bottom of this page. +If you want to explore other solvers for your problem, +you will need to install some of the other libraries listed in the navigation bar on the left. + +## Example usage + +```julia +using OrdinaryDiffEqLinear, SciMLOperators +function update_func(A, u, p, t) + A[1, 1] = 0 + A[2, 1] = sin(u[1]) + A[1, 2] = -1 + A[2, 2] = 0 +end +A0 = ones(2, 2) +A = DiffEqArrayOperator(A0, update_func = update_func) +u0 = ones(2) +tspan = (0.0, 30.0) +prob = ODEProblem(A, u0, tspan) +sol = solve(prob, LieRK4(), dt = 1 / 4) +``` + +## Full list of solvers + +### Time and State-Independent Solvers + +```@docs +LinearExponential +``` + +### Time-Dependent and State-Independent Solvers + +```@docs +MagnusMidpoint +MagnusLeapfrog +MagnusGauss4 +MagnusNC6 +MagnusGL6 +MagnusGL8 +MagnusNC8 +MagnusGL4 +``` + +### State-Dependent Solvers + +```@docs +LieEuler +RKMK2 +RKMK4 +LieRK4 +CG2 +CG4a +MagnusAdapt4 +CayleyEuler +``` + +### Time and State-Dependent Operators + +```@docs +CG3 +``` diff --git a/docs/src/semilinear/exponential_rk.md b/docs/src/semilinear/exponential_rk.md deleted file mode 100644 index 320ad68ad6..0000000000 --- a/docs/src/semilinear/exponential_rk.md +++ /dev/null @@ -1,18 +0,0 @@ -# Exponential Runge-Kutta Integrators - -```@docs -LawsonEuler -NorsettEuler -ETD2 -ETDRK2 -ETDRK3 -ETDRK4 -HochOst4 -Exp4 -EPIRK4s3A -EPIRK4s3B -EPIRK5s3 -EXPRB53s3 -EPIRK5P1 -EPIRK5P2 -``` diff --git a/docs/src/semilinear/magnus.md b/docs/src/semilinear/magnus.md deleted file mode 100644 index fa7aee8f64..0000000000 --- a/docs/src/semilinear/magnus.md +++ /dev/null @@ -1,21 +0,0 @@ -# Magnus and Lie Group Integrators - -```@docs -MagnusMidpoint -MagnusLeapfrog -LieEuler -MagnusGauss4 -MagnusNC6 -MagnusGL6 -MagnusGL8 -MagnusNC8 -MagnusGL4 -RKMK2 -RKMK4 -LieRK4 -CG2 -CG3 -CG4a -MagnusAdapt4 -CayleyEuler -``` diff --git a/docs/src/stiff/firk.md b/docs/src/stiff/firk.md deleted file mode 100644 index 774562b1de..0000000000 --- a/docs/src/stiff/firk.md +++ /dev/null @@ -1,6 +0,0 @@ -# Fully Implicit Runge-Kutta (FIRK) Methods - -```@docs -RadauIIA3 -RadauIIA5 -``` diff --git a/docs/src/stiff/implicit_extrapolation.md b/docs/src/stiff/implicit_extrapolation.md deleted file mode 100644 index 95677e885f..0000000000 --- a/docs/src/stiff/implicit_extrapolation.md +++ /dev/null @@ -1,8 +0,0 @@ -# Implicit Extrapolation Methods - -```@docs -ImplicitEulerExtrapolation -ImplicitDeuflhardExtrapolation -ImplicitHairerWannerExtrapolation -ImplicitEulerBarycentricExtrapolation -``` diff --git a/docs/src/stiff/rosenbrock.md b/docs/src/stiff/rosenbrock.md deleted file mode 100644 index e44443d7f6..0000000000 --- a/docs/src/stiff/rosenbrock.md +++ /dev/null @@ -1,44 +0,0 @@ -# Rosenbrock Methods - -## Standard Rosenbrock Methods - -```@docs -ROS2 -ROS3 -ROS2PR -ROS3PR -Scholz4_7 -ROS3PRL -ROS3PRL2 -ROS3P -Rodas3 -Rodas3P -RosShamp4 -Veldd4 -Velds4 -GRK4T -GRK4A -Ros4LStab -Rodas4 -Rodas42 -Rodas4P -Rodas4P2 -Rodas5 -Rodas5P -``` - -## Rosenbrock W-Methods - -```@docs -Rosenbrock23 -Rosenbrock32 -Rodas23W -ROS34PW1a -ROS34PW1b -ROS34PW2 -ROS34PW3 -ROS34PRw -ROK4a -ROS2S -RosenbrockW6S4OS -``` diff --git a/docs/src/stiff/sdirk.md b/docs/src/stiff/sdirk.md deleted file mode 100644 index 5236046ad0..0000000000 --- a/docs/src/stiff/sdirk.md +++ /dev/null @@ -1,23 +0,0 @@ -# Singly-Diagonally Implicit Runge-Kutta (SDIRK) Methods - -```@docs -ImplicitEuler -ImplicitMidpoint -Trapezoid -TRBDF2 -SDIRK2 -SDIRK22 -SSPSDIRK2 -Kvaerno3 -CFNLIRK3 -Cash4 -SFSDIRK4 -SFSDIRK5 -SFSDIRK6 -SFSDIRK7 -SFSDIRK8 -Hairer4 -Hairer42 -Kvaerno4 -Kvaerno5 -``` diff --git a/docs/src/stiff/stabilized_rk.md b/docs/src/stiff/stabilized_rk.md deleted file mode 100644 index 927aa3f94f..0000000000 --- a/docs/src/stiff/stabilized_rk.md +++ /dev/null @@ -1,28 +0,0 @@ -# Stabilized Runge-Kutta Methods (Runge-Kutta-Chebyshev) - -## Explicit Stabilized Runge-Kutta Methods - -Explicit stabilized methods utilize an upper bound on the spectral radius of the Jacobian. -Users can supply an upper bound by specifying the keyword argument `eigen_est`, for example - -```julia -`eigen_est = (integrator) -> integrator.eigen_est = upper_bound` -``` - -The methods `ROCK2` and `ROCK4` also include keyword arguments `min_stages` and `max_stages`, -which specify upper and lower bounds on the adaptively chosen number of stages for stability. - -```@docs -ROCK2 -ROCK4 -SERK2 -ESERK4 -ESERK5 -RKC -``` - -## Implicit Stabilized Runge-Kutta Methods - -```@docs -IRKC -``` diff --git a/docs/src/stiff/stiff_multistep.md b/docs/src/stiff/stiff_multistep.md deleted file mode 100644 index b84e2e88c0..0000000000 --- a/docs/src/stiff/stiff_multistep.md +++ /dev/null @@ -1,13 +0,0 @@ -# Multistep Methods for Stiff Equations - -```@docs -QNDF1 -QBDF1 -QNDF2 -QBDF2 -ABDF2 -QNDF -QBDF -FBDF -MEBDF2 -``` diff --git a/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/OrdinaryDiffEqAdamsBashforthMoulton.jl b/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/OrdinaryDiffEqAdamsBashforthMoulton.jl index 2b86ce4923..070524d8a3 100644 --- a/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/OrdinaryDiffEqAdamsBashforthMoulton.jl +++ b/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/OrdinaryDiffEqAdamsBashforthMoulton.jl @@ -8,6 +8,7 @@ import OrdinaryDiffEqCore: OrdinaryDiffEqMutableCache, OrdinaryDiffEqConstantCac OrdinaryDiffEqAdamsVarOrderVarStepAlgorithm, constvalue, calculate_residuals, calculate_residuals!, trivial_limiter!, get_fsalfirstlast, + generic_solver_docstring, full_cache import OrdinaryDiffEqLowOrderRK: BS3ConstantCache, BS3Cache, RK4ConstantCache, RK4Cache import RecursiveArrayTools: recursivefill! diff --git a/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/algorithms.jl b/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/algorithms.jl index b2125d68d9..af35c61140 100644 --- a/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/algorithms.jl +++ b/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/algorithms.jl @@ -1,139 +1,127 @@ # Adams Bashforth and Adams moulton methods - -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -AB3: Adams-Bashforth Explicit Method -The 3-step third order multistep method. Ralston's Second Order Method is used to calculate starting values. -""" +reference = """E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff + Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: + https://doi.org/10.1007/978-3-540-78862-1""" + +@doc generic_solver_docstring("The 3-step third order multistep method. + Ralston's Second Order Method is used to calculate starting values.", + "AB3", + "Adams-Bashforth Explicit Method", + reference, + "", + "") struct AB3 <: OrdinaryDiffEqAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -AB4: Adams-Bashforth Explicit Method -The 4-step fourth order multistep method. Runge-Kutta method of order 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("The 4-step fourth order multistep method. + Runge-Kutta method of order 4 is used to calculate starting values.", + "AB4", + "Adams-Bashforth Explicit Method", + reference, + "", + "") struct AB4 <: OrdinaryDiffEqAlgorithm end - -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -AB5: Adams-Bashforth Explicit Method -The 3-step third order multistep method. Ralston's Second Order Method is used to calculate starting values. -""" +@doc generic_solver_docstring("The 5-step fifth order multistep method. + Ralston's 3rd order Runge-Kutta method is used to calculate starting values.", + "AB5", + "Adams-Bashforth Explicit Method", + reference, + "", + "") struct AB5 <: OrdinaryDiffEqAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -ABM32: Adams-Bashforth Explicit Method -It is third order method. In ABM32, AB3 works as predictor and Adams Moulton 2-steps method works as Corrector. -Ralston's Second Order Method is used to calculate starting values. -""" +@doc generic_solver_docstring("It is third order method. + In ABM32, AB3 works as predictor and Adams Moulton 2-steps method works as Corrector. + Ralston's Second Order Method is used to calculate starting values.", + "ABM32", + "Adams-Bashforth Explicit Method", + reference, + "", + "") struct ABM32 <: OrdinaryDiffEqAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -ABM43: Adams-Bashforth Explicit Method -It is fourth order method. In ABM43, AB4 works as predictor and Adams Moulton 3-steps method works as Corrector. -Runge-Kutta method of order 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("It is fourth order method. + In ABM43, AB4 works as predictor and Adams Moulton 3-steps method works as Corrector. + Runge-Kutta method of order 4 is used to calculate starting values.", + "ABM43", + "Adams-Bashforth Explicit Method", + reference, + "", + "") struct ABM43 <: OrdinaryDiffEqAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -ABM54: Adams-Bashforth Explicit Method -It is fifth order method. In ABM54, AB5 works as predictor and Adams Moulton 4-steps method works as Corrector. -Runge-Kutta method of order 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("It is fifth order method. + In ABM54, AB5 works as predictor and Adams Moulton 4-steps method works as Corrector. + Runge-Kutta method of order 4 is used to calculate starting values.", + "ABM54", + "Adams-Bashforth Explicit Method", + reference, + "", + "") struct ABM54 <: OrdinaryDiffEqAlgorithm end # Variable Step Size Adams methods -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCAB3: Adaptive step size Adams explicit Method -The 3rd order Adams method. Bogacki-Shampine 3/2 method is used to calculate starting values. -""" +@doc generic_solver_docstring("The 3rd order Adams method. + Bogacki-Shampine 3/2 method is used to calculate starting values.", + "VCAB3", + "Adams explicit Method", + reference, + "", + "") struct VCAB3 <: OrdinaryDiffEqAdaptiveAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCAB4: Adaptive step size Adams explicit Method -The 4th order Adams method. Runge-Kutta 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("The 4th order Adams method. + Runge-Kutta 4 is used to calculate starting values.", + "VCAB4", + "Adams explicit Method", + reference, + "", + "") struct VCAB4 <: OrdinaryDiffEqAdaptiveAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCAB5: Adaptive step size Adams explicit Method -The 5th order Adams method. Runge-Kutta 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("The 5th order Adams method. + Runge-Kutta 4 is used to calculate starting values.", + "VCAB5", + "Adams explicit Method", + reference, + "", + "") struct VCAB5 <: OrdinaryDiffEqAdaptiveAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCABM3: Adaptive step size Adams explicit Method -The 3rd order Adams-Moulton method. Bogacki-Shampine 3/2 method is used to calculate starting values. -""" +@doc generic_solver_docstring("The 3rd order Adams-Moulton method. + Bogacki-Shampine 3/2 method is used to calculate starting values.", + "VCABM3", + "Adams explicit Method", + reference, + "", + "") struct VCABM3 <: OrdinaryDiffEqAdaptiveAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCABM4: Adaptive step size Adams explicit Method -The 4th order Adams-Moulton method. Runge-Kutta 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("The 4th order Adams-Moulton method. + Runge-Kutta 4 is used to calculate starting values.", + "VCABM4", + "Adams explicit Method", + reference, + "", + "") struct VCABM4 <: OrdinaryDiffEqAdaptiveAlgorithm end -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCABM5: Adaptive step size Adams explicit Method -The 5th order Adams-Moulton method. Runge-Kutta 4 is used to calculate starting values. -""" +@doc generic_solver_docstring("The 5th order Adams-Moulton method. + Runge-Kutta 4 is used to calculate starting values.", + "VCABM5", + "Adams explicit Method", + reference, + "", + "") struct VCABM5 <: OrdinaryDiffEqAdaptiveAlgorithm end # Variable Order and Variable Step Size Adams methods -""" -E. Hairer, S. P. Norsett, G. Wanner, Solving Ordinary Differential Equations I, Nonstiff -Problems. Computational Mathematics (2nd revised ed.), Springer (1996) doi: -https://doi.org/10.1007/978-3-540-78862-1 - -VCABM: Adaptive step size Adams explicit Method -An adaptive order adaptive time Adams Moulton method. -It uses an order adaptivity algorithm is derived from Shampine's DDEABM. -""" +@doc generic_solver_docstring("An adaptive order adaptive time Adams Moulton method. + It uses an order adaptivity algorithm is derived from Shampine's DDEABM.", + "VCABM", + "adaptive order Adams explicit Method", + reference, + "", + "") struct VCABM <: OrdinaryDiffEqAdamsVarOrderVarStepAlgorithm end diff --git a/lib/OrdinaryDiffEqBDF/Project.toml b/lib/OrdinaryDiffEqBDF/Project.toml index 677446afb1..1617a434c4 100644 --- a/lib/OrdinaryDiffEqBDF/Project.toml +++ b/lib/OrdinaryDiffEqBDF/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqBDF" uuid = "6ad6398a-0878-4a85-9266-38940aa047c8" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.1.1" [deps] ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" diff --git a/lib/OrdinaryDiffEqBDF/src/OrdinaryDiffEqBDF.jl b/lib/OrdinaryDiffEqBDF/src/OrdinaryDiffEqBDF.jl index 28d3ab39c3..5a2981219b 100644 --- a/lib/OrdinaryDiffEqBDF/src/OrdinaryDiffEqBDF.jl +++ b/lib/OrdinaryDiffEqBDF/src/OrdinaryDiffEqBDF.jl @@ -20,7 +20,7 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, step_accept_controller!, step_reject_controller!, post_newton_controller!, u_modified!, DAEAlgorithm, _unwrap_val, DummyController, - get_fsalfirstlast + get_fsalfirstlast, generic_solver_docstring using OrdinaryDiffEqSDIRK: ImplicitEulerConstantCache, ImplicitEulerCache using TruncatedStacktraces, MuladdMacro, MacroTools, FastBroadcast, RecursiveArrayTools @@ -93,7 +93,7 @@ PrecompileTools.@compile_workload begin end export ABDF2, QNDF1, QBDF1, QNDF2, QBDF2, QNDF, QBDF, FBDF, - SBDF2, SBDF3, SBDF4, MEBDF2, IMEXEuler, IMEXEulerARK, + SBDF, SBDF2, SBDF3, SBDF4, MEBDF2, IMEXEuler, IMEXEulerARK, DABDF2, DImplicitEuler, DFBDF end diff --git a/lib/OrdinaryDiffEqBDF/src/algorithms.jl b/lib/OrdinaryDiffEqBDF/src/algorithms.jl index 4f25e268a7..494bbcfa8a 100644 --- a/lib/OrdinaryDiffEqBDF/src/algorithms.jl +++ b/lib/OrdinaryDiffEqBDF/src/algorithms.jl @@ -1,11 +1,106 @@ -""" -E. Alberdi Celayaa, J. J. Anza Aguirrezabalab, P. Chatzipantelidisc. Implementation of -an Adaptive BDF2 Formula and Comparison with The MATLAB Ode15s. Procedia Computer Science, -29, pp 1014-1026, 2014. doi: https://doi.org/10.1016/j.procs.2014.05.091 +function BDF_docstring(description::String, + name::String; + references::String = "", + extra_keyword_description::String = "", + extra_keyword_default::String = "") + keyword_default = """ + chunk_size = Val{0}(), + autodiff = true, + standardtag = Val{true}(), + concrete_jac = nothing, + diff_type = Val{:forward}, + linsolve = nothing, + precs = DEFAULT_PRECS, + """ * "\n" * extra_keyword_default + + keyword_default_description = """ + - `chunk_size`: The chunk size used with ForwardDiff.jl. Defaults to `Val{0}()` + and thus uses the internal ForwardDiff.jl algorithm for the choice. + - `autodiff`: Specifies whether to use automatic differentiation via + [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite + differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl). + Defaults to `Val{true}()` for automatic differentiation. + - `standardtag`: Specifies whether to use package-specific tags instead of the + ForwardDiff default function-specific tags. For more information, see + [this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/). + Defaults to `Val{true}()`. + - `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to + `nothing`, which means it will be chosen true/false depending on circumstances + of the solver, such as whether a Krylov subspace method is used for `linsolve`. + - `diff_type`: The type of differentiation used in FiniteDiff.jl if `autodiff=false`. + Defaults to `Val{:forward}`, with alternatives of `Val{:central}` and + `Val{:complex}`. + - `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver. + For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify + `$name(linsolve = KLUFactorization()`). + When `nothing` is passed, uses `DefaultLinearSolver`. + - `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/) + can be used as a left or right preconditioner. + Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)` + function where the arguments are defined as: + - `W`: the current Jacobian of the nonlinear system. Specified as either + ``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will + commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy + representation of the operator. Users can construct the W-matrix on demand + by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching + the `jac_prototype`. + - `du`: the current ODE derivative + - `u`: the current ODE state + - `p`: the ODE parameters + - `t`: the current ODE time + - `newW`: a `Bool` which specifies whether the `W` matrix has been updated since + the last call to `precs`. It is recommended that this is checked to only + update the preconditioner when `newW == true`. + - `Plprev`: the previous `Pl`. + - `Prprev`: the previous `Pr`. + - `solverdata`: Optional extra data the solvers can give to the `precs` function. + Solver-dependent and subject to change. + The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners. + To specify one-sided preconditioning, simply return `nothing` for the preconditioner + which is not used. Additionally, `precs` must supply the dispatch: + ```julia + Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata) + ``` + which is used in the solver setup phase to construct the integrator + type with the preconditioners `(Pl,Pr)`. + The default is `precs=DEFAULT_PRECS` where the default preconditioner function + is defined as: + ```julia + DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing + ``` + """ * "/n" * extra_keyword_description + generic_solver_docstring( + description, name, "Multistep Method.", references, + keyword_default_description, keyword_default + ) +end -ABDF2: Multistep Method -An adaptive order 2 L-stable fixed leading coefficient multistep BDF method. -""" +@doc BDF_docstring( + "An adaptive order 2 L-stable fixed leading coefficient multistep BDF method.", + "ABDF2", + references = """ + E. Alberdi Celayaa, J. J. Anza Aguirrezabalab, P. Chatzipantelidisc. Implementation of + an Adaptive BDF2 Formula and Comparison with The MATLAB Ode15s. Procedia Computer Science, + 29, pp 1014-1026, 2014. doi: https://doi.org/10.1016/j.procs.2014.05.091 + """, + extra_keyword_description = """ + - `κ`: TBD + - `tol`: TBD + - `nlsolve`: TBD + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + κ = nothing, + tol = nothing, + nlsolve = NLNewton(), + smooth_est = true, + extrapolant = :linear, + controller = :Standard, + step_limiter! = trivial_limiter!, + """) struct ABDF2{CS, AD, F, F2, P, FDT, ST, CJ, K, T, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -31,11 +126,37 @@ function ABDF2(; chunk_size = Val{0}(), autodiff = true, standardtag = Val{true} smooth_est, extrapolant, controller, step_limiter!) end -""" -Uri M. Ascher, Steven J. Ruuth, Brian T. R. Wetton. Implicit-Explicit Methods for Time- -Dependent Partial Differential Equations. 1995 Society for Industrial and Applied Mathematics -Journal on Numerical Analysis, 32(3), pp 797-823, 1995. doi: https://doi.org/10.1137/0732037 -""" +@doc BDF_docstring( + "Implicit-explicit (IMEX) method designed for SplitODEFunction equations, +which reduce the size of the implicit handling to a subset of the equations. +It's similar to the additive Runge-Kutta methods in splitting mode, +like `KenCarp4`, but instead using a multistep BDF approach", + "SBDF", + references = """@article{ascher1995implicit, + title={Implicit-explicit methods for time-dependent partial differential equations}, + author={Ascher, Uri M and Ruuth, Steven J and Wetton, Brian TR}, + journal={SIAM Journal on Numerical Analysis}, + volume={32}, + number={3}, + pages={797--823}, + year={1995}, + publisher={SIAM}} + """, + extra_keyword_description = """ + - `κ`: TBD + - `tol`: TBD + - `nlsolve`: TBD + - `extrapolant`: TBD + - `ark`: TBD + """, + extra_keyword_default = """ + κ = nothing, + tol = nothing, + nlsolve = NLNewton(), + extrapolant = :linear, + ark = false, + order, + """) struct SBDF{CS, AD, F, F2, P, FDT, ST, CJ, K, T} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -129,13 +250,34 @@ See also `SBDF`. """ SBDF4(; kwargs...) = SBDF(4; kwargs...) -""" -QNDF1: Multistep Method -An adaptive order 1 quasi-constant timestep L-stable numerical differentiation function (NDF) method. -Optional parameter kappa defaults to Shampine's accuracy-optimal -0.1850. - -See also `QNDF`. -""" +@doc BDF_docstring( + "An adaptive order 1 quasi-constant timestep L-stable numerical differentiation function (NDF) method. +Optional parameter kappa defaults to Shampine's accuracy-optimal -0.1850.", + "QNDF1", + references = """@article{shampine1997matlab, + title={The matlab ode suite}, + author={Shampine, Lawrence F and Reichelt, Mark W}, + journal={SIAM journal on scientific computing}, + volume={18}, + number={1}, + pages={1--22}, + year={1997}, + publisher={SIAM} + }""", + extra_keyword_description = """ + - `nlsolve`: TBD + - `extrapolant`: TBD + - `kappa`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + nlsolve = NLNewton(), + extrapolant = :linear, + kappa = -0.1850, + controller = :Standard, + step_limiter! = trivial_limiter!, + """) struct QNDF1{CS, AD, F, F2, P, FDT, ST, CJ, κType, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -164,12 +306,33 @@ function QNDF1(; chunk_size = Val{0}(), autodiff = Val{true}(), standardtag = Va step_limiter!) end -""" -QNDF2: Multistep Method -An adaptive order 2 quasi-constant timestep L-stable numerical differentiation function (NDF) method. - -See also `QNDF`. -""" +@doc BDF_docstring( + "An adaptive order 2 quasi-constant timestep L-stable numerical differentiation function (NDF) method.", + "QNDF2", + references = """@article{shampine1997matlab, + title={The matlab ode suite}, + author={Shampine, Lawrence F and Reichelt, Mark W}, + journal={SIAM journal on scientific computing}, + volume={18}, + number={1}, + pages={1--22}, + year={1997}, + publisher={SIAM} + }""", + extra_keyword_description = """ + - `nlsolve`: TBD + - `extrapolant`: TBD + - `kappa`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + nlsolve = NLNewton(), + extrapolant = :linear, + kappa = -1 // 9, + controller = :Standard, + step_limiter! = trivial_limiter!, + """) struct QNDF2{CS, AD, F, F2, P, FDT, ST, CJ, κType, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -198,22 +361,38 @@ function QNDF2(; chunk_size = Val{0}(), autodiff = Val{true}(), standardtag = Va step_limiter!) end -""" -QNDF: Multistep Method -An adaptive order quasi-constant timestep NDF method. -Utilizes Shampine's accuracy-optimal kappa values as defaults (has a keyword argument for a tuple of kappa coefficients). - -@article{shampine1997matlab, -title={The matlab ode suite}, -author={Shampine, Lawrence F and Reichelt, Mark W}, -journal={SIAM journal on scientific computing}, -volume={18}, -number={1}, -pages={1--22}, -year={1997}, -publisher={SIAM} -} -""" +@doc BDF_docstring( + "An adaptive order quasi-constant timestep NDF method. +Utilizes Shampine's accuracy-optimal kappa values as defaults (has a keyword argument for a tuple of kappa coefficients).", + "QNDF", + references = """@article{shampine1997matlab, + title={The matlab ode suite}, + author={Shampine, Lawrence F and Reichelt, Mark W}, + journal={SIAM journal on scientific computing}, + volume={18}, + number={1}, + pages={1--22}, + year={1997}, + publisher={SIAM} + }""", + extra_keyword_description = """ + - `κ`: TBD + - `tol`: TBD + - `nlsolve`: TBD + - `extrapolant`: TBD + - `kappa`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + κ = nothing, + tol = nothing, + nlsolve = NLNewton(), + extrapolant = :linear, + kappa = promote(-0.1850, -1 // 9, -0.0823, -0.0415, 0), + controller = :Standard, + step_limiter! = trivial_limiter!, + """) struct QNDF{MO, CS, AD, F, F2, P, FDT, ST, CJ, K, T, κType, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} max_order::Val{MO} @@ -246,11 +425,27 @@ end TruncatedStacktraces.@truncate_stacktrace QNDF -""" -MEBDF2: Multistep Method -The second order Modified Extended BDF method, which has improved stability properties over the standard BDF. -Fixed timestep only. -""" +@doc BDF_docstring("The second order Modified Extended BDF method, + which has improved stability properties over the standard BDF. + Fixed timestep only.", + "MEBDF2", + references = """@article{cash2000modified, + title={Modified extended backward differentiation formulae for the numerical solution of stiff initial value problems in ODEs and DAEs}, + author={Cash, JR}, + journal={Journal of Computational and Applied Mathematics}, + volume={125}, + number={1-2}, + pages={117--130}, + year={2000}, + publisher={Elsevier}}""", + extra_keyword_description = """ + - `nlsolve`: TBD + - `extrapolant`: TBD + """, + extra_keyword_default = """ + nlsolve = NLNewton(), + extrapolant = :constant, + """) struct MEBDF2{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -270,19 +465,34 @@ function MEBDF2(; chunk_size = Val{0}(), autodiff = true, standardtag = Val{true extrapolant) end -""" -FBDF: Fixed leading coefficient BDF - -An adaptive order quasi-constant timestep NDF method. -Utilizes Shampine's accuracy-optimal kappa values as defaults (has a keyword argument for a tuple of kappa coefficients). - -@article{shampine2002solving, -title={Solving 0= F (t, y (t), y′(t)) in Matlab}, -author={Shampine, Lawrence F}, -year={2002}, -publisher={Walter de Gruyter GmbH \\& Co. KG} -} -""" +@doc BDF_docstring( + "An adaptive order quasi-constant timestep NDF method. +Fixed leading coefficient BDF. +Utilizes Shampine's accuracy-optimal kappa values as defaults (has a keyword argument for a tuple of kappa coefficients).", + "FBDF", + references = """@article{shampine2002solving, + title={Solving 0= F (t, y (t), y′(t)) in Matlab}, + author={Shampine, Lawrence F}, + year={2002}, + publisher={Walter de Gruyter GmbH \\& Co. KG}}""", + extra_keyword_description = """ + - `κ`: TBD + - `tol`: TBD + - `nlsolve`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + - `max_order`: TBD + """, + extra_keyword_default = """ + κ = nothing, + tol = nothing, + nlsolve = NLNewton(), + extrapolant = :linear, + controller = :Standard, + step_limiter! = trivial_limiter!, + max_order::Val{MO} = Val{5}(), + """) struct FBDF{MO, CS, AD, F, F2, P, FDT, ST, CJ, K, T, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} max_order::Val{MO} @@ -390,6 +600,20 @@ See also `SBDF`, `IMEXEuler`. """ IMEXEulerARK(; kwargs...) = SBDF(1; ark = true, kwargs...) +@doc BDF_docstring( + "Implicit Euler for implicit DAE form. +It uses an apriori error estimator for adaptivity based on a finite differencing approximation from SPICE.", + "DImplicitEuler", + extra_keyword_description = """ + - `nlsolve`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + nlsolve = NLNewton(), + extrapolant = :constant, + controller = :Standard, + """) struct DImplicitEuler{CS, AD, F, F2, P, FDT, ST, CJ} <: DAEAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F nlsolve::F2 @@ -409,6 +633,26 @@ function DImplicitEuler(; nlsolve, precs, extrapolant, controller) end +@doc BDF_docstring("Fully implicit implementation of BDF2.", + "DABDF2", + references = """@article{celaya2014implementation, + title={Implementation of an Adaptive BDF2 Formula and Comparison with the MATLAB Ode15s}, + author={Celaya, E Alberdi and Aguirrezabala, JJ Anza and Chatzipantelidis, Panagiotis}, + journal={Procedia Computer Science}, + volume={29}, + pages={1014--1026}, + year={2014}, + publisher={Elsevier}}""", + extra_keyword_description = """ + - `nlsolve`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + nlsolve = NLNewton(), + extrapolant = :constant, + controller = :Standard, + """) struct DABDF2{CS, AD, F, F2, P, FDT, ST, CJ} <: DAEAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F nlsolve::F2 @@ -441,6 +685,30 @@ DBDF(;chunk_size=Val{0}(),autodiff=Val{true}(), standardtag = Val{true}(), concr linsolve,nlsolve,precs,extrapolant) =# +@doc BDF_docstring("Fully implicit implementation of FBDF based on Shampine's", + "DFBDF", + references = """@article{shampine2002solving, + title={Solving 0= F (t, y (t), y′(t)) in Matlab}, + author={Shampine, Lawrence F}, + year={2002}, + publisher={Walter de Gruyter GmbH and Co. KG} + }""", + extra_keyword_description = """ + - `κ`: TBD + - `tol`: TBD + - `nlsolve`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `max_order`: TBD + """, + extra_keyword_default = """ + κ = nothing, + tol = nothing, + nlsolve = NLNewton(), + extrapolant = :linear, + controller = :Standard, + max_order::Val{MO} = Val{5}(), + """) struct DFBDF{MO, CS, AD, F, F2, P, FDT, ST, CJ, K, T} <: DAEAlgorithm{CS, AD, FDT, ST, CJ} max_order::Val{MO} linsolve::F diff --git a/lib/OrdinaryDiffEqBDF/src/bdf_perform_step.jl b/lib/OrdinaryDiffEqBDF/src/bdf_perform_step.jl index c410bf6a36..4f527bac7a 100644 --- a/lib/OrdinaryDiffEqBDF/src/bdf_perform_step.jl +++ b/lib/OrdinaryDiffEqBDF/src/bdf_perform_step.jl @@ -758,16 +758,17 @@ function perform_step!(integrator, cache::QNDFConstantCache{max_order}, α₀ = 1 β₀ = inv((1 - κ) * γₖ[k]) if u isa Number - u₀ = sum(D[1:k]) + uprev + u₀ = sum(view(D, 1:k)) + uprev ϕ = zero(u) for i in 1:k ϕ += γₖ[i] * D[i] end else - u₀ = reshape(sum(D[:, 1:k], dims = 2) .+ uprev, size(u)) + u₀ = _reshape(sum(view(D, :, 1:k), dims = 2), axes(u)) .+ uprev ϕ = zero(u) for i in 1:k - ϕ = @.. ϕ + γₖ[i] * D[:, i] + D_row = _reshape(view(D, :, i), axes(u)) + ϕ = @.. ϕ + γₖ[i] * D_row end end markfirststage!(nlsolver) @@ -802,14 +803,14 @@ function perform_step!(integrator, cache::QNDFConstantCache{max_order}, end integrator.EEst = error_constant(integrator, k) * internalnorm(atmp, t) if k > 1 - @views atmpm1 = calculate_residuals(D[:, k], uprev, u, integrator.opts.abstol, - integrator.opts.reltol, - integrator.opts.internalnorm, t) + @views atmpm1 = calculate_residuals(_reshape(view(D, :, k), axes(u)), + uprev, u, integrator.opts.abstol, + integrator.opts.reltol, integrator.opts.internalnorm, t) cache.EEst1 = error_constant(integrator, k - 1) * internalnorm(atmpm1, t) end if k < max_order - @views atmpp1 = calculate_residuals(D[:, k + 2], uprev, u, abstol, reltol, - internalnorm, t) + @views atmpp1 = calculate_residuals(_reshape(view(D, :, k + 2), axes(u)), + uprev, u, abstol, reltol, internalnorm, t) cache.EEst2 = error_constant(integrator, k + 1) * internalnorm(atmpp1, t) end end @@ -925,13 +926,13 @@ function perform_step!(integrator, cache::QNDFCache{max_order}, integrator.EEst = error_constant(integrator, k) * internalnorm(atmp, t) if k > 1 @views calculate_residuals!( - atmpm1, reshape(D[:, k], size(u)), uprev, u, abstol, + atmpm1, _reshape(D[:, k], axes(u)), uprev, u, abstol, reltol, internalnorm, t) cache.EEst1 = error_constant(integrator, k - 1) * internalnorm(atmpm1, t) end if k < max_order @views calculate_residuals!( - atmpp1, reshape(D[:, k + 2], size(u)), uprev, u, abstol, + atmpp1, _reshape(D[:, k + 2], axes(u)), uprev, u, abstol, reltol, internalnorm, t) cache.EEst2 = error_constant(integrator, k + 1) * internalnorm(atmpp1, t) end @@ -1112,7 +1113,7 @@ function perform_step!(integrator, cache::FBDFConstantCache{max_order}, end tmp = -uprev * bdf_coeffs[k, 2] for i in 1:(k - 1) - @views tmp = @.. tmp - u_corrector[:, i] * bdf_coeffs[k, i + 2] + tmp = @.. tmp - $(_reshape(view(u_corrector, :, i), axes(u))) * bdf_coeffs[k, i + 2] end end @@ -1169,7 +1170,7 @@ function perform_step!(integrator, cache::FBDFConstantCache{max_order}, terk *= abs(dt^(k)) else for i in 2:(k + 1) - @views terk = @.. terk + fd_weights[i, k + 1] * u_history[:, i - 1] + terk = @.. terk + fd_weights[i, k + 1] * $(_reshape(view(u_history, :, i - 1), axes(u))) end terk *= abs(dt^(k)) end diff --git a/lib/OrdinaryDiffEqBDF/src/controllers.jl b/lib/OrdinaryDiffEqBDF/src/controllers.jl index fc13dbd91a..e992aaeb1d 100644 --- a/lib/OrdinaryDiffEqBDF/src/controllers.jl +++ b/lib/OrdinaryDiffEqBDF/src/controllers.jl @@ -217,7 +217,7 @@ function choose_order!(alg::FBDF, integrator, terk_tmp = similar(u) @.. terk_tmp = fd_weights[k - 2, 1] * _vec(u) for i in 2:(k - 2) - @.. @views terk_tmp += fd_weights[i, k - 2] * u_history[:, i - 1] + @.. terk_tmp += fd_weights[i, k - 2] * $(_reshape(view(u_history, :, i - 1), axes(u))) end @.. terk_tmp *= abs(dt^(k - 2)) end diff --git a/lib/OrdinaryDiffEqBDF/src/dae_caches.jl b/lib/OrdinaryDiffEqBDF/src/dae_caches.jl index 708a3d119f..aa03fc0f25 100644 --- a/lib/OrdinaryDiffEqBDF/src/dae_caches.jl +++ b/lib/OrdinaryDiffEqBDF/src/dae_caches.jl @@ -15,7 +15,7 @@ end end # Not FSAL -get_fsalfirstlast(cache::DImplicitEulerCache, u) = (u, u) +get_fsalfirstlast(cache::DImplicitEulerCache, u) = (nothing, nothing) mutable struct DImplicitEulerConstantCache{N} <: OrdinaryDiffEqConstantCache nlsolver::N diff --git a/lib/OrdinaryDiffEqBDF/test/dae_convergence_tests.jl b/lib/OrdinaryDiffEqBDF/test/dae_convergence_tests.jl index d04143b2c0..bd0d5891c4 100644 --- a/lib/OrdinaryDiffEqBDF/test/dae_convergence_tests.jl +++ b/lib/OrdinaryDiffEqBDF/test/dae_convergence_tests.jl @@ -6,13 +6,41 @@ dts = 1 .// 2 .^ (9:-1:5) testTol = 0.2 f_dae_linear = (res, du, u, p, t) -> (@. res = du - u) +function f_dae_linear_jac(J, du, u, p, gamma, t) + J[1, 1] = gamma - 1.0 + J[2, 2] = gamma - 1.0 +end f_dae_linear_analytic = (du0, u0, p, t) -> @. u0 * exp(t) prob_dae_linear_iip = DAEProblem( DAEFunction(f_dae_linear; analytic = f_dae_linear_analytic), [1.0, 1.0], [1.0, 1.0], (0.0, 1.0)) -@testset "DAE Solver Convergence Tests (in-place)" begin +@testset "DAE Solver Convergence Tests (in-place, ad jac)" begin + prob = prob_dae_linear_iip + + sim11 = test_convergence(dts, prob, DImplicitEuler()) + @test sim11.𝒪est[:final]≈1 atol=testTol + + sim12 = test_convergence(dts, prob, DImplicitEuler(; autodiff = false)) + @test sim12.𝒪est[:final]≈1 atol=testTol + + sim13 = test_convergence(dts, prob, DABDF2()) + @test sim13.𝒪est[:final]≈2 atol=testTol + + sim14 = test_convergence(dts, prob, DABDF2(; autodiff = false)) + @test sim14.𝒪est[:final]≈2 atol=testTol + + @test_nowarn solve(prob, DFBDF()) +end + +prob_dae_linear_iip_jac = DAEProblem( + DAEFunction(f_dae_linear; + jac = f_dae_linear_jac, + analytic = f_dae_linear_analytic), + [1.0, 1.0], [1.0, 1.0], (0.0, 1.0)) + +@testset "DAE Solver Convergence Tests (in-place, custom jac)" begin prob = prob_dae_linear_iip sim11 = test_convergence(dts, prob, DImplicitEuler()) @@ -31,13 +59,42 @@ prob_dae_linear_iip = DAEProblem( end f_dae_linear = (du, u, p, t) -> (@. du - u) +function f_dae_linear_jac(du, u, p, gamma, t) + J = zeros(2, 2) + J[1, 1] = gamma - 1.0 + J[2, 2] = gamma - 1.0 +end f_dae_linear_analytic = (du0, u0, p, t) -> @. u0 * exp(t) prob_dae_linear_oop = DAEProblem( DAEFunction(f_dae_linear; analytic = f_dae_linear_analytic), 1.0, 1.0, (0.0, 1.0)) -@testset "DAE Solver Convergence Tests (out-of-place)" begin +@testset "DAE Solver Convergence Tests (out-of-place, ad jac)" begin + prob = prob_dae_linear_oop + + sim21 = test_convergence(dts, prob, DImplicitEuler()) + @test sim21.𝒪est[:final]≈1 atol=testTol + + sim22 = test_convergence(dts, prob, DImplicitEuler(; autodiff = false)) + @test sim22.𝒪est[:final]≈1 atol=testTol + + sim23 = test_convergence(dts, prob, DABDF2()) + @test sim23.𝒪est[:final]≈2 atol=testTol + + sim24 = test_convergence(dts, prob, DABDF2(; autodiff = false)) + @test sim24.𝒪est[:final]≈2 atol=testTol + + @test_nowarn solve(prob, DFBDF()) +end + +prob_dae_linear_oop = DAEProblem( + DAEFunction(f_dae_linear; + jac = f_dae_linear_jac, + analytic = f_dae_linear_analytic), + 1.0, 1.0, (0.0, 1.0)) + +@testset "DAE Solver Convergence Tests (out-of-place, custom jac)" begin prob = prob_dae_linear_oop sim21 = test_convergence(dts, prob, DImplicitEuler()) diff --git a/lib/OrdinaryDiffEqCore/Project.toml b/lib/OrdinaryDiffEqCore/Project.toml index 9a950e8230..67249ff5ab 100644 --- a/lib/OrdinaryDiffEqCore/Project.toml +++ b/lib/OrdinaryDiffEqCore/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqCore" uuid = "bbf590c4-e513-4bbe-9b18-05decba2e5d8" authors = ["ParamThakkar123 "] -version = "1.3.0" +version = "1.4.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/lib/OrdinaryDiffEqCore/src/alg_utils.jl b/lib/OrdinaryDiffEqCore/src/alg_utils.jl index 955540f2d6..5d144fcfae 100644 --- a/lib/OrdinaryDiffEqCore/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqCore/src/alg_utils.jl @@ -191,7 +191,6 @@ end # get_chunksize(alg::CompositeAlgorithm) = get_chunksize(alg.algs[alg.current_alg]) function alg_autodiff end -has_lazy_interpolation(alg) = false # Linear Exponential doesn't have any of the AD stuff function DiffEqBase.prepare_alg( @@ -348,10 +347,13 @@ qsteady_max_default(alg::OrdinaryDiffEqImplicitAlgorithm) = isadaptive(alg) ? 1 """ ssp_coefficient(alg) + Return the SSP coefficient of the ODE algorithm `alg`. If one time step of size `dt` with `alg` can be written as a convex combination of explicit Euler steps with step sizes `cᵢ * dt`, the SSP coefficient is the minimal value of `1/cᵢ`. + # Examples + ```julia-repl julia> ssp_coefficient(SSPRK104()) 6 @@ -430,3 +432,12 @@ is_mass_matrix_alg(alg::Union{OrdinaryDiffEqAlgorithm, DAEAlgorithm}) = false is_mass_matrix_alg(alg::CompositeAlgorithm) = all(is_mass_matrix_alg, alg.algs) is_mass_matrix_alg(alg::RosenbrockAlgorithm) = true is_mass_matrix_alg(alg::NewtonAlgorithm) = !isesdirk(alg) + +# All algorithms should be shown using their keyword definition, and not as structs +function Base.show(io::IO, ::MIME"text/plain", alg::OrdinaryDiffEqAlgorithm) + print(io, String(typeof(alg).name.name), "(;") + for fieldname in fieldnames(typeof(alg)) + print(io, " ", fieldname, " = ", getfield(alg, fieldname), ",") + end + print(io, ")") +end diff --git a/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl b/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl index 088fcc4b76..32d3774859 100644 --- a/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl +++ b/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl @@ -13,7 +13,14 @@ mutable struct CompositeCache{T, F} <: OrdinaryDiffEqCache current::Int end -get_fsalfirstlast(cache::CompositeCache, u) = get_fsalfirstlast(cache.caches[1], u) +function get_fsalfirstlast(cache::CompositeCache, u) + _x = get_fsalfirstlast(cache.caches[1], u) + if first(_x) !== nothing + return _x + else + return get_fsalfirstlast(cache.caches[2], u) + end +end mutable struct DefaultCache{T1, T2, T3, T4, T5, T6, A, F, uType} <: OrdinaryDiffEqCache args::A diff --git a/lib/OrdinaryDiffEqCore/src/doc_utils.jl b/lib/OrdinaryDiffEqCore/src/doc_utils.jl index 28c4fe64a0..75eb00dc7d 100644 --- a/lib/OrdinaryDiffEqCore/src/doc_utils.jl +++ b/lib/OrdinaryDiffEqCore/src/doc_utils.jl @@ -16,7 +16,7 @@ function generic_solver_docstring(description::String, # Indent the keywords properly indentation = repeat(" ", length(name) + 3) # We do not indent the first kw and no newline for the last one - if length(keyword_default) > 1 + if length(keywords_split) > 1 keywords_split[1] = keywords_split[1] * "\n" for i in 2:(length(keywords_split) - 1) keywords_split[i] = indentation * keywords_split[i] * "\n" @@ -34,14 +34,12 @@ function generic_solver_docstring(description::String, ``` $solver_class - """ : - """ - ```julia - $name() - ``` - - $solver_class - """ + """ : """ + ```julia + $name() + ``` + $solver_class + """ keyword_docstring = """ @@ -62,11 +60,13 @@ function explicit_rk_docstring(description::String, keyword_default = """ stage_limiter! = OrdinaryDiffEq.trivial_limiter!, step_limiter! = OrdinaryDiffEq.trivial_limiter!, + thread = OrdinaryDiffEq.False(), """ * extra_keyword_default keyword_default_description = """ - `stage_limiter!`: function of the form `limiter!(u, integrator, p, t)` - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. """ * extra_keyword_description generic_solver_docstring( @@ -74,3 +74,81 @@ function explicit_rk_docstring(description::String, keyword_default_description, keyword_default ) end +function differentiation_rk_docstring(description::String, + name::String, + solver_class::String; + references::String = "", + extra_keyword_description::String = "", + extra_keyword_default::String = "") + keyword_default = """ + chunk_size = Val{0}(), + autodiff = true, + standardtag = Val{true}(), + concrete_jac = nothing, + diff_type = Val{:forward}, + linsolve = nothing, + precs = DEFAULT_PRECS, + """ * extra_keyword_default + + keyword_default_description = """ + - `chunk_size`: The chunk size used with ForwardDiff.jl. Defaults to `Val{0}()` + and thus uses the internal ForwardDiff.jl algorithm for the choice. + - `autodiff`: Specifies whether to use automatic differentiation via + [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite + differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl). + Defaults to `Val{true}()` for automatic differentiation. + - `standardtag`: Specifies whether to use package-specific tags instead of the + ForwardDiff default function-specific tags. For more information, see + [this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/). + Defaults to `Val{true}()`. + - `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to + `nothing`, which means it will be chosen true/false depending on circumstances + of the solver, such as whether a Krylov subspace method is used for `linsolve`. + - `diff_type`: The type of differentiation used in FiniteDiff.jl if `autodiff=false`. + Defaults to `Val{:forward}`, with alternatives of `Val{:central}` and + `Val{:complex}`. + - `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver. + For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify + `$name(linsolve = KLUFactorization()`). + When `nothing` is passed, uses `DefaultLinearSolver`. + - `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/) + can be used as a left or right preconditioner. + Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)` + function where the arguments are defined as: + - `W`: the current Jacobian of the nonlinear system. Specified as either + ``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will + commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy + representation of the operator. Users can construct the W-matrix on demand + by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching + the `jac_prototype`. + - `du`: the current ODE derivative + - `u`: the current ODE state + - `p`: the ODE parameters + - `t`: the current ODE time + - `newW`: a `Bool` which specifies whether the `W` matrix has been updated since + the last call to `precs`. It is recommended that this is checked to only + update the preconditioner when `newW == true`. + - `Plprev`: the previous `Pl`. + - `Prprev`: the previous `Pr`. + - `solverdata`: Optional extra data the solvers can give to the `precs` function. + Solver-dependent and subject to change. + The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners. + To specify one-sided preconditioning, simply return `nothing` for the preconditioner + which is not used. Additionally, `precs` must supply the dispatch: + ```julia + Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata) + ``` + which is used in the solver setup phase to construct the integrator + type with the preconditioners `(Pl,Pr)`. + The default is `precs=DEFAULT_PRECS` where the default preconditioner function + is defined as: + ```julia + DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing + ``` + """ * extra_keyword_description + + generic_solver_docstring( + description, name, solver_class, references, + keyword_default_description, keyword_default + ) +end diff --git a/lib/OrdinaryDiffEqCore/src/integrators/integrator_interface.jl b/lib/OrdinaryDiffEqCore/src/integrators/integrator_interface.jl index b45e35cdec..ccae5a0609 100644 --- a/lib/OrdinaryDiffEqCore/src/integrators/integrator_interface.jl +++ b/lib/OrdinaryDiffEqCore/src/integrators/integrator_interface.jl @@ -45,7 +45,7 @@ function DiffEqBase.reeval_internals_due_to_modification!( if continuous_modification && integrator.opts.calck resize!(integrator.k, integrator.kshortsize) # Reset k for next step! alg = unwrap_alg(integrator, false) - if has_lazy_interpolation(alg) + if SciMLBase.has_lazy_interpolation(alg) ode_addsteps!(integrator, integrator.f, true, false, !alg.lazy) else ode_addsteps!(integrator, integrator.f, true, false) @@ -59,7 +59,7 @@ end @inline function DiffEqBase.get_du(integrator::ODEIntegrator) isdiscretecache(integrator.cache) && error("Derivatives are not defined for this stepper.") - return if isdefined(integrator, :fsallast) + return if isfsal(integrator.alg) integrator.fsallast else integrator(integrator.t, Val{1}) @@ -72,7 +72,7 @@ end if isdiscretecache(integrator.cache) out .= integrator.cache.tmp else - return if isdefined(integrator, :fsallast) && + return if isfsal(integrator.alg) && !has_stiff_interpolation(integrator.alg) # Special stiff interpolations do not store the # right value in fsallast @@ -221,8 +221,8 @@ function resize!(integrator::ODEIntegrator, i::Int) # may be required for things like units c !== nothing && resize!(c, i) end - resize!(integrator.fsalfirst, i) - resize!(integrator.fsallast, i) + !isnothing(integrator.fsalfirst) && resize!(integrator.fsalfirst, i) + !isnothing(integrator.fsallast) && resize!(integrator.fsallast, i) resize_f!(integrator.f, i) resize_nlsolver!(integrator, i) resize_J_W!(cache, integrator, i) @@ -235,8 +235,8 @@ function resize!(integrator::ODEIntegrator, i::NTuple{N, Int}) where {N} for c in full_cache(cache) resize!(c, i) end - resize!(integrator.fsalfirst, i) - resize!(integrator.fsallast, i) + !isnothing(integrator.fsalfirst) && resize!(integrator.fsalfirst, i) + !isnothing(integrator.fsallast) && resize!(integrator.fsallast, i) resize_f!(integrator.f, i) # TODO the parts below need to be adapted for implicit methods isdefined(integrator.cache, :nlsolver) && resize_nlsolver!(integrator, i) diff --git a/lib/OrdinaryDiffEqCore/src/interp_func.jl b/lib/OrdinaryDiffEqCore/src/interp_func.jl index a2bcd6b96c..782f7e249c 100644 --- a/lib/OrdinaryDiffEqCore/src/interp_func.jl +++ b/lib/OrdinaryDiffEqCore/src/interp_func.jl @@ -75,7 +75,8 @@ function SciMLBase.strip_interpolation(id::InterpolationData) end function strip_cache(cache) - if hasfield(typeof(cache), :jac_config) || hasfield(typeof(cache), :grad_config) + if hasfield(typeof(cache), :jac_config) || hasfield(typeof(cache), :grad_config) || + hasfield(typeof(cache), :nlsolver) fieldnums = length(fieldnames(typeof(cache))) noth_list = fill(nothing, fieldnums) cache_type_name = Base.typename(typeof(cache)).wrapper diff --git a/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl b/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl index 91d6d2a781..c3c101a47f 100644 --- a/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl +++ b/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl @@ -33,41 +33,41 @@ function initialize!(integrator, cache::DefaultCache) u = integrator.u if cache.current == 1 fsalfirst, fsallast = get_fsalfirstlast(cache.cache1, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, cache.cache1) elseif cache.current == 2 fsalfirst, fsallast = get_fsalfirstlast(cache.cache2, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, cache.cache2) # the controller was initialized by default for algs[1] reset_alg_dependent_opts!(integrator.opts.controller, algs[1], algs[2]) elseif cache.current == 3 fsalfirst, fsallast = get_fsalfirstlast(cache.cache3, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, cache.cache3) # the controller was initialized by default for algs[1] reset_alg_dependent_opts!(integrator.opts.controller, algs[1], algs[3]) elseif cache.current == 4 fsalfirst, fsallast = get_fsalfirstlast(cache.cache4, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, cache.cache4) # the controller was initialized by default for algs[1] reset_alg_dependent_opts!(integrator.opts.controller, algs[1], algs[4]) elseif cache.current == 5 fsalfirst, fsallast = get_fsalfirstlast(cache.cache5, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, cache.cache5) # the controller was initialized by default for algs[1] reset_alg_dependent_opts!(integrator.opts.controller, algs[1], algs[5]) elseif cache.current == 6 fsalfirst, fsallast = get_fsalfirstlast(cache.cache6, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, cache.cache6) # the controller was initialized by default for algs[1] reset_alg_dependent_opts!(integrator.opts.controller, algs[1], algs[6]) @@ -80,21 +80,21 @@ function initialize!(integrator, cache::CompositeCache) u = integrator.u if cache.current == 1 fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[1])) elseif cache.current == 2 fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[2])) # the controller was initialized by default for integrator.alg.algs[1] reset_alg_dependent_opts!(integrator.opts.controller, integrator.alg.algs[1], integrator.alg.algs[2]) else fsalfirst, fsallast = get_fsalfirstlast(cache.caches[cache.current], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[cache.current])) reset_alg_dependent_opts!(integrator.opts.controller, integrator.alg.algs[1], integrator.alg.algs[cache.current]) @@ -107,13 +107,13 @@ function initialize!(integrator, cache::CompositeCache{Tuple{T1, T2}, F}) where u = integrator.u if cache.current == 1 fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[1])) elseif cache.current == 2 fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[2])) reset_alg_dependent_opts!(integrator.opts.controller, integrator.alg.algs[1], integrator.alg.algs[2]) @@ -173,13 +173,13 @@ function choose_algorithm!(integrator, cache.current = new_current if new_current == 1 fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[1])) elseif new_current == 2 fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2], u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.caches[2])) end if old_current == 1 && new_current == 2 @@ -206,38 +206,38 @@ function choose_algorithm!(integrator, cache::DefaultCache) init_ith_default_cache(cache, algs, new_current) if new_current == 1 fsalfirst, fsallast = get_fsalfirstlast(cache.cache1, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.cache1)) new_cache = cache.cache1 elseif new_current == 2 fsalfirst, fsallast = get_fsalfirstlast(cache.cache2, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.cache2)) new_cache = cache.cache2 elseif new_current == 3 fsalfirst, fsallast = get_fsalfirstlast(cache.cache3, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.cache3)) new_cache = cache.cache3 elseif new_current == 4 fsalfirst, fsallast = get_fsalfirstlast(cache.cache4, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.cache4)) new_cache = cache.cache4 elseif new_current == 5 fsalfirst, fsallast = get_fsalfirstlast(cache.cache5, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.cache5)) new_cache = cache.cache5 elseif new_current == 6 fsalfirst, fsallast = get_fsalfirstlast(cache.cache6, u) - integrator.fsalfirst = fsalfirst - integrator.fsallast = fsallast + !isnothing(fsalfirst) && (integrator.fsalfirst = fsalfirst) + !isnothing(fsallast) && (integrator.fsallast = fsallast) initialize!(integrator, @inbounds(cache.cache6)) new_cache = cache.cache6 end diff --git a/lib/OrdinaryDiffEqCore/src/solve.jl b/lib/OrdinaryDiffEqCore/src/solve.jl index 563c7654db..a5efe16d43 100644 --- a/lib/OrdinaryDiffEqCore/src/solve.jl +++ b/lib/OrdinaryDiffEqCore/src/solve.jl @@ -469,14 +469,14 @@ function DiffEqBase.__init( reinitiailize = true saveiter = 0 # Starts at 0 so first save is at 1 saveiter_dense = 0 - faslfirst, fsallast = get_fsalfirstlast(cache, rate_prototype) + fsalfirst, fsallast = get_fsalfirstlast(cache, rate_prototype) integrator = ODEIntegrator{typeof(_alg), isinplace(prob), uType, typeof(du), tType, typeof(p), typeof(eigen_est), typeof(EEst), QT, typeof(tdir), typeof(k), SolType, FType, cacheType, - typeof(opts), typeof(faslfirst), + typeof(opts), typeof(fsalfirst), typeof(last_event_error), typeof(callback_cache), typeof(initializealg), typeof(differential_vars)}( sol, u, du, k, t, tType(dt), f, p, @@ -496,7 +496,7 @@ function DiffEqBase.__init( isout, reeval_fsal, u_modified, reinitiailize, isdae, opts, stats, initializealg, differential_vars, - faslfirst, fsallast) + fsalfirst, fsallast) if initialize_integrator if isdae || SciMLBase.has_initializeprob(prob.f) diff --git a/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl b/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl index 0914b355b0..e351ab54c3 100644 --- a/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl +++ b/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl @@ -12,7 +12,7 @@ struct StaticWOperator{isinv, T, F} <: AbstractSciMLOperator{T} # doing to how StaticArrays and StaticArraysCore are split up StaticArrays.LU(LowerTriangular(W), UpperTriangular(W), SVector{n}(1:n)) else - lu(W, check = false) + lu(W, check=false) end # when constructing W for the first time for the type # inv(W) can be singular @@ -80,7 +80,9 @@ function calc_J(integrator, cache, next_step::Bool = false) if alg isa DAEAlgorithm if DiffEqBase.has_jac(f) - J = f.jac(duprev, uprev, p, t) + duprev = integrator.duprev + uf = cache.uf + J = f.jac(duprev, uprev, p, uf.α * uf.invγdt, t) else @unpack uf = cache x = zero(uprev) @@ -899,7 +901,11 @@ function build_J_W(alg, u, uprev, p, t, dt, f::F, ::Type{uEltypeNoUnits}, end else J = if !IIP && DiffEqBase.has_jac(f) - f.jac(uprev, p, t) + if f isa DAEFunction + f.jac(uprev, uprev, p, one(t), t) + else + f.jac(uprev, p, t) + end elseif f.jac_prototype === nothing ArrayInterface.undefmatrix(u) else @@ -932,28 +938,28 @@ function LinearSolve.init_cacheval( end for alg in [LinearSolve.AppleAccelerateLUFactorization, - LinearSolve.BunchKaufmanFactorization, - LinearSolve.CHOLMODFactorization, - LinearSolve.CholeskyFactorization, - LinearSolve.CudaOffloadFactorization, - LinearSolve.DiagonalFactorization, - LinearSolve.FastLUFactorization, - LinearSolve.FastQRFactorization, - LinearSolve.GenericFactorization, - LinearSolve.GenericLUFactorization, - LinearSolve.KLUFactorization, - LinearSolve.LDLtFactorization, - LinearSolve.LUFactorization, - LinearSolve.MKLLUFactorization, - LinearSolve.MetalLUFactorization, - LinearSolve.NormalBunchKaufmanFactorization, - LinearSolve.NormalCholeskyFactorization, - LinearSolve.QRFactorization, - LinearSolve.RFLUFactorization, - LinearSolve.SVDFactorization, - LinearSolve.SimpleLUFactorization, - LinearSolve.SparspakFactorization, - LinearSolve.UMFPACKFactorization] + LinearSolve.BunchKaufmanFactorization, + LinearSolve.CHOLMODFactorization, + LinearSolve.CholeskyFactorization, + LinearSolve.CudaOffloadFactorization, + LinearSolve.DiagonalFactorization, + LinearSolve.FastLUFactorization, + LinearSolve.FastQRFactorization, + LinearSolve.GenericFactorization, + LinearSolve.GenericLUFactorization, + LinearSolve.KLUFactorization, + LinearSolve.LDLtFactorization, + LinearSolve.LUFactorization, + LinearSolve.MKLLUFactorization, + LinearSolve.MetalLUFactorization, + LinearSolve.NormalBunchKaufmanFactorization, + LinearSolve.NormalCholeskyFactorization, + LinearSolve.QRFactorization, + LinearSolve.RFLUFactorization, + LinearSolve.SVDFactorization, + LinearSolve.SimpleLUFactorization, + LinearSolve.SparspakFactorization, + LinearSolve.UMFPACKFactorization] @eval function LinearSolve.init_cacheval(alg::$alg, A::WOperator, b, u, Pl, Pr, maxiters::Int, abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions) diff --git a/lib/OrdinaryDiffEqExponentialRK/src/OrdinaryDiffEqExponentialRK.jl b/lib/OrdinaryDiffEqExponentialRK/src/OrdinaryDiffEqExponentialRK.jl index 5e0043aa35..98fde5722c 100644 --- a/lib/OrdinaryDiffEqExponentialRK/src/OrdinaryDiffEqExponentialRK.jl +++ b/lib/OrdinaryDiffEqExponentialRK/src/OrdinaryDiffEqExponentialRK.jl @@ -9,7 +9,8 @@ import OrdinaryDiffEqCore: alg_order, alg_adaptive_order, ismultistep, OrdinaryDiffEqAdaptiveExponentialAlgorithm, CompositeAlgorithm, ExponentialAlgorithm, fsal_typeof, isdtchangeable, calculate_residuals, calculate_residuals!, - full_cache, get_fsalfirstlast + full_cache, get_fsalfirstlast, + generic_solver_docstring import OrdinaryDiffEqCore using RecursiveArrayTools using MuladdMacro, FastBroadcast diff --git a/lib/OrdinaryDiffEqExponentialRK/src/algorithms.jl b/lib/OrdinaryDiffEqExponentialRK/src/algorithms.jl index 800176cdc1..6f83541846 100644 --- a/lib/OrdinaryDiffEqExponentialRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqExponentialRK/src/algorithms.jl @@ -1,13 +1,38 @@ -for Alg in [:LawsonEuler, :NorsettEuler, :ETDRK2, :ETDRK3, :ETDRK4, :HochOst4] - """ - Hochbruck, Marlis, and Alexander Ostermann. “Exponential Integrators.” Acta - Numerica 19 (2010): 209–286. doi:10.1017/S0962492910000048. - """ - @eval struct $Alg{CS, AD, FDT, ST, CJ} <: - OrdinaryDiffEqExponentialAlgorithm{CS, AD, FDT, ST, CJ} - krylov::Bool - m::Int - iop::Int +REF1 = """ +Hochbruck, Marlis, and Alexander Ostermann. “Exponential Integrators.” Acta + Numerica 19 (2010): 209–286. doi:10.1017/S0962492910000048. +""" +for (Alg, Description, Ref) in [ + (:LawsonEuler, "First order exponential Euler scheme.", REF1), + (:NorsettEuler, "First order exponential-RK scheme. Alias: `ETD1`", REF1), + (:ETDRK2, "2nd order exponential-RK scheme.", REF1), + (:ETDRK3, "3rd order exponential-RK scheme.", REF1), + (:ETDRK4, "4th order exponential-RK scheme", REF1), + (:HochOst4, "4th order exponential-RK scheme with stiff order 4.", REF1) +] + @eval begin + @doc generic_solver_docstring($Description, + $(string(Alg)), + "Semilinear ODE solver", + $Ref, + """ + - `krylov`: Determines whether Krylov approximation or operator caching is used, the latter only available for semilinear problems. + `krylov=true` is much faster for larger systems and is thus recommended whenever there are >100 ODEs. + - `m`: Controls the size of Krylov subspace. + - `iop`: If not zero, determines the length of the incomplete orthogonalization procedure (IOP). + Note that if the linear operator/Jacobian is hermitian, then the Lanczos algorithm will always be used and the IOP setting is ignored. + """, + """ + krylov = false, + m = 30, + iop = 0, + """) + struct $Alg{CS, AD, FDT, ST, CJ} <: + OrdinaryDiffEqExponentialAlgorithm{CS, AD, FDT, ST, CJ} + krylov::Bool + m::Int + iop::Int + end end @eval function $Alg(; krylov = false, m = 30, iop = 0, autodiff = true, standardtag = Val{true}(), concrete_jac = nothing, @@ -22,11 +47,32 @@ end const ETD1 = NorsettEuler # alias -for Alg in [:Exprb32, :Exprb43] - @eval struct $Alg{CS, AD, FDT, ST, CJ} <: - OrdinaryDiffEqAdaptiveExponentialAlgorithm{CS, AD, FDT, ST, CJ} - m::Int - iop::Int +REF2 = """ +Hochbruck, M., & Ostermann, A. (2010). Exponential integrators. Acta Numerica, 19, 209-286. (https://doi.org/10.1017/S0962492910000048) +""" + +for (Alg, Description, Ref) in [ + (:Exprb32, "3rd order adaptive Exponential-Rosenbrock scheme.", REF2), + (:Exprb43, "4th order adaptive Exponential-Rosenbrock scheme.", REF2)] + @eval begin + @doc generic_solver_docstring($Description, + $(string(Alg)), + "Semilinear ODE solver", + $Ref, + """ + - `m`: Controls the size of Krylov subspace. + - `iop`: If not zero, determines the length of the incomplete orthogonalization procedure (IOP). + Note that if the linear operator/Jacobian is hermitian, then the Lanczos algorithm will always be used and the IOP setting is ignored. + """, + """ + m = 30, + iop = 0, + """) + struct $Alg{CS, AD, FDT, ST, CJ} <: + OrdinaryDiffEqAdaptiveExponentialAlgorithm{CS, AD, FDT, ST, CJ} + m::Int + iop::Int + end end @eval function $Alg(; m = 30, iop = 0, autodiff = true, standardtag = Val{true}(), concrete_jac = nothing, chunk_size = Val{0}(), @@ -37,12 +83,52 @@ for Alg in [:Exprb32, :Exprb43] iop) end end -for Alg in [:Exp4, :EPIRK4s3A, :EPIRK4s3B, :EPIRK5s3, :EXPRB53s3, :EPIRK5P1, :EPIRK5P2] - @eval struct $Alg{CS, AD, FDT, ST, CJ} <: - OrdinaryDiffEqExponentialAlgorithm{CS, AD, FDT, ST, CJ} - adaptive_krylov::Bool - m::Int - iop::Int + +REF3 = """ +Hochbruck, M., Lubich, C., & Selhofer, H. (1998). Exponential integrators for large systems of differential equations. SIAM Journal on Scientific Computing, 19(5), 1552-1574. (https://doi.org/10.1137/S1064827595295337) +""" + +REF4 = """ +Rainwater, G., & Tokman, M. (2016). A new approach to constructing efficient stiffly accurate EPIRK methods. Journal of Computational Physics, 323, 283-309. (https://doi.org/10.1016/j.jcp.2016.07.026) +""" +REF5 = """ +Tokman, M., Loffeld, J., & Tranquilli, P. (2012). New Adaptive Exponential Propagation Iterative Methods of Runge--Kutta Type. SIAM Journal on Scientific Computing, 34(5), A2650-A2669. (https://doi.org/10.1137/110849961) +""" + +for (Alg, Description, Ref) in [(:Exp4, "4th order EPIRK scheme.", REF3) + (:EPIRK4s3A, + "4th order EPIRK scheme with stiff order 4.", REF4) + (:EPIRK4s3B, + "4th order EPIRK scheme with stiff order 4.", REF4) + (:EPIRK5s3, + "5th order “horizontal” EPIRK scheme with stiff order 5. Broken.", + REF4) + (:EXPRB53s3, + "5th order EPIRK scheme with stiff order 5.", REF4) + (:EPIRK5P1, "5th order EPIRK scheme", REF5) + (:EPIRK5P2, "5th order EPIRK scheme", REF5)] + @eval begin + @doc generic_solver_docstring($Description, + $(string(Alg)), + "Semilinear ODE solver", + $Ref, + """ + - `adaptive_krylov`: Determines if the adaptive Krylov algorithm with timestepping of Neisen & Wright is used. + - `m`: Controls the size of Krylov subspace. + - `iop`: If not zero, determines the length of the incomplete orthogonalization procedure (IOP). + Note that if the linear operator/Jacobian is hermitian, then the Lanczos algorithm will always be used and the IOP setting is ignored. + """, + """ + adaptive_krylov = true, + m = 30, + iop = 0, + """) + struct $Alg{CS, AD, FDT, ST, CJ} <: + OrdinaryDiffEqExponentialAlgorithm{CS, AD, FDT, ST, CJ} + adaptive_krylov::Bool + m::Int + iop::Int + end end @eval function $Alg(; adaptive_krylov = true, m = 30, iop = 0, autodiff = true, standardtag = Val{true}(), concrete_jac = nothing, diff --git a/lib/OrdinaryDiffEqExtrapolation/src/OrdinaryDiffEqExtrapolation.jl b/lib/OrdinaryDiffEqExtrapolation/src/OrdinaryDiffEqExtrapolation.jl index fd4dc8d7b3..29bbc6ca8b 100644 --- a/lib/OrdinaryDiffEqExtrapolation/src/OrdinaryDiffEqExtrapolation.jl +++ b/lib/OrdinaryDiffEqExtrapolation/src/OrdinaryDiffEqExtrapolation.jl @@ -16,7 +16,8 @@ import OrdinaryDiffEqCore: alg_order, alg_maximum_order, get_current_adaptive_or DEFAULT_PRECS, full_cache, constvalue, PolyesterThreads, Sequential, BaseThreads, _digest_beta1_beta2, timedepentdtmin, _unwrap_val, - _reshape, _vec, get_fsalfirstlast + _reshape, _vec, get_fsalfirstlast, generic_solver_docstring, + differentiation_rk_docstring using DiffEqBase, FastBroadcast, Polyester, MuladdMacro, RecursiveArrayTools, LinearSolve import OrdinaryDiffEqCore import OrdinaryDiffEqDifferentiation: TimeDerivativeWrapper, UDerivativeWrapper, calc_J, diff --git a/lib/OrdinaryDiffEqExtrapolation/src/algorithms.jl b/lib/OrdinaryDiffEqExtrapolation/src/algorithms.jl index 7b84e36bdc..205e8e1f3d 100644 --- a/lib/OrdinaryDiffEqExtrapolation/src/algorithms.jl +++ b/lib/OrdinaryDiffEqExtrapolation/src/algorithms.jl @@ -2,25 +2,59 @@ abstract type OrdinaryDiffEqExtrapolationVarOrderVarStepAlgorithm <: OrdinaryDiffEqAdaptiveAlgorithm end abstract type OrdinaryDiffEqImplicitExtrapolationAlgorithm{CS, AD, FDT, ST, CJ} <: OrdinaryDiffEqAdaptiveImplicitAlgorithm{CS, AD, FDT, ST, CJ} end - -""" -AitkenNeville: Parallelized Explicit Extrapolation Method -Euler extrapolation using Aitken-Neville with the Romberg Sequence. +reference = """@inproceedings{elrod2022parallelizing, + title={Parallelizing explicit and implicit extrapolation methods for ordinary differential equations}, + author={Elrod, Chris and Ma, Yingbo and Althaus, Konstantin and Rackauckas, Christopher and others}, + booktitle={2022 IEEE High Performance Extreme Computing Conference (HPEC)}, + pages={1--9}, + year={2022}, + organization={IEEE}} """ -struct AitkenNeville{TO} <: OrdinaryDiffEqExtrapolationVarOrderVarStepAlgorithm - max_order::Int - min_order::Int - init_order::Int - threading::TO -end -function AitkenNeville(; max_order = 10, min_order = 1, init_order = 5, threading = false) - AitkenNeville(max_order, min_order, init_order, threading) + +@doc generic_solver_docstring( + "Euler extrapolation using Aitken-Neville with the Romberg Sequence.", + "AitkenNeville", + "Parallelized Explicit Extrapolation Method.", + reference, + """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + """, + """ + max_order::Int = 10, + min_order::Int = 1, + init_order = 3, + thread = OrdinaryDiffEq.False(), + """) +Base.@kwdef struct AitkenNeville{TO} <: OrdinaryDiffEqExtrapolationVarOrderVarStepAlgorithm + max_order::Int = 10 + min_order::Int = 1 + init_order::Int = 5 + threading::TO = false end -""" -ImplicitEulerExtrapolation: Parallelized Implicit Extrapolation Method -Extrapolation of implicit Euler method with Romberg sequence. -Similar to Hairer's SEULEX. -""" + +@doc differentiation_rk_docstring( + "Extrapolation of implicit Euler method with Romberg sequence. +Similar to Hairer's SEULEX.", + "ImplicitEulerExtrapolation", + "Parallelized Explicit Extrapolation Method.", + references = reference, + extra_keyword_description = """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + - `sequence`: the step-number sequences, also called the subdividing sequence. Possible values are `:harmonic`, `:romberg` or `:bulirsch`. + """, + extra_keyword_default = """ + max_order = 12, + min_order = 3, + init_order = 5, + thread = OrdinaryDiffEq.False(), + sequence = :harmonic + """) struct ImplicitEulerExtrapolation{CS, AD, F, P, FDT, ST, CJ, TO} <: OrdinaryDiffEqImplicitExtrapolationAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -72,10 +106,27 @@ Initial order: " * lpad(init_order, 2, " ") * " --> " * lpad(init_order, 2, " ") init_order, threading, sequence) end -""" -ExtrapolationMidpointDeuflhard: Parallelized Explicit Extrapolation Method -Midpoint extrapolation using Barycentric coordinates -""" + +@doc generic_solver_docstring("Midpoint extrapolation using Barycentric coordinates.", + "ExtrapolationMidpointDeuflhard", + "Parallelized Explicit Extrapolation Method.", + reference, + """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + - `sequence`: the step-number sequences, also called the subdividing sequence. Possible values are `:harmonic`, `:romberg` or `:bulirsch`. + - `sequence_factor`: denotes which even multiple of sequence to take while evaluating internal discretizations. + """, + """ + max_order = 10, + min_order = 1, + init_order = 5, + thread = OrdinaryDiffEq.True(), + sequence = :harmonic, + sequence_factor = 2, + """) struct ExtrapolationMidpointDeuflhard{TO} <: OrdinaryDiffEqExtrapolationVarOrderVarStepAlgorithm min_order::Int # Minimal extrapolation order @@ -125,10 +176,25 @@ Initial order: " * lpad(init_order, 2, " ") * " --> " * lpad(init_order, 2, " ") ExtrapolationMidpointDeuflhard(min_order, init_order, max_order, sequence, threading, sequence_factor) end -""" -ImplicitDeuflhardExtrapolation: Parallelized Implicit Extrapolation Method -Midpoint extrapolation using Barycentric coordinates -""" + +@doc differentiation_rk_docstring("Midpoint extrapolation using Barycentric coordinates.", + "ImplicitDeuflhardExtrapolation", + "Parallelized Explicit Extrapolation Method.", + references = reference, + extra_keyword_description = """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + - `sequence`: the step-number sequences, also called the subdividing sequence. Possible values are `:harmonic`, `:romberg` or `:bulirsch`. + """, + extra_keyword_default = """ + max_order = 10, + min_order = 1, + init_order = 5, + thread = OrdinaryDiffEq.False(), + sequence = :harmonic, + """) struct ImplicitDeuflhardExtrapolation{CS, AD, F, P, FDT, ST, CJ, TO} <: OrdinaryDiffEqImplicitExtrapolationAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -183,10 +249,28 @@ Initial order: " * lpad(init_order, 2, " ") * " --> " * lpad(init_order, 2, " ") init_order, max_order, sequence, threading) end -""" -ExtrapolationMidpointHairerWanner: Parallelized Explicit Extrapolation Method -Midpoint extrapolation using Barycentric coordinates, following Hairer's ODEX in the adaptivity behavior. -""" + +@doc generic_solver_docstring("Midpoint extrapolation using Barycentric coordinates, + following Hairer's ODEX in the adaptivity behavior.", + "ExtrapolationMidpointHairerWanner", + "Parallelized Explicit Extrapolation Method.", + reference, + """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + - `sequence`: the step-number sequences, also called the subdividing sequence. Possible values are `:harmonic`, `:romberg` or `:bulirsch`. + - `sequence_factor`: denotes which even multiple of sequence to take while evaluating internal discretizations. + """, + """ + max_order = 10, + min_order = 2, + init_order = 5, + thread = OrdinaryDiffEq.True(), + sequence = :harmonic, + sequence_factor = 2, + """) struct ExtrapolationMidpointHairerWanner{TO} <: OrdinaryDiffEqExtrapolationVarOrderVarStepAlgorithm min_order::Int # Minimal extrapolation order @@ -238,10 +322,26 @@ Initial order: " * lpad(init_order, 2, " ") * " --> " * lpad(init_order, 2, " ") min_order, init_order, max_order, sequence, threading, sequence_factor) end -""" -ImplicitHairerWannerExtrapolation: Parallelized Implicit Extrapolation Method -Midpoint extrapolation using Barycentric coordinates, following Hairer's SODEX in the adaptivity behavior. -""" + +@doc differentiation_rk_docstring("Midpoint extrapolation using Barycentric coordinates, + following Hairer's SODEX in the adaptivity behavior.", + "ImplicitHairerWannerExtrapolation", + "Parallelized Explicit Extrapolation Method.", + references = reference, + extra_keyword_description = """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + - `sequence`: the step-number sequences, also called the subdividing sequence. Possible values are `:harmonic`, `:romberg` or `:bulirsch`. + """, + extra_keyword_default = """ + max_order = 10, + min_order = 2, + init_order = 5, + thread = OrdinaryDiffEq.False(), + sequence = :harmonic, + """) struct ImplicitHairerWannerExtrapolation{CS, AD, F, P, FDT, ST, CJ, TO} <: OrdinaryDiffEqImplicitExtrapolationAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -299,10 +399,27 @@ Initial order: " * lpad(init_order, 2, " ") * " --> " * lpad(init_order, 2, " ") max_order, sequence, threading) end -""" -ImplicitEulerBarycentricExtrapolation: Parallelized Implicit Extrapolation Method -Euler extrapolation using Barycentric coordinates, following Hairer's SODEX in the adaptivity behavior. -""" +@doc differentiation_rk_docstring("Euler extrapolation using Barycentric coordinates, + following Hairer's SODEX in the adaptivity behavior.", + "ImplicitEulerBarycentricExtrapolation", + "Parallelized Explicit Extrapolation Method.", + references = reference, + extra_keyword_description = """ + - `max_order`: maximum order of the adaptive order algorithm. + - `min_order`: minimum order of the adaptive order algorithm. + - `init_order`: initial order of the adaptive order algorithm. + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + - `sequence`: the step-number sequences, also called the subdividing sequence. Possible values are `:harmonic`, `:romberg` or `:bulirsch`. + - `sequence_factor`: denotes which even multiple of sequence to take while evaluating internal discretizations. + """, + extra_keyword_default = """ + max_order = 10, + min_order = 3, + init_order = 5, + thread = OrdinaryDiffEq.False(), + sequence = :harmonic, + sequence_factor = 2, + """) struct ImplicitEulerBarycentricExtrapolation{CS, AD, F, P, FDT, ST, CJ, TO} <: OrdinaryDiffEqImplicitExtrapolationAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F diff --git a/lib/OrdinaryDiffEqFIRK/src/OrdinaryDiffEqFIRK.jl b/lib/OrdinaryDiffEqFIRK/src/OrdinaryDiffEqFIRK.jl index a37ff9383b..40305282d7 100644 --- a/lib/OrdinaryDiffEqFIRK/src/OrdinaryDiffEqFIRK.jl +++ b/lib/OrdinaryDiffEqFIRK/src/OrdinaryDiffEqFIRK.jl @@ -8,7 +8,7 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, OrdinaryDiffEqAdaptiveAlgorithm, CompiledFloats, uses_uprev, alg_cache, _vec, _reshape, @cache, isfsal, full_cache, constvalue, _unwrap_val, - explicit_rk_docstring, trivial_limiter!, + differentiation_rk_docstring, trivial_limiter!, _ode_interpolant!, _ode_addsteps!, AbstractController, qmax_default, alg_adaptive_order, DEFAULT_PRECS, stepsize_controller!, step_accept_controller!, @@ -16,7 +16,7 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, PredictiveController, alg_can_repeat_jac, NewtonAlgorithm, fac_default_gamma, get_current_adaptive_order, get_fsalfirstlast, - isfirk + isfirk, generic_solver_docstring using MuladdMacro, DiffEqBase, RecursiveArrayTools using Polynomials, GenericLinearAlgebra, GenericSchur using SciMLOperators: AbstractSciMLOperator diff --git a/lib/OrdinaryDiffEqFIRK/src/algorithms.jl b/lib/OrdinaryDiffEqFIRK/src/algorithms.jl index 4429fb78b6..25165422c8 100644 --- a/lib/OrdinaryDiffEqFIRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqFIRK/src/algorithms.jl @@ -1,20 +1,31 @@ -# FIRK Methods -""" -@article{hairer1999stiff, -title={Stiff differential equations solved by Radau methods}, -author={Hairer, Ernst and Wanner, Gerhard}, -journal={Journal of Computational and Applied Mathematics}, -volume={111}, -number={1-2}, -pages={93--111}, -year={1999}, -publisher={Elsevier} -} +hairer1999stiff = """@article{hairer1999stiff, + title={Stiff differential equations solved by Radau methods}, + author={Hairer, Ernst and Wanner, Gerhard}, + journal={Journal of Computational and Applied Mathematics}, + volume={111}, + number={1-2}, + pages={93--111}, + year={1999}, + publisher={Elsevier}}""" -RadauIIA3: Fully-Implicit Runge-Kutta Method -An A-B-L stable fully implicit Runge-Kutta method with internal tableau complex basis transform for efficiency. -""" +extra_keyword_description = """ + - `extrapolant`: TBD + - `smooth_est`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)`""" +extra_keyword_default = """ + extrapolant = :dense, + smooth_est = true, + step_limiter! = trivial_limiter!""" + +@doc differentiation_rk_docstring( + "An A-B-L stable fully implicit Runge-Kutta method with internal tableau complex basis transform for efficiency. +Similar to Hairer's SEULEX.", + "RadauIIA3", + "Fully-Implicit Runge-Kutta Method."; + references = hairer1999stiff, + extra_keyword_description = extra_keyword_description, + extra_keyword_default = extra_keyword_default) struct RadauIIA3{CS, AD, F, P, FDT, ST, CJ, Tol, C1, C2, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -50,21 +61,14 @@ function RadauIIA3(; chunk_size = Val{0}(), autodiff = Val{true}(), step_limiter!) end -""" -@article{hairer1999stiff, -title={Stiff differential equations solved by Radau methods}, -author={Hairer, Ernst and Wanner, Gerhard}, -journal={Journal of Computational and Applied Mathematics}, -volume={111}, -number={1-2}, -pages={93--111}, -year={1999}, -publisher={Elsevier} -} - -RadauIIA5: Fully-Implicit Runge-Kutta Method -An A-B-L stable fully implicit Runge-Kutta method with internal tableau complex basis transform for efficiency. -""" +@doc differentiation_rk_docstring( + "An A-B-L stable fully implicit Runge-Kutta method with internal tableau complex basis transform for efficiency. +Similar to Hairer's SEULEX.", + "RadauIIA5", + "Fully-Implicit Runge-Kutta Method."; + references = hairer1999stiff, + extra_keyword_description = extra_keyword_description, + extra_keyword_default = extra_keyword_default) struct RadauIIA5{CS, AD, F, P, FDT, ST, CJ, Tol, C1, C2, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -102,21 +106,14 @@ function RadauIIA5(; chunk_size = Val{0}(), autodiff = Val{true}(), step_limiter!) end -""" -@article{hairer1999stiff, -title={Stiff differential equations solved by Radau methods}, -author={Hairer, Ernst and Wanner, Gerhard}, -journal={Journal of Computational and Applied Mathematics}, -volume={111}, -number={1-2}, -pages={93--111}, -year={1999}, -publisher={Elsevier} -} - -RadauIIA9: Fully-Implicit Runge-Kutta Method -An A-B-L stable fully implicit Runge-Kutta method with internal tableau complex basis transform for efficiency. -""" +@doc differentiation_rk_docstring( + "An A-B-L stable fully implicit Runge-Kutta method with internal tableau complex basis transform for efficiency. +Similar to Hairer's SEULEX.", + "RadauIIA9", + "Fully-Implicit Runge-Kutta Method."; + references = hairer1999stiff, + extra_keyword_description = extra_keyword_description, + extra_keyword_default = extra_keyword_default) struct RadauIIA9{CS, AD, F, P, FDT, ST, CJ, Tol, C1, C2, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F diff --git a/lib/OrdinaryDiffEqFIRK/src/firk_perform_step.jl b/lib/OrdinaryDiffEqFIRK/src/firk_perform_step.jl index c7eedf7b33..318e062494 100644 --- a/lib/OrdinaryDiffEqFIRK/src/firk_perform_step.jl +++ b/lib/OrdinaryDiffEqFIRK/src/firk_perform_step.jl @@ -166,7 +166,7 @@ end rhs1 = @. fw1 - αdt * Mw1 + βdt * Mw2 rhs2 = @. fw2 - βdt * Mw1 - αdt * Mw2 - dw12 = LU1 \ (@. rhs1 + rhs2 * im) + dw12 = _reshape(LU1 \ _vec(@. rhs1 + rhs2 * im), axes(u)) integrator.stats.nsolve += 1 dw1 = real(dw12) dw2 = imag(dw12) @@ -447,8 +447,8 @@ end rhs1 = @.. broadcast=false fw1-γdt * Mw1 rhs2 = @.. broadcast=false fw2 - αdt * Mw2+βdt * Mw3 rhs3 = @.. broadcast=false fw3 - βdt * Mw2-αdt * Mw3 - dw1 = LU1 \ rhs1 - dw23 = LU2 \ (@.. broadcast=false rhs2+rhs3 * im) + dw1 = _reshape(LU1 \ _vec(rhs1), axes(u)) + dw23 = _reshape(LU2 \ _vec(@.. broadcast=false rhs2+rhs3 * im), axes(u)) integrator.stats.nsolve += 2 dw2 = real(dw23) dw3 = imag(dw23) @@ -504,7 +504,10 @@ end tmp = @.. broadcast=false e1dt*z1+e2dt*z2+e3dt*z3 mass_matrix != I && (tmp = mass_matrix * tmp) utilde = @.. broadcast=false integrator.fsalfirst+tmp - alg.smooth_est && (utilde = LU1 \ utilde; integrator.stats.nsolve += 1) + if alg.smooth_est + utilde = _reshape(LU1 \ _vec(utilde), axes(u)) + integrator.stats.nsolve += 1 + end # RadauIIA5 needs a transformed rtol and atol see # https://github.com/luchr/ODEInterface.jl/blob/0bd134a5a358c4bc13e0fb6a90e27e4ee79e0115/src/radau5.f#L399-L421 atmp = calculate_residuals(utilde, uprev, u, atol, rtol, internalnorm, t) @@ -902,9 +905,9 @@ end rhs3 = @.. broadcast=false fw3 - β1dt * Mw2-α1dt * Mw3 rhs4 = @.. broadcast=false fw4 - α2dt * Mw4+β2dt * Mw5 rhs5 = @.. broadcast=false fw5 - β2dt * Mw4-α2dt * Mw5 - dw1 = LU1 \ rhs1 - dw23 = LU2 \ (@.. broadcast=false rhs2+rhs3 * im) - dw45 = LU3 \ (@.. broadcast=false rhs4+rhs5 * im) + dw1 = _reshape(LU1 \ _vec(rhs1), axes(u)) + dw23 = _reshape(LU2 \ _vec(@.. broadcast=false rhs2+rhs3 * im), axes(u)) + dw45 = _reshape(LU3 \ _vec(@.. broadcast=false rhs4+rhs5 * im), axes(u)) integrator.stats.nsolve += 3 dw2 = real(dw23) dw3 = imag(dw23) @@ -972,7 +975,10 @@ end tmp = @.. broadcast=false e1dt*z1+e2dt*z2+e3dt*z3+e4dt*z4+e5dt*z5 mass_matrix != I && (tmp = mass_matrix * tmp) utilde = @.. broadcast=false integrator.fsalfirst+tmp - alg.smooth_est && (utilde = LU1 \ utilde; integrator.stats.nsolve += 1) + if alg.smooth_est + utilde = _reshape(LU1 \ _vec(utilde), axes(u)) + integrator.stats.nsolve += 1 + end atmp = calculate_residuals(utilde, uprev, u, atol, rtol, internalnorm, t) integrator.EEst = internalnorm(atmp, t) diff --git a/lib/OrdinaryDiffEqFeagin/src/OrdinaryDiffEqFeagin.jl b/lib/OrdinaryDiffEqFeagin/src/OrdinaryDiffEqFeagin.jl index 5573a4dea2..a1a4236c9f 100644 --- a/lib/OrdinaryDiffEqFeagin/src/OrdinaryDiffEqFeagin.jl +++ b/lib/OrdinaryDiffEqFeagin/src/OrdinaryDiffEqFeagin.jl @@ -8,7 +8,7 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, OrdinaryDiffEqAdaptiveAlgorithm, CompiledFloats, uses_uprev, alg_cache, _vec, _reshape, @cache, isfsal, full_cache, constvalue, _unwrap_val, get_fsalfirstlast, - explicit_rk_docstring, trivial_limiter!, + generic_solver_docstring, trivial_limiter!, _ode_interpolant!, _ode_addsteps! using FastBroadcast, Polyester, MuladdMacro, RecursiveArrayTools using DiffEqBase: @def, @tight_loop_macros diff --git a/lib/OrdinaryDiffEqFeagin/src/algorithms.jl b/lib/OrdinaryDiffEqFeagin/src/algorithms.jl index 76260ce1b6..7b3a581a05 100644 --- a/lib/OrdinaryDiffEqFeagin/src/algorithms.jl +++ b/lib/OrdinaryDiffEqFeagin/src/algorithms.jl @@ -1,40 +1,56 @@ -""" -@article{feagin2012high, -title={High-order explicit Runge-Kutta methods using m-symmetry}, -author={Feagin, Terry}, -year={2012}, -publisher={Neural, Parallel \\& Scientific Computations} -} - -Feagin10: Explicit Runge-Kutta Method -Feagin's 10th-order Runge-Kutta method. -""" +@doc generic_solver_docstring( + "Feagin's 10th-order method.", "Feagin10", "Explicit Runge-Kutta Method. ", + """@article{feagin2012high, + title={High-order explicit Runge-Kutta methods using m-symmetry}, + author={Feagin, Terry}, + year={2012}, + publisher={Neural, Parallel \\& Scientific Computations} + }""", + """ + - `stage_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + """ + step_limiter! = OrdinaryDiffEq.trivial_limiter!, + """ +) Base.@kwdef struct Feagin10{StepLimiter} <: OrdinaryDiffEqAdaptiveAlgorithm step_limiter!::StepLimiter = trivial_limiter! end -""" -@article{feagin2012high, -title={High-order explicit Runge-Kutta methods using m-symmetry}, -author={Feagin, Terry}, -year={2012}, -publisher={Neural, Parallel \\& Scientific Computations} -} - -Feagin12: Explicit Runge-Kutta Method -Feagin's 12th-order Runge-Kutta method. -""" +@doc generic_solver_docstring( + "Feagin's 12th-order method.", "Feagin12", "Explicit Runge-Kutta Method. ", + """@article{feagin2012high, + title={High-order explicit Runge-Kutta methods using m-symmetry}, + author={Feagin, Terry}, + year={2012}, + publisher={Neural, Parallel \\& Scientific Computations} + }""", + """ + - `stage_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + """ + step_limiter! = OrdinaryDiffEq.trivial_limiter!, + """ +) Base.@kwdef struct Feagin12{StepLimiter} <: OrdinaryDiffEqAdaptiveAlgorithm step_limiter!::StepLimiter = trivial_limiter! end -""" -Feagin, T., “An Explicit Runge-Kutta Method of Order Fourteen,” Numerical -Algorithms, 2009 - -Feagin14: Explicit Runge-Kutta Method -Feagin's 14th-order Runge-Kutta method. -""" +@doc generic_solver_docstring( + "Feagin's 14th-order method.", "Feagin14", "Explicit Runge-Kutta Method. ", + """@article{feagin2009explicit, + title={An Explicit Runge-Kutta Method of Order Fourteen}, + author={Feagin, Terry}, + year={2009}, + publisher={Numerical Algorithms} + }""", + """ + - `stage_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + """ + step_limiter! = OrdinaryDiffEq.trivial_limiter!, + """ +) Base.@kwdef struct Feagin14{StepLimiter} <: OrdinaryDiffEqAdaptiveAlgorithm step_limiter!::StepLimiter = trivial_limiter! end diff --git a/lib/OrdinaryDiffEqFunctionMap/Project.toml b/lib/OrdinaryDiffEqFunctionMap/Project.toml index e401f0748c..ae358acea2 100644 --- a/lib/OrdinaryDiffEqFunctionMap/Project.toml +++ b/lib/OrdinaryDiffEqFunctionMap/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqFunctionMap" uuid = "d3585ca7-f5d3-4ba6-8057-292ed1abd90f" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.1.1" [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" diff --git a/lib/OrdinaryDiffEqFunctionMap/src/functionmap_caches.jl b/lib/OrdinaryDiffEqFunctionMap/src/functionmap_caches.jl index 38d7afe1d8..a2b03c0818 100644 --- a/lib/OrdinaryDiffEqFunctionMap/src/functionmap_caches.jl +++ b/lib/OrdinaryDiffEqFunctionMap/src/functionmap_caches.jl @@ -3,7 +3,7 @@ uprev::uType tmp::rateType end -get_fsalfirstlast(cache::FunctionMapCache, u) = (cache.u, cache.uprev) +get_fsalfirstlast(cache::FunctionMapCache, u) = (nothing, nothing) function alg_cache(alg::FunctionMap, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqHighOrderRK/src/algorithms.jl b/lib/OrdinaryDiffEqHighOrderRK/src/algorithms.jl index 32ddbc9dd7..87f2740948 100644 --- a/lib/OrdinaryDiffEqHighOrderRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqHighOrderRK/src/algorithms.jl @@ -15,7 +15,16 @@ function TanYam7(stage_limiter!, step_limiter! = trivial_limiter!) TanYam7(stage_limiter!, step_limiter!, False()) end -@doc explicit_rk_docstring("Tsitouras-Papakostas 8/7 Runge-Kutta method.", "TsitPap8") +@doc explicit_rk_docstring("Tsitouras-Papakostas 8/7 Runge-Kutta method.", "TsitPap8", + references = """@article{tsitouras1999cheap, + title={Cheap error estimation for Runge--Kutta methods}, + author={Tsitouras, Ch and Papakostas, SN}, + journal={SIAM Journal on Scientific Computing}, + volume={20}, + number={6}, + pages={2067--2088}, + year={1999}, + publisher={SIAM}}""") Base.@kwdef struct TsitPap8{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -44,6 +53,14 @@ function DP8(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring("Phase-fitted Runge-Kutta of 8th order.", "PFRK87", + references = """@article{tsitouras2017phase, + title={Phase-fitted Runge--Kutta pairs of orders 8 (7)}, + author={Tsitouras, Ch and Famelis, I Th and Simos, TE}, + journal={Journal of Computational and Applied Mathematics}, + volume={321}, + pages={226--231}, + year={2017}, + publisher={Elsevier}}""", extra_keyword_description = """- `omega`: a periodicity phase estimate, when accurate this method results in zero numerical dissipation. """, diff --git a/lib/OrdinaryDiffEqIMEXMultistep/src/OrdinaryDiffEqIMEXMultistep.jl b/lib/OrdinaryDiffEqIMEXMultistep/src/OrdinaryDiffEqIMEXMultistep.jl index 020d094b37..567e6b5eae 100644 --- a/lib/OrdinaryDiffEqIMEXMultistep/src/OrdinaryDiffEqIMEXMultistep.jl +++ b/lib/OrdinaryDiffEqIMEXMultistep/src/OrdinaryDiffEqIMEXMultistep.jl @@ -4,7 +4,8 @@ import OrdinaryDiffEqCore: alg_order, issplit, OrdinaryDiffEqNewtonAlgorithm, _u DEFAULT_PRECS, OrdinaryDiffEqConstantCache, OrdinaryDiffEqMutableCache, @cache, alg_cache, initialize!, perform_step!, @unpack, - full_cache, get_fsalfirstlast + full_cache, get_fsalfirstlast, + generic_solver_docstring using FastBroadcast import OrdinaryDiffEqCore diff --git a/lib/OrdinaryDiffEqIMEXMultistep/src/algorithms.jl b/lib/OrdinaryDiffEqIMEXMultistep/src/algorithms.jl index 2aca6a5bd6..69e0d7ab57 100644 --- a/lib/OrdinaryDiffEqIMEXMultistep/src/algorithms.jl +++ b/lib/OrdinaryDiffEqIMEXMultistep/src/algorithms.jl @@ -1,5 +1,25 @@ # IMEX Multistep methods +@doc generic_solver_docstring("Crank-Nicholson Adams-Bashforth 2.", + "CNAB2", + "IMEX Multistep method.", + "@article{jorgenson2014unconditional, + title={Unconditional stability of a Crank-Nicolson Adams-Bashforth 2 numerical method}, + author={JORGENSON, ANDREW D}, + journal={A (A- C)}, + volume={1}, + number={2}, + pages={1}, + year={2014}} + @article{he2010numerical, + title={Numerical implementation of the Crank--Nicolson/Adams--Bashforth scheme for the time-dependent Navier--Stokes equations}, + author={He, Yinnian and Li, Jian}, + journal={International journal for numerical methods in fluids}, + volume={62}, + number={6}, + pages={647--659}, + year={2010}, + publisher={Wiley Online Library}}", "", "") struct CNAB2{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -21,6 +41,25 @@ function CNAB2(; chunk_size = Val{0}(), autodiff = Val{true}(), standardtag = Va extrapolant) end +@doc generic_solver_docstring("Crank-Nicholson Leapfrong 2.", + "CNLF2", + "IMEX Multistep method.", + "@article{han2020second, + title={A second order, linear, unconditionally stable, Crank--Nicolson--Leapfrog scheme for phase field models of two-phase incompressible flows}, + author={Han, Daozhi and Jiang, Nan}, + journal={Applied Mathematics Letters}, + volume={108}, + pages={106521}, + year={2020}, + publisher={Elsevier}} + @article{jiang2015crank, + title={A Crank--Nicolson Leapfrog stabilization: Unconditional stability and two applications}, + author={Jiang, Nan and Kubacki, Michaela and Layton, William and Moraiti, Marina and Tran, Hoang}, + journal={Journal of Computational and Applied Mathematics}, + volume={281}, + pages={263--276}, + year={2015}, + publisher={Elsevier}}", "", "") struct CNLF2{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F diff --git a/lib/OrdinaryDiffEqLinear/src/OrdinaryDiffEqLinear.jl b/lib/OrdinaryDiffEqLinear/src/OrdinaryDiffEqLinear.jl index 1edc26727d..e7954b1833 100644 --- a/lib/OrdinaryDiffEqLinear/src/OrdinaryDiffEqLinear.jl +++ b/lib/OrdinaryDiffEqLinear/src/OrdinaryDiffEqLinear.jl @@ -8,7 +8,8 @@ import OrdinaryDiffEqCore: alg_order, alg_extrapolates, dt_required, OrdinaryDiffEqConstantCache, initialize!, perform_step!, @unpack, unwrap_alg, calculate_residuals!, get_fsalfirstlast, - _vec, isdtchangeable, full_cache + _vec, isdtchangeable, full_cache, + generic_solver_docstring using LinearAlgebra: mul!, I using SciMLOperators: AbstractSciMLOperator using ExponentialUtilities diff --git a/lib/OrdinaryDiffEqLinear/src/algorithms.jl b/lib/OrdinaryDiffEqLinear/src/algorithms.jl index 64a9b69b71..fb70e651c4 100644 --- a/lib/OrdinaryDiffEqLinear/src/algorithms.jl +++ b/lib/OrdinaryDiffEqLinear/src/algorithms.jl @@ -1,34 +1,172 @@ # Linear Methods +REF1 = """ +@article{celledoni2014introduction, + title={An introduction to Lie group integrators--basics, new developments and applications}, + author={Celledoni, Elena and Marthinsen, H{\aa}kon and Owren, Brynjulf}, + journal={Journal of Computational Physics}, + volume={257}, + pages={1040--1061}, + year={2014}, + publisher={Elsevier} +} +""" +REF2 = """ +@article{crouch1993numerical, + title={Numerical integration of ordinary differential equations on manifolds}, + author={Crouch, Peter E and Grossman, R}, + journal={Journal of Nonlinear Science}, + volume={3}, + pages={1--33}, + year={1993}, + publisher={Springer} +} +""" +REF3 = """ +@article{blanes2000improved, + title={Improved high order integrators based on the Magnus expansion}, + author={Blanes, Sergio and Casas, Fernando and Ros, Javier}, + journal={BIT Numerical Mathematics}, + volume={40}, + number={3}, + pages={434--450}, + year={2000}, + publisher={Springer} +} +""" +REF4 = """ +@article{blanes2009magnus, + title={The Magnus expansion and some of its applications}, + author={Blanes, Sergio and Casas, Fernando and Oteo, Jose-Angel and Ros, Jos{\'e}}, + journal={Physics reports}, + volume={470}, + number={5-6}, + pages={151--238}, + year={2009}, + publisher={Elsevier} +} +""" +REF5 = """ +@article{hairer2011solving, + title={Solving differential equations on manifolds}, + author={Hairer, Ernst}, + journal={Lecture notes}, + year={2011} +} +""" +REF6 = """ +@article{jackiewicz2000construction, + title={Construction of Runge--Kutta methods of Crouch--Grossman type of high order}, + author={Jackiewicz, Zdzislaw and Marthinsen, Arne and Owren, Brynjulf}, + journal={Advances in Computational Mathematics}, + volume={13}, + pages={405--415}, + year={2000}, + publisher={Springer} +} +""" -for Alg in [ - :MagnusMidpoint, - :MagnusLeapfrog, - :LieEuler, - :MagnusGauss4, - :MagnusNC6, - :MagnusGL6, - :MagnusGL8, - :MagnusNC8, - :MagnusGL4, - :RKMK2, - :RKMK4, - :LieRK4, - :CG2, - :CG3, - :CG4a -] - @eval struct $Alg <: OrdinaryDiffEqLinearExponentialAlgorithm - krylov::Bool - m::Int - iop::Int +for (Alg, Description, Ref) in [ + (:MagnusMidpoint, "Second order Magnus Midpoint method.", + "https://joshuagoings.com/2017/06/15/magnus/"), + (:MagnusLeapfrog, "Second order Magnus Leapfrog method.", + "https://joshuagoings.com/2017/06/15/magnus/"), + (:LieEuler, "description", REF1), + (:MagnusGauss4, + "Fourth order Magnus method approximated using a two stage Gauss quadrature.", + REF5), + (:MagnusNC6, + "Sixth order Magnus method approximated using Newton-Cotes quadrature.", REF3), + (:MagnusGL6, + "Sixth order Magnus method approximated using Gauss-Legendre quadrature.", REF3), + (:MagnusGL8, + "Eighth order Magnus method approximated using Newton-Cotes quadrature.", REF3), + (:MagnusNC8, + "Eighth order Magnus method approximated using Gauss-Legendre quadrature.", REF3), + (:MagnusGL4, + "Fourth order Magnus method approximated using Gauss-Legendre quadrature.", REF4), + (:RKMK2, "Second order Runge–Kutta–Munthe-Kaas method.", REF1), + (:RKMK4, "Fourth order Runge–Kutta–Munthe-Kaas method.", REF1), + (:LieRK4, "Fourth order Lie Runge-Kutta method.", REF1), + (:CG2, "Second order Crouch–Grossman method.", REF1), + (:CG3, "Third order Crouch-Grossman method.", REF2), + (:CG4a, " Fourth order Crouch-Grossman method.", REF6)] + @eval begin + @doc generic_solver_docstring($Description, + $(string(Alg)), + "Semilinear ODE solver", + $Ref, + """ + - `krylov`: Determines whether Krylov approximation or operator caching is used, the latter only available for semilinear problems. + `krylov=true` is much faster for larger systems and is thus recommended whenever there are >100 ODEs. + - `m`: Controls the size of Krylov subspace. + - `iop`: If not zero, determines the length of the incomplete orthogonalization procedure (IOP). + Note that if the linear operator/Jacobian is hermitian, then the Lanczos algorithm will always be used and the IOP setting is ignored. + """, + """ + krylov = false, + m = 30, + iop = 0, + """) + struct $Alg <: OrdinaryDiffEqLinearExponentialAlgorithm + krylov::Bool + m::Int + iop::Int + end end @eval $Alg(; krylov = false, m = 30, iop = 0) = $Alg(krylov, m, iop) end +@doc generic_solver_docstring("Fourth Order Adaptive Magnus method.", + "MagnusAdapt4", + "Semilinear ODE solver", + "@article{li2008adaptive, + title={Adaptive explicit Magnus numerical method for nonlinear dynamical systems}, + author={Li, Wen-cheng and Deng, Zi-chen}, + journal={Applied Mathematics and Mechanics}, + volume={29}, + number={9}, + pages={1111--1118}, + year={2008}, + publisher={Springer}}", "", "") struct MagnusAdapt4 <: OrdinaryDiffEqAdaptiveAlgorithm end +@doc generic_solver_docstring("First order method using Cayley transformations.", + "CayleyEuler", + "Semilinear ODE solver", + "@article{iserles2000lie, + title={Lie-group methods}, + author={Iserles, Arieh and Munthe-Kaas, Hans Z and Norsett, Syvert P and Zanna, Antonella}, + journal={Acta numerica}, + volume={9}, + pages={215--365}, + year={2000}, + publisher={Cambridge University Press}}", "", "") struct CayleyEuler <: OrdinaryDiffEqAlgorithm end +@doc generic_solver_docstring( + "Exact solution formula for linear, time-independent problems.", + "LinearExponential", + "Semilinear ODE solver", + "@book{strogatz2018nonlinear, + title={Nonlinear dynamics and chaos: with applications to physics, biology, chemistry, and engineering}, + author={Strogatz, Steven H}, + year={2018}, + publisher={CRC press}}", + """ + - `krylov`: + - `:off`: cache the operator beforehand. Requires Matrix(A) method defined for the operator A. + - `:simple`: uses simple Krylov approximations with fixed subspace size m. + - `:adaptive`: uses adaptive Krylov approximations with internal timestepping. + - `m`: Controls the size of Krylov subspace if `krylov=:simple`, and the initial subspace size if `krylov=:adaptive`. + - `iop`: If not zero, determines the length of the incomplete orthogonalization procedure + Note that if the linear operator/Jacobian is hermitian, + then the Lanczos algorithm will always be used and the IOP setting is ignored. + """, + """ + krylov = :off, + m = 10, + iop = 0, + """) struct LinearExponential <: OrdinaryDiffEqExponentialAlgorithm{1, false, Val{:forward}, Val{true}, nothing} krylov::Symbol diff --git a/lib/OrdinaryDiffEqLowOrderRK/src/OrdinaryDiffEqLowOrderRK.jl b/lib/OrdinaryDiffEqLowOrderRK/src/OrdinaryDiffEqLowOrderRK.jl index 1f83cc628b..9aec0897c1 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/src/OrdinaryDiffEqLowOrderRK.jl +++ b/lib/OrdinaryDiffEqLowOrderRK/src/OrdinaryDiffEqLowOrderRK.jl @@ -4,7 +4,8 @@ import OrdinaryDiffEqCore: alg_order, isfsal, beta2_default, beta1_default, alg_stability_size, ssp_coefficient, OrdinaryDiffEqAlgorithm, OrdinaryDiffEqExponentialAlgorithm, - explicit_rk_docstring, trivial_limiter!, + explicit_rk_docstring, generic_solver_docstring, + trivial_limiter!, OrdinaryDiffEqAdaptiveAlgorithm, unwrap_alg, @unpack, initialize!, perform_step!, calculate_residuals, @@ -16,7 +17,7 @@ import OrdinaryDiffEqCore: alg_order, isfsal, beta2_default, beta1_default, copyat_or_push!, AutoAlgSwitch, _ode_interpolant, _ode_interpolant!, full_cache, accept_step_controller, DerivativeOrderNotPossibleError, - has_lazy_interpolation, du_cache, u_cache, get_fsalfirstlast + du_cache, u_cache, get_fsalfirstlast using SciMLBase import MuladdMacro: @muladd import FastBroadcast: @.. diff --git a/lib/OrdinaryDiffEqLowOrderRK/src/alg_utils.jl b/lib/OrdinaryDiffEqLowOrderRK/src/alg_utils.jl index 17d1a1ee00..a7056f8338 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqLowOrderRK/src/alg_utils.jl @@ -25,7 +25,7 @@ alg_order(alg::Alshina2) = 2 alg_order(alg::Alshina3) = 3 alg_order(alg::Alshina6) = 6 -has_lazy_interpolation(alg::BS5) = true +SciMLBase.has_lazy_interpolation(alg::BS5) = true isfsal(alg::FRK65) = true isfsal(alg::RKO65) = false diff --git a/lib/OrdinaryDiffEqLowOrderRK/src/algorithms.jl b/lib/OrdinaryDiffEqLowOrderRK/src/algorithms.jl index 3e044f73b3..2c9472fb27 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqLowOrderRK/src/algorithms.jl @@ -1,14 +1,10 @@ -function Base.show(io::IO, alg::OrdinaryDiffEqAlgorithm) - print(io, String(typeof(alg).name.name), "(;") - for fieldname in fieldnames(typeof(alg)) - print(io, " ", fieldname, " = ", getfield(alg, fieldname), ",") - end - print(io, ")") -end - -""" -Euler - The canonical forward Euler method. Fixed timestep only. -""" +@doc generic_solver_docstring( + "The canonical forward Euler method. Fixed timestep only.", + "Euler", + "Explicit Runge-Kutta Method.", + """E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.""", "", "") struct Euler <: OrdinaryDiffEqAlgorithm end struct SplitEuler <: @@ -16,7 +12,10 @@ struct SplitEuler <: @doc explicit_rk_docstring( "The second order Heun's method. Uses embedded Euler method for adaptivity.", - "Heun") + "Heun", + references = """E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.""") Base.@kwdef struct Heun{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -30,7 +29,10 @@ end @doc explicit_rk_docstring( "The optimized second order midpoint method. Uses embedded Euler method for adaptivity.", - "Ralston") + "Ralston", + references = """E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.""") Base.@kwdef struct Ralston{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -44,7 +46,10 @@ end @doc explicit_rk_docstring( "The second order midpoint method. Uses embedded Euler method for adaptivity.", - "Midpoint") + "Midpoint", + references = """E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.""") Base.@kwdef struct Midpoint{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -80,7 +85,7 @@ function RK4(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A third-order, four-stage explicit FSAL Runge-Kutta method with embedded error + "A third-order, four-stage FSAL method with embedded error estimator of Bogacki and Shampine.", "BS3", references = "@article{bogacki19893, @@ -188,8 +193,7 @@ end year={1996}, publisher={Elsevier} }", - extra_keyword_description = """- `lazy`: determines if the lazy interpolant is used. - """, + extra_keyword_description = """- `lazy`: determines if the lazy interpolant is used.""", extra_keyword_default = "lazy = true") Base.@kwdef struct BS5{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -230,9 +234,17 @@ AutoDP5(alg; kwargs...) = AutoAlgSwitch(DP5(), alg; kwargs...) @doc explicit_rk_docstring("4th order Runge-Kutta method designed for periodic problems.", "Anas5", extra_keyword_description = """- `w`: a periodicity estimate, which when accurate the method becomes 5th order - (and is otherwise 4th order with less error for better estimates). - """, - extra_keyword_default = "w = 1") + (and is otherwise 4th order with less error for better estimates).""", + extra_keyword_default = "w = 1", + references = """@article{anastassi2005optimized, + title={An optimized Runge--Kutta method for the solution of orbital problems}, + author={Anastassi, ZA and Simos, TE}, + journal={Journal of Computational and Applied Mathematics}, + volume={175}, + number={1}, + pages={1--9}, + year={2005}, + publisher={Elsevier}}""") Base.@kwdef struct Anas5{StageLimiter, StepLimiter, Thread, T} <: OrdinaryDiffEqAlgorithm stage_limiter!::StageLimiter = trivial_limiter! step_limiter!::StepLimiter = trivial_limiter! @@ -244,7 +256,7 @@ function Anas5(stage_limiter!, step_limiter! = trivial_limiter!; w = 1) Anas5(stage_limiter!, step_limiter!, False(), w) end -@doc explicit_rk_docstring("5th order Explicit RK method.", "RKO5", +@doc explicit_rk_docstring("5th order method.", "RKO65", references = "Tsitouras, Ch. \"Explicit Runge–Kutta methods for starting integration of Lane–Emden problem.\" Applied Mathematics and Computation 354 (2019): 353-364. doi: https://doi.org/10.1016/j.amc.2019.02.047") @@ -260,9 +272,17 @@ end @doc explicit_rk_docstring("Zero Dissipation Runge-Kutta of 6th order.", "FRK65", extra_keyword_description = """- `omega`: a periodicity phase estimate, - when accurate this method results in zero numerical dissipation. - """, - extra_keyword_default = "omega = 0.0") + when accurate this method results in zero numerical dissipation.""", + extra_keyword_default = "omega = 0.0", + references = """@article{medvedev2018fitted, + title={Fitted modifications of Runge-Kutta pairs of orders 6 (5)}, + author={Medvedev, Maxim A and Simos, TE and Tsitouras, Ch}, + journal={Mathematical Methods in the Applied Sciences}, + volume={41}, + number={16}, + pages={6184--6194}, + year={2018}, + publisher={Wiley Online Library}}""") Base.@kwdef struct FRK65{StageLimiter, StepLimiter, Thread, T} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -276,7 +296,20 @@ function FRK65(stage_limiter!, step_limiter! = trivial_limiter!; omega = 0.0) FRK65(stage_limiter!, step_limiter!, False(), omega) end -@doc explicit_rk_docstring("TBD", "RKM") +@doc explicit_rk_docstring("""Method designed to have good stability properties + when applied to pseudospectral discretizations + of hyperbolic partial differential equaitons.""", + "RKM", + references = """@article{mead1999optimal, + title={Optimal Runge--Kutta methods for first order pseudospectral operators}, + author={Mead, JL and Renaut, RA}, + journal={Journal of Computational Physics}, + volume={152}, + number={1}, + pages={404--419}, + year={1999}, + publisher={Elsevier} + }""") Base.@kwdef struct RKM{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm stage_limiter!::StageLimiter = trivial_limiter! step_limiter!::StepLimiter = trivial_limiter! @@ -287,7 +320,7 @@ function RKM(stage_limiter!, step_limiter! = trivial_limiter!) RKM(stage_limiter!, step_limiter!, False()) end -@doc explicit_rk_docstring("5th order Explicit RK method.", "MSRK5", +@doc explicit_rk_docstring("5th order method.", "MSRK5", references = "Misha Stepanov - https://arxiv.org/pdf/2202.08443.pdf : Figure 3.") Base.@kwdef struct MSRK5{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -299,7 +332,7 @@ function MSRK5(stage_limiter!, step_limiter! = trivial_limiter!) MSRK5(stage_limiter!, step_limiter!, False()) end -@doc explicit_rk_docstring("6th order Explicit RK method.", "MSRK6", +@doc explicit_rk_docstring("6th order method.", "MSRK6", references = "Misha Stepanov - https://arxiv.org/pdf/2202.08443.pdf : Table4") Base.@kwdef struct MSRK6{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -311,7 +344,7 @@ function MSRK6(stage_limiter!, step_limiter! = trivial_limiter!) MSRK6(stage_limiter!, step_limiter!, False()) end -@doc explicit_rk_docstring("6-stage Pseudo-Symplectic Explicit RK method.", "4p7q(6)", +@doc explicit_rk_docstring("6-stage Pseudo-Symplectic method.", "PSRK4p7q6", references = "@article{Aubry1998, author = {A. Aubry and P. Chartier}, journal = {BIT Numer. Math.}, @@ -335,7 +368,7 @@ Base.@kwdef struct PSRK4p7q6{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffE thread::Thread = False() end -@doc explicit_rk_docstring("4-stage Pseudo-Symplectic Explicit RK method.", "3p5q(4)", +@doc explicit_rk_docstring("4-stage Pseudo-Symplectic method.", "PSRK3p5q4", references = "@article{Aubry1998, author = {A. Aubry and P. Chartier}, journal = {BIT Numer. Math.}, @@ -353,7 +386,7 @@ Base.@kwdef struct PSRK3p5q4{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffE thread::Thread = False() end -@doc explicit_rk_docstring("5-stage Pseudo-Symplectic Explicit RK method.", "3p6q(5)", +@doc explicit_rk_docstring("5-stage Pseudo-Symplectic method.", "PSRK3p6q5", references = "@article{Aubry1998, author = {A. Aubry and P. Chartier}, journal = {BIT Numer. Math.}, @@ -371,7 +404,7 @@ Base.@kwdef struct PSRK3p6q5{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffE thread::Thread = False() end -@doc explicit_rk_docstring("5th order Explicit RK method.", +@doc explicit_rk_docstring("5th order method.", "Stepanov5", references = "@article{Stepanov2021Embedded5, title={Embedded (4, 5) pairs of explicit 7-stage Runge–Kutta methods with FSAL property}, @@ -391,226 +424,100 @@ function Stepanov5(stage_limiter!, step_limiter! = trivial_limiter!) Stepanov5(stage_limiter!, step_limiter!, False()) end -""" - SIR54(; stage_limiter! = OrdinaryDiffEq.trivial_limiter!, - step_limiter! = OrdinaryDiffEq.trivial_limiter!, - thread = OrdinaryDiffEq.False()) - -5th order Explicit RK method suited for SIR-type epidemic models. - -Like SSPRK methods, this method also takes optional arguments `stage_limiter!` -and `step_limiter!`, where `stage_limiter!` and `step_limiter!` are functions -of the form `limiter!(u, integrator, p, t)`. - -The argument `thread` determines whether internal broadcasting on -appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`, -default) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when -Julia is started with multiple threads. - -## Reference - -@article{Kovalnogov2020RungeKuttaPS, -title={Runge–Kutta pairs suited for SIR‐type epidemic models}, -author={Vladislav N. Kovalnogov and Theodore E. Simos and Ch. Tsitouras}, -journal={Mathematical Methods in the Applied Sciences}, -year={2020}, -volume={44}, -pages={5210 - 5216} -} -""" -struct SIR54{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -function SIR54(; stage_limiter! = trivial_limiter!, step_limiter! = trivial_limiter!, - thread = False()) - SIR54{typeof(stage_limiter!), typeof(step_limiter!), typeof(thread)}(stage_limiter!, - step_limiter!, - thread) +@doc explicit_rk_docstring("5th order method suited for SIR-type epidemic models.", + "SIR54", + references = "@article{Kovalnogov2020RungeKuttaPS, + title={Runge–Kutta pairs suited for SIR‐type epidemic models}, + author={Vladislav N. Kovalnogov and Theodore E. Simos and Ch. Tsitouras}, + journal={Mathematical Methods in the Applied Sciences}, + year={2020}, + volume={44}, + pages={5210 - 5216} + }") +Base.@kwdef struct SIR54{StageLimiter, StepLimiter, Thread} <: + OrdinaryDiffEqAdaptiveAlgorithm + stage_limiter!::StageLimiter = trivial_limiter! + step_limiter!::StepLimiter = trivial_limiter! + thread::Thread = False() end - # for backwards compatibility function SIR54(stage_limiter!, step_limiter! = trivial_limiter!) - SIR54{typeof(stage_limiter!), typeof(step_limiter!), False}(stage_limiter!, - step_limiter!, - False()) -end - -function Base.show(io::IO, alg::SIR54) - print(io, "SIR54(stage_limiter! = ", alg.stage_limiter!, - ", step_limiter! = ", alg.step_limiter!, - ", thread = ", alg.thread, ")") -end - -""" - Alshina2(; stage_limiter! = OrdinaryDiffEq.trivial_limiter!, - step_limiter! = OrdinaryDiffEq.trivial_limiter!, - thread = OrdinaryDiffEq.False()) - -2nd order, 2-stage Explicit Runge-Kutta Method with optimal parameters. - -Like SSPRK methods, this method also takes optional arguments `stage_limiter!` -and `step_limiter!`, where `stage_limiter!` and `step_limiter!` are functions -of the form `limiter!(u, integrator, p, t)`. - -The argument `thread` determines whether internal broadcasting on -appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`, -default) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when -Julia is started with multiple threads. - -## Reference - -@article{Alshina2008, -doi = {10.1134/s0965542508030068}, -url = {https://doi.org/10.1134/s0965542508030068}, -year = {2008}, -month = mar, -publisher = {Pleiades Publishing Ltd}, -volume = {48}, -number = {3}, -pages = {395--405}, -author = {E. A. Alshina and E. M. Zaks and N. N. Kalitkin}, -title = {Optimal first- to sixth-order accurate Runge-Kutta schemes}, -journal = {Computational Mathematics and Mathematical Physics} -} -""" -struct Alshina2{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -function Alshina2(; stage_limiter! = trivial_limiter!, step_limiter! = trivial_limiter!, - thread = False()) - Alshina2{typeof(stage_limiter!), typeof(step_limiter!), typeof(thread)}(stage_limiter!, - step_limiter!, - thread) + SIR54(stage_limiter!, step_limiter!, False()) +end + +@doc explicit_rk_docstring("2nd order, 2-stage Method with optimal parameters.", + "Alshina2", + references = "@article{Alshina2008, + doi = {10.1134/s0965542508030068}, + url = {https://doi.org/10.1134/s0965542508030068}, + year = {2008}, + month = mar, + publisher = {Pleiades Publishing Ltd}, + volume = {48}, + number = {3}, + pages = {395--405}, + author = {E. A. Alshina and E. M. Zaks and N. N. Kalitkin}, + title = {Optimal first- to sixth-order accurate Runge-Kutta schemes}, + journal = {Computational Mathematics and Mathematical Physics} + }") +Base.@kwdef struct Alshina2{StageLimiter, StepLimiter, Thread} <: + OrdinaryDiffEqAdaptiveAlgorithm + stage_limiter!::StageLimiter = trivial_limiter! + step_limiter!::StepLimiter = trivial_limiter! + thread::Thread = False() end - +# for backwards compatibility function Alshina2(stage_limiter!, step_limiter! = trivial_limiter!) - Alshina2{typeof(stage_limiter!), typeof(step_limiter!), False}(stage_limiter!, - step_limiter!, - False()) -end - -function Base.show(io::IO, alg::Alshina2) - print(io, "Alshina2(stage_limiter! = ", alg.stage_limiter!, - ", step_limiter! = ", alg.step_limiter!, - ", thread = ", alg.thread, ")") -end - -""" - Alshina3(; stage_limiter! = OrdinaryDiffEq.trivial_limiter!, - step_limiter! = OrdinaryDiffEq.trivial_limiter!, - thread = OrdinaryDiffEq.False()) - -3rd order, 3-stage Explicit Runge-Kutta Method with optimal parameters. - -Like SSPRK methods, this method also takes optional arguments `stage_limiter!` -and `step_limiter!`, where `stage_limiter!` and `step_limiter!` are functions -of the form `limiter!(u, integrator, p, t)`. - -The argument `thread` determines whether internal broadcasting on -appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`, -default) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when -Julia is started with multiple threads. - -## Reference - -@article{Alshina2008, -doi = {10.1134/s0965542508030068}, -url = {https://doi.org/10.1134/s0965542508030068}, -year = {2008}, -month = mar, -publisher = {Pleiades Publishing Ltd}, -volume = {48}, -number = {3}, -pages = {395--405}, -author = {E. A. Alshina and E. M. Zaks and N. N. Kalitkin}, -title = {Optimal first- to sixth-order accurate Runge-Kutta schemes}, -journal = {Computational Mathematics and Mathematical Physics} -} -""" -struct Alshina3{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -function Alshina3(; stage_limiter! = trivial_limiter!, step_limiter! = trivial_limiter!, - thread = False()) - Alshina3{typeof(stage_limiter!), typeof(step_limiter!), typeof(thread)}(stage_limiter!, - step_limiter!, - thread) + Alshina2(stage_limiter!, step_limiter!, False()) +end + +@doc explicit_rk_docstring("3rd order, 3-stage Method with optimal parameters.", + "Alshina3", + references = "@article{Alshina2008, + doi = {10.1134/s0965542508030068}, + url = {https://doi.org/10.1134/s0965542508030068}, + year = {2008}, + month = mar, + publisher = {Pleiades Publishing Ltd}, + volume = {48}, + number = {3}, + pages = {395--405}, + author = {E. A. Alshina and E. M. Zaks and N. N. Kalitkin}, + title = {Optimal first- to sixth-order accurate Runge-Kutta schemes}, + journal = {Computational Mathematics and Mathematical Physics} + }") +Base.@kwdef struct Alshina3{StageLimiter, StepLimiter, Thread} <: + OrdinaryDiffEqAdaptiveAlgorithm + stage_limiter!::StageLimiter = trivial_limiter! + step_limiter!::StepLimiter = trivial_limiter! + thread::Thread = False() end - +# for backwards compatibility function Alshina3(stage_limiter!, step_limiter! = trivial_limiter!) - Alshina3{typeof(stage_limiter!), typeof(step_limiter!), False}(stage_limiter!, - step_limiter!, - False()) -end - -function Base.show(io::IO, alg::Alshina3) - print(io, "Alshina3(stage_limiter! = ", alg.stage_limiter!, - ", step_limiter! = ", alg.step_limiter!, - ", thread = ", alg.thread, ")") -end - -""" - Alshina6(; stage_limiter! = OrdinaryDiffEq.trivial_limiter!, - step_limiter! = OrdinaryDiffEq.trivial_limiter!, - thread = OrdinaryDiffEq.False()) - -6th order, 7-stage Explicit Runge-Kutta Method with optimal parameters. - -Like SSPRK methods, this method also takes optional arguments `stage_limiter!` -and `step_limiter!`, where `stage_limiter!` and `step_limiter!` are functions -of the form `limiter!(u, integrator, p, t)`. - -The argument `thread` determines whether internal broadcasting on -appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`, -default) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when -Julia is started with multiple threads. - -## Reference - -@article{Alshina2008, -doi = {10.1134/s0965542508030068}, -url = {https://doi.org/10.1134/s0965542508030068}, -year = {2008}, -month = mar, -publisher = {Pleiades Publishing Ltd}, -volume = {48}, -number = {3}, -pages = {395--405}, -author = {E. A. Alshina and E. M. Zaks and N. N. Kalitkin}, -title = {Optimal first- to sixth-order accurate Runge-Kutta schemes}, -journal = {Computational Mathematics and Mathematical Physics} -} -""" -struct Alshina6{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -function Alshina6(; stage_limiter! = trivial_limiter!, step_limiter! = trivial_limiter!, - thread = False()) - Alshina6{typeof(stage_limiter!), typeof(step_limiter!), typeof(thread)}(stage_limiter!, - step_limiter!, - thread) + Alshina3(stage_limiter!, step_limiter!, False()) +end + +@doc explicit_rk_docstring("6th order, 7-stage Method with optimal parameters.", + "Alshina6", + references = "@article{Alshina2008, + doi = {10.1134/s0965542508030068}, + url = {https://doi.org/10.1134/s0965542508030068}, + year = {2008}, + month = mar, + publisher = {Pleiades Publishing Ltd}, + volume = {48}, + number = {3}, + pages = {395--405}, + author = {E. A. Alshina and E. M. Zaks and N. N. Kalitkin}, + title = {Optimal first- to sixth-order accurate Runge-Kutta schemes}, + journal = {Computational Mathematics and Mathematical Physics} + }") +Base.@kwdef struct Alshina6{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm + stage_limiter!::StageLimiter = trivial_limiter! + step_limiter!::StepLimiter = trivial_limiter! + thread::Thread = False() end - +# for backwards compatibility function Alshina6(stage_limiter!, step_limiter! = trivial_limiter!) - Alshina6{typeof(stage_limiter!), typeof(step_limiter!), False}(stage_limiter!, - step_limiter!, - False()) -end - -function Base.show(io::IO, alg::Alshina6) - print(io, "Alshina6(stage_limiter! = ", alg.stage_limiter!, - ", step_limiter! = ", alg.step_limiter!, - ", thread = ", alg.thread, ")") + Alshina6(stage_limiter!, step_limiter!, False()) end diff --git a/lib/OrdinaryDiffEqLowStorageRK/Project.toml b/lib/OrdinaryDiffEqLowStorageRK/Project.toml index 75053fd953..9ca09e32d2 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/Project.toml +++ b/lib/OrdinaryDiffEqLowStorageRK/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqLowStorageRK" uuid = "b0944070-b475-4768-8dec-fb6eb410534d" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.2.1" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/OrdinaryDiffEqLowStorageRK.jl b/lib/OrdinaryDiffEqLowStorageRK/src/OrdinaryDiffEqLowStorageRK.jl index 867d79097d..8822c04e18 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/OrdinaryDiffEqLowStorageRK.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/OrdinaryDiffEqLowStorageRK.jl @@ -103,6 +103,6 @@ export ORK256, CarpenterKennedy2N54, SHLDDRK64, HSLDDRK64, DGLDDRK73_C, DGLDDRK8 ParsaniKetchesonDeconinck3S53, ParsaniKetchesonDeconinck3S173, ParsaniKetchesonDeconinck3S94, ParsaniKetchesonDeconinck3S184, ParsaniKetchesonDeconinck3S105, ParsaniKetchesonDeconinck3S205, - RDPK3Sp35, RDPK3SpFSAL35, RDPK3Sp49, RDPK3SpFSAL49, RDPK3Sp510, RDPK3SpFSAL510, + RDPK3Sp35, RDPK3SpFSAL35, RDPK3Sp49, RDPK3SpFSAL49, RDPK3Sp510, RDPK3SpFSAL510, RK46NL, SHLDDRK_2N, SHLDDRK52 end diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl b/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl index d0f69f7711..226212fd42 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl @@ -1,5 +1,5 @@ @doc explicit_rk_docstring( - "A second-order, five-stage explicit Runge-Kutta method for wave propagation + "A second-order, five-stage method for wave propagation equations. Fixed timestep only.", "ORK256", references = "Matteo Bernardini, Sergio Pirozzoli. A General Strategy for the Optimization of Runge-Kutta Schemes for Wave @@ -51,34 +51,8 @@ function DGLDDRK73_C(stage_limiter!, step_limiter! = trivial_limiter!; williamson_condition) end -@doc explicit_rk_docstring("TBD", "SHLDDRK_2N") -Base.@kwdef struct SHLDDRK_2N{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm - stage_limiter!::StageLimiter = trivial_limiter! - step_limiter!::StepLimiter = trivial_limiter! - thread::Thread = False() -end -# for backwards compatibility -function SHLDDRK_2N(stage_limiter!, step_limiter! = trivial_limiter!) - SHLDDRK_2N(stage_limiter!, - step_limiter!, - False()) -end - -@doc explicit_rk_docstring("TBD", "SHLDDRK52") -Base.@kwdef struct SHLDDRK52{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm - stage_limiter!::StageLimiter = trivial_limiter! - step_limiter!::StepLimiter = trivial_limiter! - thread::Thread = False() -end -# for backwards compatibility -function SHLDDRK52(stage_limiter!, step_limiter! = trivial_limiter!) - SHLDDRK52(stage_limiter!, - step_limiter!, - False()) -end - @doc explicit_rk_docstring( - "A fourth-order, five-stage explicit low-storage method of Carpenter and Kennedy + "A fourth-order, five-stage low-storage method of Carpenter and Kennedy (free 3rd order Hermite interpolant). Fixed timestep only. Designed for hyperbolic PDEs (stability properties).", "CarpenterKennedy2N54", @@ -251,7 +225,7 @@ function DGLDDRK84_F(stage_limiter!, step_limiter! = trivial_limiter!; end @doc explicit_rk_docstring( - "A fourth-order, six-stage explicit low-storage method. Fixed timestep only.", + "A fourth-order, six-stage low-storage method. Fixed timestep only.", "SHLDDRK64", references = "D. Stanescu, W. G. Habashi. 2N-Storage Low Dissipation and Dispersion Runge-Kutta Schemes for Computational @@ -468,7 +442,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 4-stage, third order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK43_2") +", "CKLLSRK43_2", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK43_2{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -485,7 +468,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 5-stage, fourth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK54_3C") +", "CKLLSRK54_3C", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK54_3C{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -502,7 +494,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 9-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK95_4S") +", "CKLLSRK95_4S", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK95_4S{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -519,7 +520,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 9-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK95_4C") +", "CKLLSRK95_4C", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK95_4C{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -536,7 +546,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 9-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK95_4M") +", "CKLLSRK95_4M", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK95_4M{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -553,7 +572,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 5-stage, fourth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK54_3C_3R") +", "CKLLSRK54_3C_3R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK54_3C_3R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -570,7 +598,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 5-stage, fourth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK54_3M_3R") +", "CKLLSRK54_3M_3R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK54_3M_3R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -587,7 +624,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 5-stage, fourth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK54_3N_3R") +", "CKLLSRK54_3N_3R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK54_3N_3R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -604,7 +650,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 8-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK85_4C_3R") +", "CKLLSRK85_4C_3R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK85_4C_3R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -621,7 +676,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 8-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK85_4M_3R") +", "CKLLSRK85_4M_3R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK85_4M_3R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -638,7 +702,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 8-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK85_4P_3R") +", "CKLLSRK85_4P_3R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK85_4P_3R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -655,7 +728,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 5-stage, fourth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK54_3N_4R") +", "CKLLSRK54_3N_4R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK54_3N_4R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -672,7 +754,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 5-stage, fourth order low-storage scheme, optimized for compressible Navier–Stokes equations. -", "CKLLSRK54_3M_4R") +", "CKLLSRK54_3M_4R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK54_3M_4R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -688,7 +779,16 @@ end @doc explicit_rk_docstring( "6-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations.", - "CKLLSRK65_4M_4R") + "CKLLSRK65_4M_4R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK65_4M_4R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -705,7 +805,16 @@ end @doc explicit_rk_docstring( "Low-Storage Method 8-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations.", - "CKLLSRK85_4FM_4R") + "CKLLSRK85_4FM_4R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK85_4FM_4R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -722,7 +831,16 @@ end @doc explicit_rk_docstring( "CKLLSRK75_4M_5R: Low-Storage Method 7-stage, fifth order low-storage scheme, optimized for compressible Navier–Stokes equations.", - "CKLLSRK75_4M_5R") + "CKLLSRK75_4M_5R", + references = """@article{kennedy2000low, + title={Low-storage, explicit Runge--Kutta schemes for the compressible Navier--Stokes equations}, + author={Kennedy, Christopher A and Carpenter, Mark H and Lewis, R Michael}, + journal={Applied numerical mathematics}, + volume={35}, + number={3}, + pages={177--219}, + year={2000}, + publisher={Elsevier}}""") Base.@kwdef struct CKLLSRK75_4M_5R{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAdaptiveAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -737,7 +855,7 @@ function CKLLSRK75_4M_5R(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A third-order, five-stage explicit Runge-Kutta method with embedded error estimator + "A third-order, five-stage method with embedded error estimator designed for spectral element discretizations of compressible fluid mechanics.", "RDPK3Sp35", references = "Ranocha, Dalcin, Parsani, Ketcheson (2021) @@ -757,7 +875,7 @@ function RDPK3Sp35(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A third-order, five-stage explicit Runge-Kutta method with embedded error estimator + "A third-order, five-stage method with embedded error estimator using the FSAL property designed for spectral element discretizations of compressible fluid mechanics.", "RDPK3SpFSAL35", @@ -779,7 +897,7 @@ function RDPK3SpFSAL35(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A fourth-order, nine-stage explicit Runge-Kutta method with embedded error estimator + "A fourth-order, nine-stage method with embedded error estimator designed for spectral element discretizations of compressible fluid mechanics.", "RDPK3Sp49", references = "Ranocha, Dalcin, Parsani, Ketcheson (2021) @@ -799,7 +917,7 @@ function RDPK3Sp49(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A fourth-order, nine-stage explicit Runge-Kutta method with embedded error estimator + "A fourth-order, nine-stage method with embedded error estimator using the FSAL property designed for spectral element discretizations of compressible fluid mechanics.", "RDPK3SpFSAL49", @@ -821,7 +939,7 @@ function RDPK3SpFSAL49(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A fifth-order, ten-stage explicit Runge-Kutta method with embedded error estimator + "A fifth-order, ten-stage method with embedded error estimator designed for spectral element discretizations of compressible fluid mechanics.", "RDPK3Sp510", references = "Ranocha, Dalcin, Parsani, Ketcheson (2021) @@ -841,7 +959,7 @@ function RDPK3Sp510(stage_limiter!, step_limiter! = trivial_limiter!) end @doc explicit_rk_docstring( - "A fifth-order, ten-stage explicit Runge-Kutta method with embedded error estimator + "A fifth-order, ten-stage method with embedded error estimator using the FSAL property designed for spectral element discretizations of compressible fluid mechanics.", "RDPK3SpFSAL510", @@ -914,4 +1032,50 @@ function NDBLSRK134(stage_limiter!, step_limiter! = trivial_limiter!; williamson_condition) end -#SSP Optimized Runge-Kutta Methods \ No newline at end of file +@doc explicit_rk_docstring( + "Low dissipation and dispersion Runge-Kutta schemes for computational acoustics", + "SHLDDRK_2N", + references = "@article{stanescu19982n, + title={2N-storage low dissipation and dispersion Runge-Kutta schemes for computational acoustics}, + author={Stanescu, D and Habashi, WG}, + journal={Journal of Computational Physics}, + volume={143}, + number={2}, + pages={674--681}, + year={1998}, + publisher={Elsevier}}") +Base.@kwdef struct SHLDDRK_2N{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm + stage_limiter!::StageLimiter = trivial_limiter! + step_limiter!::StepLimiter = trivial_limiter! + thread::Thread = False() +end +# for backwards compatibility +function SHLDDRK_2N(stage_limiter!, step_limiter! = trivial_limiter!) + SHLDDRK_2N(stage_limiter!, + step_limiter!, + False()) +end + +@doc explicit_rk_docstring( + "Low dissipation and dispersion Runge-Kutta schemes for computational acoustics", + "SHLDDRK52", + references = "@article{stanescu19982n, + title={2N-storage low dissipation and dispersion Runge-Kutta schemes for computational acoustics}, + author={Stanescu, D and Habashi, WG}, + journal={Journal of Computational Physics}, + volume={143}, + number={2}, + pages={674--681}, + year={1998}, + publisher={Elsevier}}") +Base.@kwdef struct SHLDDRK52{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm + stage_limiter!::StageLimiter = trivial_limiter! + step_limiter!::StepLimiter = trivial_limiter! + thread::Thread = False() +end +# for backwards compatibility +function SHLDDRK52(stage_limiter!, step_limiter! = trivial_limiter!) + SHLDDRK52(stage_limiter!, + step_limiter!, + False()) +end diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl index 6c813472d3..41a85c5726 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl @@ -273,7 +273,8 @@ function alg_cache(alg::SHLDDRK_2N, u, rate_prototype, ::Type{uEltypeNoUnits}, alg.step_limiter!, alg.thread) end -@cache struct SHLDDRK52Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: LowStorageRKMutableCache +@cache struct SHLDDRK52Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + LowStorageRKMutableCache u::uType uprev::uType k::rateType diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index 8805ca5b2f..5344dc296a 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -33,15 +33,13 @@ end integrator.u = u end -get_fsalfirstlast(cache::LowStorageRK2NCache, u) = (cache.k, cache.k) +get_fsalfirstlast(cache::LowStorageRK2NCache, u) = (nothing, nothing) function initialize!(integrator, cache::LowStorageRK2NCache) @unpack k, tmp, williamson_condition = cache integrator.kshortsize = 1 resize!(integrator.k, integrator.kshortsize) integrator.k[1] = k - integrator.fsalfirst = k # used for get_du - integrator.fsallast = k integrator.f(k, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) end @@ -1164,4 +1162,4 @@ end f(k, u, p, t + dt) end -end \ No newline at end of file +end diff --git a/lib/OrdinaryDiffEqNordsieck/src/OrdinaryDiffEqNordsieck.jl b/lib/OrdinaryDiffEqNordsieck/src/OrdinaryDiffEqNordsieck.jl index ae0b0ea0d1..fa8b873e42 100644 --- a/lib/OrdinaryDiffEqNordsieck/src/OrdinaryDiffEqNordsieck.jl +++ b/lib/OrdinaryDiffEqNordsieck/src/OrdinaryDiffEqNordsieck.jl @@ -10,7 +10,8 @@ import OrdinaryDiffEqCore: alg_order, alg_adaptive_order, qsteady_max_default, step_accept_controller!, step_reject_controller!, calculate_residuals, calculate_residuals!, get_current_adaptive_order, get_fsalfirstlast, - ode_interpolant, ode_interpolant!, trivial_limiter! + ode_interpolant, ode_interpolant!, trivial_limiter!, + generic_solver_docstring using MuladdMacro, FastBroadcast, RecursiveArrayTools import LinearAlgebra: rmul! import Static: False diff --git a/lib/OrdinaryDiffEqNordsieck/src/algorithms.jl b/lib/OrdinaryDiffEqNordsieck/src/algorithms.jl index 37aa0ced98..c8e49d97a7 100644 --- a/lib/OrdinaryDiffEqNordsieck/src/algorithms.jl +++ b/lib/OrdinaryDiffEqNordsieck/src/algorithms.jl @@ -1,9 +1,20 @@ # Adams/BDF methods in Nordsieck forms +@doc generic_solver_docstring( + """An adaptive 5th order fixed-leading coefficient Adams method in Nordsieck form. +!!! warning "Experimental" + `AN5` is experimental, the solver `VCABM` is generally preferred. +""", + "AN5", + "Adaptive step size Adams explicit Method", + "", + "", + "") +struct AN5 <: OrdinaryDiffEqAdaptiveAlgorithm end """ -AN5: Adaptive step size Adams explicit Method -An adaptive 5th order fixed-leading coefficient Adams method in Nordsieck form. +!!! warning "Experimental" + + `JVODE` is experimental, the solver `VCABM` is generally preferred. """ -struct AN5 <: OrdinaryDiffEqAdaptiveAlgorithm end struct JVODE{bType, aType} <: OrdinaryDiffEqAdamsVarOrderVarStepAlgorithm algorithm::Symbol bias1::bType @@ -16,5 +27,15 @@ function JVODE(algorithm = :Adams; bias1 = 6, bias2 = 6, bias3 = 10, addon = 1 // 10^6) JVODE(algorithm, bias1, bias2, bias3, addon) end +""" +!!! warning "Experimental" + + `JVODE` is experimental, the solver `VCABM` is generally preferred. +""" JVODE_Adams(; kwargs...) = JVODE(:Adams; kwargs...) +""" +!!! warning "Experimental" + + `JVODE` is experimental, the solver `FBDF` is generally preferred. +""" JVODE_BDF(; kwargs...) = JVODE(:BDF; kwargs...) diff --git a/lib/OrdinaryDiffEqPDIRK/Project.toml b/lib/OrdinaryDiffEqPDIRK/Project.toml index 115a797565..2e1b6bb3b4 100644 --- a/lib/OrdinaryDiffEqPDIRK/Project.toml +++ b/lib/OrdinaryDiffEqPDIRK/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqPDIRK" uuid = "5dd0a6cf-3d4b-4314-aa06-06d4e299bc89" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.1.1" [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" diff --git a/lib/OrdinaryDiffEqPDIRK/src/OrdinaryDiffEqPDIRK.jl b/lib/OrdinaryDiffEqPDIRK/src/OrdinaryDiffEqPDIRK.jl index ccdf6a9131..18a4e56205 100644 --- a/lib/OrdinaryDiffEqPDIRK/src/OrdinaryDiffEqPDIRK.jl +++ b/lib/OrdinaryDiffEqPDIRK/src/OrdinaryDiffEqPDIRK.jl @@ -5,7 +5,7 @@ import OrdinaryDiffEqCore: isfsal, alg_order, _unwrap_val, OrdinaryDiffEqMutableCache, constvalue, alg_cache, uses_uprev, @unpack, unwrap_alg, @cache, DEFAULT_PRECS, @threaded, initialize!, perform_step!, isthreaded, - full_cache, get_fsalfirstlast + full_cache, get_fsalfirstlast, differentiation_rk_docstring import StaticArrays: SVector import MuladdMacro: @muladd import FastBroadcast: @.. diff --git a/lib/OrdinaryDiffEqPDIRK/src/algorithms.jl b/lib/OrdinaryDiffEqPDIRK/src/algorithms.jl index 264feb64a0..0e93763cfd 100644 --- a/lib/OrdinaryDiffEqPDIRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqPDIRK/src/algorithms.jl @@ -1,10 +1,26 @@ -################################################################################ - -################################################# -""" -PDIRK44: Parallel Diagonally Implicit Runge-Kutta Method -A 2 processor 4th order diagonally non-adaptive implicit method. -""" +@doc differentiation_rk_docstring( + "A 2 processor 4th order diagonally non-adaptive implicit method.", + "PDIRK44", + "Parallel Diagonally Implicit Runge-Kutta Method."; + references = """"@article{iserles1990theory, + title={On the theory of parallel Runge—Kutta methods}, + author={Iserles, Arieh and Norrsett, SP}, + journal={IMA Journal of numerical Analysis}, + volume={10}, + number={4}, + pages={463--488}, + year={1990}, + publisher={Oxford University Press}}""", + extra_keyword_description = """ + - `nlsolve`: TBD, + - `extrapolant`: TBD, + - `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads. + """, + extra_keyword_default = """ + nlsolve = NLNewton(), + extrapolant = :constant, + thread = OrdinaryDiffEq.True(), + """) struct PDIRK44{CS, AD, F, F2, P, FDT, ST, CJ, TO} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F diff --git a/lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl b/lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl index 2cbbbf828f..2818424697 100644 --- a/lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl +++ b/lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl @@ -8,7 +8,7 @@ end # Non-FSAL -get_fsalfirstlast(cache::PDIRK44Cache, u) = (cache.u, cache.uprev) +get_fsalfirstlast(cache::PDIRK44Cache, u) = (nothing, nothing) struct PDIRK44ConstantCache{N, TabType} <: OrdinaryDiffEqConstantCache nlsolver::N diff --git a/lib/OrdinaryDiffEqPRK/src/OrdinaryDiffEqPRK.jl b/lib/OrdinaryDiffEqPRK/src/OrdinaryDiffEqPRK.jl index e2d35fe635..437d2769d9 100644 --- a/lib/OrdinaryDiffEqPRK/src/OrdinaryDiffEqPRK.jl +++ b/lib/OrdinaryDiffEqPRK/src/OrdinaryDiffEqPRK.jl @@ -4,7 +4,7 @@ import OrdinaryDiffEqCore: OrdinaryDiffEqAlgorithm, alg_order, OrdinaryDiffEqMut OrdinaryDiffEqConstantCache, constvalue, @unpack, @cache, alg_cache, get_fsalfirstlast, unwrap_alg, perform_step!, @threaded, initialize!, isthreaded, - full_cache + full_cache, generic_solver_docstring import MuladdMacro: @muladd import FastBroadcast: @.. using Polyester diff --git a/lib/OrdinaryDiffEqPRK/src/algorithms.jl b/lib/OrdinaryDiffEqPRK/src/algorithms.jl index 81cdf20782..5d69e69f29 100644 --- a/lib/OrdinaryDiffEqPRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqPRK/src/algorithms.jl @@ -1,10 +1,17 @@ -""" -KuttaPRK2p5: Parallel Explicit Runge-Kutta Method -A 5 parallel, 2 processor explicit Runge-Kutta method of 5th order. - -These methods utilize multithreading on the f calls to parallelize the problem. -This requires that simultaneous calls to f are thread-safe. -""" +@doc generic_solver_docstring("A 5 parallel, 2 processor method of 5th order.", + "KuttaPRK2p5", + "Explicit Runge-Kutta Method", + """@article{jackson1995potential, + title={The potential for parallelism in Runge--Kutta methods. Part 1: RK formulas in standard form}, + author={Jackson, Kenneth R and Norsett, Syvert Paul}, + journal={SIAM journal on numerical analysis}, + volume={32}, + number={1}, + pages={49--82}, + year={1995}, + publisher={SIAM}}""", + "- `thread`: determines whether internal broadcasting on appropriate CPU arrays should be serial (`thread = OrdinaryDiffEq.False()`) or use multiple threads (`thread = OrdinaryDiffEq.True()`) when Julia is started with multiple threads.", + "thread = OrdinaryDiffEq.True(),") Base.@kwdef struct KuttaPRK2p5{TO} <: OrdinaryDiffEqAlgorithm threading::TO = true end diff --git a/lib/OrdinaryDiffEqRKN/src/OrdinaryDiffEqRKN.jl b/lib/OrdinaryDiffEqRKN/src/OrdinaryDiffEqRKN.jl index 4385ace2a7..953bc58ec6 100644 --- a/lib/OrdinaryDiffEqRKN/src/OrdinaryDiffEqRKN.jl +++ b/lib/OrdinaryDiffEqRKN/src/OrdinaryDiffEqRKN.jl @@ -11,7 +11,8 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, alg_cache, _vec, _reshape, @cache, isfsal, full_cache, constvalue, _unwrap_val, _ode_interpolant, get_fsalfirstlast, - trivial_limiter!, _ode_interpolant!, _ode_addsteps! + trivial_limiter!, _ode_interpolant!, _ode_addsteps!, + generic_solver_docstring using FastBroadcast, Polyester, MuladdMacro, RecursiveArrayTools using DiffEqBase: @def, @tight_loop_macros import OrdinaryDiffEqCore diff --git a/lib/OrdinaryDiffEqRKN/src/algorithms.jl b/lib/OrdinaryDiffEqRKN/src/algorithms.jl index 7c9de04976..3c8bb658af 100644 --- a/lib/OrdinaryDiffEqRKN/src/algorithms.jl +++ b/lib/OrdinaryDiffEqRKN/src/algorithms.jl @@ -1,341 +1,243 @@ -""" - IRKN3 - -Improved Runge-Kutta-Nyström method of order three, which minimizes the amount of evaluated functions in each step. Fixed time steps only. - -Second order ODE should not depend on the first derivative. - -## References - -@article{rabiei2012numerical, -title={Numerical Solution of Second-Order Ordinary Differential Equations by Improved Runge-Kutta Nystrom Method}, -author={Rabiei, Faranak and Ismail, Fudziah and Norazak, S and Emadi, Saeid}, -publisher={Citeseer} -} -""" +@doc generic_solver_docstring( + "Method of order three, which minimizes the amount of evaluated functions in each step. Fixed time steps only. +Second order ODE should not depend on the first derivative.", + "IRKN3", + "Improved Runge-Kutta-Nyström method", + "@article{rabiei2012numerical, + title={Numerical Solution of Second-Order Ordinary Differential Equations by Improved Runge-Kutta Nystrom Method}, + author={Rabiei, Faranak and Ismail, Fudziah and Norazak, S and Emadi, Saeid}, + publisher={Citeseer}}", "", "") struct IRKN3 <: OrdinaryDiffEqPartitionedAlgorithm end -""" - Nystrom4 - -A 4th order explicit Runge-Kutta-Nyström method which can be applied directly on second order ODEs. Can only be used with fixed time steps. - +@doc generic_solver_docstring( + "A 4th order explicit method which can be applied directly on second order ODEs. +Can only be used with fixed time steps. In case the ODE Problem is not dependent on the first derivative consider using -[`Nystrom4VelocityIndependent`](@ref) to increase performance. - -## References - -E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. -Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, -Springer-Verlag. -""" +[`Nystrom4VelocityIndependent`](@ref) to increase performance.", + "Nystrom4", + "Improved Runge-Kutta-Nyström method", + "E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.", "", "") struct Nystrom4 <: OrdinaryDiffEqPartitionedAlgorithm end -""" - FineRKN4() - -A 4th order explicit Runge-Kutta-Nyström method which can be applied directly to second order ODEs. -In particular, this method allows the acceleration equation to depend on the velocity. - -## References - -``` -@article{fine1987low, - title={Low order practical {R}unge-{K}utta-{N}ystr{\"o}m methods}, - author={Fine, Jerry Michael}, - journal={Computing}, - volume={38}, - number={4}, - pages={281--297}, - year={1987}, - publisher={Springer} -} -``` -""" +@doc generic_solver_docstring( + "A 4th order explicit method which can be applied directly to second order ODEs. +In particular, this method allows the acceleration equation to depend on the velocity.", + "FineRKN4", + "Improved Runge-Kutta-Nyström method", + "@article{fine1987low, + title={Low order practical {R}unge-{K}utta-{N}ystr{\"o}m methods}, + author={Fine, Jerry Michael}, + journal={Computing}, + volume={38}, + number={4}, + pages={281--297}, + year={1987}, + publisher={Springer}}", "", "") struct FineRKN4 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - FineRKN5() - -A 5th order explicit Runge-Kutta-Nyström method which can be applied directly to second order ODEs. -In particular, this method allows the acceleration equation to depend on the velocity. - -## References - -``` -@article{fine1987low, - title={Low order practical {R}unge-{K}utta-{N}ystr{\"o}m methods}, - author={Fine, Jerry Michael}, - journal={Computing}, - volume={38}, - number={4}, - pages={281--297}, - year={1987}, - publisher={Springer} -} -``` -""" +@doc generic_solver_docstring( + "A 5th order explicit method which can be applied directly to second order ODEs. +In particular, this method allows the acceleration equation to depend on the velocity.", + "FineRKN5", + "Improved Runge-Kutta-Nyström method", + "@article{fine1987low, + title={Low order practical {R}unge-{K}utta-{N}ystr{\"o}m methods}, + author={Fine, Jerry Michael}, + journal={Computing}, + volume={38}, + number={4}, + pages={281--297}, + year={1987}, + publisher={Springer}}", "", "") struct FineRKN5 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - Nystrom4VelocityIdependent - -A 4th order explicit Runkge-Kutta-Nyström method. Used directly on second order ODEs, where the acceleration is independent from velocity (ODE Problem is not dependent on the first derivative). - -More efficient then [`Nystrom4`](@ref) on velocity independent problems, since less evaluations are needed. - -Fixed time steps only. - -## References - -E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. -Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, -Springer-Verlag. -""" +@doc generic_solver_docstring( + "A 4th order explicit method. +Used directly on second order ODEs, where the acceleration is independent from velocity +(ODE Problem is not dependent on the first derivative).", + "Nystrom4VelocityIndependent", + "Improved Runge-Kutta-Nyström method", + "E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.", "", "") struct Nystrom4VelocityIndependent <: OrdinaryDiffEqPartitionedAlgorithm end -""" - IRKN4 - -Improves Runge-Kutta-Nyström method of order four, which minimizes the amount of evaluated functions in each step. Fixed time steps only. - -Second order ODE should not be dependent on the first derivative. - -Recommended for smooth problems with expensive functions to evaluate. - -## References - -@article{rabiei2012numerical, -title={Numerical Solution of Second-Order Ordinary Differential Equations by Improved Runge-Kutta Nystrom Method}, -author={Rabiei, Faranak and Ismail, Fudziah and Norazak, S and Emadi, Saeid}, -publisher={Citeseer} -} -""" +@doc generic_solver_docstring("Improves Runge-Kutta-Nyström method of order four, + which minimizes the amount of evaluated functions in each step. + Fixed time steps only. + Second order ODE should not be dependent on the first derivative. + Recommended for smooth problems with expensive functions to evaluate.", + "IRKN4", + "Improved Runge-Kutta-Nyström method", + "@article{rabiei2012numerical, + title={Numerical Solution of Second-Order Ordinary Differential Equations by Improved Runge-Kutta Nystrom Method}, + author={Rabiei, Faranak and Ismail, Fudziah and Norazak, S and Emadi, Saeid}, + publisher={Citeseer}}", "", "") struct IRKN4 <: OrdinaryDiffEqPartitionedAlgorithm end -""" - Nystrom5VelocityIndependent - -A 5th order explicit Runkge-Kutta-Nyström method. Used directly on second order ODEs, where the acceleration is independent from velocity (ODE Problem is not dependent on the first derivative). -Fixed time steps only. - -## References - -E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. -Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, -Springer-Verlag. -""" +@doc generic_solver_docstring( + "A 5th order explicit method. +Used directly on second order ODEs, where the acceleration is independent from velocity +(ODE Problem is not dependent on the first derivative).", + "Nystrom5VelocityIndependent", + "Improved Runge-Kutta-Nyström method", + "E. Hairer, S.P. Norsett, G. Wanner, (1993) Solving Ordinary Differential Equations I. + Nonstiff Problems. 2nd Edition. Springer Series in Computational Mathematics, + Springer-Verlag.", "", "") struct Nystrom5VelocityIndependent <: OrdinaryDiffEqPartitionedAlgorithm end -""" - DPRKN4 - -4th order explicit Runge-Kutta-Nyström methods. The second order ODE should not depend on the first derivative. - -## References - -@article{Dormand1987FamiliesOR, -title={Families of Runge-Kutta-Nystrom Formulae}, -author={J. R. Dormand and Moawwad E. A. El-Mikkawy and P. J. Prince}, -journal={Ima Journal of Numerical Analysis}, -year={1987}, -volume={7}, -pages={235-250} -} -""" +@doc generic_solver_docstring("4th order explicit method. + The second order ODE should not depend on the first derivative.", + "DPRKN4", + "Improved Runge-Kutta-Nyström method", + "@article{Dormand1987FamiliesOR, + title={Families of Runge-Kutta-Nystrom Formulae}, + author={J. R. Dormand and Moawwad E. A. El-Mikkawy and P. J. Prince}, + journal={Ima Journal of Numerical Analysis}, + year={1987}, + volume={7}, + pages={235-250}}", "", "") struct DPRKN4 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - DPRKN5 - -5th order explicit Runge-Kutta-Nyström mehod. The second order ODE should not depend on the first derivative. - -## References - -@article{Bettis1973ARN, -title={A Runge-Kutta Nystrom algorithm}, -author={Dale G. Bettis}, -journal={Celestial mechanics}, -year={1973}, -volume={8}, -pages={229-233}, -publisher={Springer} -} -""" +@doc generic_solver_docstring("5th order explicit method. + The second order ODE should not depend on the first derivative.", + "DPRKN5", + "Improved Runge-Kutta-Nyström method", + "@article{Bettis1973ARN, + title={A Runge-Kutta Nystrom algorithm}, + author={Dale G. Bettis}, + journal={Celestial mechanics}, + year={1973}, + volume={8}, + pages={229-233}, + publisher={Springer}}", "", "") struct DPRKN5 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - DPRKN6 - -6th order explicit Runge-Kutta-Nyström method. The second order ODE should not depend on the first derivative. Free 6th order interpolant. - -## References - -@article{dormand1987runge, -title={Runge-kutta-nystrom triples}, -author={Dormand, JR and Prince, PJ}, -journal={Computers \\& Mathematics with Applications}, -volume={13}, -number={12}, -pages={937--949}, -year={1987}, -publisher={Elsevier} -} -""" +@doc generic_solver_docstring( + "6th order explicit method. +The second order ODE should not depend on the first derivative. Free 6th order interpolant", + "DPRKN6", + "Improved Runge-Kutta-Nyström method", + "@article{Dormand1987FamiliesOR, + title={Families of Runge-Kutta-Nystrom Formulae}, + author={J. R. Dormand and Moawwad E. A. El-Mikkawy and P. J. Prince}, + journal={Ima Journal of Numerical Analysis}, + year={1987}, + volume={7}, + pages={235-250}}", "", "") struct DPRKN6 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - DPRKN6FM - -6th order explicit Runge-Kutta-Nyström method. The second order ODE should not depend on the first derivative. - -Compared to [`DPRKN6`](@ref), this method has smaller truncation error coefficients which leads to performance gain -when only the main solution points are considered. - -## References - -@article{Dormand1987FamiliesOR, -title={Families of Runge-Kutta-Nystrom Formulae}, -author={J. R. Dormand and Moawwad E. A. El-Mikkawy and P. J. Prince}, -journal={Ima Journal of Numerical Analysis}, -year={1987}, -volume={7}, -pages={235-250} -} -""" +@doc generic_solver_docstring("6th order explicit method. + The second order ODE should not depend on the first derivative. + Compared to [`DPRKN6`](@ref), this method has smaller truncation error coefficients + which leads to performance gain when only the main solution points are considered.", + "DPRKN6FM", + "Improved Runge-Kutta-Nyström method", + "@article{Dormand1987FamiliesOR, + title={Families of Runge-Kutta-Nystrom Formulae}, + author={J. R. Dormand and Moawwad E. A. El-Mikkawy and P. J. Prince}, + journal={Ima Journal of Numerical Analysis}, + year={1987}, + volume={7}, + pages={235-250}}", "", "") struct DPRKN6FM <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - DPRKN8 - -8th order explicit Runge-Kutta-Nyström method. The second order ODE should not depend on the first derivative. - -Not as efficient as [`DPRKN12`](@ref) when high accuracy is needed, however this solver is competitive with -[`DPRKN6`](@ref) at lax tolerances and, depending on the problem, might be a good option between performance and accuracy. - -## References - -@article{dormand1987high, -title={High-order embedded Runge-Kutta-Nystrom formulae}, -author={Dormand, JR and El-Mikkawy, MEA and Prince, PJ}, -journal={IMA Journal of Numerical Analysis}, -volume={7}, -number={4}, -pages={423--430}, -year={1987}, -publisher={Oxford University Press} -} -""" +@doc generic_solver_docstring("8th order explicit method. + The second order ODE should not depend on the first derivative. + Not as efficient as [`DPRKN12`](@ref) when high accuracy is needed, + however this solver is competitive with [`DPRKN6`](@ref) at lax tolerances and, + depending on the problem, might be a good option between performance and accuracy.", + "DPRKN8", + "Improved Runge-Kutta-Nyström method", + "@article{dormand1987high, + title={High-order embedded Runge-Kutta-Nystrom formulae}, + author={Dormand, JR and El-Mikkawy, MEA and Prince, PJ}, + journal={IMA Journal of Numerical Analysis}, + volume={7}, + number={4}, + pages={423--430}, + year={1987}, + publisher={Oxford University Press}}", "", "") struct DPRKN8 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - DPRKN12 - -12th order explicit Rugne-Kutta-Nyström method. The second order ODE should not depend on the first derivative. - -Most efficient when high accuracy is needed. - -## References - -@article{dormand1987high, -title={High-order embedded Runge-Kutta-Nystrom formulae}, -author={Dormand, JR and El-Mikkawy, MEA and Prince, PJ}, -journal={IMA Journal of Numerical Analysis}, -volume={7}, -number={4}, -pages={423--430}, -year={1987}, -publisher={Oxford University Press} -} -""" +@doc generic_solver_docstring("12th order explicit method. + The second order ODE should not depend on the first derivative. + Most efficient when high accuracy is needed.", + "DPRKN12", + "Improved Runge-Kutta-Nyström method", + "@article{dormand1987high, + title={High-order embedded Runge-Kutta-Nystrom formulae}, + author={Dormand, JR and El-Mikkawy, MEA and Prince, PJ}, + journal={IMA Journal of Numerical Analysis}, + volume={7}, + number={4}, + pages={423--430}, + year={1987}, + publisher={Oxford University Press}}", "", "") struct DPRKN12 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - ERKN4 - -Embedded 4(3) pair of explicit Runge-Kutta-Nyström methods. Integrates the periodic properties of the harmonic oscillator exactly. - -The second order ODE should not depend on the first derivative. - -Uses adaptive step size control. This method is extra efficient on periodic problems. - -## References - -@article{demba2017embedded, -title={An Embedded 4 (3) Pair of Explicit Trigonometrically-Fitted Runge-Kutta-Nystr{\"o}m Method for Solving Periodic Initial Value Problems}, -author={Demba, MA and Senu, N and Ismail, F}, -journal={Applied Mathematical Sciences}, -volume={11}, -number={17}, -pages={819--838}, -year={2017} -} -""" +@doc generic_solver_docstring("Embedded 4(3) pair of explicit methods. + Integrates the periodic properties of the harmonic oscillator exactly. + The second order ODE should not depend on the first derivative. + Uses adaptive step size control. This method is extra efficient on periodic problems.", + "ERKN4", + "Improved Runge-Kutta-Nyström method", + "@article{demba2017embedded, + title={An Embedded 4 (3) Pair of Explicit Trigonometrically-Fitted Runge-Kutta-Nystr{\"o}m Method for Solving Periodic Initial Value Problems}, + author={Demba, MA and Senu, N and Ismail, F}, + journal={Applied Mathematical Sciences}, + volume={11}, + number={17}, + pages={819--838}, + year={2017}}", "", "") struct ERKN4 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - ERKN5 - -Embedded 5(4) pair of explicit Runge-Kutta-Nyström methods. Integrates the periodic properties of the harmonic oscillator exactly. - -The second order ODE should not depend on the first derivative. - -Uses adaptive step size control. This method is extra efficient on periodic problems. - -## References - -@article{demba20165, -title={A 5 (4) Embedded Pair of Explicit Trigonometrically-Fitted Runge--Kutta--Nystr{\"o}m Methods for the Numerical Solution of Oscillatory Initial Value Problems}, -author={Demba, Musa A and Senu, Norazak and Ismail, Fudziah}, -journal={Mathematical and Computational Applications}, -volume={21}, -number={4}, -pages={46}, -year={2016}, -publisher={Multidisciplinary Digital Publishing Institute} -} -""" +@doc generic_solver_docstring("Embedded 5(4) pair of explicit methods. + Integrates the periodic properties of the harmonic oscillator exactly. + The second order ODE should not depend on the first derivative. + Uses adaptive step size control. This method is extra efficient on periodic problems.", + "ERKN5", + "Improved Runge-Kutta-Nyström method", + "@article{demba20165, + title={A 5 (4) Embedded Pair of Explicit Trigonometrically-Fitted Runge--Kutta--Nystr{\"o}m Methods for the Numerical Solution of Oscillatory Initial Value Problems}, + author={Demba, Musa A and Senu, Norazak and Ismail, Fudziah}, + journal={Mathematical and Computational Applications}, + volume={21}, + number={4}, + pages={46}, + year={2016}, + publisher={Multidisciplinary Digital Publishing Institute}}", "", "") struct ERKN5 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" - ERKN7 - -Embedded pair of explicit Runge-Kutta-Nyström methods. Integrates the periodic properties of the harmonic oscillator exactly. - -The second order ODE should not depend on the first derivative. - -Uses adaptive step size control. This method is extra efficient on periodic Problems. - -## References - -@article{SimosOnHO, -title={On high order Runge-Kutta-Nystr{\"o}m pairs}, -author={Theodore E. Simos and Ch. Tsitouras}, -journal={J. Comput. Appl. Math.}, -volume={400}, -pages={113753} -} -""" +@doc generic_solver_docstring("Embedded pair of explicit methods. + Integrates the periodic properties of the harmonic oscillator exactly. + The second order ODE should not depend on the first derivative. + Uses adaptive step size control. This method is extra efficient on periodic problems.", + "ERKN7", + "Improved Runge-Kutta-Nyström method", + "@article{SimosOnHO, + title={On high order Runge-Kutta-Nystr{\"o}m pairs}, + author={Theodore E. Simos and Ch. Tsitouras}, + journal={J. Comput. Appl. Math.}, + volume={400}, + pages={113753}}", "", "") struct ERKN7 <: OrdinaryDiffEqAdaptivePartitionedAlgorithm end -""" -3 stage fourth order Runge-Kutta Nystrom method to solve second order linear inhomogeneous IVPs. - +@doc generic_solver_docstring( + "3 stage fourth order method to solve second order linear inhomogeneous IVPs. Does not include an adaptive method. Solves for for d-dimensional differential systems of second order linear inhomogeneous equations. -!!! warn - - This method is only fourth order for these systems, the method is second order otherwise! - -## References - -@article{MONTIJANO2024115533, -title = {Explicit Runge–Kutta–Nyström methods for the numerical solution of second order linear inhomogeneous IVPs}, -author = {J.I. Montijano and L. Rández and M. Calvo}, -journal = {Journal of Computational and Applied Mathematics}, -volume = {438}, -pages = {115533}, -year = {2024}, -} -""" +!!! warning +This method is only fourth order for these systems, the method is second order otherwise!", + "RKN4", + "Improved Runge-Kutta-Nyström method", + "@article{MONTIJANO2024115533, + title = {Explicit Runge–Kutta–Nyström methods for the numerical solution of second order linear inhomogeneous IVPs}, + author = {J.I. Montijano and L. Rández and M. Calvo}, + journal = {Journal of Computational and Applied Mathematics}, + volume = {438}, + pages = {115533}, + year = {2024},}", "", "") struct RKN4 <: OrdinaryDiffEqAlgorithm end diff --git a/lib/OrdinaryDiffEqRosenbrock/Project.toml b/lib/OrdinaryDiffEqRosenbrock/Project.toml index 14f0d057bf..0cd8937c85 100644 --- a/lib/OrdinaryDiffEqRosenbrock/Project.toml +++ b/lib/OrdinaryDiffEqRosenbrock/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqRosenbrock" uuid = "43230ef6-c299-4910-a778-202eb28ce4ce" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.1.1" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/lib/OrdinaryDiffEqRosenbrock/src/OrdinaryDiffEqRosenbrock.jl b/lib/OrdinaryDiffEqRosenbrock/src/OrdinaryDiffEqRosenbrock.jl index ae3b93b291..d009f9c7a3 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/OrdinaryDiffEqRosenbrock.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/OrdinaryDiffEqRosenbrock.jl @@ -48,17 +48,70 @@ function rosenbrock_wanner_docstring(description::String, extra_keyword_default = "", with_step_limiter = false) keyword_default = """ + chunk_size = Val{0}(), + standardtag = Val{true}(), autodiff = Val{true}(), concrete_jac = nothing, + diff_type = Val{:central}, linsolve = nothing, precs = DEFAULT_PRECS, """ * extra_keyword_default keyword_default_description = """ - - `autodiff`: boolean to control if the Jacobian should be computed via AD or not - - `concrete_jac`: function of the form `jac!(J, u, p, t)` - - `linsolve`: custom solver for the inner linear systems - - `precs`: custom preconditioner for the inner linear solver + - `chunk_size`: The chunk size used with ForwardDiff.jl. Defaults to `Val{0}()` + and thus uses the internal ForwardDiff.jl algorithm for the choice. + - `standardtag`: Specifies whether to use package-specific tags instead of the + ForwardDiff default function-specific tags. For more information, see + [this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/). + Defaults to `Val{true}()`. + - `autodiff`: Specifies whether to use automatic differentiation via + [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite + differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl). + Defaults to `Val{true}()` for automatic differentiation. + - `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to + `nothing`, which means it will be chosen true/false depending on circumstances + of the solver, such as whether a Krylov subspace method is used for `linsolve`. + - `diff_type`: The type of differentiation used in FiniteDiff.jl if `autodiff=false`. + Defaults to `Val{:forward}`, with alternatives of `Val{:central}` and + `Val{:complex}`. + - `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver. + For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify + `$name(linsolve = KLUFactorization()`). + When `nothing` is passed, uses `DefaultLinearSolver`. + - `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/) + can be used as a left or right preconditioner. + Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)` + function where the arguments are defined as: + - `W`: the current Jacobian of the nonlinear system. Specified as either + ``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will + commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy + representation of the operator. Users can construct the W-matrix on demand + by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching + the `jac_prototype`. + - `du`: the current ODE derivative + - `u`: the current ODE state + - `p`: the ODE parameters + - `t`: the current ODE time + - `newW`: a `Bool` which specifies whether the `W` matrix has been updated since + the last call to `precs`. It is recommended that this is checked to only + update the preconditioner when `newW == true`. + - `Plprev`: the previous `Pl`. + - `Prprev`: the previous `Pr`. + - `solverdata`: Optional extra data the solvers can give to the `precs` function. + Solver-dependent and subject to change. + The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners. + To specify one-sided preconditioning, simply return `nothing` for the preconditioner + which is not used. Additionally, `precs` must supply the dispatch: + ```julia + Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata) + ``` + which is used in the solver setup phase to construct the integrator + type with the preconditioners `(Pl,Pr)`. + The default is `precs=DEFAULT_PRECS` where the default preconditioner function + is defined as: + ```julia + DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing + ``` """ * extra_keyword_description if with_step_limiter @@ -79,15 +132,68 @@ function rosenbrock_docstring(description::String, extra_keyword_default = "", with_step_limiter = false) keyword_default = """ - autodiff = Val{true}(), - concrete_jac = nothing, - linsolve = nothing, - precs = DEFAULT_PRECS, + - `chunk_size`: The chunk size used with ForwardDiff.jl. Defaults to `Val{0}()` + and thus uses the internal ForwardDiff.jl algorithm for the choice. + - `standardtag`: Specifies whether to use package-specific tags instead of the + ForwardDiff default function-specific tags. For more information, see + [this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/). + Defaults to `Val{true}()`. + - `autodiff`: Specifies whether to use automatic differentiation via + [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite + differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl). + Defaults to `Val{true}()` for automatic differentiation. + - `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to + `nothing`, which means it will be chosen true/false depending on circumstances + of the solver, such as whether a Krylov subspace method is used for `linsolve`. + - `diff_type`: The type of differentiation used in FiniteDiff.jl if `autodiff=false`. + Defaults to `Val{:forward}`, with alternatives of `Val{:central}` and + `Val{:complex}`. + - `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver. + For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify + `$name(linsolve = KLUFactorization()`). + When `nothing` is passed, uses `DefaultLinearSolver`. + - `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/) + can be used as a left or right preconditioner. + Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)` + function where the arguments are defined as: + - `W`: the current Jacobian of the nonlinear system. Specified as either + ``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will + commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy + representation of the operator. Users can construct the W-matrix on demand + by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching + the `jac_prototype`. + - `du`: the current ODE derivative + - `u`: the current ODE state + - `p`: the ODE parameters + - `t`: the current ODE time + - `newW`: a `Bool` which specifies whether the `W` matrix has been updated since + the last call to `precs`. It is recommended that this is checked to only + update the preconditioner when `newW == true`. + - `Plprev`: the previous `Pl`. + - `Prprev`: the previous `Pr`. + - `solverdata`: Optional extra data the solvers can give to the `precs` function. + Solver-dependent and subject to change. + The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners. + To specify one-sided preconditioning, simply return `nothing` for the preconditioner + which is not used. Additionally, `precs` must supply the dispatch: + ```julia + Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata) + ``` + which is used in the solver setup phase to construct the integrator + type with the preconditioners `(Pl,Pr)`. + The default is `precs=DEFAULT_PRECS` where the default preconditioner function + is defined as: + ```julia + DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing + ``` """ * extra_keyword_default keyword_default_description = """ + - `chunk_size`: TBD + - `standardtag`: TBD - `autodiff`: boolean to control if the Jacobian should be computed via AD or not - `concrete_jac`: function of the form `jac!(J, u, p, t)` + - `diff_type`: TBD - `linsolve`: custom solver for the inner linear systems - `precs`: custom preconditioner for the inner linear solver """ * extra_keyword_description diff --git a/lib/OrdinaryDiffEqRosenbrock/src/generic_rosenbrock.jl b/lib/OrdinaryDiffEqRosenbrock/src/generic_rosenbrock.jl index 5600b1bc27..a67b4a9548 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/generic_rosenbrock.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/generic_rosenbrock.jl @@ -176,7 +176,7 @@ function gen_cache_struct(tab::RosenbrockTableau,cachename::Symbol,constcachenam end end cacheexpr=quote - @cache mutable struct $cachename{uType,rateType,uNoUnitsType,JType,WType,TabType,TFType,UFType,F,JCType,GCType} <: RosenbrockMutableCache + @cache mutable struct $cachename{uType,rateType,uNoUnitsType,JType,WType,TabType,TFType,UFType,F,JCType,GCType} <: GenericRosenbrockMutableCache u::uType uprev::uType du::rateType @@ -959,25 +959,65 @@ with_step_limiter = true) Rodas23W """ A 4th order L-stable Rosenbrock-W method. """, -"ROS34PW1a") ROS34PW1a +"ROS34PW1a", +references = """ +@article{rang2005new, + title={New Rosenbrock W-methods of order 3 for partial differential algebraic equations of index 1}, + author={Rang, Joachim and Angermann, L}, + journal={BIT Numerical Mathematics}, + volume={45}, + pages={761--787}, + year={2005}, + publisher={Springer}} +""") ROS34PW1a @doc rosenbrock_wanner_docstring( """ A 4th order L-stable Rosenbrock-W method. """, -"ROS34PW1b") ROS34PW1b +"ROS34PW1b", +references = """ +@article{rang2005new, + title={New Rosenbrock W-methods of order 3 for partial differential algebraic equations of index 1}, + author={Rang, Joachim and Angermann, L}, + journal={BIT Numerical Mathematics}, + volume={45}, + pages={761--787}, + year={2005}, + publisher={Springer}} +""") ROS34PW1b @doc rosenbrock_wanner_docstring( """ A 4th order stiffy accurate Rosenbrock-W method for PDAEs. """, -"ROS34PW2") ROS34PW2 +"ROS34PW2", +references = """ +@article{rang2005new, + title={New Rosenbrock W-methods of order 3 for partial differential algebraic equations of index 1}, + author={Rang, Joachim and Angermann, L}, + journal={BIT Numerical Mathematics}, + volume={45}, + pages={761--787}, + year={2005}, + publisher={Springer}} +""") ROS34PW2 @doc rosenbrock_wanner_docstring( """ A 4th order strongly A-stable (Rinf~0.63) Rosenbrock-W method. """, -"ROS34PW3") ROS34PW3 +"ROS34PW3", +references = """ +@article{rang2005new, + title={New Rosenbrock W-methods of order 3 for partial differential algebraic equations of index 1}, + author={Rang, Joachim and Angermann, L}, + journal={BIT Numerical Mathematics}, + volume={45}, + pages={761--787}, + year={2005}, + publisher={Springer}} +""") ROS34PW3 @doc rosenbrock_docstring( """ @@ -995,7 +1035,7 @@ references = """ """, "Rodas3", references = """ -- Steinebach G. Construction of Rosenbrock–Wanner method Rodas5P and numerical benchmarks +- Steinebach G. Construction of Rosenbrock–Wanner method Rodas5P and numerical benchmarks within the Julia Differential Equations package. In: BIT Numerical Mathematics, 63(2), 2023 """, @@ -1056,7 +1096,7 @@ lower if not corrected). """, "Rodas4P", references = """ -- Steinebach G., Rodas23W / Rodas32P - a Rosenbrock-type method for DAEs with additional error estimate +- Steinebach G., Rodas23W / Rodas32P - a Rosenbrock-type method for DAEs with additional error estimate for dense output and Julia implementation, In progress. """, @@ -1070,7 +1110,7 @@ of Roadas4P and in case of inexact Jacobians a second order W method. """, "Rodas4P2", references = """ -- Steinebach G., Rodas23W / Rodas32P - a Rosenbrock-type method for DAEs with additional error estimate +- Steinebach G., Rodas23W / Rodas32P - a Rosenbrock-type method for DAEs with additional error estimate for dense output and Julia implementation, In progress. """, @@ -1095,7 +1135,7 @@ Has improved stability in the adaptive time stepping embedding. """, "Rodas5P", references = """ -- Steinebach G. Construction of Rosenbrock–Wanner method Rodas5P and numerical benchmarks +- Steinebach G. Construction of Rosenbrock–Wanner method Rodas5P and numerical benchmarks within the Julia Differential Equations package. In: BIT Numerical Mathematics, 63(2), 2023 """, @@ -1225,10 +1265,10 @@ references = """ ROS2PRTableau() 2nd order stiffly accurate Rosenbrock method with 3 internal stages with (Rinf=0). -For problems with medium stiffness the convergence behaviour is very poor and it is recommended to use +For problems with medium stiffness the convergence behaviour is very poor and it is recommended to use [`ROS2S`](@ref) instead. -Rang, Joachim (2014): The Prothero and Robinson example: +Rang, Joachim (2014): The Prothero and Robinson example: Convergence studies for Runge-Kutta and Rosenbrock-Wanner methods. https://doi.org/10.24355/dbbs.084-201408121139-0 """ function ROS2PRTableau() # 2nd order @@ -1248,7 +1288,7 @@ end @doc rosenbrock_docstring( """ 2nd order stiffly accurate Rosenbrock method with 3 internal stages with (Rinf=0). -For problems with medium stiffness the convergence behaviour is very poor and it is recommended to use +For problems with medium stiffness the convergence behaviour is very poor and it is recommended to use [`ROS2S`](@ref) instead. """, "ROS2PR", @@ -1267,7 +1307,7 @@ ROS2PR 2nd order stiffly accurate Rosenbrock-Wanner W-method with 3 internal stages with B_PR consistent of order 2 with (Rinf=0). More Information at https://doi.org/10.24355/dbbs.084-201408121139-0 -Rang, Joachim (2014): The Prothero and Robinson example: +Rang, Joachim (2014): The Prothero and Robinson example: Convergence studies for Runge-Kutta and Rosenbrock-Wanner methods. https://doi.org/10.24355/dbbs.084-201408121139-0 """ function ROS2STableau() # 2nd order @@ -1335,7 +1375,7 @@ references = """ 3nd order stiffly accurate Rosenbrock-Wanner method with 3 internal stages with B_PR consistent of order 3, which is strongly A-stable with Rinf~=-0.73. -Rang, Joachim (2014): The Prothero and Robinson example: +Rang, Joachim (2014): The Prothero and Robinson example: Convergence studies for Runge-Kutta and Rosenbrock-Wanner methods. https://doi.org/10.24355/dbbs.084-201408121139-0 """ function ROS3PRTableau() # 3rd order @@ -1371,7 +1411,7 @@ references = """ 3nd order stiffly accurate Rosenbrock method with 3 internal stages with B_PR consistent of order 3, which is strongly A-stable with Rinf~=-0.73 Convergence with order 4 for the stiff case, but has a poor accuracy. -Rang, Joachim (2014): The Prothero and Robinson example: +Rang, Joachim (2014): The Prothero and Robinson example: Convergence studies for Runge-Kutta and Rosenbrock-Wanner methods. https://doi.org/10.24355/dbbs.084-201408121139-0 """ function Scholz4_7Tableau() # 3rd order @@ -1599,7 +1639,7 @@ references = """ B_PR consistent of order 2 with Rinf=0. The order of convergence decreases if medium stiff problems are considered, but it has good results for very stiff cases. -Rang, Joachim (2014): The Prothero and Robinson example: +Rang, Joachim (2014): The Prothero and Robinson example: Convergence studies for Runge-Kutta and Rosenbrock-Wanner methods. https://doi.org/10.24355/dbbs.084-201408121139-0 """ function ROS3PRLTableau() # 3rd order @@ -1639,7 +1679,7 @@ references = """ B_PR consistent of order 3. The order of convergence does NOT decreases if medium stiff problems are considered as it does for [`ROS3PRL`](@ref). -Rang, Joachim (2014): The Prothero and Robinson example: +Rang, Joachim (2014): The Prothero and Robinson example: Convergence studies for Runge-Kutta and Rosenbrock-Wanner methods. https://doi.org/10.24355/dbbs.084-201408121139-0 """ function ROS3PRL2Tableau() # 3rd order @@ -1677,7 +1717,7 @@ references = """ 4rd order L-stable Rosenbrock-Krylov method with 4 internal stages, with a 3rd order embedded method which is strongly A-stable with Rinf~=0.55. (when using exact Jacobians) -Tranquilli, Paul and Sandu, Adrian (2014): Rosenbrock--Krylov Methods for Large Systems of Differential Equations +Tranquilli, Paul and Sandu, Adrian (2014): Rosenbrock--Krylov Methods for Large Systems of Differential Equations https://doi.org/10.1137/130923336 """ function ROK4aTableau() # 4rd order @@ -1703,7 +1743,7 @@ with a 3rd order embedded method which is strongly A-stable with Rinf~=0.55. (wh """, "ROK4a", references = """ -- Tranquilli, Paul and Sandu, Adrian (2014): +- Tranquilli, Paul and Sandu, Adrian (2014): Rosenbrock--Krylov Methods for Large Systems of Differential Equations https://doi.org/10.1137/130923336 """) ROK4a diff --git a/lib/OrdinaryDiffEqRosenbrock/src/interp_func.jl b/lib/OrdinaryDiffEqRosenbrock/src/interp_func.jl index 27bde3e1b7..652b7ea6af 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/interp_func.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/interp_func.jl @@ -12,7 +12,7 @@ function DiffEqBase.interp_summary(::Type{cacheType}, dense::Bool) where { cacheType <: Union{Rodas4ConstantCache, Rodas23WConstantCache, Rodas3PConstantCache, - Rodas4Cache, Rodas23WCache, Rodas3PCache}} + RosenbrockCache, Rodas23WCache, Rodas3PCache}} dense ? "specialized 3rd order \"free\" stiffness-aware interpolation" : "1st order linear" end diff --git a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl index 0a70a7fdde..4b6841a1bc 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl @@ -1,13 +1,51 @@ abstract type RosenbrockMutableCache <: OrdinaryDiffEqMutableCache end +abstract type GenericRosenbrockMutableCache <: RosenbrockMutableCache end abstract type RosenbrockConstantCache <: OrdinaryDiffEqConstantCache end # Fake values since non-FSAL -get_fsalfirstlast(cache::RosenbrockMutableCache, u) = (zero(u), zero(u)) +get_fsalfirstlast(cache::RosenbrockMutableCache, u) = (nothing, nothing) +function get_fsalfirstlast(cache::GenericRosenbrockMutableCache, u) + (cache.fsalfirst, cache.fsallast) +end ################################################################################ # Shampine's Low-order Rosenbrocks +mutable struct RosenbrockCache{uType, rateType, uNoUnitsType, JType, WType, TabType, + TFType, UFType, F, JCType, GCType, RTolType, A, StepLimiter, StageLimiter} <: RosenbrockMutableCache + u::uType + uprev::uType + dense::Vector{rateType} + du::rateType + du1::rateType + du2::rateType + ks::Vector{rateType} + fsalfirst::rateType + fsallast::rateType + dT::rateType + J::JType + W::WType + tmp::rateType + atmp::uNoUnitsType + weight::uNoUnitsType + tab::TabType + tf::TFType + uf::UFType + linsolve_tmp::rateType + linsolve::F + jac_config::JCType + grad_config::GCType + reltol::RTolType + alg::A + step_limiter!::StepLimiter + stage_limiter!::StageLimiter +end +function full_cache(c::RosenbrockCache) + return [c.u, c.uprev, c.dense..., c.du, c.du1, c.du2, + c.ks..., c.fsalfirst, c.fsallast, c.dT, c.tmp, c.atmp, c.weight, c.linsolve_tmp] +end + @cache mutable struct Rosenbrock23Cache{uType, rateType, uNoUnitsType, JType, WType, TabType, TFType, UFType, F, JCType, GCType, RTolType, A, AV, StepLimiter, StageLimiter} <: RosenbrockMutableCache @@ -673,89 +711,12 @@ struct Rodas4ConstantCache{TF, UF, Tab, JType, WType, F, AD} <: RosenbrockConsta autodiff::AD end -@cache mutable struct Rodas4Cache{uType, rateType, uNoUnitsType, JType, WType, TabType, - TFType, UFType, F, JCType, GCType, RTolType, A, StepLimiter, StageLimiter} <: - RosenbrockMutableCache - u::uType - uprev::uType - dense1::rateType - dense2::rateType - du::rateType - du1::rateType - du2::rateType - k1::rateType - k2::rateType - k3::rateType - k4::rateType - k5::rateType - k6::rateType - fsalfirst::rateType - fsallast::rateType - dT::rateType - J::JType - W::WType - tmp::rateType - atmp::uNoUnitsType - weight::uNoUnitsType - tab::TabType - tf::TFType - uf::UFType - linsolve_tmp::rateType - linsolve::F - jac_config::JCType - grad_config::GCType - reltol::RTolType - alg::A - step_limiter!::StepLimiter - stage_limiter!::StageLimiter -end +tabtype(::Rodas4) = Rodas4Tableau +tabtype(::Rodas42) = Rodas42Tableau +tabtype(::Rodas4P) = Rodas4PTableau +tabtype(::Rodas4P2) = Rodas4P2Tableau -function alg_cache(alg::Rodas4, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - dense1 = zero(rate_prototype) - dense2 = zero(rate_prototype) - du = zero(rate_prototype) - du1 = zero(rate_prototype) - du2 = zero(rate_prototype) - k1 = zero(rate_prototype) - k2 = zero(rate_prototype) - k3 = zero(rate_prototype) - k4 = zero(rate_prototype) - k5 = zero(rate_prototype) - k6 = zero(rate_prototype) - fsalfirst = zero(rate_prototype) - fsallast = zero(rate_prototype) - dT = zero(rate_prototype) - J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(true)) - tmp = zero(rate_prototype) - atmp = similar(u, uEltypeNoUnits) - recursivefill!(atmp, false) - weight = similar(u, uEltypeNoUnits) - recursivefill!(weight, false) - tab = Rodas4Tableau(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) - - tf = TimeGradientWrapper(f, uprev, p) - uf = UJacobianWrapper(f, t, p) - linsolve_tmp = zero(rate_prototype) - linprob = LinearProblem(W, _vec(linsolve_tmp); u0 = _vec(tmp)) - Pl, Pr = wrapprecs( - alg.precs(W, nothing, u, p, t, nothing, nothing, nothing, - nothing)..., weight, tmp) - linsolve = init(linprob, alg.linsolve, alias_A = true, alias_b = true, - Pl = Pl, Pr = Pr, - assumptions = LinearSolve.OperatorAssumptions(true)) - grad_config = build_grad_config(alg, f, tf, du1, t) - jac_config = build_jac_config(alg, f, uf, du1, uprev, u, tmp, du2) - Rodas4Cache(u, uprev, dense1, dense2, du, du1, du2, k1, k2, k3, k4, - k5, k6, - fsalfirst, fsallast, dT, J, W, tmp, atmp, weight, tab, tf, uf, linsolve_tmp, - linsolve, jac_config, grad_config, reltol, alg, alg.step_limiter!, - alg.stage_limiter!) -end - -function alg_cache(alg::Rodas4, u, rate_prototype, ::Type{uEltypeNoUnits}, +function alg_cache(alg::Union{Rodas4, Rodas42, Rodas4P, Rodas4P2}, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, dt, reltol, p, calck, ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} @@ -765,189 +726,60 @@ function alg_cache(alg::Rodas4, u, rate_prototype, ::Type{uEltypeNoUnits}, linprob = nothing #LinearProblem(W,copy(u); u0=copy(u)) linsolve = nothing #init(linprob,alg.linsolve,alias_A=true,alias_b=true) Rodas4ConstantCache(tf, uf, - Rodas4Tableau(constvalue(uBottomEltypeNoUnits), + tabtype(alg)(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)), J, W, linsolve, alg_autodiff(alg)) end -function alg_cache(alg::Rodas42, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - dense1 = zero(rate_prototype) - dense2 = zero(rate_prototype) - du = zero(rate_prototype) - du1 = zero(rate_prototype) - du2 = zero(rate_prototype) - k1 = zero(rate_prototype) - k2 = zero(rate_prototype) - k3 = zero(rate_prototype) - k4 = zero(rate_prototype) - k5 = zero(rate_prototype) - k6 = zero(rate_prototype) - fsalfirst = zero(rate_prototype) - fsallast = zero(rate_prototype) - dT = zero(rate_prototype) - J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(true)) - tmp = zero(rate_prototype) - atmp = similar(u, uEltypeNoUnits) - recursivefill!(atmp, false) - weight = similar(u, uEltypeNoUnits) - recursivefill!(weight, false) - tab = Rodas42Tableau(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) +function alg_cache(alg::Union{Rodas4, Rodas42, Rodas4P, Rodas4P2}, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - tf = TimeGradientWrapper(f, uprev, p) - uf = UJacobianWrapper(f, t, p) - linsolve_tmp = zero(rate_prototype) - linprob = LinearProblem(W, _vec(linsolve_tmp); u0 = _vec(tmp)) - Pl, Pr = wrapprecs( - alg.precs(W, nothing, u, p, t, nothing, nothing, nothing, - nothing)..., weight, tmp) - linsolve = init(linprob, alg.linsolve, alias_A = true, alias_b = true, - Pl = Pl, Pr = Pr, - assumptions = LinearSolve.OperatorAssumptions(true)) - grad_config = build_grad_config(alg, f, tf, du1, t) - jac_config = build_jac_config(alg, f, uf, du1, uprev, u, tmp, du2) - Rodas4Cache(u, uprev, dense1, dense2, du, du1, du2, k1, k2, k3, k4, - k5, k6, - fsalfirst, fsallast, dT, J, W, tmp, atmp, weight, tab, tf, uf, linsolve_tmp, - linsolve, jac_config, grad_config, reltol, alg, alg.step_limiter!, - alg.stage_limiter!) -end - -function alg_cache(alg::Rodas42, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - tf = TimeDerivativeWrapper(f, u, p) - uf = UDerivativeWrapper(f, t, p) - J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(false)) - linprob = nothing #LinearProblem(W,copy(u); u0=copy(u)) - linsolve = nothing #init(linprob,alg.linsolve,alias_A=true,alias_b=true) - Rodas4ConstantCache(tf, uf, - Rodas42Tableau(constvalue(uBottomEltypeNoUnits), - constvalue(tTypeNoUnits)), J, W, linsolve, - alg_autodiff(alg)) -end - -function alg_cache(alg::Rodas4P, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - dense1 = zero(rate_prototype) - dense2 = zero(rate_prototype) + # Initialize vectors + dense = [zero(rate_prototype) for _ in 1:2] + ks = [zero(rate_prototype) for _ in 1:6] du = zero(rate_prototype) du1 = zero(rate_prototype) du2 = zero(rate_prototype) - k1 = zero(rate_prototype) - k2 = zero(rate_prototype) - k3 = zero(rate_prototype) - k4 = zero(rate_prototype) - k5 = zero(rate_prototype) - k6 = zero(rate_prototype) - fsalfirst = zero(rate_prototype) - fsallast = zero(rate_prototype) - dT = zero(rate_prototype) - J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(true)) - tmp = zero(rate_prototype) - atmp = similar(u, uEltypeNoUnits) - recursivefill!(atmp, false) - weight = similar(u, uEltypeNoUnits) - recursivefill!(weight, false) - tab = Rodas4PTableau(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) - - tf = TimeGradientWrapper(f, uprev, p) - uf = UJacobianWrapper(f, t, p) - linsolve_tmp = zero(rate_prototype) - linprob = LinearProblem(W, _vec(linsolve_tmp); u0 = _vec(tmp)) - Pl, Pr = wrapprecs( - alg.precs(W, nothing, u, p, t, nothing, nothing, nothing, - nothing)..., weight, tmp) - linsolve = init(linprob, alg.linsolve, alias_A = true, alias_b = true, - Pl = Pl, Pr = Pr, - assumptions = LinearSolve.OperatorAssumptions(true)) - grad_config = build_grad_config(alg, f, tf, du1, t) - jac_config = build_jac_config(alg, f, uf, du1, uprev, u, tmp, du2) - Rodas4Cache(u, uprev, dense1, dense2, du, du1, du2, k1, k2, k3, k4, - k5, k6, - fsalfirst, fsallast, dT, J, W, tmp, atmp, weight, tab, tf, uf, linsolve_tmp, - linsolve, jac_config, grad_config, reltol, alg, alg.step_limiter!, - alg.stage_limiter!) -end -function alg_cache(alg::Rodas4P, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - tf = TimeDerivativeWrapper(f, u, p) - uf = UDerivativeWrapper(f, t, p) - J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(false)) - linprob = nothing #LinearProblem(W,copy(u); u0=copy(u)) - linsolve = nothing #init(linprob,alg.linsolve,alias_A=true,alias_b=true) - Rodas4ConstantCache(tf, uf, - Rodas4PTableau(constvalue(uBottomEltypeNoUnits), - constvalue(tTypeNoUnits)), J, W, linsolve, - alg_autodiff(alg)) -end - -function alg_cache(alg::Rodas4P2, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - dense1 = zero(rate_prototype) - dense2 = zero(rate_prototype) - du = zero(rate_prototype) - du1 = zero(rate_prototype) - du2 = zero(rate_prototype) - k1 = zero(rate_prototype) - k2 = zero(rate_prototype) - k3 = zero(rate_prototype) - k4 = zero(rate_prototype) - k5 = zero(rate_prototype) - k6 = zero(rate_prototype) + # Initialize other variables fsalfirst = zero(rate_prototype) fsallast = zero(rate_prototype) dT = zero(rate_prototype) + + # Build J and W matrices J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(true)) + + # Temporary and helper variables tmp = zero(rate_prototype) atmp = similar(u, uEltypeNoUnits) recursivefill!(atmp, false) weight = similar(u, uEltypeNoUnits) recursivefill!(weight, false) - tab = Rodas4P2Tableau(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) + tab = tabtype(alg)(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) tf = TimeGradientWrapper(f, uprev, p) uf = UJacobianWrapper(f, t, p) linsolve_tmp = zero(rate_prototype) linprob = LinearProblem(W, _vec(linsolve_tmp); u0 = _vec(tmp)) + Pl, Pr = wrapprecs( alg.precs(W, nothing, u, p, t, nothing, nothing, nothing, - nothing)..., weight, tmp) + nothing)..., weight, tmp) + linsolve = init(linprob, alg.linsolve, alias_A = true, alias_b = true, - Pl = Pl, Pr = Pr, - assumptions = LinearSolve.OperatorAssumptions(true)) + Pl = Pl, Pr = Pr, + assumptions = LinearSolve.OperatorAssumptions(true)) + grad_config = build_grad_config(alg, f, tf, du1, t) jac_config = build_jac_config(alg, f, uf, du1, uprev, u, tmp, du2) - Rodas4Cache(u, uprev, dense1, dense2, du, du1, du2, k1, k2, k3, k4, - k5, k6, - fsalfirst, fsallast, dT, J, W, tmp, atmp, weight, tab, tf, uf, linsolve_tmp, - linsolve, jac_config, grad_config, reltol, alg, alg.step_limiter!, - alg.stage_limiter!) -end -function alg_cache(alg::Rodas4P2, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - tf = TimeDerivativeWrapper(f, u, p) - uf = UDerivativeWrapper(f, t, p) - J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(false)) - linprob = nothing #LinearProblem(W,copy(u); u0=copy(u)) - linsolve = nothing #init(linprob,alg.linsolve,alias_A=true,alias_b=true) - Rodas4ConstantCache(tf, uf, - Rodas4P2Tableau(constvalue(uBottomEltypeNoUnits), - constvalue(tTypeNoUnits)), J, W, linsolve, - alg_autodiff(alg)) + # Return the cache struct with vectors + RosenbrockCache( + u, uprev, dense, du, du1, du2, ks, fsalfirst, fsallast, + dT, J, W, tmp, atmp, weight, tab, tf, uf, linsolve_tmp, + linsolve, jac_config, grad_config, reltol, alg, + alg.step_limiter!, alg.stage_limiter!) end ################################################################################ diff --git a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_interpolants.jl b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_interpolants.jl index 6f50205cf1..4d7e659410 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_interpolants.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_interpolants.jl @@ -5,7 +5,7 @@ ROSENBROCKS_WITH_INTERPOLATIONS = Union{Rosenbrock23ConstantCache, Rosenbrock23C Rodas23WConstantCache, Rodas3PConstantCache, Rodas23WCache, Rodas3PCache, Rodas4ConstantCache, Rosenbrock5ConstantCache, - Rodas4Cache, Rosenbrock5Cache} + RosenbrockCache, Rosenbrock5Cache} function _ode_interpolant(Θ, dt, y₀, y₁, k, cache::ROSENBROCKS_WITH_INTERPOLATIONS, @@ -135,14 +135,14 @@ From MATLAB ODE Suite by Shampine end @muladd function _ode_interpolant( - Θ, dt, y₀, y₁, k, cache::Union{Rodas4Cache, Rodas23WCache, Rodas3PCache}, + Θ, dt, y₀, y₁, k, cache::Union{RosenbrockCache, Rodas23WCache, Rodas3PCache}, idxs::Nothing, T::Type{Val{0}}, differential_vars) Θ1 = 1 - Θ @inbounds @.. broadcast=false Θ1 * y₀+Θ * (y₁ + Θ1 * (k[1] + Θ * k[2])) end @muladd function _ode_interpolant(Θ, dt, y₀, y₁, k, - cache::Union{Rodas4ConstantCache, Rodas4Cache, Rodas23WConstantCache, + cache::Union{Rodas4ConstantCache, RosenbrockCache, Rodas23WConstantCache, Rodas23WCache, Rodas3PConstantCache, Rodas3PCache}, idxs, T::Type{Val{0}}, differential_vars) Θ1 = 1 - Θ @@ -150,7 +150,7 @@ end end @muladd function _ode_interpolant!(out, Θ, dt, y₀, y₁, k, - cache::Union{Rodas4ConstantCache, Rodas4Cache, Rodas23WConstantCache, + cache::Union{Rodas4ConstantCache, RosenbrockCache, Rodas23WConstantCache, Rodas23WCache, Rodas3PConstantCache, Rodas3PCache}, idxs::Nothing, T::Type{Val{0}}, differential_vars) Θ1 = 1 - Θ @@ -159,7 +159,7 @@ end end @muladd function _ode_interpolant!(out, Θ, dt, y₀, y₁, k, - cache::Union{Rodas4ConstantCache, Rodas4Cache, Rodas23WConstantCache, + cache::Union{Rodas4ConstantCache, RosenbrockCache, Rodas23WConstantCache, Rodas23WCache, Rodas3PConstantCache, Rodas3PCache}, idxs, T::Type{Val{0}}, differential_vars) Θ1 = 1 - Θ @@ -176,14 +176,14 @@ end end @muladd function _ode_interpolant( - Θ, dt, y₀, y₁, k, cache::Union{Rodas4Cache, Rodas23WCache, Rodas3PCache}, + Θ, dt, y₀, y₁, k, cache::Union{RosenbrockCache, Rodas23WCache, Rodas3PCache}, idxs::Nothing, T::Type{Val{1}}, differential_vars) @inbounds @.. broadcast=false (k[1] + Θ * (-2 * k[1] + 2 * k[2] - 3 * k[2] * Θ) - y₀ + y₁)/dt end @muladd function _ode_interpolant(Θ, dt, y₀, y₁, k, - cache::Union{Rodas4ConstantCache, Rodas4Cache, Rodas23WConstantCache, + cache::Union{Rodas4ConstantCache, RosenbrockCache, Rodas23WConstantCache, Rodas23WCache, Rodas3PConstantCache, Rodas3PCache}, idxs, T::Type{Val{1}}, differential_vars) @.. broadcast=false (k[1][idxs] + @@ -192,7 +192,7 @@ end end @muladd function _ode_interpolant!(out, Θ, dt, y₀, y₁, k, - cache::Union{Rodas4ConstantCache, Rodas4Cache, Rodas23WConstantCache, + cache::Union{Rodas4ConstantCache, RosenbrockCache, Rodas23WConstantCache, Rodas23WCache, Rodas3PConstantCache, Rodas3PCache}, idxs::Nothing, T::Type{Val{1}}, differential_vars) @.. broadcast=false out=(k[1] + Θ * (-2 * k[1] + 2 * k[2] - 3 * k[2] * Θ) - y₀ + y₁) / @@ -201,7 +201,7 @@ end end @muladd function _ode_interpolant!(out, Θ, dt, y₀, y₁, k, - cache::Union{Rodas4ConstantCache, Rodas4Cache, Rodas23WConstantCache, + cache::Union{Rodas4ConstantCache, RosenbrockCache, Rodas23WConstantCache, Rodas23WCache, Rodas3PConstantCache, Rodas3PCache}, idxs, T::Type{Val{1}}, differential_vars) @views @.. broadcast=false out=(k[1][idxs] + diff --git a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl index a724abbc52..51c938ee39 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl @@ -1207,31 +1207,13 @@ function initialize!(integrator, cache::Rodas4ConstantCache) end @muladd function perform_step!(integrator, cache::Rodas4ConstantCache, repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack tf, uf = cache - @unpack a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, gamma, c2, c3, c4, d1, d2, d3, d4 = cache.tab + (;t, dt, uprev, u, f, p) = integrator + (;tf, uf) = cache + (;A, C, gamma, c, d, H) = cache.tab # Precalculations - dtC21 = C21 / dt - dtC31 = C31 / dt - dtC32 = C32 / dt - dtC41 = C41 / dt - dtC42 = C42 / dt - dtC43 = C43 / dt - dtC51 = C51 / dt - dtC52 = C52 / dt - dtC53 = C53 / dt - dtC54 = C54 / dt - dtC61 = C61 / dt - dtC62 = C62 / dt - dtC63 = C63 / dt - dtC64 = C64 / dt - dtC65 = C65 / dt - - dtd1 = dt * d1 - dtd2 = dt * d2 - dtd3 = dt * d3 - dtd4 = dt * d4 + dtC = C ./ dt + dtd = dt .* d dtgamma = dt * gamma mass_matrix = integrator.f.mass_matrix @@ -1246,105 +1228,78 @@ end return nothing end + # Initialize ks + num_stages = size(A,1) du = f(uprev, p, t) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - linsolve_tmp = du + dtd1 * dT - + linsolve_tmp = @.. du + dtd[1] * dT k1 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) - integrator.stats.nsolve += 1 - u = uprev + a21 * k1 - du = f(u, p, t + c2 * dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - linsolve_tmp = du + dtd2 * dT + dtC21 * k1 - else - linsolve_tmp = du + dtd2 * dT + mass_matrix * (dtC21 * k1) - end - - k2 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) - integrator.stats.nsolve += 1 - u = uprev + a31 * k1 + a32 * k2 - du = f(u, p, t + c3 * dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - linsolve_tmp = du + dtd3 * dT + (dtC31 * k1 + dtC32 * k2) - else - linsolve_tmp = du + dtd3 * dT + mass_matrix * (dtC31 * k1 + dtC32 * k2) - end - - k3 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) - integrator.stats.nsolve += 1 - u = uprev + a41 * k1 + a42 * k2 + a43 * k3 - du = f(u, p, t + c4 * dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - linsolve_tmp = du + dtd4 * dT + (dtC41 * k1 + dtC42 * k2 + dtC43 * k3) - else - linsolve_tmp = du + dtd4 * dT + mass_matrix * (dtC41 * k1 + dtC42 * k2 + dtC43 * k3) - end - - k4 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) - integrator.stats.nsolve += 1 - u = uprev + a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4 - du = f(u, p, t + dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + # constant number for type stability make sure this is greater than num_stages + ks = ntuple(Returns(k1), 10) + # Loop for stages + for stage in 2:num_stages + u = uprev + for i in 1:stage-1 + u = @.. u + A[stage, i] * ks[i] + end - if mass_matrix === I - linsolve_tmp = du + (dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + dtC53 * k3) - else - linsolve_tmp = du + - mass_matrix * (dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + dtC53 * k3) - end + du = f(u, p, t + c[stage] * dt) + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - k5 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) - integrator.stats.nsolve += 1 - u = u + k5 - du = f(u, p, t + dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + # Compute linsolve_tmp for current stage + linsolve_tmp = zero(du) + if mass_matrix === I + for i in 1:stage-1 + linsolve_tmp = @.. linsolve_tmp + dtC[stage, i] * ks[i] + end + else + for i in 1:stage-1 + linsolve_tmp = @.. linsolve_tmp + dtC[stage, i] * ks[i] + end + linsolve_tmp = mass_matrix * linsolve_tmp + end + linsolve_tmp = @.. du + dtd[stage] * dT + linsolve_tmp - if mass_matrix === I - linsolve_tmp = du + (dtC61 * k1 + dtC62 * k2 + dtC65 * k5 + dtC64 * k4 + dtC63 * k3) - else - linsolve_tmp = du + - mass_matrix * - (dtC61 * k1 + dtC62 * k2 + dtC65 * k5 + dtC64 * k4 + dtC63 * k3) + ks = Base.setindex(ks, _reshape(W \ -_vec(linsolve_tmp), axes(uprev)), stage) + integrator.stats.nsolve += 1 end - - k6 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) - integrator.stats.nsolve += 1 - u = u + k6 + #@show ks + u = u .+ ks[num_stages] if integrator.opts.adaptive - atmp = calculate_residuals(k6, uprev, u, integrator.opts.abstol, + atmp = calculate_residuals(ks[num_stages], uprev, u, integrator.opts.abstol, integrator.opts.reltol, integrator.opts.internalnorm, t) integrator.EEst = integrator.opts.internalnorm(atmp, t) end if integrator.opts.calck - @unpack h21, h22, h23, h24, h25, h31, h32, h33, h34, h35 = cache.tab - integrator.k[1] = h21 * k1 + h22 * k2 + h23 * k3 + h24 * k4 + h25 * k5 - integrator.k[2] = h31 * k1 + h32 * k2 + h33 * k3 + h34 * k4 + h35 * k5 + for j in eachindex(integrator.k) + integrator.k[j] = zero(integrator.k[1]) + end + for i in 1:num_stages + for j in eachindex(integrator.k) + integrator.k[j] = @.. integrator.k[j] + H[j, i] * ks[i] + end + end end + integrator.u = u return nothing end -function initialize!(integrator, cache::Rodas4Cache) +function initialize!(integrator, cache::RosenbrockCache) + dense = cache.dense + dense1, dense2 = dense[1], dense[2] integrator.kshortsize = 2 - @unpack dense1, dense2 = cache resize!(integrator.k, integrator.kshortsize) integrator.k[1] = dense1 integrator.k[2] = dense2 end -@muladd function perform_step!(integrator, cache::Rodas4Cache, repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack du, du1, du2, dT, J, W, uf, tf, k1, k2, k3, k4, k5, k6, linsolve_tmp, jac_config, atmp, weight, stage_limiter!, step_limiter! = cache - @unpack a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, gamma, c2, c3, c4, d1, d2, d3, d4 = cache.tab + +@muladd function perform_step!(integrator, cache::RosenbrockCache, repeat_step = false) + (;t, dt, uprev, u, f, p) = integrator + (;du, du1, du2, dT, J, W, uf, tf, ks, linsolve_tmp, jac_config, atmp, weight, stage_limiter!, step_limiter!) = cache + (;A, C, gamma, c, d, H) = cache.tab # Assignments sizeu = size(u) @@ -1352,32 +1307,14 @@ end mass_matrix = integrator.f.mass_matrix # Precalculations - dtC21 = C21 / dt - dtC31 = C31 / dt - dtC32 = C32 / dt - dtC41 = C41 / dt - dtC42 = C42 / dt - dtC43 = C43 / dt - dtC51 = C51 / dt - dtC52 = C52 / dt - dtC53 = C53 / dt - dtC54 = C54 / dt - dtC61 = C61 / dt - dtC62 = C62 / dt - dtC63 = C63 / dt - dtC64 = C64 / dt - dtC65 = C65 / dt - - dtd1 = dt * d1 - dtd2 = dt * d2 - dtd3 = dt * d3 - dtd4 = dt * d4 + dtC = C .* inv(dt) + dtd = dt .* d dtgamma = dt * gamma - f(cache.fsalfirst, uprev, p, t) # used in calc_rosenbrock_differentiation! + f(cache.fsalfirst, uprev, p, t) OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - calc_rosenbrock_differentiation!(integrator, cache, dtd1, dtgamma, repeat_step, true) + calc_rosenbrock_differentiation!(integrator, cache, dtd[1], dtgamma, repeat_step, true) calculate_residuals!(weight, fill!(weight, one(eltype(u))), uprev, uprev, integrator.opts.abstol, integrator.opts.reltol, @@ -1394,114 +1331,56 @@ end solverdata = (; gamma = dtgamma)) end - @.. broadcast=false $(_vec(k1))=-linres.u - - integrator.stats.nsolve += 1 - - @.. broadcast=false u=uprev + a21 * k1 - stage_limiter!(u, integrator, p, t + c2 * dt) - f(du, u, p, t + c2 * dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + dtd2 * dT + dtC21 * k1 - else - @.. broadcast=false du1=dtC21 * k1 - mul!(_vec(du2), mass_matrix, _vec(du1)) - @.. broadcast=false linsolve_tmp=du + dtd2 * dT + du2 - end - - linres = dolinsolve(integrator, linres.cache; b = _vec(linsolve_tmp)) - @.. broadcast=false $(_vec(k2))=-linres.u - integrator.stats.nsolve += 1 - - @.. broadcast=false u=uprev + a31 * k1 + a32 * k2 - stage_limiter!(u, integrator, p, t + c3 * dt) - f(du, u, p, t + c3 * dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + dtd3 * dT + (dtC31 * k1 + dtC32 * k2) - else - @.. broadcast=false du1=dtC31 * k1 + dtC32 * k2 - mul!(_vec(du2), mass_matrix, _vec(du1)) - @.. broadcast=false linsolve_tmp=du + dtd3 * dT + du2 - end - - linres = dolinsolve(integrator, linres.cache; b = _vec(linsolve_tmp)) - @.. broadcast=false $(_vec(k3))=-linres.u - integrator.stats.nsolve += 1 - - @.. broadcast=false u=uprev + a41 * k1 + a42 * k2 + a43 * k3 - stage_limiter!(u, integrator, p, t + c4 * dt) - f(du, u, p, t + c4 * dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + dtd4 * dT + - (dtC41 * k1 + dtC42 * k2 + dtC43 * k3) - else - @.. broadcast=false du1=dtC41 * k1 + dtC42 * k2 + dtC43 * k3 - mul!(_vec(du2), mass_matrix, _vec(du1)) - @.. broadcast=false linsolve_tmp=du + dtd4 * dT + du2 - end - - linres = dolinsolve(integrator, linres.cache; b = _vec(linsolve_tmp)) - @.. broadcast=false $(_vec(k4))=-linres.u + @.. $(_vec(ks[1]))=-linres.u integrator.stats.nsolve += 1 - @.. broadcast=false u=uprev + a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4 - stage_limiter!(u, integrator, p, t + dt) - f(du, u, p, t + dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + - (dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + dtC53 * k3) - else - @.. broadcast=false du1=dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + dtC53 * k3 - mul!(_vec(du2), mass_matrix, _vec(du1)) - @.. broadcast=false linsolve_tmp=du + du2 - end + for stage in 2:length(ks) + u .= uprev + for i in 1:stage-1 + @.. u += A[stage, i] * ks[i] + end - linres = dolinsolve(integrator, linres.cache; b = _vec(linsolve_tmp)) - @.. broadcast=false $(_vec(k5))=-linres.u - integrator.stats.nsolve += 1 + stage_limiter!(u, integrator, p, t + c[stage] * dt) + f(du, u, p, t + c[stage] * dt) + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - u .+= k5 - f(du, u, p, t + dt) - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + du1 .= 0 + if mass_matrix === I + for i in 1:stage-1 + @.. du1 += dtC[stage, i] * ks[i] + end + else + for i in 1:stage-1 + @.. du1 += dtC[stage, i] * ks[i] + end + mul!(_vec(du2), mass_matrix, _vec(du1)) + du1 .= du2 + end + @.. linsolve_tmp = du + dtd[stage] * dT + du1 - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + (dtC61 * k1 + dtC62 * k2 + dtC65 * k5 + - dtC64 * k4 + dtC63 * k3) - else - @.. broadcast=false du1=dtC61 * k1 + dtC62 * k2 + dtC65 * k5 + dtC64 * k4 + - dtC63 * k3 - mul!(_vec(du2), mass_matrix, _vec(du1)) - @.. broadcast=false linsolve_tmp=du + du2 + linres = dolinsolve(integrator, linres.cache; b = _vec(linsolve_tmp)) + @.. $(_vec(ks[stage]))=-linres.u + integrator.stats.nsolve += 1 end - - linres = dolinsolve(integrator, linres.cache; b = _vec(linsolve_tmp)) - @.. broadcast=false $(_vec(k6))=-linres.u - integrator.stats.nsolve += 1 - - u .+= k6 + u .+= ks[end] step_limiter!(u, integrator, p, t + dt) if integrator.opts.adaptive - calculate_residuals!(atmp, k6, uprev, u, integrator.opts.abstol, + calculate_residuals!(atmp, ks[end], uprev, u, integrator.opts.abstol, integrator.opts.reltol, integrator.opts.internalnorm, t) integrator.EEst = integrator.opts.internalnorm(atmp, t) end if integrator.opts.calck - @unpack h21, h22, h23, h24, h25, h31, h32, h33, h34, h35 = cache.tab - @.. broadcast=false integrator.k[1]=h21 * k1 + h22 * k2 + h23 * k3 + h24 * k4 + - h25 * k5 - @.. broadcast=false integrator.k[2]=h31 * k1 + h32 * k2 + h33 * k3 + h34 * k4 + - h35 * k5 + for j in eachindex(integrator.k) + integrator.k[j] .= 0 + end + for i in eachindex(ks) + for j in eachindex(integrator.k) + @.. integrator.k[j] += H[j, i] * ks[i] + end + end end cache.linsolve = linres.cache end diff --git a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_tableaus.jl b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_tableaus.jl index 493c67111a..19e7a989d7 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_tableaus.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_tableaus.jl @@ -223,161 +223,66 @@ end @Rosenbrock4(:tableau) struct RodasTableau{T, T2} - a21::T - a31::T - a32::T - a41::T - a42::T - a43::T - a51::T - a52::T - a53::T - a54::T - C21::T - C31::T - C32::T - C41::T - C42::T - C43::T - C51::T - C52::T - C53::T - C54::T - C61::T - C62::T - C63::T - C64::T - C65::T + A::Matrix{T} + C::Matrix{T} gamma::T - c2::T2 - c3::T2 - c4::T2 - d1::T - d2::T - d3::T - d4::T - h21::T - h22::T - h23::T - h24::T - h25::T - h31::T - h32::T - h33::T - h34::T - h35::T + c::Vector{T2} + d::Vector{T} + H::Matrix{T} end + function Rodas4Tableau(T, T2) gamma = convert(T, 1 // 4) #BET2P=0.0317D0 #BET3P=0.0635D0 #BET4P=0.3438D0 - a21 = convert(T, 1.544000000000000) - a31 = convert(T, 0.9466785280815826) - a32 = convert(T, 0.2557011698983284) - a41 = convert(T, 3.314825187068521) - a42 = convert(T, 2.896124015972201) - a43 = convert(T, 0.9986419139977817) - a51 = convert(T, 1.221224509226641) - a52 = convert(T, 6.019134481288629) - a53 = convert(T, 12.53708332932087) - a54 = -convert(T, 0.6878860361058950) - C21 = -convert(T, 5.668800000000000) - C31 = -convert(T, 2.430093356833875) - C32 = -convert(T, 0.2063599157091915) - C41 = -convert(T, 0.1073529058151375) - C42 = -convert(T, 9.594562251023355) - C43 = -convert(T, 20.47028614809616) - C51 = convert(T, 7.496443313967647) - C52 = -convert(T, 10.24680431464352) - C53 = -convert(T, 33.99990352819905) - C54 = convert(T, 11.70890893206160) - C61 = convert(T, 8.083246795921522) - C62 = -convert(T, 7.981132988064893) - C63 = -convert(T, 31.52159432874371) - C64 = convert(T, 16.31930543123136) - C65 = -convert(T, 6.058818238834054) - - c2 = convert(T2, 0.386) - c3 = convert(T2, 0.21) - c4 = convert(T2, 0.63) - - d1 = convert(T, 0.2500000000000000) - d2 = -convert(T, 0.1043000000000000) - d3 = convert(T, 0.1035000000000000) - d4 = -convert(T, 0.03620000000000023) - - h21 = convert(T, 10.12623508344586) - h22 = -convert(T, 7.487995877610167) - h23 = -convert(T, 34.80091861555747) - h24 = -convert(T, 7.992771707568823) - h25 = convert(T, 1.025137723295662) - h31 = -convert(T, 0.6762803392801253) - h32 = convert(T, 6.087714651680015) - h33 = convert(T, 16.43084320892478) - h34 = convert(T, 24.76722511418386) - h35 = -convert(T, 6.594389125716872) - - RodasTableau(a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, - C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, - gamma, c2, c3, c4, d1, d2, d3, d4, - h21, h22, h23, h24, h25, h31, h32, h33, h34, h35) + A = T[ + 0 0 0 0 0 0 + 1.544 0 0 0 0 0 + 0.9466785280815826 0.2557011698983284 0 0 0 0 + 3.314825187068521 2.896124015972201 0.9986419139977817 0 0 0 + 1.221224509226641 6.019134481288629 12.53708332932087 -0.6878860361058950 0 0 + 1.221224509226641 6.019134481288629 12.53708332932087 -0.6878860361058950 1 0 + ] + C = T[ + 0 0 0 0 0 + -5.6688 0 0 0 0 + -2.430093356833875 -0.2063599157091915 0 0 0 + -0.1073529058151375 -9.594562251023355 -20.47028614809616 0 0 + 7.496443313967647 -10.24680431464352 -33.99990352819905 11.70890893206160 0 + 8.083246795921522 -7.981132988064893 -31.52159432874371 16.31930543123136 -6.058818238834054 + ] + c = T2[0, 0.386, 0.21, 0.63, 1, 1] + d = T[0.25, -0.1043, 0.1035, -0.0362, 0, 0] + H = T[10.12623508344586 -7.487995877610167 -34.80091861555747 -7.992771707568823 1.025137723295662 0 + -0.6762803392801253 6.087714651680015 16.43084320892478 24.76722511418386 -6.594389125716872 0] + RodasTableau(A, C, gamma, c, d, H) end function Rodas42Tableau(T, T2) gamma = convert(T, 1 // 4) - #BET2P=0.0317D0 - #BET3P=0.0047369D0 - #BET4P=0.3438D0 - a21 = convert(T, 1.402888400000000) - a31 = convert(T, 0.6581212688557198) - a32 = -convert(T, 1.320936088384301) - a41 = convert(T, 7.131197445744498) - a42 = convert(T, 16.02964143958207) - a43 = -convert(T, 5.561572550509766) - a51 = convert(T, 22.73885722420363) - a52 = convert(T, 67.38147284535289) - a53 = -convert(T, 31.21877493038560) - a54 = convert(T, 0.7285641833203814) - C21 = -convert(T, 5.104353600000000) - C31 = -convert(T, 2.899967805418783) - C32 = convert(T, 4.040399359702244) - C41 = -convert(T, 32.64449927841361) - C42 = -convert(T, 99.35311008728094) - C43 = convert(T, 49.99119122405989) - C51 = -convert(T, 76.46023087151691) - C52 = -convert(T, 278.5942120829058) - C53 = convert(T, 153.9294840910643) - C54 = convert(T, 10.97101866258358) - C61 = -convert(T, 76.29701586804983) - C62 = -convert(T, 294.2795630511232) - C63 = convert(T, 162.0029695867566) - C64 = convert(T, 23.65166903095270) - C65 = -convert(T, 7.652977706771382) - c2 = convert(T2, 0.3507221) - c3 = convert(T2, 0.2557041) - c4 = convert(T2, 0.6817790) - d1 = convert(T, 0.2500000000000000) - d2 = -convert(T, 0.06902209999999998) - d3 = -convert(T, 0.0009671999999999459) - d4 = -convert(T, 0.08797900000000025) - - h21 = -convert(T, 38.71940424117216) - h22 = -convert(T, 135.8025833007622) - h23 = convert(T, 64.51068857505875) - h24 = -convert(T, 4.192663174613162) - h25 = -convert(T, 2.531932050335060) - h31 = -convert(T, 14.99268484949843) - h32 = -convert(T, 76.30242396627033) - h33 = convert(T, 58.65928432851416) - h34 = convert(T, 16.61359034616402) - h35 = -convert(T, 0.6758691794084156) - - RodasTableau(a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, - C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, - gamma, c2, c3, c4, d1, d2, d3, d4, - h21, h22, h23, h24, h25, h31, h32, h33, h34, h35) + A = T[ + 0.0 0 0 0 0 0 + 1.4028884 0 0 0 0 0 + 0.6581212688557198 -1.320936088384301 0 0 0 0 + 7.131197445744498 16.02964143958207 -5.561572550509766 0 0 0 + 22.73885722420363 67.38147284535289 -31.21877493038560 0.7285641833203814 0 0 + 22.73885722420363 67.38147284535289 -31.21877493038560 0.7285641833203814 1 0 + ] + C = T[ + 0 0 0 0 0 + -5.1043536 0 0 0 0 + -2.899967805418783 4.040399359702244 0 0 0 + -32.64449927841361 -99.35311008728094 49.99119122405989 0 0 + -76.46023087151691 -278.5942120829058 153.9294840910643 10.97101866258358 0 + -76.29701586804983 -294.2795630511232 162.0029695867566 23.65166903095270 -7.652977706771382 + ] + c = T2[0, 0.3507221, 0.2557041, 0.681779, 1, 1] + d = T[0.25, -0.0690221, -0.0009672, -0.087979, 0, 0] + H = T[-38.71940424117216 -135.8025833007622 64.51068857505875 -4.192663174613162 -2.531932050335060 0 + -14.99268484949843 -76.30242396627033 58.65928432851416 16.61359034616402 -0.6758691794084156 0] + RodasTableau(A, C, gamma, c, d, H) end function Rodas4PTableau(T, T2) @@ -385,108 +290,52 @@ function Rodas4PTableau(T, T2) #BET2P=0.D0 #BET3P=c3*c3*(c3/6.d0-GAMMA/2.d0)/(GAMMA*GAMMA) #BET4P=0.3438D0 - a21 = convert(T, 3) - a31 = convert(T, 1.831036793486759) - a32 = convert(T, 0.4955183967433795) - a41 = convert(T, 2.304376582692669) - a42 = -convert(T, 0.05249275245743001) - a43 = -convert(T, 1.176798761832782) - a51 = -convert(T, 7.170454962423024) - a52 = -convert(T, 4.741636671481785) - a53 = -convert(T, 16.31002631330971) - a54 = -convert(T, 1.062004044111401) - C21 = -convert(T, 12) - C31 = -convert(T, 8.791795173947035) - C32 = -convert(T, 2.207865586973518) - C41 = convert(T, 10.81793056857153) - C42 = convert(T, 6.780270611428266) - C43 = convert(T, 19.53485944642410) - C51 = convert(T, 34.19095006749676) - C52 = convert(T, 15.49671153725963) - C53 = convert(T, 54.74760875964130) - C54 = convert(T, 14.16005392148534) - C61 = convert(T, 34.62605830930532) - C62 = convert(T, 15.30084976114473) - C63 = convert(T, 56.99955578662667) - C64 = convert(T, 18.40807009793095) - C65 = -convert(T, 5.714285714285717) - c2 = convert(T2, 3 * gamma) - c3 = convert(T2, 0.21) - c4 = convert(T2, 0.63) - d1 = convert(T, 0.2500000000000000) - d2 = convert(T, -0.5000000000000000) - d3 = convert(T, -0.0235040000000000) - d4 = convert(T, -0.0362000000000000) - - h21 = convert(T, 25.09876703708589) - h22 = convert(T, 11.62013104361867) - h23 = convert(T, 28.49148307714626) - h24 = -convert(T, 5.664021568594133) - h25 = convert(T, 0) - h31 = convert(T, 1.638054557396973) - h32 = -convert(T, 0.7373619806678748) - h33 = convert(T, 8.477918219238990) - h34 = convert(T, 15.99253148779520) - h35 = -convert(T, 1.882352941176471) - - RodasTableau(a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, - C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, - gamma, c2, c3, c4, d1, d2, d3, d4, - h21, h22, h23, h24, h25, h31, h32, h33, h34, h35) + A = T[ + 0 0 0 0 0 0 + 3 0 0 0 0 0 + 1.831036793486759 0.4955183967433795 0 0 0 0 + 2.304376582692669 -0.05249275245743001 -1.176798761832782 0 0 0 + -7.170454962423024 -4.741636671481785 -16.31002631330971 -1.062004044111401 0 0 + -7.170454962423024 -4.741636671481785 -16.31002631330971 -1.062004044111401 1 0 + ] + C = T[ + 0 0 0 0 0 + -12 0 0 0 0 + -8.791795173947035 -2.207865586973518 0 0 0 + 10.81793056857153 6.780270611428266 19.53485944642410 0 0 + 34.19095006749676 15.49671153725963 54.74760875964130 14.16005392148534 0 + 34.62605830930532 15.30084976114473 56.99955578662667 18.40807009793095 -5.714285714285717 + ] + c = T2[0, 0.75, 0.21, 0.63, 1, 1] + d = T[0.25, -0.5, -0.023504, -0.0362, 0, 0] + H = T[25.09876703708589 11.62013104361867 28.49148307714626 -5.664021568594133 0 0 + 1.638054557396973 -0.7373619806678748 8.477918219238990 15.99253148779520 -1.882352941176471 0] + RodasTableau(A, C, gamma, c, d, H) end function Rodas4P2Tableau(T, T2) gamma = convert(T, 1 // 4) - a21 = convert(T, 3.000000000000000) - a31 = convert(T, 0.906377755268814) - a32 = -convert(T, 0.189707390391685) - a41 = convert(T, 3.758617027739064) - a42 = convert(T, 1.161741776019525) - a43 = -convert(T, 0.849258085312803) - a51 = convert(T, 7.089566927282776) - a52 = convert(T, 4.573591406461604) - a53 = -convert(T, 8.423496976860259) - a54 = -convert(T, 0.959280113459775) - - C21 = convert(T, -12.00000000000000) - C31 = convert(T, -6.354581592719008) - C32 = convert(T, 0.338972550544623) - C41 = convert(T, -8.575016317114033) - C42 = convert(T, -7.606483992117508) - C43 = convert(T, 12.224997650124820) - C51 = convert(T, -5.888975457523102) - C52 = convert(T, -8.157396617841821) - C53 = convert(T, 24.805546872612922) - C54 = convert(T, 12.790401512796979) - C61 = convert(T, -4.408651676063871) - C62 = convert(T, -6.692003137674639) - C63 = convert(T, 24.625568527593117) - C64 = convert(T, 16.627521966636085) - C65 = convert(T, -5.714285714285718) - - c2 = convert(T2, 0.750000000000000) - c3 = convert(T2, 0.321448134013046) - c4 = convert(T2, 0.519745732277726) - d1 = convert(T, 0.250000000000000) - d2 = convert(T, -0.500000000000000) - d3 = convert(T, -0.189532918363016) - d4 = convert(T, 0.085612108792769) - - h21 = convert(T, -5.323528268423303) - h22 = convert(T, -10.042123754867493) - h23 = convert(T, 17.175254928256965) - h24 = convert(T, -5.079931171878093) - h25 = convert(T, -0.016185991706112) - h31 = convert(T, 6.984505741529879) - h32 = convert(T, 6.914061169603662) - h33 = convert(T, -0.849178943070653) - h34 = convert(T, 18.104410789349338) - h35 = convert(T, -3.516963011559032) - - RodasTableau(a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, - C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, - gamma, c2, c3, c4, d1, d2, d3, d4, - h21, h22, h23, h24, h25, h31, h32, h33, h34, h35) + A = T[ + 0 0 0 0 0 0 + 3 0 0 0 0 0 + 0.906377755268814 -0.189707390391685 0 0 0 0 + 3.758617027739064 1.161741776019525 -0.849258085312803 0 0 0 + 7.089566927282776 4.573591406461604 -8.423496976860259 -0.959280113459775 0 0 + 7.089566927282776 4.573591406461604 -8.423496976860259 -0.959280113459775 1 0 + ] + C = T[ + 0 0 0 0 0 + -12 0 0 0 0 + -6.354581592719008 0.338972550544623 0 0 0 + -8.575016317114033 -7.606483992117508 12.224997650124820 0 0 + -5.888975457523102 -8.157396617841821 24.805546872612922 12.790401512796979 0 + -4.408651676063871 -6.692003137674639 24.625568527593117 16.627521966636085 -5.714285714285718 + ] + c = T2[0, 0.75, 0.321448134013046, 0.519745732277726, 1, 1] + d = T[0.25, -0.5, -0.189532918363016, 0.085612108792769, 0, 0] + H = [-5.323528268423303 -10.042123754867493 17.175254928256965 -5.079931171878093 -0.016185991706112 0 + 6.984505741529879 6.914061169603662 -0.849178943070653 18.104410789349338 -3.516963011559032 0] + RodasTableau(A, C, gamma, c, d, H) end struct Rodas5Tableau{T, T2} diff --git a/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl b/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl index 6e77125e14..57a643afc6 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl @@ -291,30 +291,12 @@ function _ode_addsteps!(k, t, uprev, u, dt, f, p, cache::Rodas4ConstantCache, always_calc_begin = false, allow_calc_end = true, force_calc_end = false) if length(k) < 2 || always_calc_begin - @unpack tf, uf = cache - @unpack a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, gamma, c2, c3, c4, d1, d2, d3, d4 = cache.tab + (;tf, uf) = cache + (;A, C, gamma, c, d, H) = cache.tab # Precalculations - dtC21 = C21 / dt - dtC31 = C31 / dt - dtC32 = C32 / dt - dtC41 = C41 / dt - dtC42 = C42 / dt - dtC43 = C43 / dt - dtC51 = C51 / dt - dtC52 = C52 / dt - dtC53 = C53 / dt - dtC54 = C54 / dt - dtC61 = C61 / dt - dtC62 = C62 / dt - dtC63 = C63 / dt - dtC64 = C64 / dt - dtC65 = C65 / dt - - dtd1 = dt * d1 - dtd2 = dt * d2 - dtd3 = dt * d3 - dtd4 = dt * d4 + dtC = C ./ dt + dtd = dt .* d dtgamma = dt * gamma mass_matrix = f.mass_matrix @@ -335,52 +317,60 @@ function _ode_addsteps!(k, t, uprev, u, dt, f, p, cache::Rodas4ConstantCache, J = ForwardDiff.derivative(uf, uprev) W = 1 / dtgamma - J end + + + num_stages = size(A,1) + du = f(u, p, t) + linsolve_tmp = @.. du + dtd[1] * dT + k1 = _reshape(W \ _vec(linsolve_tmp), axes(uprev)) + # constant number for type stability make sure this is greater than num_stages + ks = ntuple(Returns(k1), 10) + # Last stage doesn't affect ks + for stage in 2:num_stages-1 + u = uprev + for i in 1:stage-1 + u = @.. u + A[stage, i] * ks[i] + end + + du = f(u, p, t + c[stage] * dt) + + # Compute linsolve_tmp for current stage + linsolve_tmp = zero(du) + if mass_matrix === I + for i in 1:stage-1 + linsolve_tmp = @.. linsolve_tmp + dtC[stage, i] * ks[i] + end + else + for i in 1:stage-1 + linsolve_tmp = @.. linsolve_tmp + dtC[stage, i] * ks[i] + end + linsolve_tmp = mass_matrix * linsolve_tmp + end + linsolve_tmp = @.. du + dtd[stage] * dT + linsolve_tmp + ks = Base.setindex(ks, _reshape(W \ _vec(linsolve_tmp), axes(uprev)), stage) + end - du = f(uprev, p, t) - - linsolve_tmp = du + dtd1 * dT - - k1 = W \ linsolve_tmp - u = uprev + a21 * k1 - du = f(u, p, t + c2 * dt) - - linsolve_tmp = du + dtd2 * dT + dtC21 * k1 - - k2 = W \ linsolve_tmp - u = uprev + a31 * k1 + a32 * k2 - du = f(u, p, t + c3 * dt) - - linsolve_tmp = du + dtd3 * dT + (dtC31 * k1 + dtC32 * k2) - - k3 = W \ linsolve_tmp - u = uprev + a41 * k1 + a42 * k2 + a43 * k3 - du = f(u, p, t + c4 * dt) - - linsolve_tmp = du + dtd4 * dT + (dtC41 * k1 + dtC42 * k2 + dtC43 * k3) - - k4 = W \ linsolve_tmp - u = uprev + a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4 - du = f(u, p, t + dt) - - linsolve_tmp = du + (dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + dtC53 * k3) - - k5 = W \ linsolve_tmp + k1 = zero(ks[1]) + k2 = zero(ks[1]) + H = cache.tab.H + # Last stage doesn't affect ks + for i in 1:num_stages-1 + k1 = @.. k1 + H[1, i] * ks[i] + k2 = @.. k2 + H[2, i] * ks[i] + end - @unpack h21, h22, h23, h24, h25, h31, h32, h33, h34, h35 = cache.tab - k₁ = h21 * k1 + h22 * k2 + h23 * k3 + h24 * k4 + h25 * k5 - k₂ = h31 * k1 + h32 * k2 + h33 * k3 + h34 * k4 + h35 * k5 - copyat_or_push!(k, 1, k₁) - copyat_or_push!(k, 2, k₂) + copyat_or_push!(k, 1, k1) + copyat_or_push!(k, 2, k2) end nothing end -function _ode_addsteps!(k, t, uprev, u, dt, f, p, cache::Rodas4Cache, +function _ode_addsteps!(k, t, uprev, u, dt, f, p, cache::RosenbrockCache, always_calc_begin = false, allow_calc_end = true, force_calc_end = false) if length(k) < 2 || always_calc_begin - @unpack du, du1, du2, tmp, k1, k2, k3, k4, k5, k6, dT, J, W, uf, tf, linsolve_tmp, jac_config, fsalfirst, weight = cache - @unpack a21, a31, a32, a41, a42, a43, a51, a52, a53, a54, C21, C31, C32, C41, C42, C43, C51, C52, C53, C54, C61, C62, C63, C64, C65, gamma, c2, c3, c4, d1, d2, d3, d4 = cache.tab + (;du, du1, du2, tmp, ks, dT, J, W, uf, tf, linsolve_tmp, jac_config, fsalfirst, weight) = cache + (;A, C, gamma, c, d , H) = cache.tab # Assignments sizeu = size(u) @@ -388,114 +378,52 @@ function _ode_addsteps!(k, t, uprev, u, dt, f, p, cache::Rodas4Cache, mass_matrix = f.mass_matrix # Precalculations - dtC21 = C21 / dt - dtC31 = C31 / dt - dtC32 = C32 / dt - dtC41 = C41 / dt - dtC42 = C42 / dt - dtC43 = C43 / dt - dtC51 = C51 / dt - dtC52 = C52 / dt - dtC53 = C53 / dt - dtC54 = C54 / dt - dtC61 = C61 / dt - dtC62 = C62 / dt - dtC63 = C63 / dt - dtC64 = C64 / dt - dtC65 = C65 / dt - - dtd1 = dt * d1 - dtd2 = dt * d2 - dtd3 = dt * d3 - dtd4 = dt * d4 + dtC = C ./ dt + dtd = dt .* d dtgamma = dt * gamma - @.. broadcast=false linsolve_tmp=@muladd fsalfirst + dtgamma * dT + @.. linsolve_tmp=@muladd fsalfirst + dtgamma * dT - ### Jacobian does not need to be re-evaluated after an event - ### Since it's unchanged + # Jacobian does not need to be re-evaluated after an event since it's unchanged jacobian2W!(W, mass_matrix, dtgamma, J, true) linsolve = cache.linsolve - linres = dolinsolve(cache, linsolve; A = W, b = _vec(linsolve_tmp), - reltol = cache.reltol) - vecu = _vec(linres.u) - veck1 = _vec(k1) - - @.. broadcast=false veck1=-vecu - @.. broadcast=false tmp=uprev + a21 * k1 - f(du, tmp, p, t + c2 * dt) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + dtd2 * dT + dtC21 * k1 - else - @.. broadcast=false du1=dtC21 * k1 - mul!(du2, mass_matrix, du1) - @.. broadcast=false linsolve_tmp=du + dtd2 * dT + du2 - end - - linres = dolinsolve(cache, linres.cache; b = _vec(linsolve_tmp), - reltol = cache.reltol) - vecu = _vec(linres.u) - veck2 = _vec(k2) - @.. broadcast=false veck2=-vecu - @.. broadcast=false tmp=uprev + a31 * k1 + a32 * k2 - f(du, tmp, p, t + c3 * dt) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + dtd3 * dT + (dtC31 * k1 + dtC32 * k2) - else - @.. broadcast=false du1=dtC31 * k1 + dtC32 * k2 - mul!(du2, mass_matrix, du1) - @.. broadcast=false linsolve_tmp=du + dtd3 * dT + du2 - end - - linres = dolinsolve(cache, linres.cache; b = _vec(linsolve_tmp), - reltol = cache.reltol) - vecu = _vec(linres.u) - veck3 = _vec(k3) - @.. broadcast=false veck3=-vecu - @.. broadcast=false tmp=uprev + a41 * k1 + a42 * k2 + a43 * k3 - f(du, tmp, p, t + c4 * dt) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + dtd4 * dT + - (dtC41 * k1 + dtC42 * k2 + dtC43 * k3) - else - @.. broadcast=false du1=dtC41 * k1 + dtC42 * k2 + dtC43 * k3 - mul!(du2, mass_matrix, du1) - @.. broadcast=false linsolve_tmp=du + dtd4 * dT + du2 + linres = dolinsolve(cache, linsolve; A = W, b = _vec(linsolve_tmp), reltol = cache.reltol) + @.. $(_vec(ks[1]))=-linres.u + # Last stage doesn't affect ks + for stage in 2:length(ks)-1 + tmp .= uprev + for i in 1:stage-1 + @.. tmp += A[stage, i] * _vec(ks[i]) + end + f(du, tmp, p, t + c[stage] * dt) + + if mass_matrix === I + @.. linsolve_tmp = du + dtd[stage] * dT + for i in 1:stage-1 + @.. linsolve_tmp += dtC[stage, i] * _vec(ks[i]) + end + else + du1 .= du + for i in 1:stage-1 + @.. du1 += dtC[stage, i] * _vec(ks[i]) + end + mul!(_vec(du2), mass_matrix, _vec(du1)) + @.. linsolve_tmp = du + dtd[stage] * dT + du2 + end + + linres = dolinsolve(cache, linres.cache; b = _vec(linsolve_tmp), reltol = cache.reltol) + @.. $(_vec(ks[stage]))=-linres.u end - linres = dolinsolve(cache, linres.cache; b = _vec(linsolve_tmp), - reltol = cache.reltol) - vecu = _vec(linres.u) - veck4 = _vec(k4) - @.. broadcast=false veck4=-vecu - @.. broadcast=false tmp=uprev + a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4 - f(du, tmp, p, t + dt) - - if mass_matrix === I - @.. broadcast=false linsolve_tmp=du + (dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + - dtC53 * k3) - else - @.. broadcast=false du1=dtC52 * k2 + dtC54 * k4 + dtC51 * k1 + dtC53 * k3 - mul!(du2, mass_matrix, du1) - @.. broadcast=false linsolve_tmp=du + du2 + copyat_or_push!(k, 1, zero(du)) + copyat_or_push!(k, 2, zero(du)) + # Last stage doesn't affect ks + for i in 1:length(ks)-1 + @.. k[1] += H[1, i] * _vec(ks[i]) + @.. k[2] += H[2, i] * _vec(ks[i]) end - - linres = dolinsolve(cache, linres.cache; b = _vec(linsolve_tmp), - reltol = cache.reltol) - vecu = _vec(linres.u) - veck5 = _vec(k5) - @.. broadcast=false veck5=-vecu - @unpack h21, h22, h23, h24, h25, h31, h32, h33, h34, h35 = cache.tab - @.. broadcast=false k6=h21 * k1 + h22 * k2 + h23 * k3 + h24 * k4 + h25 * k5 - copyat_or_push!(k, 1, copy(k6)) - - @.. broadcast=false k6=h31 * k1 + h32 * k2 + h33 * k3 + h34 * k4 + h35 * k5 - copyat_or_push!(k, 2, copy(k6)) end nothing end diff --git a/lib/OrdinaryDiffEqSDIRK/src/OrdinaryDiffEqSDIRK.jl b/lib/OrdinaryDiffEqSDIRK/src/OrdinaryDiffEqSDIRK.jl index 0d8ff786a1..f9fc3bbd9e 100644 --- a/lib/OrdinaryDiffEqSDIRK/src/OrdinaryDiffEqSDIRK.jl +++ b/lib/OrdinaryDiffEqSDIRK/src/OrdinaryDiffEqSDIRK.jl @@ -13,7 +13,7 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, constvalue, _unwrap_val, _ode_interpolant, trivial_limiter!, _ode_interpolant!, isesdirk, issplit, - ssp_coefficient, get_fsalfirstlast + ssp_coefficient, get_fsalfirstlast, generic_solver_docstring using TruncatedStacktraces, MuladdMacro, MacroTools, FastBroadcast, RecursiveArrayTools using SciMLBase: SplitFunction using LinearAlgebra: mul!, I diff --git a/lib/OrdinaryDiffEqSDIRK/src/algorithms.jl b/lib/OrdinaryDiffEqSDIRK/src/algorithms.jl index 01f796f650..226f92e57f 100644 --- a/lib/OrdinaryDiffEqSDIRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqSDIRK/src/algorithms.jl @@ -1,9 +1,103 @@ -# SDIRK Methods -""" -ImplicitEuler: SDIRK Method -A 1st order implicit solver. A-B-L-stable. Adaptive timestepping through a divided differences estimate via memory. -Strong-stability preserving (SSP). -""" +function SDIRK_docstring(description::String, + name::String; + references::String = "", + extra_keyword_description::String = "", + extra_keyword_default::String = "") + keyword_default = """ + chunk_size = Val{0}(), + autodiff = true, + standardtag = Val{true}(), + concrete_jac = nothing, + diff_type = Val{:forward}, + linsolve = nothing, + precs = DEFAULT_PRECS, + nlsolve = NLNewton(), + """ * extra_keyword_default + + keyword_default_description = """ + - `chunk_size`: The chunk size used with ForwardDiff.jl. Defaults to `Val{0}()` + and thus uses the internal ForwardDiff.jl algorithm for the choice. + - `autodiff`: Specifies whether to use automatic differentiation via + [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite + differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl). + Defaults to `Val{true}()` for automatic differentiation. + - `standardtag`: Specifies whether to use package-specific tags instead of the + ForwardDiff default function-specific tags. For more information, see + [this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/). + Defaults to `Val{true}()`. + - `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to + `nothing`, which means it will be chosen true/false depending on circumstances + of the solver, such as whether a Krylov subspace method is used for `linsolve`. + - `diff_type`: The type of differentiation used in FiniteDiff.jl if `autodiff=false`. + Defaults to `Val{:forward}`, with alternatives of `Val{:central}` and + `Val{:complex}`. + - `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver. + For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify + `$name(linsolve = KLUFactorization()`). + When `nothing` is passed, uses `DefaultLinearSolver`. + - `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/) + can be used as a left or right preconditioner. + Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)` + function where the arguments are defined as: + - `W`: the current Jacobian of the nonlinear system. Specified as either + ``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will + commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy + representation of the operator. Users can construct the W-matrix on demand + by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching + the `jac_prototype`. + - `du`: the current ODE derivative + - `u`: the current ODE state + - `p`: the ODE parameters + - `t`: the current ODE time + - `newW`: a `Bool` which specifies whether the `W` matrix has been updated since + the last call to `precs`. It is recommended that this is checked to only + update the preconditioner when `newW == true`. + - `Plprev`: the previous `Pl`. + - `Prprev`: the previous `Pr`. + - `solverdata`: Optional extra data the solvers can give to the `precs` function. + Solver-dependent and subject to change. + The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners. + To specify one-sided preconditioning, simply return `nothing` for the preconditioner + which is not used. Additionally, `precs` must supply the dispatch: + ```julia + Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata) + ``` + which is used in the solver setup phase to construct the integrator + type with the preconditioners `(Pl,Pr)`. + The default is `precs=DEFAULT_PRECS` where the default preconditioner function + is defined as: + ```julia + DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing + ``` + - `nlsolve`: TBD + """ * extra_keyword_description + + generic_solver_docstring( + description, name, "SDIRK Method.", references, + keyword_default_description, keyword_default + ) +end + +@doc SDIRK_docstring("A 1st order implicit solver. A-B-L-stable. + Adaptive timestepping through a divided differences estimate via memory. + Strong-stability preserving (SSP).", + "ImplicitEuler"; + references = "@book{wanner1996solving, + title={Solving ordinary differential equations II}, + author={Wanner, Gerhard and Hairer, Ernst}, + volume={375}, + year={1996}, + publisher={Springer Berlin Heidelberg New York}}", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + extrapolant = :constant, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct ImplicitEuler{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -25,11 +119,24 @@ function ImplicitEuler(; chunk_size = Val{0}(), autodiff = Val{true}(), _unwrap_val(concrete_jac), typeof(step_limiter!)}(linsolve, nlsolve, precs, extrapolant, controller, step_limiter!) end -""" -ImplicitMidpoint: SDIRK Method -A second order A-stable symplectic and symmetric implicit solver. -Good for highly stiff equations which need symplectic integration. -""" + +@doc SDIRK_docstring("A second order A-stable symplectic and symmetric implicit solver. + Good for highly stiff equations which need symplectic integration.", + "ImplicitMidpoint"; + references = "@book{wanner1996solving, + title={Solving ordinary differential equations II}, + author={Wanner, Gerhard and Hairer, Ernst}, + volume={375}, + year={1996}, + publisher={Springer Berlin Heidelberg New York}}", + extra_keyword_description = """ + - `extrapolant`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + extrapolant = :linear, + step_limiter! = trivial_limiter!, + """) struct ImplicitMidpoint{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -53,17 +160,24 @@ function ImplicitMidpoint(; chunk_size = Val{0}(), autodiff = Val{true}(), step_limiter!) end -""" -Andre Vladimirescu. 1994. The Spice Book. John Wiley & Sons, Inc., New York, -NY, USA. - -Trapezoid: SDIRK Method -A second order A-stable symmetric ESDIRK method. +@doc SDIRK_docstring( + """Second order A-stable symmetric ESDIRK method. "Almost symplectic" without numerical dampening. Also known as Crank-Nicolson when applied to PDEs. Adaptive timestepping via divided differences approximation to the second derivative terms in the local truncation error -estimate (the SPICE approximation strategy). -""" +estimate (the SPICE approximation strategy).""", + "Trapezoid"; + references = "Andre Vladimirescu. 1994. The Spice Book. John Wiley & Sons, Inc., New York, NY, USA.", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct Trapezoid{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -90,22 +204,31 @@ function Trapezoid(; chunk_size = Val{0}(), autodiff = Val{true}(), step_limiter!) end -""" -@article{hosea1996analysis, -title={Analysis and implementation of TR-BDF2}, -author={Hosea, ME and Shampine, LF}, -journal={Applied Numerical Mathematics}, -volume={20}, -number={1-2}, -pages={21--37}, -year={1996}, -publisher={Elsevier} -} - -TRBDF2: SDIRK Method -A second order A-B-L-S-stable one-step ESDIRK method. -Includes stiffness-robust error estimates for accurate adaptive timestepping, smoothed derivatives for highly stiff and oscillatory problems. -""" +@doc SDIRK_docstring("A second order A-B-L-S-stable one-step ESDIRK method. + Includes stiffness-robust error estimates for accurate adaptive timestepping, + smoothed derivatives for highly stiff and oscillatory problems.", + "TRBDF2"; + references = "@article{hosea1996analysis, + title={Analysis and implementation of TR-BDF2}, + author={Hosea, ME and Shampine, LF}, + journal={Applied Numerical Mathematics}, + volume={20}, + number={1-2}, + pages={21--37}, + year={1996}, + publisher={Elsevier}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct TRBDF2{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -130,21 +253,29 @@ end TruncatedStacktraces.@truncate_stacktrace TRBDF2 -""" -@article{hindmarsh2005sundials, -title={{SUNDIALS}: Suite of nonlinear and differential/algebraic equation solvers}, -author={Hindmarsh, Alan C and Brown, Peter N and Grant, Keith E and Lee, Steven L and Serban, Radu and Shumaker, Dan E and Woodward, Carol S}, -journal={ACM Transactions on Mathematical Software (TOMS)}, -volume={31}, -number={3}, -pages={363--396}, -year={2005}, -publisher={ACM} -} - -SDIRK2: SDIRK Method -An A-B-L stable 2nd order SDIRK method -""" +@doc SDIRK_docstring("SDIRK2: SDIRK Method An A-B-L stable 2nd order SDIRK method", + "SDIRK2"; + references = "@article{hindmarsh2005sundials, + title={{SUNDIALS}: Suite of nonlinear and differential/algebraic equation solvers}, + author={Hindmarsh, Alan C and Brown, Peter N and Grant, Keith E and Lee, Steven L and Serban, Radu and Shumaker, Dan E and Woodward, Carol S}, + journal={ACM Transactions on Mathematical Software (TOMS)}, + volume={31}, + number={3}, + pages={363--396}, + year={2005}, + publisher={ACM}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct SDIRK2{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -169,6 +300,24 @@ function SDIRK2(; chunk_size = Val{0}(), autodiff = Val{true}(), standardtag = V step_limiter!) end +@doc SDIRK_docstring("Description TBD", + "SDIRK22"; + references = "@techreport{kennedy2016diagonally, + title={Diagonally implicit Runge-Kutta methods for ordinary differential equations. A review}, + author={Kennedy, Christopher A and Carpenter, Mark H}, + year={2016}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct SDIRK22{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -195,6 +344,32 @@ function SDIRK22(; step_limiter!) end +@doc SDIRK_docstring( + """SSPSDIRK is an SSP-optimized SDIRK method, +so it's an implicit SDIRK method for handling stiffness but if the `dt` is below the SSP `coefficient * dt`, +then the SSP property of the SSP integrators (the other page) is satisified. +As such this is a method which is expected to be good on advection-dominated cases where an explicit SSP integrator would be used, +but where reaction equations are sufficient stiff to justify implicit integration.""", + "SSPSDIRK2"; + references = "@article{ketcheson2009optimal, + title={Optimal implicit strong stability preserving Runge--Kutta methods}, + author={Ketcheson, David I and Macdonald, Colin B and Gottlieb, Sigal}, + journal={Applied Numerical Mathematics}, + volume={59}, + number={2}, + pages={373--392}, + year={2009}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :constant, + controller = :PI, + """) struct SSPSDIRK2{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} # Not adaptive linsolve::F @@ -217,21 +392,29 @@ function SSPSDIRK2(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@article{kvaerno2004singly, -title={Singly diagonally implicit Runge--Kutta methods with an explicit first stage}, -author={Kv{\\ae}rn{\\o}, Anne}, -journal={BIT Numerical Mathematics}, -volume={44}, -number={3}, -pages={489--502}, -year={2004}, -publisher={Springer} -} - -Kvaerno3: SDIRK Method -An A-L stable stiffly-accurate 3rd order ESDIRK method -""" +@doc SDIRK_docstring("An A-L stable stiffly-accurate 3rd order ESDIRK method.", + "Kvaerno3"; + references = "@article{kvaerno2004singly, + title={Singly diagonally implicit Runge--Kutta methods with an explicit first stage}, + author={Kv{\\ae}rn{\\o}, Anne}, + journal={BIT Numerical Mathematics}, + volume={44}, + number={3}, + pages={489--502}, + year={2004}, + publisher={Springer}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct Kvaerno3{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -254,17 +437,26 @@ function Kvaerno3(; chunk_size = Val{0}(), autodiff = Val{true}(), smooth_est, extrapolant, controller, step_limiter!) end -""" -@book{kennedy2001additive, -title={Additive Runge-Kutta schemes for convection-diffusion-reaction equations}, -author={Kennedy, Christopher Alan}, -year={2001}, -publisher={National Aeronautics and Space Administration, Langley Research Center} -} - -KenCarp3: SDIRK Method -An A-L stable stiffly-accurate 3rd order ESDIRK method with splitting -""" +@doc SDIRK_docstring( + "An A-L stable stiffly-accurate 3rd order ESDIRK method with splitting.", + "KenCarp3"; + references = "@book{kennedy2001additive, + title={Additive Runge-Kutta schemes for convection-diffusion-reaction equations}, + author={Kennedy, Christopher Alan}, + year={2001}, + publisher={National Aeronautics and Space Administration, Langley Research Center}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter!`: function of the form `limiter!(u, integrator, p, t)` + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct KenCarp3{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -287,6 +479,23 @@ function KenCarp3(; chunk_size = Val{0}(), autodiff = Val{true}(), smooth_est, extrapolant, controller, step_limiter!) end +@doc SDIRK_docstring("Third order method.", + "CFNLIRK3"; + references = "@article{calvo2001linearly, + title={Linearly implicit Runge--Kutta methods for advection--reaction--diffusion equations}, + author={Calvo, MP and De Frutos, J and Novo, J}, + journal={Applied Numerical Mathematics}, + volume={37}, + number={4}, + pages={535--549}, + year={2001}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `extrapolant`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + """) struct CFNLIRK3{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -307,21 +516,29 @@ function CFNLIRK3(; chunk_size = Val{0}(), autodiff = Val{true}(), extrapolant) end -""" -@article{hindmarsh2005sundials, -title={{SUNDIALS}: Suite of nonlinear and differential/algebraic equation solvers}, -author={Hindmarsh, Alan C and Brown, Peter N and Grant, Keith E and Lee, Steven L and Serban, Radu and Shumaker, Dan E and Woodward, Carol S}, -journal={ACM Transactions on Mathematical Software (TOMS)}, -volume={31}, -number={3}, -pages={363--396}, -year={2005}, -publisher={ACM} -} - -Cash4: SDIRK Method -An A-L stable 4th order SDIRK method -""" +@doc SDIRK_docstring("An A-L stable 4th order SDIRK method.", + "Cash4"; + references = "@article{hindmarsh2005sundials, + title={{SUNDIALS}: Suite of nonlinear and differential/algebraic equation solvers}, + author={Hindmarsh, Alan C and Brown, Peter N and Grant, Keith E and Lee, Steven L and Serban, Radu and Shumaker, Dan E and Woodward, Carol S}, + journal={ACM Transactions on Mathematical Software (TOMS)}, + volume={31}, + number={3}, + pages={363--396}, + year={2005}, + publisher={ACM}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `embedding`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + embedding = 3, + """) struct Cash4{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -349,6 +566,23 @@ function Cash4(; chunk_size = Val{0}(), autodiff = Val{true}(), standardtag = Va controller) end +@doc SDIRK_docstring("Method of order 4.", + "SFSDIRK4"; + references = "@article{ferracina2008strong, + title={Strong stability of singly-diagonally-implicit Runge--Kutta methods}, + author={Ferracina, Luca and Spijker, MN}, + journal={Applied Numerical Mathematics}, + volume={58}, + number={11}, + pages={1675--1686}, + year={2008}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `extrapolant`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + """) struct SFSDIRK4{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -369,6 +603,23 @@ function SFSDIRK4(; chunk_size = Val{0}(), autodiff = Val{true}(), extrapolant) end +@doc SDIRK_docstring("Method of order 5.", + "SFSDIRK5"; + references = "@article{ferracina2008strong, + title={Strong stability of singly-diagonally-implicit Runge--Kutta methods}, + author={Ferracina, Luca and Spijker, MN}, + journal={Applied Numerical Mathematics}, + volume={58}, + number={11}, + pages={1675--1686}, + year={2008}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `extrapolant`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + """) struct SFSDIRK5{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -390,6 +641,23 @@ function SFSDIRK5(; chunk_size = Val{0}(), autodiff = Val{true}(), extrapolant) end +@doc SDIRK_docstring("Method of order 6.", + "SFSDIRK6"; + references = "@article{ferracina2008strong, + title={Strong stability of singly-diagonally-implicit Runge--Kutta methods}, + author={Ferracina, Luca and Spijker, MN}, + journal={Applied Numerical Mathematics}, + volume={58}, + number={11}, + pages={1675--1686}, + year={2008}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `extrapolant`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + """) struct SFSDIRK6{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -411,6 +679,23 @@ function SFSDIRK6(; chunk_size = Val{0}(), autodiff = Val{true}(), extrapolant) end +@doc SDIRK_docstring("Method of order 7.", + "SFSDIRK7"; + references = "@article{ferracina2008strong, + title={Strong stability of singly-diagonally-implicit Runge--Kutta methods}, + author={Ferracina, Luca and Spijker, MN}, + journal={Applied Numerical Mathematics}, + volume={58}, + number={11}, + pages={1675--1686}, + year={2008}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `extrapolant`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + """) struct SFSDIRK7{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -432,6 +717,23 @@ function SFSDIRK7(; chunk_size = Val{0}(), autodiff = Val{true}(), extrapolant) end +@doc SDIRK_docstring("Method of order 8.", + "SFSDIRK8"; + references = "@article{ferracina2008strong, + title={Strong stability of singly-diagonally-implicit Runge--Kutta methods}, + author={Ferracina, Luca and Spijker, MN}, + journal={Applied Numerical Mathematics}, + volume={58}, + number={11}, + pages={1675--1686}, + year={2008}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `extrapolant`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + """) struct SFSDIRK8{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -453,14 +755,21 @@ function SFSDIRK8(; chunk_size = Val{0}(), autodiff = Val{true}(), extrapolant) end -""" -E. Hairer, G. Wanner, Solving ordinary differential equations II, stiff and -differential-algebraic problems. Computational mathematics (2nd revised ed.), -Springer (1996) - -Hairer4: SDIRK Method -An A-L stable 4th order SDIRK method -""" +@doc SDIRK_docstring("An A-L stable 4th order SDIRK method.", + "Hairer4"; + references = "E. Hairer, G. Wanner, Solving ordinary differential equations II, stiff and + differential-algebraic problems. Computational mathematics (2nd revised ed.), + Springer (1996)", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + """) struct Hairer4{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -482,14 +791,21 @@ function Hairer4(; controller) end -""" -E. Hairer, G. Wanner, Solving ordinary differential equations II, stiff and -differential-algebraic problems. Computational mathematics (2nd revised ed.), -Springer (1996) - -Hairer42: SDIRK Method -An A-L stable 4th order SDIRK method -""" +@doc SDIRK_docstring("An A-L stable 4th order SDIRK method.", + "Hairer42"; + references = "E. Hairer, G. Wanner, Solving ordinary differential equations II, stiff and + differential-algebraic problems. Computational mathematics (2nd revised ed.), + Springer (1996)", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + """) struct Hairer42{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -511,21 +827,29 @@ function Hairer42(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@article{kvaerno2004singly, -title={Singly diagonally implicit Runge--Kutta methods with an explicit first stage}, -author={Kv{\\ae}rn{\\o}, Anne}, -journal={BIT Numerical Mathematics}, -volume={44}, -number={3}, -pages={489--502}, -year={2004}, -publisher={Springer} -} - -Kvaerno4: SDIRK Method -An A-L stable stiffly-accurate 4th order ESDIRK method. -""" +@doc SDIRK_docstring("An A-L stable stiffly-accurate 4th order ESDIRK method.", + "Kvaerno4"; + references = "@article{kvaerno2004singly, + title={Singly diagonally implicit Runge--Kutta methods with an explicit first stage}, + author={Kv{\\ae}rn{\\o}, Anne}, + journal={BIT Numerical Mathematics}, + volume={44}, + number={3}, + pages={489--502}, + year={2004}, + publisher={Springer}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct Kvaerno4{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -548,21 +872,29 @@ function Kvaerno4(; chunk_size = Val{0}(), autodiff = Val{true}(), smooth_est, extrapolant, controller, step_limiter!) end -""" -@article{kvaerno2004singly, -title={Singly diagonally implicit Runge--Kutta methods with an explicit first stage}, -author={Kv{\\ae}rn{\\o}, Anne}, -journal={BIT Numerical Mathematics}, -volume={44}, -number={3}, -pages={489--502}, -year={2004}, -publisher={Springer} -} - -Kvaerno5: SDIRK Method -An A-L stable stiffly-accurate 5th order ESDIRK method -""" +@doc SDIRK_docstring("An A-L stable stiffly-accurate 5th order ESDIRK method.", + "Kvaerno5"; + references = "@article{kvaerno2004singly, + title={Singly diagonally implicit Runge--Kutta methods with an explicit first stage}, + author={Kv{\\ae}rn{\\o}, Anne}, + journal={BIT Numerical Mathematics}, + volume={44}, + number={3}, + pages={489--502}, + year={2004}, + publisher={Springer}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct Kvaerno5{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -585,17 +917,26 @@ function Kvaerno5(; chunk_size = Val{0}(), autodiff = Val{true}(), smooth_est, extrapolant, controller, step_limiter!) end -""" -@book{kennedy2001additive, -title={Additive Runge-Kutta schemes for convection-diffusion-reaction equations}, -author={Kennedy, Christopher Alan}, -year={2001}, -publisher={National Aeronautics and Space Administration, Langley Research Center} -} - -KenCarp4: SDIRK Method -An A-L stable stiffly-accurate 4th order ESDIRK method with splitting -""" +@doc SDIRK_docstring( + "An A-L stable stiffly-accurate 4th order ESDIRK method with splitting.", + "KenCarp4"; + references = "@book{kennedy2001additive, + title={Additive Runge-Kutta schemes for convection-diffusion-reaction equations}, + author={Kennedy, Christopher Alan}, + year={2001}, + publisher={National Aeronautics and Space Administration, Langley Research Center}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct KenCarp4{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -620,20 +961,27 @@ end TruncatedStacktraces.@truncate_stacktrace KenCarp4 -""" -@article{kennedy2019higher, -title={Higher-order additive Runge--Kutta schemes for ordinary differential equations}, -author={Kennedy, Christopher A and Carpenter, Mark H}, -journal={Applied Numerical Mathematics}, -volume={136}, -pages={183--205}, -year={2019}, -publisher={Elsevier} -} - -KenCarp47: SDIRK Method -An A-L stable stiffly-accurate 4th order seven-stage ESDIRK method with splitting -""" +@doc SDIRK_docstring( + "An A-L stable stiffly-accurate 4th order seven-stage ESDIRK method with splitting.", + "KenCarp47"; + references = "@article{kennedy2019higher, + title={Higher-order additive Runge--Kutta schemes for ordinary differential equations}, + author={Kennedy, Christopher A and Carpenter, Mark H}, + journal={Applied Numerical Mathematics}, + volume={136}, + pages={183--205}, + year={2019}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + """) struct KenCarp47{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -655,17 +1003,26 @@ function KenCarp47(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@book{kennedy2001additive, -title={Additive Runge-Kutta schemes for convection-diffusion-reaction equations}, -author={Kennedy, Christopher Alan}, -year={2001}, -publisher={National Aeronautics and Space Administration, Langley Research Center} -} - -KenCarp5: SDIRK Method -An A-L stable stiffly-accurate 5th order ESDIRK method with splitting -""" +@doc SDIRK_docstring( + "An A-L stable stiffly-accurate 5th order ESDIRK method with splitting.", + "KenCarp5"; + references = "@book{kennedy2001additive, + title={Additive Runge-Kutta schemes for convection-diffusion-reaction equations}, + author={Kennedy, Christopher Alan}, + year={2001}, + publisher={National Aeronautics and Space Administration, Langley Research Center}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + - `step_limiter`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + step_limiter! = trivial_limiter!, + """) struct KenCarp5{CS, AD, F, F2, P, FDT, ST, CJ, StepLimiter} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -687,20 +1044,28 @@ function KenCarp5(; chunk_size = Val{0}(), autodiff = Val{true}(), _unwrap_val(concrete_jac), typeof(step_limiter!)}(linsolve, nlsolve, precs, smooth_est, extrapolant, controller, step_limiter!) end -""" -@article{kennedy2019higher, -title={Higher-order additive Runge--Kutta schemes for ordinary differential equations}, -author={Kennedy, Christopher A and Carpenter, Mark H}, -journal={Applied Numerical Mathematics}, -volume={136}, -pages={183--205}, -year={2019}, -publisher={Elsevier} -} - -KenCarp58: SDIRK Method -An A-L stable stiffly-accurate 5th order eight-stage ESDIRK method with splitting -""" + +@doc SDIRK_docstring( + "An A-L stable stiffly-accurate 5th order eight-stage ESDIRK method with splitting.", + "KenCarp58"; + references = "@article{kennedy2019higher, + title={Higher-order additive Runge--Kutta schemes for ordinary differential equations}, + author={Kennedy, Christopher A and Carpenter, Mark H}, + journal={Applied Numerical Mathematics}, + volume={136}, + pages={183--205}, + year={2019}, + publisher={Elsevier}}", + extra_keyword_description = """ + - `smooth_est`: TBD + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + smooth_est = true, + extrapolant = :linear, + controller = :PI, + """) struct KenCarp58{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -723,6 +1088,27 @@ function KenCarp58(; chunk_size = Val{0}(), autodiff = Val{true}(), end # `smooth_est` is not necessary, as the embedded method is also L-stable +@doc SDIRK_docstring( + "Optimized ESDIRK tableaus. +Updates of the original KenCarp tableau expected to achieve lower error for the same steps in theory, +but are still being fully evaluated in context.", + "ESDIRK54I8L2SA"; + references = """@article{Kennedy2019DiagonallyIR, + title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, + author={Christopher A. Kennedy and Mark H. Carpenter}, + journal={Applied Numerical Mathematics}, + year={2019}, + volume={146}, + pages={221-244} + }""", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + controller = :PI, + """) struct ESDIRK54I8L2SA{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -742,16 +1128,27 @@ function ESDIRK54I8L2SA(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@article{Kennedy2019DiagonallyIR, -title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, -author={Christopher A. Kennedy and Mark H. Carpenter}, -journal={Applied Numerical Mathematics}, -year={2019}, -volume={146}, -pages={221-244} -} -""" +@doc SDIRK_docstring( + "Optimized ESDIRK tableaus. +Updates of the original KenCarp tableau expected to achieve lower error for the same steps in theory, +but are still being fully evaluated in context.", + "ESDIRK436L2SA2"; + references = """@article{Kennedy2019DiagonallyIR, + title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, + author={Christopher A. Kennedy and Mark H. Carpenter}, + journal={Applied Numerical Mathematics}, + year={2019}, + volume={146}, + pages={221-244} + }""", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + controller = :PI, + """) struct ESDIRK436L2SA2{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -771,16 +1168,27 @@ function ESDIRK436L2SA2(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@article{Kennedy2019DiagonallyIR, -title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, -author={Christopher A. Kennedy and Mark H. Carpenter}, -journal={Applied Numerical Mathematics}, -year={2019}, -volume={146}, -pages={221-244} -} -""" +@doc SDIRK_docstring( + "Optimized ESDIRK tableaus. +Updates of the original KenCarp tableau expected to achieve lower error for the same steps in theory, +but are still being fully evaluated in context.", + "ESDIRK437L2SA"; + references = """@article{Kennedy2019DiagonallyIR, + title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, + author={Christopher A. Kennedy and Mark H. Carpenter}, + journal={Applied Numerical Mathematics}, + year={2019}, + volume={146}, + pages={221-244} + }""", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + controller = :PI, + """) struct ESDIRK437L2SA{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -800,16 +1208,27 @@ function ESDIRK437L2SA(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@article{Kennedy2019DiagonallyIR, -title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, -author={Christopher A. Kennedy and Mark H. Carpenter}, -journal={Applied Numerical Mathematics}, -year={2019}, -volume={146}, -pages={221-244} -} -""" +@doc SDIRK_docstring( + "Optimized ESDIRK tableaus. +Updates of the original KenCarp tableau expected to achieve lower error for the same steps in theory, +but are still being fully evaluated in context.", + "ESDIRK547L2SA2"; + references = """@article{Kennedy2019DiagonallyIR, + title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, + author={Christopher A. Kennedy and Mark H. Carpenter}, + journal={Applied Numerical Mathematics}, + year={2019}, + volume={146}, + pages={221-244} + }""", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + controller = :PI, + """) struct ESDIRK547L2SA2{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F @@ -829,19 +1248,29 @@ function ESDIRK547L2SA2(; chunk_size = Val{0}(), autodiff = Val{true}(), controller) end -""" -@article{Kennedy2019DiagonallyIR, -title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, -author={Christopher A. Kennedy and Mark H. Carpenter}, -journal={Applied Numerical Mathematics}, -year={2019}, -volume={146}, -pages={221-244} - +@doc SDIRK_docstring( + "Optimized ESDIRK tableaus. +Updates of the original KenCarp tableau expected to achieve lower error for the same steps in theory, +but are still being fully evaluated in context. Currently has STABILITY ISSUES, causing it to fail the adaptive tests. -Check issue https://github.com/SciML/OrdinaryDiffEq.jl/issues/1933 for more details. -} -""" +Check issue https://github.com/SciML/OrdinaryDiffEq.jl/issues/1933 for more details.", + "ESDIRK659L2SA"; + references = """@article{Kennedy2019DiagonallyIR, + title={Diagonally implicit Runge–Kutta methods for stiff ODEs}, + author={Christopher A. Kennedy and Mark H. Carpenter}, + journal={Applied Numerical Mathematics}, + year={2019}, + volume={146}, + pages={221-244} + }""", + extra_keyword_description = """ + - `extrapolant`: TBD + - `controller`: TBD + """, + extra_keyword_default = """ + extrapolant = :linear, + controller = :PI, + """) struct ESDIRK659L2SA{CS, AD, F, F2, P, FDT, ST, CJ} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F diff --git a/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl b/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl index efe6a1ef75..f28ca2b71a 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl @@ -320,8 +320,17 @@ function SSPRK33(stage_limiter!, step_limiter! = trivial_limiter!) step_limiter!, False()) end -@doc explicit_rk_docstring("TBD", - "KYKSSPRK42") +@doc explicit_rk_docstring( + "Optimal strong-stability-preserving Runge-Kutta time discretizations for discontinuous Galerkin methods", + "KYKSSPRK42", + references = "@article{kubatko2014optimal, + title={Optimal strong-stability-preserving Runge--Kutta time discretizations for discontinuous Galerkin methods}, + author={Kubatko, Ethan J and Yeager, Benjamin A and Ketcheson, David I}, + journal={Journal of Scientific Computing}, + volume={60}, + pages={313--344}, + year={2014}, + publisher={Springer}}") Base.@kwdef struct KYKSSPRK42{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm stage_limiter!::StageLimiter = trivial_limiter! step_limiter!::StepLimiter = trivial_limiter! @@ -334,8 +343,17 @@ function KYKSSPRK42(stage_limiter!, step_limiter! = trivial_limiter!) False()) end -@doc explicit_rk_docstring("TBD", - "KYK2014DGSSPRK_3S2") +@doc explicit_rk_docstring( + "Optimal strong-stability-preserving Runge-Kutta time discretizations for discontinuous Galerkin methods", + "KYK2014DGSSPRK_3S2", + references = """@article{kubatko2014optimal, + title={Optimal strong-stability-preserving Runge--Kutta time discretizations for discontinuous Galerkin methods}, + author={Kubatko, Ethan J and Yeager, Benjamin A and Ketcheson, David I}, + journal={Journal of Scientific Computing}, + volume={60}, + pages={313--344}, + year={2014}, + publisher={Springer}}""") Base.@kwdef struct KYK2014DGSSPRK_3S2{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm stage_limiter!::StageLimiter = trivial_limiter! @@ -347,4 +365,4 @@ function KYK2014DGSSPRK_3S2(stage_limiter!, step_limiter! = trivial_limiter!) KYK2014DGSSPRK_3S2(stage_limiter!, step_limiter!, False()) -end \ No newline at end of file +end diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl index 443166b9fd..e38f302891 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl @@ -1,8 +1,9 @@ abstract type SSPRKMutableCache <: OrdinaryDiffEqMutableCache end abstract type SSPRKConstantCache <: OrdinaryDiffEqConstantCache end -get_fsalfirstlast(cache::SSPRKMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::SSPRKMutableCache, u) = (cache.fsalfirst, cache.k) -@cache struct SSPRK22Cache{uType, rateType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK22Cache{uType, rateType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -34,7 +35,8 @@ function alg_cache(alg::SSPRK22, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK22ConstantCache() end -@cache struct SSPRK33Cache{uType, rateType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK33Cache{uType, rateType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -144,7 +146,8 @@ function alg_cache(alg::KYKSSPRK42, u, rate_prototype, ::Type{uEltypeNoUnits}, KYKSSPRK42ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SSPRK53Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK53Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -363,7 +366,8 @@ function alg_cache(alg::SSPRK53_2N2, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK53_2N2ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SSPRK53_HCache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK53_HCache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -434,7 +438,8 @@ function alg_cache(alg::SSPRK53_H, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK53_HConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SSPRK63Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK63Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -512,7 +517,8 @@ function alg_cache(alg::SSPRK63, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK63ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SSPRK73Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK73Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -599,7 +605,8 @@ function alg_cache(alg::SSPRK73, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK73ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SSPRK83Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK83Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -961,7 +968,8 @@ function alg_cache(alg::SSPRK932, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK932ConstantCache() end -@cache struct SSPRK54Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK54Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -1049,7 +1057,8 @@ function alg_cache(alg::SSPRK54, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK54ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SSPRK104Cache{uType, rateType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SSPRK104Cache{uType, rateType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -1161,4 +1170,4 @@ function alg_cache(alg::KYK2014DGSSPRK_3S2, u, rate_prototype, ::Type{uEltypeNoU ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} KYK2014DGSSPRK_3S2_ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) -end \ No newline at end of file +end diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl index 2d5ed7ca7d..21109ec47a 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl @@ -1516,4 +1516,4 @@ end f(integrator.k[2], u, p, t + dt) # For interpolation, then FSAL'd OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) return nothing -end \ No newline at end of file +end diff --git a/lib/OrdinaryDiffEqStabilizedIRK/src/OrdinaryDiffEqStabilizedIRK.jl b/lib/OrdinaryDiffEqStabilizedIRK/src/OrdinaryDiffEqStabilizedIRK.jl index cd2cfa4a5f..f16310de7e 100644 --- a/lib/OrdinaryDiffEqStabilizedIRK/src/OrdinaryDiffEqStabilizedIRK.jl +++ b/lib/OrdinaryDiffEqStabilizedIRK/src/OrdinaryDiffEqStabilizedIRK.jl @@ -10,7 +10,8 @@ import OrdinaryDiffEqCore: alg_order, alg_maximum_order, OrdinaryDiffEqAdaptiveAlgorithm, OrdinaryDiffEqAdaptiveImplicitAlgorithm, alg_cache, _unwrap_val, DEFAULT_PRECS, @cache, - _reshape, _vec, full_cache, get_fsalfirstlast + _reshape, _vec, full_cache, get_fsalfirstlast, + generic_solver_docstring using OrdinaryDiffEqDifferentiation: dolinsolve, update_W! using OrdinaryDiffEqNonlinearSolve: NLNewton, nlsolve!, isnewton, build_nlsolver, diff --git a/lib/OrdinaryDiffEqStabilizedIRK/src/algorithms.jl b/lib/OrdinaryDiffEqStabilizedIRK/src/algorithms.jl index 1a59689554..85cf0825fa 100644 --- a/lib/OrdinaryDiffEqStabilizedIRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqStabilizedIRK/src/algorithms.jl @@ -1,3 +1,12 @@ +@doc generic_solver_docstring("Implicit Runge-Kutta-Chebyshev method.", + "IRKC", + "Stabalized Implicit Runge Kutta method.", + "REF TBD", + "- `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration.", + "eigen_est = nothing,") struct IRKC{CS, AD, F, F2, P, FDT, ST, CJ, K, T, E} <: OrdinaryDiffEqNewtonAdaptiveAlgorithm{CS, AD, FDT, ST, CJ} linsolve::F diff --git a/lib/OrdinaryDiffEqStabilizedRK/src/OrdinaryDiffEqStabilizedRK.jl b/lib/OrdinaryDiffEqStabilizedRK/src/OrdinaryDiffEqStabilizedRK.jl index 10a03b8d2b..d9ad47342e 100644 --- a/lib/OrdinaryDiffEqStabilizedRK/src/OrdinaryDiffEqStabilizedRK.jl +++ b/lib/OrdinaryDiffEqStabilizedRK/src/OrdinaryDiffEqStabilizedRK.jl @@ -9,7 +9,8 @@ import OrdinaryDiffEqCore: alg_order, alg_adaptive_order, calculate_residuals!, OrdinaryDiffEqMutableCache, OrdinaryDiffEqConstantCache, OrdinaryDiffEqAdaptiveAlgorithm, calc_dt_propose!, alg_cache, _vec, _reshape, @cache, - constvalue, _unwrap_val, full_cache, get_fsalfirstlast + constvalue, _unwrap_val, full_cache, get_fsalfirstlast, + generic_solver_docstring using FastBroadcast, MuladdMacro, RecursiveArrayTools import StaticArrays: SArray, MVector, SVector, @SVector, StaticArray, MMatrix, SA import OrdinaryDiffEqCore diff --git a/lib/OrdinaryDiffEqStabilizedRK/src/algorithms.jl b/lib/OrdinaryDiffEqStabilizedRK/src/algorithms.jl index de7c9228e7..7102b4ab26 100644 --- a/lib/OrdinaryDiffEqStabilizedRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqStabilizedRK/src/algorithms.jl @@ -1,19 +1,24 @@ -""" -Assyr Abdulle, Alexei A. Medovikov. Second Order Chebyshev Methods based on Orthogonal Polynomials. -Numerische Mathematik, 90 (1), pp 1-18, 2001. doi: https://dx.doi.org/10.1007/s002110100292 -ROCK2: Stabilized Explicit Method. -Second order stabilized Runge-Kutta method. -Exhibits high stability for real eigenvalues and is smoothened to allow for moderate sized complex eigenvalues. - -This method takes optional keyword arguments `min_stages`, `max_stages`, and `eigen_est`. -The function `eigen_est` should be of the form - -`eigen_est = (integrator) -> integrator.eigen_est = upper_bound`, - -where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. If `eigen_est` -is not provided, `upper_bound` will be estimated using the power iteration. -""" +@doc generic_solver_docstring( + """Second order method. Exhibits high stability for real eigenvalues +and is smoothened to allow for moderate sized complex eigenvalues.""", + "ROCK2", + "Stabilized Explicit Method.", + """Assyr Abdulle, Alexei A. Medovikov. Second Order Chebyshev Methods based on Orthogonal Polynomials. + Numerische Mathematik, 90 (1), pp 1-18, 2001. doi: https://dx.doi.org/10.1007/s002110100292""", + """ + - `min_stages`: The minimum degree of the Chebyshev polynomial. + - `max_stages`: The maximumdegree of the Chebyshev polynomial. + - `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. + """, + """ + min_stages = 0, + max_stages = 200, + eigen_est = nothing, + """) struct ROCK2{E} <: OrdinaryDiffEqAdaptiveAlgorithm min_stages::Int max_stages::Int @@ -23,25 +28,27 @@ function ROCK2(; min_stages = 0, max_stages = 200, eigen_est = nothing) ROCK2(min_stages, max_stages, eigen_est) end -""" - ROCK4(; min_stages = 0, max_stages = 152, eigen_est = nothing) - -Assyr Abdulle. Fourth Order Chebyshev Methods With Recurrence Relation. 2002 Society for -Industrial and Applied Mathematics Journal on Scientific Computing, 23(6), pp 2041-2054, 2001. -doi: https://doi.org/10.1137/S1064827500379549 - -ROCK4: Stabilized Explicit Method. -Fourth order stabilized Runge-Kutta method. -Exhibits high stability for real eigenvalues and is smoothened to allow for moderate sized complex eigenvalues. - -This method takes optional keyword arguments `min_stages`, `max_stages`, and `eigen_est`. -The function `eigen_est` should be of the form - -`eigen_est = (integrator) -> integrator.eigen_est = upper_bound`, - -where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. If `eigen_est` -is not provided, `upper_bound` will be estimated using the power iteration. -""" +@doc generic_solver_docstring( + """Fourth order method. Exhibits high stability for real eigenvalues +and is smoothened to allow for moderate sized complex eigenvalues.""", + "ROCK4", + "Stabilized Explicit Method.", + """Assyr Abdulle. Fourth Order Chebyshev Methods With Recurrence Relation. 2002 Society for + Industrial and Applied Mathematics Journal on Scientific Computing, 23(6), pp 2041-2054, 2001. + doi: https://doi.org/10.1137/S1064827500379549""", + """ + - `min_stages`: The minimum degree of the Chebyshev polynomial. + - `max_stages`: The maximumdegree of the Chebyshev polynomial. + - `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. + """, + """ + min_stages = 0, + max_stages = 152, + eigen_est = nothing, + """) struct ROCK4{E} <: OrdinaryDiffEqAdaptiveAlgorithm min_stages::Int max_stages::Int @@ -62,66 +69,85 @@ for Alg in [:ESERK4, :ESERK5, :RKC] end end -""" - RKC(; eigen_est = nothing) - -B. P. Sommeijer, L. F. Shampine, J. G. Verwer. RKC: An Explicit Solver for Parabolic PDEs, -Journal of Computational and Applied Mathematics, 88(2), pp 315-326, 1998. doi: -https://doi.org/10.1016/S0377-0427(97)00219-7 - -RKC: Stabilized Explicit Method. -Second order stabilized Runge-Kutta method. -Exhibits high stability for real eigenvalues. - -This method takes the keyword argument `eigen_est` of the form - -`eigen_est = (integrator) -> integrator.eigen_est = upper_bound`, - -where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. If `eigen_est` -is not provided, `upper_bound` will be estimated using the power iteration. -""" +@doc generic_solver_docstring( + """Second order method. Exhibits high stability for real eigenvalues.""", + "RKC", + "Stabilized Explicit Method.", + """B. P. Sommeijer, L. F. Shampine, J. G. Verwer. RKC: An Explicit Solver for Parabolic PDEs, + Journal of Computational and Applied Mathematics, 88(2), pp 315-326, 1998. doi: + https://doi.org/10.1016/S0377-0427(97)00219-7""", + """ + - `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. + """, + """ + eigen_est = nothing, + """) function RKC end -""" - ESERK4(; eigen_est = nothing) - -J. Martín-Vaquero, B. Kleefeld. Extrapolated stabilized explicit Runge-Kutta methods, -Journal of Computational Physics, 326, pp 141-155, 2016. doi: -https://doi.org/10.1016/j.jcp.2016.08.042. - -ESERK4: Stabilized Explicit Method. -Fourth order extrapolated stabilized Runge-Kutta method. -Exhibits high stability for real eigenvalues and is smoothened to allow for moderate sized complex eigenvalues. - -This method takes the keyword argument `eigen_est` of the form - -`eigen_est = (integrator) -> integrator.eigen_est = upper_bound`, - -where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. -If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. -""" +@doc generic_solver_docstring( + """Fourth order method. Exhibits high stability for real eigenvalues +and is smoothened to allow for moderate sized complex eigenvalues.""", + "ESERK4", + "Stabilized Explicit Method.", + """J. Martín-Vaquero, B. Kleefeld. Extrapolated stabilized explicit Runge-Kutta methods, + Journal of Computational Physics, 326, pp 141-155, 2016. doi: + https://doi.org/10.1016/j.jcp.2016.08.042.""", + """ + - `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. + """, + """ + eigen_est = nothing, + """) function ESERK4 end -""" - ESERK5(; eigen_est = nothing) - -J. Martín-Vaquero, A. Kleefeld. ESERK5: A fifth-order extrapolated stabilized explicit Runge-Kutta method, -Journal of Computational and Applied Mathematics, 356, pp 22-36, 2019. doi: -https://doi.org/10.1016/j.cam.2019.01.040. - -ESERK5: Stabilized Explicit Method. -Fifth order extrapolated stabilized Runge-Kutta method. -Exhibits high stability for real eigenvalues and is smoothened to allow for moderate sized complex eigenvalues. - -This method takes the keyword argument `eigen_est` of the form - -`eigen_est = (integrator) -> integrator.eigen_est = upper_bound`, - -where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. -If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. -""" +@doc generic_solver_docstring( + """Fifth order method. Exhibits high stability for real eigenvalues +and is smoothened to allow for moderate sized complex eigenvalues.""", + "ESERK5", + "Stabilized Explicit Method.", + """J. Martín-Vaquero, A. Kleefeld. ESERK5: A fifth-order extrapolated stabilized explicit Runge-Kutta method, + Journal of Computational and Applied Mathematics, 356, pp 22-36, 2019. doi: + https://doi.org/10.1016/j.cam.2019.01.040.""", + """ + - `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. + """, + """ + eigen_est = nothing, + """) function ESERK5 end +@doc generic_solver_docstring("""Second order method.""", + "SERK2", + "Stabilized Explicit Method.", + """@article{kleefeld2013serk2v2, + title={SERK2v2: A new second-order stabilized explicit Runge-Kutta method for stiff problems}, + author={Kleefeld, B and Martin-Vaquero, J}, + journal={Numerical Methods for Partial Differential Equations}, + volume={29}, + number={1}, + pages={170--185}, + year={2013}, + publisher={Wiley Online Library}}""", + """ + - `controller`: TBD + - `eigen_est`: function of the form + `(integrator) -> integrator.eigen_est = upper_bound`, + where `upper_bound` is an estimated upper bound on the spectral radius of the Jacobian matrix. + If `eigen_est` is not provided, `upper_bound` will be estimated using the power iteration. + """, + """ + controller = :PI + eigen_est = nothing, + """) struct SERK2{E} <: OrdinaryDiffEqAdaptiveAlgorithm controller::Symbol eigen_est::E diff --git a/lib/OrdinaryDiffEqSymplecticRK/src/OrdinaryDiffEqSymplecticRK.jl b/lib/OrdinaryDiffEqSymplecticRK/src/OrdinaryDiffEqSymplecticRK.jl index 67dc1e38d8..c100a75215 100644 --- a/lib/OrdinaryDiffEqSymplecticRK/src/OrdinaryDiffEqSymplecticRK.jl +++ b/lib/OrdinaryDiffEqSymplecticRK/src/OrdinaryDiffEqSymplecticRK.jl @@ -11,7 +11,8 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, alg_cache, _vec, _reshape, @cache, isfsal, full_cache, constvalue, _unwrap_val, explicit_rk_docstring, trivial_limiter!, - _ode_interpolant!, _ode_addsteps!, get_fsalfirstlast + _ode_interpolant!, _ode_addsteps!, get_fsalfirstlast, + generic_solver_docstring using FastBroadcast, Polyester, MuladdMacro, RecursiveArrayTools import OrdinaryDiffEqCore diff --git a/lib/OrdinaryDiffEqSymplecticRK/src/algorithms.jl b/lib/OrdinaryDiffEqSymplecticRK/src/algorithms.jl index c93ee790d8..cdbc53d2e1 100644 --- a/lib/OrdinaryDiffEqSymplecticRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqSymplecticRK/src/algorithms.jl @@ -1,6 +1,10 @@ +@doc generic_solver_docstring("First order explicit symplectic integrator.", + "SymplecticEuler", + "Symplectic Runge-Kutta Methods", + "https://en.wikipedia.org/wiki/Semi-implicit_Euler_method", "", "") struct SymplecticEuler <: OrdinaryDiffEqPartitionedAlgorithm end -""" +verlet1967 = """ @article{verlet1967computer, title={Computer" experiments" on classical fluids. I. Thermodynamical properties of Lennard-Jones molecules}, author={Verlet, Loup}, @@ -13,39 +17,26 @@ publisher={APS} } """ +@doc generic_solver_docstring( + "2nd order explicit symplectic integrator. Requires f_2(t,u) = v, i.e. a second order ODE.", + "VelocityVerlet", + "Symplectic Runge-Kutta Methods", + verlet1967, "", "") struct VelocityVerlet <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{verlet1967computer, -title={Computer" experiments" on classical fluids. I. Thermodynamical properties of Lennard-Jones molecules}, -author={Verlet, Loup}, -journal={Physical review}, -volume={159}, -number={1}, -pages={98}, -year={1967}, -publisher={APS} -} -""" - +@doc generic_solver_docstring("2nd order explicit symplectic integrator.", + "VerletLeapfrog", + "Symplectic Runge-Kutta Methods", + verlet1967, "", "") struct VerletLeapfrog <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{verlet1967computer, -title={Computer" experiments" on classical fluids. I. Thermodynamical properties of Lennard-Jones molecules}, -author={Verlet, Loup}, -journal={Physical review}, -volume={159}, -number={1}, -pages={98}, -year={1967}, -publisher={APS} -} -""" - +@doc generic_solver_docstring("2nd order explicit symplectic integrator.", + "PseudoVerletLeapfrog", + "Symplectic Runge-Kutta Methods", + verlet1967, "", "") struct PseudoVerletLeapfrog <: OrdinaryDiffEqPartitionedAlgorithm end -""" +mclachlan1992 = """ @article{mclachlan1992accuracy, title={The accuracy of symplectic integrators}, author={McLachlan, Robert I and Atela, Pau}, @@ -58,167 +49,151 @@ publisher={IOP Publishing} } """ +@doc generic_solver_docstring( + "Optimized efficiency 2nd order explicit symplectic integrator.", + "McAte2", + "Symplectic Runge-Kutta Methods", + mclachlan1992, "", "") struct McAte2 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{ruth1983canonical, -title={A canonical integration technique}, -author={Ruth, Ronald D}, -journal={IEEE Trans. Nucl. Sci.}, -volume={30}, -number={CERN-LEP-TH-83-14}, -pages={2669--2671}, -year={1983} -} -""" - +@doc generic_solver_docstring("3rd order explicit symplectic integrator.", + "Ruth3", + "Symplectic Runge-Kutta Methods", + """@article{ruth1983canonical, + title={A canonical integration technique}, + author={Ruth, Ronald D}, + journal={IEEE Trans. Nucl. Sci.}, + volume={30}, + number={CERN-LEP-TH-83-14}, + pages={2669--2671}, + year={1983}}""", "", "") struct Ruth3 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{mclachlan1992accuracy, -title={The accuracy of symplectic integrators}, -author={McLachlan, Robert I and Atela, Pau}, -journal={Nonlinearity}, -volume={5}, -number={2}, -pages={541}, -year={1992}, -publisher={IOP Publishing} -} -""" - +@doc generic_solver_docstring( + "Optimized efficiency 3rd order explicit symplectic integrator.", + "McAte3", + "Symplectic Runge-Kutta Methods", + mclachlan1992, "", "") struct McAte3 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{candy1991symplectic, -title={A symplectic integration algorithm for separable Hamiltonian functions}, -author={Candy, J and Rozmus, W}, -journal={Journal of Computational Physics}, -volume={92}, -number={1}, -pages={230--256}, -year={1991}, -publisher={Elsevier} -} -""" - +@doc generic_solver_docstring("4th order explicit symplectic integrator.", + "CandyRoz4", + "Symplectic Runge-Kutta Methods", + """@article{candy1991symplectic, + itle={A symplectic integration algorithm for separable Hamiltonian functions}, + uthor={Candy, J and Rozmus, W}, + ournal={Journal of Computational Physics}, + olume={92}, + umber={1}, + ages={230--256}, + ear={1991}, + ublisher={Elsevier}}""", "", "") struct CandyRoz4 <: OrdinaryDiffEqPartitionedAlgorithm end +@doc generic_solver_docstring( + "4th order explicit symplectic integrator. Requires quadratic kinetic energy.", + "McAte4", + "Symplectic Runge-Kutta Methods", + mclachlan1992, "", "") struct McAte4 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{sanz1993symplectic, -title={Symplectic numerical methods for Hamiltonian problems}, -author={Sanz-Serna, Jes{\'u}s Maria and Calvo, Mari-Paz}, -journal={International Journal of Modern Physics C}, -volume={4}, -number={02}, -pages={385--392}, -year={1993}, -publisher={World Scientific} -} -""" - +@doc generic_solver_docstring( + "Optimized efficiency 4th order explicit symplectic integrator.", + "CalvoSanz4", + "Symplectic Runge-Kutta Methods", + """@article{sanz1993symplectic, + title={Symplectic numerical methods for Hamiltonian problems}, + author={Sanz-Serna, Jes{\'u}s Maria and Calvo, Mari-Paz}, + journal={International Journal of Modern Physics C}, + volume={4}, + number={02}, + pages={385--392}, + year={1993}, + publisher={World Scientific} + }""", "", "") struct CalvoSanz4 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{mclachlan1992accuracy, -title={The accuracy of symplectic integrators}, -author={McLachlan, Robert I and Atela, Pau}, -journal={Nonlinearity}, -volume={5}, -number={2}, -pages={541}, -year={1992}, -publisher={IOP Publishing} -} -""" - +@doc generic_solver_docstring("4th order explicit symplectic integrator. BROKEN", + "McAte42", + "Symplectic Runge-Kutta Methods", + mclachlan1992, "", "") struct McAte42 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{mclachlan1992accuracy, -title={The accuracy of symplectic integrators}, -author={McLachlan, Robert I and Atela, Pau}, -journal={Nonlinearity}, -volume={5}, -number={2}, -pages={541}, -year={1992}, -publisher={IOP Publishing} -} -""" - +@doc generic_solver_docstring( + "Optimized efficiency 5th order explicit symplectic integrator. Requires quadratic kinetic energy.", + "McAte5", + "Symplectic Runge-Kutta Methods", + mclachlan1992, "", "") struct McAte5 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{yoshida1990construction, -title={Construction of higher order symplectic integrators}, -author={Yoshida, Haruo}, -journal={Physics letters A}, -volume={150}, -number={5-7}, -pages={262--268}, -year={1990}, -publisher={Elsevier} -} -""" - +@doc generic_solver_docstring("6th order explicit symplectic integrator.", + "Yoshida6", + "Symplectic Runge-Kutta Methods", + """@article{yoshida1990construction, + title={Construction of higher order symplectic integrators}, + author={Yoshida, Haruo}, + journal={Physics letters A}, + volume={150}, + number={5-7}, + pages={262--268}, + year={1990}, + publisher={Elsevier}}""", "", "") struct Yoshida6 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{kahan1997composition, -title={Composition constants for raising the orders of unconventional schemes for ordinary differential equations}, -author={Kahan, William and Li, Ren-Cang}, -journal={Mathematics of computation}, -volume={66}, -number={219}, -pages={1089--1099}, -year={1997} -} -""" - +@doc generic_solver_docstring( + "Optimized efficiency 6th order explicit symplectic integrator.", + "KahanLi6", + "Symplectic Runge-Kutta Methods", + """@article{yoshida1990construction, + title={Construction of higher order symplectic integrators}, + author={Yoshida, Haruo}, + journal={Physics letters A}, + volume={150}, + number={5-7}, + pages={262--268}, + year={1990}, + publisher={Elsevier}}""", "", "") struct KahanLi6 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{mclachlan1995numerical, -title={On the numerical integration of ordinary differential equations by symmetric composition methods}, -author={McLachlan, Robert I}, -journal={SIAM Journal on Scientific Computing}, -volume={16}, -number={1}, -pages={151--168}, -year={1995}, -publisher={SIAM} -} -""" - +@doc generic_solver_docstring("8th order explicit symplectic integrator.", + "McAte8", + "Symplectic Runge-Kutta Methods", + """@article{mclachlan1995numerical, + title={On the numerical integration of ordinary differential equations by symmetric composition methods}, + author={McLachlan, Robert I}, + journal={SIAM Journal on Scientific Computing}, + volume={16}, + number={1}, + pages={151--168}, + year={1995}, + publisher={SIAM} + }""", "", "") struct McAte8 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{kahan1997composition, -title={Composition constants for raising the orders of unconventional schemes for ordinary differential equations}, -author={Kahan, William and Li, Ren-Cang}, -journal={Mathematics of computation}, -volume={66}, -number={219}, -pages={1089--1099}, -year={1997} -} -""" - +@doc generic_solver_docstring( + "Optimized efficiency 8th order explicit symplectic integrator.", + "KahanLi8", + "Symplectic Runge-Kutta Methods", + """@article{kahan1997composition, + title={Composition constants for raising the orders of unconventional schemes for ordinary differential equations}, + author={Kahan, William and Li, Ren-Cang}, + journal={Mathematics of computation}, + volume={66}, + number={219}, + pages={1089--1099}, + year={1997}}""", "", "") struct KahanLi8 <: OrdinaryDiffEqPartitionedAlgorithm end -""" -@article{sofroniou2005derivation, -title={Derivation of symmetric composition constants for symmetric integrators}, -author={Sofroniou, Mark and Spaletta, Giulia}, -journal={Optimization Methods and Software}, -volume={20}, -number={4-5}, -pages={597--613}, -year={2005}, -publisher={Taylor \\& Francis} -} -""" +@doc generic_solver_docstring("10th order explicit symplectic integrator.", + "SofSpa10", + "Symplectic Runge-Kutta Methods", + """@article{sofroniou2005derivation, + title={Derivation of symmetric composition constants for symmetric integrators}, + author={Sofroniou, Mark and Spaletta, Giulia}, + journal={Optimization Methods and Software}, + volume={20}, + number={4-5}, + pages={597--613}, + year={2005}, + publisher={Taylor \\& Francis}}""", "", "") struct SofSpa10 <: OrdinaryDiffEqPartitionedAlgorithm end diff --git a/lib/OrdinaryDiffEqTsit5/src/algorithms.jl b/lib/OrdinaryDiffEqTsit5/src/algorithms.jl index 45cfbcc5a1..c19efefcd3 100644 --- a/lib/OrdinaryDiffEqTsit5/src/algorithms.jl +++ b/lib/OrdinaryDiffEqTsit5/src/algorithms.jl @@ -1,6 +1,7 @@ @doc explicit_rk_docstring( "A fifth-order explicit Runge-Kutta method with embedded error -estimator of Tsitouras. Free 4th order interpolant.", "Tsit5", + estimator of Tsitouras. Free 4th order interpolant.", + "Tsit5", references = "@article{tsitouras2011runge, title={Runge--Kutta pairs of order 5 (4) satisfying only the first column simplifying assumption}, author={Tsitouras, Ch}, @@ -23,4 +24,13 @@ function Tsit5(stage_limiter!, step_limiter! = trivial_limiter!) Tsit5(stage_limiter!, step_limiter!, False()) end -AutoTsit5(alg; kwargs...) = AutoAlgSwitch(Tsit5(), alg; kwargs...) +""" +Automatic switching algorithm that can switch between the (non-stiff) `Tsit5()` and `stiff_alg`. + + AutoTsit5(stiff_alg; kwargs...) + +This method is equivalent to `AutoAlgSwitch(Tsit5(), stiff_alg; kwargs...)`. +To gain access to stiff algorithms you might have to install additional libraries, +such as `OrdinaryDiffEqRosenbrock`. +""" +AutoTsit5(stiff_alg; kwargs...) = AutoAlgSwitch(Tsit5(), stiff_alg; kwargs...) diff --git a/lib/OrdinaryDiffEqVerner/Project.toml b/lib/OrdinaryDiffEqVerner/Project.toml index 6c0788b1c7..dffb73e28a 100644 --- a/lib/OrdinaryDiffEqVerner/Project.toml +++ b/lib/OrdinaryDiffEqVerner/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqVerner" uuid = "79d7bb75-1356-48c1-b8c0-6832512096c2" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.1.1" [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" diff --git a/lib/OrdinaryDiffEqVerner/src/OrdinaryDiffEqVerner.jl b/lib/OrdinaryDiffEqVerner/src/OrdinaryDiffEqVerner.jl index b5c2ec183e..ca6328e98c 100644 --- a/lib/OrdinaryDiffEqVerner/src/OrdinaryDiffEqVerner.jl +++ b/lib/OrdinaryDiffEqVerner/src/OrdinaryDiffEqVerner.jl @@ -13,7 +13,7 @@ import OrdinaryDiffEqCore: alg_order, calculate_residuals!, _ode_interpolant!, _ode_addsteps!, @fold, @OnDemandTableauExtract, AutoAlgSwitch, DerivativeOrderNotPossibleError, - has_lazy_interpolation, get_fsalfirstlast + get_fsalfirstlast using FastBroadcast, Polyester, MuladdMacro, RecursiveArrayTools using DiffEqBase: @def, @tight_loop_macros using Static: False diff --git a/lib/OrdinaryDiffEqVerner/src/alg_utils.jl b/lib/OrdinaryDiffEqVerner/src/alg_utils.jl index bd62e06eea..f38d2ec768 100644 --- a/lib/OrdinaryDiffEqVerner/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqVerner/src/alg_utils.jl @@ -12,4 +12,4 @@ alg_stability_size(alg::Vern7) = 4.6400 alg_stability_size(alg::Vern8) = 5.8641 alg_stability_size(alg::Vern9) = 4.4762 -has_lazy_interpolation(alg::Union{Vern6, Vern7, Vern8, Vern9}) = true +SciMLBase.has_lazy_interpolation(alg::Union{Vern6, Vern7, Vern8, Vern9}) = true diff --git a/lib/OrdinaryDiffEqVerner/src/algorithms.jl b/lib/OrdinaryDiffEqVerner/src/algorithms.jl index 7786b94e22..e1fbb1fb16 100644 --- a/lib/OrdinaryDiffEqVerner/src/algorithms.jl +++ b/lib/OrdinaryDiffEqVerner/src/algorithms.jl @@ -113,7 +113,43 @@ function Vern9(stage_limiter!, step_limiter! = trivial_limiter!; lazy = true) Vern9(stage_limiter!, step_limiter!, False(), lazy) end +""" +Automatic switching algorithm that can switch between the (non-stiff) `Vern6()` and `stiff_alg`. + + AutoVern6(stiff_alg; kwargs...) + +This method is equivalent to `AutoAlgSwitch(Vern6(), stiff_alg; kwargs...)`. +To gain access to stiff algorithms you might have to install additional libraries, +such as `OrdinaryDiffEqRosenbrock`. +""" AutoVern6(alg; lazy = true, kwargs...) = AutoAlgSwitch(Vern6(lazy = lazy), alg; kwargs...) +""" +Automatic switching algorithm that can switch between the (non-stiff) `Vern7()` and `stiff_alg`. + + AutoVern7(stiff_alg; kwargs...) + +This method is equivalent to `AutoAlgSwitch(Vern7(), stiff_alg; kwargs...)`. +To gain access to stiff algorithms you might have to install additional libraries, +such as `OrdinaryDiffEqRosenbrock`. +""" AutoVern7(alg; lazy = true, kwargs...) = AutoAlgSwitch(Vern7(lazy = lazy), alg; kwargs...) +""" +Automatic switching algorithm that can switch between the (non-stiff) `Vern8()` and `stiff_alg`. + + AutoVern8(stiff_alg; kwargs...) + +This method is equivalent to `AutoAlgSwitch(Vern8(), stiff_alg; kwargs...)`. +To gain access to stiff algorithms you might have to install additional libraries, +such as `OrdinaryDiffEqRosenbrock`. +""" AutoVern8(alg; lazy = true, kwargs...) = AutoAlgSwitch(Vern8(lazy = lazy), alg; kwargs...) +""" +Automatic switching algorithm that can switch between the (non-stiff) `Vern9()` and `stiff_alg`. + + AutoVern9(stiff_alg; kwargs...) + +This method is equivalent to `AutoAlgSwitch(Vern9(), stiff_alg; kwargs...)`. +To gain access to stiff algorithms you might have to install additional libraries, +such as `OrdinaryDiffEqRosenbrock`. +""" AutoVern9(alg; lazy = true, kwargs...) = AutoAlgSwitch(Vern9(lazy = lazy), alg; kwargs...) diff --git a/lib/OrdinaryDiffEqVerner/src/verner_caches.jl b/lib/OrdinaryDiffEqVerner/src/verner_caches.jl index 19289eb2c2..9a3444d101 100644 --- a/lib/OrdinaryDiffEqVerner/src/verner_caches.jl +++ b/lib/OrdinaryDiffEqVerner/src/verner_caches.jl @@ -87,7 +87,7 @@ end end # fake values since non-FSAL method -get_fsalfirstlast(cache::Vern7Cache, u) = (cache.k1, cache.k2) +get_fsalfirstlast(cache::Vern7Cache, u) = (nothing, nothing) function alg_cache(alg::Vern7, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, @@ -153,7 +153,7 @@ end end # fake values since non-FSAL method -get_fsalfirstlast(cache::Vern8Cache, u) = (cache.k1, cache.k2) +get_fsalfirstlast(cache::Vern8Cache, u) = (nothing, nothing) function alg_cache(alg::Vern8, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, @@ -227,7 +227,7 @@ end end # fake values since non-FSAL method -get_fsalfirstlast(cache::Vern9Cache, u) = (cache.k1, cache.k2) +get_fsalfirstlast(cache::Vern9Cache, u) = (nothing, nothing) function alg_cache(alg::Vern9, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/test/interface/get_du.jl b/test/interface/get_du.jl new file mode 100644 index 0000000000..d745a63132 --- /dev/null +++ b/test/interface/get_du.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq, OrdinaryDiffEqCore, Test +function lorenz!(du, u, p, t) + du[1] = 10.0(u[2] - u[1]) + du[2] = u[1] * (28.0 - u[3]) - u[2] + du[3] = u[1] * u[2] - (8 / 3) * u[3] +end +u0 = [1.0; 0.0; 0.0] +tspan = (0.0, 3.0) +condition(u, t, integrator) = t == 0.2 +cache = zeros(3) +affect!(integrator) = cache .= get_du(integrator) +dusave = DiscreteCallback(condition, affect!) +affect2!(integrator) = get_du!(cache, integrator) +dusave_inplace = DiscreteCallback(condition, affect2!) + +prob = ODEProblem(lorenz!, u0, tspan) +sol = solve( + prob, Tsit5(), tstops = [0.2], callback = dusave, abstol = 1e-12, reltol = 1e-12) +res = copy(cache) + +for alg in [Vern6(), Vern7(), Vern8(), Vern9(), Rodas4(), Rodas4P(), + Rodas5(), Rodas5P(), TRBDF2(), KenCarp4(), FBDF(), QNDF()] + sol = solve( + prob, alg, tstops = [0.2], callback = dusave, abstol = 1e-12, reltol = 1e-12) + @test res≈cache rtol=1e-5 + + sol = solve(prob, alg, tstops = [0.2], callback = dusave_inplace, + abstol = 1e-12, reltol = 1e-12) + @test res≈cache rtol=1e-5 +end diff --git a/test/interface/ode_strip_test.jl b/test/interface/ode_strip_test.jl index e476c024ee..870bb46c6c 100644 --- a/test/interface/ode_strip_test.jl +++ b/test/interface/ode_strip_test.jl @@ -11,7 +11,28 @@ u0 = [1.0; 0.0; 0.0] tspan = (0.0, 0.5) prob = ODEProblem(lorenz!, u0, tspan) -sol = solve(prob, Rosenbrock23()) +rosenbrock_sol = solve(prob, Rosenbrock23()) +TRBDF_sol = solve(prob, TRBDF2()) +vern_sol = solve(prob, Vern7()) +@testset "Interpolation Stripping" begin + @test isnothing(SciMLBase.strip_interpolation(rosenbrock_sol.interp).f) + @test isnothing(SciMLBase.strip_interpolation(rosenbrock_sol.interp).cache.jac_config) + @test isnothing(SciMLBase.strip_interpolation(rosenbrock_sol.interp).cache.grad_config) +end + +@testset "Rosenbrock Solution Stripping" begin + @test isnothing(SciMLBase.strip_solution(rosenbrock_sol).prob) + @test isnothing(SciMLBase.strip_solution(rosenbrock_sol).alg) + @test isnothing(SciMLBase.strip_solution(rosenbrock_sol).interp.f) + @test isnothing(SciMLBase.strip_solution(rosenbrock_sol).interp.cache.jac_config) + @test isnothing(SciMLBase.strip_solution(rosenbrock_sol).interp.cache.grad_config) +end + +@testset "TRBDF Solution Stripping" begin + @test isnothing(SciMLBase.strip_solution(TRBDF_sol).prob) + @test isnothing(SciMLBase.strip_solution(TRBDF_sol).alg) + @test isnothing(SciMLBase.strip_solution(TRBDF_sol).interp.f) + @test isnothing(SciMLBase.strip_solution(TRBDF_sol).interp.cache.nlsolver) +end -@test isnothing(SciMLBase.strip_interpolation(sol.interp).f) -@test isnothing(SciMLBase.strip_interpolation(sol.interp).cache.jac_config) +@test_throws SciMLBase.LazyInterpolationException SciMLBase.strip_solution(vern_sol) diff --git a/test/runtests.jl b/test/runtests.jl index a452d56ee8..5c89af81b7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -66,6 +66,7 @@ end @time @safetestset "Linear Solver Split ODE Tests" include("interface/linear_solver_split_ode_test.jl") @time @safetestset "Sparse Diff Tests" include("interface/sparsediff_tests.jl") @time @safetestset "Enum Tests" include("interface/enums.jl") + @time @safetestset "Enum Tests" include("interface/get_du.jl") @time @safetestset "Mass Matrix Tests" include("interface/mass_matrix_tests.jl") @time @safetestset "W-Operator prototype tests" include("interface/wprototype_tests.jl") end