Hi All,
I am trying to model an electromagnetic launcher using ModelingToolkit.jl. The electric circuit is basically an RLC with a crowbar circuit that cut off the capacitor when the voltage is 0V. I managed to do the simulation using callbacks (terminating the first simulation-sol1- at 0V and starting another RL circuit simulation-sol2).
The current generated by this circuits is used for accelerating an object so I need to add the currents from the two solutions (sol1.i + sol2.i).
The end goal of my simulations is to optimize the launcher by varying the number of capacitor banks. I would like to do it automatically by generating the code based one the number of capacitors banks.
I tried to model the crowbar circuit as “idealCommutingSwitch” from Modelica but I didn’t manage to make it work (I have an unballanced system). Basically now I am trying to figure out how can I monitor the voltage and once the voltage hits the threshold how can I modify the circuits. Is this something possible in ModelingToolkit.jl?
Thank you for your help.
Here is a my code with a single capacitor bank:
using ModelingToolkit, Plots, DifferentialEquations
@variables t
@connector function Pin(;name)
    sts = @variables v(t)=1.0 i(t)=1.0 [connect = Flow]
    ODESystem(Equation[], t, sts, []; name=name)
end
function Ground(;name)
    @named g = Pin()
    eqs = [g.v ~ 0]
    compose(ODESystem(eqs, t, [], []; name=name), g)
end
function OnePort(;name)
    @named p = Pin()
    @named n = Pin()
    sts = @variables v(t)=1.0 i(t)=1.0
    eqs = [
           v ~ p.v - n.v
           0 ~ p.i + n.i
           i ~ p.i
          ]
    compose(ODESystem(eqs, t, sts, []; name=name), p, n)
end
function Resistor(;name, R = 1.0)
    @named oneport = OnePort()
    @unpack v, i = oneport
    ps = @parameters R=R
    eqs = [
           v ~ i * R
          ]
    extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
function Capacitor(;name, C = 1.0)
    @named oneport = OnePort()
    @unpack v, i = oneport
    ps = @parameters C=C
    D = Differential(t)
    eqs = [
           D(v) ~ i / C
          ]
    extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
function Inductor(; name, L=1.0)
    @named oneport = OnePort()
    @unpack v, i = oneport
    ps = @parameters L=L
    D = Differential(t)
    eqs = [
        D(i) ~ v / L
          ]
    extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
function ConstantVoltage(;name, V = 1.0)
    @named oneport = OnePort()
    @unpack v = oneport
    ps = @parameters V=V
    eqs = [
           V ~ v
          ]
    extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
L1 = 0.6*1e-6; L2 = 4*1e-6
L3 = 1.1*1e-6; R1= 4*1e-3; R2 = 0.28*1e-3; R3 = 3.6*1e-3
RD = 0.1*1e-3; Lpr = 4.2*1e-9
C = 3.08*1e-3 ; Uc = 10*1e3
L = L1+L2+L3
R = R1+R2+R3
@named resistor_1 = Resistor(R=R1)
@named resistor_2 = Resistor(R=R2)
@named resistor_3 = Resistor(R=R3)
@named capacitor = Capacitor(C=C)
@named inductor_1 = Inductor(L=L1)
@named inductor_2 = Inductor(L=L2)
@named inductor_3 = Inductor(L=L3)
@named resistor_D = Resistor(R=RD)
#@named diode = Gate(false)
@named ground = Ground()
rc_eqs = [
        #connect_pins(V1.p, R1.p)
        connect_pins(resistor_1.n, inductor_1.p)
        #connect_pins(inductor_1.n, capacitor.p)
        connect_pins(capacitor.n, resistor_1.p, ground.g)
        connect_pins(inductor_1.n, resistor_2.p)
        #connect_pins(resistor_2.n, capacitor.p)
        connect_pins(resistor_2.n, inductor_2.p)
        connect_pins(inductor_2.n, resistor_3.p)
        connect_pins(resistor_3.n, inductor_3.p)
        connect_pins(inductor_3.n, capacitor.p)
        #connect_pins(capacitor.n, resistor_1.p)
        #connect_pins(V1.n, L2.n, GND.g)
         ]
rc_eqs2 = [
        
        
        #connect_pins(inductor_3.n, resistor_D.p, ground.g)
        connect_pins(resistor_D.n, resistor_2.p)
        #connect_pins(resistor_2.n, capacitor.p)
        connect_pins(resistor_2.n, inductor_2.p)
        connect_pins(inductor_2.n, resistor_3.p)
        connect_pins(resistor_3.n, inductor_3.p)
        connect_pins(inductor_3.n, resistor_D.p, ground.g)
        
]
@named _rc_model = ODESystem(rc_eqs, t)
@named _rc_model2 = ODESystem(rc_eqs2, t)
@named rc_model = compose(_rc_model,
[resistor_1,resistor_2,resistor_3, capacitor, inductor_1, inductor_2, inductor_3,ground])
@named rc_model2 = compose(_rc_model2,
[resistor_2,resistor_3, inductor_2, inductor_3,ground,resistor_D])
sys = structural_simplify(rc_model)
sys2 = structural_simplify(rc_model2)
u0 = [
        capacitor.v => -Uc
        inductor_1.i => 0.0
        inductor_2.i => 0.0
        inductor_3.i => 0.0
        inductor_2.v => 0.0
        inductor_3.v => 0.0
       ]
prob = ODEProblem(sys, u0, (0, 0.01))
function condition(u,t,integrator)
    -(integrator.sol[capacitor.v][end]+integrator.sol[resistor_1.v][end]+integrator.sol[inductor_1.v][end])<0.0
end
affect!(integrator) = terminate!(integrator)
cb = DiscreteCallback(condition,affect!, save_positions=(false,false))
sol = solve(prob, Rodas4(), reltol=1e-12,abstol=1e-12,callback=cb)
u02 = [
           inductor_2.i => sol[inductor_2.i][end]
           inductor_3.i => sol[inductor_3.i][end]
           inductor_3.v => sol[inductor_3.v][end]
          ]
prob2 = ODEProblem(sys2, u02, (sol.t[end], 0.01))
sol2 = solve(prob2, Rodas4(),reltol=1e-12,abstol=1e-12)
#plot(sol2)
