REECA
Source: GridKit/Model/PhasorDynamics/Converter/REECA/README.md
Renewable Energy Electrical Control Model (REECA)
REECA is a WECC renewable energy electrical control model for inverter-coupled resources. In GridKit it is represented as a signal-control model that computes active- and reactive-current commands.
Notes:
Internal electrical quantities and current commands are on model base unless otherwise stated.
Optional signal inputs default to their documented constant values when omitted.
Timer-based post-dip reactive-current injection hold and active-current limit hold are not modeled in this version; \(T_{\mathrm{hld}}\) and \(T_{\mathrm{hld2}}\) must be zero.
Block Diagram
Standard REECA block diagram.
Figure 1: REECA block diagram. Figure courtesy of PowerWorld
Model Parameters
Symbol |
Units |
Description |
Typical Value |
Note |
|---|---|---|---|---|
\(S^{\mathrm{base}}\) |
[MVA] |
REECA model power base |
TBD |
Block name: |
\(s_{\mathrm{pf}}\) |
[binary] |
Power-factor control flag |
TBD |
Block name: |
\(s_V\) |
[binary] |
Voltage-control mode flag |
TBD |
Block name: |
\(s_Q\) |
[binary] |
Reactive-power control flag |
TBD |
Block name: |
\(s_P\) |
[binary] |
Active-power reference speed-multiplier flag |
TBD |
Block name: |
\(s_{PQ}\) |
[binary] |
P/Q priority flag for converter current limit |
TBD |
Block name: |
\(T_{\mathrm{rv}}\) |
[sec] |
Voltage-measurement filter time constant |
TBD |
Block name: |
\(T_{\mathrm{p}}\) |
[sec] |
Electrical-power measurement filter time constant |
TBD |
Block name: |
\(V_{\mathrm{ref0}}\) |
[p.u.] |
Outer-loop voltage reference |
TBD |
Block name: |
\(V_{\mathrm{dip}}\) |
[p.u.] |
Low-voltage threshold for reactive-current injection logic |
TBD |
Block name: |
\(V_{\mathrm{up}}\) |
[p.u.] |
High-voltage threshold for reactive-current injection logic |
TBD |
Block name: |
\(D_{\mathrm{bd1}}\) |
[p.u.] |
Overvoltage deadband for voltage-error response |
TBD |
Block name: |
\(D_{\mathrm{bd2}}\) |
[p.u.] |
Undervoltage deadband for voltage-error response |
TBD |
Block name: |
\(K_{\mathrm{qv}}\) |
[p.u.] |
Reactive-current injection gain during voltage dip/overvoltage logic |
TBD |
Block name: |
\(I_{\mathrm{qinj}}^{\min}\) |
[p.u.] |
Minimum reactive-current injection limit |
TBD |
Block name: |
\(I_{\mathrm{qinj}}^{\max}\) |
[p.u.] |
Maximum reactive-current injection limit |
TBD |
Block name: |
\(I_{\mathrm{qinj}}^{\mathrm{frz}}\) |
[p.u.] |
Held reactive-current injection value after voltage dip |
TBD |
Block name: |
\(T_{\mathrm{hld}}\) |
[sec] |
Reactive-current injection hold time after voltage dip clears |
TBD |
Block name: |
\(Q^{\max}\) |
[p.u.] |
Maximum reactive-power control limit |
TBD |
Block name: |
\(Q^{\min}\) |
[p.u.] |
Minimum reactive-power control limit |
TBD |
Block name: |
\(K_{\mathrm{qp}}\) |
[p.u.] |
Reactive-power control proportional gain |
TBD |
Block name: |
\(K_{\mathrm{qi}}\) |
[p.u./s] |
Reactive-power control integral gain |
TBD |
Block name: |
\(V^{\max}\) |
[p.u.] |
Maximum voltage-control limit |
TBD |
Block name: |
\(V^{\min}\) |
[p.u.] |
Minimum voltage-control limit |
TBD |
Block name: |
\(V_{\mathrm{ref1}}\) |
[p.u.] |
Inner-loop voltage-control reference/bias |
0 |
Block name: |
\(K_{\mathrm{vp}}\) |
[p.u.] |
Voltage-control proportional gain |
TBD |
Block name: |
\(K_{\mathrm{vi}}\) |
[p.u./s] |
Voltage-control integral gain |
TBD |
Block name: |
\(T_{\mathrm{iq}}\) |
[sec] |
Reactive-current command lag time constant |
TBD |
Block name: |
\(T_{\mathrm{pord}}\) |
[sec] |
Active-power order filter time constant |
TBD |
Block name: |
\(R_P^{\max}\) |
[p.u./s] |
Positive active-power order ramp-rate limit |
TBD |
Block name: |
\(R_P^{\min}\) |
[p.u./s] |
Negative active-power order ramp-rate limit |
TBD |
Block name: |
\(P^{\max}\) |
[p.u.] |
Maximum active-power order limit |
TBD |
Block name: |
\(P^{\min}\) |
[p.u.] |
Minimum active-power order limit |
TBD |
Block name: |
\(I^{\max}\) |
[p.u.] |
Maximum total converter current |
TBD |
Block name: |
\(V_{\mathrm{q},1}\) |
[p.u.] |
VDL1 voltage point 1 |
TBD |
Block name: |
\(I_{\mathrm{q},1}^{\max}\) |
[p.u.] |
VDL1 reactive-current limit point 1 |
TBD |
Block name: |
\(V_{\mathrm{q},2}\) |
[p.u.] |
VDL1 voltage point 2 |
TBD |
Block name: |
\(I_{\mathrm{q},2}^{\max}\) |
[p.u.] |
VDL1 reactive-current limit point 2 |
TBD |
Block name: |
\(V_{\mathrm{q},3}\) |
[p.u.] |
VDL1 voltage point 3 |
TBD |
Block name: |
\(I_{\mathrm{q},3}^{\max}\) |
[p.u.] |
VDL1 reactive-current limit point 3 |
TBD |
Block name: |
\(V_{\mathrm{q},4}\) |
[p.u.] |
VDL1 voltage point 4 |
TBD |
Block name: |
\(I_{\mathrm{q},4}^{\max}\) |
[p.u.] |
VDL1 reactive-current limit point 4 |
TBD |
Block name: |
\(V_{\mathrm{p},1}\) |
[p.u.] |
VDL2 voltage point 1 |
TBD |
Block name: |
\(I_{\mathrm{p},1}^{\max}\) |
[p.u.] |
VDL2 active-current limit point 1 |
TBD |
Block name: |
\(V_{\mathrm{p},2}\) |
[p.u.] |
VDL2 voltage point 2 |
TBD |
Block name: |
\(I_{\mathrm{p},2}^{\max}\) |
[p.u.] |
VDL2 active-current limit point 2 |
TBD |
Block name: |
\(V_{\mathrm{p},3}\) |
[p.u.] |
VDL2 voltage point 3 |
TBD |
Block name: |
\(I_{\mathrm{p},3}^{\max}\) |
[p.u.] |
VDL2 active-current limit point 3 |
TBD |
Block name: |
\(V_{\mathrm{p},4}\) |
[p.u.] |
VDL2 voltage point 4 |
TBD |
Block name: |
\(I_{\mathrm{p},4}^{\max}\) |
[p.u.] |
VDL2 active-current limit point 4 |
TBD |
Block name: |
\(T_{\mathrm{hld2}}\) |
[sec] |
Active-current limit hold time after voltage dip clears |
TBD |
Block name: |
Parameter Validation
Implementations should reject invalid REECA parameter sets. If source data preprocessing adjusts active-power ramp-rate or order limits, apply these checks to the effective values used by the equations.
The required checks are:
Model Derived Parameters
The off-mode flag complements are:
The VDL functions use GridKit’s smooth Linear Segment helper and provide flat extrapolation outside the first and fourth voltage points:
Model Variables
Internal Variables
Differential
Symbol |
Units |
Description |
Note |
|---|---|---|---|
\(V_{\mathrm{meas}}\) |
[p.u.] |
Filtered terminal voltage |
State 1 in Fig. 1; source label: |
\(P_{\mathrm{meas}}\) |
[p.u.] |
Filtered electrical power |
State 2 in Fig. 1; source label: |
\(x_{\mathrm{PIQ}}\) |
[p.u.] |
Reactive-power PI controller state |
State 3 in Fig. 1; source label: |
\(x_{\mathrm{PIV}}\) |
[p.u.] |
Voltage PI controller state |
State 4 in Fig. 1; source label: |
\(Q_V\) |
[p.u.] |
Reactive-current command lag state |
State 5 in Fig. 1; source label: |
\(P_{\mathrm{ord}}\) |
[p.u.] |
Filtered active-power order |
State 6 in Fig. 1; source label: |
Algebraic
Symbol |
Units |
Description |
Note |
|---|---|---|---|
\(V_T\) |
[p.u.] |
Terminal voltage magnitude |
|
\(V_{\mathrm{meas}}^{\mathrm{safe}}\) |
[p.u.] |
Safe filtered terminal voltage for divider blocks |
Lower bounded by 0.01 |
\(s_{\mathrm{dip}}\) |
[binary] |
Voltage-dip/overvoltage freeze indicator |
1 when outside voltage thresholds |
\(V_{\mathrm{err}}\) |
[p.u.] |
Deadbanded voltage error |
Defined by CommonMath |
\(I_{\mathrm{qv}}\) |
[p.u.] |
Reactive-current injection candidate |
Converter base |
\(Q_{\mathrm{ref}}\) |
[p.u.] |
Selected reactive-power reference |
From power-factor or external reactive-power command |
\(e_Q\) |
[p.u.] |
Reactive-power control error |
Limited \(Q_{\mathrm{ref}}\) minus \(Q_{\mathrm{gen}}\) |
\(V_{\mathrm{PIQ}}\) |
[p.u.] |
Reactive-power control PI output |
Limited by \(V^{\min}\) and \(V^{\max}\) |
\(e_{\mathrm{PIV}}\) |
[p.u.] |
Voltage-control PI error |
Selected voltage-control signal minus \(V_{\mathrm{meas}}\) |
\(f_{\mathrm{pord}}\) |
[p.u./s] |
Active-power order derivative before ramp-rate limiting |
Feeds \(r_{\mathrm{pord}}\) |
\(r_{\mathrm{pord}}\) |
[p.u./s] |
Ramp-rate-limited active-power order derivative |
Feeds \(P_{\mathrm{ord}}\) anti-windup |
\(I_{\mathrm{q}}^{\mathrm{circ}}\) |
[p.u.] |
Reactive-current limit from converter current circle |
Converter base; nonnegative algebraic branch |
\(I_{\mathrm{p}}^{\mathrm{circ}}\) |
[p.u.] |
Active-current limit from converter current circle |
Converter base; nonnegative algebraic branch |
\(I_{\mathrm{q}}^{\max}\) |
[p.u.] |
Final reactive-current upper limit |
Converter base; updated by VDL1 and current-limit logic |
\(I_{\mathrm{p}}^{\max}\) |
[p.u.] |
Final active-current upper limit |
Converter base; updated by VDL2 and current-limit logic |
\(I_{\mathrm{qbase}}\) |
[p.u.] |
Base reactive-current command |
Converter base; before \(s_Q\) selection and reactive-current injection |
\(I_{\mathrm{q}}^{\mathrm{raw}}\) |
[p.u.] |
Raw reactive-current command before final limit |
Converter base |
\(I_{\mathrm{q}}^{\mathrm{cmd}}\) |
[p.u.] |
Reactive-current command output |
Converter base |
\(I_{\mathrm{p}}^{\mathrm{cmd}}\) |
[p.u.] |
Active-current command output |
Converter base |
External Variables
Differential
Symbol |
Units |
Description |
Note |
|---|---|---|---|
\(\omega\) |
[p.u.] |
Generator speed deviation |
Optional, defaults to zero; source diagram \(\omega_g = 1 + \omega\) |
Algebraic
Symbol |
Units |
Description |
Note |
|---|---|---|---|
\(V_{\mathrm{r}}\) |
[p.u.] |
Terminal voltage, real component |
Owned by bus object |
\(V_{\mathrm{i}}\) |
[p.u.] |
Terminal voltage, imaginary component |
Owned by bus object |
\(P_e\) |
[p.u.] |
Electrical active power |
Source label: |
\(Q_{\mathrm{gen}}\) |
[p.u.] |
Reactive-power feedback |
Source label: |
\(Q_{\mathrm{ext}}\) |
[p.u.] |
External reactive-power command |
Optional, defaults to initialized constant |
\(\phi_{\mathrm{pf}}^{\mathrm{ref}}\) |
[rad] |
Power-factor angle reference |
Source label: |
\(P_{\mathrm{ref}}\) |
[p.u.] |
External active-power reference |
Optional, defaults to initialized constant |
Model Equations
For readability, define:
Differential Equations
The state-equation residuals use compact limiter notation where applicable. The measurement filters are written in descriptor form: if \(T_{\mathrm{rv}} = 0\) or \(T_{\mathrm{p}} = 0\), the corresponding variable should be tagged algebraic. The \(Q_V\) equation also uses \(T_{\mathrm{iq}}\) as a derivative coefficient, but \(T_{\mathrm{iq}} > 0\) remains required because the freeze multiplier makes the zero-time case structurally different.
CommonMath defines the Anti-Windup target and smooth approximation.
Algebraic Equations
The algebraic targets use CommonMath helper notation where applicable:
The \(V_T\), \(I_{\mathrm{q}}^{\mathrm{circ}}\), and \(I_{\mathrm{p}}^{\mathrm{circ}}\) variables use nonnegative branches of squared algebraic residuals. This preserves the \(s_{PQ}=0\) Q-priority and \(s_{PQ}=1\) P-priority current-circle behavior without explicit square roots; a consistent solution should satisfy the nonnegative branch and nonnegative radicands.
CommonMath defines the helper targets and smooth approximations for min, max, clamp, deadband, and outside.
Initialization
Initialization is performed by evaluating the steady-state residuals in dependency order. Let subscript \(0\) denote initial values and set all internal derivatives to zero. If optional signals are not connected, use steady-state constants:
Connected optional signals use their supplied initial values; if only some are omitted, compute the omitted constants with the connected initial values. Inconsistent supplied commands require a residual solve or initialization rejection.
If \(V_{\mathrm{ref0}}\) is omitted, set \(V_{\mathrm{ref0}} = V_{T,0}\). Initialize the measurement variables from the descriptor-form filter residuals:
When \(T_{\mathrm{rv}} = 0\) or \(T_{\mathrm{p}} = 0\), the corresponding relation is an algebraic residual rather than a differential-state initial condition.
Then evaluate the upstream algebraic chain:
Initialize the reactive-power PI output so its residual and zero-derivative anti-windup condition hold:
For an unsaturated zero-derivative start, require \(e_{Q,0}=0\) for \(x_{\mathrm{PIQ}}\) and choose or verify \(e_{\mathrm{PIV},0}=0\) for \(x_{\mathrm{PIV}}\). Then \(x_{\mathrm{PIQ},0}=V_{\mathrm{PIQ},0}-K_{\mathrm{qp}}e_{Q,0}\); when \(s_V=1\), set \(V_{\mathrm{PIQ},0}=V_{\mathrm{meas},0}\), and when \(s_V=0\), the supplied \(Q_{\mathrm{ref},0}+V_{\mathrm{ref1}}\) must equal \(V_{\mathrm{meas},0}\). Saturated initial conditions should be solved against the anti-windup residuals, not forced by this unsaturated formula.
Finish by evaluating \(g_q(V_{\mathrm{meas},0})\), \(g_p(V_{\mathrm{meas},0})\), and the current-limit and current-command algebraic residuals in priority order. At the command steps, use the power-flow current targets before final limiting:
For \(s_{PQ}=0\), use:
For \(s_{PQ}=1\), use:
After \(I_{\mathrm{q},0}^{\max}\) and \(I_{\mathrm{qbase},0}\) are known, initialize the voltage PI state from its output residual; the unsaturated zero-derivative start also requires the \(e_{\mathrm{PIV},0}=0\) condition above:
The current-circle variables use the nonnegative branch of the squared algebraic residuals; initialization must reject negative radicands. A standard steady-state initialization assumes \(s_{\mathrm{dip},0}=0\). If initialized during voltage-dip or overvoltage logic, \(Q_V\), \(P_{\mathrm{ord}}\), and the PI histories are not uniquely determined without the unsupported hold-timer histories, so the implementation should solve a saturation-consistent state or reject the start.
Model Outputs
Output |
Units |
Description |
Note |
|---|---|---|---|
|
[p.u.] |
Reactive-current command output |
Converter base |
|
[p.u.] |
Active-current command output |
Converter base |
|
[p.u.] |
Filtered terminal voltage |
|
|
[p.u.] |
Filtered electrical power |
|
|
[p.u.] |
Reactive-power PI controller state |
|
|
[p.u.] |
Voltage PI controller state |
|
|
[p.u.] |
Reactive-current command lag state |
|
|
[p.u.] |
Filtered active-power order |
|
|
[p.u.] |
Selected reactive-power reference |
|
|
[binary] |
Voltage-dip/overvoltage freeze indicator |
|
|
[p.u.] |
Final reactive-current upper limit |
Converter base |
|
[p.u.] |
Final active-current upper limit |
Converter base |
|
[p.u.] |
Reactive-current injection candidate |
Converter base |
|
[p.u.] |
Reactive-power control PI output |
|
|
[p.u.] |
Base reactive-current command |
Converter base |
Outstanding
Nonzero \(T_{\mathrm{hld}}\) and \(T_{\mathrm{hld2}}\) require timer/history-state support and are not modeled yet. With the required zero values, \(I_{\mathrm{qinj}}^{\mathrm{frz}}\) is unreachable and \(I_{\mathrm{p}}^{\max}\) is recalculated from VDL2 and current-circle logic at each residual evaluation instead of held after voltage recovery.
A future smooth approximation of the held reactive-current path could introduce a continuous gate \(h_q\):
That approximation is a modeling choice and is not part of the present equations.