Skip to content

Commit 55e96aa

Browse files
Fix MIRK AD fallback and view flattening
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
1 parent a456d96 commit 55e96aa

4 files changed

Lines changed: 73 additions & 28 deletions

File tree

lib/BoundaryValueDiffEqCore/src/utils.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
_unwrap_val(::Val{B}) where {B} = B
22
_unwrap_val(B) = B
33

4-
recursive_length(x::Vector{<:AbstractArray}) = sum(length, x)
4+
recursive_length(x::AbstractVector{<:AbstractArray}) = sum(length, x)
55
recursive_length(x::Vector{<:DiffCache}) = sum(xᵢ -> length(xᵢ.u), x)
66

7-
function recursive_flatten(x::Vector{<:AbstractArray})
7+
function recursive_flatten(x::AbstractVector{<:AbstractArray})
88
y = zero(first(x), recursive_length(x))
99
recursive_flatten!(y, x)
1010
return y
1111
end
1212

13-
@views function recursive_flatten!(y::AbstractVector, x::Vector{<:AbstractArray})
13+
@views function recursive_flatten!(y::AbstractVector, x::AbstractVector{<:AbstractArray})
1414
i = 0
1515
for xᵢ in x
1616
copyto!(y[(i + 1):(i + length(xᵢ))], xᵢ)
1717
i += length(xᵢ)
1818
end
1919
return y
2020
end
21-
@views function recursive_flatten_twopoint!(y::AbstractVector, x::Vector{<:AbstractArray}, sizes)
21+
@views function recursive_flatten_twopoint!(y::AbstractVector, x::AbstractVector{<:AbstractArray}, sizes)
2222
x_, xiter = first(x), x[2:end]
2323
copyto!(y[1:prod(sizes[1])], x_[1:prod(sizes[1])])
2424
i = prod(sizes[1])
@@ -30,7 +30,7 @@ end
3030
return y
3131
end
3232

33-
@views function recursive_unflatten!(y::Vector{<:AbstractArray}, x::AbstractVector)
33+
@views function recursive_unflatten!(y::AbstractVector{<:AbstractArray}, x::AbstractVector)
3434
i = 0
3535
for yᵢ in y
3636
copyto!(yᵢ, x[(i + 1):(i + length(yᵢ))])

lib/BoundaryValueDiffEqMIRK/src/BoundaryValueDiffEqMIRK.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module BoundaryValueDiffEqMIRK
22

3-
using ADTypes: ADTypes, AutoForwardDiff, AutoSparse
3+
using ADTypes: ADTypes, AutoForwardDiff, AutoSparse, AutoEnzyme, AutoMooncake
44
using ArrayInterface: fast_scalar_indexing
55
using BandedMatrices: BandedMatrix, Ones
66
using BoundaryValueDiffEqCore: BoundaryValueDiffEqCore,
@@ -45,7 +45,7 @@ using SciMLBase: SciMLBase, AbstractDiffEqInterpolation, BVPFunction, BVProblem,
4545
__solve, isinplace, remake, solve
4646
using Setfield: @set!
4747
using Reexport: @reexport
48-
using PreallocationTools: PreallocationTools, get_tmp
48+
using PreallocationTools: PreallocationTools, DiffCache, get_tmp
4949
using PrecompileTools: @compile_workload, @setup_workload
5050
using Preferences: Preferences
5151
using SparseArrays: sparse

lib/BoundaryValueDiffEqMIRK/src/interpolation.jl

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,7 @@ function (s::EvalSol{C})(tval::Number) where {C <: MIRKCache}
224224
dt = cache.mesh_dt[ii]
225225
τ = (tval - t[ii]) / dt
226226
w, _ = interp_weights(τ, alg)
227-
K = __needs_diffcache(alg.jac_alg) ? @view(k_discrete[ii].du[:, 1:stage]) :
228-
@view(k_discrete[ii][:, 1:stage])
227+
K = __mirk_discrete_stage_view(cache, ii, stage)
229228
KI = @view(k_interp.u[ii][1:length_z, 1:(cache.ITU.s_star - stage)])
230229
__maybe_matmul!(@view(z[1:length_z]), K, @view(w[1:stage]))
231230
__maybe_matmul!(@view(z[1:length_z]), KI, @view(w[(stage + 1):cache.ITU.s_star]), true, true)
@@ -256,8 +255,7 @@ function (s::EvalSol{C})(tvals::AbstractArray{<:Number}) where {C <: MIRKCache}
256255
dt = mesh_dt[ii]
257256
τ = (tval - t[ii]) / dt
258257
w, _ = interp_weights(τ, alg)
259-
K = __needs_diffcache(alg.jac_alg) ? @view(k_discrete[ii].du[:, 1:stage]) :
260-
@view(k_discrete[ii][:, 1:stage])
258+
K = __mirk_discrete_stage_view(cache, ii, stage)
261259
KI = @view(k_interp.u[ii][1:length_z, 1:(cache.ITU.s_star - stage)])
262260
__maybe_matmul!(@view(zvals[i][1:length_z]), K, @view(w[1:stage]))
263261
__maybe_matmul!(
@@ -283,14 +281,26 @@ function (s::EvalSol{C})(tval::Number, ::Type{Val{1}}) where {C <: MIRKCache}
283281
dt = mesh_dt[ii]
284282
τ = (tval - t[ii]) / dt
285283
_, w′ = interp_weights(τ, alg)
286-
__maybe_matmul!(z′, @view(k_discrete[ii].du[:, 1:stage]), @view(w′[1:stage]))
284+
__maybe_matmul!(z′, __mirk_discrete_stage_view(cache, ii, stage), @view(w′[1:stage]))
287285
__maybe_matmul!(
288286
z′, @view(k_interp.u[ii][:, 1:(cache.ITU.s_star - stage)]), @view(w′[(stage + 1):cache.ITU.s_star]),
289287
true, true
290288
)
291289
return z′
292290
end
293291

292+
@inline function __mirk_discrete_stage_view(
293+
cache::MIRKCache{iip, T, use_both, DiffCacheNeeded}, ii, stage
294+
) where {iip, T, use_both}
295+
return @view(cache.k_discrete[ii].du[:, 1:stage])
296+
end
297+
298+
@inline function __mirk_discrete_stage_view(
299+
cache::MIRKCache{iip, T, use_both, NoDiffCacheNeeded}, ii, stage
300+
) where {iip, T, use_both}
301+
return @view(cache.k_discrete[ii][:, 1:stage])
302+
end
303+
294304
"""
295305
interp_setup!(cache::MIRKCache)
296306

lib/BoundaryValueDiffEqMIRK/src/mirk.jl

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function SciMLBase.__init(
5151
verbose_spec = _process_verbose_param(verbose)
5252
@set! alg.jac_alg = concrete_jacobian_algorithm(alg.jac_alg, prob, alg)
5353
iip = isinplace(prob)
54-
diffcache = __cache_trait(alg.jac_alg)
54+
diffcache = __mirk_iip_cache_trait(Val(iip), alg.jac_alg)
5555
@assert (iip || isnothing(alg.optimize)) "Out-of-place constraints don't allow optimization solvers "
5656

5757
tune_parameters = haskey(prob.kwargs, :tune_parameters)
@@ -74,7 +74,9 @@ function SciMLBase.__init(
7474
mesh_dt = diff(mesh)
7575

7676
chunksize = pickchunksize(N * (Nig - 1))
77-
__alloc = @closure x -> __maybe_allocate_diffcache(vec(zero(x)), chunksize, alg.jac_alg)
77+
__alloc = @closure x -> __mirk_iip_maybe_allocate_diffcache(
78+
vec(zero(x)), chunksize, Val(iip), alg.jac_alg
79+
)
7880

7981
fᵢ_cache = __alloc(zero(u0))
8082
fᵢ₂_cache = vec(zero(u0))
@@ -91,12 +93,16 @@ function SciMLBase.__init(
9193

9294
k_discrete = if !constraint
9395
[
94-
__maybe_allocate_diffcache(safe_similar(u0, N, stage), chunksize, alg.jac_alg)
96+
__mirk_iip_maybe_allocate_diffcache(
97+
safe_similar(u0, N, stage), chunksize, Val(iip), alg.jac_alg
98+
)
9599
for _ in 1:Nig
96100
]
97101
else
98102
[
99-
__maybe_allocate_diffcache(safe_similar(u0, L_f_prototype, stage), chunksize, alg.jac_alg)
103+
__mirk_iip_maybe_allocate_diffcache(
104+
safe_similar(u0, L_f_prototype, stage), chunksize, Val(iip), alg.jac_alg
105+
)
100106
for _ in 1:Nig
101107
]
102108
end
@@ -391,6 +397,33 @@ function __construct_problem(cache::MIRKCache{iip}, y::AbstractVector, y₀::Abs
391397
return __construct_problem(cache, y, y₀, Val(constraint))
392398
end
393399

400+
__mirk_iip_ad_diffmode(::Val{true}, ::AutoEnzyme) = AutoForwardDiff()
401+
__mirk_iip_ad_diffmode(::Val{true}, ::AutoMooncake) = AutoForwardDiff()
402+
function __mirk_iip_ad_diffmode(iip, diffmode::AutoSparse)
403+
return AutoSparse(
404+
__mirk_iip_ad_diffmode(iip, get_dense_ad(diffmode));
405+
sparsity_detector = __default_sparsity_detector(diffmode),
406+
coloring_algorithm = __default_coloring_algorithm(diffmode)
407+
)
408+
end
409+
__mirk_iip_ad_diffmode(_, diffmode) = diffmode
410+
411+
__mirk_iip_needs_diffcache(iip, diffmode::AutoSparse) = __mirk_iip_needs_diffcache(
412+
iip, get_dense_ad(diffmode)
413+
)
414+
__mirk_iip_needs_diffcache(iip, diffmode) = __needs_diffcache(__mirk_iip_ad_diffmode(iip, diffmode))
415+
function __mirk_iip_needs_diffcache(iip, jac_alg::BVPJacobianAlgorithm)
416+
return __mirk_iip_needs_diffcache(iip, jac_alg.diffmode) ||
417+
__mirk_iip_needs_diffcache(iip, jac_alg.bc_diffmode) ||
418+
__mirk_iip_needs_diffcache(iip, jac_alg.nonbc_diffmode)
419+
end
420+
__mirk_iip_cache_trait(iip, jac_alg) = __mirk_iip_needs_diffcache(iip, jac_alg) ?
421+
DiffCacheNeeded() : NoDiffCacheNeeded()
422+
function __mirk_iip_maybe_allocate_diffcache(x, chunksize, iip, jac_alg)
423+
return __mirk_iip_needs_diffcache(iip, jac_alg) ?
424+
DiffCache(x, chunksize; warn_on_resize = false) : x
425+
end
426+
394427
function __construct_problem(
395428
cache::MIRKCache{iip}, y::AbstractVector,
396429
y₀::AbstractVectorOfArray, constraint
@@ -400,7 +433,7 @@ function __construct_problem(
400433

401434
eval_sol = EvalSol(__restructure_sol(y₀.u, cache.in_size), cache.mesh, cache)
402435

403-
trait = __cache_trait(jac_alg)
436+
trait = __mirk_iip_cache_trait(Val(iip), jac_alg)
404437

405438
loss_bc = if iip
406439
@closure (
@@ -614,7 +647,7 @@ function __construct_problem(
614647
) where {iip, T, UB, DC, tune_parameters, BC, C, LF}
615648
(; jac_alg) = cache.alg
616649
(; f_prototype, bcresid_prototype, prob) = cache
617-
(; bc_diffmode) = jac_alg
650+
bc_diffmode = __mirk_iip_ad_diffmode(Val(iip), jac_alg.bc_diffmode)
618651
N = length(cache.mesh)
619652

620653
resid_bc = bcresid_prototype
@@ -623,7 +656,8 @@ function __construct_problem(
623656
resid_collocation = safe_similar(y, L_f_prototype * (N - 1))
624657
loss_bc_ad = if iip
625658
@closure (u, p) -> __mirk_loss_bc_iip_ad(
626-
u, p, StandardBVProblem(), cache.bc, cache.y, cache.mesh, cache, __cache_trait(jac_alg)
659+
u, p, StandardBVProblem(), cache.bc, cache.y, cache.mesh, cache,
660+
__mirk_iip_cache_trait(Val(iip), jac_alg)
627661
)
628662
else
629663
loss_bc
@@ -634,7 +668,7 @@ function __construct_problem(
634668
)
635669

636670
nonbc_diffmode = AutoSparse(
637-
get_dense_ad(jac_alg.nonbc_diffmode),
671+
__mirk_iip_ad_diffmode(Val(iip), get_dense_ad(jac_alg.nonbc_diffmode)),
638672
sparsity_detector = __default_sparsity_detector(jac_alg.nonbc_diffmode),
639673
coloring_algorithm = __default_coloring_algorithm(jac_alg.nonbc_diffmode)
640674
)
@@ -700,7 +734,7 @@ function __construct_problem(
700734
) where {iip, T, UB, DC, tune_parameters, BC, C, LF}
701735
(; jac_alg) = cache.alg
702736
(; f_prototype, bcresid_prototype, prob) = cache
703-
(; bc_diffmode) = jac_alg
737+
bc_diffmode = __mirk_iip_ad_diffmode(Val(iip), jac_alg.bc_diffmode)
704738
N = length(cache.mesh)
705739

706740
resid_bc = bcresid_prototype
@@ -709,7 +743,8 @@ function __construct_problem(
709743
resid_prototype = vcat(resid_bc, resid_collocation)
710744
loss_bc_ad = if iip
711745
@closure (u, p) -> __mirk_loss_bc_iip_ad(
712-
u, p, StandardBVProblem(), cache.bc, cache.y, cache.mesh, cache, __cache_trait(jac_alg)
746+
u, p, StandardBVProblem(), cache.bc, cache.y, cache.mesh, cache,
747+
__mirk_iip_cache_trait(Val(iip), jac_alg)
713748
)
714749
else
715750
loss_bc
@@ -736,13 +771,13 @@ function __construct_problem(
736771
)
737772
end
738773
AutoSparse(
739-
get_dense_ad(jac_alg.nonbc_diffmode);
774+
__mirk_iip_ad_diffmode(Val(iip), get_dense_ad(jac_alg.nonbc_diffmode));
740775
sparsity_detector = ADTypes.KnownJacobianSparsityDetector(sparse_jacobian_prototype),
741776
coloring_algorithm = __default_coloring_algorithm(jac_alg.nonbc_diffmode)
742777
)
743778
else
744779
J_full_band = nothing
745-
jac_alg.nonbc_diffmode
780+
__mirk_iip_ad_diffmode(Val(iip), jac_alg.nonbc_diffmode)
746781
end
747782

748783
cache_collocation = if iip
@@ -903,12 +938,12 @@ function __construct_problem(
903938

904939
diffmode = if jac_alg.diffmode isa AutoSparse
905940
AutoSparse(
906-
get_dense_ad(jac_alg.diffmode);
941+
__mirk_iip_ad_diffmode(Val(iip), get_dense_ad(jac_alg.diffmode));
907942
sparsity_detector = __default_sparsity_detector(jac_alg.diffmode),
908943
coloring_algorithm = __default_coloring_algorithm(jac_alg.diffmode)
909944
)
910945
else
911-
jac_alg.diffmode
946+
__mirk_iip_ad_diffmode(Val(iip), jac_alg.diffmode)
912947
end
913948

914949
diffcache = if iip
@@ -970,12 +1005,12 @@ function __construct_problem(
9701005
@view(bcresid_prototype[(prod(cache.resid_size[1]) + 1):end]), cache.M, N
9711006
)
9721007
AutoSparse(
973-
get_dense_ad(jac_alg.diffmode);
1008+
__mirk_iip_ad_diffmode(Val(iip), get_dense_ad(jac_alg.diffmode));
9741009
sparsity_detector = ADTypes.KnownJacobianSparsityDetector(sparse_jacobian_prototype),
9751010
coloring_algorithm = __default_coloring_algorithm(jac_alg.diffmode)
9761011
)
9771012
else
978-
jac_alg.diffmode
1013+
__mirk_iip_ad_diffmode(Val(iip), jac_alg.diffmode)
9791014
end
9801015

9811016
diffcache = if iip

0 commit comments

Comments
 (0)