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, although the parameters probably need to be updated. 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 centerpiece of the model, we define a reversible component that describes the coupling of the magnetic energy domain and the kinetic energy domain, which depends on the magnetic flux generated by the stator:

mkc = let
  bₛ₊x = XVar(:bₛ)
  b₊e = EVar(:b)
  p₊e = EVar(:p)
  b₊f = bₛ₊x * p₊e
  p₊f = -(bₛ₊x * b₊e)
  ReversibleComponent(
    Dtry(
      :b => Dtry(ReversiblePort(FlowPort(magnetic_flux, b₊f))),
      :p => Dtry(ReversiblePort(FlowPort(angular_momentum, p₊f))),
      :bₛ => Dtry(ReversiblePort(StatePort(magnetic_flux)))
    )
  )
end;

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.θ