# ModelingToolkit compilation time for many small simulations

**URL:** <https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631>\
**Category:** Performance\
**Tags:** modelingtoolkit, differentialequation\
**Created:** [August 9, 2023, 11:25am UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631 "2023-08-09T11:25:00Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Antomek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antomek/32/9406_2.png) [@Antomek](https://discourse.julialang.org/u/Antomek)\
**Post date:** [August 9, 2023, 11:25am UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631/1 "2023-08-09T11:25:00Z")

</div>

Hello all,

I am in a situation where I want to run many small ODEs, to do an ensemble-type of simulation.  
I really like using `ModelingToolkit`, and was trying to use it for this purpose.

However, my code is running really slowly, and I was wondering if I could be doing something smarter, or it there are inherent drawbacks to using `ModelingToolkit` (specifically, the compilation time).

Take a slightly modified [example from its docs here](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/ode_modeling/#Specifying-a-time-variable-forcing-function):

```julia
using ModelingToolkit, OrdinaryDiffEq

@variables t x(t) # independent and dependent variables
@parameters τ # parameters
D = Differential(t) # define an operator for the differentiation w.r.t. time

# your first ODE, consisting of a single equation, the equality indicated by ~
@variables f(t)

trials = 50

@time for ω in 0.1:0.5:5
    for i in 1:trials
        @named fol_variable_f = ODESystem([f ~ sin((ω * rand()) * t), D(x) ~ (f - x) / τ])
        _sys = structural_simplify(fol_variable_f)

        prob = ODEProblem(_sys, [x => 0.0], (0.0, 10.0), [τ => 0.75])
        # parameter `τ` can be assigned a value, but constant `h` cannot
        sol = solve(prob, Tsit5())
    end
end

```

this gives on my machine:

```julia
264.382315 seconds (103.54 M allocations: 6.749 GiB, 2.51% gc time, 97.25% compilation time)

```

As you can see, this is almost all compilation time.  
Is this compilation time inherent to using `ModelingToolkit`, or is there something I can do to drastically speed things up here?

---

<div class="post-metadata">

**Author:** ![maxfreu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxfreu/32/17468_2.png) [@maxfreu](https://discourse.julialang.org/u/maxfreu)\
**Post date:** [August 9, 2023, 11:52am UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631/2 "2023-08-09T11:52:32Z")

</div>

I am absolutely unfamiliar with ModelingToolkit, but it seems very likely to me that the issue is that you work in the global scope. Try wrapping everything in a function, e.g. main() and then run that and see how the timings look like.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [August 9, 2023, 12:10pm UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631/3 "2023-08-09T12:10:13Z")

</div>

I believe what you want to do here is to make a single ode with parameters and then solve it repeatedtly varying the parameters

---

<div class="post-metadata">

**Author:** ![Antomek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antomek/32/9406_2.png) [@Antomek](https://discourse.julialang.org/u/Antomek)\
**Post date:** [August 9, 2023, 1:00pm UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631/4 "2023-08-09T13:00:19Z")

</div>

That’s a good suggestion, but that’s what my initial approach was.  
Seemed to give no improvement benefits in this case!

---

<div class="post-metadata">

**Author:** ![Antomek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antomek/32/9406_2.png) [@Antomek](https://discourse.julialang.org/u/Antomek)\
**Post date:** [August 9, 2023, 1:01pm UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631/5 "2023-08-09T13:01:34Z")

</div>

That would probably work… if I can figure out how to make the input functions of my systems depend on those parameters, without it requiring Julia to recompile everything.  
I suspect that it is possible somehow, I just haven’t found a way of achieving that yet.

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [August 9, 2023, 4:21pm UTC](https://discourse.julialang.org/t/modelingtoolkit-compilation-time-for-many-small-simulations/102631/6 "2023-08-09T16:21:14Z")

</div>

[remake](https://docs.sciml.ai/MethodOfLines/stable/tutorials/params/#Remake-with-different-parameter-values) is the function you are looking for.

```julia
using ModelingToolkit, OrdinaryDiffEq

function create_problem()
    @variables t x(t) f(t) # independent and dependent variables
    @parameters τ=0.75 ω=1.0 # parameters
    D = Differential(t) # define an operator for the differentiation w.r.t. time

    eqs = [
        f ~ sin((ω * rand()) * t)
        D(x) ~ (f - x) / τ
    ]

    @named fol_variable_f = ODESystem(eqs)
    _sys = structural_simplify(fol_variable_f)

    prob = ODEProblem(_sys, [x => 0.0], (0.0, 10.0))
end

function run_simulations(prob; trials = 50)
    @parameters ω
    for ω_ in 0.1:0.5:5
        for i in 1:trials
            prob_ = remake(prob, p=[ω=>ω_])
            sol = solve(prob_, Tsit5())
        end
    end
end

```

```julia
julia> prob = create_problem()
ODEProblem with uType Vector{Float64} and tType Float64. In-place: true
timespan: (0.0, 10.0)
u0: 1-element Vector{Float64}:
 0.0

julia> @time run_simulations(prob)
  0.072954 seconds (359.97 k allocations: 30.387 MiB, 68.91% compilation time)

julia> @time run_simulations(prob)
  0.051170 seconds (249.95 k allocations: 23.109 MiB, 53.83% gc time)

```
