Skip to content

Bounds error when assertion is applied to input in a flow-like system in isolation #3954

@TicTac127

Description

@TicTac127

Describe the bug 🐞

When adding an assertion to a flow-like system boundary, and running the system in isolation, a BoundsError is thrown when constructing the problem.

Expected behavior

Unsure? At least a more helpful error message.

Minimal Reproducible Example 👇

using ModelingToolkit, OrdinaryDiffEq
using ModelingToolkit: t_nounits as t, D_nounits as D

@variables y(t) u(t)
@named flow = System([y ~ 2*u], t; assertions = [(u > 0.0) => "Oops!"])

combined = compose(System([flow.u ~ -t], t; name = :combined), flow)
combined = mtkcompile(combined)
prob = ODEProblem(combined, [], (0.0, 10.0))
sol = OrdinaryDiffEq.solve(prob, ROS3P())

Error & Stacktrace ⚠️

julia> include("bounds_err.jl")
WARNING: import of ModelingToolkit.t_nounits into Main conflicts with an existing identifier; ignored.
ERROR: LoadError: BoundsError: attempt to access 0-element Vector{Any} at index [0]
Stacktrace:
  [1] throw_boundserror(A::Vector{Any}, I::Tuple{Int64})
    @ Base ./essentials.jl:14
  [2] getindex(A::Vector{Any}, i::Int64)
    @ Base ./essentials.jl:916
  [3] generate_rhs(sys::System; implicit_dae::Bool, scalar::Bool, expression::Type, wrap_gfw::Type, eval_expression::Bool, eval_module::Module, override_discrete::Bool, kwargs::@Kwargs{})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/kD28h/src/systems/codegen.jl:76
  [4] (ODEFunction{})(sys::System; u0::Nothing, p::MTKParameters{…}, tgrad::Bool, jac::Bool, t::Nothing, eval_expression::Bool, eval_module::Module, sparse::Bool, steady_state::Bool, checkbounds::Bool, sparsity::Bool, analytic::Nothing, simplify::Bool, cse::Bool, initialization_data::SciMLBase.OverrideInitData{…}, expression::Type, check_compatibility::Bool, nlstep::Bool, nlstep_compile::Bool, nlstep_scc::Bool, kwargs::@Kwargs{})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/kD28h/src/problems/odeproblem.jl:11
  [5] process_SciMLProblem(constructor::Type, sys::System, op::Vector{…}; build_initializeprob::Bool, implicit_dae::Bool, t::Float64, guesses::Dict{…}, warn_initialize_determined::Bool, initialization_eqs::Vector{…}, eval_expression::Bool, eval_module::Module, fully_determined::Nothing, check_initialization_units::Bool, u0_eltype::Nothing, tofloat::Bool, u0_constructor::typeof(identity), p_constructor::typeof(identity), check_length::Bool, symbolic_u0::Bool, warn_cyclic_dependency::Bool, circular_dependency_max_cycle_length::Int64, circular_dependency_max_cycles::Int64, substitution_limit::Int64, use_scc::Bool, time_dependent_init::Bool, algebraic_only::Bool, allow_incomplete::Bool, is_initializeprob::Bool, kwargs::@Kwargs{})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/kD28h/src/systems/problem_utils.jl:1476
  [6] (ODEProblem{})(sys::System, op::Vector{…}, tspan::Tuple{…}; callback::Nothing, check_length::Bool, eval_expression::Bool, expression::Type, eval_module::Module, check_compatibility::Bool, kwargs::@Kwargs{})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/kD28h/src/problems/odeproblem.jl:81
  [7] ODEProblem
    @ ~/.julia/packages/ModelingToolkit/kD28h/src/problems/odeproblem.jl:73 [inlined]
  [8] ODEProblem
    @ ./none:0 [inlined]
  [9] ODEProblem(sys::System, op::Vector{Any}, tspan::Tuple{Float64, Float64})
    @ ModelingToolkit ./none:0
 [10] top-level scope
    @ ~/projects/julia/ControlsWebsite.jl/bounds_err.jl:9
in expression starting at /home/tictac/projects/julia/cwx.jl/bounds_err.jl:9
Some type information was truncated. Use `show(err)` to see complete types.

Environment (please complete the following information):

  • Output of using Pkg; Pkg.status()
Status `~/projects/julia/cwx.jl/Project.toml`
  [e084ae63] CoolProp v0.2.2
  [82cc6244] DataInterpolations v8.6.1
  [a98d9a8b] Interpolations v0.16.2
  [961ee093] ModelingToolkit v10.24.0
  [429524aa] Optim v1.13.2
  [1dea7af3] OrdinaryDiffEq v6.102.1
  [a03496cd] PlotlyBase v0.8.21
  [f2990250] PlotlyKaleido v2.3.0
  [592b5752] Trapz v2.0.3
  • Output of versioninfo()
Julia Version 1.11.7
Commit f2b3dbda30a (2025-09-08 12:10 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 16 × AMD Ryzen 7 7800X3D 8-Core Processor
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, znver4)
Threads: 1 default, 0 interactive, 1 GC (on 16 virtual cores)
Environment:
  JULIA_EDITOR = code
  JULIA_VSCODE_REPL = 1

Additional context

I ran into this problem when trying to hunt down a bug in a system. I was trying to add assertions to the boundary of a commonly used system which acts as a flow, but kept getting this error when trying to unit test the connector in isolation. This error doesn't get thrown when using the connector in a larger context.

Curiously, if you change the MWE to

using ModelingToolkit, OrdinaryDiffEq
using ModelingToolkit: t_nounits as t, D_nounits as D

@variables y(t) u(t)
@named flow = System([D(y) ~ 2*u], t; assertions = [(u > 0.0) => "Oops!"]) # < ---------- Now has a derivative.

combined = compose(System([flow.u ~ -t], t; name = :combined), flow)
combined = mtkcompile(combined)
prob = ODEProblem(combined, [flow.y => 1.0], (0.0, 10.0)) # < ----------- Initial Condition
sol = OrdinaryDiffEq.solve(prob, ROS3P())

the model doesn't throw the BoundsError, and the problem properly halts at 0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions