diff --git a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl index a62c6b0462..03557a12d3 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/rosenbrock_perform_step.jl @@ -1240,7 +1240,7 @@ end linsolve_tmp = @.. du + dtd[1] * dT k1 = _reshape(W \ -_vec(linsolve_tmp), axes(uprev)) # constant number for type stability make sure this is greater than num_stages - ks = ntuple(Returns(k1), 20) + ks = ntuple(Returns(k1), Val(20)) # Loop for stages for stage in 2:num_stages u = uprev diff --git a/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl b/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl index 5d4f2a131c..4eceacb59b 100644 --- a/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl +++ b/lib/OrdinaryDiffEqRosenbrock/src/stiff_addsteps.jl @@ -85,7 +85,7 @@ function _ode_addsteps!(k, t, uprev, u, dt, f, p, cache::RosenbrockCombinedConst linsolve_tmp = @.. du + dtd[1] * dT k1 = _reshape(W \ _vec(linsolve_tmp), axes(uprev)) # constant number for type stability make sure this is greater than num_stages - ks = ntuple(Returns(k1), 20) + ks = ntuple(Returns(k1), Val(20)) # Last stage affect's ks for Rodas5,5P,6P for stage in 2:num_stages u = uprev diff --git a/lib/OrdinaryDiffEqRosenbrock/test/allocation_tests.jl b/lib/OrdinaryDiffEqRosenbrock/test/allocation_tests.jl index 911b472062..8cd370f0ab 100644 --- a/lib/OrdinaryDiffEqRosenbrock/test/allocation_tests.jl +++ b/lib/OrdinaryDiffEqRosenbrock/test/allocation_tests.jl @@ -12,32 +12,41 @@ Currently, Rosenbrock solvers are allocating and marked with @test_broken. @testset "Rosenbrock Allocation Tests" begin # Test problem - use a simple linear problem for stiff solvers linear_prob = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0)) - + # Vector problem function simple_system!(du, u, p, t) du[1] = -0.5 * u[1] du[2] = -1.5 * u[2] end vector_prob = ODEProblem(simple_system!, [1.0, 1.0], (0.0, 1.0)) - - # Test all exported Rosenbrock solvers for allocation-free behavior - rosenbrock_solvers = [Rosenbrock23(), Rosenbrock32(), RosShamp4(), Veldd4(), Velds4(), GRK4T(), GRK4A(), - Rodas3(), Rodas23W(), Rodas3P(), Rodas4(), Rodas42(), Rodas4P(), Rodas4P2(), Rodas5(), - Rodas5P(), Rodas5Pe(), Rodas5Pr(), Rodas6P()] - + + # Test all exported Rosenbrock solvers for allocation-free behavior + rosenbrock_solvers = [ + Rosenbrock23(), Rosenbrock32(), RosShamp4(), Veldd4(), Velds4(), GRK4T(), GRK4A(), + Rodas3(), Rodas23W(), Rodas3P(), Rodas4(), Rodas42(), Rodas4P(), Rodas4P2(), Rodas5(), + Rodas5P(), Rodas5Pe(), Rodas5Pr(), Rodas6P()] + @testset "Rosenbrock Solver Allocation Analysis" begin for solver in rosenbrock_solvers @testset "$(typeof(solver)) allocation check" begin - integrator = init(linear_prob, solver, dt=0.1, save_everystep=false, abstol=1e-6, reltol=1e-6) + integrator = init(linear_prob, solver, dt = 0.1, + save_everystep = false, abstol = 1e-6, reltol = 1e-6) step!(integrator) # Setup step may allocate - + # Use AllocCheck for accurate allocation detection allocs = check_allocs(step!, (typeof(integrator),)) - + # These solvers should be allocation-free, but mark as broken for now # to verify with AllocCheck (more accurate than @allocated) @test_broken length(allocs) == 0 - + + # However, we don't want to allow any dynamic dispatch from this module + @test count( + t -> t isa AllocCheck.DynamicDispatch && + any(s -> contains(string(s.file), "Rosenbrock"), t.backtrace), + allocs + ) == 0 + if length(allocs) > 0 println("AllocCheck found $(length(allocs)) allocation sites in $(typeof(solver)) step!:") for (i, alloc) in enumerate(allocs[1:min(3, end)]) # Show first 3 @@ -49,4 +58,4 @@ Currently, Rosenbrock solvers are allocating and marked with @test_broken. end end end -end \ No newline at end of file +end