# Slow indexing of constant-valued variables in MTK

**URL:** <https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922>\
**Category:** Modelling & Simulations\
**Tags:** question, modelingtoolkit\
**Created:** [October 4, 2024, 2:50pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922 "2024-10-04T14:50:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![bspanoghe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bspanoghe/32/209460_2.png) [@bspanoghe](https://discourse.julialang.org/u/bspanoghe)\
**Post date:** [October 4, 2024, 2:50pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/1 "2024-10-04T14:50:55Z")

</div>

Hi

I’m currently working with large hierarchical models in ModelingToolkit.jl and found that indexing the solution with constant-valued variables becomes incredibly slow for larger systems. This results in plotting of the solution taking multiple minutes whereas the actual solving only takes seconds.

Replacing this variable with a parameter or constant is the obvious solution (and does reduce the indexing time to normal levels), but doesn’t seem like an option for my case as the constant-valued variable in question is actually only constant for some subsystems and variable in others.

Please consider the below MWE, where `B` serves as the constant-valued variable:

```julia
using ModelingToolkit, OrdinaryDiffEq
import ModelingToolkit: t_nounits as t, D

n = 1000
@variables A(t)[1:n] = zeros(n) B(t)[1:n]
@parameters B_val[1:n] = rand(n)

eqs = [
    # some complex equation for A
    [D(A[i]) ~ sin(t + B[i]) for i in eachindex(A)]...,
    # constant value for B - in reality some B also have complex eqs
    [B[i] ~ B_val[i] for i in eachindex(B)]...,
]

@named sys = ODESystem(eqs, t)
sys_simpl = structural_simplify(sys);
prob = ODEProblem(sys_simpl, [], (0.0, 100))
sol = solve(prob);

@time sol[A[rand(1:n)]]; # ~0.0002s
@time sol[B[rand(1:n)]]; # ~0.8s

```

I feel like I must be doing something incredibly dumb but can’t figure it out. Any help would be greatly appreciated.

I’m using Julia 1.10.4 with following package versions:

```julia
  [961ee093] ModelingToolkit v9.41.0
  [1dea7af3] OrdinaryDiffEq v6.89.0

```

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [October 4, 2024, 4:05pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/2 "2024-10-04T16:05:30Z")

</div>

This post was temporarily hidden by the community for possibly being off-topic, unfocused, inappropriate, or spammy.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [October 4, 2024, 4:34pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/3 "2024-10-04T16:34:26Z")

</div>

Welcome @bspanoghe! I’ve not dug into this, but there are two things here:

- the simplified system doesn’t directly solve for `B`
- solving for each `B` index involves compilation time the first time you do it and then the second time is fast.

I’m not sure how I’d apply the generic perf tips here, @nsajko if you have ideas please elaborate.

---

<div class="post-metadata">

**Author:** ![bspanoghe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bspanoghe/32/209460_2.png) [@bspanoghe](https://discourse.julialang.org/u/bspanoghe)\
**Post date:** [October 7, 2024, 12:28pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/4 "2024-10-07T12:28:41Z")

</div>

Thank you for your response!

I’ve considered forcing the system to solve directly for `B` by instantiating it with the desired values  
`@variables B(t)[1:n] = rand(n)`  
and then setting the gradient to 0.  
`[D(B[i]) ~ 0 for i in eachindex(B)]...`

This does solve the indexing time problem (at the cost of slightly higher solving time), but I was hoping for a cleaner solution.

Based on [this thread](https://discourse.julialang.org/t/modelingtoolkit-jl-intermediate-symbolic-variables-calculated-from-solutions-output-in-the-state-vector/54024) it seems there is some way to mark variables you want to track, but the closest I’ve found is the `irreducible` metadata tag mentioned [here](https://docs.sciml.ai/ModelingToolkit/stable/basics/Variable_metadata/#Irreducible):  
`@variables A(t)[1:n] = zeros(n) B(t)[1:n] [irreducible = true]`

Sadly it slows down the solver immensely, making it an even worse solution for my problem.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [October 8, 2024, 2:10pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/5 "2024-10-08T14:10:49Z")

</div>

Maybe it would be faster to use SymbolicIndexingInterface:

```julia
using SymbolicIndexingInterface
evalsol = getu(sol, B)
Bvals = evalsol(sol) # should be a vector of vector of values of B at each time

```

You can reuse `evalsol` each time you want to pull out the B values (as long as the underlying problem is the same I believe), so it will only be slow the first time it is called and compiled.

---

<div class="post-metadata">

**Author:** ![bspanoghe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bspanoghe/32/209460_2.png) [@bspanoghe](https://discourse.julialang.org/u/bspanoghe)\
**Post date:** [October 9, 2024, 1:37pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/6 "2024-10-09T13:37:21Z")

</div>

I did a quick test and it seems that this method is equally quick to simply using `sol[B]` - I assume MTK might use SymbolicIndexingInterface under the hood for indexing?

However, I also learned some unexpected behavior for indexing multiple variables:  
Indexing a subset of the variables simultaneously  
`sol[[B[i] for i in rand(1:n, 10)]]`  
is about **equally quick** as indexing just a single variable  
`sol[B[rand(1:n)]]`  
while indexing **all** variables `sol[B]` is **twice as quick** as indexing a single one - `sol[B]` ends up being ~1000x faster than indexing all `B` separately!

Indexing for all variables will be more complex for my actual use case but should get plotting times to reasonable levels, so thanks a lot!

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [October 9, 2024, 1:56pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/7 "2024-10-09T13:56:10Z")

</div>

Glad that helped. It is using SymbolicIndexingInterface under the hood, but I was worried it was recompiling each time you called `sol` via a symbolic index (even if previously used). It is good to hear that it is apparently caching the function.

---

<div class="post-metadata">

**Author:** ![isaacsas](https://avatars.discourse-cdn.com/v4/letter/i/f6c823/32.png) [@isaacsas](https://discourse.julialang.org/u/isaacsas)\
**Post date:** [October 9, 2024, 1:58pm UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/8 "2024-10-09T13:58:34Z")

</div>

Every time you index a single (new) variable I imagine it is compiling a function to extract that variable, whereas when grabbing the whole vector it is only compiling one function. So that would give a noticeable performance difference.

---

<div class="post-metadata">

**Author:** ![bspanoghe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bspanoghe/32/209460_2.png) [@bspanoghe](https://discourse.julialang.org/u/bspanoghe)\
**Post date:** [October 11, 2024, 8:42am UTC](https://discourse.julialang.org/t/slow-indexing-of-constant-valued-variables-in-mtk/120922/9 "2024-10-11T08:42:17Z")

</div>

Indeed, it’s very obvious in hindsight why it took so long to index the solution a few hundred times but simply hadn’t thought of it. Just changed the plotting function to do all the indexing in one step and it dropped plotting time from ~5 minutes to a few seconds. Thanks both for the help 🙂
