|
167 | 167 | @test approx ≈ Γ atol = 1.0e-1 |
168 | 168 | end |
169 | 169 | end |
| 170 | + |
| 171 | +# Regression test for https://github.com/JuliaDynamics/DynamicalSystemsBase.jl/issues/251: |
| 172 | +# the auto-generated diffusion closure used to recompute its (constant) output on every |
| 173 | +# call, allocating ~1 KB per `step!` and dominating long integrations. The closure must |
| 174 | +# now return a precomputed constant with no allocations. |
| 175 | +@testset "auto-diffusion closure is allocation-free (#251)" begin |
| 176 | + f_oop(u, p, t) = SVector{2}(0.0, 0.0) |
| 177 | + f_iip(du, u, p, t) = (du .= 0; nothing) |
| 178 | + Γ = [1.0 0.3; 0.3 1.0] |
| 179 | + |
| 180 | + function call_oop(g, n) |
| 181 | + s = SVector(0.1, 0.2) |
| 182 | + out = SVector(0.0, 0.0) |
| 183 | + for _ in 1:n |
| 184 | + out = g(s, nothing, 0.0) |
| 185 | + end |
| 186 | + return out |
| 187 | + end |
| 188 | + function call_iip!(g, du, n) |
| 189 | + u = [0.0, 0.0] |
| 190 | + for _ in 1:n |
| 191 | + g(du, u, nothing, 0.0) |
| 192 | + end |
| 193 | + return du |
| 194 | + end |
| 195 | + |
| 196 | + @testset "OOP diagonal" begin |
| 197 | + ds = CoupledSDEs(f_oop, SVector(0.0, 0.0); noise_strength = 2.5) |
| 198 | + g = ds.integ.sol.prob.f.g |
| 199 | + @test g(SVector(0.0, 0.0), nothing, 0.0) === g(SVector(1.0, 1.0), nothing, 5.0) |
| 200 | + @test g(SVector(0.0, 0.0), nothing, 0.0) == SVector(2.5, 2.5) |
| 201 | + call_oop(g, 10) # warmup |
| 202 | + @test (@allocated call_oop(g, 10_000)) < 100 |
| 203 | + end |
| 204 | + |
| 205 | + @testset "OOP non-diagonal" begin |
| 206 | + ds = CoupledSDEs(f_oop, SVector(0.0, 0.0); covariance = Γ, noise_strength = 1.5) |
| 207 | + g = ds.integ.sol.prob.f.g |
| 208 | + @test g(SVector(0.0, 0.0), nothing, 0.0) === g(SVector(1.0, 1.0), nothing, 5.0) |
| 209 | + @test g(SVector(0.0, 0.0), nothing, 0.0) ≈ 1.5 .* sqrt(Γ) |
| 210 | + call_oop(g, 10) |
| 211 | + @test (@allocated call_oop(g, 10_000)) < 100 |
| 212 | + end |
| 213 | + |
| 214 | + @testset "IIP diagonal" begin |
| 215 | + ds = CoupledSDEs(f_iip, [0.0, 0.0]; noise_strength = 2.5) |
| 216 | + g = ds.integ.sol.prob.f.g |
| 217 | + du = zeros(2) |
| 218 | + g(du, [0.0, 0.0], nothing, 0.0) |
| 219 | + @test du == [2.5, 2.5] |
| 220 | + call_iip!(g, du, 10) |
| 221 | + @test (@allocated call_iip!(g, du, 10_000)) < 100 |
| 222 | + end |
| 223 | + |
| 224 | + @testset "IIP non-diagonal" begin |
| 225 | + ds = CoupledSDEs(f_iip, [0.0, 0.0]; covariance = Γ, noise_strength = 1.5) |
| 226 | + g = ds.integ.sol.prob.f.g |
| 227 | + DU = zeros(2, 2) |
| 228 | + g(DU, [0.0, 0.0], nothing, 0.0) |
| 229 | + @test DU ≈ 1.5 .* sqrt(Γ) |
| 230 | + function call_iip_mat!(g, DU, n) |
| 231 | + u = [0.0, 0.0] |
| 232 | + for _ in 1:n |
| 233 | + g(DU, u, nothing, 0.0) |
| 234 | + end |
| 235 | + return DU |
| 236 | + end |
| 237 | + call_iip_mat!(g, DU, 10) |
| 238 | + @test (@allocated call_iip_mat!(g, DU, 10_000)) < 100 |
| 239 | + end |
| 240 | +end |
0 commit comments