Getting started#

HERMESS simulates power system dynamics as one nonlinear differential-algebraic system. This notebook runs a shipped system end to end: pick a case, simulate it, read the initial power flow, and plot the trajectories.

[1]:
import matplotlib.pyplot as plt

import hermess

hermess.list_systems()
[1]:
['3bus',
 '3bus_avrac1a',
 '3bus_avrst1a',
 '3bus_dynlines_psid',
 '3bus_genrou',
 '3bus_genrou_psse',
 '3bus_gensal',
 '3bus_gfm_psid',
 '3bus_ieeedc1a',
 '3bus_loadstep',
 '3bus_marconato_pscad',
 '3bus_psskundur',
 '3bus_sauerpai_psid',
 '3bus_sexst',
 '3bus_shaft5mass_psid',
 '3bus_tgov1',
 'ieee39',
 'ieee39_conv',
 'ieee39_conv_old',
 'ieee39_ideal',
 'kundur',
 'kundur_conv',
 'omib_gfl_pscad',
 'omib_gfm_pscad',
 'omib_vsm_pscad',
 'sea14gen/case1',
 'sea14gen/case1_conv',
 'sea14gen/case1_nopss',
 'sea14gen/case2',
 'sea14gen/case2_nopss',
 'sea14gen/case3',
 'sea14gen/case3_nopss',
 'sea14gen/case4',
 'sea14gen/case4_nopss',
 'sea14gen/case5',
 'sea14gen/case5_nopss',
 'sea14gen/case6',
 'sea14gen/case6_nopss',
 'sea14gen/smib']

3bus is the smallest shipped system that contains both kinds of dynamic device: a Sauer-Pai synchronous machine at bus 1, a grid-forming converter at bus 3 and a ZIP load at bus 2. Its disturbance file opens the line between buses 3 and 1 at t = 3 s.

The shipped case pairs a dynamic LCL output filter with the dynamic network model, so we keep line_dyn=True and integrate with a 0.1 ms step. simulate accepts any field of the configuration as a keyword argument and returns the finished model; extract_results turns it into plain numpy containers.

[2]:
dae = hermess.simulate("3bus", T_end=6.0, ts=1e-4, line_dyn=True)
res = hermess.extract_results(dae)
Simulation: 100%|██████████| 100.0/100% [00:01<00:00]

The run is initialized from a power flow, so t = 0 s is a steady state:

[3]:
res.power_flow_bus
[3]:
Bus V Magnitude (pu) V Phase (deg) P Gen (MW) Q Gen (MVAr) P Shunt (MW) Q Shunt (MVAr) P Shunt Trafo (MW) Q Shunt Trafo (MVAr)
0 1 1.000000 4.108738e-27 50.846313 -1.057522 0.050000 -1.500000 0.050000 -1.500000
1 2 0.992809 -2.530079e+00 -100.000000 -10.000000 0.197134 -3.942677 0.197134 -3.942677
2 3 1.000000 7.954493e-02 50.000000 0.177044 0.150000 -2.500000 0.150000 -2.500000

res.voltage maps each bus to its complex voltage trajectory. The line opening at t = 3 s and the electromagnetic transient it excites are both visible:

[4]:
fig, ax = plt.subplots(figsize=(8, 3.2))
for bus in res.buses():
    ax.plot(res.t, res.voltage_magnitude(bus), lw=0.8, label=f"bus {bus}")
ax.axvline(3.0, color="0.6", ls=":", lw=1)
ax.set_xlabel("t [s]")
ax.set_ylabel("|v| [p.u.]")
ax.legend()
fig.tight_layout()
../_images/examples_getting_started_7_0.png

Every device keeps its own differential states, listed per unit in res.devices:

[5]:
for dev in res.devices:
    print(f"{dev.unit} at bus {dev.bus}: {', '.join(dev.states)}")
SG1 at bus 1: delta, omega, psv, pm, Efd, Rf, Vr, e_dprim, e_qprim, psid, psiq, psid2, psiq2
GFMI2 at bus 3: Vfd_ext, Vfq_ext, ifd_ext, ifq_ext, itd_ext, itq_ext, Pc_tilde, delta_c, Qc_tilde, xi_d, xi_q, gamma_d, gamma_q

The machine speed and the converter’s filtered active power tell the electromechanical story of the event: the converter picks up the power the lost line no longer carries, and the machine settles at a slightly different angle.

[6]:
sg1 = next(d for d in res.devices if d.unit == "SG1")
gfm = next(d for d in res.devices if d.unit == "GFMI2")

fig, axes = plt.subplots(2, 1, figsize=(8, 4.6), sharex=True)
axes[0].plot(res.t, sg1.states["omega"], color="#215CAF")
axes[0].set_ylabel(r"$\omega_{\mathrm{SG1}}$ [p.u.]")
axes[1].plot(res.t, gfm.states["Pc_tilde"], color="#007894")
axes[1].set_ylabel(r"$\tilde p_{c,\mathrm{GFM}}$ [p.u.]")
axes[1].set_xlabel("t [s]")
for ax in axes:
    ax.axvline(3.0, color="0.6", ls=":", lw=1)
fig.tight_layout()
../_images/examples_getting_started_11_0.png

From here, each of the remaining notebooks picks out one aspect of the simulator: scheduled disturbances, the hybrid EMT/RMS network, small-signal analysis and parametric sensitivities. The user guide describes the system files, and the model library documents every device class.