Skip to content

Commit 97ef817

Browse files
ChrisRackauckas-ClaudeChrisRackauckasclaude
authored
Import ReturnCode in independentlylinearizedtests.jl (fixes Core test group) (#317)
* Import ReturnCode in independentlylinearizedtests.jl The SciMLTesting v1.2 folder-based harness (#316) runs each test file in its own isolated module. `independentlylinearizedtests.jl` references `ReturnCode.Default` but never imported `ReturnCode`; previously it leaked in from `periodic_tests.jl` because all files shared one module. Import it explicitly from SciMLBase, matching the existing pattern in periodic_tests.jl. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Make integrating_GK_sum_tests.jl self-contained (fixes Core test group) Under the SciMLTesting v1.2 per-file isolated-module harness, the linear- system helpers (simple_linear_system, adjoint_linear[_inplace], analytical_derivative, callback_saving_linear[_inplace], compute_dGdp) are no longer leaked in from integrating_GK_tests.jl, so the file errored with `UndefVarError: `simple_linear_system` not defined`. Define the helpers it uses inline, matching the self-contained pattern of the other Core files. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Read integrator error estimate without the removed EEst field OrdinaryDiffEqCore's ODEIntegrator no longer exposes an `EEst` field; the scalar error estimate now lives on the controller cache (`integrator.controller_cache.EEst`, surfaced there as `get_EEst`). Reading `integrator.EEst` directly threw `FieldError: type ODEIntegrator has no field EEst`, breaking `AdaptiveProbIntsUncertainty` (src/probints.jl, exercised by the Core group's probints.jl) and the AD group's saving_tracker_tests.jl. Add a dependency-free `_integrator_EEst` accessor that uses the `EEst` field when present (older integrators / SDE integrators) and otherwise reads it off the controller cache, keeping DiffEqCallbacks free of an OrdinaryDiffEqCore dependency while supporting both layouts. Apply the same fallback in the AD test. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 78c7413 commit 97ef817

4 files changed

Lines changed: 150 additions & 6 deletions

File tree

src/probints.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# Read the integrator's scalar error estimate. Older integrators stored it as the
2+
# `EEst` field directly; current OrdinaryDiffEqCore moved it onto the controller
3+
# cache (`integrator.controller_cache.EEst`, exposed there as `get_EEst`). Reading
4+
# it this way keeps DiffEqCallbacks free of an OrdinaryDiffEqCore dependency while
5+
# supporting both integrator layouts.
6+
function _integrator_EEst(integrator)
7+
if hasproperty(integrator, :EEst)
8+
return getproperty(integrator, :EEst)
9+
else
10+
return integrator.controller_cache.EEst
11+
end
12+
end
13+
114
struct ProbIntsCache{T}
215
σ::T
316
order::Int
@@ -40,7 +53,7 @@ struct AdaptiveProbIntsCache
4053
order::Int
4154
end
4255
function (p::AdaptiveProbIntsCache)(integrator)
43-
return integrator.u .= integrator.u .+ integrator.EEst * sqrt(integrator.dt^(2 * p.order)) * randn(size(integrator.u))
56+
return integrator.u .= integrator.u .+ _integrator_EEst(integrator) * sqrt(integrator.dt^(2 * p.order)) * randn(size(integrator.u))
4457
end
4558

4659
"""

test/AD/saving_tracker_tests.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ u0 = TrackedArray([1.0f0, 0.0f0, 0.0f0])
3030
tspan = TrackedArray([0.0f0, 1.0f0])
3131
prob = ODEProblem{false}(rober, u0, tspan, p)
3232
saved_values = SavedValues(eltype(tspan), eltype(p))
33-
cb = SavingCallback((u, t, integrator) -> integrator.EEst * integrator.dt, saved_values)
33+
# OrdinaryDiffEqCore's ODEIntegrator no longer has an `EEst` field; the scalar
34+
# error estimate now lives on the controller cache.
35+
eest(integrator) = hasproperty(integrator, :EEst) ? integrator.EEst :
36+
integrator.controller_cache.EEst
37+
cb = SavingCallback((u, t, integrator) -> eest(integrator) * integrator.dt, saved_values)
3438

3539
@test !all(
3640
iszero.(

test/independentlylinearizedtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Test, DiffEqCallbacks
22
using DiffEqCallbacks: sample, store!, IndependentlyLinearizedSolutionChunks, finish!
3+
using SciMLBase: ReturnCode
34

45
@testset "IndependentlyLinearizedSolution" begin
56
ils = IndependentlyLinearizedSolution{Float64, Float64}(

test/integrating_GK_sum_tests.jl

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,136 @@ sol = solve(
2626

2727
#### TESTING ON LINEAR SYSTEM WITH ANALYTICAL SOLUTION ####
2828

29-
# Reuse shared helper functions defined in integrating_GK_tests.jl:
30-
# compute_dGdp, compute_dGdp_nt, simple_linear_system, adjoint_linear,
31-
# adjoint_linear_inplace, analytical_derivative, callback_saving_linear,
32-
# callback_saving_linear_inplace
29+
function compute_dGdp(integrand)
30+
temp = zeros(length(integrand.integrand), length(integrand.integrand[1]))
31+
for i in 1:length(integrand.integrand)
32+
for j in 1:length(integrand.integrand[1])
33+
temp[i, j] = integrand.integrand[i][j]
34+
end
35+
end
36+
return sum(temp, dims = 1)[:]
37+
end
38+
39+
function simple_linear_system(u, p, t)
40+
a, b = p
41+
return [-a * u[2], b * u[1]]
42+
end
43+
44+
function adjoint_linear(u, p, t, sol)
45+
a, b = p
46+
return -[0 b; -a 0] * u - 2.0 * (sol(t) .- 1.0)
47+
end
48+
49+
function adjoint_linear_inplace(du, u, p, t, sol)
50+
a, b = p
51+
return du .= -[0 b; -a 0] * u - 2.0 * (sol(t) .- 1.0)
52+
end
53+
54+
function analytical_derivative(p, t)
55+
a, b = p
56+
d1 = (
57+
b * (
58+
(cos(2t * sqrt(a * b)) - 4cos(t * sqrt(a * b))) / (b * sqrt(a / b)) +
59+
(b * t * cos(2t * sqrt(a * b))) / sqrt(a * b) +
60+
(-4b * t * cos(t * sqrt(a * b))) / sqrt(a * b) +
61+
2(
62+
(2b * t * sin(t * sqrt(a * b))) / sqrt(a * b) +
63+
(-b * t * sin(2t * sqrt(a * b))) / sqrt(a * b)
64+
) * sqrt(a / b)
65+
) +
66+
(b * t * (a + 3b)) / sqrt(a * b) +
67+
(-a * b * t * cos(2t * sqrt(a * b))) / sqrt(a * b) + 3 / sqrt(a / b) +
68+
2t * sqrt(a * b) - sin(2t * sqrt(a * b))
69+
) / (4.0(a^0.5) * (b^1.5)) +
70+
(
71+
(3a * (b / (a^2))) / sqrt(b / a) +
72+
(a * (b / (a^2)) * cos(2t * sqrt(a * b))) / sqrt(b / a) +
73+
(b * t * (b + 3a)) / sqrt(a * b) +
74+
(b * t * (a - b) * cos(2t * sqrt(a * b))) / sqrt(a * b) +
75+
(-4a * (b / (a^2)) * cos(t * sqrt(a * b))) / sqrt(b / a) +
76+
(-4a * b * t * cos(t * sqrt(a * b))) / sqrt(a * b) +
77+
(2a * b * t * sqrt(b / a) * sin(2t * sqrt(a * b))) / sqrt(a * b) +
78+
(-4a * b * t * sqrt(b / a) * sin(t * sqrt(a * b))) / sqrt(a * b) +
79+
6t * sqrt(a * b) + 8sqrt(b / a) * cos(t * sqrt(a * b)) + sin(2t * sqrt(a * b)) -
80+
6sqrt(b / a) - 8sin(t * sqrt(a * b)) - 2sqrt(b / a) * cos(2t * sqrt(a * b))
81+
) /
82+
(4.0(a^1.5) * (b^0.5)) +
83+
(
84+
-2.0(b^1.5) *
85+
(
86+
(
87+
b * (
88+
2(cos(2t * sqrt(a * b)) - 4cos(t * sqrt(a * b))) * sqrt(a / b) +
89+
sin(2t * sqrt(a * b)) - 8sin(t * sqrt(a * b))
90+
) + 6b * sqrt(a / b) +
91+
2t * (a + 3b) * sqrt(a * b) - a * sin(2t * sqrt(a * b))
92+
) / (16.0a * (b^3.0))
93+
)
94+
) /
95+
(a^0.5) -
96+
6.0(a^0.5) * (b^0.5) *
97+
(
98+
(
99+
(a - b) * sin(2t * sqrt(a * b)) + 8a * sqrt(b / a) * cos(t * sqrt(a * b)) +
100+
2t * (b + 3a) * sqrt(a * b) - 6a * sqrt(b / a) - 8a * sin(t * sqrt(a * b)) -
101+
2a * sqrt(b / a) * cos(2t * sqrt(a * b))
102+
) / (16.0b * (a^3.0))
103+
)
104+
d2 = (
105+
b * (
106+
(a * t * cos(2t * sqrt(a * b))) / sqrt(a * b) +
107+
(-(a / (b^2)) * (cos(2t * sqrt(a * b)) - 4cos(t * sqrt(a * b)))) / sqrt(a / b) +
108+
(-4a * t * cos(t * sqrt(a * b))) / sqrt(a * b) +
109+
2(
110+
(2a * t * sin(t * sqrt(a * b))) / sqrt(a * b) +
111+
(-a * t * sin(2t * sqrt(a * b))) / sqrt(a * b)
112+
) * sqrt(a / b)
113+
) +
114+
(-3b * (a / (b^2))) / sqrt(a / b) + (a * t * (a + 3b)) / sqrt(a * b) +
115+
(-t * (a^2) * cos(2t * sqrt(a * b))) / sqrt(a * b) + 6sqrt(a / b) +
116+
2(cos(2t * sqrt(a * b)) - 4cos(t * sqrt(a * b))) * sqrt(a / b) +
117+
6t * sqrt(a * b) + sin(2t * sqrt(a * b)) - 8sin(t * sqrt(a * b))
118+
) /
119+
(4.0(a^0.5) * (b^1.5)) +
120+
(
121+
(4cos(t * sqrt(a * b))) / sqrt(b / a) + (-cos(2t * sqrt(a * b))) / sqrt(b / a) +
122+
(a * t * (b + 3a)) / sqrt(a * b) +
123+
(-4t * (a^2) * cos(t * sqrt(a * b))) / sqrt(a * b) +
124+
(a * t * (a - b) * cos(2t * sqrt(a * b))) / sqrt(a * b) +
125+
(-4t * (a^2) * sqrt(b / a) * sin(t * sqrt(a * b))) / sqrt(a * b) +
126+
(2t * (a^2) * sqrt(b / a) * sin(2t * sqrt(a * b))) / sqrt(a * b) +
127+
-3 / sqrt(b / a) + 2t * sqrt(a * b) - sin(2t * sqrt(a * b))
128+
) /
129+
(4.0(a^1.5) * (b^0.5)) +
130+
(
131+
-2.0(a^1.5) *
132+
(
133+
(
134+
(a - b) * sin(2t * sqrt(a * b)) + 8a * sqrt(b / a) * cos(t * sqrt(a * b)) +
135+
2t * (b + 3a) * sqrt(a * b) - 6a * sqrt(b / a) - 8a * sin(t * sqrt(a * b)) -
136+
2a * sqrt(b / a) * cos(2t * sqrt(a * b))
137+
) / (16.0b * (a^3.0))
138+
)
139+
) / (b^0.5) -
140+
6.0(a^0.5) * (b^0.5) *
141+
(
142+
(
143+
b * (
144+
2(cos(2t * sqrt(a * b)) - 4cos(t * sqrt(a * b))) * sqrt(a / b) +
145+
sin(2t * sqrt(a * b)) - 8sin(t * sqrt(a * b))
146+
) + 6b * sqrt(a / b) +
147+
2t * (a + 3b) * sqrt(a * b) - a * sin(2t * sqrt(a * b))
148+
) / (16.0a * (b^3.0))
149+
)
150+
return [d1, d2]
151+
end
152+
153+
function callback_saving_linear(u, t, integrator, sol)
154+
return -1 .* [-sol(t)[2] 0; 0 sol(t)[1]]' * u
155+
end
156+
function callback_saving_linear_inplace(du, u, t, integrator, sol)
157+
return du .= -1 .* [-sol(t)[2] 0; 0 sol(t)[1]]' * u
158+
end
33159

34160
u0 = [1.0, 1.0] # initial condition
35161
tspan = (0.0, 10.0) # simulation time

0 commit comments

Comments
 (0)