# How does ModelingToolkit handle time-varying, but purely algebraic problems?

**URL:** https://discourse.julialang.org/t/how-does-modelingtoolkit-handle-time-varying-but-purely-algebraic-problems/134092
**Category:** Modelling & Simulations
**Tags:** question
**Created:** [November 24, 2025, 6:05pm UTC](https://discourse.julialang.org/t/how-does-modelingtoolkit-handle-time-varying-but-purely-algebraic-problems/134092 "2025-11-24T18:05:15Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![NicholasHemenway](https://avatars.discourse-cdn.com/v4/letter/n/e99b99/32.png) [@NicholasHemenway](https://discourse.julialang.org/u/NicholasHemenway)
#### Post date: [November 24, 2025, 6:05pm UTC](https://discourse.julialang.org/t/how-does-modelingtoolkit-handle-time-varying-but-purely-algebraic-problems/134092/1 "2025-11-24T18:05:16Z")

</div>

I’ve constructed a simple resistive circuit with a quadratically increasing voltage using ModelingToolkit. The following diagram gives a graphical depiction of the code below:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/4/d4ecc962d33f0b3d180bb7de5e624012d9c59ecd.png)

```julia
using ModelingToolkit
using ModelingToolkitStandardLibrary.Electrical
using ModelingToolkitStandardLibrary.Blocks

@mtkmodel SimpleCircuit begin
    @components begin
        resistor = Resistor(R=1)
        ground = Ground()
        voltage = Voltage()
        ramp = Ramp(height=10)
        product = Product()
    end
    @equations begin
        connect(resistor.p, voltage.p)
        connect(resistor.n, voltage.n, ground.g)
        connect(ramp.output, product.input1)
        connect(ramp.output, product.input2)
        connect(voltage.V, product.output)
    end
end

@mtkcompile sys = SimpleCircuit()
prob = ODEProblem(sys, Pair[], (0.0,1.0))
sol = solve(prob)

```

As can be seen above, after compiling the system, I cast it to an `ODEProblem` and then `solve`. Looking at the solution (below), we see that it solved the system at the start/end times of the provided time interval and the resistor current behaves as expected at these times (e.g. at 1 second, voltage = 100 and thus current should be 100 given R=1).

```console
julia> sol
retcode: Success
Interpolation: 1st order linear
t: 2-element Vector{Float64}:
 0.0
 1.0
u: 2-element Vector{Vector{Float64}}:
 []
 []
julia> sol[sys.resistor.i]
2-element Vector{Float64}:
   0.0
 100.0

```

My question then is: How does ModelingToolkit handle time varying, but purely algebraic systems? As a point of reference, if I were to set up this exact same problem in Simscape and then plot the resistor current time series data, I would see a nice smooth curve of resistor currents evaluated at time-points dictated by the **max step size** setting of the solver.

As far as I’m aware, since there aren’t any differential quantities to integrate, an ODE solver would not work for a problem like this – rather it has to be done as a sequence of repeated algebraic solves (numerically or analytically) at each time step. I could see the argument that maybe this should be set up then as a `NonlinearProblem` rather than an `ODEProblem`, but I’m not sure how that would work since the variables defined in each component have an explicit time dependence. If posed as a `NonlinearProblem`, is the time dependence of the variables just dropped? Perhaps more important though, I feel that setting it up as a `NonlinearProblem` goes against the intent of the problem formulation above – which is to solve the time evolution of a system (that just happens to be purely algebraic in nature). The above implementation makes the intent very clear – apply a time varying excitation and compute how the system reacts to it.

What happens under the hood when ModelingToolkit is provided a system like the above? And how would I go about forcing it to evaluate more time points?

As a follow-up but related question: when looking at the `System` object, I see that all equations are observed – I’m assuming that it’s because the equations are simple enough that ModelingToolkit has deduced that it can solve for each variable explicitly?

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [November 24, 2025, 8:33pm UTC](https://discourse.julialang.org/t/how-does-modelingtoolkit-handle-time-varying-but-purely-algebraic-problems/134092/2 "2025-11-24T20:33:10Z")

</div>

> [@NicholasHemenway](#):
>
> What happens under the hood when ModelingToolkit is provided a system like the above? And how would I go about forcing it to evaluate more time points?

I guess the adaptive timestep just concludes that it can get away with making the timestep as large as it wants without the error growing. I guess that’s why you see that you got solutions only for the start and end time.  
To get a more densely sampled solution use `saveat` and set it to the desired timestep (or pass an array of values to save at). See the documentation for related options:

> **[Common Solver Options (Solve Keyword Arguments) · DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts/)**
>
> Documentation for DifferentialEquations.jl.

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [November 25, 2025, 8:18am UTC](https://discourse.julialang.org/t/how-does-modelingtoolkit-handle-time-varying-but-purely-algebraic-problems/134092/3 "2025-11-25T08:18:16Z")

</div>

> [@NicholasHemenway](#):
>
> ```julia-auto
> julia> sol
> retcode: Success
> Interpolation: 1st order linear
> t: 2-element Vector{Float64}:
> 0.0
> 1.0
> u: 2-element Vector{Vector{Float64}}:
> []
> []
> julia> sol[sys.resistor.i]
> 2-element Vector{Float64}:
> 0.0
> 100.0
> 
> ```

The data arrays stored in the solution object is slightly misleading in this case, instead, try `plot(sol, idxs=sys.resistor.i)` or access the solution like

```julia-auto
sol(timepoints, idxs=sys.resistor.i)

```

and you’d get the full solution.
