Usage#
After Installation, the system model and the control system are built as in motulator, see the usage of motulator. The package has a module for each system type:
from motulator_impedance import drive, grid
The system model and the control system are built in motulator as usual. The mechanical impedance of a drive, whose rotor speed is imposed by ExternalRotorSpeed:
import motulator.drive.control.im as control
import numpy as np
from motulator.drive import model
from motulator_impedance import drive
par = model.InductionMachineInvGammaPars(
n_p=2, R_s=60e-3, R_R=30e-3, L_sgm=2.2e-3, L_M=24.5e-3
)
mechanics = model.ExternalRotorSpeed()
mechanics.set_external_rotor_speed(40.0) # Operating-point speed (rad/s)
mdl = model.Drive(
model.InductionMachine(par), mechanics, model.VoltageSourceConverter(u_dc=540)
)
cfg = control.ObserverBasedVHzControllerCfg(psi_s_nom=1.04, i_s_max=170.0)
ctrl = control.VHzControlSystem(control.ObserverBasedVHzController(par, cfg))
ctrl.set_speed_ref(40.0)
meas_cfg = drive.MeasurementCfg(abs_w_e=0.3, freqs=np.geomspace(1, 500, 50))
if __name__ == "__main__": # Needed for the parallel processes, see Scope
Z_M = drive.measure_mechanical_impedance(mdl, ctrl, meas_cfg)
drive.plot_mechanical_impedance(Z_M)
The output admittance of a grid converter:
import numpy as np
from motulator.grid import control, model
from motulator_impedance import grid
mdl = model.GridConverterSystem(
model.VoltageSourceConverter(u_dc=650),
model.LFilter(L_f=5e-3),
model.ThreePhaseSource(w_g=2 * np.pi * 50, e_g=326.6),
)
cfg = control.CurrentVectorControllerCfg(i_max=30.0, L=5e-3, T_s=1 / 10e3)
ctrl = control.GridConverterControlSystem(control.CurrentVectorController(cfg))
ctrl.set_power_ref(5e3)
ctrl.set_reactive_power_ref(0.0)
meas_cfg = grid.MeasurementCfg(abs_u_e=3.0, freqs=np.geomspace(1, 10e3, 100))
if __name__ == "__main__":
Y = grid.measure_output_admittance(mdl, ctrl, meas_cfg)
grid.plot_output_admittance(Y, form="re_im")
The results are dataclasses, which can be saved, e.g., by scipy.io.savemat(path, dataclasses.asdict(Y)). Complete examples are in the example gallery.
Scope#
The frequencies are simulated in parallel processes by default (
multiprocess=True), so the model and the control system must be picklable: use module-level functions or callable objects as references, not lambda functions. In a script, call the measurement underif __name__ == "__main__":, since the processes import the script again on Windows and macOS, as well as on Linux from Python 3.14 onward. In the interactive interpreter, usemultiprocess=False.With carrier-comparison PWM, background switching harmonics can bias the measured admittance near the switching harmonics and their sidebands.
The grid impedance and the DC bus of the system model are included in the operating point; the admittance is measured with the PCC voltage imposed.