diff --git a/lib/ModelingToolkitBase/src/systems/problem_utils.jl b/lib/ModelingToolkitBase/src/systems/problem_utils.jl index 30e3b0f63a..f80bacc037 100644 --- a/lib/ModelingToolkitBase/src/systems/problem_utils.jl +++ b/lib/ModelingToolkitBase/src/systems/problem_utils.jl @@ -1113,8 +1113,12 @@ function (recon::MTKParametersReconstructor)(src, dst) if !iszero(diffcache_buffer_idx) @set! nonnumerics[diffcache_buffer_idx] = DiffCacheAllocatorAPIWrapper{ForwardDiff.valtype(eltype(initialvals))}.(nonnumerics[diffcache_buffer_idx]) end + # This `convert` exists because a `Real` discrete might get its value from an + # integer function of integer parameters/discretes. This ends up creating a + # `BlockedArray{Int, ...}` instead of a `BlockedArray{Float64, ...}`. return MTKParameters( - tunablevals, initialvals, recon.discretes_fn(src), + tunablevals, initialvals, + convert(typeof(parameter_values(dst).discrete), recon.discretes_fn(src)), recon.consts_fn(src), nonnumerics, oldcache isa Tuple{} ? () : copy.(oldcache) ) end diff --git a/lib/ModelingToolkitBase/test/initial_values.jl b/lib/ModelingToolkitBase/test/initial_values.jl index 8f7bfea050..ecdea95ae0 100644 --- a/lib/ModelingToolkitBase/test/initial_values.jl +++ b/lib/ModelingToolkitBase/test/initial_values.jl @@ -474,4 +474,24 @@ if !@isdefined(ModelingToolkit) sys′ = ModelingToolkitBase.subset_tunables(mtkcompile(sys), []) @test_nowarn ODEProblem(sys′, [], (0.0, 1.0)) end + + @testset "`Real` discrete obtained via `Int` in initialization" begin + @variables x(t) + @parameters a::Int b + @discretes d(t) + # `d` must be a discrete, it should be bound to an integer, and the + # initialization must be non-trivial. + @mtkcompile sys = System( + [D(x) ~ d + a + b], t; + bindings = [d => a], + continuous_events = ModelingToolkitBase.SymbolicContinuousCallback( + [x ~ 3], [d ~ Pre(d) + 1]; discrete_parameters = d + ), initialization_eqs = [b^2 ~ 2a] + ) + prob = ODEProblem(sys, [x => 1, a => 1], (0.0, 3.0)) + # This would build a `BlockedVector{Int, ...}` for the discretes, since `d` + # is obtained via `a`. However, `prob.p` contains a `BlockedVector{Float64, ..}` + # and this type mismatch causes an error. + @test_nowarn solve(prob, Tsit5()) + end end