From e6c5dcb67bc41aec275d1e1523de76e53ff87a3d Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Thu, 22 Aug 2024 22:21:18 +0530 Subject: [PATCH 01/45] commit --- .../Project.toml | 19 + .../src/OrdinaryDiffEqDifferentiation.jl | 55 + .../src/alg_utils.jl | 79 ++ .../src/derivative_utils.jl | 969 ++++++++++++++++++ .../src/derivative_wrappers.jl | 411 ++++++++ .../src/linsolve_utils.jl | 59 ++ .../test/runtests.jl | 0 lib/OrdinaryDiffEqNonlinearSolve/Project.toml | 20 + .../src/OrdinaryDiffEqNonlinearSolve.jl | 49 + .../src/functional.jl | 260 +++++ .../src/initialize_dae.jl | 687 +++++++++++++ .../src/newton.jl | 536 ++++++++++ .../src/nlsolve.jl | 160 +++ lib/OrdinaryDiffEqNonlinearSolve/src/type.jl | 225 ++++ lib/OrdinaryDiffEqNonlinearSolve/src/utils.jl | 578 +++++++++++ .../test/newton_tests.jl | 16 + .../test/runtests.jl | 3 + 17 files changed, 4126 insertions(+) create mode 100644 lib/OrdinaryDiffEqDifferentiation/Project.toml create mode 100644 lib/OrdinaryDiffEqDifferentiation/src/OrdinaryDiffEqDifferentiation.jl create mode 100644 lib/OrdinaryDiffEqDifferentiation/src/alg_utils.jl create mode 100644 lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl create mode 100644 lib/OrdinaryDiffEqDifferentiation/src/derivative_wrappers.jl create mode 100644 lib/OrdinaryDiffEqDifferentiation/src/linsolve_utils.jl create mode 100644 lib/OrdinaryDiffEqDifferentiation/test/runtests.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/Project.toml create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/initialize_dae.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/nlsolve.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/type.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/src/utils.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl create mode 100644 lib/OrdinaryDiffEqNonlinearSolve/test/runtests.jl diff --git a/lib/OrdinaryDiffEqDifferentiation/Project.toml b/lib/OrdinaryDiffEqDifferentiation/Project.toml new file mode 100644 index 0000000000..d8c9db7f87 --- /dev/null +++ b/lib/OrdinaryDiffEqDifferentiation/Project.toml @@ -0,0 +1,19 @@ +name = "OrdinaryDiffEqDifferentiation" +uuid = "4302a76b-040a-498a-8c04-15b101fed76b" +authors = ["Chris Rackauckas ", "Yingbo Ma "] +version = "1.0.0" + +[deps] +OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" + +[compat] +julia = "1.10" + +[extras] +DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["DiffEqDevTools", "Random", "SafeTestsets", "Test"] diff --git a/lib/OrdinaryDiffEqDifferentiation/src/OrdinaryDiffEqDifferentiation.jl b/lib/OrdinaryDiffEqDifferentiation/src/OrdinaryDiffEqDifferentiation.jl new file mode 100644 index 0000000000..e2a099b5cb --- /dev/null +++ b/lib/OrdinaryDiffEqDifferentiation/src/OrdinaryDiffEqDifferentiation.jl @@ -0,0 +1,55 @@ +module OrdinaryDiffEqDifferentiation + +import ADTypes: AutoFiniteDiff, AutoForwardDiff + +import SparseDiffTools: SparseDiffTools, matrix_colors, forwarddiff_color_jacobian!, + forwarddiff_color_jacobian, ForwardColorJacCache, + default_chunk_size, getsize, JacVec + +import ForwardDiff, FiniteDiff +import ForwardDiff.Dual +import LinearSolve +import LinearSolve: OperatorAssumptions +import FunctionWrappersWrappers +using DiffEqBase + +import LinearAlgebra +import LinearAlgebra: Diagonal, I, UniformScaling, diagind, mul!,lmul!, axpby!, opnorm +import SparseArrays: SparseMatrixCSC, AbstractSparseMatrix, nonzeros + +import InteractiveUtils +import ArrayInterface + +import StaticArrayInterface +import StaticArrays: SArray, MVector, SVector, @SVector, StaticArray, MMatrix, SA, + StaticMatrix + +using DiffEqBase: TimeGradientWrapper, + UJacobianWrapper, TimeDerivativeWrapper, + UDerivativeWrapper +using SciMLBase: AbstractSciMLOperator +using OrdinaryDiffEq: OrdinaryDiffEqAlgorithm, OrdinaryDiffEqAdaptiveImplicitAlgorithm, DAEAlgorithm, +OrdinaryDiffEqImplicitAlgorithm, CompositeAlgorithm, OrdinaryDiffEqExponentialAlgorithm, +OrdinaryDiffEqAdaptiveExponentialAlgorithm, @unpack, AbstractNLSolver, nlsolve_f, issplit, +concrete_jac, unwrap_alg, OrdinaryDiffEqCache, _vec, standardtag, isnewton, _unwrap_val, +set_new_W!, set_W_γdt!, alg_difftype, unwrap_cache, diffdir, get_W, isfirstcall, isfirststage, isJcurrent, get_new_W_γdt_cutoff, +TryAgain, DIRK, COEFFICIENT_MULTISTEP, NORDSIECK_MULTISTEP, GLM, FastConvergence, Convergence, SlowConvergence, VerySlowConvergence, Divergence, NLStatus, MethodType, constvalue + +import OrdinaryDiffEq: get_chunksize, resize_J_W!, resize_nlsolver! + +import OrdinaryDiffEq: alg_autodiff + +using FastBroadcast: @.. + +@static if isdefined(DiffEqBase, :OrdinaryDiffEqTag) + import DiffEqBase: OrdinaryDiffEqTag +else + struct OrdinaryDiffEqTag end +end + +include("alg_utils.jl") +include("linsolve_utils.jl") +include("derivative_utils.jl") +include("derivative_wrappers.jl") + +end diff --git a/lib/OrdinaryDiffEqDifferentiation/src/alg_utils.jl b/lib/OrdinaryDiffEqDifferentiation/src/alg_utils.jl new file mode 100644 index 0000000000..cfc14219c5 --- /dev/null +++ b/lib/OrdinaryDiffEqDifferentiation/src/alg_utils.jl @@ -0,0 +1,79 @@ +# Extract AD type parameter from algorithm, returning as Val to ensure type stability for boolean options. +function _alg_autodiff(alg::OrdinaryDiffEqAlgorithm) + error("This algorithm does not have an autodifferentiation option defined.") +end +_alg_autodiff(::OrdinaryDiffEqAdaptiveImplicitAlgorithm{CS, AD}) where {CS, AD} = Val{AD}() +_alg_autodiff(::DAEAlgorithm{CS, AD}) where {CS, AD} = Val{AD}() +_alg_autodiff(::OrdinaryDiffEqImplicitAlgorithm{CS, AD}) where {CS, AD} = Val{AD}() +_alg_autodiff(alg::CompositeAlgorithm) = _alg_autodiff(alg.algs[end]) +function _alg_autodiff(::Union{OrdinaryDiffEqExponentialAlgorithm{CS, AD}, + OrdinaryDiffEqAdaptiveExponentialAlgorithm{CS, AD} +}) where { + CS, AD +} + Val{AD}() +end + +function alg_autodiff(alg) + autodiff = _alg_autodiff(alg) + if autodiff == Val(false) + return AutoFiniteDiff() + elseif autodiff == Val(true) + return AutoForwardDiff() + else + return _unwrap_val(autodiff) + end +end + +Base.@pure function determine_chunksize(u, alg::DiffEqBase.DEAlgorithm) + determine_chunksize(u, get_chunksize(alg)) +end +Base.@pure function determine_chunksize(u, CS) + if CS != 0 + return CS + else + return ForwardDiff.pickchunksize(length(u)) + end +end + +function DiffEqBase.prepare_alg( + alg::Union{ + OrdinaryDiffEqAdaptiveImplicitAlgorithm{0, AD, + FDT}, + OrdinaryDiffEqImplicitAlgorithm{0, AD, FDT}, + DAEAlgorithm{0, AD, FDT}, + OrdinaryDiffEqExponentialAlgorithm{0, AD, FDT}}, + u0::AbstractArray{T}, + p, prob) where {AD, FDT, T} + + # If not using autodiff or norecompile mode or very large bitsize (like a dual number u0 already) + # don't use a large chunksize as it will either error or not be beneficial + if !(alg_autodiff(alg) isa AutoForwardDiff) || + (isbitstype(T) && sizeof(T) > 24) || + (prob.f isa ODEFunction && + prob.f.f isa FunctionWrappersWrappers.FunctionWrappersWrapper) + return remake(alg, chunk_size = Val{1}()) + end + + L = StaticArrayInterface.known_length(typeof(u0)) + if L === nothing # dynamic sized + # If chunksize is zero, pick chunksize right at the start of solve and + # then do function barrier to infer the full solve + x = if prob.f.colorvec === nothing + length(u0) + else + maximum(prob.f.colorvec) + end + + cs = ForwardDiff.pickchunksize(x) + return remake(alg, chunk_size = Val{cs}()) + else # statically sized + cs = pick_static_chunksize(Val{L}()) + return remake(alg, chunk_size = cs) + end +end + +@generated function pick_static_chunksize(::Val{chunksize}) where {chunksize} + x = ForwardDiff.pickchunksize(chunksize) + :(Val{$x}()) +end \ No newline at end of file diff --git a/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl b/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl new file mode 100644 index 0000000000..316f0690f0 --- /dev/null +++ b/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl @@ -0,0 +1,969 @@ +const ROSENBROCK_INV_CUTOFF = 7 # https://github.com/SciML/OrdinaryDiffEq.jl/pull/1539 + +struct StaticWOperator{isinv, T} <: AbstractSciMLOperator{T} + W::T + function StaticWOperator(W::T, callinv = true) where {T} + isinv = size(W, 1) <= ROSENBROCK_INV_CUTOFF + + # when constructing W for the first time for the type + # inv(W) can be singular + _W = if isinv && callinv + inv(W) + else + W + end + new{isinv, T}(_W) + end +end +isinv(W::StaticWOperator{S}) where {S} = S +Base.:\(W::StaticWOperator, v::AbstractArray) = isinv(W) ? W.W * v : W.W \ v + +function calc_tderivative!(integrator, cache, dtd1, repeat_step) + @inbounds begin + @unpack t, dt, uprev, u, f, p = integrator + @unpack du2, fsalfirst, dT, tf, linsolve_tmp = cache + + # Time derivative + if !repeat_step # skip calculation if step is repeated + if DiffEqBase.has_tgrad(f) + f.tgrad(dT, uprev, p, t) + else + tf.uprev = uprev + tf.p = p + derivative!(dT, tf, t, du2, integrator, cache.grad_config) + end + end + + @.. broadcast=false linsolve_tmp=fsalfirst + dtd1 * dT + end +end + +function calc_tderivative(integrator, cache) + @unpack t, dt, uprev, u, f, p = integrator + + # Time derivative + if DiffEqBase.has_tgrad(f) + dT = f.tgrad(uprev, p, t) + else + tf = cache.tf + tf.u = uprev + tf.p = p + dT = derivative(tf, t, integrator) + end + dT +end + +""" + calc_J(integrator, cache, next_step::Bool = false) + +Return a new Jacobian object. + +If `integrator.f` has a custom Jacobian update function, then it will be called. Otherwise, +either automatic or finite differencing will be used depending on the `uf` object of the +cache. If `next_step`, then it will evaluate the Jacobian at the next step. +""" +function calc_J(integrator, cache, next_step::Bool = false) + @unpack dt, t, uprev, f, p, alg = integrator + if next_step + t = t + dt + uprev = integrator.u + end + + if alg isa DAEAlgorithm + if DiffEqBase.has_jac(f) + J = f.jac(duprev, uprev, p, t) + else + @unpack uf = cache + x = zero(uprev) + J = jacobian(uf, x, integrator) + end + else + if DiffEqBase.has_jac(f) + J = f.jac(uprev, p, t) + else + @unpack uf = cache + + uf.f = nlsolve_f(f, alg) + uf.p = p + uf.t = t + + J = jacobian(uf, uprev, integrator) + end + + if alg isa CompositeAlgorithm + integrator.eigen_est = constvalue(opnorm(J, Inf)) + end + end + + integrator.stats.njacs += 1 + J +end + +""" + calc_J!(J, integrator, cache, next_step::Bool = false) -> J + +Update the Jacobian object `J`. + +If `integrator.f` has a custom Jacobian update function, then it will be called. Otherwise, +either automatic or finite differencing will be used depending on the `cache`. +If `next_step`, then it will evaluate the Jacobian at the next step. +""" +function calc_J!(J, integrator, cache, next_step::Bool = false) + @unpack dt, t, uprev, f, p, alg = integrator + if next_step + t = t + dt + uprev = integrator.u + end + + if alg isa DAEAlgorithm + if DiffEqBase.has_jac(f) + duprev = integrator.duprev + uf = cache.uf + f.jac(J, duprev, uprev, p, uf.α * uf.invγdt, t) + else + @unpack du1, uf, jac_config = cache + # using `dz` as temporary array + x = cache.dz + uf.t = t + fill!(x, zero(eltype(x))) + jacobian!(J, uf, x, du1, integrator, jac_config) + end + else + if DiffEqBase.has_jac(f) + f.jac(J, uprev, p, t) + else + @unpack du1, uf, jac_config = cache + + uf.f = nlsolve_f(f, alg) + uf.t = t + if !(p isa DiffEqBase.NullParameters) + uf.p = p + end + jacobian!(J, uf, uprev, du1, integrator, jac_config) + end + end + + if alg isa CompositeAlgorithm + integrator.eigen_est = constvalue(opnorm(J, Inf)) + end + + integrator.stats.njacs += 1 + return nothing +end + +""" + WOperator(mass_matrix,gamma,J[;transform=false]) + +A linear operator that represents the W matrix of an ODEProblem, defined as + +```math +W = MM - \\gamma J +``` + +or, if `transform=true`: + +```math +W = \\frac{1}{\\gamma}MM - J +``` + +where `MM` is the mass matrix (a regular `AbstractMatrix` or a `UniformScaling`), +`γ` is a real number proportional to the time step, and `J` is the Jacobian +operator (must be a `AbstractSciMLOperator`). A `WOperator` can also be +constructed using a `*DEFunction` directly as + + WOperator(f,gamma[;transform=false]) + +`f` needs to have a jacobian and `jac_prototype`, but the prototype does not need +to be a diffeq operator --- it will automatically be converted to one. + +`WOperator` supports lazy `*` and `mul!` operations, the latter utilizing an +internal cache (can be specified in the constructor; default to regular `Vector`). +It supports all of `AbstractSciMLOperator`'s interface. +""" +mutable struct WOperator{IIP, T, + MType, + GType, + JType, + F, + C, + JV} <: AbstractSciMLOperator{T} + mass_matrix::MType + gamma::GType + J::JType + transform::Bool # true => W = mm/gamma - J; false => W = mm - gamma*J + _func_cache::F # cache used in `mul!` + _concrete_form::C # non-lazy form (matrix/number) of the operator + jacvec::JV + + function WOperator{IIP}(mass_matrix, gamma, J, u, jacvec = nothing; + transform = false) where {IIP} + # TODO: there is definitely a missing interface. + # Tentative interface: `has_concrete` and `concertize(A)` + if J isa Union{Number, ScalarOperator} + if transform + _concrete_form = -mass_matrix / gamma + convert(Number, J) + else + _concrete_form = -mass_matrix + gamma * convert(Number, J) + end + _func_cache = nothing + else + AJ = J isa MatrixOperator ? convert(AbstractMatrix, J) : J + if AJ isa AbstractMatrix + mm = mass_matrix isa MatrixOperator ? + convert(AbstractMatrix, mass_matrix) : mass_matrix + if AJ isa AbstractSparseMatrix + + # If gamma is zero, then it's just an initialization and we want to make sure + # we get the right sparsity pattern. If gamma is not zero, then it's a case where + # a new W is created (as part of an out-of-place solve) and thus the actual + # values actually matter! + # + # Constant operators never refactorize so always use the correct values there + # as well + if gamma == 0 && !(J isa MatrixOperator && isconstant(J)) + # Workaround https://github.com/JuliaSparse/SparseArrays.jl/issues/190 + # Hopefully `rand()` does not match any value in the array (prob ~ 0, with a check) + # Then `one` is required since gamma is zero + # Otherwise this will not pick up the union sparsity pattern + # But instead drop the runtime zeros (i.e. all values) of the AJ pattern! + AJn = nonzeros(AJ) + x = rand() + @assert all(!isequal(x), AJn) + + fill!(AJn, rand()) + if transform + _concrete_form = -mm / one(gamma) + AJ + else + _concrete_form = -mm + one(gamma) * AJ + end + fill!(_concrete_form, false) # safety measure, throw singular error if not filled + else + if transform + _concrete_form = -mm / gamma + AJ + else + _concrete_form = -mm + gamma * AJ + end + end + else + if transform + _concrete_form = -mm / gamma + AJ + else + _concrete_form = -mm + gamma * AJ + end + end + + else + _concrete_form = nothing + end + _func_cache = zero(u) + end + T = eltype(_concrete_form) + MType = typeof(mass_matrix) + GType = typeof(gamma) + JType = typeof(J) + F = typeof(_func_cache) + C = typeof(_concrete_form) + JV = typeof(jacvec) + return new{IIP, T, MType, GType, JType, F, C, JV}(mass_matrix, gamma, J, transform, + _func_cache, _concrete_form, + jacvec) + end +end +function WOperator{IIP}(f, u, gamma; transform = false) where {IIP} + if isa(f, Union{SplitFunction, DynamicalODEFunction}) + error("WOperator does not support $(typeof(f)) yet") + end + mass_matrix = f.mass_matrix + # TODO: does this play nicely with time-state dependent mass matrix? + if !isa(mass_matrix, Union{AbstractMatrix, UniformScaling}) + mass_matrix = convert(AbstractMatrix, mass_matrix) + end + # Convert jacobian, if needed + J = deepcopy(f.jac_prototype) + if J isa AbstractMatrix + @assert DiffEqBase.has_jac(f) "f needs to have an associated jacobian" + J = MatrixOperator(J; update_func! = f.jac) + end + return WOperator{IIP}(mass_matrix, gamma, J, u; transform = transform) +end + +SciMLBase.isinplace(::WOperator{IIP}, i) where {IIP} = IIP +Base.eltype(W::WOperator) = eltype(W.J) + +# In WOperator update_coefficients!, accept both missing u/p/t and missing dtgamma/transform and don't update them in that case. +# This helps support partial updating logic used with Newton solvers. +function SciMLOperators.update_coefficients!(W::WOperator, + u = nothing, + p = nothing, + t = nothing; + dtgamma = nothing, + transform = nothing) + if (u !== nothing) && (p !== nothing) && (t !== nothing) + update_coefficients!(W.J, u, p, t) + update_coefficients!(W.mass_matrix, u, p, t) + !isnothing(W.jacvec) && update_coefficients!(W.jacvec, u, p, t) + end + dtgamma !== nothing && (W.gamma = dtgamma) + transform !== nothing && (W.transform = transform) + W +end + +function SciMLOperators.update_coefficients!(J::UJacobianWrapper, u, p, t) + J.p = p + J.t = t +end + +function Base.convert(::Type{AbstractMatrix}, W::WOperator{IIP}) where {IIP} + if !IIP + # Allocating + if W.transform + W._concrete_form = -W.mass_matrix / W.gamma + convert(AbstractMatrix, W.J) + else + W._concrete_form = -W.mass_matrix + W.gamma * convert(AbstractMatrix, W.J) + end + else + # Non-allocating already updated + #_W = W._concrete_form + #jacobian2W!(_W, W.mass_matrix, W.gamma, W.J, W.transform) + end + return W._concrete_form +end +function Base.convert(::Type{Number}, W::WOperator) + if W.transform + W._concrete_form = -W.mass_matrix / W.gamma + convert(Number, W.J) + else + W._concrete_form = -W.mass_matrix + W.gamma * convert(Number, W.J) + end + return W._concrete_form +end +Base.size(W::WOperator) = size(W.J) +Base.size(W::WOperator, d::Integer) = d <= 2 ? size(W)[d] : 1 +function Base.getindex(W::WOperator, i::Int) + if W.transform + -W.mass_matrix[i] / W.gamma + W.J[i] + else + -W.mass_matrix[i] + W.gamma * W.J[i] + end +end +function Base.getindex(W::WOperator, I::Vararg{Int, N}) where {N} + if W.transform + -W.mass_matrix[I...] / W.gamma + W.J[I...] + else + -W.mass_matrix[I...] + W.gamma * W.J[I...] + end +end +function Base.:*(W::WOperator, x::AbstractVecOrMat) + if W.transform + (W.mass_matrix * x) / -W.gamma + W.J * x + else + -W.mass_matrix * x + W.gamma * (W.J * x) + end +end +function Base.:*(W::WOperator, x::Number) + if W.transform + (W.mass_matrix * x) / -W.gamma + W.J * x + else + -W.mass_matrix * x + W.gamma * (W.J * x) + end +end +function Base.:\(W::WOperator, x::AbstractVecOrMat) + if size(W) == () # scalar operator + convert(Number, W) \ x + else + convert(AbstractMatrix, W) \ x + end +end +function Base.:\(W::WOperator, x::Number) + if size(W) == () # scalar operator + convert(Number, W) \ x + else + convert(AbstractMatrix, W) \ x + end +end + +function LinearAlgebra.mul!(Y::AbstractVecOrMat, W::WOperator, B::AbstractVecOrMat) + if W.transform + # Compute mass_matrix * B + if isa(W.mass_matrix, UniformScaling) + a = -W.mass_matrix.λ / W.gamma + @.. broadcast=false Y=a * B + else + mul!(_vec(Y), W.mass_matrix, _vec(B)) + lmul!(-1 / W.gamma, Y) + end + # Compute J * B and add + if W.jacvec !== nothing + mul!(_vec(W._func_cache), W.jacvec, _vec(B)) + else + mul!(_vec(W._func_cache), W.J, _vec(B)) + end + _vec(Y) .+= _vec(W._func_cache) + else + # Compute mass_matrix * B + if isa(W.mass_matrix, UniformScaling) + vY = _vec(Y) + vB = _vec(B) + @.. broadcast=false vY=W.mass_matrix.λ * vB + else + mul!(_vec(Y), W.mass_matrix, _vec(B)) + end + # Compute J * B + if W.jacvec !== nothing + mul!(_vec(W._func_cache), W.jacvec, _vec(B)) + else + mul!(_vec(W._func_cache), W.J, _vec(B)) + end + # Add result + axpby!(W.gamma, _vec(W._func_cache), -one(W.gamma), _vec(Y)) + end +end + +""" + islinearfunction(integrator) -> Tuple{Bool,Bool} + +return the tuple `(is_linear_wrt_odealg, islinearodefunction)`. +""" +islinearfunction(integrator) = islinearfunction(integrator.f, integrator.alg) + +""" + islinearfunction(f, alg) -> Tuple{Bool,Bool} + +return the tuple `(is_linear_wrt_odealg, islinearodefunction)`. +""" +function islinearfunction(f, alg)::Tuple{Bool, Bool} + isode = f isa ODEFunction && islinear(f.f) + islin = isode || (issplit(alg) && f isa SplitFunction && islinear(f.f1.f)) + return islin, isode +end + +function do_newJW(integrator, alg, nlsolver, repeat_step)::NTuple{2, Bool} + integrator.iter <= 1 && return true, true # at least one JW eval at the start + repeat_step && return false, false + islin, _ = islinearfunction(integrator) + islin && return false, false # no further JW eval when it's linear + !integrator.opts.adaptive && return true, true # Not adaptive will always refactorize + errorfail = integrator.EEst > one(integrator.EEst) + if alg isa DAEAlgorithm + return true, true + end + # TODO: add `isJcurrent` support for Rosenbrock solvers + if !isnewton(nlsolver) + isfreshJ = !(integrator.alg isa CompositeAlgorithm) && + (integrator.iter > 1 && errorfail && !integrator.u_modified) + return !isfreshJ, true + end + isfirstcall(nlsolver) && return true, true + isfs = isfirststage(nlsolver) + isfreshJ = isJcurrent(nlsolver, integrator) && !integrator.u_modified + iszero(nlsolver.fast_convergence_cutoff) && return isfs && !isfreshJ, isfs + mm = integrator.f.mass_matrix + is_varying_mm = !isconstant(mm) + if isfreshJ + jbad = false + smallstepchange = true + else + W_iγdt = inv(nlsolver.cache.W_γdt) + iγdt = inv(nlsolver.γ * integrator.dt) + smallstepchange = abs(iγdt / W_iγdt - 1) <= get_new_W_γdt_cutoff(nlsolver) + jbad = nlsolver.status === TryAgain && smallstepchange + end + wbad = (!smallstepchange) || (isfs && errorfail) || nlsolver.status === Divergence + return jbad, (is_varying_mm || jbad || wbad) +end + +@noinline _throwWJerror(W, J) = throw(DimensionMismatch("W: $(axes(W)), J: $(axes(J))")) +@noinline function _throwWMerror(W, mass_matrix) + throw(DimensionMismatch("W: $(axes(W)), mass matrix: $(axes(mass_matrix))")) +end +@noinline function _throwJMerror(J, mass_matrix) + throw(DimensionMismatch("J: $(axes(J)), mass matrix: $(axes(mass_matrix))")) +end + +function jacobian2W!( + W::AbstractMatrix, mass_matrix, dtgamma::Number, J::AbstractMatrix, + W_transform::Bool)::Nothing + # check size and dimension + iijj = axes(W) + @boundscheck (iijj == axes(J) && length(iijj) == 2) || _throwWJerror(W, J) + mass_matrix isa UniformScaling || + @boundscheck axes(mass_matrix) == axes(W) || _throwWMerror(W, mass_matrix) + @inbounds if W_transform + invdtgamma = inv(dtgamma) + if mass_matrix isa UniformScaling + copyto!(W, J) + idxs = diagind(W) + λ = -mass_matrix.λ + if ArrayInterface.fast_scalar_indexing(J) && + ArrayInterface.fast_scalar_indexing(W) + @inbounds for i in 1:size(J, 1) + W[i, i] = muladd(λ, invdtgamma, J[i, i]) + end + else + @.. broadcast=false @view(W[idxs])=muladd(λ, invdtgamma, @view(J[idxs])) + end + else + @.. broadcast=false W=muladd(-mass_matrix, invdtgamma, J) + end + else + if mass_matrix isa UniformScaling + λ = -mass_matrix.λ + if W isa SparseMatrixCSC + #= + using LinearAlgebra, SparseArrays, FastBroadcast + J = sparse(Diagonal(ones(4))) + W = sparse(Diagonal(ones(4))); + J[4,4] = 0 + gamma = 1.0 + W .= gamma .* J + + 4×4 SparseMatrixCSC{Float64, Int64} with 3 stored entries: + 1.0 ⋅ ⋅ ⋅ + ⋅ 1.0 ⋅ ⋅ + ⋅ ⋅ 1.0 ⋅ + ⋅ ⋅ ⋅ ⋅ + + Thus broadcast cannot be used. + + Instead, check the sparsity pattern is correct and directly broadcast the nzval + =# + @assert J.colptr == W.colptr + @assert J.rowval == W.rowval + @.. broadcast=false W.nzval=dtgamma * J.nzval + idxs = diagind(W) + @.. broadcast=false @view(W[idxs])=@view(W[idxs]) + λ + elseif W isa AbstractSparseMatrix + # This is specifically to catch the GPU sparse matrix cases + # Which do not support diagonal indexing + # https://github.com/JuliaGPU/CUDA.jl/issues/1395 + + Wn = nonzeros(W) + Jn = nonzeros(J) + + # I would hope to check this generically, but `CuSparseMatrixCSC` has `colPtr` + # and `rowVal` while SparseMatrixCSC is colptr and rowval, and there is no + # standard for checking sparsity patterns in general. So for now, write it for + # the convention of CUDA.jl and handle the case of some other convention when + # it comes up. + + @assert J.colPtr == W.colPtr + @assert J.rowVal == W.rowVal + + @.. broadcast=false Wn=dtgamma * Jn + W .= W + λ * I + else # Anything not a sparse matrix + @.. broadcast=false W=dtgamma * J + idxs = diagind(W) + @.. broadcast=false @view(W[idxs])=@view(W[idxs]) + λ + end + else + @.. broadcast=false W=muladd(dtgamma, J, -mass_matrix) + end + end + return nothing +end + +function jacobian2W!(W::Matrix, mass_matrix, dtgamma::Number, J::Matrix, + W_transform::Bool)::Nothing + # check size and dimension + iijj = axes(W) + @boundscheck (iijj == axes(J) && length(iijj) == 2) || _throwWJerror(W, J) + mass_matrix isa UniformScaling || + @boundscheck axes(mass_matrix) == axes(W) || _throwWMerror(W, mass_matrix) + @inbounds if W_transform + invdtgamma = inv(dtgamma) + if mass_matrix isa UniformScaling + copyto!(W, J) + idxs = diagind(W) + λ = -mass_matrix.λ + @inbounds for i in 1:size(J, 1) + W[i, i] = muladd(λ, invdtgamma, J[i, i]) + end + else + @inbounds @simd ivdep for i in eachindex(W) + W[i] = muladd(-mass_matrix[i], invdtgamma, J[i]) + end + end + else + if mass_matrix isa UniformScaling + idxs = diagind(W) + @inbounds @simd ivdep for i in eachindex(W) + W[i] = dtgamma * J[i] + end + λ = -mass_matrix.λ + @inbounds for i in idxs + W[i] = W[i] + λ + end + else + @inbounds @simd ivdep for i in eachindex(W) + W[i] = muladd(dtgamma, J[i], -mass_matrix[i]) + end + end + end + return nothing +end + +function jacobian2W(mass_matrix, dtgamma::Number, J::AbstractMatrix, + W_transform::Bool) + # check size and dimension + mass_matrix isa UniformScaling || + @boundscheck axes(mass_matrix) == axes(J) || _throwJMerror(J, mass_matrix) + @inbounds if W_transform + invdtgamma = inv(dtgamma) + if mass_matrix isa UniformScaling + λ = -mass_matrix.λ + W = J + (λ * invdtgamma) * I + else + W = muladd(-mass_matrix, invdtgamma, J) + end + else + if mass_matrix isa UniformScaling + λ = -mass_matrix.λ + W = dtgamma * J + λ * I + else + W = muladd(dtgamma, J, -mass_matrix) + end + end + return W +end + +is_always_new(alg) = isdefined(alg, :always_new) ? alg.always_new : false + +function calc_W!(W, integrator, nlsolver::Union{Nothing, AbstractNLSolver}, cache, dtgamma, + repeat_step, W_transform = false, newJW = nothing) + @unpack t, dt, uprev, u, f, p = integrator + lcache = nlsolver === nothing ? cache : nlsolver.cache + next_step = is_always_new(nlsolver) + if next_step + t = t + integrator.dt + uprev = integrator.u + end + + @unpack J = lcache + isdae = integrator.alg isa DAEAlgorithm + alg = unwrap_alg(integrator, true) + if !isdae + mass_matrix = integrator.f.mass_matrix + end + is_compos = integrator.alg isa CompositeAlgorithm + + # handle Wfact + if W_transform && DiffEqBase.has_Wfact_t(f) + f.Wfact_t(W, u, p, dtgamma, t) + isnewton(nlsolver) && set_W_γdt!(nlsolver, dtgamma) + is_compos && (integrator.eigen_est = constvalue(opnorm(LowerTriangular(W), Inf)) + + inv(dtgamma)) # TODO: better estimate + # It's equivalent with evaluating a new Jacobian, but not a new W, + # because we won't call `lu!`, and the iteration matrix is fresh. + return (true, false) + elseif !W_transform && DiffEqBase.has_Wfact(f) + f.Wfact(W, u, p, dtgamma, t) + isnewton(nlsolver) && set_W_γdt!(nlsolver, dtgamma) + if is_compos + opn = opnorm(LowerTriangular(W), Inf) + integrator.eigen_est = (constvalue(opn) + one(opn)) / dtgamma # TODO: better estimate + end + return (true, false) + end + + # check if we need to update J or W + if newJW === nothing + new_jac, new_W = do_newJW(integrator, alg, nlsolver, repeat_step) + else + new_jac, new_W = newJW + end + + if new_jac && isnewton(lcache) + lcache.J_t = t + if isdae + lcache.uf.α = nlsolver.α + lcache.uf.invγdt = inv(dtgamma) + lcache.uf.tmp = nlsolver.tmp + end + end + + # calculate W + if W isa WOperator + if isnewton(nlsolver) + # we will call `update_coefficients!` for u/p/t in NLNewton + update_coefficients!(W; transform = W_transform, dtgamma) + else + update_coefficients!(W, uprev, p, t; transform = W_transform, dtgamma) + end + if W.J !== nothing && !(W.J isa AbstractSciMLOperator) + islin, isode = islinearfunction(integrator) + islin ? (J = isode ? f.f : f.f1.f) : + (new_jac && (calc_J!(W.J, integrator, lcache, next_step))) + new_W && !isdae && + jacobian2W!(W._concrete_form, mass_matrix, dtgamma, J, W_transform) + end + elseif W isa AbstractSciMLOperator && !(W isa StaticWOperator) + update_coefficients!(W, uprev, p, t; transform = W_transform, dtgamma) + else # concrete W using jacobian from `calc_J!` + islin, isode = islinearfunction(integrator) + islin ? (J = isode ? f.f : f.f1.f) : + (new_jac && (calc_J!(J, integrator, lcache, next_step))) + new_W && !isdae && jacobian2W!(W, mass_matrix, dtgamma, J, W_transform) + end + if isnewton(nlsolver) + set_new_W!(nlsolver, new_W) + if new_jac && isdae + set_W_γdt!(nlsolver, nlsolver.α * inv(dtgamma)) + elseif new_W && !isdae + set_W_γdt!(nlsolver, dtgamma) + end + end + + new_W && (integrator.stats.nw += 1) + return new_jac, new_W +end + +@noinline function calc_W(integrator, nlsolver, dtgamma, repeat_step, W_transform = false) + @unpack t, uprev, p, f = integrator + + next_step = is_always_new(nlsolver) + if next_step + t = t + integrator.dt + uprev = integrator.u + end + # Handle Rosenbrock has no nlsolver so passes cache directly + cache = nlsolver isa OrdinaryDiffEqCache ? nlsolver : nlsolver.cache + + isdae = integrator.alg isa DAEAlgorithm + if !isdae + mass_matrix = integrator.f.mass_matrix + end + isarray = uprev isa AbstractArray + # calculate W + is_compos = integrator.alg isa CompositeAlgorithm + islin, isode = islinearfunction(integrator) + !isdae && update_coefficients!(mass_matrix, uprev, p, t) + + if cache.W isa StaticWOperator + integrator.stats.nw += 1 + J = calc_J(integrator, cache, next_step) + W = StaticWOperator(W_transform ? J - mass_matrix * inv(dtgamma) : + dtgamma * J - mass_matrix) + elseif cache.W isa WOperator + integrator.stats.nw += 1 + J = if islin + isode ? f.f : f.f1.f + else + calc_J(integrator, cache, next_step) + end + W = WOperator{false}( + mass_matrix, dtgamma, J, uprev, cache.W.jacvec; transform = W_transform) + elseif cache.W isa AbstractSciMLOperator + W = update_coefficients(cache.W, uprev, p, t; dtgamma, transform = W_transform) + else + integrator.stats.nw += 1 + J = islin ? isode ? f.f : f.f1.f : calc_J(integrator, cache, next_step) + if isdae + W = J + else + W = W_transform ? J - mass_matrix * inv(dtgamma) : + dtgamma * J - mass_matrix + if !isa(W, Number) + W = DiffEqBase.default_factorize(W) + end + end + end + is_compos && (integrator.eigen_est = isarray ? constvalue(opnorm(J, Inf)) : + integrator.opts.internalnorm(J, t)) + return W +end + +function calc_rosenbrock_differentiation!(integrator, cache, dtd1, dtgamma, repeat_step, + W_transform) + nlsolver = nothing + # we need to skip calculating `J` and `W` when a step is repeated + new_jac = new_W = false + if !repeat_step + new_jac, new_W = calc_W!( + cache.W, integrator, nlsolver, cache, dtgamma, repeat_step, + W_transform) + end + # If the Jacobian is not updated, we won't have to update ∂/∂t either. + calc_tderivative!(integrator, cache, dtd1, repeat_step || !new_jac) + return new_W +end + +# update W matrix (only used in Newton method) +function update_W!(integrator, cache, dtgamma, repeat_step, newJW = nothing) + update_W!(cache.nlsolver, integrator, cache, dtgamma, repeat_step, newJW) +end + +function update_W!(nlsolver::AbstractNLSolver, + integrator::SciMLBase.DEIntegrator{<:Any, true}, cache, dtgamma, + repeat_step::Bool, newJW = nothing) + if isnewton(nlsolver) + calc_W!(get_W(nlsolver), integrator, nlsolver, cache, dtgamma, repeat_step, true, + newJW) + end + nothing +end + +function update_W!(nlsolver::AbstractNLSolver, + integrator::SciMLBase.DEIntegrator{<:Any, false}, cache, dtgamma, + repeat_step::Bool, newJW = nothing) + if isnewton(nlsolver) + isdae = integrator.alg isa DAEAlgorithm + new_jac, new_W = true, true + if isdae && new_jac + lcache = nlsolver.cache + lcache.uf.α = nlsolver.α + lcache.uf.invγdt = inv(dtgamma) + lcache.uf.tmp = @. nlsolver.tmp + lcache.uf.uprev = @. integrator.uprev + end + nlsolver.cache.W = calc_W(integrator, nlsolver, dtgamma, repeat_step, true) + #TODO: jacobian reuse for oop + new_jac && (nlsolver.cache.J_t = integrator.t) + set_new_W!(nlsolver, new_W) + if new_jac && isdae + set_W_γdt!(nlsolver, nlsolver.α * inv(dtgamma)) + elseif new_W && !isdae + set_W_γdt!(nlsolver, dtgamma) + end + end + nothing +end + +function build_J_W(alg, u, uprev, p, t, dt, f::F, ::Type{uEltypeNoUnits}, + ::Val{IIP}) where {IIP, uEltypeNoUnits, F} + # TODO - make J, W AbstractSciMLOperators (lazily defined with scimlops functionality) + # TODO - if jvp given, make it SciMLOperators.FunctionOperator + # TODO - make mass matrix a SciMLOperator so it can be updated with time. Default to IdentityOperator + islin, isode = islinearfunction(f, alg) + if isdefined(f, :W_prototype) && (f.W_prototype isa AbstractSciMLOperator) + # We use W_prototype when it is provided as a SciMLOperator, and in this case we require jac_prototype to be a SciMLOperator too. + if !(f.jac_prototype isa AbstractSciMLOperator) + error("SciMLOperator for W_prototype only supported when jac_prototype is a SciMLOperator, but got $(typeof(f.jac_prototype))") + end + W = f.W_prototype + J = f.jac_prototype + elseif f.jac_prototype isa AbstractSciMLOperator + W = WOperator{IIP}(f, u, dt) + J = W.J + elseif islin + J = isode ? f.f : f.f1.f # unwrap the Jacobian accordingly + W = WOperator{IIP}(f.mass_matrix, dt, J, u) + elseif IIP && f.jac_prototype !== nothing && concrete_jac(alg) === nothing && + (alg.linsolve === nothing || LinearSolve.needs_concrete_A(alg.linsolve)) + + # If factorization, then just use the jac_prototype + J = similar(f.jac_prototype) + W = similar(J) + elseif (IIP && (concrete_jac(alg) === nothing || !concrete_jac(alg)) && + alg.linsolve !== nothing && + !LinearSolve.needs_concrete_A(alg.linsolve)) + # If the user has chosen GMRES but no sparse Jacobian, assume that the dense + # Jacobian is a bad idea and create a fully matrix-free solver. This can + # be overridden with concrete_jac. + + _f = islin ? (isode ? f.f : f.f1.f) : f + jacvec = JacVec((du, u, p, t) -> _f(du, u, p, t), copy(u), p, t; + autodiff = alg_autodiff(alg), tag = OrdinaryDiffEqTag()) + J = jacvec + W = WOperator{IIP}(f.mass_matrix, dt, J, u, jacvec) + elseif alg.linsolve !== nothing && !LinearSolve.needs_concrete_A(alg.linsolve) || + concrete_jac(alg) !== nothing && concrete_jac(alg) + # The linear solver does not need a concrete Jacobian, but the user has + # asked for one. This will happen when the Jacobian is used in the preconditioner + # Thus setup JacVec and a concrete J, using sparsity when possible + _f = islin ? (isode ? f.f : f.f1.f) : f + J = if f.jac_prototype === nothing + ArrayInterface.undefmatrix(u) + else + deepcopy(f.jac_prototype) + end + W = if J isa StaticMatrix + StaticWOperator(J, false) + else + __f = if IIP + (du, u, p, t) -> _f(du, u, p, t) + else + (u, p, t) -> _f(u, p, t) + end + jacvec = JacVec(__f, copy(u), p, t; + autodiff = alg_autodiff(alg), tag = OrdinaryDiffEqTag()) + WOperator{IIP}(f.mass_matrix, dt, J, u, jacvec) + end + else + J = if !IIP && DiffEqBase.has_jac(f) + f.jac(uprev, p, t) + elseif f.jac_prototype === nothing + ArrayInterface.undefmatrix(u) + else + deepcopy(f.jac_prototype) + end + W = if alg isa DAEAlgorithm + J + elseif IIP + similar(J) + elseif J isa StaticMatrix + StaticWOperator(J, false) + else + ArrayInterface.lu_instance(J) + end + end + return J, W +end + +build_uf(alg, nf, t, p, ::Val{true}) = UJacobianWrapper(nf, t, p) +build_uf(alg, nf, t, p, ::Val{false}) = UDerivativeWrapper(nf, t, p) + +function LinearSolve.init_cacheval( + alg::LinearSolve.DefaultLinearSolver, A::WOperator, b, u, + Pl, Pr, + maxiters::Int, abstol, reltol, verbose::Bool, + assumptions::OperatorAssumptions) + LinearSolve.init_cacheval(alg, A.J, b, u, Pl, Pr, + maxiters::Int, abstol, reltol, verbose::Bool, + assumptions::OperatorAssumptions) +end + +for alg in InteractiveUtils.subtypes(LinearSolve.AbstractFactorization) + @eval function LinearSolve.init_cacheval(alg::$alg, A::WOperator, b, u, Pl, Pr, + maxiters::Int, abstol, reltol, verbose::Bool, + assumptions::OperatorAssumptions) + LinearSolve.init_cacheval(alg, A.J, b, u, Pl, Pr, + maxiters::Int, abstol, reltol, verbose::Bool, + assumptions::OperatorAssumptions) + end +end + +function resize_J_W!(cache, integrator, i) + (isdefined(cache, :J) && isdefined(cache, :W)) || return + + @unpack f = integrator + + if cache.W isa WOperator + nf = nlsolve_f(f, integrator.alg) + islin = f isa Union{ODEFunction, SplitFunction} && islinear(nf.f) + if !islin + if cache.J isa AbstractSciMLOperator + resize!(cache.J, i) + elseif f.jac_prototype !== nothing + J = similar(f.jac_prototype, i, i) + J = MatrixOperator(J; update_func! = f.jac) + end + if cache.W.jacvec isa AbstractSciMLOperator + resize!(cache.W.jacvec, i) + end + cache.W = WOperator{DiffEqBase.isinplace(integrator.sol.prob)}(f.mass_matrix, + integrator.dt, + cache.J, + integrator.u, + cache.W.jacvec; + transform = cache.W.transform) + cache.J = cache.W.J + end + else + if cache.J !== nothing + cache.J = similar(cache.J, i, i) + end + cache.W = similar(cache.W, i, i) + end + + nothing +end \ No newline at end of file diff --git a/lib/OrdinaryDiffEqDifferentiation/src/derivative_wrappers.jl b/lib/OrdinaryDiffEqDifferentiation/src/derivative_wrappers.jl new file mode 100644 index 0000000000..b5948646cf --- /dev/null +++ b/lib/OrdinaryDiffEqDifferentiation/src/derivative_wrappers.jl @@ -0,0 +1,411 @@ +const FIRST_AUTODIFF_TGRAD_MESSAGE = """ + First call to automatic differentiation for time gradient + failed. This means that the user `f` function is not compatible + with automatic differentiation. Methods to fix this include: + + 1. Turn off automatic differentiation (e.g. Rosenbrock23() becomes + Rosenbrock23(autodiff=false)). More details can be found at + https://docs.sciml.ai/DiffEqDocs/stable/features/performance_overloads/ + 2. Improving the compatibility of `f` with ForwardDiff.jl automatic + differentiation (using tools like PreallocationTools.jl). More details + can be found at https://docs.sciml.ai/DiffEqDocs/stable/basics/faq/#Autodifferentiation-and-Dual-Numbers + 3. Defining analytical Jacobians and time gradients. More details can be + found at https://docs.sciml.ai/DiffEqDocs/stable/types/ode_types/#SciMLBase.ODEFunction + + Note 1: this failure occurred inside of the time gradient function. These + time gradients are only required by Rosenbrock methods (`Rosenbrock23`, + `Rodas4`, etc.) are are done by automatic differentiation w.r.t. the + argument `t`. If your function is compatible with automatic differentiation + w.r.t. `u`, i.e. for Jacobian generation, another way to work around this + issue is to switch to a non-Rosenbrock method. + + Note 2: turning off automatic differentiation tends to have a very minimal + performance impact (for this use case, because it's forward mode for a + square Jacobian. This is different from optimization gradient scenarios). + However, one should be careful as some methods are more sensitive to + accurate gradients than others. Specifically, Rodas methods like `Rodas4` + and `Rodas5P` require accurate Jacobians in order to have good convergence, + while many other methods like BDF (`QNDF`, `FBDF`), SDIRK (`KenCarp4`), + and Rosenbrock-W (`Rosenbrock23`) do not. Thus if using an algorithm which + is sensitive to autodiff and solving at a low tolerance, please change the + algorithm as well. + """ + +struct FirstAutodiffTgradError <: Exception + e::Any +end + +function Base.showerror(io::IO, e::FirstAutodiffTgradError) + println(io, FIRST_AUTODIFF_TGRAD_MESSAGE) + Base.showerror(io, e.e) +end + +const FIRST_AUTODIFF_JAC_MESSAGE = """ + First call to automatic differentiation for the Jacobian + failed. This means that the user `f` function is not compatible + with automatic differentiation. Methods to fix this include: + + 1. Turn off automatic differentiation (e.g. Rosenbrock23() becomes + Rosenbrock23(autodiff=false)). More details can befound at + https://docs.sciml.ai/DiffEqDocs/stable/features/performance_overloads/ + 2. Improving the compatibility of `f` with ForwardDiff.jl automatic + differentiation (using tools like PreallocationTools.jl). More details + can be found at https://docs.sciml.ai/DiffEqDocs/stable/basics/faq/#Autodifferentiation-and-Dual-Numbers + 3. Defining analytical Jacobians. More details can be + found at https://docs.sciml.ai/DiffEqDocs/stable/types/ode_types/#SciMLBase.ODEFunction + + Note: turning off automatic differentiation tends to have a very minimal + performance impact (for this use case, because it's forward mode for a + square Jacobian. This is different from optimization gradient scenarios). + However, one should be careful as some methods are more sensitive to + accurate gradients than others. Specifically, Rodas methods like `Rodas4` + and `Rodas5P` require accurate Jacobians in order to have good convergence, + while many other methods like BDF (`QNDF`, `FBDF`), SDIRK (`KenCarp4`), + and Rosenbrock-W (`Rosenbrock23`) do not. Thus if using an algorithm which + is sensitive to autodiff and solving at a low tolerance, please change the + algorithm as well. + """ + +struct FirstAutodiffJacError <: Exception + e::Any +end + +function Base.showerror(io::IO, e::FirstAutodiffJacError) + println(io, FIRST_AUTODIFF_JAC_MESSAGE) + Base.showerror(io, e.e) +end + +function derivative!(df::AbstractArray{<:Number}, f, + x::Union{Number, AbstractArray{<:Number}}, fx::AbstractArray{<:Number}, + integrator, grad_config) + alg = unwrap_alg(integrator, true) + tmp = length(x) # We calculate derivative for all elements in gradient + if alg_autodiff(alg) isa AutoForwardDiff + T = if standardtag(alg) + typeof(ForwardDiff.Tag(OrdinaryDiffEqTag(), eltype(df))) + else + typeof(ForwardDiff.Tag(f, eltype(df))) + end + + xdual = Dual{T, eltype(df), 1}(convert(eltype(df), x), + ForwardDiff.Partials((one(eltype(df)),))) + + if integrator.iter == 1 + try + f(grad_config, xdual) + catch e + throw(FirstAutodiffTgradError(e)) + end + else + f(grad_config, xdual) + end + + df .= first.(ForwardDiff.partials.(grad_config)) + integrator.stats.nf += 1 + elseif alg_autodiff(alg) isa AutoFiniteDiff + FiniteDiff.finite_difference_gradient!(df, f, x, grad_config, + dir = diffdir(integrator)) + fdtype = alg_difftype(alg) + if fdtype == Val{:forward} || fdtype == Val{:central} + tmp *= 2 + if eltype(df) <: Complex + tmp *= 2 + end + end + integrator.stats.nf += tmp + else + error("$alg_autodiff not yet supported in derivative! function") + end + nothing +end + +function derivative(f, x::Union{Number, AbstractArray{<:Number}}, + integrator) + local d + tmp = length(x) # We calculate derivative for all elements in gradient + alg = unwrap_alg(integrator, true) + if alg_autodiff(alg) isa AutoForwardDiff + integrator.stats.nf += 1 + if integrator.iter == 1 + try + d = ForwardDiff.derivative(f, x) + catch e + throw(FirstAutodiffTgradError(e)) + end + else + d = ForwardDiff.derivative(f, x) + end + elseif alg_autodiff(alg) isa AutoFiniteDiff + d = FiniteDiff.finite_difference_derivative(f, x, alg_difftype(alg), + dir = diffdir(integrator)) + if alg_difftype(alg) === Val{:central} || alg_difftype(alg) === Val{:forward} + tmp *= 2 + end + integrator.stats.nf += tmp + d + else + error("$alg_autodiff not yet supported in derivative function") + end +end + +jacobian_autodiff(f, x, odefun, alg) = (ForwardDiff.derivative(f, x), 1, alg) +function jacobian_autodiff(f, x::AbstractArray, odefun, alg) + jac_prototype = odefun.jac_prototype + sparsity, colorvec = sparsity_colorvec(odefun, x) + maxcolor = maximum(colorvec) + chunk_size = get_chunksize(alg) === Val(0) ? nothing : get_chunksize(alg) + num_of_chunks = chunk_size === nothing ? + Int(ceil(maxcolor / getsize(ForwardDiff.pickchunksize(maxcolor)))) : + Int(ceil(maxcolor / _unwrap_val(chunk_size))) + ( + forwarddiff_color_jacobian(f, x, colorvec = colorvec, sparsity = sparsity, + jac_prototype = jac_prototype, chunksize = chunk_size), + num_of_chunks) +end + +function _nfcount(N, ::Type{diff_type}) where {diff_type} + if diff_type === Val{:complex} + tmp = N + elseif diff_type === Val{:forward} + tmp = N + 1 + else + tmp = 2N + end + tmp +end + +function jacobian_finitediff(f, x, ::Type{diff_type}, dir, colorvec, sparsity, + jac_prototype) where {diff_type} + (FiniteDiff.finite_difference_derivative(f, x, diff_type, eltype(x), dir = dir), 2) +end +function jacobian_finitediff(f, x::AbstractArray, ::Type{diff_type}, dir, colorvec, + sparsity, jac_prototype) where {diff_type} + f_in = diff_type === Val{:forward} ? f(x) : similar(x) + ret_eltype = eltype(f_in) + J = FiniteDiff.finite_difference_jacobian(f, x, diff_type, ret_eltype, f_in, + dir = dir, colorvec = colorvec, + sparsity = sparsity, + jac_prototype = jac_prototype) + return J, _nfcount(maximum(colorvec), diff_type) +end +function jacobian(f, x, integrator) + alg = unwrap_alg(integrator, true) + local tmp + if alg_autodiff(alg) isa AutoForwardDiff + if integrator.iter == 1 + try + J, tmp = jacobian_autodiff(f, x, integrator.f, alg) + catch e + throw(FirstAutodiffJacError(e)) + end + else + J, tmp = jacobian_autodiff(f, x, integrator.f, alg) + end + elseif alg_autodiff(alg) isa AutoFiniteDiff + jac_prototype = integrator.f.jac_prototype + sparsity, colorvec = sparsity_colorvec(integrator.f, x) + dir = diffdir(integrator) + J, tmp = jacobian_finitediff(f, x, alg_difftype(alg), dir, colorvec, sparsity, + jac_prototype) + else + bleh + end + integrator.stats.nf += tmp + J +end + +function jacobian_finitediff_forward!(J, f, x, jac_config, forwardcache, integrator) + (FiniteDiff.finite_difference_jacobian!(J, f, x, jac_config, forwardcache, + dir = diffdir(integrator)); + maximum(jac_config.colorvec)) +end +function jacobian_finitediff!(J, f, x, jac_config, integrator) + (FiniteDiff.finite_difference_jacobian!(J, f, x, jac_config, + dir = diffdir(integrator)); + 2 * maximum(jac_config.colorvec)) +end + +function jacobian!(J::AbstractMatrix{<:Number}, f, x::AbstractArray{<:Number}, + fx::AbstractArray{<:Number}, integrator::DiffEqBase.DEIntegrator, + jac_config) + alg = unwrap_alg(integrator, true) + if alg_autodiff(alg) isa AutoForwardDiff + if integrator.iter == 1 + try + forwarddiff_color_jacobian!(J, f, x, jac_config) + catch e + throw(FirstAutodiffJacError(e)) + end + else + forwarddiff_color_jacobian!(J, f, x, jac_config) + end + integrator.stats.nf += 1 + elseif alg_autodiff(alg) isa AutoFiniteDiff + isforward = alg_difftype(alg) === Val{:forward} + if isforward + forwardcache = get_tmp_cache(integrator, alg, unwrap_cache(integrator, true))[2] + f(forwardcache, x) + integrator.stats.nf += 1 + tmp = jacobian_finitediff_forward!(J, f, x, jac_config, forwardcache, + integrator) + else # not forward difference + tmp = jacobian_finitediff!(J, f, x, jac_config, integrator) + end + integrator.stats.nf += tmp + else + error("$alg_autodiff not yet supported in jacobian! function") + end + nothing +end + +function build_jac_config(alg, f::F1, uf::F2, du1, uprev, u, tmp, du2, + ::Val{transform} = Val(true)) where {transform, F1, F2} + haslinsolve = hasfield(typeof(alg), :linsolve) + + if !DiffEqBase.has_jac(f) && # No Jacobian if has analytical solution + (transform || !DiffEqBase.has_Wfact(f)) && # No Jacobian if has_Wfact and Wfact is the one that's used + (!transform || !DiffEqBase.has_Wfact_t(f)) && # No Jacobian has_Wfact and Wfact_t is the one that's used + ((concrete_jac(alg) === nothing && (!haslinsolve || (haslinsolve && # No Jacobian if linsolve doesn't want it + (alg.linsolve === nothing || LinearSolve.needs_concrete_A(alg.linsolve))))) || + (concrete_jac(alg) !== nothing && concrete_jac(alg))) # Jacobian if explicitly asked for + jac_prototype = f.jac_prototype + + if jac_prototype isa SparseMatrixCSC + if f.mass_matrix isa UniformScaling + idxs = diagind(jac_prototype) + @. @view(jac_prototype[idxs]) = 1 + else + idxs = findall(!iszero, f.mass_matrix) + @. @view(jac_prototype[idxs]) = @view(f.mass_matrix[idxs]) + end + end + + sparsity, colorvec = sparsity_colorvec(f, u) + + if alg_autodiff(alg) isa AutoForwardDiff + _chunksize = get_chunksize(alg) === Val(0) ? nothing : get_chunksize(alg) # SparseDiffEq uses different convection... + T = if standardtag(alg) + typeof(ForwardDiff.Tag(OrdinaryDiffEqTag(), eltype(u))) + else + typeof(ForwardDiff.Tag(uf, eltype(u))) + end + jac_config = ForwardColorJacCache(uf, uprev, _chunksize; colorvec = colorvec, + sparsity = sparsity, tag = T) + elseif alg_autodiff(alg) isa AutoFiniteDiff + if alg_difftype(alg) !== Val{:complex} + jac_config = FiniteDiff.JacobianCache(tmp, du1, du2, alg_difftype(alg), + colorvec = colorvec, + sparsity = sparsity) + else + jac_config = FiniteDiff.JacobianCache(Complex{eltype(tmp)}.(tmp), + Complex{eltype(du1)}.(du1), nothing, + alg_difftype(alg), eltype(u), + colorvec = colorvec, + sparsity = sparsity) + end + else + error("$alg_autodiff not yet supported in build_jac_config function") + end + else + jac_config = nothing + end + jac_config +end + +function get_chunksize(jac_config::ForwardDiff.JacobianConfig{ + T, + V, + N, + D +}) where {T, V, N, D +} + Val(N) +end # don't degrade compile time information to runtime information + +function resize_jac_config!(jac_config::SparseDiffTools.ForwardColorJacCache, i) + resize!(jac_config.fx, i) + resize!(jac_config.dx, i) + resize!(jac_config.t, i) + ps = SparseDiffTools.adapt.(DiffEqBase.parameterless_type(jac_config.dx), + SparseDiffTools.generate_chunked_partials(jac_config.dx, + 1:length(jac_config.dx), + Val(ForwardDiff.npartials(jac_config.t[1])))) + resize!(jac_config.p, length(ps)) + jac_config.p .= ps +end + +function resize_jac_config!(jac_config::FiniteDiff.JacobianCache, i) + resize!(jac_config, i) + jac_config +end + +function resize_grad_config!(grad_config::AbstractArray, i) + resize!(grad_config, i) + grad_config +end + +function resize_grad_config!(grad_config::ForwardDiff.DerivativeConfig, i) + resize!(grad_config.duals, i) + grad_config +end + +function resize_grad_config!(grad_config::FiniteDiff.GradientCache, i) + @unpack fx, c1, c2 = grad_config + fx !== nothing && resize!(fx, i) + c1 !== nothing && resize!(c1, i) + c2 !== nothing && resize!(c2, i) + grad_config +end + +function build_grad_config(alg, f::F1, tf::F2, du1, t) where {F1, F2} + if !DiffEqBase.has_tgrad(f) + if alg_autodiff(alg) isa AutoForwardDiff + T = if standardtag(alg) + typeof(ForwardDiff.Tag(OrdinaryDiffEqTag(), eltype(du1))) + else + typeof(ForwardDiff.Tag(f, eltype(du1))) + end + + if du1 isa Array + dualt = Dual{T, eltype(du1), 1}(first(du1) * t, + ForwardDiff.Partials((one(eltype(du1)),))) + grad_config = similar(du1, typeof(dualt)) + fill!(grad_config, false) + else + grad_config = ArrayInterface.restructure(du1, + Dual{ + T, + eltype(du1), + 1 + }.(du1, + (ForwardDiff.Partials((one(eltype(du1)),)),)) .* + false) + end + elseif alg_autodiff(alg) isa AutoFiniteDiff + grad_config = FiniteDiff.GradientCache(du1, t, alg_difftype(alg)) + else + error("$alg_autodiff not yet supported in build_grad_config function") + end + else + grad_config = nothing + end + grad_config +end + +function sparsity_colorvec(f, x) + sparsity = f.sparsity + + if sparsity isa SparseMatrixCSC + if f.mass_matrix isa UniformScaling + idxs = diagind(sparsity) + @. @view(sparsity[idxs]) = 1 + else + idxs = findall(!iszero, f.mass_matrix) + @. @view(sparsity[idxs]) = @view(f.mass_matrix[idxs]) + end + end + + colorvec = DiffEqBase.has_colorvec(f) ? f.colorvec : + (isnothing(sparsity) ? (1:length(x)) : matrix_colors(sparsity)) + sparsity, colorvec +end diff --git a/lib/OrdinaryDiffEqDifferentiation/src/linsolve_utils.jl b/lib/OrdinaryDiffEqDifferentiation/src/linsolve_utils.jl new file mode 100644 index 0000000000..f2f77162fd --- /dev/null +++ b/lib/OrdinaryDiffEqDifferentiation/src/linsolve_utils.jl @@ -0,0 +1,59 @@ +issuccess_W(W::LinearAlgebra.Factorization) = LinearAlgebra.issuccess(W) +issuccess_W(W::Number) = !iszero(W) +issuccess_W(::Any) = true + +function dolinsolve(integrator, linsolve; A = nothing, linu = nothing, b = nothing, + du = nothing, u = nothing, p = nothing, t = nothing, + weight = nothing, solverdata = nothing, + reltol = integrator === nothing ? nothing : integrator.opts.reltol) + A !== nothing && (linsolve.A = A) + b !== nothing && (linsolve.b = b) + linu !== nothing && (linsolve.u = linu) + + Plprev = linsolve.Pl isa LinearSolve.ComposePreconditioner ? linsolve.Pl.outer : + linsolve.Pl + Prprev = linsolve.Pr isa LinearSolve.ComposePreconditioner ? linsolve.Pr.outer : + linsolve.Pr + + _alg = unwrap_alg(integrator, true) + + _Pl, _Pr = _alg.precs(linsolve.A, du, u, p, t, A !== nothing, Plprev, Prprev, + solverdata) + if (_Pl !== nothing || _Pr !== nothing) + __Pl = _Pl === nothing ? SciMLOperators.IdentityOperator(length(integrator.u)) : _Pl + __Pr = _Pr === nothing ? SciMLOperators.IdentityOperator(length(integrator.u)) : _Pr + linsolve.Pl = __Pl + linsolve.Pr = __Pr + end + + linres = solve!(linsolve; reltol) + + # TODO: this ignores the add of the `f` count for add_steps! + if integrator isa SciMLBase.DEIntegrator && _alg.linsolve !== nothing && + !LinearSolve.needs_concrete_A(_alg.linsolve) && + linsolve.A isa WOperator && linsolve.A.J isa AbstractSciMLOperator + if alg_autodiff(_alg) isa AutoForwardDiff + integrator.stats.nf += linres.iters + elseif alg_autodiff(_alg) isa AutoFiniteDiff + integrator.stats.nf += 2 * linres.iters + else + error("$alg_autodiff not yet supported in dolinsolve function") + end + end + + return linres +end + +function wrapprecs(_Pl::Nothing, _Pr::Nothing, weight, u) + Pl = LinearSolve.InvPreconditioner(Diagonal(_vec(weight))) + Pr = Diagonal(_vec(weight)) + Pl, Pr +end + +function wrapprecs(_Pl, _Pr, weight, u) + Pl = _Pl === nothing ? SciMLOperators.IdentityOperator(length(u)) : _Pl + Pr = _Pr === nothing ? SciMLOperators.IdentityOperator(length(u)) : _Pr + Pl, Pr +end + +Base.resize!(p::LinearSolve.LinearCache, i) = p diff --git a/lib/OrdinaryDiffEqDifferentiation/test/runtests.jl b/lib/OrdinaryDiffEqDifferentiation/test/runtests.jl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/OrdinaryDiffEqNonlinearSolve/Project.toml b/lib/OrdinaryDiffEqNonlinearSolve/Project.toml new file mode 100644 index 0000000000..fa93085036 --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/Project.toml @@ -0,0 +1,20 @@ +name = "OrdinaryDiffEqNonlinearSolve" +uuid = "127b3ac7-2247-4354-8eb6-78cf4e7c58e8" +authors = ["Chris Rackauckas ", "Yingbo Ma "] +version = "1.0.0" + +[deps] +OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +OrdinaryDiffEqDifferentiation = "4302a76b-040a-498a-8c04-15b101fed76b" + +[compat] +julia = "1.10" + +[extras] +DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["DiffEqDevTools", "Random", "SafeTestsets", "Test"] diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl new file mode 100644 index 0000000000..97069910d2 --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl @@ -0,0 +1,49 @@ +module OrdinaryDiffEqNonlinearSolve + +import ADTypes: AutoFiniteDiff, AutoForwardDiff + +import SciMLBase +import SciMLBase: init, solve, solve! +using SciMLBase: DAEFunction, DEIntegrator, NonlinearFunction, NonlinearProblem, NonlinearLeastSquaresProblem, LinearProblem, ODEProblem, DAEProblem, update_coefficients!, get_tmp_cache, AbstractSciMLOperator, ReturnCode +import DiffEqBase +import PreallocationTools +using SimpleNonlinearSolve: SimpleTrustRegion, SimpleGaussNewton +using NonlinearSolve: FastShortcutNonlinearPolyalg, FastShortcutNLLSPolyalg, NewtonRaphson +using MuladdMacro, FastBroadcast +import FastClosures: @closure +using LinearAlgebra: UniformScaling, UpperTriangular +import LinearAlgebra +import ArrayInterface +import LinearSolve +import ForwardDiff +using ForwardDiff: Dual +using LinearSolve: I, rmul!, norm, mul!, ldiv! +using RecursiveArrayTools: recursivecopy! +import SciMLStructures: canonicalize, Tunable, isscimlstructure + +import SciMLOperators: islinear +import OrdinaryDiffEq: nlsolve_f, set_new_W!, set_W_γdt! + +using OrdinaryDiffEq: OrdinaryDiffEqDifferentiation, +AbstractNLSolverAlgorithm, AbstractNLSolverCache, AbstractNLSolver, NewtonAlgorithm, @unpack, +OverrideInit, ShampineCollocationInit, BrownFullBasicInit, _vec, _unwrap_val, DAEAlgorithm, +_reshape, calculate_residuals, calculate_residuals!, has_special_newton_error, isadaptive, +TryAgain, DIRK, COEFFICIENT_MULTISTEP, NORDSIECK_MULTISTEP, GLM, FastConvergence, Convergence, +SlowConvergence, VerySlowConvergence, Divergence, NLStatus, MethodType, alg_order, error_constant, +alg_extrapolates, resize_J_W!, has_autodiff + +import OrdinaryDiffEq: _initialize_dae!, isnewton, get_W, isfirstcall, isfirststage, isJcurrent, get_new_W_γdt_cutoff, resize_nlsolver!, apply_step!, postamble!, build_nlsolver + +import OrdinaryDiffEq.OrdinaryDiffEqDifferentiation: update_W!, is_always_new, build_uf, build_J_W, WOperator, StaticWOperator, wrapprecs, build_jac_config, dolinsolve, alg_autodiff, resize_jac_config! + +import StaticArrays: SArray, MVector, SVector, @SVector, StaticArray, MMatrix, SA, + StaticMatrix + +include("type.jl") +include("utils.jl") +include("nlsolve.jl") +include("functional.jl") +include("newton.jl") +include("initialize_dae.jl") + +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl new file mode 100644 index 0000000000..d6e9898215 --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl @@ -0,0 +1,260 @@ +## initialize! + +@muladd function initialize!(nlsolver::NLSolver{<:NLFunctional}, + integrator::DiffEqBase.DEIntegrator) + nlsolver.cache.tstep = integrator.t + nlsolver.c * integrator.dt + + nothing +end + +@muladd function initialize!(nlsolver::NLSolver{<:NLAnderson}, + integrator::DiffEqBase.DEIntegrator) + @unpack cache = nlsolver + + cache.history = 0 + cache.tstep = integrator.t + nlsolver.c * integrator.dt + + nothing +end + +## initial_η + +function initial_η(nlsolver::NLSolver{<:Union{NLFunctional, NLAnderson}}, integrator) + nlsolver.ηold +end + +## compute_step! + +""" + compute_step!(nlsolver::NLSolver{<:Union{NLFunctional,NLAnderson}}, integrator) + +Compute the next step of the fixed-point iteration + +```math +g(z) = dt⋅f(tmp + γ⋅z, p, t + c⋅dt), +``` + +and return the norm of ``g(z) - z``. + +# References + +Ernst Hairer and Gerhard Wanner, "Solving Ordinary Differential +Equations II, Springer Series in Computational Mathematics. ISBN +978-3-642-05221-7. Section IV.8. +[doi:10.1007/978-3-642-05221-7](https://doi.org/10.1007/978-3-642-05221-7). +""" +function compute_step!(nlsolver::NLSolver{<:NLFunctional}, integrator) + compute_step_fixedpoint!(nlsolver, integrator) +end + +@muladd function compute_step!(nlsolver::NLSolver{<:NLAnderson, false}, integrator) + @unpack cache = nlsolver + @unpack aa_start = cache + + # perform Anderson acceleration + previter = nlsolver.iter - 1 + if previter == aa_start + # update cached values for next step of Anderson acceleration + cache.dzold = cache.dz + cache.z₊old = nlsolver.z + elseif previter > aa_start + # actually perform Anderson acceleration + nlsolver.z = anderson(nlsolver.z, cache) + if DiffEqBase.has_stats(integrator) + integrator.stats.nsolve += 1 + end + end + + # compute next step + compute_step_fixedpoint!(nlsolver, integrator) +end + +@muladd function compute_step!(nlsolver::NLSolver{<:NLAnderson, true}, integrator) + @unpack cache = nlsolver + @unpack aa_start = cache + + # perform Anderson acceleration + previter = nlsolver.iter - 1 + if previter == aa_start + # update cached values for next step of Anderson acceleration + @.. broadcast=false cache.dzold=cache.dz + @.. broadcast=false cache.z₊old=nlsolver.z + elseif previter > aa_start + # actually perform Anderson acceleration + anderson!(nlsolver.z, cache) + if DiffEqBase.has_stats(integrator) + integrator.stats.nsolve += 1 + end + end + + # compute next step + compute_step_fixedpoint!(nlsolver, integrator) +end + +@muladd function compute_step_fixedpoint!( + nlsolver::NLSolver{ + <:Union{NLFunctional, + NLAnderson}, false}, + integrator) + @unpack uprev, t, p, dt, opts = integrator + @unpack z, γ, α, cache, tmp = nlsolver + @unpack tstep = cache + + f = nlsolve_f(integrator) + isdae = f isa DAEFunction + + γdt = γ * dt + if isdae + ustep = @.. broadcast=false uprev+z + invγdt = inv(γdt) + dustep = @.. broadcast=false (tmp + α * z)*invγdt + dz = f(dustep, ustep, p, t) + ztmp = @.. broadcast=false z+dz + else + mass_matrix = integrator.f.mass_matrix + if nlsolver.method === COEFFICIENT_MULTISTEP + ustep = z + if mass_matrix === I + ztmp = (tmp .+ f(z, p, tstep)) * (γdt / α) + dz = ztmp .- z + else + ztmp = _reshape(mass_matrix * _vec(z), axes(z)) + dz = (tmp .+ f(z, p, tstep)) * γdt - α .* ztmp + ztmp = dz .+ z + end + else + ustep = @.. broadcast=false tmp+γ * z + if mass_matrix === I + ztmp = dt .* f(ustep, p, tstep) + dz = ztmp .- z + else + ztmp = _reshape(mass_matrix * _vec(z), axes(z)) + dz = dt .* f(ustep, p, tstep) .- ztmp + ztmp = z .+ dz + end + end + end + if DiffEqBase.has_stats(integrator) + integrator.stats.nf += 1 + end + + # compute norm of residuals + atmp = calculate_residuals(dz, uprev, ustep, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + + # cache results + nlsolver.ztmp = ztmp + if isdefined(cache, :dz) + cache.dz = dz + end + + ndz +end + +@muladd function compute_step_fixedpoint!( + nlsolver::NLSolver{ + <:Union{NLFunctional, + NLAnderson}, true}, + integrator) + @unpack uprev, t, p, dt, opts = integrator + @unpack z, tmp, ztmp, γ, α, cache = nlsolver + @unpack ustep, tstep, k, atmp, dz = cache + + f = nlsolve_f(integrator) + isdae = f isa DAEFunction + + γdt = γ * dt + if isdae + @.. broadcast=false ustep=uprev + z + @.. broadcast=false ztmp=(tmp + α * z) * inv(γdt) + f(k, ztmp, ustep, p, tstep) + @.. broadcast=false dz=k + @.. broadcast=false ztmp=z + dz + else + mass_matrix = integrator.f.mass_matrix + if nlsolver.method === COEFFICIENT_MULTISTEP + ustep = z + f(k, ustep, p, tstep) + if mass_matrix === I + @.. broadcast=false ztmp=(tmp + k) * (γdt / α) + @.. broadcast=false dz=ztmp - z + else + update_coefficients!(mass_matrix, ustep, p, tstep) + mul!(_vec(ztmp), mass_matrix, _vec(z)) + @.. broadcast=false dz=(tmp + k) * γdt - α * ztmp + @.. broadcast=false ztmp=dz + z + end + else + @.. broadcast=false ustep=tmp + γ * z + f(k, ustep, p, tstep) + if mass_matrix === I + @.. broadcast=false ztmp=dt * k + @.. broadcast=false dz=ztmp - z + else + update_coefficients!(mass_matrix, ustep, p, tstep) + mul!(_vec(ztmp), mass_matrix, _vec(z)) + @.. broadcast=false dz=dt * k - ztmp + @.. broadcast=false ztmp=z + dz + end + end + end + + if DiffEqBase.has_stats(integrator) + integrator.stats.nf += 1 + end + + # compute norm of residuals + calculate_residuals!(atmp, dz, uprev, ustep, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + + ndz +end + +## resize! + +function Base.resize!(nlcache::NLFunctionalCache, i::Int) + resize!(nlcache.ustep, i) + resize!(nlcache.k, i) + resize!(nlcache.atmp, i) + resize!(nlcache.dz, i) + nothing +end + +function Base.resize!(nlcache::NLAndersonCache, nlsolver::NLSolver{<:NLAnderson}, + integrator, i::Int) + resize!(nlcache, nlsolver.alg, i) +end + +function Base.resize!(nlcache::NLAndersonCache, nlalg::NLAnderson, i::Int) + @unpack z₊old, Δz₊s = nlcache + + resize!(nlcache.ustep, i) + resize!(nlcache.k, i) + resize!(nlcache.atmp, i) + resize!(nlcache.dz, i) + resize!(nlcache.dzold, i) + resize!(z₊old, i) + + # update history of Anderson cache + max_history_old = length(Δz₊s) + max_history = min(nlalg.max_history, nlalg.max_iter, i) + + resize!(nlcache.γs, max_history) + resize!(nlcache.Δz₊s, max_history) + + if max_history != max_history_old + nlcache.Q = typeof(nlcache.Q)(undef, i, max_history) + nlcache.R = typeof(nlcache.R)(undef, max_history, max_history) + end + + max_history = length(Δz₊s) + if max_history > max_history_old + for i in (max_history_old + 1):max_history + Δz₊s[i] = zero(z₊old) + end + end + + nothing +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/initialize_dae.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/initialize_dae.jl new file mode 100644 index 0000000000..6564022f54 --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/initialize_dae.jl @@ -0,0 +1,687 @@ +default_nlsolve(alg, isinplace, u, initprob, autodiff = false) = alg + +function default_nlsolve( + ::Nothing, isinplace, u::Nothing, ::NonlinearProblem, autodiff = false) + nothing +end +function default_nlsolve(::Nothing, isinplace, u, ::NonlinearProblem, autodiff = false) + FastShortcutNonlinearPolyalg(; + autodiff = autodiff ? AutoForwardDiff() : AutoFiniteDiff()) +end +function default_nlsolve(::Nothing, isinplace::Val{false}, u::StaticArray, + ::NonlinearProblem, autodiff = false) + SimpleTrustRegion(autodiff = autodiff ? AutoForwardDiff() : AutoFiniteDiff()) +end + +function default_nlsolve( + ::Nothing, isinplace, u::Nothing, ::NonlinearLeastSquaresProblem, autodiff = false) + nothing +end +function default_nlsolve( + ::Nothing, isinplace, u, ::NonlinearLeastSquaresProblem, autodiff = false) + FastShortcutNLLSPolyalg(; autodiff = autodiff ? AutoForwardDiff() : AutoFiniteDiff()) +end +function default_nlsolve(::Nothing, isinplace::Val{false}, u::StaticArray, + ::NonlinearLeastSquaresProblem, autodiff = false) + SimpleGaussNewton(autodiff = autodiff ? AutoForwardDiff() : AutoFiniteDiff()) +end + +## OverrideInit + +function _initialize_dae!(integrator, prob::Union{ODEProblem, DAEProblem}, + alg::OverrideInit, isinplace::Union{Val{true}, Val{false}}) + initializeprob = prob.f.initializeprob + + # If it doesn't have autodiff, assume it comes from symbolic system like ModelingToolkit + # Since then it's the case of not a DAE but has initializeprob + # In which case, it should be differentiable + isAD = if initializeprob.u0 === nothing + AutoForwardDiff + elseif has_autodiff(integrator.alg) + alg_autodiff(integrator.alg) isa AutoForwardDiff + else + true + end + + alg = default_nlsolve(alg.nlsolve, isinplace, initializeprob.u0, initializeprob, isAD) + nlsol = solve(initializeprob, alg) + if isinplace === Val{true}() + integrator.u .= prob.f.initializeprobmap(nlsol) + elseif isinplace === Val{false}() + integrator.u = prob.f.initializeprobmap(nlsol) + else + error("Unreachable reached. Report this error.") + end + + if nlsol.retcode != ReturnCode.Success + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end +end + +## ShampineCollocationInit + +#= +The method: + +du = (u-u0)/h +Solve for `u` + +=# + +function _initialize_dae!(integrator, prob::ODEProblem, alg::ShampineCollocationInit, + isinplace::Val{true}) + @unpack p, t, f = integrator + M = integrator.f.mass_matrix + dtmax = integrator.opts.dtmax + tmp = first(get_tmp_cache(integrator)) + u0 = integrator.u + + dt = if alg.initdt === nothing + integrator.dt != 0 ? min(integrator.dt / 5, dtmax) : + (prob.tspan[end] - prob.tspan[begin]) / 1000 # Haven't implemented norm reduction + else + alg.initdt + end + + algebraic_vars = [all(iszero, x) for x in eachcol(M)] + algebraic_eqs = [all(iszero, x) for x in eachrow(M)] + (iszero(algebraic_vars) || iszero(algebraic_eqs)) && return + update_coefficients!(M, u0, p, t) + f(tmp, u0, p, t) + tmp .= ArrayInterface.restructure(tmp, algebraic_eqs .* _vec(tmp)) + + integrator.opts.internalnorm(tmp, t) <= integrator.opts.abstol && return + + if isdefined(integrator.cache, :nlsolver) && !isnothing(alg.nlsolve) + # backward Euler + nlsolver = integrator.cache.nlsolver + oldγ, oldc, oldmethod, olddt = nlsolver.γ, nlsolver.c, nlsolver.method, + integrator.dt + nlsolver.tmp .= integrator.uprev + nlsolver.γ, nlsolver.c = 1, 1 + nlsolver.method = DIRK + integrator.dt = dt + z = nlsolve!(nlsolver, integrator, integrator.cache) + nlsolver.γ, nlsolver.c, nlsolver.method, integrator.dt = oldγ, oldc, oldmethod, + olddt + failed = nlsolvefail(nlsolver) + @.. broadcast=false integrator.u=integrator.uprev + z + else + + # _u0 should be non-dual since NonlinearSolve does not differentiate the solver + # These non-dual values are thus used to make the caches + #_du = DiffEqBase.value.(du) + _u0 = DiffEqBase.value.(u0) + + # If not doing auto-diff of the solver, save an allocation + if typeof(u0) === typeof(_u0) + tmp = get_tmp_cache(integrator)[1] + else + tmp = copy(_u0) + end + + isAD = alg_autodiff(integrator.alg) isa AutoForwardDiff || + typeof(u0) !== typeof(_u0) + if isAD + chunk = ForwardDiff.pickchunksize(length(tmp)) + _tmp = PreallocationTools.dualcache(tmp, chunk) + else + _tmp = tmp + end + + nlequation! = @closure (out, u, p) -> begin + TP = DiffEqBase.anyeltypedual(p) + if TP <: Dual + T = Base.promote_type(eltype(u), TP) + else + T = eltype(u) + end + update_coefficients!(M, u, p, t) + # f(u,p,t) + M * (u0 - u)/dt + tmp = isAD ? PreallocationTools.get_tmp(_tmp, T) : _tmp + @. tmp = (_u0 - u) / dt + mul!(_vec(out), M, _vec(tmp)) + f(tmp, u, p, t) + out .+= tmp + nothing + end + + jac = if isnothing(f.jac) + f.jac + else + @closure (J, u, p) -> begin + # f(u,p,t) + M * (u0 - u)/dt + # df(u,p,t)/du - M/dt + f.jac(J, u, p, t) + J .-= M .* inv(dt) + nothing + end + end + + nlfunc = NonlinearFunction(nlequation!; + jac_prototype = f.jac_prototype, + jac = jac) + nlprob = NonlinearProblem(nlfunc, integrator.u, p) + nlsolve = default_nlsolve(alg.nlsolve, isinplace, u0, nlprob, isAD) + nlsol = solve(nlprob, nlsolve; abstol = integrator.opts.abstol, + reltol = integrator.opts.reltol) + integrator.u .= nlsol.u + failed = nlsol.retcode != ReturnCode.Success + end + recursivecopy!(integrator.uprev, integrator.u) + if alg_extrapolates(integrator.alg) + recursivecopy!(integrator.uprev2, integrator.uprev) + end + + if failed + @warn "ShampineCollocationInit DAE initialization algorithm failed with dt=$dt. Try to adjust initdt like `ShampineCollocationInit(initdt)`." + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +function _initialize_dae!(integrator, prob::ODEProblem, alg::ShampineCollocationInit, + isinplace::Val{false}) + @unpack p, t, f = integrator + u0 = integrator.u + M = integrator.f.mass_matrix + dtmax = integrator.opts.dtmax + + dt = if alg.initdt === nothing + integrator.dt != 0 ? min(integrator.dt / 5, dtmax) : + (prob.tspan[end] - prob.tspan[begin]) / 1000 # Haven't implemented norm reduction + else + alg.initdt + end + + algebraic_vars = [all(iszero, x) for x in eachcol(M)] + algebraic_eqs = [all(iszero, x) for x in eachrow(M)] + (iszero(algebraic_vars) || iszero(algebraic_eqs)) && return + update_coefficients!(M, u0, p, t) + du = f(u0, p, t) + resid = _vec(du)[algebraic_eqs] + + integrator.opts.internalnorm(resid, t) <= integrator.opts.abstol && return + + if isdefined(integrator.cache, :nlsolver) && !isnothing(alg.nlsolve) + # backward Euler + nlsolver = integrator.cache.nlsolver + oldγ, oldc, oldmethod, olddt = nlsolver.γ, nlsolver.c, nlsolver.method, + integrator.dt + nlsolver.tmp .= integrator.uprev + nlsolver.γ, nlsolver.c = 1, 1 + nlsolver.method = DIRK + integrator.dt = dt + z = nlsolve!(nlsolver, integrator, integrator.cache) + nlsolver.γ, nlsolver.c, nlsolver.method, integrator.dt = oldγ, oldc, oldmethod, + olddt + failed = nlsolvefail(nlsolver) + @.. broadcast=false integrator.u=integrator.uprev + z + else + nlequation_oop = @closure (u, _) -> begin + update_coefficients!(M, u, p, t) + M * (u - u0) / dt - f(u, p, t) + end + + jac = if isnothing(f.jac) + f.jac + else + @closure (u, p) -> begin + return M * (u .- u0) ./ dt .- f.jac(u, p, t) + end + end + + nlfunc = NonlinearFunction(nlequation_oop; + jac_prototype = f.jac_prototype, + jac = jac) + nlprob = NonlinearProblem(nlfunc, u0) + nlsolve = default_nlsolve(alg.nlsolve, isinplace, nlprob, u0) + + nlsol = solve(nlprob, nlsolve; abstol = integrator.opts.abstol, + reltol = integrator.opts.reltol) + integrator.u = nlsol.u + failed = nlsol.retcode != ReturnCode.Success + end + + integrator.uprev = copy(integrator.u) + if alg_extrapolates(integrator.alg) + integrator.uprev2 = copy(integrator.uprev) + end + + if failed + @warn "ShampineCollocationInit DAE initialization algorithm failed with dt=$dt. Try to adjust initdt like `ShampineCollocationInit(initdt)`." + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +function _initialize_dae!(integrator, prob::DAEProblem, + alg::ShampineCollocationInit, isinplace::Val{true}) + @unpack p, t, f = integrator + u0 = integrator.u + + dtmax = integrator.opts.dtmax + resid = get_tmp_cache(integrator)[2] + + dt = t != 0 ? min(t / 1000, dtmax / 10) : dtmax / 10 # Haven't implemented norm reduction + + f(resid, integrator.du, u0, p, t) + integrator.opts.internalnorm(resid, t) <= integrator.opts.abstol && return + + # _du and _u should be non-dual since NonlinearSolve does not differentiate the solver + # These non-dual values are thus used to make the caches + #_du = DiffEqBase.value.(du) + _u0 = DiffEqBase.value.(u0) + + # If not doing auto-diff of the solver, save an allocation + if typeof(u0) === typeof(_u0) + tmp = get_tmp_cache(integrator)[1] + else + tmp = copy(_u0) + end + + isAD = alg_autodiff(integrator.alg) isa AutoForwardDiff || typeof(u0) !== typeof(_u0) + if isAD + chunk = ForwardDiff.pickchunksize(length(tmp)) + _tmp = PreallocationTools.dualcache(tmp, chunk) + else + _tmp = tmp + end + + nlequation! = @closure (out, u, p) -> begin + TP = DiffEqBase.anyeltypedual(p) + if TP <: Dual + T = Base.promote_type(eltype(u), TP) + else + T = eltype(u) + end + tmp = isAD ? PreallocationTools.get_tmp(_tmp, T) : _tmp + #M * (u-u0)/dt - f(u,p,t) + @. tmp = (u - _u0) / dt + f(out, tmp, u, p, t) + nothing + end + + jac = if isnothing(f.jac) + f.jac + else + @closure (J, u, p) -> begin + f.jac(J, u, p, inv(dt), t) + nothing + end + end + + nlfunc = NonlinearFunction(nlequation!; + jac_prototype = f.jac_prototype, + jac = jac) + nlprob = NonlinearProblem(nlfunc, u0, p) + nlsolve = default_nlsolve(alg.nlsolve, isinplace, u0, nlprob, isAD) + nlsol = solve(nlprob, nlsolve; abstol = integrator.opts.abstol, + reltol = integrator.opts.reltol) + + integrator.u = nlsol.u + recursivecopy!(integrator.uprev, integrator.u) + if alg_extrapolates(integrator.alg) + recursivecopy!(integrator.uprev2, integrator.uprev) + end + if nlsol.retcode != ReturnCode.Success + @warn "ShampineCollocationInit DAE initialization algorithm failed with dt=$dt. Try to adjust initdt like `ShampineCollocationInit(initdt)`." + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +function _initialize_dae!(integrator, prob::DAEProblem, + alg::ShampineCollocationInit, isinplace::Val{false}) + @unpack p, t, f = integrator + u0 = integrator.u + dtmax = integrator.opts.dtmax + + dt = t != 0 ? min(t / 1000, dtmax / 10) : dtmax / 10 # Haven't implemented norm reduction + + nlequation_oop = u -> begin + f((u - u0) / dt, u, p, t) + end + + nlequation = (u, _) -> nlequation_oop(u) + + resid = f(integrator.du, u0, p, t) + integrator.opts.internalnorm(resid, t) <= integrator.opts.abstol && return + + jac = if isnothing(f.jac) + f.jac + else + @closure (u, p) -> begin + return f.jac(u, p, inv(dt), t) + end + end + nlfunc = NonlinearFunction(nlequation; jac_prototype = f.jac_prototype, + jac = jac) + nlprob = NonlinearProblem(nlfunc, u0) + nlsolve = default_nlsolve(alg.nlsolve, isinplace, nlprob, u0) + + nlfunc = NonlinearFunction(nlequation; jac_prototype = f.jac_prototype) + nlprob = NonlinearProblem(nlfunc, u0) + nlsol = solve(nlprob, nlsolve; abstol = integrator.opts.abstol, + reltol = integrator.opts.reltol) + + integrator.u = nlsol.u + + integrator.uprev = copy(integrator.u) + if alg_extrapolates(integrator.alg) + integrator.uprev2 = copy(integrator.uprev) + end + if nlsol.retcode != ReturnCode.Success + @warn "ShampineCollocationInit DAE initialization algorithm failed with dt=$dt. Try to adjust initdt like `ShampineCollocationInit(initdt)`." + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +## BrownFullBasic + +#= +The method: + +Keep differential variables constant +Solve for the algebraic variables + +=# + +algebraic_jacobian(::Nothing, algebraic_eqs, algebraic_vars) = nothing +function algebraic_jacobian(jac_prototype::T, algebraic_eqs, + algebraic_vars) where {T <: AbstractMatrix} + jac_prototype[algebraic_eqs, algebraic_vars] +end + +function _initialize_dae!(integrator, prob::ODEProblem, + alg::BrownFullBasicInit, isinplace::Val{true}) + @unpack p, t, f = integrator + u = integrator.u + M = integrator.f.mass_matrix + M isa UniformScaling && return + update_coefficients!(M, u, p, t) + algebraic_vars = [all(iszero, x) for x in eachcol(M)] + algebraic_eqs = [all(iszero, x) for x in eachrow(M)] + (iszero(algebraic_vars) || iszero(algebraic_eqs)) && return + tmp = get_tmp_cache(integrator)[1] + + f(tmp, u, p, t) + + tmp .= ArrayInterface.restructure(tmp, algebraic_eqs .* _vec(tmp)) + + integrator.opts.internalnorm(tmp, t) <= alg.abstol && return + alg_u = @view u[algebraic_vars] + + # These non-dual values are thus used to make the caches + _u = DiffEqBase.value.(u) + + # If auto-diff of the solver, should be non-dual since NonlinearSolve does not differentiate the solver + if typeof(u) !== typeof(_u) + tmp = DiffEqBase.value.(tmp) + end + + isAD = alg_autodiff(integrator.alg) isa AutoForwardDiff || typeof(u) !== typeof(_u) + if isAD + csize = count(algebraic_vars) + if !(p isa SciMLBase.NullParameters) && typeof(_u) !== typeof(u) + if isscimlstructure(p) + csize = max(csize, length(canonicalize(Tunable(), p)[1])) + else + csize = max(csize, length(p)) + end + end + chunk = ForwardDiff.pickchunksize(csize) + _tmp = PreallocationTools.dualcache(tmp, chunk) + _du_tmp = PreallocationTools.dualcache(similar(tmp), chunk) + else + _tmp, _du_tmp = tmp, similar(tmp) + end + + nlequation! = @closure (out, x, p) -> begin + TP = DiffEqBase.anyeltypedual(p) + if TP <: Dual + T = Base.promote_type(eltype(x), TP) + else + T = eltype(x) + end + uu = isAD ? PreallocationTools.get_tmp(_tmp, T) : _tmp + du_tmp = isAD ? PreallocationTools.get_tmp(_du_tmp, T) : _du_tmp + copyto!(uu, _u) + alg_uu = @view uu[algebraic_vars] + alg_uu .= x + f(du_tmp, uu, p, t) + out .= @view du_tmp[algebraic_eqs] + return nothing + end + + J = algebraic_jacobian(f.jac_prototype, algebraic_eqs, algebraic_vars) + nlfunc = NonlinearFunction(nlequation!; jac_prototype = J) + nlprob = NonlinearProblem(nlfunc, alg_u, p) + nlsolve = default_nlsolve(alg.nlsolve, isinplace, u, nlprob, isAD) + + nlsol = solve(nlprob, nlsolve; abstol = alg.abstol, reltol = integrator.opts.reltol) + alg_u .= nlsol + + recursivecopy!(integrator.uprev, integrator.u) + if alg_extrapolates(integrator.alg) + recursivecopy!(integrator.uprev2, integrator.uprev) + end + + if nlsol.retcode != ReturnCode.Success + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +function _initialize_dae!(integrator, prob::ODEProblem, + alg::BrownFullBasicInit, isinplace::Val{false}) + @unpack p, t, f = integrator + + u0 = integrator.u + M = integrator.f.mass_matrix + update_coefficients!(M, u0, p, t) + algebraic_vars = [all(iszero, x) for x in eachcol(M)] + algebraic_eqs = [all(iszero, x) for x in eachrow(M)] + (iszero(algebraic_vars) || iszero(algebraic_eqs)) && return + + du = f(u0, p, t) + resid = _vec(du)[algebraic_eqs] + + integrator.opts.internalnorm(resid, t) <= alg.abstol && return + + isAD = alg_autodiff(integrator.alg) isa AutoForwardDiff + if isAD + chunk = ForwardDiff.pickchunksize(count(algebraic_vars)) + _tmp = PreallocationTools.dualcache(similar(u0), chunk) + else + _tmp = similar(u0) + end + + if u0 isa Number + # This doesn't fix static arrays! + u = [u0] + else + u = u0 + end + + nlequation = @closure (x, _) -> begin + uu = isAD ? PreallocationTools.get_tmp(_tmp, x) : _tmp + copyto!(uu, integrator.u) + alg_u = @view uu[algebraic_vars] + alg_u .= x + du = f(uu, p, t) + @views du[algebraic_eqs] + end + + J = algebraic_jacobian(f.jac_prototype, algebraic_eqs, algebraic_vars) + nlfunc = NonlinearFunction(nlequation; jac_prototype = J) + nlprob = NonlinearProblem(nlfunc, u0[algebraic_vars]) + nlsolve = default_nlsolve(alg.nlsolve, isinplace, u0, nlprob, isAD) + + nlsol = solve(nlprob, nlsolve) + + u[algebraic_vars] .= nlsol.u + + if u0 isa Number + # This doesn't fix static arrays! + integrator.u = first(u) + else + integrator.u = u + end + + integrator.uprev = copy(integrator.u) + if alg_extrapolates(integrator.alg) + integrator.uprev2 = copy(integrator.uprev) + end + + if nlsol.retcode != ReturnCode.Success + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +function _initialize_dae!(integrator, prob::DAEProblem, + alg::BrownFullBasicInit, isinplace::Val{true}) + @unpack p, t, f = integrator + differential_vars = prob.differential_vars + u = integrator.u + du = integrator.du + + # _du and _u should be non-dual since NonlinearSolve does not differentiate the solver + # These non-dual values are thus used to make the caches + _du = DiffEqBase.value.(du) + _u = DiffEqBase.value.(u) + + # If not doing auto-diff of the solver, save an allocation + if typeof(u) === typeof(_u) + tmp = get_tmp_cache(integrator)[1] + du_tmp = get_tmp_cache(integrator)[2] + else + tmp = copy(_u) + du_tmp = copy(_du) + end + + # Can be the same as tmp + normtmp = get_tmp_cache(integrator)[1] + f(normtmp, du, u, p, t) + + if integrator.opts.internalnorm(normtmp, t) <= alg.abstol + return + elseif differential_vars === nothing + error("differential_vars must be set for DAE initialization to occur. Either set consistent initial conditions, differential_vars, or use a different initialization algorithm.") + end + + isAD = alg_autodiff(integrator.alg) isa AutoForwardDiff || typeof(u) !== typeof(_u) + if isAD + chunk = ForwardDiff.pickchunksize(length(tmp)) + _tmp = PreallocationTools.dualcache(tmp, chunk) + _du_tmp = PreallocationTools.dualcache(du_tmp, chunk) + else + _tmp, _du_tmp = tmp, du_tmp + end + + nlequation! = @closure (out, x, p) -> begin + TP = DiffEqBase.anyeltypedual(p) + if TP <: Dual + T = Base.promote_type(eltype(x), TP) + else + T = eltype(x) + end + du_tmp = isAD ? PreallocationTools.get_tmp(_du_tmp, T) : _du_tmp + uu = isAD ? PreallocationTools.get_tmp(_tmp, T) : _tmp + + @. du_tmp = ifelse(differential_vars, x, _du) + @. uu = ifelse(differential_vars, _u, x) + + f(out, du_tmp, uu, p, t) + end + + if alg.nlsolve !== nothing + nlsolve = alg.nlsolve + else + nlsolve = NewtonRaphson(autodiff = alg_autodiff(integrator.alg)) + end + + nlfunc = NonlinearFunction(nlequation!; jac_prototype = f.jac_prototype) + nlprob = NonlinearProblem(nlfunc, ifelse.(differential_vars, du, u), p) + nlsol = solve(nlprob, nlsolve; abstol = alg.abstol, reltol = integrator.opts.reltol) + + @. du = ifelse(differential_vars, nlsol.u, du) + @. u = ifelse(differential_vars, u, nlsol.u) + + recursivecopy!(integrator.uprev, integrator.u) + if alg_extrapolates(integrator.alg) + recursivecopy!(integrator.uprev2, integrator.uprev) + end + + if nlsol.retcode != ReturnCode.Success + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end + +function _initialize_dae!(integrator, prob::DAEProblem, + alg::BrownFullBasicInit, isinplace::Val{false}) + @unpack p, t, f = integrator + differential_vars = prob.differential_vars + + if integrator.opts.internalnorm(f(integrator.du, integrator.u, p, t), t) <= alg.abstol + return + elseif differential_vars === nothing + error("differential_vars must be set for DAE initialization to occur. Either set consistent initial conditions, differential_vars, or use a different initialization algorithm.") + end + + if integrator.u isa Number && integrator.du isa Number + # This doesn't fix static arrays! + u = [integrator.u] + du = [integrator.du] + else + u = integrator.u + du = integrator.du + end + + nlequation = @closure (x, _) -> begin + du = ifelse.(differential_vars, x, du) + u = ifelse.(differential_vars, u, x) + f(du, u, p, t) + end + + nlfunc = NonlinearFunction(nlequation; jac_prototype = f.jac_prototype) + nlprob = NonlinearProblem(nlfunc, ifelse.(differential_vars, du, u)) + + nlsolve = default_nlsolve(alg.nlsolve, isinplace, nlprob, integrator.u) + + nlsol = solve(nlprob, nlsolve) + + du = ifelse.(differential_vars, nlsol.u, du) + u = ifelse.(differential_vars, u, nlsol.u) + + if integrator.u isa Number && integrator.du isa Number + # This doesn't fix static arrays! + integrator.u = first(u) + integrator.du = first(du) + else + integrator.u = u + integrator.du = du + end + + integrator.uprev = copy(integrator.u) + if alg_extrapolates(integrator.alg) + integrator.uprev2 = copy(integrator.uprev) + end + + if nlsol.retcode != ReturnCode.Success + integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, + ReturnCode.InitialFailure) + end + return +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl new file mode 100644 index 0000000000..8757fc362e --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl @@ -0,0 +1,536 @@ +## initialize! + +@muladd function initialize!(nlsolver::NLSolver{<:NLNewton, false}, + integrator::DiffEqBase.DEIntegrator) + @unpack dt = integrator + @unpack cache = nlsolver + + cache.invγdt = inv(dt * nlsolver.γ) + cache.tstep = integrator.t + nlsolver.c * dt + + nothing +end + +@muladd function initialize!(nlsolver::NLSolver{<:NLNewton, true}, + integrator::DiffEqBase.DEIntegrator) + @unpack u, uprev, t, dt, opts = integrator + @unpack cache = nlsolver + @unpack weight = cache + + cache.invγdt = inv(dt * nlsolver.γ) + cache.tstep = integrator.t + nlsolver.c * dt + calculate_residuals!(weight, fill!(weight, one(eltype(u))), uprev, u, + opts.abstol, opts.reltol, opts.internalnorm, t) + + nothing +end + +function initialize!(nlsolver::NLSolver{<:NonlinearSolveAlg, false}, + integrator::DiffEqBase.DEIntegrator) + @unpack uprev, t, p, dt, opts, f = integrator + @unpack z, tmp, ztmp, γ, α, iter, cache, method, alg = nlsolver + cache.invγdt = inv(dt * nlsolver.γ) + cache.tstep = integrator.t + nlsolver.c * dt + + @unpack ustep, tstep, k, invγdt = cache + if DiffEqBase.has_stats(integrator) + integrator.stats.nf += cache.cache.stats.nf + integrator.stats.nnonliniter += cache.cache.stats.nsteps + integrator.stats.njacs += cache.cache.stats.njacs + end + if f isa DAEFunction + nlp_params = (tmp, α, tstep, invγdt, p, dt, uprev, f) + else + nlp_params = (tmp, γ, α, tstep, invγdt, method, p, dt, f) + end + new_prob = remake(cache.prob, p = nlp_params, u0 = z) + cache.cache = init(new_prob, alg.alg) + nothing +end + +function initialize!(nlsolver::NLSolver{<:NonlinearSolveAlg, true}, + integrator::DiffEqBase.DEIntegrator) + @unpack uprev, t, p, dt, opts, f = integrator + @unpack z, tmp, ztmp, γ, α, iter, cache, method, alg = nlsolver + + cache.invγdt = inv(dt * nlsolver.γ) + cache.tstep = integrator.t + nlsolver.c * dt + + @unpack ustep, tstep, k, invγdt = cache + + if DiffEqBase.has_stats(integrator) + integrator.stats.nf += cache.cache.stats.nf + integrator.stats.nnonliniter += cache.cache.stats.nsteps + integrator.stats.njacs += cache.cache.stats.njacs + end + if f isa DAEFunction + nlp_params = (tmp, ztmp, ustep, γ, α, tstep, k, invγdt, p, dt, f) + else + nlp_params = (tmp, ustep, γ, α, tstep, k, invγdt, method, p, dt, f) + end + new_prob = remake(cache.prob, p = nlp_params, u0 = z) + cache.cache = init(new_prob, alg.alg) + nothing +end + +## compute_step! + +@muladd function compute_step!(nlsolver::NLSolver{<:NonlinearSolveAlg, false}, integrator) + @unpack uprev, t, p, dt, opts = integrator + @unpack z, tmp, ztmp, γ, α, cache, method = nlsolver + @unpack tstep, invγdt = cache + + nlcache = nlsolver.cache.cache + step!(nlcache) + nlsolver.ztmp = nlcache.u + + ustep = compute_ustep(tmp, γ, z, method) + atmp = calculate_residuals(nlcache.fu, uprev, ustep, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + #ndz = opts.internalnorm(nlcache.fu, t) + # NDF and BDF are special because the truncation error is directly + # proportional to the total displacement. + if has_special_newton_error(integrator.alg) + ndz *= error_constant(integrator, alg_order(integrator.alg)) + end + return ndz +end + +@muladd function compute_step!(nlsolver::NLSolver{<:NonlinearSolveAlg, true}, integrator) + @unpack uprev, t, p, dt, opts = integrator + @unpack z, tmp, ztmp, γ, α, cache, method = nlsolver + @unpack tstep, invγdt, atmp, ustep = cache + + nlcache = nlsolver.cache.cache + step!(nlcache) + @.. broadcast=false ztmp=nlcache.u + + ustep = compute_ustep!(ustep, tmp, γ, z, method) + calculate_residuals!(atmp, nlcache.fu, uprev, ustep, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + #ndz = opts.internalnorm(nlcache.fu, t) + # NDF and BDF are special because the truncation error is directly + # proportional to the total displacement. + if has_special_newton_error(integrator.alg) + ndz *= error_constant(integrator, alg_order(integrator.alg)) + end + ndz +end + +""" + compute_step!(nlsolver::NLSolver{<:NLNewton}, integrator) + +Compute next iterate of numerically stable modified Newton iteration +that is specialized for implicit methods. + +Please check +https://github.com/SciML/DiffEqDevMaterials/blob/master/newton/output/main.pdf +for more details. + +# References + +M.E.Hoseaa and L.F.Shampine, "Analysis and implementation of TR-BDF2", +Applied Numerical Mathematics, Volume 20, Issues 1–2, February 1996, Pages +21-37. +[doi:10.1016/0168-9274(95)00115-8](https://doi.org/10.1016/0168-9274(95)00115-8). + +Ernst Hairer and Gerhard Wanner, "Solving Ordinary Differential +Equations II, Springer Series in Computational Mathematics. ISBN +978-3-642-05221-7. Section IV.8. +[doi:10.1007/978-3-642-05221-7](https://doi.org/10.1007/978-3-642-05221-7). +""" +@muladd function compute_step!(nlsolver::NLSolver{<:NLNewton, false}, integrator, γW) + @unpack uprev, t, p, dt, opts = integrator + @unpack z, tmp, ztmp, γ, α, cache, method = nlsolver + @unpack tstep, W, invγdt = cache + + f = nlsolve_f(integrator) + + if f isa DAEFunction + _uprev = get_dae_uprev(integrator, uprev) + ztmp, ustep = _compute_rhs(tmp, α, tstep, invγdt, p, _uprev, f, z) + else + ztmp, ustep = _compute_rhs(tmp, γ, α, tstep, invγdt, method, p, dt, f, z) + end + + if DiffEqBase.has_stats(integrator) + integrator.stats.nf += 1 + end + + # update W + if W isa Union{WOperator, StaticWOperator} + update_coefficients!(W, ustep, p, tstep) + elseif W isa AbstractSciMLOperator + error("Non-concrete Jacobian not yet supported by out-of-place Newton solve.") + end + dz = _reshape(W \ _vec(ztmp), axes(ztmp)) + dz = relax(dz, nlsolver, integrator, f) + if DiffEqBase.has_stats(integrator) + integrator.stats.nsolve += 1 + end + + atmp = calculate_residuals(dz, uprev, ustep, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + # NDF and BDF are special because the truncation error is directly + # proportional to the total displacement. + if has_special_newton_error(integrator.alg) + ndz *= error_constant(integrator, alg_order(integrator.alg)) + end + + # compute next iterate + nlsolver.ztmp = z .- dz + + ndz +end + +@muladd function compute_step!(nlsolver::NLSolver{<:NLNewton, true}, integrator, γW) + @unpack uprev, t, p, dt, opts = integrator + @unpack z, tmp, ztmp, γ, α, iter, cache, method = nlsolver + @unpack W_γdt, ustep, tstep, k, atmp, dz, W, new_W, invγdt, linsolve, weight = cache + + f = nlsolve_f(integrator) + isdae = f isa DAEFunction + + if DiffEqBase.has_stats(integrator) + integrator.stats.nf += 1 + end + + if isdae + _uprev = get_dae_uprev(integrator, uprev) + b, ustep = _compute_rhs!(tmp, ztmp, ustep, α, tstep, k, invγdt, p, _uprev, f, z) + else + b, ustep = _compute_rhs!( + tmp, ztmp, ustep, γ, α, tstep, k, invγdt, method, p, dt, f, z) + end + + # update W + if W isa Union{WOperator, StaticWOperator} + update_coefficients!(W, ustep, p, tstep) + elseif W isa AbstractSciMLOperator + # logic for generic AbstractSciMLOperator does not yet support partial state updates, so provide full state + update_coefficients!(W, ustep, p, tstep; dtgamma = γW, transform = true) + end + + if integrator.opts.adaptive + reltol = integrator.opts.reltol + else + reltol = eps(eltype(dz)) + end + + if is_always_new(nlsolver) || (iter == 1 && new_W) + linres = dolinsolve(integrator, linsolve; A = W, b = _vec(b), linu = _vec(dz), + reltol = reltol) + else + linres = dolinsolve( + integrator, linsolve; A = nothing, b = _vec(b), linu = _vec(dz), + reltol = reltol) + end + + cache.linsolve = linres.cache + + if DiffEqBase.has_stats(integrator) + integrator.stats.nsolve += 1 + end + + # relaxed Newton + # Diagonally Implicit Runge-Kutta Methods for Ordinary Differential + # Equations. A Review, by Christopher A. Kennedy and Mark H. Carpenter + # page 54. + γdt = isdae ? α * invγdt : γ * dt + + !(W_γdt ≈ γdt) && (rmul!(dz, 2 / (1 + γdt / W_γdt))) + relax!(dz, nlsolver, integrator, f) + + calculate_residuals!(atmp, dz, uprev, ustep, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + + # NDF and BDF are special because the truncation error is directly + # proportional to the total displacement. + if has_special_newton_error(integrator.alg) + ndz *= error_constant(integrator, alg_order(integrator.alg)) + end + + # compute next iterate + @.. broadcast=false ztmp=z - dz + + ndz +end + +function get_dae_uprev(integrator, uprev) + # not all predictors are uprev, for other forms of predictors, defined in u₀ + if isdefined(integrator.cache, :u₀) + integrator.cache.u₀ + else + uprev + end +end + +function _compute_rhs(tmp, α, tstep, invγdt, p, uprev, f::TF, z) where {TF <: DAEFunction} + ustep = @.. uprev + z + dustep = @. (tmp + α * z) * invγdt + ztmp = f(dustep, ustep, p, tstep) + return ztmp, ustep +end + +function compute_ustep(tmp, γ, z, method) + if method === COEFFICIENT_MULTISTEP + z + else + @. tmp + γ * z + end +end + +function compute_ustep!(ustep, tmp, γ, z, method) + if method === COEFFICIENT_MULTISTEP + ustep = z + else + @.. ustep = tmp + γ * z + end + ustep +end + +function _compute_rhs(tmp, γ, α, tstep, invγdt, method::MethodType, p, dt, f, z) + mass_matrix = f.mass_matrix + ustep = compute_ustep(tmp, γ, z, method) + if method === COEFFICIENT_MULTISTEP + # tmp = outertmp ./ hγ + if mass_matrix === I + ztmp = tmp .+ f(z, p, tstep) .- (α * invγdt) .* z + else + update_coefficients!(mass_matrix, ustep, p, tstep) + ztmp = tmp .+ f(z, p, tstep) .- (mass_matrix * z) .* (α * invγdt) + end + else + if mass_matrix === I + ztmp = (dt * f(ustep, p, tstep) - z) * invγdt + else + update_coefficients!(mass_matrix, ustep, p, tstep) + ztmp = (dt * f(ustep, p, tstep) - mass_matrix * z) * invγdt + end + end + return ztmp, ustep +end + +function _compute_rhs!(tmp, ztmp, ustep, α, tstep, k, + invγdt, p, uprev, f::TF, z) where {TF <: DAEFunction} + @.. broadcast=false ztmp=(tmp + α * z) * invγdt + @.. ustep = uprev + z + f(k, ztmp, ustep, p, tstep) + return _vec(k), ustep +end + +function _compute_rhs!(tmp, ztmp, ustep, γ, α, tstep, k, + invγdt, method::MethodType, p, dt, f, z) + mass_matrix = f.mass_matrix + ustep = compute_ustep!(ustep, tmp, γ, z, method) + if method === COEFFICIENT_MULTISTEP + f(k, z, p, tstep) + if mass_matrix === I + @.. broadcast=false ztmp=tmp + k - (α * invγdt) * z + else + update_coefficients!(mass_matrix, ustep, p, tstep) + mul!(_vec(ztmp), mass_matrix, _vec(z)) + @.. broadcast=false ztmp=tmp + k - (α * invγdt) * ztmp + end + else + f(k, ustep, p, tstep) + if mass_matrix === I + @.. ztmp = (dt * k - z) * invγdt + else + update_coefficients!(mass_matrix, ustep, p, tstep) + mul!(_vec(ztmp), mass_matrix, _vec(z)) + @.. ztmp = (dt * k - ztmp) * invγdt + end + end + return _vec(ztmp), ustep +end + +function _compute_rhs!(tmp::Array, ztmp::Array, ustep::Array, α, tstep, k, + invγdt, p, uprev, f::TF, z) where {TF <: DAEFunction} + @inbounds @simd ivdep for i in eachindex(z) + ztmp[i] = (tmp[i] + α * z[i]) * invγdt + end + @inbounds @simd ivdep for i in eachindex(z) + ustep[i] = uprev[i] + z[i] + end + f(k, ztmp, ustep, p, tstep) + + return _vec(k), ustep +end + +function _compute_rhs!(tmp::Array, ztmp::Array, ustep::Array, γ, α, tstep, k, + invγdt, method::MethodType, p, dt, f, z) + mass_matrix = f.mass_matrix + ustep = compute_ustep!(ustep, tmp, γ, z, method) + if method === COEFFICIENT_MULTISTEP + f(k, z, p, tstep) + if mass_matrix === I + @inbounds @simd ivdep for i in eachindex(z) + ztmp[i] = tmp[i] + k[i] - (α * invγdt) * z[i] + end + else + update_coefficients!(mass_matrix, ustep, p, tstep) + mul!(_vec(ztmp), mass_matrix, _vec(z)) + + @inbounds @simd ivdep for i in eachindex(z) + ztmp[i] = tmp[i] + k[i] - (α * invγdt) * ztmp[i] + end + end + else + f(k, ustep, p, tstep) + if mass_matrix === I + @inbounds @simd ivdep for i in eachindex(z) + ztmp[i] = (dt * k[i] - z[i]) * invγdt + end + else + update_coefficients!(mass_matrix, ustep, p, tstep) + mul!(_vec(ztmp), mass_matrix, _vec(z)) + @inbounds @simd ivdep for i in eachindex(z) + ztmp[i] = (dt * k[i] - ztmp[i]) * invγdt + end + end + end + + return _vec(ztmp), ustep +end + +## relax! +function relax!(dz, nlsolver::AbstractNLSolver, integrator::DEIntegrator, f::TF) where {TF} + relax!(dz, nlsolver, integrator, f, relax(nlsolver)) +end +function relax(dz, nlsolver::AbstractNLSolver, integrator::DEIntegrator, f::TF) where {TF} + relax(dz, nlsolver, integrator, f, relax(nlsolver)) +end +function relax!(dz, nlsolver::AbstractNLSolver, integrator::DEIntegrator, f::TF, + r::Number) where {TF} + if !iszero(r) + rmul!(dz, 1 - r) + end +end + +function relax!(dz, nlsolver::AbstractNLSolver, integrator::DEIntegrator, f::TF, + linesearch) where {TF} + let dz = dz, + integrator = integrator, + nlsolver = nlsolver, + f = f, + linesearch = linesearch + + @unpack uprev, t, p, dt, opts, isdae = integrator + @unpack z, tmp, ztmp, γ, iter, α, cache, method = nlsolver + @unpack ustep, atmp, tstep, k, invγdt, tstep, k, invγdt = cache + function resid(z) + # recompute residual (rhs) + if isdae + _uprev = get_dae_uprev(integrator, uprev) + b, ustep2 = _compute_rhs!( + tmp, ztmp, ustep, α, tstep, k, invγdt, p, _uprev, f::TF, z) + else + b, ustep2 = _compute_rhs!( + tmp, ztmp, ustep, γ, α, tstep, k, invγdt, method, p, dt, f, z) + end + calculate_residuals!(atmp, b, uprev, ustep2, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + return ndz + end + function ϕ(α) + local z = @.. atmp = nlsolver.z - dz * α + res = resid(z) + return res + end + function dϕ(α) + ϵ = sqrt(eps()) + return (ϕ(α + ϵ) - ϕ(α)) / ϵ + end + function ϕdϕ(α) + ϵ = sqrt(eps()) + ϕ_1 = ϕ(α) + ϕ_2 = ϕ(α + ϵ) + ∂ϕ∂α = (ϕ_2 - ϕ_1) / ϵ + return ϕ_1, ∂ϕ∂α + end + α0 = one(eltype(ustep)) + ϕ0, dϕ0 = ϕdϕ(zero(α0)) + α, _ = linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ0, dϕ0) + @.. dz = dz * α + return dz + end +end + +function relax(dz, nlsolver::AbstractNLSolver, integrator::DEIntegrator, f::TF, + r::Number) where {TF} + if !iszero(r) + dz = (1 - r) * dz + end + return dz +end + +function relax(dz, nlsolver::AbstractNLSolver, integrator::DEIntegrator, f::TF, + linesearch) where {TF} + let dz = dz, + integrator = integrator, + nlsolver = nlsolver, + f = f, + linesearch = linesearch + + @unpack uprev, t, p, dt, opts = integrator + @unpack z, tmp, ztmp, γ, iter, cache = nlsolver + function resid(z) + # recompute residual (rhs) + if f isa DAEFunction + _uprev = get_dae_uprev(integrator, uprev) + ztmp, ustep2 = _compute_rhs(tmp, α, tstep, invγdt, p, dt, _uprev, f, z) + else + ztmp, ustep2 = _compute_rhs(tmp, γ, α, tstep, invγdt, method, p, f, z) + end + atmp = calculate_residuals(b, uprev, ustep2, opts.abstol, opts.reltol, + opts.internalnorm, t) + ndz = opts.internalnorm(atmp, t) + return ndz + end + function ϕ(α) + local z = @.. nlsolver.z - dz * α + return resid(z) + end + function dϕ(α) + ϵ = sqrt(eps()) + return (ϕ(α + ϵ) - ϕ(α)) / ϵ + end + function ϕdϕ(α) + ϵ = sqrt(eps()) + ϕ_1 = ϕ(α) + ϕ_2 = ϕ(α + ϵ) + ∂ϕ∂α = (ϕ_2 - ϕ_1) / ϵ + return ϕ_1, ∂ϕ∂α + end + α0 = one(eltype(dz)) + ϕ0, dϕ0 = ϕdϕ(zero(α0)) + α, _ = linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ0, dϕ0) + dz = dz * α + return dz + end +end + +## resize! + +function Base.resize!(nlcache::NLNewtonCache, ::AbstractNLSolver, integrator, i::Int) + resize!(nlcache.ustep, i) + resize!(nlcache.k, i) + resize!(nlcache.atmp, i) + resize!(nlcache.dz, i) + resize!(nlcache.du1, i) + if nlcache.jac_config !== nothing + resize_jac_config!(nlcache.jac_config, i) + end + resize!(nlcache.weight, i) + + # resize J and W (or rather create new ones of appropriate size and type) + resize_J_W!(nlcache, integrator, i) + + nothing +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/nlsolve.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/nlsolve.jl new file mode 100644 index 0000000000..1633531bdc --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/nlsolve.jl @@ -0,0 +1,160 @@ +@inline eps_around_one(θ::T) where {T} = 100sqrt(eps(one(θ))) + +""" + nlsolve!(nlsolver::AbstractNLSolver, integrator) + +Solve + +```math +dt⋅f(innertmp + γ⋅z, p, t + c⋅dt) + outertmp = z +``` + +where `dt` is the step size and `γ` and `c` are constants, and return the solution `z`. +""" +function nlsolve!(nlsolver::NL, integrator::DiffEqBase.DEIntegrator, + cache = nothing, repeat_step = false) where {NL <: AbstractNLSolver} + always_new = is_always_new(nlsolver) + check_div′ = check_div(nlsolver) + @label REDO + if isnewton(nlsolver) + cache === nothing && + throw(ArgumentError("cache is not passed to `nlsolve!` when using NLNewton")) + if nlsolver.method === DIRK + γW = nlsolver.γ * integrator.dt + else + γW = nlsolver.γ * integrator.dt / nlsolver.α + end + always_new || update_W!(nlsolver, integrator, cache, γW, repeat_step) + end + + @unpack maxiters, κ, fast_convergence_cutoff = nlsolver + + initialize!(nlsolver, integrator) + nlsolver.status = check_div′ ? Divergence : Convergence + η = get_new_W!(nlsolver) ? initial_η(nlsolver, integrator) : nlsolver.ηold + + local ndz + for iter in 1:maxiters + if always_new && isnewton(nlsolver) + if ArrayInterface.ismutable(integrator.u) + @.. integrator.u = integrator.uprev + nlsolver.γ * nlsolver.z + else + integrator.u = @.. integrator.uprev + nlsolver.γ * nlsolver.z + end + update_W!(nlsolver, integrator, cache, γW, repeat_step, (true, true)) + end + nlsolver.iter = iter + + # compute next step and calculate norm of residuals + iter > 1 && (ndzprev = ndz) + if isnewton(nlsolver) + # Newton solve requires γW in order to update W + ndz = compute_step!(nlsolver, integrator, γW) + else + ndz = compute_step!(nlsolver, integrator) + end + if !isfinite(ndz) + nlsolver.status = Divergence + nlsolver.nfails += 1 + break + end + + has_prev_θ = hasfield(NL, :prev_θ) + prev_θ = has_prev_θ ? nlsolver.prev_θ : one(ndz) + + # check divergence (not in initial step) + if iter > 1 + θ = prev_θ = has_prev_θ ? max(0.3 * prev_θ, ndz / ndzprev) : ndz / ndzprev + + # When one Newton iteration basically does nothing, it's likely that we + # are at the precision limit of floating point number. Thus, we just call + # it convergence/divergence according to `ndz` directly. + if abs(θ - one(θ)) <= eps_around_one(θ) + if ndz <= one(ndz) + nlsolver.status = Convergence + nlsolver.nfails = 0 + break + elseif check_div′ + nlsolver.status = Divergence + nlsolver.nfails += 1 + break + end + end + + # divergence + if check_div′ && θ > 2 + nlsolver.status = Divergence + nlsolver.nfails += 1 + break + end + else + if !integrator.accept_step + prev_θ = one(prev_θ) + end + θ = prev_θ + end + + if has_prev_θ + nlsolver.prev_θ = prev_θ + end + + apply_step!(nlsolver, integrator) + + # check for convergence + η = DiffEqBase.value(θ / (1 - θ)) + # don't trust θ for non-adaptive on first iter because the solver doesn't provide feedback + # for us to know whether our previous nlsolve converged sufficiently well + check_η_convergance = (iter > 1 || + (isnewton(nlsolver) && isadaptive(integrator.alg))) + if (iter == 1 && ndz < 1e-5) || + (check_η_convergance && η >= zero(η) && η * ndz < κ) + nlsolver.status = Convergence + nlsolver.nfails = 0 + break + end + end + + if isnewton(nlsolver) && nlsolver.status == Divergence && + !isJcurrent(nlsolver, integrator) + nlsolver.status = TryAgain + nlsolver.nfails += 1 + always_new || @goto REDO + end + + nlsolver.ηold = η + postamble!(nlsolver, integrator) +end + +## default implementations + +initialize!(::AbstractNLSolver, integrator::DiffEqBase.DEIntegrator) = nothing + +function initial_η(nlsolver::NLSolver, integrator) + max(nlsolver.ηold, eps(eltype(integrator.opts.reltol)))^(0.8) +end + +function apply_step!(nlsolver::NLSolver{algType, iip}, + integrator::DiffEqBase.DEIntegrator) where {algType, iip} + if iip + @.. broadcast=false nlsolver.z=nlsolver.ztmp + else + nlsolver.z = nlsolver.ztmp + end + + nothing +end + +function postamble!(nlsolver::NLSolver, integrator::DiffEqBase.DEIntegrator) + if DiffEqBase.has_stats(integrator) + integrator.stats.nnonliniter += nlsolver.iter + + if nlsolvefail(nlsolver) + integrator.stats.nnonlinconvfail += 1 + end + end + integrator.force_stepfail = nlsolvefail(nlsolver) + setfirststage!(nlsolver, false) + isnewton(nlsolver) && (nlsolver.cache.firstcall = false) + + nlsolver.z +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/type.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/type.jl new file mode 100644 index 0000000000..4c36666b6e --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/type.jl @@ -0,0 +1,225 @@ +# algorithms +struct NLFunctional{K, C} <: AbstractNLSolverAlgorithm + κ::K + fast_convergence_cutoff::C + max_iter::Int +end + +function NLFunctional(; κ = 1 // 100, max_iter = 10, fast_convergence_cutoff = 1 // 5) + NLFunctional(κ, fast_convergence_cutoff, max_iter) +end + +struct NLAnderson{K, D, C} <: AbstractNLSolverAlgorithm + κ::K + fast_convergence_cutoff::C + max_iter::Int + max_history::Int + aa_start::Int + droptol::D +end + +function NLAnderson(; κ = 1 // 100, max_iter = 10, max_history::Int = 5, aa_start::Int = 1, + droptol = nothing, fast_convergence_cutoff = 1 // 5) + NLAnderson(κ, fast_convergence_cutoff, max_iter, max_history, aa_start, droptol) +end + +struct NLNewton{K, C1, C2, R} <: AbstractNLSolverAlgorithm + κ::K + max_iter::Int + fast_convergence_cutoff::C1 + new_W_dt_cutoff::C2 + always_new::Bool + check_div::Bool + relax::R +end + +function NLNewton(; κ = 1 // 100, max_iter = 10, fast_convergence_cutoff = 1 // 5, + new_W_dt_cutoff = 1 // 5, always_new = false, check_div = true, + relax = 0 // 1) + if relax isa Number && !(0 <= relax < 1) + throw(ArgumentError("The relaxation parameter must be in [0, 1), got `relax = $relax`")) + end + + NLNewton(κ, max_iter, fast_convergence_cutoff, new_W_dt_cutoff, always_new, check_div, + relax) +end + +struct NonlinearSolveAlg{K, C1, C2, A} <: AbstractNLSolverAlgorithm + κ::K + max_iter::Int + fast_convergence_cutoff::C1 + new_W_dt_cutoff::C2 + always_new::Bool + check_div::Bool + alg::A +end + +function NonlinearSolveAlg(alg = NewtonRaphson(autodiff = AutoFiniteDiff()); + κ = 1 // 100, max_iter = 10, fast_convergence_cutoff = 1 // 5, + new_W_dt_cutoff = 1 // 5, always_new = false, check_div = true) + if relax isa Number && !(0 <= relax < 1) + throw(ArgumentError("The relaxation parameter must be in [0, 1), got `relax = $relax`")) + end + + NonlinearSolveAlg( + κ, max_iter, fast_convergence_cutoff, new_W_dt_cutoff, always_new, check_div, + alg) +end + +# solver + +mutable struct NLSolver{algType, iip, uType, gamType, tmpType, tType, + C <: AbstractNLSolverCache, E} <: AbstractNLSolver{algType, iip} + z::uType + tmp::uType # DIRK and multistep methods only use tmp + tmp2::tmpType # for GLM if necessary + ztmp::uType + γ::gamType + c::tType + α::tType + alg::algType + κ::tType + fast_convergence_cutoff::tType + ηold::tType + iter::Int + maxiters::Int + status::NLStatus + cache::C + method::MethodType + nfails::Int + prev_θ::E +end + +# default to DIRK +function NLSolver{iip, tType}(z, tmp, ztmp, γ, c, α, alg, κ, fast_convergence_cutoff, ηold, + iter, maxiters, status, cache, method = DIRK, tmp2 = nothing, + nfails::Int = 0) where {iip, tType} + RT = real(eltype(z)) + NLSolver{typeof(alg), iip, typeof(z), typeof(γ), typeof(tmp2), tType, typeof(cache), RT}( + z, + tmp, + tmp2, + ztmp, + γ, + convert(tType, c), + convert(tType, α), + alg, + convert(tType, κ), + convert(tType, fast_convergence_cutoff), + convert(tType, ηold), + iter, + maxiters, + status, + cache, + method, + nfails, + one(RT)) +end + +# caches + +mutable struct NLNewtonCache{ + uType, + tType, + tType2, + rateType, + J, + W, + ufType, + jcType, + lsType +} <: AbstractNLSolverCache + ustep::uType + tstep::tType + k::rateType + atmp::uType + dz::uType + J::J + W::W + new_W::Bool + firststage::Bool + firstcall::Bool + W_γdt::tType + du1::uType + uf::ufType + jac_config::jcType + linsolve::lsType + weight::uType + invγdt::tType2 + new_W_γdt_cutoff::tType + J_t::tType +end + +mutable struct NLNewtonConstantCache{tType, tType2, J, W, ufType} <: AbstractNLSolverCache + tstep::tType + J::J + W::W + new_W::Bool + firststage::Bool + firstcall::Bool + W_γdt::tType + uf::ufType + invγdt::tType2 + new_W_γdt_cutoff::tType + J_t::tType +end + +mutable struct NLFunctionalCache{uType, tType, rateType} <: AbstractNLSolverCache + ustep::uType + tstep::tType + k::rateType + atmp::uType + dz::uType +end + +mutable struct NLFunctionalConstantCache{tType} <: AbstractNLSolverCache + tstep::tType +end + +mutable struct NLAndersonCache{uType, tType, rateType, uEltypeNoUnits} <: + AbstractNLSolverCache + ustep::uType + tstep::tType + k::rateType + atmp::uType + dz::uType + """residuals `g(zprev) - zprev` of previous fixed-point iteration""" + dzold::uType + """value `g(zprev)` of previous fixed-point iteration""" + z₊old::uType + Δz₊s::Vector{uType} + Q::Matrix{uEltypeNoUnits} + R::Matrix{uEltypeNoUnits} + γs::Vector{uEltypeNoUnits} + history::Int + aa_start::Int + droptol::Union{Nothing, tType} +end + +mutable struct NLAndersonConstantCache{uType, tType, uEltypeNoUnits} <: + AbstractNLSolverCache + tstep::tType + dz::uType + """residuals `g(zprev) - zprev` of previous fixed-point iteration""" + dzold::uType + """value `g(zprev)` of previous fixed-point iteration""" + z₊old::uType + Δz₊s::Vector{uType} + Q::Matrix{uEltypeNoUnits} + R::Matrix{uEltypeNoUnits} + γs::Vector{uEltypeNoUnits} + history::Int + aa_start::Int + droptol::Union{Nothing, tType} +end + +mutable struct NonlinearSolveCache{uType, tType, rateType, tType2, P, C} <: + AbstractNLSolverCache + ustep::uType + tstep::tType + k::rateType + atmp::uType + invγdt::tType2 + prob::P + cache::C +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/utils.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/utils.jl new file mode 100644 index 0000000000..3bed6a453a --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/utils.jl @@ -0,0 +1,578 @@ +get_status(nlsolver::AbstractNLSolver) = nlsolver.status +get_new_W_γdt_cutoff(nlsolver::AbstractNLSolver) = nlsolver.cache.new_W_γdt_cutoff +# handle FIRK +get_new_W_γdt_cutoff(alg::NewtonAlgorithm) = alg.new_W_γdt_cutoff + +nlsolvefail(nlsolver::AbstractNLSolver) = nlsolvefail(get_status(nlsolver)) +nlsolvefail(status::NLStatus) = Int8(status) <= 0 + +relax(nlsolver::AbstractNLSolver) = relax(nlsolver.alg) +relax(alg::NLNewton) = alg.relax +relax(_) = 0 // 1 + +isnewton(nlsolver::AbstractNLSolver) = isnewton(nlsolver.cache) +isnewton(::AbstractNLSolverCache) = false +isnewton(::Union{NLNewtonCache, NLNewtonConstantCache}) = true + +is_always_new(nlsolver::AbstractNLSolver) = is_always_new(nlsolver.alg) +check_div(nlsolver::AbstractNLSolver) = check_div(nlsolver.alg) +check_div(alg) = isdefined(alg, :check_div) ? alg.check_div : true + +isJcurrent(nlsolver::AbstractNLSolver, integrator) = integrator.t == nlsolver.cache.J_t +isfirstcall(nlsolver::AbstractNLSolver) = nlsolver.cache.firstcall +isfirststage(nlsolver::AbstractNLSolver) = nlsolver.cache.firststage +setfirststage!(nlsolver::AbstractNLSolver, val::Bool) = setfirststage!(nlsolver.cache, val) +function setfirststage!(nlcache::Union{NLNewtonCache, NLNewtonConstantCache}, val::Bool) + (nlcache.firststage = val) +end +setfirststage!(::Any, val::Bool) = nothing +markfirststage!(nlsolver::AbstractNLSolver) = setfirststage!(nlsolver, true) + +getnfails(_) = 0 +getnfails(nlsolver::AbstractNLSolver) = nlsolver.nfails + +set_new_W!(nlsolver::AbstractNLSolver, val::Bool)::Bool = set_new_W!(nlsolver.cache, val) +set_new_W!(nlcache::Union{NLNewtonCache, NLNewtonConstantCache}, val::Bool)::Bool = nlcache.new_W = val +get_new_W!(nlsolver::AbstractNLSolver)::Bool = get_new_W!(nlsolver.cache) +get_new_W!(nlcache::Union{NLNewtonCache, NLNewtonConstantCache})::Bool = nlcache.new_W +get_new_W!(::AbstractNLSolverCache)::Bool = true + +get_W(nlsolver::AbstractNLSolver) = get_W(nlsolver.cache) +get_W(nlcache::Union{NLNewtonCache, NLNewtonConstantCache}) = nlcache.W + +set_W_γdt!(nlsolver::AbstractNLSolver, W_γdt) = set_W_γdt!(nlsolver.cache, W_γdt) +function set_W_γdt!(nlcache::Union{NLNewtonCache, NLNewtonConstantCache}, W_γdt) + nlcache.W_γdt = W_γdt + W_γdt +end + +du_cache(nlsolver::AbstractNLSolver) = du_cache(nlsolver.cache) +du_cache(::AbstractNLSolverCache) = nothing +du_cache(nlcache::Union{NLFunctionalCache, NLAndersonCache, NLNewtonCache}) = (nlcache.k,) + +function du_alias_or_new(nlsolver::AbstractNLSolver, rate_prototype) + _du_cache = du_cache(nlsolver) + if _du_cache === nothing + zero(rate_prototype) + else + first(_du_cache) + end +end + +mutable struct DAEResidualJacobianWrapper{isAD, F, pType, duType, uType, alphaType, + gammaType, + tmpType, uprevType, tType} <: Function + f::F + p::pType + tmp_du::duType + tmp_u::uType + α::alphaType + invγdt::gammaType + tmp::tmpType + uprev::uprevType + t::tType + function DAEResidualJacobianWrapper(alg, f, p, α, invγdt, tmp, uprev, t) + isautodiff = alg_autodiff(alg) isa AutoForwardDiff + if isautodiff + tmp_du = PreallocationTools.dualcache(uprev) + tmp_u = PreallocationTools.dualcache(uprev) + else + tmp_du = similar(uprev) + tmp_u = similar(uprev) + end + new{isautodiff, typeof(f), typeof(p), typeof(tmp_du), typeof(tmp_u), typeof(α), + typeof(invγdt), typeof(tmp), typeof(uprev), typeof(t)}(f, p, tmp_du, tmp_u, α, + invγdt, tmp, uprev, t) + end +end + +is_autodiff(m::DAEResidualJacobianWrapper{isAD}) where {isAD} = isAD + +function (m::DAEResidualJacobianWrapper)(out, x) + if is_autodiff(m) + tmp_du = PreallocationTools.get_tmp(m.tmp_du, x) + tmp_u = PreallocationTools.get_tmp(m.tmp_u, x) + else + tmp_du = m.tmp_du + tmp_u = m.tmp_u + end + @. tmp_du = (m.α * x + m.tmp) * m.invγdt + @. tmp_u = x + m.uprev + m.f(out, tmp_du, tmp_u, m.p, m.t) +end + +mutable struct DAEResidualDerivativeWrapper{F, pType, alphaType, gammaType, tmpType, + uprevType, tType} + f::F + p::pType + α::alphaType + invγdt::gammaType + tmp::tmpType + uprev::uprevType + t::tType +end + +function (m::DAEResidualDerivativeWrapper)(x) + tmp_du = (m.α * x + m.tmp) * m.invγdt + tmp_u = x + m.uprev + m.f(tmp_du, tmp_u, m.p, m.t) +end + +DiffEqBase.has_jac(f::DAEResidualJacobianWrapper) = DiffEqBase.has_jac(f.f) +DiffEqBase.has_Wfact(f::DAEResidualJacobianWrapper) = DiffEqBase.has_Wfact(f.f) +DiffEqBase.has_Wfact_t(f::DAEResidualJacobianWrapper) = DiffEqBase.has_Wfact_t(f.f) + +DiffEqBase.has_jac(f::DAEResidualDerivativeWrapper) = DiffEqBase.has_jac(f.f) +DiffEqBase.has_Wfact(f::DAEResidualDerivativeWrapper) = DiffEqBase.has_Wfact(f.f) +DiffEqBase.has_Wfact_t(f::DAEResidualDerivativeWrapper) = DiffEqBase.has_Wfact_t(f.f) + +function build_nlsolver(alg, u, uprev, p, t, dt, f::F, rate_prototype, + ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, + ::Type{tTypeNoUnits}, γ, c, + iip) where {F, uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + build_nlsolver(alg, u, uprev, p, t, dt, f, rate_prototype, uEltypeNoUnits, + uBottomEltypeNoUnits, + tTypeNoUnits, γ, c, 1, iip) +end + +function build_nlsolver(alg, u, uprev, p, t, dt, f::F, rate_prototype, + ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, + ::Type{tTypeNoUnits}, γ, c, α, + iip) where {F, uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + build_nlsolver(alg, alg.nlsolve, u, uprev, p, t, dt, f, rate_prototype, uEltypeNoUnits, + uBottomEltypeNoUnits, tTypeNoUnits, γ, c, α, iip) +end + +function build_nlsolver( + alg, nlalg::Union{NLFunctional, NLAnderson, NLNewton, NonlinearSolveAlg}, + u, uprev, p, t, dt, + f::F, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, + γ, c, α, + ::Val{true}) where {F, uEltypeNoUnits, uBottomEltypeNoUnits, + tTypeNoUnits} + #TODO + #nlalg = DiffEqBase.handle_defaults(alg, nlalg) + # define unitless type + uTolType = real(uBottomEltypeNoUnits) + isdae = alg isa DAEAlgorithm + + # define fields of non-linear solver + z = zero(u) + tmp = zero(u) + ztmp = zero(u) + + # build cache of non-linear solver + ustep = zero(u) + tstep = zero(t) + k = zero(rate_prototype) + atmp = similar(u, uEltypeNoUnits) + dz = zero(u) + + if nlalg isa Union{NLNewton, NonlinearSolveAlg} + nf = nlsolve_f(f, alg) + J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(true)) + + # TODO: check if the solver is iterative + weight = zero(u) + + if islinear(f) || SciMLBase.has_jac(f) + du1 = rate_prototype + uf = nothing + jac_config = nothing + else + du1 = zero(rate_prototype) + if isdae + uf = DAEResidualJacobianWrapper(alg, f, p, α, inv(γ * dt), tmp, uprev, t) + else + uf = build_uf(alg, nf, t, p, Val(true)) + end + jac_config = build_jac_config(alg, nf, uf, du1, uprev, u, ztmp, dz) + end + linprob = LinearProblem(W, _vec(k); u0 = _vec(dz)) + Pl, Pr = wrapprecs( + alg.precs(W, nothing, u, p, t, nothing, nothing, nothing, + nothing)..., + weight, dz) + linsolve = init(linprob, alg.linsolve, alias_A = true, alias_b = true, + Pl = Pl, Pr = Pr, + assumptions = LinearSolve.OperatorAssumptions(true)) + + tType = typeof(t) + invγdt = inv(oneunit(t) * one(uTolType)) + + if nlalg isa NonlinearSolveAlg + α = tTypeNoUnits(α) + dt = tTypeNoUnits(dt) + if isdae + nlf = (ztmp, z, p) -> begin + tmp, ustep, γ, α, tstep, k, invγdt, _p, dt, f = p + _compute_rhs!(tmp, ztmp, ustep, γ, α, tstep, k, invγdt, _p, dt, f, z)[1] + end + nlp_params = (tmp, ustep, γ, α, tstep, k, invγdt, p, dt, f) + else + nlf = (ztmp, z, p) -> begin + tmp, ustep, γ, α, tstep, k, invγdt, method, _p, dt, f = p + _compute_rhs!( + tmp, ztmp, ustep, γ, α, tstep, k, invγdt, method, _p, dt, f, z)[1] + end + nlp_params = (tmp, ustep, γ, α, tstep, k, invγdt, DIRK, p, dt, f) + end + prob = NonlinearProblem(NonlinearFunction(nlf), ztmp, nlp_params) + cache = init(prob, nlalg.alg) + nlcache = NonlinearSolveCache(ustep, tstep, k, atmp, invγdt, prob, cache) + else + nlcache = NLNewtonCache(ustep, tstep, k, atmp, dz, J, W, true, + true, true, tType(dt), du1, uf, jac_config, + linsolve, weight, invγdt, tType(nlalg.new_W_dt_cutoff), t) + end + elseif nlalg isa NLFunctional + nlcache = NLFunctionalCache(ustep, tstep, k, atmp, dz) + elseif nlalg isa NLAnderson + max_history = min(nlalg.max_history, nlalg.max_iter, length(z)) + Δz₊s = [zero(z) for i in 1:max_history] + Q = Matrix{uEltypeNoUnits}(undef, length(z), max_history) + R = Matrix{uEltypeNoUnits}(undef, max_history, max_history) + γs = Vector{uEltypeNoUnits}(undef, max_history) + + dzold = zero(z) + z₊old = zero(z) + + nlcache = NLAndersonCache(ustep, tstep, atmp, k, dz, dzold, z₊old, Δz₊s, Q, R, γs, + 0, + nlalg.aa_start, nlalg.droptol) + end + + # build non-linear solver + ηold = one(t) + + NLSolver{true, tTypeNoUnits}(z, tmp, ztmp, γ, c, α, nlalg, nlalg.κ, + nlalg.fast_convergence_cutoff, ηold, 0, nlalg.max_iter, + Divergence, nlcache) +end + +function build_nlsolver( + alg, nlalg::Union{NLFunctional, NLAnderson, NLNewton, NonlinearSolveAlg}, + u, uprev, p, + t, dt, + f::F, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, + γ, c, α, + ::Val{false}) where {F, uEltypeNoUnits, uBottomEltypeNoUnits, + tTypeNoUnits} + #TODO + #nlalg = DiffEqBase.handle_defaults(alg, nlalg) + # define unitless type + uTolType = real(uBottomEltypeNoUnits) + isdae = alg isa DAEAlgorithm + + # define fields of non-linear solver + z = u + tmp = u + ztmp = u + + # build cache of non-linear solver + tstep = zero(t) + + if nlalg isa Union{NLNewton, NonlinearSolveAlg} + nf = nlsolve_f(f, alg) + if isdae + uf = DAEResidualDerivativeWrapper(f, p, α, inv(γ * dt), tmp, uprev, t) + else + uf = build_uf(alg, nf, t, p, Val(false)) + end + + tType = typeof(t) + invγdt = inv(oneunit(t) * one(uTolType)) + + J, W = build_J_W(alg, u, uprev, p, t, dt, f, uEltypeNoUnits, Val(false)) + if nlalg isa NonlinearSolveAlg + α = tTypeNoUnits(α) + dt = tTypeNoUnits(dt) + if isdae + nlf = (z, p) -> begin + tmp, α, tstep, invγdt, _p, dt, uprev, f = p + _compute_rhs(tmp, α, tstep, invγdt, p, dt, uprev, f, z)[1] + end + nlp_params = (tmp, α, tstep, invγdt, _p, dt, uprev, f) + else + nlf = (z, p) -> begin + tmp, γ, α, tstep, invγdt, method, _p, dt, f = p + _compute_rhs(tmp, γ, α, tstep, invγdt, method, _p, dt, f, z)[1] + end + nlp_params = (tmp, γ, α, tstep, invγdt, DIRK, p, dt, f) + end + prob = NonlinearProblem(NonlinearFunction(nlf), copy(ztmp), nlp_params) + cache = init(prob, nlalg.alg) + nlcache = NonlinearSolveCache( + nothing, tstep, nothing, nothing, invγdt, prob, cache) + else + nlcache = NLNewtonConstantCache(tstep, J, W, true, true, true, tType(dt), uf, + invγdt, tType(nlalg.new_W_dt_cutoff), t) + end + elseif nlalg isa NLFunctional + nlcache = NLFunctionalConstantCache(tstep) + elseif nlalg isa NLAnderson + max_history = min(nlalg.max_history, nlalg.max_iter, length(z)) + Δz₊s = Vector{typeof(z)}(undef, max_history) + Q = Matrix{uEltypeNoUnits}(undef, length(z), max_history) + R = Matrix{uEltypeNoUnits}(undef, max_history, max_history) + γs = Vector{uEltypeNoUnits}(undef, max_history) + + dz = u + dzold = u + z₊old = u + + nlcache = NLAndersonConstantCache(tstep, dz, dzold, z₊old, Δz₊s, Q, R, γs, 0, + nlalg.aa_start, nlalg.droptol) + end + + # build non-linear solver + ηold = one(tTypeNoUnits) + NLSolver{false, tTypeNoUnits}(z, tmp, ztmp, γ, c, α, nlalg, nlalg.κ, + nlalg.fast_convergence_cutoff, ηold, 0, nlalg.max_iter, + Divergence, + nlcache) +end + +## Anderson acceleration + +""" + anderson(z, cache) + +Return the next iterate of the fixed-point iteration `z = g(z)` by performing Anderson +acceleration based on the current iterate `z` and the settings and history in the `cache`. +""" +@muladd function anderson(z, cache) + @unpack dz, Δz₊s, z₊old, dzold, R, Q, γs, history, droptol = cache + + # increase size of history + history += 1 + + # remove oldest history if maximum size is exceeded + max_history = length(Δz₊s) + if history > max_history + # circularly shift differences of z₊ + for i in 1:(max_history - 1) + Δz₊s[i] = Δz₊s[i + 1] + end + + # delete left-most column of QR decomposition + qrdelete!(Q, R, max_history) + + # update size of history + history = max_history + end + + # update history of differences of z₊ + Δz₊s[history] = @.. broadcast=false z-z₊old + + # replace/add difference of residuals as right-most column to QR decomposition + qradd!(Q, R, _vec(dz .- dzold), history) + + # update cached values + cache.dzold = dz + cache.z₊old = z + + # define current Q and R matrices + Qcur, Rcur = view(Q, :, 1:history), UpperTriangular(view(R, 1:history, 1:history)) + + # check condition (TODO: incremental estimation) + if droptol !== nothing + while cond(R) > droptol && history > 1 + qrdelete!(Q, R, history) + history -= 1 + Qcur, Rcur = view(Q, :, 1:history), + UpperTriangular(view(R, 1:history, 1:history)) + end + end + + # save updated history + cache.history = history + + # solve least squares problem + γscur = view(γs, 1:history) + ldiv!(Rcur, mul!(γscur, Qcur', _vec(dz))) + + # update next iterate + for i in 1:history + z = @.. broadcast=false z-γs[i] * Δz₊s[i] + end + + z +end + +""" + anderson!(z, cache) + +Update the current iterate `z` of the fixed-point iteration `z = g(z)` in-place +by performing Anderson acceleration based on the settings and history in the `cache`. +""" +@muladd function anderson!(z, cache) + @unpack dz, z₊old, dzold, Δz₊s, γs, R, Q, history, droptol = cache + + # increase size of history + history += 1 + + # remove oldest history if maximum size is exceeded + max_history = length(Δz₊s) + if history > max_history + # circularly shift differences of z₊ + ptr = Δz₊s[1] + for i in 1:(max_history - 1) + Δz₊s[i] = Δz₊s[i + 1] + end + Δz₊s[max_history] = ptr + + # delete left-most column of QR decomposition + qrdelete!(Q, R, max_history) + + # update size of history + history = max_history + end + + # update history of differences of z₊ + @.. broadcast=false Δz₊s[history]=z - z₊old + + # replace/add difference of residuals as right-most column to QR decomposition + @.. broadcast=false dzold=dz - dzold + qradd!(Q, R, _vec(dzold), history) + + # update cached values + @.. broadcast=false dzold=dz + @.. broadcast=false z₊old=z + + # define current Q and R matrices + Qcur, Rcur = view(Q, :, 1:history), UpperTriangular(view(R, 1:history, 1:history)) + + # check condition (TODO: incremental estimation) + if droptol !== nothing + while cond(R) > droptol && history > 1 + qrdelete!(Q, R, history) + history -= 1 + Qcur, Rcur = view(Q, :, 1:history), + UpperTriangular(view(R, 1:history, 1:history)) + end + end + + # save updated history + cache.history = history + + # solve least squares problem + γscur = view(γs, 1:history) + ldiv!(Rcur, mul!(γscur, Qcur', _vec(dz))) + + # update next iterate + for i in 1:history + @.. broadcast=false z=z - γs[i] * Δz₊s[i] + end + + nothing +end + +## resize + +function resize_nlsolver!(integrator::DiffEqBase.DEIntegrator, i::Int) + isdefined(integrator.cache, :nlsolver) || return + + @unpack nlsolver = integrator.cache + + if nlsolver isa AbstractArray + for idx in eachindex(nlsolver) + resize!(nlsolver[idx], integrator, i) + end + else + resize!(nlsolver, integrator, i) + end + + nlsolver.alg isa NLNewton && resize!(nlsolver.cache.linsolve, i) + + # make it reset everything since the caches changed size! + nlsolver.cache.firstcall = true + + nothing +end + +function Base.resize!(nlsolver::AbstractNLSolver, integrator, i::Int) + resize!(nlsolver.z, i) + resize!(nlsolver.tmp, i) + resize!(nlsolver.ztmp, i) + + resize!(nlsolver.cache, nlsolver, integrator, i) +end + +## default: dispatch only on the cache +function Base.resize!(cache::AbstractNLSolverCache, nlsolver, integrator, i::Int) + Base.resize!(cache, i) +end + +""" + qrdelete!(Q, R, k) + +Delete the left-most column of F = Q[:, 1:k] * R[1:k, 1:k] by updating Q and R. +Only Q[:, 1:(k-1)] and R[1:(k-1), 1:(k-1)] are valid on exit. +""" +function qrdelete!(Q::AbstractMatrix, R::AbstractMatrix, k::Int) + n, m = size(Q) + m == LinearAlgebra.checksquare(R) || throw(DimensionMismatch()) + 1 ≤ k ≤ m || throw(ArgumentError()) + + # apply Givens rotations + for i in 2:k + g = first(givens(R, i - 1, i, i)) + lmul!(g, R) + rmul!(Q, g') + end + + # move columns of R + @inbounds for j in 1:(k - 1) + for i in 1:(k - 1) + R[i, j] = R[i, j + 1] + end + end + + Q, R +end + +""" + qradd!(Q, R, v, k) + +Replace the right-most column of F = Q[:, 1:k] * R[1:k, 1:k] with v by updating Q and R. +This implementation modifies vector v as well. Only Q[:, 1:k] and R[1:k, 1:k] are valid on +exit. +""" +function qradd!(Q::AbstractMatrix, R::AbstractMatrix, v::AbstractVector, k::Int) + n, m = size(Q) + n == length(v) || throw(DimensionMismatch()) + m == LinearAlgebra.checksquare(R) || throw(DimensionMismatch()) + 1 ≤ k ≤ m || throw(ArgumentError()) + + @inbounds for i in 1:(k - 1) + q = view(Q, :, i) + r = dot(q, v) + + R[i, k] = r + axpy!(-r, q, v) + end + + @inbounds begin + d = norm(v) + R[k, k] = d + @.. broadcast=false @view(Q[:, k])=v / d + end + + Q, R +end + +function qradd!(Q::AbstractMatrix, R::AbstractMatrix, v::Number, k::Int) + 1 == LinearAlgebra.checksquare(Q) == LinearAlgebra.checksquare(R) || + throw(DimensionMismatch()) + k == 1 || throw(ArgumentError()) + + R[1, 1] = abs(v) + Q[1, 1] = one(v) + + Q, R +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl b/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl new file mode 100644 index 0000000000..67fb6f03c8 --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl @@ -0,0 +1,16 @@ +using OrdinaryDiffEq +using DiffEqDevTools +using DiffEqBase +using LineSearches +using Test + +import ODEProblemLibrary: prob_ode_orego, prob_ode_rober, prob_ode_lorenz + +for prob in (prob_ode_lorenz, prob_ode_orego) + sol1 = solve(prob, Trapezoid(), reltol = 1e-12, abstol = 1e-12) + @test sol1.retcode == DiffEqBase.ReturnCode.Success + sol2 = solve(prob, Trapezoid(nlsolve = NLNewton(relax = BackTracking())), + reltol = 1e-12, abstol = 1e-12) + @test sol2.retcode == DiffEqBase.ReturnCode.Success + @test sol2.stats.nf <= sol1.stats.nf +end diff --git a/lib/OrdinaryDiffEqNonlinearSolve/test/runtests.jl b/lib/OrdinaryDiffEqNonlinearSolve/test/runtests.jl new file mode 100644 index 0000000000..37192c8dbf --- /dev/null +++ b/lib/OrdinaryDiffEqNonlinearSolve/test/runtests.jl @@ -0,0 +1,3 @@ +using SafeTestsets + +@time @safetestset "Newton Tests" include("interface/newton_tests.jl") From eb36d655775b0f7a2d61dc4282c078ecb8ab31d6 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Thu, 22 Aug 2024 12:55:41 +0530 Subject: [PATCH 02/45] fixes #2373 --- .../src/OrdinaryDiffEqLowStorageRK.jl | 4 +- .../src/alg_utils.jl | 19 +- .../src/algorithms.jl | 43 +-- .../src/low_storage_rk_caches.jl | 235 +++++++++++------ .../src/low_storage_rk_perform_step.jl | 95 ++++--- .../test/ode_low_storage_rk_tests.jl | 33 +++ .../src/OrdinaryDiffEqSSPRK.jl | 2 +- lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl | 18 +- lib/OrdinaryDiffEqSSPRK/src/algorithms.jl | 25 +- lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl | 247 ++++++------------ .../src/ssprk_perform_step.jl | 145 +++++----- .../test/ode_ssprk_tests.jl | 33 --- src/OrdinaryDiffEq.jl | 4 +- 13 files changed, 445 insertions(+), 458 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/OrdinaryDiffEqLowStorageRK.jl b/lib/OrdinaryDiffEqLowStorageRK/src/OrdinaryDiffEqLowStorageRK.jl index 2e7f9fb8e2..867d79097d 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, - KYK2014DGSSPRK_3S2, RK46NL + RDPK3Sp35, RDPK3SpFSAL35, RDPK3Sp49, RDPK3SpFSAL49, RDPK3Sp510, RDPK3SpFSAL510, + RK46NL, SHLDDRK_2N, SHLDDRK52 end diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/alg_utils.jl b/lib/OrdinaryDiffEqLowStorageRK/src/alg_utils.jl index 787fa9ba00..1dc1a9e81a 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/alg_utils.jl @@ -1,4 +1,3 @@ -alg_order(alg::KYK2014DGSSPRK_3S2) = 2 alg_order(alg::ORK256) = 2 alg_order(alg::CarpenterKennedy2N54) = 4 alg_order(alg::NDBLSRK124) = 4 @@ -41,6 +40,8 @@ alg_order(alg::CKLLSRK54_3N_4R) = 4 alg_order(alg::CKLLSRK75_4M_5R) = 5 alg_order(alg::CKLLSRK54_3M_4R) = 4 alg_order(alg::CKLLSRK65_4M_4R) = 5 +alg_order(alg::SHLDDRK_2N) = 4 +alg_order(alg::SHLDDRK52) = 2 isfsal(alg::ORK256) = false isfsal(alg::CarpenterKennedy2N54) = false @@ -83,22 +84,6 @@ uses_uprev(alg::CKLLSRK65_4M_4R, adaptive::Bool) = adaptive uses_uprev(alg::CKLLSRK85_4FM_4R, adaptive::Bool) = adaptive uses_uprev(alg::CKLLSRK75_4M_5R, adaptive::Bool) = adaptive -""" - 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 -``` -""" -ssp_coefficient(alg::KYK2014DGSSPRK_3S2) = 0.8417 - function default_controller(alg::RDPK3Sp35, cache, qoldinit, args...) QT = typeof(qoldinit) return PIDController(map(Base.Fix1(convert, QT), (0.64, -0.31, 0.04))...) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl b/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl index 58b3b3808f..d0f69f7711 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/algorithms.jl @@ -51,6 +51,32 @@ 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 (free 3rd order Hermite interpolant). Fixed timestep only. Designed for @@ -888,19 +914,4 @@ function NDBLSRK134(stage_limiter!, step_limiter! = trivial_limiter!; williamson_condition) end -#SSP Optimized Runge-Kutta Methods - -@doc explicit_rk_docstring("TBD", - "KYK2014DGSSPRK_3S2") -Base.@kwdef struct KYK2014DGSSPRK_3S2{StageLimiter, StepLimiter, Thread} <: - OrdinaryDiffEqAlgorithm - stage_limiter!::StageLimiter = trivial_limiter! - step_limiter!::StepLimiter = trivial_limiter! - thread::Thread = False() -end -# for backwards compatibility -function KYK2014DGSSPRK_3S2(stage_limiter!, step_limiter! = trivial_limiter!) - KYK2014DGSSPRK_3S2(stage_limiter!, - step_limiter!, - False()) -end +#SSP Optimized Runge-Kutta Methods \ No newline at end of file diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl index c2f4ca4623..10decc9cfa 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl @@ -119,83 +119,6 @@ struct RK46NLConstantCache{T, T2} <: OrdinaryDiffEqConstantCache end end -@cache struct KYK2014DGSSPRK_3S2_Cache{uType, rateType, TabType, StageLimiter, StepLimiter, - Thread} <: - LowStorageRKMutableCache - u::uType - uprev::uType - k::rateType - fsalfirst::rateType - tab::TabType - #temporary values for Shu-Osher - u_1::uType - u_2::uType - kk_1::rateType - kk_2::rateType - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -struct KYK2014DGSSPRK_3S2_ConstantCache{T, T2} <: OrdinaryDiffEqConstantCache - #These are not α and β for RK but for Shu-Osher - #see top of page 317 in - #Optimal Strong-Stability-Preserving Runge–Kutta Time Discretizations for - #Discontinuous Garlekin Methods, Kubatko, Yaeger, Ketcheson 2014 - α_10::T - α_20::T - α_21::T - α_30::T - α_32::T - β_10::T - β_21::T - β_30::T - β_32::T - #Shu-Osher is normally stated for autonomous systems, the times - #are calculated by hand for this scheme - c_1::T - c_2::T - - function KYK2014DGSSPRK_3S2_ConstantCache(T, T2) - α_10 = T(1.0) - α_20 = T(0.087353119859156) - α_21 = T(0.912646880140844) - α_30 = T(0.344956917166841) - α_32 = T(0.655043082833159) - β_10 = T(0.528005024856522) - β_21 = T(0.481882138633993) - β_30 = T(0.022826837460491) - β_32 = T(0.345866039233415) - c_1 = β_10 - c_2 = α_21 * β_10 + β_21 # ==0.96376427726 - new{T, T2}(α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2) - end -end - -function alg_cache(alg::KYK2014DGSSPRK_3S2, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - u_1 = zero(u) - u_2 = zero(u) - kk_1 = zero(rate_prototype) - kk_2 = zero(rate_prototype) - k = zero(rate_prototype) - fsalfirst = zero(rate_prototype) - tab = KYK2014DGSSPRK_3S2_ConstantCache(constvalue(uBottomEltypeNoUnits), - constvalue(tTypeNoUnits)) - KYK2014DGSSPRK_3S2_Cache(u, uprev, k, fsalfirst, tab, u_1, u_2, kk_1, kk_2, - alg.stage_limiter!, alg.step_limiter!, alg.thread) -end - -function alg_cache(alg::KYK2014DGSSPRK_3S2, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - KYK2014DGSSPRK_3S2_ConstantCache(constvalue(uBottomEltypeNoUnits), - constvalue(tTypeNoUnits)) -end - function alg_cache(alg::RK46NL, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, dt, reltol, p, calck, @@ -244,6 +167,164 @@ function CarpenterKennedy2N54ConstantCache(T, T2) LowStorageRK2NConstantCache{4, T, T2}(A2end, B1, B2end, c2end) end +@cache mutable struct SHLDDRK_2NCache{uType, rateType, TabType, StageLimiter, StepLimiter, + Thread} <: SSPRKMutableCache + u::uType + uprev::uType + k::rateType + tmp::uType + fsalfirst::rateType + tab::TabType + step::Int + stage_limiter!::StageLimiter + step_limiter!::StepLimiter + thread::Thread +end + +mutable struct SHLDDRK_2NConstantCache{T1, T2} <: SSPRKConstantCache + α21::T1 + α31::T1 + α41::T1 + α51::T1 + β11::T1 + β21::T1 + β31::T1 + β41::T1 + β51::T1 + c21::T2 + c31::T2 + c41::T2 + c51::T2 + + α22::T1 + α32::T1 + α42::T1 + α52::T1 + α62::T1 + β12::T1 + β22::T1 + β32::T1 + β42::T1 + β52::T1 + β62::T1 + c22::T2 + c32::T2 + c42::T2 + c52::T2 + c62::T2 + + step::Int +end + +function SHLDDRK_2NConstantCache(T1, T2) + α21 = T1(-0.6051226) + α31 = T1(-2.0437564) + α41 = T1(-0.7406999) + α51 = T1(-4.4231765) + β11 = T1(0.2687454) + β21 = T1(0.8014706) + β31 = T1(0.5051570) + β41 = T1(0.5623568) + β51 = T1(0.0590065) + c21 = T2(0.2687454) + c31 = T2(0.5852280) + c41 = T2(0.6827066) + c51 = T2(1.1646854) + + α22 = T1(-0.4412737) + α32 = T1(-1.0739820) + α42 = T1(-1.7063570) + α52 = T1(-2.7979293) + α62 = T1(-4.0913537) + β12 = T1(0.1158488) + β22 = T1(0.3728769) + β32 = T1(0.7379536) + β42 = T1(0.5798110) + β52 = T1(1.0312849) + β62 = T1(0.15) + c22 = T2(0.1158485) + c32 = T2(0.3241850) + c42 = T2(0.6193208) + c52 = T2(0.8034472) + c62 = T2(0.9184166) + SHLDDRK_2NConstantCache( + α21, α31, α41, α51, β11, β21, β31, β41, β51, c21, c31, c41, c51, + α22, α32, α42, α52, α62, β12, β22, β32, β42, β52, β62, c22, c32, + c42, c52, c62, 1) +end + +function alg_cache(alg::SHLDDRK_2N, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + SHLDDRK_2NConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) +end + +function alg_cache(alg::SHLDDRK_2N, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + tmp = zero(u) + k = zero(rate_prototype) + fsalfirst = zero(rate_prototype) + tab = SHLDDRK_2NConstantCache(constvalue(uBottomEltypeNoUnits), + constvalue(tTypeNoUnits)) + SHLDDRK_2NCache(u, uprev, k, tmp, fsalfirst, tab, 1, alg.stage_limiter!, + alg.step_limiter!, alg.thread) +end + +struct SHLDDRK52ConstantCache{T1, T2} <: SSPRKConstantCache + α2::T1 + α3::T1 + α4::T1 + α5::T1 + β1::T1 + β2::T1 + β3::T1 + β4::T1 + β5::T1 + c2::T2 + c3::T2 + c4::T2 + c5::T2 +end + +function SHLDDRK52ConstantCache(T1, T2) + α2 = T1(-0.6913065) + α3 = T1(-2.655155) + α4 = T1(-0.8147688) + α5 = T1(-0.6686587) + β1 = T1(0.1) + β2 = T1(0.75) + β3 = T1(0.7) + β4 = T1(0.479313) + β5 = T1(0.310392) + c2 = T2(0.1) + c3 = T2(0.3315201) + c4 = T2(0.4577796) + c5 = T2(0.8666528) + SHLDDRK52ConstantCache(α2, α3, α4, α5, β1, β2, β3, β4, β5, c2, c3, c4, c5) +end + +function alg_cache(alg::SHLDDRK52, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + SHLDDRK52ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) +end + +function alg_cache(alg::SHLDDRK52, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + tmp = zero(u) + k = zero(rate_prototype) + fsalfirst = zero(rate_prototype) + tab = SHLDDRK52ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) + SHLDDRK52Cache(u, uprev, k, tmp, fsalfirst, tab, alg.stage_limiter!, alg.step_limiter!, + alg.thread) +end + function alg_cache(alg::CarpenterKennedy2N54, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, dt, reltol, p, calck, diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index f76fcb4eb6..d3a6e7a37d 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -932,34 +932,46 @@ end integrator.u = u end -function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache) - integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) +function initialize!(integrator, cache::SHLDDRK52ConstantCache) integrator.kshortsize = 2 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) + integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) # Avoid undefined entries if k is an array of arrays integrator.fsallast = zero(integrator.fsalfirst) - return nothing + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = integrator.fsallast end -@muladd function perform_step!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache, +@muladd function perform_step!(integrator, cache::SHLDDRK52ConstantCache, repeat_step = false) @unpack t, dt, uprev, u, f, p = integrator - @unpack α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2 = cache - u_1 = α_10 * uprev + dt * β_10 * integrator.fsalfirst - u_2 = (α_20 * uprev + - α_21 * u_1 + dt * β_21 * f(u_1, p, t + c_1 * dt)) - integrator.u = (α_30 * uprev + dt * β_30 * integrator.fsalfirst + - α_32 * u_2 + dt * β_32 * f(u_2, p, t + c_2 * dt)) + @unpack α2, α3, α4, α5, β1, β2, β3, β4, β5, c2, c3, c4, c5 = cache + + # u1 + tmp = dt * integrator.fsalfirst + u = uprev + β1 * tmp + # u2 + tmp = α2 * tmp + dt * f(u, p, t + c2 * dt) + u = u + β2 * tmp + # u3 + tmp = α3 * tmp + dt * f(u, p, t + c3 * dt) + u = u + β3 * tmp + # u4 + tmp = α4 * tmp + dt * f(u, p, t + c4 * dt) + u = u + β4 * tmp + # u5 = u + tmp = α5 * tmp + dt * f(u, p, t + c5 * dt) + u = u + β5 * tmp + + integrator.fsallast = f(u, p, t + dt) # For interpolation, then FSAL'd integrator.k[1] = integrator.fsalfirst - integrator.k[2] = f(integrator.u, p, t + dt) # For interpolation, then FSAL'd - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) - integrator.fsallast = integrator.k[2] - return nothing + integrator.k[2] = integrator.fsallast + integrator.u = u end -function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_Cache) +function initialize!(integrator, cache::SHLDDRK52Cache) @unpack k, fsalfirst = cache integrator.kshortsize = 2 @@ -967,29 +979,38 @@ function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_Cache) integrator.k[1] = integrator.fsalfirst integrator.k[2] = integrator.fsallast integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - return nothing end -@muladd function perform_step!(integrator, cache::KYK2014DGSSPRK_3S2_Cache, - repeat_step = false) +@muladd function perform_step!(integrator, cache::SHLDDRK52Cache, repeat_step = false) @unpack t, dt, uprev, u, f, p = integrator - @unpack k, fsalfirst, u_1, u_2, kk_1, kk_2, stage_limiter!, step_limiter!, thread = cache - @unpack α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2 = cache.tab - - @.. broadcast=false thread=thread u_1=α_10 * uprev + dt * β_10 * integrator.fsalfirst - stage_limiter!(u_1, integrator, p, t + c_1 * dt) - f(kk_1, u_1, p, t + c_1 * dt) - @.. broadcast=false thread=thread u_2=(α_20 * uprev + - α_21 * u_1 + dt * β_21 * kk_1) - stage_limiter!(u_2, integrator, p, t + c_2 * dt) - f(kk_2, u_2, p, t + c_2 * dt) - @.. broadcast=false thread=thread u=(α_30 * uprev + - dt * β_30 * integrator.fsalfirst + - α_32 * u_2 + dt * β_32 * kk_2) + @unpack k, fsalfirst, tmp, stage_limiter!, step_limiter!, thread = cache + @unpack α2, α3, α4, α5, β1, β2, β3, β4, β5, c2, c3, c4, c5 = cache.tab + + # u1 + @.. thread=thread tmp=dt * fsalfirst + @.. thread=thread u=uprev + β1 * tmp + stage_limiter!(u, integrator, p, t + c2 * dt) + # u2 + f(k, u, p, t + c2 * dt) + @.. thread=thread tmp=α2 * tmp + dt * k + @.. thread=thread u=u + β2 * tmp + stage_limiter!(u, integrator, p, t + c3 * dt) + # u3 + f(k, u, p, t + c3 * dt) + @.. thread=thread tmp=α3 * tmp + dt * k + @.. thread=thread u=u + β3 * tmp + stage_limiter!(u, integrator, p, t + c4 * dt) + # u4 + f(k, u, p, t + c4 * dt) + @.. thread=thread tmp=α4 * tmp + dt * k + @.. thread=thread u=u + β4 * tmp + stage_limiter!(u, integrator, p, t + c5 * dt) + # u5 = u + f(k, u, p, t + c5 * dt) + @.. thread=thread tmp=α5 * tmp + dt * k + @.. thread=thread u=u + β5 * tmp stage_limiter!(u, integrator, p, t + dt) step_limiter!(u, integrator, p, t + dt) - f(integrator.k[2], u, p, t + dt) # For interpolation, then FSAL'd - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) - return nothing -end + + f(k, u, p, t + dt) +end \ No newline at end of file diff --git a/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl b/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl index 109aedb3e8..37fbc6e047 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl @@ -41,6 +41,39 @@ test_problems_nonlinear = [prob_ode_nonlinear, prob_ode_nonlinear_inplace] u0_large = rand(10^6) prob_ode_large = ODEProblem((du, u, p, t) -> du .= u, u0_large, (0.0, 1.0)) +println("SHLDDRK_2N") +dts_SHLDDRK_2N = (1 / 2) .^ (0:3) +alg = SHLDDRK_2N() +for prob in test_problems_only_time + sim = test_convergence(dts_SHLDDRK_2N, prob, alg) + @test sim.𝒪est[:final]≈4 atol=0.46 +end +for prob in test_problems_linear + sim = test_convergence(dts_SHLDDRK_2N, prob, alg) + @test sim.𝒪est[:final]≈4 atol=0.46 +end +for prob in test_problems_nonlinear + sim = test_convergence(dts_SHLDDRK_2N, prob, alg) + @test sim.𝒪est[:final]≈4 atol=1 + # due to unusual saturation towards high dts(0.5 and onwards) and + # saturation towards low dts due to less precision in the provided values of weights , tolerance is kept so high +end + +println("SHLDDRK52") +alg = SHLDDRK52() +for prob in test_problems_only_time + sim = test_convergence(dts, prob, alg) + @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol +end +for prob in test_problems_linear + sim = test_convergence(dts, prob, alg) + @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol +end +for prob in test_problems_nonlinear + sim = test_convergence(dts, prob, alg) + @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol +end + @testset "ORK256" begin alg = ORK256() alg2 = ORK256(; williamson_condition = false) diff --git a/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl b/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl index fde64f8ef7..09d5a56a51 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl @@ -99,6 +99,6 @@ end export SSPRK53_2N2, SSPRK22, SSPRK53, SSPRK63, SSPRK83, SSPRK43, SSPRK432, SSPRKMSVS32, SSPRK54, SSPRK53_2N1, SSPRK104, SSPRK932, SSPRKMSVS43, SSPRK73, SSPRK53_H, - SSPRK33, SHLDDRK_2N, KYKSSPRK42, SHLDDRK52 + SSPRK33, KYKSSPRK42, KYK2014DGSSPRK_3S2 end diff --git a/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl b/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl index f68b6e1b18..debbe67f17 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl @@ -30,8 +30,21 @@ alg_order(alg::SSPRKMSVS43) = 3 alg_order(alg::SSPRK932) = 3 alg_order(alg::SSPRK54) = 4 alg_order(alg::SSPRK104) = 4 -alg_order(alg::SHLDDRK_2N) = 4 -alg_order(alg::SHLDDRK52) = 2 + +""" + 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 +``` +""" ssp_coefficient(alg::SSPRK53_2N1) = 2.18 ssp_coefficient(alg::SSPRK53_2N2) = 2.148 @@ -50,3 +63,4 @@ ssp_coefficient(alg::SSPRK22) = 1 ssp_coefficient(alg::SSPRKMSVS32) = 0.5 ssp_coefficient(alg::SSPRKMSVS43) = 0.33 ssp_coefficient(alg::KYKSSPRK42) = 2.459 +ssp_coefficient(alg::KYK2014DGSSPRK_3S2) = 0.8417 \ No newline at end of file diff --git a/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl b/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl index 68c97a9b10..efe6a1ef75 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/algorithms.jl @@ -320,19 +320,6 @@ function SSPRK33(stage_limiter!, step_limiter! = trivial_limiter!) step_limiter!, False()) 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", "KYKSSPRK42") Base.@kwdef struct KYKSSPRK42{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm @@ -347,15 +334,17 @@ function KYKSSPRK42(stage_limiter!, step_limiter! = trivial_limiter!) False()) end -@doc explicit_rk_docstring("TBD", "SHLDDRK52") -Base.@kwdef struct SHLDDRK52{StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqAlgorithm +@doc explicit_rk_docstring("TBD", + "KYK2014DGSSPRK_3S2") +Base.@kwdef struct KYK2014DGSSPRK_3S2{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!, +function KYK2014DGSSPRK_3S2(stage_limiter!, step_limiter! = trivial_limiter!) + KYK2014DGSSPRK_3S2(stage_limiter!, step_limiter!, False()) -end +end \ No newline at end of file diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl index cdd41f568b..69c56adf10 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl @@ -217,176 +217,6 @@ function alg_cache(alg::SSPRK53, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK53ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SHLDDRK52Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache - u::uType - uprev::uType - k::rateType - tmp::uType - fsalfirst::rateType - tab::TabType - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -struct SHLDDRK52ConstantCache{T1, T2} <: SSPRKConstantCache - α2::T1 - α3::T1 - α4::T1 - α5::T1 - β1::T1 - β2::T1 - β3::T1 - β4::T1 - β5::T1 - c2::T2 - c3::T2 - c4::T2 - c5::T2 -end - -function SHLDDRK52ConstantCache(T1, T2) - α2 = T1(-0.6913065) - α3 = T1(-2.655155) - α4 = T1(-0.8147688) - α5 = T1(-0.6686587) - β1 = T1(0.1) - β2 = T1(0.75) - β3 = T1(0.7) - β4 = T1(0.479313) - β5 = T1(0.310392) - c2 = T2(0.1) - c3 = T2(0.3315201) - c4 = T2(0.4577796) - c5 = T2(0.8666528) - SHLDDRK52ConstantCache(α2, α3, α4, α5, β1, β2, β3, β4, β5, c2, c3, c4, c5) -end - -function alg_cache(alg::SHLDDRK52, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - SHLDDRK52ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) -end - -function alg_cache(alg::SHLDDRK52, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - tmp = zero(u) - k = zero(rate_prototype) - fsalfirst = zero(rate_prototype) - tab = SHLDDRK52ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) - SHLDDRK52Cache(u, uprev, k, tmp, fsalfirst, tab, alg.stage_limiter!, alg.step_limiter!, - alg.thread) -end - -@cache mutable struct SHLDDRK_2NCache{uType, rateType, TabType, StageLimiter, StepLimiter, - Thread} <: SSPRKMutableCache - u::uType - uprev::uType - k::rateType - tmp::uType - fsalfirst::rateType - tab::TabType - step::Int - stage_limiter!::StageLimiter - step_limiter!::StepLimiter - thread::Thread -end - -mutable struct SHLDDRK_2NConstantCache{T1, T2} <: SSPRKConstantCache - α21::T1 - α31::T1 - α41::T1 - α51::T1 - β11::T1 - β21::T1 - β31::T1 - β41::T1 - β51::T1 - c21::T2 - c31::T2 - c41::T2 - c51::T2 - - α22::T1 - α32::T1 - α42::T1 - α52::T1 - α62::T1 - β12::T1 - β22::T1 - β32::T1 - β42::T1 - β52::T1 - β62::T1 - c22::T2 - c32::T2 - c42::T2 - c52::T2 - c62::T2 - - step::Int -end - -function SHLDDRK_2NConstantCache(T1, T2) - α21 = T1(-0.6051226) - α31 = T1(-2.0437564) - α41 = T1(-0.7406999) - α51 = T1(-4.4231765) - β11 = T1(0.2687454) - β21 = T1(0.8014706) - β31 = T1(0.5051570) - β41 = T1(0.5623568) - β51 = T1(0.0590065) - c21 = T2(0.2687454) - c31 = T2(0.5852280) - c41 = T2(0.6827066) - c51 = T2(1.1646854) - - α22 = T1(-0.4412737) - α32 = T1(-1.0739820) - α42 = T1(-1.7063570) - α52 = T1(-2.7979293) - α62 = T1(-4.0913537) - β12 = T1(0.1158488) - β22 = T1(0.3728769) - β32 = T1(0.7379536) - β42 = T1(0.5798110) - β52 = T1(1.0312849) - β62 = T1(0.15) - c22 = T2(0.1158485) - c32 = T2(0.3241850) - c42 = T2(0.6193208) - c52 = T2(0.8034472) - c62 = T2(0.9184166) - SHLDDRK_2NConstantCache( - α21, α31, α41, α51, β11, β21, β31, β41, β51, c21, c31, c41, c51, - α22, α32, α42, α52, α62, β12, β22, β32, β42, β52, β62, c22, c32, - c42, c52, c62, 1) -end - -function alg_cache(alg::SHLDDRK_2N, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - SHLDDRK_2NConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) -end - -function alg_cache(alg::SHLDDRK_2N, u, rate_prototype, ::Type{uEltypeNoUnits}, - ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, - dt, reltol, p, calck, - ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} - tmp = zero(u) - k = zero(rate_prototype) - fsalfirst = zero(rate_prototype) - tab = SHLDDRK_2NConstantCache(constvalue(uBottomEltypeNoUnits), - constvalue(tTypeNoUnits)) - SHLDDRK_2NCache(u, uprev, k, tmp, fsalfirst, tab, 1, alg.stage_limiter!, - alg.step_limiter!, alg.thread) -end - @cache struct SSPRK53_2N1Cache{ uType, rateType, @@ -1255,3 +1085,80 @@ function alg_cache(alg::SSPRK104, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} SSPRK104ConstantCache() end + +@cache struct KYK2014DGSSPRK_3S2_Cache{uType, rateType, TabType, StageLimiter, StepLimiter, + Thread} <: + LowStorageRKMutableCache + u::uType + uprev::uType + k::rateType + fsalfirst::rateType + tab::TabType + #temporary values for Shu-Osher + u_1::uType + u_2::uType + kk_1::rateType + kk_2::rateType + stage_limiter!::StageLimiter + step_limiter!::StepLimiter + thread::Thread +end + +struct KYK2014DGSSPRK_3S2_ConstantCache{T, T2} <: OrdinaryDiffEqConstantCache + #These are not α and β for RK but for Shu-Osher + #see top of page 317 in + #Optimal Strong-Stability-Preserving Runge–Kutta Time Discretizations for + #Discontinuous Garlekin Methods, Kubatko, Yaeger, Ketcheson 2014 + α_10::T + α_20::T + α_21::T + α_30::T + α_32::T + β_10::T + β_21::T + β_30::T + β_32::T + #Shu-Osher is normally stated for autonomous systems, the times + #are calculated by hand for this scheme + c_1::T + c_2::T + + function KYK2014DGSSPRK_3S2_ConstantCache(T, T2) + α_10 = T(1.0) + α_20 = T(0.087353119859156) + α_21 = T(0.912646880140844) + α_30 = T(0.344956917166841) + α_32 = T(0.655043082833159) + β_10 = T(0.528005024856522) + β_21 = T(0.481882138633993) + β_30 = T(0.022826837460491) + β_32 = T(0.345866039233415) + c_1 = β_10 + c_2 = α_21 * β_10 + β_21 # ==0.96376427726 + new{T, T2}(α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2) + end +end + +function alg_cache(alg::KYK2014DGSSPRK_3S2, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + u_1 = zero(u) + u_2 = zero(u) + kk_1 = zero(rate_prototype) + kk_2 = zero(rate_prototype) + k = zero(rate_prototype) + fsalfirst = zero(rate_prototype) + tab = KYK2014DGSSPRK_3S2_ConstantCache(constvalue(uBottomEltypeNoUnits), + constvalue(tTypeNoUnits)) + KYK2014DGSSPRK_3S2_Cache(u, uprev, k, fsalfirst, tab, u_1, u_2, kk_1, kk_2, + alg.stage_limiter!, alg.step_limiter!, alg.thread) +end + +function alg_cache(alg::KYK2014DGSSPRK_3S2, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + KYK2014DGSSPRK_3S2_ConstantCache(constvalue(uBottomEltypeNoUnits), + constvalue(tTypeNoUnits)) +end \ No newline at end of file diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl index cbdf80f982..80dab6cf55 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl @@ -116,89 +116,6 @@ end integrator.u = u end -function initialize!(integrator, cache::SHLDDRK52ConstantCache) - integrator.kshortsize = 2 - integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) - integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - # Avoid undefined entries if k is an array of arrays - integrator.fsallast = zero(integrator.fsalfirst) - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast -end - -@muladd function perform_step!(integrator, cache::SHLDDRK52ConstantCache, - repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack α2, α3, α4, α5, β1, β2, β3, β4, β5, c2, c3, c4, c5 = cache - - # u1 - tmp = dt * integrator.fsalfirst - u = uprev + β1 * tmp - # u2 - tmp = α2 * tmp + dt * f(u, p, t + c2 * dt) - u = u + β2 * tmp - # u3 - tmp = α3 * tmp + dt * f(u, p, t + c3 * dt) - u = u + β3 * tmp - # u4 - tmp = α4 * tmp + dt * f(u, p, t + c4 * dt) - u = u + β4 * tmp - # u5 = u - tmp = α5 * tmp + dt * f(u, p, t + c5 * dt) - u = u + β5 * tmp - - integrator.fsallast = f(u, p, t + dt) # For interpolation, then FSAL'd - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast - integrator.u = u -end - -function initialize!(integrator, cache::SHLDDRK52Cache) - @unpack k, fsalfirst = cache - - integrator.kshortsize = 2 - resize!(integrator.k, integrator.kshortsize) - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast - integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation -end - -@muladd function perform_step!(integrator, cache::SHLDDRK52Cache, repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack k, fsalfirst, tmp, stage_limiter!, step_limiter!, thread = cache - @unpack α2, α3, α4, α5, β1, β2, β3, β4, β5, c2, c3, c4, c5 = cache.tab - - # u1 - @.. thread=thread tmp=dt * fsalfirst - @.. thread=thread u=uprev + β1 * tmp - stage_limiter!(u, integrator, p, t + c2 * dt) - # u2 - f(k, u, p, t + c2 * dt) - @.. thread=thread tmp=α2 * tmp + dt * k - @.. thread=thread u=u + β2 * tmp - stage_limiter!(u, integrator, p, t + c3 * dt) - # u3 - f(k, u, p, t + c3 * dt) - @.. thread=thread tmp=α3 * tmp + dt * k - @.. thread=thread u=u + β3 * tmp - stage_limiter!(u, integrator, p, t + c4 * dt) - # u4 - f(k, u, p, t + c4 * dt) - @.. thread=thread tmp=α4 * tmp + dt * k - @.. thread=thread u=u + β4 * tmp - stage_limiter!(u, integrator, p, t + c5 * dt) - # u5 = u - f(k, u, p, t + c5 * dt) - @.. thread=thread tmp=α5 * tmp + dt * k - @.. thread=thread u=u + β5 * tmp - stage_limiter!(u, integrator, p, t + dt) - step_limiter!(u, integrator, p, t + dt) - - f(k, u, p, t + dt) -end - function initialize!(integrator, cache::SHLDDRK_2NConstantCache) integrator.kshortsize = 2 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) @@ -1688,3 +1605,65 @@ end step_limiter!(u, integrator, p, t + dt) OrdinaryDiffEqCore.increment_nf!(integrator.stats, 10) end + +function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache) + integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + integrator.kshortsize = 2 + integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) + + # Avoid undefined entries if k is an array of arrays + integrator.fsallast = zero(integrator.fsalfirst) + return nothing +end + +@muladd function perform_step!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache, + repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator + @unpack α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2 = cache + u_1 = α_10 * uprev + dt * β_10 * integrator.fsalfirst + u_2 = (α_20 * uprev + + α_21 * u_1 + dt * β_21 * f(u_1, p, t + c_1 * dt)) + integrator.u = (α_30 * uprev + dt * β_30 * integrator.fsalfirst + + α_32 * u_2 + dt * β_32 * f(u_2, p, t + c_2 * dt)) + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = f(integrator.u, p, t + dt) # For interpolation, then FSAL'd + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) + integrator.fsallast = integrator.k[2] + return nothing +end + +function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_Cache) + @unpack k, fsalfirst = cache + + integrator.kshortsize = 2 + resize!(integrator.k, integrator.kshortsize) + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = integrator.fsallast + integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + return nothing +end + +@muladd function perform_step!(integrator, cache::KYK2014DGSSPRK_3S2_Cache, + repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator + @unpack k, fsalfirst, u_1, u_2, kk_1, kk_2, stage_limiter!, step_limiter!, thread = cache + @unpack α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2 = cache.tab + + @.. broadcast=false thread=thread u_1=α_10 * uprev + dt * β_10 * integrator.fsalfirst + stage_limiter!(u_1, integrator, p, t + c_1 * dt) + f(kk_1, u_1, p, t + c_1 * dt) + @.. broadcast=false thread=thread u_2=(α_20 * uprev + + α_21 * u_1 + dt * β_21 * kk_1) + stage_limiter!(u_2, integrator, p, t + c_2 * dt) + f(kk_2, u_2, p, t + c_2 * dt) + @.. broadcast=false thread=thread u=(α_30 * uprev + + dt * β_30 * integrator.fsalfirst + + α_32 * u_2 + dt * β_32 * kk_2) + stage_limiter!(u, integrator, p, t + dt) + step_limiter!(u, integrator, p, t + dt) + 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 diff --git a/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl b/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl index 31facc3d6a..2f9fa6614e 100644 --- a/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl +++ b/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl @@ -102,39 +102,6 @@ sol = solve(test_problem_ssp_long, alg, dt = OrdinaryDiffEqSSPRK.ssp_coefficient dense = false) @test all(sol.u .>= 0) -println("SHLDDRK52") -alg = SHLDDRK52() -for prob in test_problems_only_time - sim = test_convergence(dts, prob, alg) - @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol -end -for prob in test_problems_linear - sim = test_convergence(dts, prob, alg) - @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol -end -for prob in test_problems_nonlinear - sim = test_convergence(dts, prob, alg) - @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol -end - -println("SHLDDRK_2N") -dts_SHLDDRK_2N = (1 / 2) .^ (0:3) -alg = SHLDDRK_2N() -for prob in test_problems_only_time - sim = test_convergence(dts_SHLDDRK_2N, prob, alg) - @test sim.𝒪est[:final]≈4 atol=0.46 -end -for prob in test_problems_linear - sim = test_convergence(dts_SHLDDRK_2N, prob, alg) - @test sim.𝒪est[:final]≈4 atol=0.46 -end -for prob in test_problems_nonlinear - sim = test_convergence(dts_SHLDDRK_2N, prob, alg) - @test sim.𝒪est[:final]≈4 atol=1 - # due to unusual saturation towards high dts(0.5 and onwards) and - # saturation towards low dts due to less precision in the provided values of weights , tolerance is kept so high -end - println("SSPRK33") alg = SSPRK33() for prob in test_problems_only_time diff --git a/src/OrdinaryDiffEq.jl b/src/OrdinaryDiffEq.jl index dfafe9b9d3..9f6c1f1cc0 100644 --- a/src/OrdinaryDiffEq.jl +++ b/src/OrdinaryDiffEq.jl @@ -101,12 +101,12 @@ export ORK256, CarpenterKennedy2N54, SHLDDRK64, HSLDDRK64, DGLDDRK73_C, DGLDDRK8 ParsaniKetchesonDeconinck3S94, ParsaniKetchesonDeconinck3S184, ParsaniKetchesonDeconinck3S105, ParsaniKetchesonDeconinck3S205, RDPK3Sp35, RDPK3SpFSAL35, RDPK3Sp49, RDPK3SpFSAL49, RDPK3Sp510, RDPK3SpFSAL510, - KYK2014DGSSPRK_3S2, RK46NL + RK46NL, SHLDDRK_2N, SHLDDRK52 using OrdinaryDiffEqSSPRK export SSPRK53_2N2, SSPRK22, SSPRK53, SSPRK63, SSPRK83, SSPRK43, SSPRK432, SSPRKMSVS32, SSPRK54, SSPRK53_2N1, SSPRK104, SSPRK932, SSPRKMSVS43, SSPRK73, SSPRK53_H, - SSPRK33, SHLDDRK_2N, KYKSSPRK42, SHLDDRK52 + SSPRK33, KYKSSPRK42, KYK2014DGSSPRK_3S2 using OrdinaryDiffEqFeagin export Feagin10, Feagin12, Feagin14 From 2ceb19b770ca6ea9944e5c245671b576ec3ba4a4 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Thu, 22 Aug 2024 12:55:41 +0530 Subject: [PATCH 03/45] fixes #2373 From 954dcdfdbcd4db840b217ffc30f328f1a5cf4b27 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Thu, 22 Aug 2024 22:45:06 +0530 Subject: [PATCH 04/45] Fixes --- lib/OrdinaryDiffEqNonlinearSolve/Project.toml | 10 --------- .../src/OrdinaryDiffEqNonlinearSolve.jl | 22 ------------------- .../src/functional.jl | 8 ------- .../src/newton.jl | 8 ------- .../test/newton_tests.jl | 4 ---- 5 files changed, 52 deletions(-) diff --git a/lib/OrdinaryDiffEqNonlinearSolve/Project.toml b/lib/OrdinaryDiffEqNonlinearSolve/Project.toml index 6599ebebdc..d0a8add51a 100644 --- a/lib/OrdinaryDiffEqNonlinearSolve/Project.toml +++ b/lib/OrdinaryDiffEqNonlinearSolve/Project.toml @@ -1,15 +1,6 @@ name = "OrdinaryDiffEqNonlinearSolve" uuid = "127b3ac7-2247-4354-8eb6-78cf4e7c58e8" authors = ["Chris Rackauckas ", "Yingbo Ma "] -<<<<<<< HEAD -version = "1.0.0" - -[deps] -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -OrdinaryDiffEqDifferentiation = "4302a76b-040a-498a-8c04-15b101fed76b" - -[compat] -======= version = "1.1.0" [deps] @@ -57,7 +48,6 @@ SciMLStructures = "1.4.2" SimpleNonlinearSolve = "1.12.0" StaticArrays = "1.9.7" Test = "<0.0.1, 1" ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 julia = "1.10" [extras] diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl index 220daedee0..c00ac00848 100644 --- a/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/OrdinaryDiffEqNonlinearSolve.jl @@ -4,13 +4,9 @@ import ADTypes: AutoFiniteDiff, AutoForwardDiff import SciMLBase import SciMLBase: init, solve, solve! -<<<<<<< HEAD -using SciMLBase: DAEFunction, DEIntegrator, NonlinearFunction, NonlinearProblem, NonlinearLeastSquaresProblem, LinearProblem, ODEProblem, DAEProblem, update_coefficients!, get_tmp_cache, AbstractSciMLOperator, ReturnCode -======= using SciMLBase: DAEFunction, DEIntegrator, NonlinearFunction, NonlinearProblem, NonlinearLeastSquaresProblem, LinearProblem, ODEProblem, DAEProblem, update_coefficients!, get_tmp_cache, AbstractSciMLOperator, ReturnCode ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 import DiffEqBase import PreallocationTools using SimpleNonlinearSolve: SimpleTrustRegion, SimpleGaussNewton @@ -26,23 +22,6 @@ using ForwardDiff: Dual using LinearSolve: I, rmul!, norm, mul!, ldiv! using RecursiveArrayTools: recursivecopy! import SciMLStructures: canonicalize, Tunable, isscimlstructure -<<<<<<< HEAD - -import SciMLOperators: islinear -import OrdinaryDiffEq: nlsolve_f, set_new_W!, set_W_γdt! - -using OrdinaryDiffEq: OrdinaryDiffEqDifferentiation, -AbstractNLSolverAlgorithm, AbstractNLSolverCache, AbstractNLSolver, NewtonAlgorithm, @unpack, -OverrideInit, ShampineCollocationInit, BrownFullBasicInit, _vec, _unwrap_val, DAEAlgorithm, -_reshape, calculate_residuals, calculate_residuals!, has_special_newton_error, isadaptive, -TryAgain, DIRK, COEFFICIENT_MULTISTEP, NORDSIECK_MULTISTEP, GLM, FastConvergence, Convergence, -SlowConvergence, VerySlowConvergence, Divergence, NLStatus, MethodType, alg_order, error_constant, -alg_extrapolates, resize_J_W!, has_autodiff - -import OrdinaryDiffEq: _initialize_dae!, isnewton, get_W, isfirstcall, isfirststage, isJcurrent, get_new_W_γdt_cutoff, resize_nlsolver!, apply_step!, postamble!, build_nlsolver - -import OrdinaryDiffEq.OrdinaryDiffEqDifferentiation: update_W!, is_always_new, build_uf, build_J_W, WOperator, StaticWOperator, wrapprecs, build_jac_config, dolinsolve, alg_autodiff, resize_jac_config! -======= import OrdinaryDiffEqCore import SciMLOperators: islinear @@ -69,7 +48,6 @@ import OrdinaryDiffEqDifferentiation: update_W!, is_always_new, build_uf, build_ WOperator, StaticWOperator, wrapprecs, build_jac_config, dolinsolve, alg_autodiff, resize_jac_config! ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 import StaticArrays: SArray, MVector, SVector, @SVector, StaticArray, MMatrix, SA, StaticMatrix diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl index 947013fe08..377e9c12a5 100644 --- a/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/functional.jl @@ -135,11 +135,7 @@ end end end if DiffEqBase.has_stats(integrator) -<<<<<<< HEAD - integrator.stats.nf += 1 -======= OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 end # compute norm of residuals @@ -205,11 +201,7 @@ end end if DiffEqBase.has_stats(integrator) -<<<<<<< HEAD - integrator.stats.nf += 1 -======= OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 end # compute norm of residuals diff --git a/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl b/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl index 7c711fb2b1..c1c8f67db7 100644 --- a/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl +++ b/lib/OrdinaryDiffEqNonlinearSolve/src/newton.jl @@ -156,11 +156,7 @@ Equations II, Springer Series in Computational Mathematics. ISBN end if DiffEqBase.has_stats(integrator) -<<<<<<< HEAD - integrator.stats.nf += 1 -======= OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 end # update W @@ -199,11 +195,7 @@ end isdae = f isa DAEFunction if DiffEqBase.has_stats(integrator) -<<<<<<< HEAD - integrator.stats.nf += 1 -======= OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 end if isdae diff --git a/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl b/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl index 6565fc2049..67fb6f03c8 100644 --- a/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl +++ b/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl @@ -1,8 +1,4 @@ -<<<<<<< HEAD using OrdinaryDiffEq -======= -using OrdinaryDiffEqCore ->>>>>>> 1b257031152b893ed04eb8a96ba99eb2f917b708 using DiffEqDevTools using DiffEqBase using LineSearches From 3bc0e40af5f885b45d445d965a418cd59ff75080 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Thu, 22 Aug 2024 23:45:51 +0530 Subject: [PATCH 05/45] Fixed abstract types --- lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl | 2 +- lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl index 10decc9cfa..859f686f09 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl @@ -168,7 +168,7 @@ function CarpenterKennedy2N54ConstantCache(T, T2) end @cache mutable struct SHLDDRK_2NCache{uType, rateType, TabType, StageLimiter, StepLimiter, - Thread} <: SSPRKMutableCache + Thread} <: LowStorageRKMutableCache u::uType uprev::uType k::rateType diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl index 69c56adf10..443166b9fd 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl @@ -1088,7 +1088,7 @@ end @cache struct KYK2014DGSSPRK_3S2_Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: - LowStorageRKMutableCache + SSPRKMutableCache u::uType uprev::uType k::rateType From 4e79ff859e54a87739e707702cbfcbf9a1740ed8 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Thu, 22 Aug 2024 23:54:56 +0530 Subject: [PATCH 06/45] fixes --- .../src/low_storage_rk_perform_step.jl | 150 ++++++++++++++++++ .../src/ssprk_perform_step.jl | 150 ------------------ 2 files changed, 150 insertions(+), 150 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index d3a6e7a37d..1307a3f168 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -1013,4 +1013,154 @@ end step_limiter!(u, integrator, p, t + dt) f(k, u, p, t + dt) +end + +function initialize!(integrator, cache::SHLDDRK_2NConstantCache) + integrator.kshortsize = 2 + integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) + integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + + # Avoid undefined entries if k is an array of arrays + integrator.fsallast = zero(integrator.fsalfirst) + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = integrator.fsallast +end + +@muladd function perform_step!(integrator, cache::SHLDDRK_2NConstantCache, + repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator + @unpack α21, α31, α41, α51, β11, β21, β31, β41, β51, c21, c31, c41, c51, α22, α32, α42, α52, α62, β12, β22, β32, β42, β52, β62, c22, c32, c42, c52, c62 = cache + + if integrator.u_modified + cache.step = 1 + end + # cnt = cache.step + + if cache.step % 2 == 1 + cache.step += 1 + # u1 + tmp = dt * integrator.fsalfirst + u = uprev + β11 * tmp + # u2 + tmp = α21 * tmp + dt * f(u, p, t + c21 * dt) + u = u + β21 * tmp + # u3 + tmp = α31 * tmp + dt * f(u, p, t + c31 * dt) + u = u + β31 * tmp + # u4 + tmp = α41 * tmp + dt * f(u, p, t + c41 * dt) + u = u + β41 * tmp + # u5 = u + tmp = α51 * tmp + dt * f(u, p, t + c51 * dt) + u = u + β51 * tmp + + else + cache.step += 1 + # u1 + tmp = dt * integrator.fsalfirst + u = uprev + β12 * tmp + # u2 + tmp = α22 * tmp + dt * f(u, p, t + c22 * dt) + u = u + β22 * tmp + # u3 + tmp = α32 * tmp + dt * f(u, p, t + c32 * dt) + u = u + β32 * tmp + # u4 + tmp = α42 * tmp + dt * f(u, p, t + c42 * dt) + u = u + β42 * tmp + # u5 = u + tmp = α52 * tmp + dt * f(u, p, t + c52 * dt) + u = u + β52 * tmp + tmp = α62 * tmp + dt * f(u, p, t + c62 * dt) + u = u + β62 * tmp + end + + integrator.fsallast = f(u, p, t + dt) # For interpolation, then FSAL'd + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = integrator.fsallast + integrator.u = u +end + +function initialize!(integrator, cache::SHLDDRK_2NCache) + @unpack k, fsalfirst = cache + + integrator.kshortsize = 2 + resize!(integrator.k, integrator.kshortsize) + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = integrator.fsallast + integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation +end + +@muladd function perform_step!(integrator, cache::SHLDDRK_2NCache, repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator + @unpack k, fsalfirst, tmp, stage_limiter!, step_limiter!, thread = cache + @unpack α21, α31, α41, α51, β11, β21, β31, β41, β51, c21, c31, c41, c51, α22, α32, α42, α52, α62, β12, β22, β32, β42, β52, β62, c22, c32, c42, c52, c62 = cache.tab + + if integrator.u_modified + cache.step = 1 + end + + if cache.step % 2 == 1 + # u1 + @.. thread=thread tmp=dt * fsalfirst + @.. thread=thread u=uprev + β11 * tmp + stage_limiter!(u, integrator, p, t + c21 * dt) + # u2 + f(k, u, p, t + c21 * dt) + @.. thread=thread tmp=α21 * tmp + dt * k + @.. thread=thread u=u + β21 * tmp + stage_limiter!(u, integrator, p, t + c31 * dt) + # u3 + f(k, u, p, t + c31 * dt) + @.. thread=thread tmp=α31 * tmp + dt * k + @.. thread=thread u=u + β31 * tmp + stage_limiter!(u, integrator, p, t + c41 * dt) + # u4 + f(k, u, p, t + c41 * dt) + @.. thread=thread tmp=α41 * tmp + dt * k + @.. thread=thread u=u + β41 * tmp + stage_limiter!(u, integrator, p, t + c51 * dt) + # u5 = u + f(k, u, p, t + c51 * dt) + @.. thread=thread tmp=α51 * tmp + dt * k + @.. thread=thread u=u + β51 * tmp + stage_limiter!(u, integrator, p, t + dt) + step_limiter!(u, integrator, p, t + dt) + + f(k, u, p, t + dt) + else + # u1 + @.. thread=thread tmp=dt * fsalfirst + @.. thread=thread u=uprev + β12 * tmp + stage_limiter!(u, integrator, p, t + c22 * dt) + # u2 + f(k, u, p, t + c22 * dt) + @.. thread=thread tmp=α22 * tmp + dt * k + @.. thread=thread u=u + β22 * tmp + stage_limiter!(u, integrator, p, t + c32 * dt) + # u3 + f(k, u, p, t + c32 * dt) + @.. thread=thread tmp=α32 * tmp + dt * k + @.. thread=thread u=u + β32 * tmp + stage_limiter!(u, integrator, p, t + c42 * dt) + # u4 + f(k, u, p, t + c42 * dt) + @.. thread=thread tmp=α42 * tmp + dt * k + @.. thread=thread u=u + β42 * tmp + stage_limiter!(u, integrator, p, t + c52 * dt) + # u5 = u + f(k, u, p, t + c52 * dt) + @.. thread=thread tmp=α52 * tmp + dt * k + @.. thread=thread u=u + β52 * tmp + stage_limiter!(u, integrator, p, t + c62 * dt) + # u6 = u + f(k, u, p, t + c62 * dt) + @.. thread=thread tmp=α62 * tmp + dt * k + @.. thread=thread u=u + β62 * tmp + stage_limiter!(u, integrator, p, t + dt) + step_limiter!(u, integrator, p, t + dt) + + f(k, u, p, t + dt) + end end \ No newline at end of file diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl index 80dab6cf55..2d5ed7ca7d 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/ssprk_perform_step.jl @@ -116,156 +116,6 @@ end integrator.u = u end -function initialize!(integrator, cache::SHLDDRK_2NConstantCache) - integrator.kshortsize = 2 - integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) - integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - - # Avoid undefined entries if k is an array of arrays - integrator.fsallast = zero(integrator.fsalfirst) - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast -end - -@muladd function perform_step!(integrator, cache::SHLDDRK_2NConstantCache, - repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack α21, α31, α41, α51, β11, β21, β31, β41, β51, c21, c31, c41, c51, α22, α32, α42, α52, α62, β12, β22, β32, β42, β52, β62, c22, c32, c42, c52, c62 = cache - - if integrator.u_modified - cache.step = 1 - end - # cnt = cache.step - - if cache.step % 2 == 1 - cache.step += 1 - # u1 - tmp = dt * integrator.fsalfirst - u = uprev + β11 * tmp - # u2 - tmp = α21 * tmp + dt * f(u, p, t + c21 * dt) - u = u + β21 * tmp - # u3 - tmp = α31 * tmp + dt * f(u, p, t + c31 * dt) - u = u + β31 * tmp - # u4 - tmp = α41 * tmp + dt * f(u, p, t + c41 * dt) - u = u + β41 * tmp - # u5 = u - tmp = α51 * tmp + dt * f(u, p, t + c51 * dt) - u = u + β51 * tmp - - else - cache.step += 1 - # u1 - tmp = dt * integrator.fsalfirst - u = uprev + β12 * tmp - # u2 - tmp = α22 * tmp + dt * f(u, p, t + c22 * dt) - u = u + β22 * tmp - # u3 - tmp = α32 * tmp + dt * f(u, p, t + c32 * dt) - u = u + β32 * tmp - # u4 - tmp = α42 * tmp + dt * f(u, p, t + c42 * dt) - u = u + β42 * tmp - # u5 = u - tmp = α52 * tmp + dt * f(u, p, t + c52 * dt) - u = u + β52 * tmp - tmp = α62 * tmp + dt * f(u, p, t + c62 * dt) - u = u + β62 * tmp - end - - integrator.fsallast = f(u, p, t + dt) # For interpolation, then FSAL'd - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast - integrator.u = u -end - -function initialize!(integrator, cache::SHLDDRK_2NCache) - @unpack k, fsalfirst = cache - - integrator.kshortsize = 2 - resize!(integrator.k, integrator.kshortsize) - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast - integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation -end - -@muladd function perform_step!(integrator, cache::SHLDDRK_2NCache, repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack k, fsalfirst, tmp, stage_limiter!, step_limiter!, thread = cache - @unpack α21, α31, α41, α51, β11, β21, β31, β41, β51, c21, c31, c41, c51, α22, α32, α42, α52, α62, β12, β22, β32, β42, β52, β62, c22, c32, c42, c52, c62 = cache.tab - - if integrator.u_modified - cache.step = 1 - end - - if cache.step % 2 == 1 - # u1 - @.. thread=thread tmp=dt * fsalfirst - @.. thread=thread u=uprev + β11 * tmp - stage_limiter!(u, integrator, p, t + c21 * dt) - # u2 - f(k, u, p, t + c21 * dt) - @.. thread=thread tmp=α21 * tmp + dt * k - @.. thread=thread u=u + β21 * tmp - stage_limiter!(u, integrator, p, t + c31 * dt) - # u3 - f(k, u, p, t + c31 * dt) - @.. thread=thread tmp=α31 * tmp + dt * k - @.. thread=thread u=u + β31 * tmp - stage_limiter!(u, integrator, p, t + c41 * dt) - # u4 - f(k, u, p, t + c41 * dt) - @.. thread=thread tmp=α41 * tmp + dt * k - @.. thread=thread u=u + β41 * tmp - stage_limiter!(u, integrator, p, t + c51 * dt) - # u5 = u - f(k, u, p, t + c51 * dt) - @.. thread=thread tmp=α51 * tmp + dt * k - @.. thread=thread u=u + β51 * tmp - stage_limiter!(u, integrator, p, t + dt) - step_limiter!(u, integrator, p, t + dt) - - f(k, u, p, t + dt) - else - # u1 - @.. thread=thread tmp=dt * fsalfirst - @.. thread=thread u=uprev + β12 * tmp - stage_limiter!(u, integrator, p, t + c22 * dt) - # u2 - f(k, u, p, t + c22 * dt) - @.. thread=thread tmp=α22 * tmp + dt * k - @.. thread=thread u=u + β22 * tmp - stage_limiter!(u, integrator, p, t + c32 * dt) - # u3 - f(k, u, p, t + c32 * dt) - @.. thread=thread tmp=α32 * tmp + dt * k - @.. thread=thread u=u + β32 * tmp - stage_limiter!(u, integrator, p, t + c42 * dt) - # u4 - f(k, u, p, t + c42 * dt) - @.. thread=thread tmp=α42 * tmp + dt * k - @.. thread=thread u=u + β42 * tmp - stage_limiter!(u, integrator, p, t + c52 * dt) - # u5 = u - f(k, u, p, t + c52 * dt) - @.. thread=thread tmp=α52 * tmp + dt * k - @.. thread=thread u=u + β52 * tmp - stage_limiter!(u, integrator, p, t + c62 * dt) - # u6 = u - f(k, u, p, t + c62 * dt) - @.. thread=thread tmp=α62 * tmp + dt * k - @.. thread=thread u=u + β62 * tmp - stage_limiter!(u, integrator, p, t + dt) - step_limiter!(u, integrator, p, t + dt) - - f(k, u, p, t + dt) - end -end - function initialize!(integrator, cache::SSPRK33ConstantCache) integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) From 61c3da36b2da8a7d2913e9dd2d9f5e6631ce34ac Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Fri, 23 Aug 2024 00:22:10 +0530 Subject: [PATCH 07/45] Fixes --- lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl index 859f686f09..c5e20f5e9d 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl @@ -181,7 +181,7 @@ end thread::Thread end -mutable struct SHLDDRK_2NConstantCache{T1, T2} <: SSPRKConstantCache +mutable struct SHLDDRK_2NConstantCache{T1, T2} <: OrdinaryDiffEqConstantCache α21::T1 α31::T1 α41::T1 @@ -273,7 +273,7 @@ function alg_cache(alg::SHLDDRK_2N, u, rate_prototype, ::Type{uEltypeNoUnits}, alg.step_limiter!, alg.thread) end -struct SHLDDRK52ConstantCache{T1, T2} <: SSPRKConstantCache +struct SHLDDRK52ConstantCache{T1, T2} <: OrdinaryDiffEqConstantCache α2::T1 α3::T1 α4::T1 From f6c28c96c262897607c7b1b1c0884cfbdb44512c Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Fri, 23 Aug 2024 00:33:14 +0530 Subject: [PATCH 08/45] Fixes --- .../src/low_storage_rk_caches.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl index c5e20f5e9d..d84d894020 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl @@ -273,6 +273,18 @@ 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 + u::uType + uprev::uType + k::rateType + tmp::uType + fsalfirst::rateType + tab::TabType + stage_limiter!::StageLimiter + step_limiter!::StepLimiter + thread::Thread +end + struct SHLDDRK52ConstantCache{T1, T2} <: OrdinaryDiffEqConstantCache α2::T1 α3::T1 From b724e76d0b78e1028611b65295fb6b80eaa46e80 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Fri, 23 Aug 2024 00:53:04 +0530 Subject: [PATCH 09/45] Changes --- .../src/low_storage_rk_perform_step.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index 1307a3f168..126a77d159 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -967,8 +967,10 @@ end integrator.fsallast = f(u, p, t + dt) # For interpolation, then FSAL'd integrator.k[1] = integrator.fsalfirst - integrator.k[2] = integrator.fsallast - integrator.u = u + integrator.k[2] = f(integrator.u, p, t + dt) # For interpolation, then FSAL'd + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) + integrator.fsallast = integrator.k[2] + return nothing end function initialize!(integrator, cache::SHLDDRK52Cache) @@ -979,6 +981,7 @@ function initialize!(integrator, cache::SHLDDRK52Cache) integrator.k[1] = integrator.fsalfirst integrator.k[2] = integrator.fsallast integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # FSAL for interpolation + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) end @muladd function perform_step!(integrator, cache::SHLDDRK52Cache, repeat_step = false) From 2bedaa49a63fbc1f6a9484857a11fb27f88a48f1 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 02:17:21 +0000 Subject: [PATCH 10/45] CompatHelper: add new compat entry for OrdinaryDiffEqIMEXMultistep at version 1, (keep existing compat) --- Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9cc17d5a6c..33b3cf229a 100644 --- a/Project.toml +++ b/Project.toml @@ -103,9 +103,10 @@ OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExtrapolation = "1" OrdinaryDiffEqFeagin = "1" OrdinaryDiffEqFunctionMap = "1" +OrdinaryDiffEqHighOrderRK = "1" +OrdinaryDiffEqIMEXMultistep = "1" OrdinaryDiffEqLowOrderRK = "1" OrdinaryDiffEqLowStorageRK = "1" -OrdinaryDiffEqHighOrderRK = "1" OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" From 4274eecb5467259871d85607a5db4d9e7b58603a Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 02:17:29 +0000 Subject: [PATCH 11/45] CompatHelper: add new compat entry for OrdinaryDiffEqExplicitRK at version 1, (keep existing compat) --- Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9cc17d5a6c..d16b67eb9e 100644 --- a/Project.toml +++ b/Project.toml @@ -100,12 +100,13 @@ NonlinearSolve = "3" OrdinaryDiffEqAdamsBashforthMoulton = "1" OrdinaryDiffEqCore = "1" OrdinaryDiffEqDifferentiation = "1" +OrdinaryDiffEqExplicitRK = "1" OrdinaryDiffEqExtrapolation = "1" OrdinaryDiffEqFeagin = "1" OrdinaryDiffEqFunctionMap = "1" +OrdinaryDiffEqHighOrderRK = "1" OrdinaryDiffEqLowOrderRK = "1" OrdinaryDiffEqLowStorageRK = "1" -OrdinaryDiffEqHighOrderRK = "1" OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" From 253adb84c5c21c4bac3bed360590b71859ada39c Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Fri, 23 Aug 2024 08:16:50 +0530 Subject: [PATCH 12/45] Changes made --- .../src/low_storage_rk_perform_step.jl | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index 126a77d159..b1d0d1dad0 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -932,6 +932,33 @@ end integrator.u = u end +function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache) + integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) + integrator.kshortsize = 2 + integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) + + # Avoid undefined entries if k is an array of arrays + integrator.fsallast = zero(integrator.fsalfirst) + return nothing +end + +@muladd function perform_step!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache, + repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator + @unpack α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2 = cache + u_1 = α_10 * uprev + dt * β_10 * integrator.fsalfirst + u_2 = (α_20 * uprev + + α_21 * u_1 + dt * β_21 * f(u_1, p, t + c_1 * dt)) + integrator.u = (α_30 * uprev + dt * β_30 * integrator.fsalfirst + + α_32 * u_2 + dt * β_32 * f(u_2, p, t + c_2 * dt)) + integrator.k[1] = integrator.fsalfirst + integrator.k[2] = f(integrator.u, p, t + dt) # For interpolation, then FSAL'd + OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) + integrator.fsallast = integrator.k[2] + return nothing +end + function initialize!(integrator, cache::SHLDDRK52ConstantCache) integrator.kshortsize = 2 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) From 19367f5c96881d6c679a268b0147c661bf73afb0 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Fri, 23 Aug 2024 08:21:56 +0530 Subject: [PATCH 13/45] Changes --- .../src/low_storage_rk_perform_step.jl | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index b1d0d1dad0..126a77d159 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -932,33 +932,6 @@ end integrator.u = u end -function initialize!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache) - integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 1) - integrator.kshortsize = 2 - integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) - - # Avoid undefined entries if k is an array of arrays - integrator.fsallast = zero(integrator.fsalfirst) - return nothing -end - -@muladd function perform_step!(integrator, cache::KYK2014DGSSPRK_3S2_ConstantCache, - repeat_step = false) - @unpack t, dt, uprev, u, f, p = integrator - @unpack α_10, α_20, α_21, α_30, α_32, β_10, β_21, β_30, β_32, c_1, c_2 = cache - u_1 = α_10 * uprev + dt * β_10 * integrator.fsalfirst - u_2 = (α_20 * uprev + - α_21 * u_1 + dt * β_21 * f(u_1, p, t + c_1 * dt)) - integrator.u = (α_30 * uprev + dt * β_30 * integrator.fsalfirst + - α_32 * u_2 + dt * β_32 * f(u_2, p, t + c_2 * dt)) - integrator.k[1] = integrator.fsalfirst - integrator.k[2] = f(integrator.u, p, t + dt) # For interpolation, then FSAL'd - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) - integrator.fsallast = integrator.k[2] - return nothing -end - function initialize!(integrator, cache::SHLDDRK52ConstantCache) integrator.kshortsize = 2 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) From 2c08fd9480180c80c6c85a92d5adc09499af21a5 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 06:24:06 +0000 Subject: [PATCH 14/45] CompatHelper: add new compat entry for OrdinaryDiffEqIMEXMultistep at version 1, (keep existing compat) --- Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9cc17d5a6c..33b3cf229a 100644 --- a/Project.toml +++ b/Project.toml @@ -103,9 +103,10 @@ OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExtrapolation = "1" OrdinaryDiffEqFeagin = "1" OrdinaryDiffEqFunctionMap = "1" +OrdinaryDiffEqHighOrderRK = "1" +OrdinaryDiffEqIMEXMultistep = "1" OrdinaryDiffEqLowOrderRK = "1" OrdinaryDiffEqLowStorageRK = "1" -OrdinaryDiffEqHighOrderRK = "1" OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" From 2093b6a8670e76ef3fdbf7941d8a7f1333efb178 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 06:55:48 +0000 Subject: [PATCH 15/45] CompatHelper: add new compat entry for OrdinaryDiffEqFIRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 75fcfc27f4..d33a1a7683 100644 --- a/Project.toml +++ b/Project.toml @@ -102,6 +102,7 @@ OrdinaryDiffEqCore = "1" OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExplicitRK = "1" OrdinaryDiffEqExtrapolation = "1" +OrdinaryDiffEqFIRK = "1" OrdinaryDiffEqFeagin = "1" OrdinaryDiffEqFunctionMap = "1" OrdinaryDiffEqHighOrderRK = "1" From 3d8a5e85a8b99fa90132b7050ab19584fc86e5ec Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 06:55:53 +0000 Subject: [PATCH 16/45] CompatHelper: add new compat entry for OrdinaryDiffEqFIRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 75fcfc27f4..d33a1a7683 100644 --- a/Project.toml +++ b/Project.toml @@ -102,6 +102,7 @@ OrdinaryDiffEqCore = "1" OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExplicitRK = "1" OrdinaryDiffEqExtrapolation = "1" +OrdinaryDiffEqFIRK = "1" OrdinaryDiffEqFeagin = "1" OrdinaryDiffEqFunctionMap = "1" OrdinaryDiffEqHighOrderRK = "1" From 50230842db7a617cf11e446f45fa4f320551411a Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Fri, 23 Aug 2024 13:04:24 +0530 Subject: [PATCH 17/45] Fixes --- lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl b/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl index 2f9fa6614e..ec0c73f11b 100644 --- a/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl +++ b/lib/OrdinaryDiffEqSSPRK/test/ode_ssprk_tests.jl @@ -474,7 +474,7 @@ integ = init(prob_ode_large, alg, dt = 1.e-2, save_start = false, save_end = fal @test Base.summarysize(integ) ÷ Base.summarysize(u0_large) <= 5 println("KYK2014DGSSPRK_3S2") -alg = OrdinaryDiffEqLowStorageRK.KYK2014DGSSPRK_3S2() +alg = KYK2014DGSSPRK_3S2() for prob in test_problems_only_time sim = test_convergence(dts, prob, alg) @test abs(sim.𝒪est[:final] - OrdinaryDiffEqSSPRK.alg_order(alg)) < testTol From ca00cf155de3c019ed44e8d0d26ebaf54239e180 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:30 +0000 Subject: [PATCH 18/45] CompatHelper: add new compat entry for OrdinaryDiffEqLinear at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..4ac40f261b 100644 --- a/Project.toml +++ b/Project.toml @@ -107,6 +107,7 @@ OrdinaryDiffEqFeagin = "1" OrdinaryDiffEqFunctionMap = "1" OrdinaryDiffEqHighOrderRK = "1" OrdinaryDiffEqIMEXMultistep = "1" +OrdinaryDiffEqLinear = "1" OrdinaryDiffEqLowOrderRK = "1" OrdinaryDiffEqLowStorageRK = "1" OrdinaryDiffEqNonlinearSolve = "1" From a9ebea886740a7c657248a9e568dca8410cfbf42 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:35 +0000 Subject: [PATCH 19/45] CompatHelper: add new compat entry for OrdinaryDiffEqBDF at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..6e8b35dd58 100644 --- a/Project.toml +++ b/Project.toml @@ -98,6 +98,7 @@ MacroTools = "0.5" MuladdMacro = "0.2.1" NonlinearSolve = "3" OrdinaryDiffEqAdamsBashforthMoulton = "1" +OrdinaryDiffEqBDF = "1" OrdinaryDiffEqCore = "1" OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExplicitRK = "1" From b114c1ff286600df7f5008ca3e1f5d4c7b00f4e9 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:38 +0000 Subject: [PATCH 20/45] CompatHelper: add new compat entry for OrdinaryDiffEqRosenbrock at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..cac27ee7ee 100644 --- a/Project.toml +++ b/Project.toml @@ -113,6 +113,7 @@ OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" +OrdinaryDiffEqRosenbrock = "1" OrdinaryDiffEqStabilizedRK = "1" OrdinaryDiffEqTsit5 = "1" OrdinaryDiffEqVerner = "1" From 157d583c8f1ac8e01e811897f1f449963388a494 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:40 +0000 Subject: [PATCH 21/45] CompatHelper: add new compat entry for OrdinaryDiffEqNordsieck at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..ed6640e241 100644 --- a/Project.toml +++ b/Project.toml @@ -110,6 +110,7 @@ OrdinaryDiffEqIMEXMultistep = "1" OrdinaryDiffEqLowOrderRK = "1" OrdinaryDiffEqLowStorageRK = "1" OrdinaryDiffEqNonlinearSolve = "1" +OrdinaryDiffEqNordsieck = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" From b9e9f2d5a2a3602f5dad406e1d140ac5d9e354f6 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:44 +0000 Subject: [PATCH 22/45] CompatHelper: add new compat entry for OrdinaryDiffEqSDIRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..43cfe1fabb 100644 --- a/Project.toml +++ b/Project.toml @@ -113,6 +113,7 @@ OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" +OrdinaryDiffEqSDIRK = "1" OrdinaryDiffEqStabilizedRK = "1" OrdinaryDiffEqTsit5 = "1" OrdinaryDiffEqVerner = "1" From 3acf488f126ce2eba40a2b9ef86071a9b839ea15 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:47 +0000 Subject: [PATCH 23/45] CompatHelper: add new compat entry for OrdinaryDiffEqDefault at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..264af13964 100644 --- a/Project.toml +++ b/Project.toml @@ -99,6 +99,7 @@ MuladdMacro = "0.2.1" NonlinearSolve = "3" OrdinaryDiffEqAdamsBashforthMoulton = "1" OrdinaryDiffEqCore = "1" +OrdinaryDiffEqDefault = "1" OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExplicitRK = "1" OrdinaryDiffEqExtrapolation = "1" From 6e18290bdd68b0b02d74c2379323b56a5b0d37ed Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:49 +0000 Subject: [PATCH 24/45] CompatHelper: add new compat entry for OrdinaryDiffEqExponentialRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..fba2150eb7 100644 --- a/Project.toml +++ b/Project.toml @@ -101,6 +101,7 @@ OrdinaryDiffEqAdamsBashforthMoulton = "1" OrdinaryDiffEqCore = "1" OrdinaryDiffEqDifferentiation = "1" OrdinaryDiffEqExplicitRK = "1" +OrdinaryDiffEqExponentialRK = "1" OrdinaryDiffEqExtrapolation = "1" OrdinaryDiffEqFIRK = "1" OrdinaryDiffEqFeagin = "1" From f7896d35be7b5c6968d04c2b9a70f009b93e440a Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:53 +0000 Subject: [PATCH 25/45] CompatHelper: add new compat entry for OrdinaryDiffEqPDIRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..d88281b02a 100644 --- a/Project.toml +++ b/Project.toml @@ -110,6 +110,7 @@ OrdinaryDiffEqIMEXMultistep = "1" OrdinaryDiffEqLowOrderRK = "1" OrdinaryDiffEqLowStorageRK = "1" OrdinaryDiffEqNonlinearSolve = "1" +OrdinaryDiffEqPDIRK = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" From 71fdc1a490d6787d44d6533660dc9d50c60ebdb4 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:56 +0000 Subject: [PATCH 26/45] CompatHelper: add new compat entry for OrdinaryDiffEqSSPRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..358d00c9cc 100644 --- a/Project.toml +++ b/Project.toml @@ -113,6 +113,7 @@ OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" +OrdinaryDiffEqSSPRK = "1" OrdinaryDiffEqStabilizedRK = "1" OrdinaryDiffEqTsit5 = "1" OrdinaryDiffEqVerner = "1" From 9d5b45e5d58eec6741a34eebdca16cdfbd9cb0c0 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:07:59 +0000 Subject: [PATCH 27/45] CompatHelper: add new compat entry for OrdinaryDiffEqSymplecticRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..48f011fe93 100644 --- a/Project.toml +++ b/Project.toml @@ -114,6 +114,7 @@ OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" OrdinaryDiffEqStabilizedRK = "1" +OrdinaryDiffEqSymplecticRK = "1" OrdinaryDiffEqTsit5 = "1" OrdinaryDiffEqVerner = "1" Polyester = "0.7" From a32a0f86669d5832e5ce62fbfa63f3a3c0f4f749 Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Fri, 23 Aug 2024 14:08:01 +0000 Subject: [PATCH 28/45] CompatHelper: add new compat entry for OrdinaryDiffEqStabilizedIRK at version 1, (keep existing compat) --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index d33a1a7683..11bff76c80 100644 --- a/Project.toml +++ b/Project.toml @@ -113,6 +113,7 @@ OrdinaryDiffEqNonlinearSolve = "1" OrdinaryDiffEqPRK = "1" OrdinaryDiffEqQPRK = "1" OrdinaryDiffEqRKN = "1" +OrdinaryDiffEqStabilizedIRK = "1" OrdinaryDiffEqStabilizedRK = "1" OrdinaryDiffEqTsit5 = "1" OrdinaryDiffEqVerner = "1" From b637b86220a5635fbb63e77f7d11c613bc8359f9 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Fri, 23 Aug 2024 22:58:14 -0400 Subject: [PATCH 29/45] Ready a release --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1bfa9b4df4..ef900b0fc0 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.87.0" +version = "6.88.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" From f8358fe78acca71f408376d1556c2f9944ff21ce Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Sat, 24 Aug 2024 09:05:59 +0530 Subject: [PATCH 30/45] Fixes --- lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl b/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl index 37fbc6e047..4b70c66c4e 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl @@ -60,6 +60,7 @@ for prob in test_problems_nonlinear end println("SHLDDRK52") +dts = 1 .// 2 .^ (8:-1:4) alg = SHLDDRK52() for prob in test_problems_only_time sim = test_convergence(dts, prob, alg) From ff181f397f13b5ef938423f2dec1712b447e5d9f Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 06:29:22 -0400 Subject: [PATCH 31/45] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1bfa9b4df4..ef900b0fc0 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.87.0" +version = "6.88.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" From 722806cea558dccf151b06d045e80de22a9c5a46 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 08:59:57 -0400 Subject: [PATCH 32/45] Update OrdinaryDiffEqCoreEnzymeCoreExt.jl Fix https://github.com/SciML/OrdinaryDiffEq.jl/issues/2429 --- .../ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl b/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl index c43dd98c3e..cc80d34bd0 100644 --- a/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl +++ b/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl @@ -1,12 +1,12 @@ module OrdinaryDiffEqCoreEnzymeCoreExt import OrdinaryDiffEqCore, EnzymeCore -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_nf!), args...) = true -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.fixed_t_for_floatingpoint_error!), args...) = true -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_accept!), args...) = true -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_reject!), args...) = true -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_nf_perform_step!), args...) = true -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.check_error!), args...) = true -Enzyme.EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.log_step!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_nf!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.fixed_t_for_floatingpoint_error!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_accept!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_reject!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_nf_perform_step!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.check_error!), args...) = true +EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.log_step!), args...) = true -end \ No newline at end of file +end From 0ca92b3725b11218051f37f9f492e7f9c023fb87 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 09:02:22 -0400 Subject: [PATCH 33/45] format --- .../src/adams_bashforth_moulton_caches.jl | 6 ++- lib/OrdinaryDiffEqBDF/src/algorithms.jl | 5 +- lib/OrdinaryDiffEqBDF/src/bdf_caches.jl | 4 +- lib/OrdinaryDiffEqBDF/src/controllers.jl | 4 +- lib/OrdinaryDiffEqBDF/src/dae_caches.jl | 6 ++- lib/OrdinaryDiffEqBDF/src/dae_perform_step.jl | 2 - .../ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl | 20 ++++++-- .../src/OrdinaryDiffEqCore.jl | 3 +- .../src/caches/basic_caches.jl | 11 +++-- .../src/integrators/integrator_utils.jl | 16 +++---- lib/OrdinaryDiffEqCore/src/interp_func.jl | 3 +- .../perform_step/composite_perform_step.jl | 38 +++++++-------- .../src/precompilation_setup.jl | 10 ++-- lib/OrdinaryDiffEqCore/src/solve.jl | 2 +- .../src/derivative_utils.jl | 46 +++++++++---------- .../src/explicit_rk_caches.jl | 2 +- .../src/exponential_rk_caches.jl | 6 +-- .../src/extrapolation_caches.jl | 4 +- lib/OrdinaryDiffEqFIRK/src/firk_caches.jl | 2 +- lib/OrdinaryDiffEqFeagin/src/feagin_caches.jl | 2 +- .../src/feagin_rk_perform_step.jl | 3 -- .../src/functionmap_caches.jl | 2 +- .../src/high_order_rk_caches.jl | 4 +- .../src/imex_multistep_caches.jl | 4 +- lib/OrdinaryDiffEqLinear/src/linear_caches.jl | 4 +- .../src/fixed_timestep_perform_step.jl | 10 ++-- .../src/low_order_rk_perform_step.jl | 38 +++++++-------- .../src/split_perform_step.jl | 2 +- .../src/low_storage_rk_caches.jl | 2 +- .../src/low_storage_rk_perform_step.jl | 2 +- .../src/nordsieck_caches.jl | 4 +- lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl | 2 +- lib/OrdinaryDiffEqPRK/src/prk_caches.jl | 2 +- lib/OrdinaryDiffEqQPRK/src/qprk_caches.jl | 2 +- lib/OrdinaryDiffEqRKN/src/rkn_caches.jl | 2 +- .../src/rosenbrock_caches.jl | 13 ++++-- lib/OrdinaryDiffEqSDIRK/src/sdirk_caches.jl | 4 +- .../src/OrdinaryDiffEqSSPRK.jl | 1 - lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl | 32 ++++++++----- .../src/irkc_caches.jl | 4 +- .../src/rkc_caches.jl | 2 +- .../src/symplectic_caches.jl | 5 +- .../src/symplectic_perform_step.jl | 1 - lib/OrdinaryDiffEqTsit5/src/tsit_caches.jl | 2 +- lib/OrdinaryDiffEqVerner/src/verner_caches.jl | 8 ++-- test/interface/default_solver_tests.jl | 4 +- test/interface/linear_solver_test.jl | 10 ++-- test/interface/noindex_tests.jl | 36 +++++++++------ test/interface/ode_strip_test.jl | 2 +- 49 files changed, 221 insertions(+), 178 deletions(-) diff --git a/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/adams_bashforth_moulton_caches.jl b/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/adams_bashforth_moulton_caches.jl index fda72a8cd8..d417f9cdad 100644 --- a/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/adams_bashforth_moulton_caches.jl +++ b/lib/OrdinaryDiffEqAdamsBashforthMoulton/src/adams_bashforth_moulton_caches.jl @@ -1,7 +1,9 @@ abstract type ABMMutableCache <: OrdinaryDiffEqMutableCache end abstract type ABMVariableCoefficientMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::ABMMutableCache,u) = (cache.fsalfirst, cache.k) -get_fsalfirstlast(cache::ABMVariableCoefficientMutableCache,u) = (cache.fsalfirst, cache.k4) +get_fsalfirstlast(cache::ABMMutableCache, u) = (cache.fsalfirst, cache.k) +function get_fsalfirstlast(cache::ABMVariableCoefficientMutableCache, u) + (cache.fsalfirst, cache.k4) +end @cache mutable struct AB3Cache{uType, rateType} <: ABMMutableCache u::uType uprev::uType diff --git a/lib/OrdinaryDiffEqBDF/src/algorithms.jl b/lib/OrdinaryDiffEqBDF/src/algorithms.jl index 1a4c960c7b..4f25e268a7 100644 --- a/lib/OrdinaryDiffEqBDF/src/algorithms.jl +++ b/lib/OrdinaryDiffEqBDF/src/algorithms.jl @@ -150,7 +150,7 @@ end function QNDF1(; chunk_size = Val{0}(), autodiff = Val{true}(), standardtag = Val{true}(), concrete_jac = nothing, diff_type = Val{:forward}, linsolve = nothing, precs = DEFAULT_PRECS, nlsolve = NLNewton(), - extrapolant = :linear, kappa = -37//200, + extrapolant = :linear, kappa = -37 // 200, controller = :Standard, step_limiter! = trivial_limiter!) QNDF1{ _unwrap_val(chunk_size), _unwrap_val(autodiff), typeof(linsolve), typeof(nlsolve), @@ -233,7 +233,8 @@ function QNDF(; max_order::Val{MO} = Val{5}(), chunk_size = Val{0}(), diff_type = Val{:forward}, linsolve = nothing, precs = DEFAULT_PRECS, nlsolve = NLNewton(), κ = nothing, tol = nothing, - extrapolant = :linear, kappa = (-37//200, -1//9, -823//10000, -83//2000, 0//1), + extrapolant = :linear, kappa = ( + -37 // 200, -1 // 9, -823 // 10000, -83 // 2000, 0 // 1), controller = :Standard, step_limiter! = trivial_limiter!) where {MO} QNDF{MO, _unwrap_val(chunk_size), _unwrap_val(autodiff), typeof(linsolve), typeof(nlsolve), typeof(precs), diff_type, _unwrap_val(standardtag), diff --git a/lib/OrdinaryDiffEqBDF/src/bdf_caches.jl b/lib/OrdinaryDiffEqBDF/src/bdf_caches.jl index 9d60023c13..00c6875cef 100644 --- a/lib/OrdinaryDiffEqBDF/src/bdf_caches.jl +++ b/lib/OrdinaryDiffEqBDF/src/bdf_caches.jl @@ -1,5 +1,7 @@ abstract type BDFMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::BDFMutableCache,u) = (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +function get_fsalfirstlast(cache::BDFMutableCache, u) + (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +end @cache mutable struct ABDF2ConstantCache{N, dtType, rate_prototype} <: OrdinaryDiffEqConstantCache diff --git a/lib/OrdinaryDiffEqBDF/src/controllers.jl b/lib/OrdinaryDiffEqBDF/src/controllers.jl index c001e6a586..fc13dbd91a 100644 --- a/lib/OrdinaryDiffEqBDF/src/controllers.jl +++ b/lib/OrdinaryDiffEqBDF/src/controllers.jl @@ -206,7 +206,7 @@ function choose_order!(alg::FBDF, integrator, Val(max_order)) local terk_tmp if u isa Number - terk_tmp = fd_weights[k - 2, 1]*u + terk_tmp = fd_weights[k - 2, 1] * u for i in 2:(k - 2) terk_tmp += fd_weights[i, k - 2] * u_history[i - 1] end @@ -215,7 +215,7 @@ function choose_order!(alg::FBDF, integrator, # we need terk_tmp to be mutable. # so it can be updated terk_tmp = similar(u) - @.. terk_tmp = fd_weights[k - 2, 1]*_vec(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] end diff --git a/lib/OrdinaryDiffEqBDF/src/dae_caches.jl b/lib/OrdinaryDiffEqBDF/src/dae_caches.jl index 00bfb4ca5a..708a3d119f 100644 --- a/lib/OrdinaryDiffEqBDF/src/dae_caches.jl +++ b/lib/OrdinaryDiffEqBDF/src/dae_caches.jl @@ -1,5 +1,7 @@ abstract type DAEBDFMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::DAEBDFMutableCache,u) = (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +function get_fsalfirstlast(cache::DAEBDFMutableCache, u) + (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +end @cache mutable struct DImplicitEulerCache{uType, rateType, uNoUnitsType, N} <: DAEBDFMutableCache @@ -13,7 +15,7 @@ get_fsalfirstlast(cache::DAEBDFMutableCache,u) = (cache.fsalfirst, du_alias_or_n end # Not FSAL -get_fsalfirstlast(cache::DImplicitEulerCache,u) = (u,u) +get_fsalfirstlast(cache::DImplicitEulerCache, u) = (u, u) mutable struct DImplicitEulerConstantCache{N} <: OrdinaryDiffEqConstantCache nlsolver::N diff --git a/lib/OrdinaryDiffEqBDF/src/dae_perform_step.jl b/lib/OrdinaryDiffEqBDF/src/dae_perform_step.jl index fd9b007963..d372a89a5e 100644 --- a/lib/OrdinaryDiffEqBDF/src/dae_perform_step.jl +++ b/lib/OrdinaryDiffEqBDF/src/dae_perform_step.jl @@ -160,8 +160,6 @@ end end function initialize!(integrator, cache::DABDF2Cache) - - integrator.kshortsize = 2 @unpack k₁, k₂ = cache.eulercache resize!(integrator.k, integrator.kshortsize) diff --git a/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl b/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl index cc80d34bd0..ddd276c10f 100644 --- a/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl +++ b/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl @@ -2,10 +2,22 @@ module OrdinaryDiffEqCoreEnzymeCoreExt import OrdinaryDiffEqCore, EnzymeCore EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_nf!), args...) = true -EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.fixed_t_for_floatingpoint_error!), args...) = true -EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_accept!), args...) = true -EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_reject!), args...) = true -EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.increment_nf_perform_step!), args...) = true +function EnzymeCore.EnzymeRules.inactive( + ::typeof(OrdinaryDiffEqCore.fixed_t_for_floatingpoint_error!), args...) + true +end +function EnzymeCore.EnzymeRules.inactive( + ::typeof(OrdinaryDiffEqCore.increment_accept!), args...) + true +end +function EnzymeCore.EnzymeRules.inactive( + ::typeof(OrdinaryDiffEqCore.increment_reject!), args...) + true +end +function EnzymeCore.EnzymeRules.inactive( + ::typeof(OrdinaryDiffEqCore.increment_nf_perform_step!), args...) + true +end EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.check_error!), args...) = true EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.log_step!), args...) = true diff --git a/lib/OrdinaryDiffEqCore/src/OrdinaryDiffEqCore.jl b/lib/OrdinaryDiffEqCore/src/OrdinaryDiffEqCore.jl index 6cbb4ec20a..bc36e5c7a0 100644 --- a/lib/OrdinaryDiffEqCore/src/OrdinaryDiffEqCore.jl +++ b/lib/OrdinaryDiffEqCore/src/OrdinaryDiffEqCore.jl @@ -41,7 +41,7 @@ using SimpleUnPack, RecursiveArrayTools, DataStructures, ArrayInterface import TruncatedStacktraces import StaticArraysCore: SArray, MVector, SVector, StaticArray, MMatrix, - StaticMatrix + StaticMatrix # Integrator Interface import DiffEqBase: resize!, deleteat!, addat!, full_cache, user_cache, u_cache, du_cache, @@ -54,7 +54,6 @@ import DiffEqBase: resize!, deleteat!, addat!, full_cache, user_cache, u_cache, isautodifferentiable, get_tstops, get_tstops_array, get_tstops_max - using DiffEqBase: check_error!, @def, _vec, _reshape using FastBroadcast: @.., True, False diff --git a/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl b/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl index f8aef04cda..088fcc4b76 100644 --- a/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl +++ b/lib/OrdinaryDiffEqCore/src/caches/basic_caches.jl @@ -5,7 +5,7 @@ struct ODEEmptyCache <: OrdinaryDiffEqConstantCache end struct ODEChunkCache{CS} <: OrdinaryDiffEqConstantCache end # Don't worry about the potential alloc on a constant cache -get_fsalfirstlast(cache::OrdinaryDiffEqConstantCache,u) = (zero(u), zero(u)) +get_fsalfirstlast(cache::OrdinaryDiffEqConstantCache, u) = (zero(u), zero(u)) mutable struct CompositeCache{T, F} <: OrdinaryDiffEqCache caches::T @@ -13,7 +13,7 @@ mutable struct CompositeCache{T, F} <: OrdinaryDiffEqCache current::Int end -get_fsalfirstlast(cache::CompositeCache,u) = get_fsalfirstlast(cache.caches[1],u) +get_fsalfirstlast(cache::CompositeCache, u) = get_fsalfirstlast(cache.caches[1], u) mutable struct DefaultCache{T1, T2, T3, T4, T5, T6, A, F, uType} <: OrdinaryDiffEqCache args::A @@ -28,12 +28,13 @@ mutable struct DefaultCache{T1, T2, T3, T4, T5, T6, A, F, uType} <: OrdinaryDiff cache6::T6 function DefaultCache{T1, T2, T3, T4, T5, T6, F, uType}( args, choice_function, current, u) where {T1, T2, T3, T4, T5, T6, F, uType} - new{T1, T2, T3, T4, T5, T6, typeof(args), F, uType}(args, choice_function, current, u) + new{T1, T2, T3, T4, T5, T6, typeof(args), F, uType}( + args, choice_function, current, u) end end -function get_fsalfirstlast(cache::DefaultCache,u) - (cache.u,cache.u) # will be overwritten by the cache choice +function get_fsalfirstlast(cache::DefaultCache, u) + (cache.u, cache.u) # will be overwritten by the cache choice end function alg_cache(alg::CompositeAlgorithm, u, rate_prototype, ::Type{uEltypeNoUnits}, diff --git a/lib/OrdinaryDiffEqCore/src/integrators/integrator_utils.jl b/lib/OrdinaryDiffEqCore/src/integrators/integrator_utils.jl index 3024f40827..fc56ed8d50 100644 --- a/lib/OrdinaryDiffEqCore/src/integrators/integrator_utils.jl +++ b/lib/OrdinaryDiffEqCore/src/integrators/integrator_utils.jl @@ -255,8 +255,8 @@ function _loopfooter!(integrator) end if integrator.opts.progress && integrator.iter % integrator.opts.progress_steps == 0 log_step!(integrator.opts.progress_name, integrator.opts.progress_id, - integrator.opts.progress_message, integrator.dt, integrator.u, - integrator.p, integrator.t, integrator.sol.prob.tspan) + integrator.opts.progress_message, integrator.dt, integrator.u, + integrator.p, integrator.t, integrator.sol.prob.tspan) end # Take value because if t is dual then maxeig can be dual @@ -280,18 +280,18 @@ end function log_step!(progress_name, progress_id, progress_message, dt, u, p, t, tspan) t1, t2 = tspan - @logmsg(LogLevel(-1),progress_name, - _id=progress_id, - message=progress_message(dt, u, p, t), - progress=(t - t1) / (t2 - t1)) + @logmsg(LogLevel(-1), progress_name, + _id=progress_id, + message=progress_message(dt, u, p, t), + progress=(t - t1) / (t2 - t1)) end function fixed_t_for_floatingpoint_error!(integrator, ttmp) if has_tstop(integrator) tstop = integrator.tdir * first_tstop(integrator) if abs(ttmp - tstop) < - 100eps(float(max(integrator.t, tstop) / oneunit(integrator.t))) * - oneunit(integrator.t) + 100eps(float(max(integrator.t, tstop) / oneunit(integrator.t))) * + oneunit(integrator.t) tstop else ttmp diff --git a/lib/OrdinaryDiffEqCore/src/interp_func.jl b/lib/OrdinaryDiffEqCore/src/interp_func.jl index f0c29d4967..a2bcd6b96c 100644 --- a/lib/OrdinaryDiffEqCore/src/interp_func.jl +++ b/lib/OrdinaryDiffEqCore/src/interp_func.jl @@ -62,7 +62,6 @@ end # strip interpolation of function information function SciMLBase.strip_interpolation(id::InterpolationData) - cache = strip_cache(id.cache) InterpolationData(nothing, id.timeseries, @@ -78,7 +77,7 @@ end function strip_cache(cache) if hasfield(typeof(cache), :jac_config) || hasfield(typeof(cache), :grad_config) fieldnums = length(fieldnames(typeof(cache))) - noth_list = fill(nothing,fieldnums) + noth_list = fill(nothing, fieldnums) cache_type_name = Base.typename(typeof(cache)).wrapper cache_type_name(noth_list...) else diff --git a/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl b/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl index c3b277a7bc..91d6d2a781 100644 --- a/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl +++ b/lib/OrdinaryDiffEqCore/src/perform_step/composite_perform_step.jl @@ -32,40 +32,40 @@ function initialize!(integrator, cache::DefaultCache) init_ith_default_cache(cache, algs, cache.current) u = integrator.u if cache.current == 1 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache1,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache1, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, cache.cache1) elseif cache.current == 2 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache2,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache2, u) integrator.fsalfirst = fsalfirst 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) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache3, u) integrator.fsalfirst = fsalfirst 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) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache4, u) integrator.fsalfirst = fsalfirst 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) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache5, u) integrator.fsalfirst = fsalfirst 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) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache6, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, cache.cache6) @@ -79,12 +79,12 @@ function initialize!(integrator, cache::CompositeCache) cache.current = cache.choice_function(integrator) u = integrator.u if cache.current == 1 - fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1],u) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[1])) elseif cache.current == 2 - fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2],u) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[2])) @@ -92,7 +92,7 @@ function initialize!(integrator, cache::CompositeCache) 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) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[cache.current], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[cache.current])) @@ -106,12 +106,12 @@ function initialize!(integrator, cache::CompositeCache{Tuple{T1, T2}, F}) where cache.current = cache.choice_function(integrator) u = integrator.u if cache.current == 1 - fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1],u) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[1])) elseif cache.current == 2 - fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2],u) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[2])) @@ -172,12 +172,12 @@ function choose_algorithm!(integrator, @inbounds if new_current != old_current cache.current = new_current if new_current == 1 - fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1],u) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[1], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[1])) elseif new_current == 2 - fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2],u) + fsalfirst, fsallast = get_fsalfirstlast(cache.caches[2], u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.caches[2])) @@ -205,37 +205,37 @@ function choose_algorithm!(integrator, cache::DefaultCache) cache.current = new_current init_ith_default_cache(cache, algs, new_current) if new_current == 1 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache1,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache1, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.cache1)) new_cache = cache.cache1 elseif new_current == 2 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache2,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache2, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.cache2)) new_cache = cache.cache2 elseif new_current == 3 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache3,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache3, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.cache3)) new_cache = cache.cache3 elseif new_current == 4 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache4,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache4, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.cache4)) new_cache = cache.cache4 elseif new_current == 5 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache5,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache5, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.cache5)) new_cache = cache.cache5 elseif new_current == 6 - fsalfirst, fsallast = get_fsalfirstlast(cache.cache6,u) + fsalfirst, fsallast = get_fsalfirstlast(cache.cache6, u) integrator.fsalfirst = fsalfirst integrator.fsallast = fsallast initialize!(integrator, @inbounds(cache.cache6)) diff --git a/lib/OrdinaryDiffEqCore/src/precompilation_setup.jl b/lib/OrdinaryDiffEqCore/src/precompilation_setup.jl index 655db1737c..bfb61ff69a 100644 --- a/lib/OrdinaryDiffEqCore/src/precompilation_setup.jl +++ b/lib/OrdinaryDiffEqCore/src/precompilation_setup.jl @@ -12,16 +12,16 @@ PrecompileTools.@compile_workload begin ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0)) ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]) ODEProblem{true, SciMLBase.AutoSpecialize}(lorenz, [1.0; 0.0; 0.0], - (0.0, 1.0)) + (0.0, 1.0)) ODEProblem{true, SciMLBase.AutoSpecialize}(lorenz, [1.0; 0.0; 0.0], - (0.0, 1.0), Float64[]) + (0.0, 1.0), Float64[]) ODEProblem{true, SciMLBase.FunctionWrapperSpecialize}(lorenz, [1.0; 0.0; 0.0], - (0.0, 1.0)) + (0.0, 1.0)) ODEProblem{true, SciMLBase.FunctionWrapperSpecialize}(lorenz, [1.0; 0.0; 0.0], - (0.0, 1.0), Float64[]) + (0.0, 1.0), Float64[]) ODEProblem{true, SciMLBase.NoSpecialize}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0)) ODEProblem{true, SciMLBase.NoSpecialize}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), - Float64[]) + Float64[]) lorenz([1.0; 0.0; 0.0], [1.0; 0.0; 0.0], DiffEqBase.NullParameters(), 0.0) lorenz([1.0; 0.0; 0.0], [1.0; 0.0; 0.0], Float64[], 0.0) diff --git a/lib/OrdinaryDiffEqCore/src/solve.jl b/lib/OrdinaryDiffEqCore/src/solve.jl index cef15ee62b..563c7654db 100644 --- a/lib/OrdinaryDiffEqCore/src/solve.jl +++ b/lib/OrdinaryDiffEqCore/src/solve.jl @@ -469,7 +469,7 @@ 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) + faslfirst, fsallast = get_fsalfirstlast(cache, rate_prototype) integrator = ODEIntegrator{typeof(_alg), isinplace(prob), uType, typeof(du), tType, typeof(p), diff --git a/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl b/lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl index d16df97fa7..8544af197a 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 @@ -932,28 +932,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/OrdinaryDiffEqExplicitRK/src/explicit_rk_caches.jl b/lib/OrdinaryDiffEqExplicitRK/src/explicit_rk_caches.jl index 853e216b06..943bbb4d64 100644 --- a/lib/OrdinaryDiffEqExplicitRK/src/explicit_rk_caches.jl +++ b/lib/OrdinaryDiffEqExplicitRK/src/explicit_rk_caches.jl @@ -11,7 +11,7 @@ tab::TabType end -get_fsalfirstlast(cache::ExplicitRKCache,u) = (cache.kk[1], cache.fsallast) +get_fsalfirstlast(cache::ExplicitRKCache, u) = (cache.kk[1], cache.fsallast) function alg_cache(alg::ExplicitRK, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqExponentialRK/src/exponential_rk_caches.jl b/lib/OrdinaryDiffEqExponentialRK/src/exponential_rk_caches.jl index 65b662f825..6a2217e3e0 100644 --- a/lib/OrdinaryDiffEqExponentialRK/src/exponential_rk_caches.jl +++ b/lib/OrdinaryDiffEqExponentialRK/src/exponential_rk_caches.jl @@ -2,7 +2,7 @@ # Classical ExpRK method caches abstract type ExpRKCache <: OrdinaryDiffEqMutableCache end abstract type ExpRKConstantCache <: OrdinaryDiffEqConstantCache end -get_fsalfirstlast(cache::ExpRKCache,u) = (zero(cache.rtmp), zero(cache.rtmp)) +get_fsalfirstlast(cache::ExpRKCache, u) = (zero(cache.rtmp), zero(cache.rtmp)) # Precomputation of exponential-like operators """ @@ -872,7 +872,7 @@ struct ETD2ConstantCache{expType} <: OrdinaryDiffEqConstantCache B0::expType # -ϕ2(hA) end -get_fsalfirstlast(cache::ETD2ConstantCache,u) = (ETD2Fsal(u), ETD2Fsal(u)) +get_fsalfirstlast(cache::ETD2ConstantCache, u) = (ETD2Fsal(u), ETD2Fsal(u)) function alg_cache(alg::ETD2, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, @@ -894,7 +894,7 @@ end B1::expType # ϕ1(hA) + ϕ2(hA) B0::expType # -ϕ2(hA) end -get_fsalfirstlast(cache::ETD2Cache,u) = (ETD2Fsal(cache.rtmp1), ETD2Fsal(cache.rtmp1)) +get_fsalfirstlast(cache::ETD2Cache, u) = (ETD2Fsal(cache.rtmp1), ETD2Fsal(cache.rtmp1)) function alg_cache(alg::ETD2, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqExtrapolation/src/extrapolation_caches.jl b/lib/OrdinaryDiffEqExtrapolation/src/extrapolation_caches.jl index 7ede4e5b1a..30c8fc16c9 100644 --- a/lib/OrdinaryDiffEqExtrapolation/src/extrapolation_caches.jl +++ b/lib/OrdinaryDiffEqExtrapolation/src/extrapolation_caches.jl @@ -1,5 +1,5 @@ abstract type ExtrapolationMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::ExtrapolationMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::ExtrapolationMutableCache, u) = (cache.fsalfirst, cache.k) @cache mutable struct AitkenNevilleCache{ uType, @@ -128,7 +128,7 @@ end diff1::Array{uType, 1} diff2::Array{uType, 1} end -get_fsalfirstlast(cache::ImplicitEulerExtrapolationCache,u) = (zero(u), zero(u)) +get_fsalfirstlast(cache::ImplicitEulerExtrapolationCache, u) = (zero(u), zero(u)) @cache mutable struct ImplicitEulerExtrapolationConstantCache{QType, dtType, arrayType, TF, UF, sequenceType} <: diff --git a/lib/OrdinaryDiffEqFIRK/src/firk_caches.jl b/lib/OrdinaryDiffEqFIRK/src/firk_caches.jl index 516775e085..47fdad5374 100644 --- a/lib/OrdinaryDiffEqFIRK/src/firk_caches.jl +++ b/lib/OrdinaryDiffEqFIRK/src/firk_caches.jl @@ -1,5 +1,5 @@ abstract type FIRKMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::FIRKMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::FIRKMutableCache, u) = (cache.fsalfirst, cache.k) mutable struct RadauIIA3ConstantCache{F, Tab, Tol, Dt, U, JType} <: OrdinaryDiffEqConstantCache diff --git a/lib/OrdinaryDiffEqFeagin/src/feagin_caches.jl b/lib/OrdinaryDiffEqFeagin/src/feagin_caches.jl index 927d4778b2..e350b35725 100644 --- a/lib/OrdinaryDiffEqFeagin/src/feagin_caches.jl +++ b/lib/OrdinaryDiffEqFeagin/src/feagin_caches.jl @@ -1,5 +1,5 @@ abstract type FeaginCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::FeaginCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::FeaginCache, u) = (cache.fsalfirst, cache.k) @cache struct Feagin10Cache{uType, uNoUnitsType, rateType, TabType, StepLimiter} <: FeaginCache diff --git a/lib/OrdinaryDiffEqFeagin/src/feagin_rk_perform_step.jl b/lib/OrdinaryDiffEqFeagin/src/feagin_rk_perform_step.jl index 296f5ece4f..ddba6505b9 100644 --- a/lib/OrdinaryDiffEqFeagin/src/feagin_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqFeagin/src/feagin_rk_perform_step.jl @@ -86,7 +86,6 @@ end end function initialize!(integrator, cache::Feagin10Cache) - integrator.kshortsize = 2 resize!(integrator.k, integrator.kshortsize) integrator.k[1] = integrator.fsalfirst @@ -417,7 +416,6 @@ end end function initialize!(integrator, cache::Feagin12Cache) - integrator.kshortsize = 2 resize!(integrator.k, integrator.kshortsize) integrator.k[1] = integrator.fsalfirst @@ -907,7 +905,6 @@ end end function initialize!(integrator, cache::Feagin14Cache) - integrator.kshortsize = 2 resize!(integrator.k, integrator.kshortsize) integrator.k[1] = integrator.fsalfirst diff --git a/lib/OrdinaryDiffEqFunctionMap/src/functionmap_caches.jl b/lib/OrdinaryDiffEqFunctionMap/src/functionmap_caches.jl index 401a55adeb..38d7afe1d8 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) = (cache.u, cache.uprev) function alg_cache(alg::FunctionMap, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqHighOrderRK/src/high_order_rk_caches.jl b/lib/OrdinaryDiffEqHighOrderRK/src/high_order_rk_caches.jl index 2f8a0f4244..3aed829fb2 100644 --- a/lib/OrdinaryDiffEqHighOrderRK/src/high_order_rk_caches.jl +++ b/lib/OrdinaryDiffEqHighOrderRK/src/high_order_rk_caches.jl @@ -1,5 +1,5 @@ abstract type HighOrderRKMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::HighOrderRKMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::HighOrderRKMutableCache, u) = (cache.fsalfirst, cache.k) @cache struct TanYam7Cache{uType, rateType, uNoUnitsType, TabType, StageLimiter, StepLimiter, Thread} <: HighOrderRKMutableCache @@ -92,7 +92,7 @@ end step_limiter!::StepLimiter thread::Thread end -get_fsalfirstlast(cache::DP8Cache,u) = (cache.k1, cache.k13) +get_fsalfirstlast(cache::DP8Cache, u) = (cache.k1, cache.k13) function alg_cache(alg::DP8, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqIMEXMultistep/src/imex_multistep_caches.jl b/lib/OrdinaryDiffEqIMEXMultistep/src/imex_multistep_caches.jl index 20d33b9d1b..d30425975a 100644 --- a/lib/OrdinaryDiffEqIMEXMultistep/src/imex_multistep_caches.jl +++ b/lib/OrdinaryDiffEqIMEXMultistep/src/imex_multistep_caches.jl @@ -1,6 +1,8 @@ # IMEX Multistep methods abstract type IMEXMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::IMEXMutableCache,u) = (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +function get_fsalfirstlast(cache::IMEXMutableCache, u) + (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +end # CNAB2 diff --git a/lib/OrdinaryDiffEqLinear/src/linear_caches.jl b/lib/OrdinaryDiffEqLinear/src/linear_caches.jl index b18605f1fa..47a1d1bde1 100644 --- a/lib/OrdinaryDiffEqLinear/src/linear_caches.jl +++ b/lib/OrdinaryDiffEqLinear/src/linear_caches.jl @@ -1,5 +1,5 @@ abstract type LinearMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::LinearMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::LinearMutableCache, u) = (cache.fsalfirst, cache.k) @cache struct MagnusMidpointCache{uType, rateType, WType, expType} <: LinearMutableCache @@ -565,7 +565,7 @@ end exp_cache::expType end -get_fsalfirstlast(cache::LinearExponentialCache,u) = (zero(u), zero(u)) +get_fsalfirstlast(cache::LinearExponentialCache, u) = (zero(u), zero(u)) function _phiv_timestep_caches(u_prototype, maxiter::Int, p::Int) n = length(u_prototype) diff --git a/lib/OrdinaryDiffEqLowOrderRK/src/fixed_timestep_perform_step.jl b/lib/OrdinaryDiffEqLowOrderRK/src/fixed_timestep_perform_step.jl index c4ab6f12a6..cfccbcb25a 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/src/fixed_timestep_perform_step.jl +++ b/lib/OrdinaryDiffEqLowOrderRK/src/fixed_timestep_perform_step.jl @@ -21,7 +21,7 @@ function perform_step!(integrator, cache::EulerConstantCache, repeat_step = fals integrator.u = u end -get_fsalfirstlast(cache::EulerCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::EulerCache, u) = (cache.fsalfirst, cache.k) function initialize!(integrator, cache::EulerCache) integrator.kshortsize = 2 @unpack k, fsalfirst = cache @@ -97,7 +97,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::Union{HeunCache, RalstonCache},u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::Union{HeunCache, RalstonCache}, u) = (cache.fsalfirst, cache.k) function initialize!(integrator, cache::Union{HeunCache, RalstonCache}) integrator.kshortsize = 2 @unpack k, fsalfirst = cache @@ -189,7 +189,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::MidpointCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::MidpointCache, u) = (cache.fsalfirst, cache.k) function initialize!(integrator, cache::MidpointCache) @unpack k, fsalfirst = cache integrator.fsalfirst = fsalfirst @@ -288,7 +288,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::RK4Cache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::RK4Cache, u) = (cache.fsalfirst, cache.k) function initialize!(integrator, cache::RK4Cache) @unpack tmp, fsalfirst, k₂, k₃, k₄, k = cache integrator.fsalfirst = fsalfirst @@ -420,7 +420,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::Anas5Cache,u) = (cache.k1, cache.k7) +get_fsalfirstlast(cache::Anas5Cache, u) = (cache.k1, cache.k7) function initialize!(integrator, cache::Anas5Cache) integrator.kshortsize = 7 resize!(integrator.k, integrator.kshortsize) diff --git a/lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_perform_step.jl b/lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_perform_step.jl index b7f8bdd7f0..9d9928f678 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowOrderRK/src/low_order_rk_perform_step.jl @@ -33,7 +33,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::BS3Cache,u) = (cache.fsalfirst, cache.k4) +get_fsalfirstlast(cache::BS3Cache, u) = (cache.fsalfirst, cache.k4) function initialize!(integrator, cache::BS3Cache) integrator.kshortsize = 2 resize!(integrator.k, integrator.kshortsize) @@ -113,7 +113,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::OwrenZen3Cache,u) = (cache.k1, cache.k4) +get_fsalfirstlast(cache::OwrenZen3Cache, u) = (cache.k1, cache.k4) function initialize!(integrator, cache::OwrenZen3Cache) integrator.kshortsize = 4 resize!(integrator.k, integrator.kshortsize) @@ -195,7 +195,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::OwrenZen4Cache,u) = (cache.k1, cache.k6) +get_fsalfirstlast(cache::OwrenZen4Cache, u) = (cache.k1, cache.k6) function initialize!(integrator, cache::OwrenZen4Cache) integrator.kshortsize = 6 resize!(integrator.k, integrator.kshortsize) @@ -297,7 +297,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::OwrenZen5Cache,u) = (cache.k1, cache.k8) +get_fsalfirstlast(cache::OwrenZen5Cache, u) = (cache.k1, cache.k8) function initialize!(integrator, cache::OwrenZen5Cache) integrator.kshortsize = 8 resize!(integrator.k, integrator.kshortsize) @@ -454,7 +454,7 @@ end end end -get_fsalfirstlast(cache::BS5Cache,u) = (cache.k1, cache.k8) +get_fsalfirstlast(cache::BS5Cache, u) = (cache.k1, cache.k8) function initialize!(integrator, cache::BS5Cache) alg = unwrap_alg(integrator, false) alg.lazy ? (integrator.kshortsize = 8) : (integrator.kshortsize = 11) @@ -619,7 +619,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::DP5Cache,u) = (cache.k1, cache.k7) +get_fsalfirstlast(cache::DP5Cache, u) = (cache.k1, cache.k7) function initialize!(integrator, cache::DP5Cache) integrator.kshortsize = 4 resize!(integrator.k, integrator.kshortsize) @@ -736,7 +736,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::RKO65Cache,u) = (cache.k1, cache.k6) +get_fsalfirstlast(cache::RKO65Cache, u) = (cache.k1, cache.k6) function initialize!(integrator, cache::RKO65Cache) @unpack k, fsalfirst = cache integrator.kshortsize = 6 @@ -863,7 +863,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::FRK65Cache,u) = (cache.k1, cache.k9) +get_fsalfirstlast(cache::FRK65Cache, u) = (cache.k1, cache.k9) function initialize!(integrator, cache::FRK65Cache) integrator.kshortsize = 9 @@ -991,7 +991,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::RKMCache,u) = (cache.k1, zero(cache.k1)) +get_fsalfirstlast(cache::RKMCache, u) = (cache.k1, zero(cache.k1)) function initialize!(integrator, cache::RKMCache) @unpack k, fsalfirst = cache integrator.kshortsize = 6 @@ -1081,7 +1081,7 @@ function perform_step!(integrator, cache::PSRK4p7q6ConstantCache, repeat_step = integrator.u = u end -get_fsalfirstlast(cache::PSRK4p7q6Cache,u) = (cache.k1, cache.k6) +get_fsalfirstlast(cache::PSRK4p7q6Cache, u) = (cache.k1, cache.k6) function initialize!(integrator, cache::PSRK4p7q6Cache) @unpack uprev, f, p, t = integrator @@ -1169,7 +1169,7 @@ function perform_step!(integrator, cache::PSRK3p6q5ConstantCache, repeat_step = integrator.u = u end -get_fsalfirstlast(cache::PSRK3p6q5Cache,u) = (cache.k1, cache.k5) +get_fsalfirstlast(cache::PSRK3p6q5Cache, u) = (cache.k1, cache.k5) function initialize!(integrator, cache::PSRK3p6q5Cache) @unpack uprev, f, p, t = integrator @@ -1246,7 +1246,7 @@ function perform_step!(integrator, cache::PSRK3p5q4ConstantCache, repeat_step = integrator.u = u end -get_fsalfirstlast(cache::PSRK3p5q4Cache,u) = (cache.k1, cache.k4) +get_fsalfirstlast(cache::PSRK3p5q4Cache, u) = (cache.k1, cache.k4) function initialize!(integrator, cache::PSRK3p5q4Cache) @unpack uprev, f, p, t = integrator @@ -1335,7 +1335,7 @@ function perform_step!(integrator, cache::MSRK5ConstantCache, repeat_step = fals integrator.u = u end -get_fsalfirstlast(cache::MSRK5Cache,u) = (cache.k1, cache.k9) +get_fsalfirstlast(cache::MSRK5Cache, u) = (cache.k1, cache.k9) function initialize!(integrator, cache::MSRK5Cache) @unpack uprev, f, p, t = integrator @@ -1452,7 +1452,7 @@ function perform_step!(integrator, cache::MSRK6ConstantCache, repeat_step = fals integrator.u = u end -get_fsalfirstlast(cache::MSRK6Cache,u) = (cache.k1, cache.k9) +get_fsalfirstlast(cache::MSRK6Cache, u) = (cache.k1, cache.k9) function initialize!(integrator, cache::MSRK6Cache) @unpack uprev, f, p, t = integrator @@ -1572,7 +1572,7 @@ function perform_step!(integrator, cache::Stepanov5ConstantCache, repeat_step = integrator.u = u end -get_fsalfirstlast(cache::Stepanov5Cache,u) = (cache.k1, cache.k7) +get_fsalfirstlast(cache::Stepanov5Cache, u) = (cache.k1, cache.k7) function initialize!(integrator, cache::Stepanov5Cache) @unpack uprev, f, p, t = integrator @@ -1693,7 +1693,7 @@ function perform_step!(integrator, cache::SIR54ConstantCache, repeat_step = fals integrator.u = u end -get_fsalfirstlast(cache::SIR54Cache,u) = (cache.k1, cache.k8) +get_fsalfirstlast(cache::SIR54Cache, u) = (cache.k1, cache.k8) function initialize!(integrator, cache::SIR54Cache) @unpack uprev, f, p, t = integrator @@ -1801,7 +1801,7 @@ function perform_step!(integrator, cache::Alshina2ConstantCache, repeat_step = f integrator.u = u end -get_fsalfirstlast(cache::Alshina2Cache,u) = (cache.k1, cache.k2) +get_fsalfirstlast(cache::Alshina2Cache, u) = (cache.k1, cache.k2) function initialize!(integrator, cache::Alshina2Cache) @unpack uprev, f, p, t = integrator @@ -1882,7 +1882,7 @@ function perform_step!(integrator, cache::Alshina3ConstantCache, repeat_step = f integrator.u = u end -get_fsalfirstlast(cache::Alshina3Cache,u) = (cache.k1, cache.k3) +get_fsalfirstlast(cache::Alshina3Cache, u) = (cache.k1, cache.k3) function initialize!(integrator, cache::Alshina3Cache) @unpack uprev, f, p, t = integrator @@ -1978,7 +1978,7 @@ function perform_step!(integrator, cache::Alshina6ConstantCache, repeat_step = f integrator.u = u end -get_fsalfirstlast(cache::Alshina6Cache,u) = (cache.k1, cache.k7) +get_fsalfirstlast(cache::Alshina6Cache, u) = (cache.k1, cache.k7) function initialize!(integrator, cache::Alshina6Cache) @unpack uprev, f, p, t = integrator diff --git a/lib/OrdinaryDiffEqLowOrderRK/src/split_perform_step.jl b/lib/OrdinaryDiffEqLowOrderRK/src/split_perform_step.jl index 997610988f..aeb8511f0c 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/src/split_perform_step.jl +++ b/lib/OrdinaryDiffEqLowOrderRK/src/split_perform_step.jl @@ -24,7 +24,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::SplitEulerCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::SplitEulerCache, u) = (cache.fsalfirst, cache.k) function initialize!(integrator, cache::SplitEulerCache) integrator.kshortsize = 2 @unpack k, fsalfirst = cache diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl index c2f4ca4623..b19144a0b7 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_caches.jl @@ -1,5 +1,5 @@ abstract type LowStorageRKMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::LowStorageRKMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::LowStorageRKMutableCache, u) = (cache.fsalfirst, cache.k) # 2N low storage methods introduced by Williamson @cache struct LowStorageRK2NCache{uType, rateType, TabType, StageLimiter, StepLimiter, diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index f76fcb4eb6..8012cb9918 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -33,7 +33,7 @@ end integrator.u = u end -get_fsalfirstlast(cache::LowStorageRK2NCache,u) = (cache.k, cache.k) +get_fsalfirstlast(cache::LowStorageRK2NCache, u) = (cache.k, cache.k) function initialize!(integrator, cache::LowStorageRK2NCache) @unpack k, tmp, williamson_condition = cache diff --git a/lib/OrdinaryDiffEqNordsieck/src/nordsieck_caches.jl b/lib/OrdinaryDiffEqNordsieck/src/nordsieck_caches.jl index fb175b5e38..a9ecb45215 100644 --- a/lib/OrdinaryDiffEqNordsieck/src/nordsieck_caches.jl +++ b/lib/OrdinaryDiffEqNordsieck/src/nordsieck_caches.jl @@ -265,4 +265,6 @@ function alg_cache(alg::JVODE, u, rate_prototype, ::Type{uEltypeNoUnits}, dts, Δ, atmp, tsit5cache, 2, 1, 1, 2, η, η, η, η, η) end -get_fsalfirstlast(cache::Union{JVODECache, AN5Cache},u) = get_fsalfirstlast(cache.tsit5cache,u) \ No newline at end of file +function get_fsalfirstlast(cache::Union{JVODECache, AN5Cache}, u) + get_fsalfirstlast(cache.tsit5cache, u) +end diff --git a/lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl b/lib/OrdinaryDiffEqPDIRK/src/pdirk_caches.jl index 0b1d86d995..2cbbbf828f 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) = (cache.u, cache.uprev) struct PDIRK44ConstantCache{N, TabType} <: OrdinaryDiffEqConstantCache nlsolver::N diff --git a/lib/OrdinaryDiffEqPRK/src/prk_caches.jl b/lib/OrdinaryDiffEqPRK/src/prk_caches.jl index 17c5fa8ba5..059fffcbaa 100644 --- a/lib/OrdinaryDiffEqPRK/src/prk_caches.jl +++ b/lib/OrdinaryDiffEqPRK/src/prk_caches.jl @@ -11,7 +11,7 @@ fsalfirst::rateType tab::TabType end -get_fsalfirstlast(cache::KuttaPRK2p5Cache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::KuttaPRK2p5Cache, u) = (cache.fsalfirst, cache.k) struct KuttaPRK2p5ConstantCache{T, T2} <: OrdinaryDiffEqConstantCache α21::T diff --git a/lib/OrdinaryDiffEqQPRK/src/qprk_caches.jl b/lib/OrdinaryDiffEqQPRK/src/qprk_caches.jl index 667d45823b..8ceb2bc451 100644 --- a/lib/OrdinaryDiffEqQPRK/src/qprk_caches.jl +++ b/lib/OrdinaryDiffEqQPRK/src/qprk_caches.jl @@ -30,7 +30,7 @@ struct QPRK98ConstantCache <: OrdinaryDiffEqConstantCache end thread::Thread end -get_fsalfirstlast(cache::QPRK98Cache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::QPRK98Cache, u) = (cache.fsalfirst, cache.k) function alg_cache(alg::QPRK98, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, diff --git a/lib/OrdinaryDiffEqRKN/src/rkn_caches.jl b/lib/OrdinaryDiffEqRKN/src/rkn_caches.jl index 649052ce8c..e259a1e6ed 100644 --- a/lib/OrdinaryDiffEqRKN/src/rkn_caches.jl +++ b/lib/OrdinaryDiffEqRKN/src/rkn_caches.jl @@ -1,5 +1,5 @@ abstract type NystromMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::NystromMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::NystromMutableCache, u) = (cache.fsalfirst, cache.k) @cache struct Nystrom4Cache{uType, rateType, reducedRateType} <: NystromMutableCache u::uType diff --git a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl index 4a266e77f3..0a70a7fdde 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_caches.jl @@ -2,7 +2,7 @@ abstract type RosenbrockMutableCache <: OrdinaryDiffEqMutableCache 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) = (zero(u), zero(u)) ################################################################################ @@ -1132,10 +1132,13 @@ function alg_cache( constvalue(tTypeNoUnits)), J, W, linsolve) end - -get_fsalfirstlast(cache::Union{Rosenbrock23Cache,Rosenbrock32Cache, Rosenbrock33Cache, -Rosenbrock34Cache, -Rosenbrock4Cache},u) = (cache.fsalfirst, cache.fsallast) +function get_fsalfirstlast( + cache::Union{Rosenbrock23Cache, Rosenbrock32Cache, Rosenbrock33Cache, + Rosenbrock34Cache, + Rosenbrock4Cache}, + u) + (cache.fsalfirst, cache.fsallast) +end ################################################################################ diff --git a/lib/OrdinaryDiffEqSDIRK/src/sdirk_caches.jl b/lib/OrdinaryDiffEqSDIRK/src/sdirk_caches.jl index 21c4f878ee..75a6453fcf 100644 --- a/lib/OrdinaryDiffEqSDIRK/src/sdirk_caches.jl +++ b/lib/OrdinaryDiffEqSDIRK/src/sdirk_caches.jl @@ -1,6 +1,8 @@ abstract type SDIRKMutableCache <: OrdinaryDiffEqMutableCache end abstract type SDIRKConstantCache <: OrdinaryDiffEqConstantCache end -get_fsalfirstlast(cache::SDIRKMutableCache,u) = (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +function get_fsalfirstlast(cache::SDIRKMutableCache, u) + (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +end @cache mutable struct ImplicitEulerCache{ uType, rateType, uNoUnitsType, N, AV, StepLimiter} <: diff --git a/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl b/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl index fde64f8ef7..2d960a9d36 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/OrdinaryDiffEqSSPRK.jl @@ -46,7 +46,6 @@ PrecompileTools.@compile_workload begin ] low_storage_nonadaptive = [ - ] if Preferences.@load_preference("PrecompileLowStorage", false) diff --git a/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl b/lib/OrdinaryDiffEqSSPRK/src/ssprk_caches.jl index cdd41f568b..6ec542a139 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 @@ -217,7 +220,8 @@ function alg_cache(alg::SSPRK53, u, rate_prototype, ::Type{uEltypeNoUnits}, SSPRK53ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -@cache struct SHLDDRK52Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: SSPRKMutableCache +@cache struct SHLDDRK52Cache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: + SSPRKMutableCache u::uType uprev::uType k::rateType @@ -533,7 +537,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 @@ -604,7 +609,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 @@ -682,7 +688,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 @@ -769,7 +776,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 @@ -1131,7 +1139,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 @@ -1219,7 +1228,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 diff --git a/lib/OrdinaryDiffEqStabilizedIRK/src/irkc_caches.jl b/lib/OrdinaryDiffEqStabilizedIRK/src/irkc_caches.jl index 80f92326f9..60239258c9 100644 --- a/lib/OrdinaryDiffEqStabilizedIRK/src/irkc_caches.jl +++ b/lib/OrdinaryDiffEqStabilizedIRK/src/irkc_caches.jl @@ -23,7 +23,9 @@ end constantcache::C end -get_fsalfirstlast(cache::IRKCCache,u) = (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +function get_fsalfirstlast(cache::IRKCCache, u) + (cache.fsalfirst, du_alias_or_new(cache.nlsolver, cache.fsalfirst)) +end function alg_cache(alg::IRKC, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqStabilizedRK/src/rkc_caches.jl b/lib/OrdinaryDiffEqStabilizedRK/src/rkc_caches.jl index cbdaa5cc2e..e598d1243c 100644 --- a/lib/OrdinaryDiffEqStabilizedRK/src/rkc_caches.jl +++ b/lib/OrdinaryDiffEqStabilizedRK/src/rkc_caches.jl @@ -1,5 +1,5 @@ abstract type StabilizedRKMutableCache <: OrdinaryDiffEqMutableCache end -get_fsalfirstlast(cache::StabilizedRKMutableCache,u) = (cache.fsalfirst, cache.k) +get_fsalfirstlast(cache::StabilizedRKMutableCache, u) = (cache.fsalfirst, cache.k) mutable struct ROCK2ConstantCache{T, T2, zType} <: OrdinaryDiffEqConstantCache ms::SVector{46, Int} diff --git a/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_caches.jl b/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_caches.jl index 6112a89792..dca14b6d28 100644 --- a/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_caches.jl +++ b/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_caches.jl @@ -421,4 +421,7 @@ function alg_cache(alg::SofSpa10, u, rate_prototype, ::Type{uEltypeNoUnits}, SofSpa10ConstantCache(constvalue(uBottomEltypeNoUnits), constvalue(tTypeNoUnits)) end -get_fsalfirstlast(cache::Union{HamiltonMutableCache, VelocityVerletCache, SymplecticEulerCache},u) = (cache.fsalfirst, cache.k) +function get_fsalfirstlast( + cache::Union{HamiltonMutableCache, VelocityVerletCache, SymplecticEulerCache}, u) + (cache.fsalfirst, cache.k) +end diff --git a/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_perform_step.jl b/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_perform_step.jl index 06173ff5f2..2e581be283 100644 --- a/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_perform_step.jl +++ b/lib/OrdinaryDiffEqSymplecticRK/src/symplectic_perform_step.jl @@ -126,7 +126,6 @@ end function initialize!(integrator, cache::C) where {C <: Union{HamiltonMutableCache, VelocityVerletCache}} - integrator.kshortsize = 2 resize!(integrator.k, integrator.kshortsize) integrator.k[1] = integrator.fsalfirst diff --git a/lib/OrdinaryDiffEqTsit5/src/tsit_caches.jl b/lib/OrdinaryDiffEqTsit5/src/tsit_caches.jl index b8bc6b611b..040f9a9869 100644 --- a/lib/OrdinaryDiffEqTsit5/src/tsit_caches.jl +++ b/lib/OrdinaryDiffEqTsit5/src/tsit_caches.jl @@ -36,7 +36,7 @@ function alg_cache(alg::Tsit5, u, rate_prototype, ::Type{uEltypeNoUnits}, alg.stage_limiter!, alg.step_limiter!, alg.thread) end -get_fsalfirstlast(cache::Tsit5Cache,u) = (cache.k1, cache.k7) +get_fsalfirstlast(cache::Tsit5Cache, u) = (cache.k1, cache.k7) function alg_cache(alg::Tsit5, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/lib/OrdinaryDiffEqVerner/src/verner_caches.jl b/lib/OrdinaryDiffEqVerner/src/verner_caches.jl index a118fc9f24..19289eb2c2 100644 --- a/lib/OrdinaryDiffEqVerner/src/verner_caches.jl +++ b/lib/OrdinaryDiffEqVerner/src/verner_caches.jl @@ -23,7 +23,7 @@ lazy::Bool end -get_fsalfirstlast(cache::Vern6Cache,u) = (cache.k1, cache.k9) +get_fsalfirstlast(cache::Vern6Cache, u) = (cache.k1, cache.k9) function alg_cache(alg::Vern6, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, @@ -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) = (cache.k1, cache.k2) 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) = (cache.k1, cache.k2) 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) = (cache.k1, cache.k2) function alg_cache(alg::Vern9, u, rate_prototype, ::Type{uEltypeNoUnits}, ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, diff --git a/test/interface/default_solver_tests.jl b/test/interface/default_solver_tests.jl index 4cdef37e80..3c56f9f7ea 100644 --- a/test/interface/default_solver_tests.jl +++ b/test/interface/default_solver_tests.jl @@ -112,9 +112,9 @@ SA_ode_problem = ODEProblem((u, p, t) -> zero(u), SA[0], 2) @test solve(SA_ode_problem; callback = cb).retcode == ReturnCode.Success # test Complex numbers -H(s) = (1-s) * complex([0 1; 1 0]) + s * complex([1 0; 0 -1]) +H(s) = (1 - s) * complex([0 1; 1 0]) + s * complex([1 0; 0 -1]) schrod_eq(state, time, s) = -im * time * H(s) * state -prob_complex = ODEProblem(schrod_eq, complex([1, -1]/sqrt(2)), (0,1), 100) +prob_complex = ODEProblem(schrod_eq, complex([1, -1] / sqrt(2)), (0, 1), 100) complex_sol = solve(prob_complex) @test complex_sol.retcode == ReturnCode.Success diff --git a/test/interface/linear_solver_test.jl b/test/interface/linear_solver_test.jl index 12a449d603..a615deb515 100644 --- a/test/interface/linear_solver_test.jl +++ b/test/interface/linear_solver_test.jl @@ -161,7 +161,7 @@ end using OrdinaryDiffEq, StaticArrays, LinearSolve, ParameterizedFunctions hires = @ode_def Hires begin - dy1 = -1.71f0 * y1 + 0.43f0 * y2 + 8.32f0 * y3 + 0.0007f0 + 1f-18*t + dy1 = -1.71f0 * y1 + 0.43f0 * y2 + 8.32f0 * y3 + 0.0007f0 + 1.0f-18 * t dy2 = 1.71f0 * y1 - 8.75f0 * y2 dy3 = -10.03f0 * y3 + 0.43f0 * y4 + 0.035f0 * y5 dy4 = 8.32f0 * y2 + 1.71f0 * y3 - 1.12f0 * y4 @@ -178,11 +178,11 @@ u0[8] = 0.0057 probiip = ODEProblem{true}(hires, u0, (0.0, 10.0)) proboop = ODEProblem{false}(hires, u0, (0.0, 10.0)) probstatic = ODEProblem{false}(hires, SVector{8}(u0), (0.0, 10.0)) -probiipf32 = ODEProblem{true}(hires, Float32.(u0), (0f0, 10f0)) -proboopf32 = ODEProblem{false}(hires, Float32.(u0), (0f0, 10f0)) -probstaticf32 = ODEProblem{false}(hires, SVector{8}(Float32.(u0)), (0f0, 10f0)) +probiipf32 = ODEProblem{true}(hires, Float32.(u0), (0.0f0, 10.0f0)) +proboopf32 = ODEProblem{false}(hires, Float32.(u0), (0.0f0, 10.0f0)) +probstaticf32 = ODEProblem{false}(hires, SVector{8}(Float32.(u0)), (0.0f0, 10.0f0)) probs = (; probiip, proboop, probstatic) -probsf32 = (;probiipf32, proboopf32, probstaticf32) +probsf32 = (; probiipf32, proboopf32, probstaticf32) qndf = QNDF() krylov_qndf = QNDF(linsolve = KrylovJL_GMRES()) fbdf = FBDF() diff --git a/test/interface/noindex_tests.jl b/test/interface/noindex_tests.jl index f013c59fd9..3aca1a635d 100644 --- a/test/interface/noindex_tests.jl +++ b/test/interface/noindex_tests.jl @@ -56,17 +56,18 @@ for alg in algs @test_nowarn sol(similar(prob.u0), 0.1) end - struct CustomArray{T, N} x::Array{T, N} end Base.size(x::CustomArray) = size(x.x) Base.axes(x::CustomArray) = axes(x.x) Base.ndims(x::CustomArray) = ndims(x.x) -Base.ndims(::Type{<:CustomArray{T,N}}) where {T,N} = N +Base.ndims(::Type{<:CustomArray{T, N}}) where {T, N} = N Base.zero(x::CustomArray) = CustomArray(zero(x.x)) -Base.zero(::Type{<:CustomArray{T,N}}) where {T,N} = CustomArray(zero(Array{T,N})) -Base.similar(x::CustomArray, dims::Union{Integer, AbstractUnitRange}...) = CustomArray(similar(x.x, dims...)) +Base.zero(::Type{<:CustomArray{T, N}}) where {T, N} = CustomArray(zero(Array{T, N})) +function Base.similar(x::CustomArray, dims::Union{Integer, AbstractUnitRange}...) + CustomArray(similar(x.x, dims...)) +end Base.copyto!(x::CustomArray, y::CustomArray) = CustomArray(copyto!(x.x, y.x)) Base.copy(x::CustomArray) = CustomArray(copy(x.x)) Base.length(x::CustomArray) = length(x.x) @@ -82,21 +83,28 @@ Base.any(f::Function, x::CustomArray; kwargs...) = any(f, x.x; kwargs...) Base.all(f::Function, x::CustomArray; kwargs...) = all(f, x.x; kwargs...) Base.similar(x::CustomArray, t) = CustomArray(similar(x.x, t)) Base.:(==)(x::CustomArray, y::CustomArray) = x.x == y.x -Base.:(*)(x::Number, y::CustomArray) = CustomArray(x*y.x) -Base.:(/)(x::CustomArray, y::Number) = CustomArray(x.x/y) +Base.:(*)(x::Number, y::CustomArray) = CustomArray(x * y.x) +Base.:(/)(x::CustomArray, y::Number) = CustomArray(x.x / y) LinearAlgebra.norm(x::CustomArray) = norm(x.x) struct CustomStyle{N} <: Broadcast.BroadcastStyle where {N} end -CustomStyle(::Val{N}) where N = CustomStyle{N}() -CustomStyle{M}(::Val{N}) where {N,M} = NoIndexStyle{N}() -Base.BroadcastStyle(::Type{<:CustomArray{T,N}}) where {T,N} = CustomStyle{N}() -Broadcast.BroadcastStyle(::CustomStyle{N}, ::Broadcast.DefaultArrayStyle{0}) where {N} = CustomStyle{N}() -Base.similar(bc::Base.Broadcast.Broadcasted{CustomStyle{N}}, ::Type{ElType}) where {N, ElType} = CustomArray(similar(Array{ElType, N}, axes(bc))) +CustomStyle(::Val{N}) where {N} = CustomStyle{N}() +CustomStyle{M}(::Val{N}) where {N, M} = NoIndexStyle{N}() +Base.BroadcastStyle(::Type{<:CustomArray{T, N}}) where {T, N} = CustomStyle{N}() +function Broadcast.BroadcastStyle( + ::CustomStyle{N}, ::Broadcast.DefaultArrayStyle{0}) where {N} + CustomStyle{N}() +end +function Base.similar( + bc::Base.Broadcast.Broadcasted{CustomStyle{N}}, ::Type{ElType}) where {N, ElType} + CustomArray(similar(Array{ElType, N}, axes(bc))) +end Base.Broadcast._broadcast_getindex(x::CustomArray, i) = x.x[i] Base.Broadcast.extrude(x::CustomArray) = x Base.Broadcast.broadcastable(x::CustomArray) = x -@inline function Base.copyto!(dest::CustomArray, bc::Base.Broadcast.Broadcasted{<:CustomStyle}) +@inline function Base.copyto!( + dest::CustomArray, bc::Base.Broadcast.Broadcasted{<:CustomStyle}) axes(dest) == axes(bc) || throwdm(axes(dest), axes(bc)) bc′ = Base.Broadcast.preprocess(dest, bc) dest′ = dest.x @@ -127,7 +135,7 @@ RecursiveArrayTools.recursivefill!(x::CustomArray, a) = fill!(x, a) Base.show_vector(io::IO, x::CustomArray) = Base.show_vector(io, x.x) -Base.show(io::IO, x::CustomArray) = (print(io, "CustomArray");show(io, x.x)) +Base.show(io::IO, x::CustomArray) = (print(io, "CustomArray"); show(io, x.x)) function Base.show(io::IO, ::MIME"text/plain", x::CustomArray) println(io, Base.summary(x), ":") Base.print_array(io, x.x) @@ -139,4 +147,4 @@ for alg in algs sol = @test_nowarn solve(prob, alg) @test_nowarn sol(0.1) @test_nowarn sol(similar(prob.u0), 0.1) -end \ No newline at end of file +end diff --git a/test/interface/ode_strip_test.jl b/test/interface/ode_strip_test.jl index ed5a448051..e476c024ee 100644 --- a/test/interface/ode_strip_test.jl +++ b/test/interface/ode_strip_test.jl @@ -14,4 +14,4 @@ prob = ODEProblem(lorenz!, u0, tspan) sol = solve(prob, Rosenbrock23()) @test isnothing(SciMLBase.strip_interpolation(sol.interp).f) -@test isnothing(SciMLBase.strip_interpolation(sol.interp).cache.jac_config) \ No newline at end of file +@test isnothing(SciMLBase.strip_interpolation(sol.interp).cache.jac_config) From 4dc378b3887f87f04e44f6d642ffcbda22c77ce7 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 09:04:29 -0400 Subject: [PATCH 34/45] Update OrdinaryDiffEqCoreEnzymeCoreExt.jl --- lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl b/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl index ddd276c10f..b8bc336b57 100644 --- a/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl +++ b/lib/OrdinaryDiffEqCore/ext/OrdinaryDiffEqCoreEnzymeCoreExt.jl @@ -14,10 +14,6 @@ function EnzymeCore.EnzymeRules.inactive( ::typeof(OrdinaryDiffEqCore.increment_reject!), args...) true end -function EnzymeCore.EnzymeRules.inactive( - ::typeof(OrdinaryDiffEqCore.increment_nf_perform_step!), args...) - true -end EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.check_error!), args...) = true EnzymeCore.EnzymeRules.inactive(::typeof(OrdinaryDiffEqCore.log_step!), args...) = true From ceae110b362586866c4c8662a431b043d923ea89 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 09:04:45 -0400 Subject: [PATCH 35/45] Update Project.toml --- lib/OrdinaryDiffEqCore/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OrdinaryDiffEqCore/Project.toml b/lib/OrdinaryDiffEqCore/Project.toml index f5228b185c..9a950e8230 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.2.0" +version = "1.3.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" From e7dd8b336ac3c794c3f8b1421dd3c926a7517080 Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Sat, 24 Aug 2024 23:07:02 +0530 Subject: [PATCH 36/45] Fixes --- .../src/low_storage_rk_perform_step.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl index 126a77d159..87f66cd32f 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/src/low_storage_rk_perform_step.jl @@ -967,10 +967,8 @@ end integrator.fsallast = f(u, p, t + dt) # For interpolation, then FSAL'd integrator.k[1] = integrator.fsalfirst - integrator.k[2] = f(integrator.u, p, t + dt) # For interpolation, then FSAL'd - OrdinaryDiffEqCore.increment_nf!(integrator.stats, 3) - integrator.fsallast = integrator.k[2] - return nothing + integrator.k[2] = integrator.fsallast + integrator.u = u end function initialize!(integrator, cache::SHLDDRK52Cache) From dd76a4933094e518aeda7f97fa01d19455aace69 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 14:20:50 -0400 Subject: [PATCH 37/45] Update alg_utils.jl --- lib/OrdinaryDiffEqCore/src/alg_utils.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/OrdinaryDiffEqCore/src/alg_utils.jl b/lib/OrdinaryDiffEqCore/src/alg_utils.jl index b8d1fdd9ba..955540f2d6 100644 --- a/lib/OrdinaryDiffEqCore/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqCore/src/alg_utils.jl @@ -345,6 +345,18 @@ qsteady_max_default(alg::OrdinaryDiffEqImplicitAlgorithm) = isadaptive(alg) ? 1 #DiffEqBase.nlsolve_default(::QNDF, ::Val{κ}) = 1//2 # SSP coefficients + +""" + 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 +``` +""" ssp_coefficient(alg) = error("$alg is not a strong stability preserving method.") # We shouldn't do this probably. From 51ead363a6091f01ac7090ed6320b5d66a59fc42 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 14:21:39 -0400 Subject: [PATCH 38/45] Update alg_utils.jl --- lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl b/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl index debbe67f17..a00dc9a13f 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl @@ -31,21 +31,6 @@ alg_order(alg::SSPRK932) = 3 alg_order(alg::SSPRK54) = 4 alg_order(alg::SSPRK104) = 4 -""" - 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 -``` -""" - ssp_coefficient(alg::SSPRK53_2N1) = 2.18 ssp_coefficient(alg::SSPRK53_2N2) = 2.148 ssp_coefficient(alg::SSPRK53) = 2.65 @@ -63,4 +48,4 @@ ssp_coefficient(alg::SSPRK22) = 1 ssp_coefficient(alg::SSPRKMSVS32) = 0.5 ssp_coefficient(alg::SSPRKMSVS43) = 0.33 ssp_coefficient(alg::KYKSSPRK42) = 2.459 -ssp_coefficient(alg::KYK2014DGSSPRK_3S2) = 0.8417 \ No newline at end of file +ssp_coefficient(alg::KYK2014DGSSPRK_3S2) = 0.8417 From 360d5c93835115db564ae57bdad1f6e210faeb16 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 17:48:48 -0400 Subject: [PATCH 39/45] no need to import strip_interpolation --- src/OrdinaryDiffEq.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrdinaryDiffEq.jl b/src/OrdinaryDiffEq.jl index dfafe9b9d3..6e8d63e6f6 100644 --- a/src/OrdinaryDiffEq.jl +++ b/src/OrdinaryDiffEq.jl @@ -58,7 +58,7 @@ import OrdinaryDiffEqCore: trivial_limiter!, CompositeAlgorithm, alg_order, _change_t_via_interpolation!, ODEIntegrator, _ode_interpolant!, current_interpolant, resize_nlsolver!, _ode_interpolant, handle_tstop!, _postamble!, update_uprev!, resize_J_W!, - DAEAlgorithm, get_fsalfirstlast, strip_cache, strip_interpolation + DAEAlgorithm, get_fsalfirstlast, strip_cache export CompositeAlgorithm, ShampineCollocationInit, BrownFullBasicInit, NoInit AutoSwitch From 9529728d0e3345e14c6d77bc871ad9cf9f96d68d Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 24 Aug 2024 17:56:48 -0400 Subject: [PATCH 40/45] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index ef900b0fc0..9194b91f37 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.0" +version = "6.88.1" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" From ff65f68b1490d0dd310b228a4922af6e2f3adf47 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 25 Aug 2024 07:14:09 -0400 Subject: [PATCH 41/45] Update lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl --- .../test/ode_low_storage_rk_tests.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl b/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl index 4b70c66c4e..2ddc6f4401 100644 --- a/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl +++ b/lib/OrdinaryDiffEqLowStorageRK/test/ode_low_storage_rk_tests.jl @@ -64,15 +64,15 @@ dts = 1 .// 2 .^ (8:-1:4) alg = SHLDDRK52() for prob in test_problems_only_time sim = test_convergence(dts, prob, alg) - @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol + @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqLowStorageRK.alg_order(alg) atol=testTol end for prob in test_problems_linear sim = test_convergence(dts, prob, alg) - @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol + @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqLowStorageRK.alg_order(alg) atol=testTol end for prob in test_problems_nonlinear sim = test_convergence(dts, prob, alg) - @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqSSPRK.alg_order(alg) atol=testTol + @test_broken sim.𝒪est[:final]≈OrdinaryDiffEqLowStorageRK.alg_order(alg) atol=testTol end @testset "ORK256" begin From b43e5153e83255f97970e22f28212a4e9806a78e Mon Sep 17 00:00:00 2001 From: ParamThakkar123 Date: Sun, 25 Aug 2024 16:49:13 +0530 Subject: [PATCH 42/45] Changes --- lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl b/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl index 67fb6f03c8..bbb78122c8 100644 --- a/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl +++ b/lib/OrdinaryDiffEqNonlinearSolve/test/newton_tests.jl @@ -1,4 +1,4 @@ -using OrdinaryDiffEq +using OrdinaryDiffEqCore using DiffEqDevTools using DiffEqBase using LineSearches From 533668a1bbf3eec253604e1f4e724adf7e123dd6 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 25 Aug 2024 08:52:32 -0400 Subject: [PATCH 43/45] Update alg_utils.jl --- lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl b/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl index a00dc9a13f..81102dd71e 100644 --- a/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl +++ b/lib/OrdinaryDiffEqSSPRK/src/alg_utils.jl @@ -13,6 +13,7 @@ isfsal(alg::SSPRK932) = false isfsal(alg::SSPRK54) = false isfsal(alg::SSPRK104) = false +alg_order(alg::KYK2014DGSSPRK_3S2) = 2 alg_order(alg::KYKSSPRK42) = 2 alg_order(alg::SSPRKMSVS32) = 2 alg_order(alg::SSPRK33) = 3 From cbe41dd9c18038be20653fa63fd10cad66b03e08 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 25 Aug 2024 12:00:56 -0400 Subject: [PATCH 44/45] Update Project.toml --- lib/OrdinaryDiffEqSSPRK/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OrdinaryDiffEqSSPRK/Project.toml b/lib/OrdinaryDiffEqSSPRK/Project.toml index 4875988c14..faccc02874 100644 --- a/lib/OrdinaryDiffEqSSPRK/Project.toml +++ b/lib/OrdinaryDiffEqSSPRK/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqSSPRK" uuid = "669c94d9-1f4b-4b64-b377-1aa079aa2388" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.2.0" [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" From 5f8f3a035bb5b4ef97441a397020798b40978f94 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sun, 25 Aug 2024 12:01:29 -0400 Subject: [PATCH 45/45] Update Project.toml --- lib/OrdinaryDiffEqLowOrderRK/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OrdinaryDiffEqLowOrderRK/Project.toml b/lib/OrdinaryDiffEqLowOrderRK/Project.toml index 737d7e9e1f..75b4acea91 100644 --- a/lib/OrdinaryDiffEqLowOrderRK/Project.toml +++ b/lib/OrdinaryDiffEqLowOrderRK/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqLowOrderRK" uuid = "1344f307-1e59-4825-a18e-ace9aa3fa4c6" authors = ["ParamThakkar123 "] -version = "1.1.0" +version = "1.2.0" [deps] DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"