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
- 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}}\]