Small-signal analysis#
With small_signal_analysis=True the operating point is linearized before the time stepping: the algebraic variables are eliminated, the reduced state matrix is built, and its eigenvalues, participation factors and a modal report are attached to the returned model. The analysis lives entirely at t = 0 s, so a short horizon keeps the run cheap.
The system is the standard IEEE 39-bus benchmark with ten subtransient machines. The run prints the modal report, sorted by damping ratio, so the critical electromechanical modes top the list:
[1]:
import hermess
dae = hermess.simulate(
"ieee39", T_end=0.5, ts=5e-3, line_dyn=False,
small_signal_analysis=True, small_signal_figures=False,
)
Small-signal modal analysis: 80 modes (0 unstable) over 110 states, sorted by damping ratio (most critical first).
| # | Eigenvalue (σ±jω) | f [Hz] | ζ [%] | Flag | Dominant states (top 4, participation %) |
|-----|---------------------|----------|---------|--------|--------------------------------------------------------------------------------|
| 1 | -0.000 | — | +0.0 | zero | SM@31:delta (10%), SM@34:delta (10%), SM@32:delta (10%), SM@30:delta (10%) |
| 2 | -0.271 ± 7.026j | 1.118 | +3.9 | low ζ | SM@32:omega (25%), SM@32:delta (25%), SM@31:omega (21%), SM@31:delta (21%) |
| 3 | -0.345 ± 7.892j | 1.256 | +4.4 | low ζ | SM@33:omega (33%), SM@33:delta (33%), SM@35:omega (5%), SM@35:delta (5%) |
| 4 | -0.274 ± 5.978j | 0.951 | +4.6 | low ζ | SM@38:omega (15%), SM@38:delta (15%), SM@31:omega (12%), SM@31:delta (12%) |
| 5 | -0.182 ± 3.896j | 0.620 | +4.7 | low ζ | SM@39:omega (15%), SM@39:delta (15%), SM@34:omega (7%), SM@34:delta (6%) |
| 6 | -0.377 ± 8.005j | 1.274 | +4.7 | low ζ | SM@36:omega (28%), SM@36:delta (28%), SM@35:omega (15%), SM@35:delta (15%) |
| 7 | -0.301 ± 6.351j | 1.011 | +4.7 | low ζ | SM@35:omega (16%), SM@35:delta (16%), SM@36:omega (9%), SM@36:delta (9%) |
| 8 | -0.411 ± 7.500j | 1.194 | +5.5 | | SM@37:omega (28%), SM@37:delta (28%), SM@30:omega (6%), SM@30:delta (6%) |
| 9 | -0.329 ± 5.629j | 0.896 | +5.8 | | SM@34:omega (21%), SM@34:delta (21%), SM@38:omega (19%), SM@38:delta (19%) |
| 10 | -0.750 ± 9.906j | 1.577 | +7.6 | | SM@30:omega (35%), SM@30:delta (35%), SM@37:omega (10%), SM@37:delta (10%) |
| 11 | -0.459 ± 1.683j | 0.268 | +26.3 | | SM@38:e_qprim (25%), SM@38:Rf (13%), SM@38:Efd (7%), SM@36:e_qprim (5%) |
| 12 | -0.493 ± 1.089j | 0.173 | +41.2 | | SM@39:e_qprim (31%), SM@39:Rf (23%), SM@36:e_qprim (8%), SM@36:Rf (5%) |
| 13 | -0.552 ± 1.211j | 0.193 | +41.5 | | SM@38:e_qprim (20%), SM@38:Rf (12%), SM@36:e_qprim (8%), SM@39:e_qprim (6%) |
| 14 | -5.311 ± 9.109j | 1.450 | +50.4 | | SM@37:Vr (44%), SM@37:Efd (43%), SM@37:Rf (12%), SM@37:e_qprim (1%) |
| 15 | -5.280 ± 8.815j | 1.403 | +51.4 | | SM@32:Vr (34%), SM@32:Efd (33%), SM@33:Vr (10%), SM@32:Rf (9%) |
| 16 | -0.448 ± 0.745j | 0.119 | +51.5 | | SM@31:e_qprim (17%), SM@30:e_qprim (14%), SM@31:Rf (13%), SM@32:e_qprim (11%) |
| 17 | -5.292 ± 8.760j | 1.394 | +51.7 | | SM@33:Vr (32%), SM@33:Efd (31%), SM@33:Rf (9%), SM@32:Vr (9%) |
| 18 | -0.489 ± 0.803j | 0.128 | +52.0 | | SM@30:e_qprim (24%), SM@30:Rf (17%), SM@34:e_qprim (7%), SM@30:Efd (5%) |
| 19 | -5.293 ± 8.563j | 1.363 | +52.6 | | SM@35:Vr (41%), SM@35:Efd (40%), SM@35:Rf (11%), SM@33:Vr (2%) |
| 20 | -0.332 ± 0.496j | 0.079 | +55.6 | | SM@37:e_qprim (43%), SM@37:Rf (36%), SM@37:Efd (5%), SM@30:e_qprim (3%) |
| 21 | -0.568 ± 0.837j | 0.133 | +56.1 | | SM@36:e_qprim (21%), SM@34:e_qprim (17%), SM@36:Rf (13%), SM@34:Rf (11%) |
| 22 | -5.262 ± 7.668j | 1.220 | +56.6 | | SM@39:Vr (40%), SM@39:Efd (39%), SM@39:Rf (13%), SM@39:e_qprim (3%) |
| 23 | -5.227 ± 7.487j | 1.192 | +57.2 | | SM@31:Vr (41%), SM@31:Efd (40%), SM@31:Rf (13%), SM@31:e_qprim (1%) |
| 24 | -0.380 ± 0.506j | 0.080 | +60.1 | | SM@35:e_qprim (36%), SM@35:Rf (30%), SM@33:e_qprim (5%), SM@36:e_qprim (5%) |
| 25 | -0.413 ± 0.524j | 0.083 | +61.9 | | SM@32:e_qprim (25%), SM@32:Rf (22%), SM@31:e_qprim (18%), SM@31:Rf (14%) |
| 26 | -5.245 ± 6.284j | 1.000 | +64.1 | | SM@30:Vr (41%), SM@30:Efd (39%), SM@30:Rf (14%), SM@30:e_qsec (2%) |
| 27 | -0.456 ± 0.514j | 0.082 | +66.3 | | SM@33:e_qprim (27%), SM@33:Rf (24%), SM@34:e_qprim (15%), SM@34:Rf (8%) |
| 28 | -5.068 ± 5.514j | 0.878 | +67.7 | | SM@34:Vr (37%), SM@34:Efd (35%), SM@34:Rf (14%), SM@36:Vr (4%) |
| 29 | -5.087 ± 5.345j | 0.851 | +68.9 | | SM@36:Vr (30%), SM@36:Efd (28%), SM@36:Rf (12%), SM@38:Vr (7%) |
| 30 | -5.037 ± 5.134j | 0.817 | +70.0 | | SM@38:Vr (29%), SM@38:Efd (28%), SM@38:Rf (13%), SM@38:e_qprim (6%) |
| 31 | -5.126 ± 0.197j | 0.031 | +99.9 | | SM@35:e_dprim (33%), SM@35:psv (24%), SM@37:e_dprim (12%), SM@37:psv (10%) |
| 32 | -241.142 | — | +100.0 | | SM@34:e_dsec (98%), SM@34:e_dprim (2%), SM@35:e_dsec (0%), SM@38:e_dsec (0%) |
| 33 | -257.630 | — | +100.0 | | SM@37:e_dsec (83%), SM@38:e_dsec (14%), SM@35:e_dsec (2%), SM@37:e_dprim (1%) |
| 34 | -264.580 | — | +100.0 | | SM@35:e_dsec (92%), SM@38:e_dsec (7%), SM@35:e_dprim (1%), SM@37:e_dsec (0%) |
| 35 | -261.869 | — | +100.0 | | SM@38:e_dsec (78%), SM@37:e_dsec (17%), SM@35:e_dsec (5%), SM@37:e_dprim (0%) |
| 36 | -144.644 | — | +100.0 | | SM@39:e_dsec (100%), SM@39:e_dprim (0%), SM@30:e_dsec (0%), SM@30:e_dprim (0%) |
| 37 | -100.429 | — | +100.0 | | SM@30:e_dsec (99%), SM@30:e_dprim (1%), SM@39:e_dsec (0%), SM@30:omega (0%) |
| 38 | -70.527 | — | +100.0 | | SM@32:e_dsec (80%), SM@31:e_dsec (12%), SM@36:e_dsec (5%), SM@33:e_dsec (3%) |
| 39 | -71.833 | — | +100.0 | | SM@36:e_dsec (70%), SM@33:e_dsec (18%), SM@32:e_dsec (10%), SM@31:e_dsec (1%) |
| 40 | -72.386 | — | +100.0 | | SM@31:e_dsec (70%), SM@36:e_dsec (12%), SM@32:e_dsec (9%), SM@33:e_dsec (9%) |
| 41 | -72.480 | — | +100.0 | | SM@33:e_dsec (69%), SM@31:e_dsec (17%), SM@36:e_dsec (13%), SM@32:e_dsec (1%) |
| 42 | -19.257 | — | +100.0 | | SM@34:e_qsec (92%), SM@33:e_qsec (3%), SM@34:e_qprim (3%), SM@34:Vr (0%) |
| 43 | -17.689 | — | +100.0 | | SM@33:e_qsec (54%), SM@36:e_qsec (27%), SM@32:e_qsec (10%), SM@34:e_qsec (3%) |
| 44 | -18.102 | — | +100.0 | | SM@32:e_qsec (84%), SM@33:e_qsec (7%), SM@36:e_qsec (4%), SM@32:e_qprim (2%) |
| 45 | -18.001 | — | +100.0 | | SM@36:e_qsec (64%), SM@33:e_qsec (31%), SM@36:e_qprim (2%), SM@33:e_qprim (1%) |
| 46 | -15.649 | — | +100.0 | | SM@31:e_qsec (91%), SM@37:e_qsec (2%), SM@31:e_qprim (2%), SM@38:e_qsec (1%) |
| 47 | -15.302 | — | +100.0 | | SM@37:e_qsec (81%), SM@38:e_qsec (13%), SM@37:e_qprim (2%), SM@31:e_qsec (1%) |
| 48 | -14.917 | — | +100.0 | | SM@38:e_qsec (78%), SM@37:e_qsec (11%), SM@38:e_qprim (2%), SM@35:e_qsec (2%) |
| 49 | -13.870 | — | +100.0 | | SM@35:e_qsec (80%), SM@39:e_qsec (11%), SM@38:e_qsec (2%), SM@35:e_qprim (2%) |
| 50 | -14.143 | — | +100.0 | | SM@39:e_qsec (82%), SM@35:e_qsec (12%), SM@39:e_qprim (2%), SM@39:Vr (1%) |
| 51 | -9.892 | — | +100.0 | | SM@30:e_qsec (92%), SM@30:e_qprim (3%), SM@30:Vr (2%), SM@30:Efd (1%) |
| 52 | -6.837 | — | +100.0 | | SM@34:e_dprim (87%), SM@34:omega (2%), SM@34:delta (2%), SM@35:e_dprim (2%) |
| 53 | -5.413 | — | +100.0 | | SM@37:e_dprim (42%), SM@35:e_dprim (21%), SM@37:psv (21%), SM@35:psv (6%) |
| 54 | -5.271 | — | +100.0 | | SM@37:psv (42%), SM@37:e_dprim (20%), SM@35:e_dprim (14%), SM@35:psv (11%) |
| 55 | -5.218 | — | +100.0 | | SM@34:psv (35%), SM@35:psv (14%), SM@33:psv (8%), SM@36:psv (7%) |
| 56 | -5.169 | — | +100.0 | | SM@34:psv (46%), SM@35:psv (10%), SM@38:psv (9%), SM@36:psv (8%) |
| 57 | -5.015 | — | +100.0 | | SM@39:psv (96%), SM@30:psv (3%), SM@39:pm (1%), SM@39:omega (0%) |
| 58 | -5.045 | — | +100.0 | | SM@30:psv (84%), SM@38:psv (4%), SM@32:psv (2%), SM@39:psv (2%) |
| 59 | -5.120 | — | +100.0 | | SM@31:psv (45%), SM@38:psv (42%), SM@32:psv (5%), SM@31:pm (2%) |
| 60 | -5.115 | — | +100.0 | | SM@36:psv (49%), SM@38:psv (22%), SM@31:psv (16%), SM@33:psv (5%) |
| 61 | -5.095 | — | +100.0 | | SM@33:psv (60%), SM@36:psv (19%), SM@32:psv (7%), SM@31:psv (5%) |
| 62 | -5.090 | — | +100.0 | | SM@32:psv (68%), SM@33:psv (15%), SM@31:psv (11%), SM@32:pm (2%) |
| 63 | -0.139 | — | +100.0 | | SM@39:omega (29%), SM@39:delta (25%), SM@37:delta (3%), SM@34:delta (3%) |
| 64 | -1.419 | — | +100.0 | | SM@39:e_dprim (93%), SM@30:omega (0%), SM@32:omega (0%), SM@30:pm (0%) |
| 65 | -2.183 | — | +100.0 | | SM@34:pm (11%), SM@36:pm (8%), SM@35:pm (8%), SM@33:pm (8%) |
| 66 | -1.312 | — | +100.0 | | SM@32:e_dprim (87%), SM@32:Rf (7%), SM@32:e_qprim (1%), SM@31:e_dprim (1%) |
| 67 | -1.184 | — | +100.0 | | SM@30:e_dprim (91%), SM@30:Rf (3%), SM@30:omega (1%), SM@30:e_qprim (1%) |
| 68 | -0.866 | — | +100.0 | | SM@36:e_dprim (92%), SM@36:Rf (5%), SM@36:Efd (1%), SM@36:e_qprim (1%) |
| 69 | -1.006 | — | +100.0 | | SM@38:e_dprim (93%), SM@38:Rf (3%), SM@38:e_qprim (1%), SM@31:e_dprim (1%) |
| 70 | -2.499 | — | +100.0 | | SM@30:pm (78%), SM@39:pm (15%), SM@30:e_dprim (2%), SM@37:pm (1%) |
| 71 | -2.481 | — | +100.0 | | SM@39:pm (78%), SM@30:pm (10%), SM@32:pm (4%), SM@37:pm (2%) |
| 72 | -0.925 | — | +100.0 | | SM@33:e_dprim (89%), SM@33:Rf (5%), SM@33:e_qprim (1%), SM@31:e_dprim (1%) |
| 73 | -0.967 | — | +100.0 | | SM@31:e_dprim (91%), SM@31:Rf (3%), SM@33:e_dprim (1%), SM@31:e_qprim (1%) |
| 74 | -2.397 | — | +100.0 | | SM@34:pm (67%), SM@37:pm (6%), SM@31:pm (6%), SM@38:pm (5%) |
| 75 | -2.451 | — | +100.0 | | SM@32:pm (46%), SM@33:pm (38%), SM@31:pm (8%), SM@34:pm (2%) |
| 76 | -2.422 | — | +100.0 | | SM@35:pm (34%), SM@36:pm (24%), SM@37:pm (18%), SM@38:pm (7%) |
| 77 | -2.425 | — | +100.0 | | SM@31:pm (54%), SM@37:pm (20%), SM@38:pm (9%), SM@32:pm (8%) |
| 78 | -2.433 | — | +100.0 | | SM@38:pm (58%), SM@37:pm (35%), SM@38:psv (2%), SM@38:delta (1%) |
| 79 | -2.447 | — | +100.0 | | SM@35:pm (46%), SM@36:pm (40%), SM@33:pm (5%), SM@32:pm (2%) |
| 80 | -2.449 | — | +100.0 | | SM@33:pm (38%), SM@32:pm (23%), SM@36:pm (17%), SM@31:pm (10%) |
Simulation: 100%|██████████| 100.0/100% [00:00<00:00]
The s-plane shows the same information at a glance. Modes to the right of the dashed damping cone are the ones to watch, the swing modes between 0.6 and 1.6 Hz:
[2]:
dae.plot_eigenvalues(damping_ref=0.05)
The participation factors say which states carry a mode, i.e. where a damping problem lives and which machine a controller should act on. Mode 2 of the report is the least damped oscillatory mode; its participation is shared across machines on both sides of the network, the signature of an inter-area mode rather than a local one:
[3]:
dae.participation_table(mode=2)
[3]:
| state | participation | |
|---|---|---|
| 0 | SM@32:omega | 0.2546 |
| 1 | SM@32:delta | 0.2531 |
| 2 | SM@31:omega | 0.2134 |
| 3 | SM@31:delta | 0.2119 |
| 4 | SM@32:e_qprim | 0.0113 |
| 5 | SM@31:e_qprim | 0.0090 |
| 6 | SM@32:e_dprim | 0.0071 |
| 7 | SM@31:e_qsec | 0.0069 |
| 8 | SM@32:e_qsec | 0.0065 |
| 9 | SM@35:omega | 0.0032 |
Everything shown here is also available as plain data (dae.A, dae.eigenvalues, dae.state_names, and res.small_signal after extract_results), so a parameter study, a damping-versus-gain sweep for example, is a loop over simulate calls away.