Skip to content

Commit 6c1eac1

Browse files
Fix __resize! on AbstractVectorOfArray under RecursiveArrayTools v4
Closes #484. `__resize!(::AbstractVectorOfArray, n, M)` was missed by the SciMLBase-v3 / RecursiveArrayTools-v4 compatibility patch (bea82b8). Under RAT v4, `AbstractVectorOfArray` subtypes `AbstractArray` with column-major linear-indexing semantics, so: - `length(x)` is now the total scalar count (`prod(size(x))`), not the number of timesteps. - `last(x)` is now the last scalar, not the last timestep vector. - `append!(x, ::AbstractVectorOfArray)` falls back to the generic AbstractArray `append!`, which iterates scalars rather than timestep vectors. The old code in `__resize!`: N = n - length(x) N > 0 ? append!(x, VectorOfArray([safe_similar(last(x)) for _ in 1:N])) : resize!(x, n) silently miscomputes `N` (target timesteps minus scalar count) and never grows `x.u`, so subsequent `cache.y₀.u[i]` reads on the post-mesh-refinement loop in MIRK / FIRK hit `#undef` and throw `UndefRefError` from `mirk.jl:342` (`firk.jl` analog). Switch to `x.u` for both `length` and `last`, and `append!` directly into `x.u` instead of constructing a wrapper `VectorOfArray`. `resize!(x, n)` already delegates to `resize!(x.u, n)` in RAT v4 and is left as-is. The same pattern fix applies to the FIRK-specific overloads in `BoundaryValueDiffEqFIRK/src/utils.jl` for both `FIRKTableau{false}` and `FIRKTableau{true}`. Adds a regression test based on the issue MWE (torus geodesic BVP that triggers adaptive mesh refinement). Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
1 parent e0cd15b commit 6c1eac1

4 files changed

Lines changed: 43 additions & 7 deletions

File tree

lib/BoundaryValueDiffEqCore/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "BoundaryValueDiffEqCore"
22
uuid = "56b672f2-a5fe-4263-ab2d-da677488eb3a"
3-
version = "2.5.0"
3+
version = "2.5.1"
44
authors = ["Qingyu Qu <erikqqy123@gmail.com>"]
55

66
[deps]

lib/BoundaryValueDiffEqCore/src/utils.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,9 @@ function __resize!(x::AbstractVector{<:DiffCache}, n, M)
262262
end
263263

264264
function __resize!(x::AbstractVectorOfArray, n, M)
265-
N = n - length(x)
265+
N = n - length(x.u)
266266
N == 0 && return x
267-
N > 0 ? append!(x, VectorOfArray([safe_similar(last(x)) for _ in 1:N])) : resize!(x, n)
267+
N > 0 ? append!(x.u, [safe_similar(last(x.u)) for _ in 1:N]) : resize!(x, n)
268268
return x
269269
end
270270

lib/BoundaryValueDiffEqFIRK/src/utils.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ end
2424

2525
function BoundaryValueDiffEqCore.__resize!(x::AbstractVectorOfArray, n, M, TU::FIRKTableau{false})
2626
(; s) = TU
27-
N = (n - 1) * (s + 1) + 1 - length(x)
27+
N = (n - 1) * (s + 1) + 1 - length(x.u)
2828
N == 0 && return x
29-
N > 0 ? append!(x, VectorOfArray([safe_similar(last(x)) for _ in 1:N])) :
29+
N > 0 ? append!(x.u, [safe_similar(last(x.u)) for _ in 1:N]) :
3030
resize!(x, (n - 1) * (s + 1) + 1)
3131
return x
3232
end
3333

3434
function BoundaryValueDiffEqCore.__resize!(x::AbstractVectorOfArray, n, M, TU::FIRKTableau{true})
3535
(; s) = TU
36-
N = n - length(x)
36+
N = n - length(x.u)
3737
N == 0 && return x
38-
N > 0 ? append!(x, VectorOfArray([safe_similar(last(x)) for _ in 1:N])) : resize!(x, n)
38+
N > 0 ? append!(x.u, [safe_similar(last(x.u)) for _ in 1:N]) : resize!(x, n)
3939
return x
4040
end
4141
@inline __K0_on_u0(

lib/BoundaryValueDiffEqMIRK/test/mirk_basic_tests.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,3 +687,39 @@ end
687687
sol2 = solve(bvp2, MIRK4(), dt = 0.1, adaptive = false, nlsolve_kwargs = (; maxiters = 0))
688688
@test sol2.u == u_guess
689689
end
690+
691+
# https://github.com/SciML/BoundaryValueDiffEq.jl/issues/484
692+
# Adaptive mesh refinement on a sufficiently nonlinear BVP must not throw
693+
# UndefRefError. The torus geodesic system is smooth and nonlinear enough
694+
# that the solver decides to refine the mesh.
695+
@testitem "Adaptive mesh refinement (issue 484)" begin
696+
using BoundaryValueDiffEqMIRK
697+
698+
R = 3.0
699+
r = 2.0
700+
701+
function f!(du, u, p, t)
702+
sinθ, cosθ = sincos(u[1])
703+
R_θ = R + r * cosθ
704+
du[1] = u[3]
705+
du[2] = u[4]
706+
du[3] = -u[4]^2 * R_θ * sinθ / r
707+
du[4] = 2 * r * sinθ / R_θ * u[3] * u[4]
708+
end
709+
710+
a1 = [0.5, -1.2]
711+
a2 = [-0.5, 0.3]
712+
713+
function bc!(residual, u, p, t)
714+
ua = u(0.0)
715+
ub = u(1.0)
716+
residual[1:2] = ua[1:2] - a1
717+
residual[3:4] = ub[1:2] - a2
718+
end
719+
720+
prob = BVProblem(f!, bc!, vcat(a1, zero(a1)), (0.0, 1.0))
721+
sol = solve(prob, MIRK4(); dt = 0.05)
722+
@test SciMLBase.successful_retcode(sol)
723+
@test sol.u[1][1:2] a1 atol = 1.0e-8
724+
@test sol.u[end][1:2] a2 atol = 1.0e-8
725+
end

0 commit comments

Comments
 (0)