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);