After >20 years working with MODELICA I tried to use Complex equations in MTK
.
In a simple example an ohmic resistor and a inductor are connected in series to a constant voltage source. I used per unit system with space-phasors and variable speed of reference frame @parameters wReference
.
using ModelingToolkit
using DifferentialEquations
using Plots
frequency = 50.0
Omegarated = frequency*2pi
JJ = 1.0im
function NewVars(eqName::String, CCX::Vector{Complex{Num}})::Tuple{Expr, Expr}
vari::String = "newVariables = @variables "
substi::String = ""
for cx in CCX
stcx = string(cx)[1:end-3] # without '(t)'
vari = string(vari,stcx*"₋re(t) ",stcx*"₋im(t) ")
substi = string(substi,"$eqName = substitute($eqName,(real($stcx)=>$(stcx)₋re)); ")
substi = string(substi,"$eqName = substitute($eqName,(imag($stcx)=>$(stcx)₋im)); ")
end
return (Meta.parse(vari), Meta.parse(substi))
end
@variables t rad(t)=0.0 w(t)
CX = @variables begin
deri(t)::ComplexF64
amps(t)::ComplexF64
gridVolts(t)::ComplexF64
end
@parameters x r wReference = 1.0
D = Differential(t)
# DiffC(cpx) = Complex(D(real(cpx)),D(imag(cpx))) # used for testing
#NOTE
#NOTE this line was added in Symbolics - diff.jl
# (D::Differential)(x::Complex{Num}) = Num(D(real(x)))+Num(D(imag(x)))*im
#NOTE
eqs1 = [ D(amps) ~ deri*Omegarated
gridVolts ~ x*(deri + wReference*amps*JJ) + r*amps
w ~ D(rad)
w ~ Omegarated*(1.0-wReference)
gridVolts ~ Complex(cos(rad), sin(rad))
]
eqs=deepcopy(eqs1)
(Bvaria, Bsubst) = NewVars("eqs",CX)
eval(Bvaria) # create new variables
eval(Bsubst) # substitute
pr = 0.3; px = 0.1
u0 = [0.0, 0.0, 0.0]
p = [x => px, r=> pr, wReference => 1.0]
# exact solution
strom = (1.0+0im)/(pr+JJ*px)
println("exact solution: amps = $(strom)")
@named model = ODESystem(eqs)
sys = structural_simplify(model)
prob = ODEProblem(sys, u0, (0., 1.0/frequency), p)
sol = solve(prob, Tsit5())
plot(sol)
my approach
(D::Differential)(x::Complex{Num}
an additional line in diff.jl
(D::Differential)(x::Complex{Num}) = Num(D(real(x)))+Num(D(imag(x)))*im
substitute real(x), imag(x)
real(x), imag(x)
are replaced by new @variables x_re x_im
Questions
- This works with monolithic models. But how to do with component based models? (e.g.
connect()
andFlow
)
backup alternative
To split Complex equations manually. This works, but Symbolics
should do this for me.
Thanks