hermess.devices.synchronous =========================== .. py:module:: hermess.devices.synchronous Classes ------- .. autoapisummary:: hermess.devices.synchronous.Synchronous hermess.devices.synchronous.SynchronousTransient hermess.devices.synchronous.SynchronousSubtransient hermess.devices.synchronous.SynchronousSubtransientSP hermess.devices.synchronous.SynchronousSubtransientSP6 hermess.devices.synchronous.SynchronousSubtransientSP6DAE hermess.devices.synchronous.SynchronousSubtransientSP_DAE hermess.devices.synchronous.GENROU hermess.devices.synchronous.GENSAL Module Contents --------------- .. py:class:: Synchronous(avr: hermess.devices.avr.AVR = None, governor: hermess.devices.governor.Governor = None, pss: hermess.devices.pss.PSS = None, shaft: hermess.devices.shaft.Shaft = None) Bases: :py:obj:`hermess.devices.device.DeviceRect` Metaclass for SG in rectangular coordinates with TGOV1 governor and pluggable AVR .. py:attribute:: _shaft :type: hermess.devices.shaft.Shaft .. py:attribute:: _avr :type: hermess.devices.avr.AVR .. py:attribute:: _governor :type: hermess.devices.governor.Governor .. py:attribute:: _pss :type: hermess.devices.pss.PSS :value: None .. py:attribute:: fn .. py:attribute:: H .. py:attribute:: R_s .. py:attribute:: x_d .. py:attribute:: x_q .. py:attribute:: x_l .. py:attribute:: D .. py:attribute:: f .. py:attribute:: ns :value: 0 .. py:method:: gcall(dae: hermess.system.Dae, i_d: casadi.SX, i_q: casadi.SX) -> None .. py:method:: _omega_ref(dae: hermess.system.Dae) -> casadi.SX Per-machine reference-frame frequency: the nominal ``dae.omega_net`` (= 1 p.u.) by default, or the per-bus reference frequency when ``dae.omega_ref_buses`` is present. .. py:method:: rotor(dae: hermess.system.Dae, Pe: casadi.SX) -> None Delegate the swing (rotor-motion) equations to the pluggable shaft strategy. The default :class:`SingleMass` writes the classic single-mass swing equation (reading the governor port ``var_sym("pm")``, the air-gap power ``Pe`` and the reference frequency); a multi-mass (torsional) shaft adds further rotor masses while keeping the generator mass on the ``delta`` / ``omega`` names, so the electromagnetic models, the network injection and the controllers are untouched. .. py:method:: fgcall(dae: hermess.system.Dae) -> None Template orchestration shared by all machine models: the EM subclass defines stator currents + flux dynamics and returns the air-gap power; the base wires the rotor, the controller ports, and the network. .. py:method:: electromagnetic(dae: hermess.system.Dae) :abstractmethod: Subclass hook: define the stator currents (i_d, i_q), write the flux/emf differential equations, and return ``(i_d, i_q, Pe)`` where ``Pe`` is the air-gap power/torque consumed by :meth:`rotor`. .. py:method:: governor_fcall(dae: hermess.system.Dae) -> None Delegate the governor's equations to the strategy object. The strategy writes its differential equations into ``dae.f`` and, if it declares private algebraics (e.g. an algebraic 'pm'), their residuals into ``dae.g``. .. py:method:: tgov1(dae: hermess.system.Dae) -> None Deprecated: use governor_fcall instead. .. py:method:: avr_fcall(dae: hermess.system.Dae) -> None Delegate the AVR's equations to the strategy object. The strategy writes its differential equations into ``dae.f`` and, if it declares private algebraics (e.g. an algebraic 'Efd'), their residuals into ``dae.g``. .. py:method:: var_sym(dae: hermess.system.Dae, name: str) -> casadi.SX Resolve a registered variable to its symbol, wherever it lives. A coupling variable such as 'Efd' may be a differential state (in ``dae.x``) or a device-private algebraic (in ``dae.y``), depending on the AVR strategy. This resolver lets the machine's electromagnetic equations reference it without knowing which, so state-based and algebraic exciters are interchangeable. .. py:method:: pss_fcall(dae: hermess.system.Dae) -> None Delegate the PSS's equations to the strategy object (no-op if there is no PSS). The strategy writes its differential equations into ``dae.f`` and, if it declares private algebraics (e.g. an algebraic 'Vs'), their residuals into ``dae.g``. .. py:method:: pss_signal(dae: hermess.system.Dae) -> casadi.SX The supplementary stabilizing signal 'Vs' summed into the AVR voltage error (the host-mediated PSS->AVR coupling). Returns the 'Vs' symbol (state or private algebraic, via :meth:`var_sym`) when a PSS is present, else 0. .. py:method:: ieeedc1a(dae: hermess.system.Dae) -> None Deprecated: use avr_fcall instead. .. py:class:: SynchronousTransient(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`Synchronous` Transient two-axis SG with TGOV1 governor and IEEEDC1A AVR **Rotor Dynamics** .. math:: \dot{\delta} &= 2 \pi f_n \Delta \omega \\ \Delta \dot{\omega} &= \frac{1}{2 H} \left( P_m - E_d I_d - E_q I_q + (X_q' - X_d') I_d I_q - D \Delta \omega - f (\Delta \omega + 1) \right) **Electromagnetic Equations** .. math:: \dot{E}_q &= \frac{1}{T_{d'}} \left( -E_q + E_f + (X_d - X_d') I_d \right)\\ \dot{E}_d &= \frac{1}{T_{q'}} \left( -E_d - (X_q - X_q') I_q \right) **Excitation System Equations** .. math:: \dot{E}_{\textup{fd}} &= \frac{1}{T_{E}} \left( -K_{E,i}E_{\textup{fd},i} + V_{R,i}\right)\\ \dot{R}_{f} &= \frac{1}{T_{F} } \left(- R_{f} + \frac{K_{F}}{T_{F}}E_{\textup{fd}} \right)\\ \dot{V}_{R} &= \frac{1}{T_{A}} \left(-V_{R} + K_{A}R_{f} - \frac{K_{A}K_{F}}{T_{F}}E_{\textup{fd}} + K_{A}(v_{\textup{ref}} - v_i) \right) **Turbine-Governor System Equations** .. math:: \dot{p}_{\textup{m}} &= \frac{1}{T_{ch}} \left( p_{\textup{sv}}- p_{\textup{m}} \right)\\ \dot{p}_{sv} &= \frac{1}{T_{sv}} \left( - \frac{\Delta \omega}{R_d} - p_{\textup{sv}} + p_{\textup{ref}} \right) .. py:attribute:: _type :value: 'Synchronous_machine' .. py:attribute:: _name :value: 'Synchronous_machine_transient_model' .. py:attribute:: e_dprim .. py:attribute:: e_qprim .. py:attribute:: x_dprim .. py:attribute:: x_qprim .. py:attribute:: T_dprim .. py:attribute:: T_qprim .. py:method:: input_current(dae: hermess.system.Dae) -> Tuple[casadi.SX, casadi.SX] .. py:method:: electromagnetic(dae: hermess.system.Dae) Two-axis (transient) electromagnetic model: stator currents, the e'_d/e'_q dynamics, and the air-gap power. The swing equation and orchestration live in the base (rotor / fgcall template). .. py:class:: SynchronousSubtransient(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`Synchronous` Subtransient Anderson Fouad SG with TGOV1 governor and IEEEDC1A AVR The subtransient behavior of the synchronous generator is described by the following differential equations: **Rotor Dynamics** .. math:: \dot{\delta} &= 2 \pi f_n \Delta \omega \\ \Delta \dot{\omega} &= \frac{1}{2 H} \Big( P_m - E_{d}^{\prime\prime} I_d - E_{q}^{\prime\prime} I_q + (X_q^{\prime\prime} - X_d^{\prime\prime}) I_d I_q - D \Delta \omega - f (\Delta \omega + 1) \Big) \\ **Electromagnetic Equations** .. math:: \dot{E}_q^{\prime} &= \frac{1}{T_{d}^{\prime}} \Big( -E_q + E_f + (X_d - X_d^{\prime}) I_d \Big) \\ \dot{E}_d^{\prime} &= \frac{1}{T_{q}^{\prime}} \Big( -E_d - (X_q - X_q^{\prime}) I_q \Big) \\ \dot{E}_{q}^{\prime\prime} &= \frac{1}{T_{d}^{\prime\prime}} \Big( E_q - E_{q}^{\prime\prime} + (X_d^{\prime} - X_d^{\prime\prime}) I_d \Big) \\ \dot{E}_{d}^{\prime\prime} &= \frac{1}{T_{q}^{\prime\prime}} \Big( E_d - E_{d}^{\prime\prime} - (X_q^{\prime} - X_q^{\prime\prime}) I_q \Big) \\ **Excitation System Equations** .. math:: \dot{E}_{\textup{fd}} &= \frac{1}{T_{E}} \left( -K_{E,i}E_{\textup{fd},i} + V_{R,i}\right)\\ \dot{R}_{f} &= \frac{1}{T_{F} } \left(- R_{f} + \frac{K_{F}}{T_{F}}E_{\textup{fd}} \right)\\ \dot{V}_{R} &= \frac{1}{T_{A}} \left(-V_{R} + K_{A}R_{f} - \frac{K_{A}K_{F}}{T_{F}}E_{\textup{fd}} + K_{A}(v_{\textup{ref}} - v_i) \right) **Turbine-Governor System Equations** .. math:: \dot{p}_{\textup{m}} &= \frac{1}{T_{ch}} \left( p_{\textup{sv}}- p_{\textup{m}} \right)\\ \dot{p}_{sv} &= \frac{1}{T_{sv}} \left( - \frac{\Delta \omega}{R_d} - p_{\textup{sv}} + p_{\textup{ref}} \right) .. py:attribute:: _type :value: 'Synchronous_machine' .. py:attribute:: _name :value: 'Synchronous_machine_subtransient_model' .. py:attribute:: e_dprim .. py:attribute:: e_qprim .. py:attribute:: e_dsec .. py:attribute:: e_qsec .. py:attribute:: x_dprim .. py:attribute:: x_qprim .. py:attribute:: T_dprim .. py:attribute:: T_qprim .. py:attribute:: x_dsec .. py:attribute:: x_qsec .. py:attribute:: T_dsec .. py:attribute:: T_qsec .. py:method:: input_current(dae: hermess.system.Dae) -> Tuple[casadi.SX, casadi.SX] .. py:method:: electromagnetic(dae: hermess.system.Dae) Anderson-Fouad (subtransient) electromagnetic model: stator currents, the e'/e'' dynamics, and the air-gap power. Swing/orchestration in base. .. py:class:: SynchronousSubtransientSP(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`Synchronous` Subtransient Sauer and Pai SG model with stator dynamics with TGOV1 governor and IEEEDC1A AVR The model includes the following equations for rotor dynamics, stator dynamics, and the excitation system: **Rotor Dynamics** .. math:: \dot{\delta} &= 2 \pi f_n \Delta \omega \\ \Delta \dot{\omega} &= \frac{1}{2 H} \Big( P_m - (\psi_d I_q - \psi_q I_d) - D \Delta \omega - f (\Delta \omega + 1) \Big) **Electromagnetic Equations** The stator dynamics include the following equations for the flux linkages in the d and q axes: .. math:: \dot{E}_d' &= \frac{1}{T_q'} \Big( -E_d' + (X_q - X_q') (i_q - g_{q2} \Psi_{q2} - (1 - g_{q1}) i_q - g_{q2} E_d') \Big) \\ \dot{E}_q' &= \frac{1}{T_d'} \Big( -E_q' - (X_d - X_d') (i_d - g_{d2} \Psi_{d2} - (1 - g_{d1}) i_d + g_{d2} E_q') + E_f \Big)\\ \dot{\Psi}_{d2} &= \frac{1}{T_{d2}} \Big( -\Psi_{d2} + E_q' - (X_d' - X_l) i_d \Big) \\ \dot{\Psi}_{q2} &= \frac{1}{T_{q2}} \Big( -\Psi_{q2} - E_d' - (X_q' - X_l) i_q \Big) **Flux Linkage Dynamics** The following equations describe the stator flux linkage dynamics in the d and q axes: .. math:: \dot{\Psi}_d &= 2 \pi f_n (R_s i_d + (1 + \Delta \omega) \Psi_q + v_d) \\ \dot{\Psi}_q &= 2 \pi f_n (R_s i_q - (1 + \Delta \omega) \Psi_d + v_q) **Algebraic Equations** The following algebraic equations govern the system: .. math:: i_d &= \frac{1}{x_d''} \Big( -\psi_d + g_{d1} e_q' + (1 - g_{d1}) \psi_{d2} \Big)\\ i_q &= \frac{1}{x_q''} \Big( -\psi_q - g_{q1} e_d' + (1 - g_{q1}) \psi_{q2} \Big)\\ g_{d1} &= \frac{x_d'' - x_l}{x_d' - x_l}\\ g_{q1} &= \frac{x_q'' - x_l}{x_q' - x_l}\\ g_{d2} &= \frac{1 - g_{d1}}{x_d' - x_l}\\ g_{q2} &= \frac{1 - g_{q1}}{x_q' - x_l} .. py:attribute:: _type :value: 'Synchronous_machine' .. py:attribute:: _name :value: 'Synchronous_machine_subtransient_model_Sauer_Pai' .. py:attribute:: e_dprim .. py:attribute:: e_qprim .. py:attribute:: psid .. py:attribute:: psiq .. py:attribute:: psid2 .. py:attribute:: psiq2 .. py:attribute:: x_l .. py:attribute:: gd1 .. py:attribute:: gq1 .. py:attribute:: gd2 .. py:attribute:: gq2 .. py:attribute:: x_dprim .. py:attribute:: x_qprim .. py:attribute:: T_dprim .. py:attribute:: T_qprim .. py:attribute:: x_dsec .. py:attribute:: x_qsec .. py:attribute:: T_dsec .. py:attribute:: T_qsec .. py:method:: sauer_pai(dae: hermess.system.Dae, i_d: casadi.SX, i_q: casadi.SX) Sauer and Pai model. :param dae: :type dae: DAE :param i_d: :type i_d: casadi.SX :param i_q: :type i_q: casadi.SX .. py:method:: _gd_coeffs() -> None Subtransient coupling coefficients used by both the stator-current expressions and the flux ODEs. .. py:method:: input_current(dae: hermess.system.Dae) -> Tuple[casadi.SX, casadi.SX] Stator currents as inlined explicit expressions of the flux states. .. py:method:: electromagnetic(dae: hermess.system.Dae) Sauer-Pai (subtransient, stator dynamics) electromagnetic model. The stator-current derivation is :meth:`input_current` (overridden by the _DAE variant to expose i_d/i_q as private algebraics); the shared flux/ stator physics and the air-gap power live in :meth:`sauer_pai`. .. py:class:: SynchronousSubtransientSP6(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`Synchronous` Subtransient Sauer and Pai SG 6th order model with neglected stator dynamics (stator modeled with algebraic equations) and included TGOV1 governor and IEEEDC1A AVR The model includes the following equations: **Rotor Dynamics** .. math:: \dot{\delta} &= 2 \pi f_n \Delta \omega \\ \Delta \dot{\omega} &= \frac{1}{2 H} \Big( P_m - (\psi_d I_q - \psi_q I_d) - D \Delta \omega - f (\Delta \omega + 1) \Big) **Electromagnetic Equations** The stator dynamics include the following equations for the flux linkages in the d and q axes: .. math:: \dot{E}_d' &= \frac{1}{T_q'} \Big( -E_d' + (X_q - X_q') (i_q - g_{q2} \Psi_{q2} - (1 - g_{q1}) i_q - g_{q2} E_d') \Big) \\ \dot{E}_q' &= \frac{1}{T_d'} \Big( -E_q' - (X_d - X_d') (i_d - g_{d2} \Psi_{d2} - (1 - g_{d1}) i_d + g_{d2} E_q') + E_f \Big)\\ \dot{\Psi}_{d2} &= \frac{1}{T_{d2}} \Big( -\Psi_{d2} + E_q' - (X_d' - X_l) i_d \Big) \\ \dot{\Psi}_{q2} &= \frac{1}{T_{q2}} \Big( -\Psi_{q2} - E_d' - (X_q' - X_l) i_q \Big) **Flux Linkage Dynamics** The following equations describe the stator flux linkage dynamics in the d and q axes: **Algebraic Equations** The following algebraic equations govern the system: .. math:: 0 &=-i_d +\frac{1}{x_d''} \Big( -\psi_d + g_{d1} e_q' + (1 - g_{d1}) \psi_{d2} \Big)\\ 0&=-i_q +\frac{1}{x_q''} \Big( -\psi_q - g_{q1} e_d' + (1 - g_{q1}) \psi_{q2} \Big)\\ 0&= R_s i_d + (1 + \Delta \omega) \Psi_q + v_d \\ 0&= R_s i_q - (1 + \Delta \omega) \Psi_d + v_q \\ g_{d1} &= \frac{x_d'' - x_l}{x_d' - x_l}\\ g_{q1} &= \frac{x_q'' - x_l}{x_q' - x_l}\\ g_{d2} &= \frac{1 - g_{d1}}{x_d' - x_l}\\ g_{q2} &= \frac{1 - g_{q1}}{x_q' - x_l} .. py:attribute:: _type :value: 'Synchronous_machine' .. py:attribute:: _name :value: 'Synchronous_machine_subtransient_model_Sauer_Pai_6th_order' .. py:attribute:: e_dprim .. py:attribute:: e_qprim .. py:attribute:: psid2 .. py:attribute:: psiq2 .. py:attribute:: x_l .. py:attribute:: gd1 .. py:attribute:: gq1 .. py:attribute:: gd2 .. py:attribute:: gq2 .. py:attribute:: x_dprim .. py:attribute:: x_qprim .. py:attribute:: T_dprim .. py:attribute:: T_qprim .. py:attribute:: x_dsec .. py:attribute:: x_qsec .. py:attribute:: T_dsec .. py:attribute:: T_qsec .. py:method:: sauer_pai_6(dae: hermess.system.Dae, i_d: casadi.SX, i_q: casadi.SX, psid: casadi.SX, psiq: casadi.SX) Sauer and Pai model. :param dae: :type dae: DAE :param i_d: :type i_d: casadi.SX :param i_q: :type i_q: casadi.SX :param psid: :type psid: casadi.SX :param psiq: :type psiq: casadi.SX :returns: * * *Args* -- psid (): psiq (): .. py:method:: stator_solve(dae: hermess.system.Dae) Eliminate the four algebraic stator unknowns (i_d, i_q, psi_d, psi_q) by a symbolic 4x4 solve per machine. Returns (i_d, i_q, psid, psiq). The _DAE variant overrides this to expose them as private algebraics. .. py:method:: electromagnetic(dae: hermess.system.Dae) Sauer-Pai 6th-order (algebraic stator) electromagnetic model. The four stator unknowns come from :meth:`stator_solve` (overridden by the _DAE variant to expose them as private algebraics); the shared flux physics and the air-gap power live in :meth:`sauer_pai_6`. .. py:class:: SynchronousSubtransientSP6DAE(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`SynchronousSubtransientSP6` Subtransient Sauer-Pai 6th-order machine expressed as an explicit DAE. Identical physics to :class:`SynchronousSubtransientSP6`, but the four stator unknowns (``i_d, i_q, psi_d, psi_q``) are declared as device-private algebraic variables/equations (``_algebs_int``) and handed to the DAE solver rather than symbolically eliminated with a per-instance ``ca.solve``. Serves as a parity vehicle for the private-algebraic mechanism: it reproduces :class:`SynchronousSubtransientSP6` to integrator tolerance. The stator block is *linear* in the unknowns, so the parent's ``ca.solve`` is the exact solution of ``g = 0``; the DAE integrator converges to the same values via a numerical Newton solve per step instead of a closed-form expression built once. .. py:attribute:: _name :value: 'Synchronous_machine_subtransient_model_Sauer_Pai_6th_order_DAE' .. py:method:: stator_solve(dae: hermess.system.Dae) The four stator unknowns are device-private algebraic variables in dae.y; write their defining equations and return them, so the integrator solves the 4x4 block instead of ca.solve. Inherits SP6's :meth:`electromagnetic` and the base orchestration. .. py:class:: SynchronousSubtransientSP_DAE(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`SynchronousSubtransientSP` Subtransient Sauer-Pai machine (with stator dynamics) with the stator currents exposed as explicit device-private algebraic variables. Identical physics to :class:`SynchronousSubtransientSP`, but the stator currents ``i_d, i_q`` are declared as private algebraic variables (``_algebs_int``) with their defining equations ``0 = -i + `` handed to the DAE solver, rather than inlined as explicit expressions of the flux states. Reproduces :class:`SynchronousSubtransientSP` to integrator tolerance. A parity vehicle for the private-algebraic mechanism: the parent model initialises robustly and the defining equations are linear with a trivially non-singular Jacobian (index-1). .. py:attribute:: _name :value: 'Synchronous_machine_subtransient_model_Sauer_Pai_DAE' .. py:method:: input_current(dae: hermess.system.Dae) -> Tuple[casadi.SX, casadi.SX] Stator currents as device-private algebraic variables in dae.y, defined by 0 = -i + (the same expression the parent inlines). The defining Jacobian dg/di = -1 is trivially non-singular (index-1). Inherits SP's :meth:`electromagnetic` and the base orchestration. .. py:class:: GENROU(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`Synchronous` Sixth-order round-rotor synchronous machine (PSS/E GENROU): two rotor windings per axis, in the K-coefficient form of Gibbard & Vowles 2014, Appendix I.5.1, eqs. (11)-(24). A general-purpose machine model (the SEA benchmark is one user). States: :math:`\delta, \omega, E'_q, \psi_{kd}, E'_d, \psi_{kq}`; the stator is algebraic with the transformer voltages and the speed dependency of the rotational voltages neglected, and magnetic saturation disabled: .. math:: T'_{d0}\dot{E}'_q &= E_{fd} - [K_{1d}E'_q + K_{2d}\psi_{kd} + K_{3d}I_d] \\ T''_{d0}\dot{\psi}_{kd} &= E'_q - \psi_{kd} - (X'_d - X_a) I_d \\ T'_{q0}\dot{E}'_d &= K_{1q}E'_d + K_{2q}\psi_{kq} + K_{3q}I_q \\ T''_{q0}\dot{\psi}_{kq} &= E'_d - \psi_{kq} + (X'_q - X_a) I_q with the stator equations :math:`v_d = -R_s I_d + X''_q I_q + \psi''_q`, :math:`v_q = -R_s I_q - X''_d I_d + \psi''_d`, the subtransient flux linkages (19)-(20) and the coupling coefficients (22)/(24). The air-gap power follows from the stator equations as :math:`P_e = \psi''_d I_q + \psi''_q I_d + (X''_q - X''_d) I_d I_q`. The ``+(X'_q - X_a) I_q`` sign in the last differential equation is deliberate (see the sign note in :meth:`electromagnetic`): with the stator convention above, the q-axis steady state must reproduce ``v_d = X_q I_q``. It is independently cross-validated against the PSID GENROU reference equations. All reactances/time constants in per unit on the machine MVA rating. .. py:attribute:: _type :value: 'Synchronous_machine' .. py:attribute:: _name :value: 'Synchronous_machine_GENROU' .. py:attribute:: e_qprim .. py:attribute:: psi_kd .. py:attribute:: e_dprim .. py:attribute:: psi_kq .. py:attribute:: x_a .. py:attribute:: x_dprim .. py:attribute:: x_qprim .. py:attribute:: x_dsec .. py:attribute:: x_qsec .. py:attribute:: T_d0prim .. py:attribute:: T_q0prim .. py:attribute:: T_d0sec .. py:attribute:: T_q0sec .. py:method:: finit_guess(dae: hermess.system.Dae) Operating-point-aware Newton seeds from the power-flow phasors. The machine equations have a mirror (saddle) equilibrium at delta − π with all EMFs negated; with a uniform delta guess, Newton lands in the wrong basin for machines at buses with large voltage angles. Seed each instance from the standard phasor construction E_q = V + (R_s + j·x_q)·I instead (and the exact steady-state chain for the rotor states), which puts the guess next to the physical root. .. py:method:: _seed_values(dae, i, *, delta, eq1, psikd, ed1, psikq, iq, efd, v_t) -> dict Map the phasor-derived quantities onto this class's state names; AVR/PSS/governor states default to their steady-state values. .. py:method:: _subtransient_flux(dae: hermess.system.Dae) psi''_d, psi''_q from eqs. (19)-(20). .. py:method:: input_current(dae: hermess.system.Dae) -> Tuple[casadi.SX, casadi.SX] .. py:method:: electromagnetic(dae: hermess.system.Dae) Subclass hook: define the stator currents (i_d, i_q), write the flux/emf differential equations, and return ``(i_d, i_q, Pe)`` where ``Pe`` is the air-gap power/torque consumed by :meth:`rotor`. .. py:class:: GENSAL(avr=None, governor=None, pss=None, shaft=None) Bases: :py:obj:`GENROU` Fifth-order salient-pole synchronous machine (PSS/E GENSAL): two rotor windings on the d-axis, one on the q-axis. The d-axis circuits and the equations of motion are those of :class:`GENROU`; the q-axis transient pair :math:`(E'_d, \psi_{kq})` is replaced by the single subtransient flux state :math:`\psi''_q`, in the K-coefficient form of Gibbard & Vowles 2014, Appendix I.5.2, eqs. (25)-(26): .. math:: T''_{q0}\,\dot{\psi}''_q = -\psi''_q + (X_q - X''_q) I_q . The ``+(X_q - X''_q) I_q`` sign is deliberate (the q-axis steady state must give :math:`\psi''_q = (X_q - X''_q) I_q` so that ``v_d = X_q I_q``); it is cross-validated against the PSID GENSAL reference equations, which define their ``psi_q''`` state with the opposite sign. .. py:attribute:: _name :value: 'Synchronous_machine_GENSAL' .. py:attribute:: psi_qsec .. py:method:: _subtransient_flux(dae: hermess.system.Dae) psi''_d, psi''_q from eqs. (19)-(20). .. py:method:: electromagnetic(dae: hermess.system.Dae) Subclass hook: define the stator currents (i_d, i_q), write the flux/emf differential equations, and return ``(i_d, i_q, Pe)`` where ``Pe`` is the air-gap power/torque consumed by :meth:`rotor`.