From eb23f16992ed79a19bf320ba0b577e8bd99373d3 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 12 Jul 2026 21:36:23 -0400 Subject: [PATCH 1/2] Fix callable interpolation builder symtype Register CachedInterpolation's symbolic result as a callable Real-to-Real value, derived through public SymbolicUtils APIs. Add a regression that calls the bound interpolator before building and solving the ODEProblem. Co-Authored-By: Chris Rackauckas --- src/Blocks/Blocks.jl | 1 + src/Blocks/sources.jl | 10 +++++++++- test/sources.jl | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Blocks/Blocks.jl b/src/Blocks/Blocks.jl index 2670de16..e07ec5e8 100644 --- a/src/Blocks/Blocks.jl +++ b/src/Blocks/Blocks.jl @@ -5,6 +5,7 @@ module Blocks using ModelingToolkitBase: ModelingToolkitBase, @component, @connector, @named, @parameters, @unpack, System, compose, connect, extend, getdefault, t_nounits as t, D_nounits as D +using SymbolicUtils: @syms, symtype using Symbolics: Symbolics, @register_symbolic, @variables, Differential, Equation import Base: ifelse import ..@symcheck diff --git a/src/Blocks/sources.jl b/src/Blocks/sources.jl index 9e282d86..e7463a5d 100644 --- a/src/Blocks/sources.jl +++ b/src/Blocks/sources.jl @@ -864,7 +864,15 @@ end Base.nameof(::CachedInterpolation) = :CachedInterpolation -@register_symbolic (f::CachedInterpolation)(u::AbstractArray, x::AbstractArray, args::Tuple) +const _INTERPOLATOR_SYMTYPE = let + @syms interpolator(::Real)::Real + symtype(interpolator) +end + +# Calling the builder returns the interpolation function, not an interpolated scalar. +@register_symbolic (f::CachedInterpolation)( + u::AbstractArray, x::AbstractArray, args::Tuple +)::_INTERPOLATOR_SYMTYPE """ ParametrizedInterpolation(interp_type, u, x, args...; name, t = ModelingToolkitBase.t_nounits) diff --git a/test/sources.jl b/test/sources.jl index 31efad4d..780830e3 100644 --- a/test/sources.jl +++ b/test/sources.jl @@ -14,6 +14,7 @@ using SymbolicIndexingInterface using SciMLStructures: SciMLStructures, Tunable using ForwardDiff using ADTypes +using SymbolicUtils: symtype @testset "Constant" begin @named src = Constant(k = 2) @@ -650,6 +651,9 @@ end @testset "LinearInterpolation" begin @named i = ParametrizedInterpolation(LinearInterpolation, u, x) + interpolator = only(values(bindings(i))) + @test symtype(interpolator(0.0)) === Real + eqs = [i.input.u ~ t, D(y) ~ i.output.u] @named model = System(eqs, t, systems = [i]) From 7a131c93a37a10f44812f6c4eefab4c0a6aaafcb Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 12 Jul 2026 21:55:12 -0400 Subject: [PATCH 2/2] Repair documentation example setup Supply the position-domain initialization equations, bind OnePort's extended names explicitly, and make OrdinaryDiffEqSDIRK a direct documentation dependency for ImplicitEuler. Co-Authored-By: Chris Rackauckas --- docs/Project.toml | 2 ++ docs/src/connectors/connections.md | 3 ++- docs/src/tutorials/custom_component.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 4b65c921..1d95d904 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -7,6 +7,7 @@ IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" ModelingToolkitStandardLibrary = "16a59e39-deab-5bd0-87e4-056b12336739" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +OrdinaryDiffEqSDIRK = "2d112036-d095-4a1e-ab9a-08536f3ecdbf" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" SciCompDSL = "91a8cdf1-4ca6-467b-a780-87fda3fff15e" @@ -19,5 +20,6 @@ IfElse = "0.1" ModelingToolkit = "11" ModelingToolkitStandardLibrary = "2.28.0" OrdinaryDiffEq = "6, 7" +OrdinaryDiffEqSDIRK = "1, 2" Plots = "1.36" SciCompDSL = "1" diff --git a/docs/src/connectors/connections.md b/docs/src/connectors/connections.md index 3af6451c..1e079d46 100644 --- a/docs/src/connectors/connections.md +++ b/docs/src/connectors/connections.md @@ -191,7 +191,8 @@ nothing # hide As can be seen, we get exactly the same result. The only difference here is that we are solving an extra equation, which allows us to plot the body position as well. ```@example connections -prob = ODEProblem(sys, [], (0, 10.0), fully_determined = true) +prob = ODEProblem( + sys, [], (0, 10.0); initialization_eqs = [sys.body.s ~ 0, sys.body.v ~ 1]) sol_p = solve(prob) p1 = plot(sol_p, idxs = [body.v]) diff --git a/docs/src/tutorials/custom_component.md b/docs/src/tutorials/custom_component.md index 5d277b39..6192d6f8 100644 --- a/docs/src/tutorials/custom_component.md +++ b/docs/src/tutorials/custom_component.md @@ -36,7 +36,7 @@ this can almost be directly translated to the syntax of `ModelingToolkit`. ```@example components @mtkmodel NonlinearResistor begin - @extend OnePort() + @extend v, i = oneport = OnePort() @parameters begin Ga Gb @@ -58,7 +58,7 @@ nothing # hide Since the non-linear resistor is essentially a standard electrical component with two ports, we can extend from the `OnePort` component of the library. ```julia -@extend OnePort() +@extend v, i = oneport = OnePort() ``` This extends `OnePort` and unpacks `v` and `i` variables.