@@ -1163,6 +1163,46 @@ end
11631163safe_float (x) = x
11641164safe_float (x:: AbstractArray ) = isempty (x) ? x : float (x)
11651165
1166+ """
1167+ PromoteToTunableEltype(observed, floatT)
1168+
1169+ Wraps an `initializeprob` observed function so its output array is promoted to an
1170+ eltype compatible with the current tunable parameters. Addresses the case where
1171+ the observed function is generated from fully constant RHS (e.g. `initialization_eqs
1172+ = [s ~ 0]`): the resulting `create_array(Array, nothing, …, 0, 0)` would otherwise
1173+ produce `Vector{Int64}`, which — when downstream `remake` reinstalls it as `u0` —
1174+ silently defeats ForwardDiff/Tracker/Measurements promotion of `u0`.
1175+
1176+ `floatT` is the static floor (the same `floatT` the rest of the construction pipeline
1177+ commits to, derived from the user's varmap). It guarantees integer RHS gets lifted
1178+ to a float without overriding the user's chosen precision (e.g. `Float32`). The
1179+ dynamic tunable eltype is read fresh from `parameter_values(nlsol)` on every call,
1180+ so a later `remake` with `ForwardDiff.Dual` parameters still wins via `promote_type`.
1181+ """
1182+ struct PromoteToTunableEltype{F, floatT}
1183+ observed:: F
1184+ end
1185+
1186+ PromoteToTunableEltype (observed, :: Type{T} ) where {T} =
1187+ PromoteToTunableEltype {typeof(observed), T} (observed)
1188+
1189+ function (p:: PromoteToTunableEltype{F, floatT} )(nlsol) where {F, floatT}
1190+ raw = p. observed (nlsol)
1191+ raw isa AbstractArray || return raw
1192+ isempty (raw) && return raw
1193+ T = promote_type (eltype (raw), _tunable_eltype (parameter_values (nlsol)), floatT)
1194+ T === eltype (raw) ? raw : convert (AbstractArray{T}, raw)
1195+ end
1196+
1197+ _tunable_eltype (p:: MTKParameters ) = isempty (p. tunable) ? Bool : eltype (p. tunable)
1198+ function _tunable_eltype (p)
1199+ if SciMLStructures. isscimlstructure (p)
1200+ tun = SciMLStructures. canonicalize (SciMLStructures. Tunable (), p)[1 ]
1201+ return isempty (tun) ? Bool : eltype (tun)
1202+ end
1203+ return Bool
1204+ end
1205+
11661206"""
11671207 $(TYPEDSIGNATURES)
11681208
@@ -1262,8 +1302,8 @@ function maybe_build_initialization_problem(
12621302 if isempty (solved_unknowns)
12631303 initializeprobmap = nothing
12641304 else
1265- initializeprobmap = u0_constructor ∘ safe_float ∘
1266- getu (initializeprob, solved_unknowns)
1305+ initializeprobmap = u0_constructor ∘ PromoteToTunableEltype (
1306+ getu (initializeprob, solved_unknowns), floatT)
12671307 end
12681308 else
12691309 initializeprobmap = nothing
0 commit comments