DC shunt motor
A DC motor has a fixed outer part, called stator, and a rotating inner part, called rotor. Both parts contain a coil of wire through which current flows. In the case of a shunt motor, these two inductors are connected in parallel to a source of electric energy.
First, we model the stator and then the rotor. Finally, we combine them into the motor model.
Stator
First and foremost, the stator has a coil, which generates a magnetic field. We use the methods linear_inductor
and thermal_capacity
from the ComponentLibrary
to define storage components that model its inductance and thermal capacity:
coil = linear_inductor(1.0)
tc = thermal_capacity(1.0, 2.0);
To define the stator model, we further use the reversible component emc
that models the coupling between the electric and the magnetic energy domain, and we use the method magnetic_resistor
to define an irreversible component that models the resistance of the coil.
stator = CompositeSystem(
Dtry(
:b => Dtry(Junction(magnetic_flux, Position(2, 3), exposed=true, power=false)),
:q => Dtry(Junction(charge, Position(2, 1), exposed=true)),
:s => Dtry(Junction(entropy, Position(2, 5))),
),
Dtry(
:emc => Dtry(
InnerBox(
Dtry(
:q => Dtry(InnerPort(■.q)),
:b => Dtry(InnerPort(■.b)),
),
emc,
Position(2, 2)
),
),
:coil => Dtry(
InnerBox(
Dtry(
:b => Dtry(InnerPort(■.b)),
),
coil,
Position(1, 3)
),
),
:res => Dtry(
InnerBox(
Dtry(
:b => Dtry(InnerPort(■.b)),
:s => Dtry(InnerPort(■.s))
),
magnetic_resistor(0.01),
Position(2, 4)
),
),
:tc => Dtry(
InnerBox(
Dtry(
:s => Dtry(InnerPort(■.s))
),
tc,
Position(1, 5)
),
),
)
)
Rotor
For simplicity, we reuse the primitive subsystems coil
and tc
of the stator model. Further, we use the method angular_mass
from the library to define a component that models storage of kinetic energy:
mass = angular_mass(1.0);
As the central coupling component of the motor model, we use the component mkc
from the library:
EPHS.ComponentLibrary.ReversibleComponentLibrary.mkc
— ConstantMagnetic-kinetic coupling: Reversible coupling of of a magnetic energy domain at port $\mathtt{b}$ (magnetic flux) and a kinetic energy domain at port $\mathtt{p}$ (angular momentum) based on the Lorentz force. The strength of the coupling is proportional to the magnetic flux at the state port $\mathtt{b_s}$. The Dirac structure is given by
\[\begin{bmatrix} \mathtt{b.f} \\ \mathtt{p.f} \end{bmatrix} \: = \: \begin{bmatrix} 0 & +\mathtt{b_s.x} \\ -\mathtt{b_s.x} & 0 \end{bmatrix} \, \begin{bmatrix} \mathtt{b.e} \\ \mathtt{p.e} \end{bmatrix} \,.\]
To define the rotor model, we additionally use the library method rotational_friction
to describe the mechanical friction of the rotor.
rotor = CompositeSystem(
Dtry(
:q => Dtry(Junction(charge, Position(2, 1), exposed=true)),
:b => Dtry(Junction(magnetic_flux, Position(2, 3))),
:bₛ => Dtry(Junction(magnetic_flux, Position(1, 4), exposed=true, power=false)),
:p => Dtry(Junction(angular_momentum, Position(2, 5), exposed=true)),
:s => Dtry(Junction(entropy, Position(3, 4))),
),
Dtry(
:emc => Dtry(
InnerBox(
Dtry(
:q => Dtry(InnerPort(■.q)),
:b => Dtry(InnerPort(■.b)),
),
emc,
Position(2, 2)
),
),
:coil => Dtry(
InnerBox(
Dtry(
:b => Dtry(InnerPort(■.b)),
),
coil,
Position(1, 3)
),
),
:mkc => Dtry(
InnerBox(
Dtry(
:b => Dtry(InnerPort(■.b)),
:p => Dtry(InnerPort(■.p)),
:bₛ => Dtry(InnerPort(■.bₛ, power=false)),
),
mkc,
Position(2, 4)
),
),
:mass => Dtry(
InnerBox(
Dtry(
:p => Dtry(InnerPort(■.p)),
),
mass,
Position(1, 5)
),
),
:res => Dtry(
InnerBox(
Dtry(
:b => Dtry(InnerPort(■.b)),
:s => Dtry(InnerPort(■.s))
),
magnetic_resistor(0.01),
Position(3, 3)
),
),
:mf => Dtry(
InnerBox(
Dtry(
:p => Dtry(InnerPort(■.p)),
:s => Dtry(InnerPort(■.s))
),
rotational_friction(0.01),
Position(3, 5)
),
),
:tc => Dtry(
InnerBox(
Dtry(
:s => Dtry(InnerPort(■.s))
),
tc,
Position(4, 4)
),
),
)
)
Motor
Now we interconnect the stator and rotor:
motor = CompositeSystem(
Dtry(
:q => Dtry(Junction(charge, Position(2, 1), exposed=true)),
:bₛ => Dtry(Junction(magnetic_flux, Position(2, 2), power=false)),
:p => Dtry(Junction(angular_momentum, Position(3, 3), exposed=true)),
),
Dtry(
:stator => Dtry(
InnerBox(
Dtry(
:q => Dtry(InnerPort(■.q)),
:b => Dtry(InnerPort(■.bₛ, power=false)),
),
stator,
Position(1, 2)
),
),
:rotor => Dtry(
InnerBox(
Dtry(
:q => Dtry(InnerPort(■.q)),
:bₛ => Dtry(InnerPort(■.bₛ, power=false)),
:p => Dtry(InnerPort(■.p)),
),
rotor,
Position(3, 2)
),
),
)
)
Evolution equations
As the implementation does not yet support the simulation of open systems with 'boundary conditions', we can merely assemble the equations:
assemble(motor)
Flows:
rotor.coil.b.f = q.e + -1.0 * stator.coil.b.x * rotor.mass.p.e + -1.0 * rotor.res.r * rotor.coil.b.e
rotor.mass.p.f = -1.0 * rotor.mf.d * rotor.mass.p.e + stator.coil.b.x * rotor.coil.b.e + p.f
rotor.tc.s.f = rotor.mf.d * (rotor.mass.p.e^2.0) * ((ENV.θ + rotor.tc.s.e)^-1.0) + rotor.res.r * (rotor.coil.b.e^2.0) * ((ENV.θ + rotor.tc.s.e)^-1.0)
stator.coil.b.f = q.e + -1.0 * stator.res.r * stator.coil.b.e
stator.tc.s.f = stator.res.r * (stator.coil.b.e^2.0) * ((ENV.θ + stator.tc.s.e)^-1.0)
Efforts:
rotor.coil.b.e = rotor.coil.b.x * (rotor.coil.l^-1.0)
rotor.mass.p.e = rotor.mass.p.x * (rotor.mass.m^-1.0)
rotor.tc.s.e = rotor.tc.c₁ * (exp(rotor.tc.s.x * (rotor.tc.c₂^-1.0))) * (rotor.tc.c₂^-1.0) + -1.0 * ENV.θ
stator.coil.b.e = stator.coil.b.x * (stator.coil.l^-1.0)
stator.tc.s.e = stator.tc.c₁ * (exp(stator.tc.s.x * (stator.tc.c₂^-1.0))) * (stator.tc.c₂^-1.0) + -1.0 * ENV.θ