Dynamic Models

Below is the list of all dynamic models used in the system. The corresponding classes are located in the ./devices directory. The following documentation describes the mathematical equations and the python implementation. Detailed instructions on how to create user-defined models aro not yet available.

Metaclass

All devices are derived from

class pydynamicestimator.devices.device.DeviceRect[source]

Dynamic or static device modeled in rectangular coordinates. Used as a parent class for all devices modeled in rectangular coordinates.

properties

Flags for method calls (e.g., ‘gcall’, ‘fcall’).

Type:

dict[str, bool]

xf

Final state results for simulation/estimation.

Type:

dict[str, np.ndarray]

xinit

Initial state values for all devices of the instance.

Type:

dict[State, list[float]]

xmin

Minimum limited state value.

Type:

list[float]

xmax

Maximum limited state value.

Type:

list[float]

_params

Device parameters, such as rated voltage, power, and frequency and internal parameters.

Type:

dict[str, float]

_data

Additional data which will be used in a list, one entry for each device of this object instance.

Type:

dict[str, str]

bus

Buses where the device is connected. Each device has an entry in the list.

Type:

list[Optional[str]]

states

State variables.

Type:

list[States]

units

Units of state variables.

Type:

list[States]

ns

Total number of states in the model.

Type:

float

_states_noise

Noise for each state variable.

Type:

dict[States, float]

_states_init_error

Initial error for each state variable.

Type:

dict[States, float]

vre

Order of the real voltage value for each device in the overall DAE model.

Type:

list[float]

vim

Order of the real voltage value for each device in the overall DAE model.

Type:

list[float]

_algebs

Algebraic variables (‘vre’, ‘vim’).

Type:

list[str]

_descr

Descriptions for key parameters.

Type:

dict[str, str]

The method for generating the differential and algebraic equations in each model is:

pydynamicestimator.devices.device.DeviceRect.fgcall(self, dae)

A method that executes the differential and algebraic equations of the model and adds them to the appropriate places in the Dae class

Parameters:

dae (Dae) – an instance of a class Dae

Returns:

None

Return type:

None

Synchronous Generator Transient Model

The Synchronous Generator Transient Model provides a two-axis dynamic approximation of a synchronous generator. It is based on the formulation provided in [1].

Python Implementation

class pydynamicestimator.devices.synchronous.SynchronousTransient[source]

Transient two-axis SG with TGOV1 governor and IEEEDC1A AVR

Rotor Dynamics

\[\begin{split}\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)\end{split}\]

Electromagnetic Equations

\[\begin{split}\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)\end{split}\]

Excitation System Equations

\[\begin{split} \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)\end{split}\]

Turbine-Governor System Equations

\[\begin{split}\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)\end{split}\]

Synchronous Generator Subtransient Model

The Synchronous Generator Subransient Model provides a dynamic approximation of a synchronous generator based on Anderson-Fauad’s model. It is based on the formulation provided in [1].

Python Implementation

class pydynamicestimator.devices.synchronous.SynchronousSubtransient[source]
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

\[\begin{split}\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) \\\end{split}\]

Electromagnetic Equations

\[\begin{split}\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) \\\end{split}\]

Excitation System Equations

\[\begin{split} \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)\end{split}\]

Turbine-Governor System Equations

\[\begin{split}\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)\end{split}\]

Synchronous Generator Subtransient Model (with Stator Dynamics)

The Synchronous Generator Subtransient Model with Stator Dynamics provides a dynamic approximation of a synchronous generator, including stator dynamics, based on the formulation by Sauer and Pai. It extends the standard subtransient model by incorporating additional stator field dynamics, as described in [3].

Python Implementation

class pydynamicestimator.devices.synchronous.SynchronousSubtransientSP[source]
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

\[\begin{split}\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)\end{split}\]

Electromagnetic Equations

The stator dynamics include the following equations for the flux linkages in the d and q axes:

\[\begin{split}\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)\end{split}\]

Flux Linkage Dynamics

The following equations describe the stator flux linkage dynamics in the d and q axes:

\[\begin{split}\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)\end{split}\]

Algebraic Equations

The following algebraic equations govern the system:

\[\begin{split}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}\end{split}\]

Synchronous Generator Subtransient Model (without Stator Dynamics)

The Synchronous Generator Subtransient Model without Stator Dynamics provides a dynamic approximation of a synchronous generator, based on the formulation by Sauer and Pai. The stator dynamics are neglected making the model 6th order [3].

Python Implementation

class pydynamicestimator.devices.synchronous.SynchronousSubtransientSP6[source]
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

\[\begin{split}\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)\end{split}\]

Electromagnetic Equations

The stator dynamics include the following equations for the flux linkages in the d and q axes:

\[\begin{split}\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)\end{split}\]

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:

\[\begin{split}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}\end{split}\]

Converter Metaclass

This is the parent class for all inverter models. It introduces all necessary parameters and also stores the model initialization details with a custom script.

class pydynamicestimator.devices.inverter.Inverter[source]

Metaclass for inverters

filter_init(dae)[source]

Steady-state initialization of the inverter filter. Based on methods used in https://github.com/NREL-Sienna/PowerSimulationsDynamics.jl

Parameters:

dae (pydynamicestimator.system.Dae) – DAE object

Returns:

Vswd (ndarray): d-component of the switching block voltage Vswq (ndarray): q-component of the switching block voltage ifd_ext (ndarray): d-component of the filter current in the network (external) dq-reference frame ifq_ext (ndarray): q-component of the filter current in the network (external) dq-reference frame Vfd_ext (ndarray): d-component of the filter voltage in the network (external) dq-reference frame Vfq_ext (ndarray): q-component of the filter voltage in the network (external) dq-reference frame itd_ext (ndarray): d-component of the terminal current in the network (external) dq-reference frame itq_ext (ndarray): q-component of the terminal current in the network (external) dq-reference frame

Return type:

Tuple

finit(dae)[source]
Parameters:

dae (pydynamicestimator.system.Dae)

Returns:

None

frequency_estimator_init(Vfd_ext, Vfq_ext)[source]

Steady-state initialization of the frequency estimator. Based on methods used in https://github.com/NREL-Sienna/PowerSimulationsDynamics.jl

Return type:

Tuple[ndarray, ndarray, ndarray]

Parameters:
  • Vfd_ext (ndarray) – d-component of the filter voltage in the network (external) dq-reference frame

  • Vfq_ext (ndarray) – q-component of the filter voltage in the network (external) dq-reference frame

Returns:

Vfq_pll (ndarray): q-component of the filter voltage in the PLL’s dq-reference frame epsilon (ndarray): integrator state of the PLL delta_pll (ndarray): angle difference between the dq-reference frame of the PLL and the network

Return type:

Tuple

inner_loop_init(dae, ifd_ext, ifq_ext, Vfd_ext, Vfq_ext, Vswd, Vswq)[source]

Steady-state initialization of the inverter inner loop. Based on methods used in https://github.com/NREL-Sienna/PowerSimulationsDynamics.jl

Return type:

Tuple[ndarray, ndarray, ndarray, ndarray, ndarray, ndarray, ndarray, ndarray]

Parameters:
  • dae (pydynamicestimator.system.Dae) – DAE object

  • ifd_ext (ndarray)

  • ifq_ext (ndarray)

  • Vfd_ext (ndarray)

  • Vfq_ext (ndarray)

  • Vswd (ndarray)

  • Vswq (ndarray)

Returns:

delta_c Vref xi_d xi_q gamma_d gamma_q Pc_tilde Qc_tilde

Return type:

Tuple

outer_loop_init(dae, Vfd_ext, Vfq_ext)[source]

Steady-state initialization of the inverter outer loop. Based on methods used in https://github.com/NREL-Sienna/PowerSimulationsDynamics.jl

Return type:

Tuple[ndarray, ndarray]

Parameters:
  • dae (pydynamicestimator.system.Dae) – DAE object

  • Vfd_ext (ndarray) – d-component of the filter voltage in the network (external) dq-reference frame

  • Vfq_ext (ndarray) – q-component of the filter voltage in the network (external) dq-reference frame

Returns:

Pref (ndarray): active power reference Qref (ndarray): reactive power reference

Return type:

Tuple

Grid-Following Converter

The Grid-Following Converter Model provides a dynamic representation of a grid-following inverter. It captures the small-signal stability behavior in low-inertia power systems, as described in [2].

Python Implementation

class pydynamicestimator.devices.inverter.GridFollowing[source]
Grid-Following Inverter (with Droop)

Based on the grid-following inverter model in https://doi.org/10.1109/TPWRS.2021.3061434

The dynamic behavior of the grid-following converter is described by the following differential equations:

Converter Voltage Dynamics

\[\dot{v}_{fd_{ext}} = \frac{\omega_{b}}{c_{f}}(i_{fd_{ext}} - i_{td_{ext}}) + \omega_{net}\omega_{b}v_{fq_{ext}}\]
\[\dot{v}_{fq_{ext}} = \frac{\omega_{b}}{c_{f}}(i_{fq_{ext}} - i_{tq_{ext}}) - \omega_{net}\omega_{b}v_{fd_{ext}}\]

Converter Current Dynamics

\[\dot{i}_{fd_{ext}} = \frac{\omega_{b}}{l_{f}}(v_{swd} - v_{fd_{ext}}) - \frac{\omega_{b}r_{f}}{l_{f}}i_{fd_{ext}} + \omega_{net}\omega_{b}i_{fq_{ext}}\]
\[\dot{i}_{fq_{ext}} = \frac{\omega_{b}}{l_{f}}(v_{swq} - v_{fq_{ext}}) - \frac{\omega_{b}r_{f}}{l_{f}}i_{fq_{ext}} - \omega_{net}\omega_{b}i_{fd_{ext}}\]

Grid-Side Current Dynamics

\[\dot{i}_{td_{ext}} = \frac{\omega_b}{l_t}(v_{fd_{ext}} - v_{n_{re}}) - \frac{\omega_b r_t}{l_t}i_{td_{ext}} + \omega_{net} \omega_b i_{tq_{ext}}\]
\[\dot{i}_{tq_{ext}} = \frac{\omega_b}{l_t}(v_{fq_{ext}} - v_{n_{im}}) - \frac{\omega_b r_t}{l_t}i_{tq_{ext}} - \omega_{net} \omega_b i_{td_{ext}}\]

Phase-Locked Loop (PLL) Dynamics

\[\dot{\epsilon} = v_{fq_{pll}}\]
\[\delta\dot{\theta}_{pll} = \omega_{b}\delta\omega_{pll}\]

Power and Frequency Dynamics

\[\dot{\tilde{p}}_{c} = \omega_{f}(p_{c} - \tilde{p}_{c})\]
\[\delta\dot{\theta}_{c} = \omega_{b}\delta\omega_{c}\]
\[\dot{\tilde{q}}_{c} = \omega_{f}(q_{c} - \tilde{q}_{c})\]

Control Dynamics

\[\dot{\xi}_{d} = v_{fd^{*}} - v_{fd_{int}}\]
\[\dot{\xi}_{q} = v_{fq^{*}} - v_{fq_{int}}\]
\[\dot{\gamma}_{d} = i_{fd^{*}} - i_{fd_{int}}\]
\[\dot{\gamma}_{q} = i_{fq^{*}} - i_{fq_{int}}\]

Grid-Forming Converter

The Grid-Forming Converter Model provides a dynamic representation of a grid-forming inverter. It captures the small-signal stability behavior in low-inertia power systems, as described in [2].

Python Implementation

class pydynamicestimator.devices.inverter.GridForming[source]
Grid-Forming Inverter (Droop-Based)

Based on the grid-forming inverter model in https://doi.org/10.1109/TPWRS.2021.3061434 The dynamic behavior of the grid-forming converter is described by the following differential equations:

Converter Voltage Dynamics

\[\dot{v}_{fd_{ext}} = \frac{\omega_{b}}{c_{f}}(i_{fd_{ext}} - i_{td_{ext}}) + \omega_{net}\omega_{b}v_{fq_{ext}}\]
\[\dot{v}_{fq_{ext}} = \frac{\omega_{b}}{c_{f}}(i_{fq_{ext}} - i_{tq_{ext}}) - \omega_{net}\omega_{b}v_{fd_{ext}}\]

Converter Current Dynamics

\[\dot{i}_{fd_{ext}} = \frac{\omega_{b}}{l_{f}}(v_{swd} - v_{fd_{ext}}) - \frac{\omega_{b}r_{f}}{l_{f}}i_{fd_{ext}} + \omega_{net}\omega_{b}i_{fq_{ext}}\]
\[\dot{i}_{fq_{ext}} = \frac{\omega_{b}}{l_{f}}(v_{swq} - v_{fq_{ext}}) - \frac{\omega_{b}r_{f}}{l_{f}}i_{fq_{ext}} - \omega_{net}\omega_{b}i_{fd_{ext}}\]

Grid-Side Current Dynamics

\[\dot{i}_{td_{ext}} = \frac{\omega_b}{l_t}(v_{fd_{ext}} - v_{n_{re}}) - \frac{\omega_b r_t}{l_t}i_{td_{ext}} + \omega_{net} \omega_b i_{tq_{ext}}\]
\[\dot{i}_{tq_{ext}} = \frac{\omega_b}{l_t}(v_{fq_{ext}} - v_{n_{im}}) - \frac{\omega_b r_t}{l_t}i_{tq_{ext}} - \omega_{net} \omega_b i_{td_{ext}}\]

Power and Frequency Dynamics

\[\dot{\tilde{p}}_{c} = \omega_{f}(p_{c} - \tilde{p}_{c})\]
\[\delta\dot{\theta}_{c} = \omega_{b}\delta\omega_{c}\]
\[\dot{\tilde{q}}_{c} = \omega_{f}(q_{c} - \tilde{q}_{c})\]

Control Dynamics

\[\dot{\xi}_{d} = v_{fd^{*}} - v_{fd_{int}}\]
\[\dot{\xi}_{q} = v_{fq^{*}} - v_{fq_{int}}\]
\[\dot{\gamma}_{d} = i_{fd^{*}} - i_{fd_{int}}\]
\[\dot{\gamma}_{q} = i_{fq^{*}} - i_{fq_{int}}\]

References