Loop Rerolling

Basic Usage

To use loop rerolling for repeated components, one can use the @named syntax to instantiate multiple ModelingToolkit systems at once. Then, call the compressed_connection_expansion function to construct an IRState directly, taking full advantage of the repeat structure. The following example demonstrates this approach of rerolling repeated expressions into loops for the RC ladder circuit with 100 RC elements. Note that one can also use the keyword argument loop = false to disable loop rerolling.

using ModelingToolkit, JuliaSimCompiler, DifferentialEquations
using ModelingToolkitStandardLibrary
using ModelingToolkitStandardLibrary.Blocks
using ModelingToolkitStandardLibrary.Electrical

n = 100
t = Blocks.t
D = Differential(t)
systems = @named begin
    sine = Sine(frequency = 10)
    source = Voltage()
    resistors[1:n] = Resistor()
    capacitors[1:n] = Capacitor()
    ground = Ground()
end;
systems = reduce(vcat, systems);
eqs = [connect(sine.output, source.V)
       connect(source.p, resistors[1].p)
       [connect(resistors[i].n, resistors[i + 1].p, capacitors[i].p)
        for i in 1:(n - 1)]
       connect(resistors[end].n, capacitors[end].p)
       [connect(capacitors[i].n, source.n) for i in 1:n]
       connect(source.n, ground.g)];
@named sys = ODESystem(eqs, t; systems);
ir_state = JuliaSimCompiler.compressed_connection_expansion(sys);
@time sys_loop = structural_simplify(ir_state);
@time sys_scalar = structural_simplify(ir_state, loop = false);
u0 = [capacitors[i].v => float(i) for i in 1:n];
ps = [[resistors[i].R => 1 / i for i in 1:n];
      [capacitors[i].C => 1 / i^2 for i in 1:n]]
prob_scalar = ODEProblem(sys_scalar, u0, (0, 10.0), ps);
prob_loop = ODEProblem(sys_loop, u0, (0, 10.0), ps);

@time sol_scalar = solve(prob_scalar);
@time sol_loop = solve(prob_loop);