Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
- Remove data copying between system and components in `PowerElectronics` models.
- Added multi-contingency analysis application.
- Added `BusToSignalAdapter` component for communicating bus voltages and injection currents.
- Added `REGCA` converter model implementation for PhasorDynamics.
- Added `HYGOV` governor model implementation for PhasorDynamics.

## v0.1

Expand Down
30 changes: 27 additions & 3 deletions GridKit/CommonMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,31 @@ namespace GridKit
}

/**
* @brief Smooth two-sided deadband function
* @brief Smooth Type 1 no-offset two-sided deadband function
*
* Smooth approximation to a deadband that returns zero inside the band and
* passes the input through unchanged outside the band.
*
* @tparam ScalarT - scalar data type
* @tparam RealT - Real data type (see GridKit::ScalarTraits<ScalarT>::RealT)
*
* @param[in] x - Input signal
* @param[in] lower - Lower breakpoint
* @param[in] upper - Upper breakpoint
* @return Smooth no-offset deadbanded value
*/
template <class ScalarT, typename RealT>
__attribute__((always_inline)) inline ScalarT deadband1(
const ScalarT x,
const RealT lower,
const RealT upper)
{
assert(lower <= upper);
return x * (sigmoid(lower - x) + sigmoid(x - upper));
}

/**
* @brief Smooth Type 2 offset two-sided deadband function
*
* Smooth approximation to x - min(max(x, lower), upper), composed from the
* smooth ramp function.
Expand All @@ -164,10 +188,10 @@ namespace GridKit
* @param[in] x - Input signal
* @param[in] lower - Lower breakpoint
* @param[in] upper - Upper breakpoint
* @return Smooth deadbanded value
* @return Smooth offset deadbanded value
*/
template <class ScalarT, typename RealT>
__attribute__((always_inline)) inline ScalarT deadband(
__attribute__((always_inline)) inline ScalarT deadband2(
const ScalarT x,
const RealT lower,
const RealT upper)
Expand Down
16 changes: 13 additions & 3 deletions GridKit/CommonMath.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ The scale $\mu=4\cdot f_{\text{sync}}=240$ is chosen so $\sigma$ behaves like a
| `max` | Smooth binary maximum | `REECA` |
| `min` | Smooth binary minimum | `REECA` |
| `clamp` | Bounded saturation | `IEEEST` |
| `deadband` | Signed two-sided deadband | `REECA` |
| `deadband1` | Type 1 no-offset signed two-sided deadband | - |
| `deadband2` | Type 2 offset signed two-sided deadband | `REECA` |
| `slew` | Symmetric slew-rate limiter | - |
| `linseg` | Saturated linear segment contribution | `REGCA`, `REECA` |
| `above` | Above-lower-limit indicator | - |
Expand Down Expand Up @@ -84,7 +85,15 @@ x & \ell \le x \le u \\
u & x > u
\end{cases}
\\
\text{deadband}(x;\ell,u)
\text{deadband1}(x;\ell,u)
&=
\begin{cases}
x & x < \ell \\
0 & \ell \le x \le u \\
x & x > u
\end{cases}
\\
\text{deadband2}(x;\ell,u)
&=
\begin{cases}
x-\ell & x < \ell \\
Expand Down Expand Up @@ -156,7 +165,8 @@ f & x \ge u \land f < 0 \\
\text{max}(x,y) &= y+\rho(x-y) \\
\text{min}(x,y) &= x-\rho(x-y) \\
\text{clamp}(x;\ell,u) &= \ell+\rho(x-\ell)-\rho(x-u) \\
\text{deadband}(x;\ell,u) &= \rho(x-u)-\rho(\ell-x) \\
\text{deadband1}(x;\ell,u) &= x\left[\sigma(\ell-x)+\sigma(x-u)\right] \\
\text{deadband2}(x;\ell,u) &= \rho(x-u)-\rho(\ell-x) \\
\text{slew}(f;r) &= -r+\rho(f+r)-\rho(f-r) \\
\text{linseg}(x;a,b,h) &= \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right] \\
\text{above}(x;\ell) &= \sigma(x-\ell) \\
Expand Down
1 change: 1 addition & 0 deletions GridKit/Model/PhasorDynamics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ add_subdirectory(Branch)
add_subdirectory(Bus)
add_subdirectory(BusFault)
add_subdirectory(BusToSignalAdapter)
add_subdirectory(Converter)
add_subdirectory(Exciter)
add_subdirectory(Governor)
add_subdirectory(Load)
Expand Down
2 changes: 2 additions & 0 deletions GridKit/Model/PhasorDynamics/ComponentLibrary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
#include <GridKit/Model/PhasorDynamics/Bus/Bus.hpp>
#include <GridKit/Model/PhasorDynamics/BusFault/BusFault.hpp>
#include <GridKit/Model/PhasorDynamics/BusToSignalAdapter/BusToSignalAdapter.hpp>
#include <GridKit/Model/PhasorDynamics/Converter/REGCA/Regca.hpp>
#include <GridKit/Model/PhasorDynamics/Exciter/IEEET1/Ieeet1.hpp>
#include <GridKit/Model/PhasorDynamics/Exciter/SEXS-PTI/SexsPti.hpp>
#include <GridKit/Model/PhasorDynamics/Governor/HYGOV/Hygov.hpp>
#include <GridKit/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp>
#include <GridKit/Model/PhasorDynamics/Load/Load.hpp>
#include <GridKit/Model/PhasorDynamics/LoadZIP/LoadZIP.hpp>
Expand Down
6 changes: 6 additions & 0 deletions GridKit/Model/PhasorDynamics/Converter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# [[
# Author(s):
# - Luke Lowery <lukel@tamu.edu>
# ]]

add_subdirectory(REGCA)
8 changes: 4 additions & 4 deletions GridKit/Model/PhasorDynamics/Converter/REECA/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ Symbol | Units | Description |
$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 `deadband`
$V_{\mathrm{err}}$ | [p.u.] | Deadbanded voltage error | Defined by CommonMath `deadband2`
$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}}$
Expand Down Expand Up @@ -262,7 +262,7 @@ The algebraic targets use CommonMath helper notation where applicable:
0 &= -V_T^2 + V_\mathrm r^2 + V_\mathrm i^2 \\
0 &= -V_\mathrm{meas}^\mathrm{safe} + \max(V_\mathrm{meas}, 0.01) \\
0 &= -s_\mathrm{dip} + \text{outside}(V_T, V_\mathrm{dip}, V_\mathrm{up}) \\
0 &= -V_\mathrm{err} + \text{deadband}(V_\mathrm{ref0} - V_\mathrm{meas}, D_\mathrm{bd1}, D_\mathrm{bd2}) \\
0 &= -V_\mathrm{err} + \text{deadband2}(V_\mathrm{ref0} - V_\mathrm{meas}, D_\mathrm{bd1}, D_\mathrm{bd2}) \\
0 &= -I_\mathrm{qv} + \text{clamp}(K_\mathrm{qv} V_\mathrm{err}, I_\mathrm{qinj}^{\min}, I_\mathrm{qinj}^{\max}) \\
0 &= -Q_\mathrm{ref}
+ s_\mathrm{pf} P_\mathrm{meas}\tan(\phi_\mathrm{pf}^\mathrm{ref})
Expand Down Expand Up @@ -290,7 +290,7 @@ 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](../../../../CommonMath.md#derived-functions).
CommonMath defines the helper targets and smooth approximations for [min, max, clamp, deadband2, and outside](../../../../CommonMath.md#derived-functions).

## Initialization

Expand Down Expand Up @@ -324,7 +324,7 @@ Then evaluate the upstream algebraic chain:
\begin{aligned}
V_{\mathrm{meas},0}^{\mathrm{safe}} &= \text{max}(V_{\mathrm{meas},0}, 0.01) \\
s_{\mathrm{dip},0} &= \text{outside}(V_{T,0}, V_{\mathrm{dip}}, V_{\mathrm{up}}) \\
V_{\mathrm{err},0} &= \text{deadband}(V_{\mathrm{ref0}} - V_{\mathrm{meas},0}, D_{\mathrm{bd1}}, D_{\mathrm{bd2}}) \\
V_{\mathrm{err},0} &= \text{deadband2}(V_{\mathrm{ref0}} - V_{\mathrm{meas},0}, D_{\mathrm{bd1}}, D_{\mathrm{bd2}}) \\
I_{\mathrm{qv},0} &= \text{clamp}(K_{\mathrm{qv}} V_{\mathrm{err},0}, I_{\mathrm{qinj}}^{\min}, I_{\mathrm{qinj}}^{\max}) \\
Q_{\mathrm{ref},0} &= s_{\mathrm{pf}} P_{\mathrm{meas},0}\tan(\phi_{\mathrm{pf},0}^{\mathrm{ref}}) + s_{\mathrm{pf}}^{\mathrm{off}} Q_{\mathrm{ext},0} \\
e_{Q,0} &= \text{clamp}(Q_{\mathrm{ref},0}, Q^{\min}, Q^{\max}) - Q_{\mathrm{gen},0} \\
Expand Down
49 changes: 49 additions & 0 deletions GridKit/Model/PhasorDynamics/Converter/REGCA/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# [[
# Author(s):
# - Luke Lowery <lukel@tamu.edu>
# ]]

set(_install_headers
Regca.hpp
RegcaData.hpp)

if(GRIDKIT_ENABLE_ENZYME)
gridkit_add_library(phasor_dynamics_converter_regca
SOURCES
RegcaEnzyme.cpp
HEADERS
${_install_headers}
INCLUDE_DIRECTORIES
PRIVATE ${GRIDKIT_THIRD_PARTY_DIR}/magic-enum/include
LINK_LIBRARIES
PUBLIC GridKit::phasor_dynamics_core
PUBLIC GridKit::phasor_dynamics_signal
PRIVATE ClangEnzymeFlags
COMPILE_OPTIONS
PRIVATE -mllvm -enzyme-auto-sparsity=1 -fno-math-errno)
else()
gridkit_add_library(phasor_dynamics_converter_regca
SOURCES
Regca.cpp
HEADERS
${_install_headers}
INCLUDE_DIRECTORIES
PRIVATE ${GRIDKIT_THIRD_PARTY_DIR}/magic-enum/include
LINK_LIBRARIES
PUBLIC GridKit::phasor_dynamics_core
PUBLIC GridKit::phasor_dynamics_signal)
endif()

gridkit_add_library(phasor_dynamics_converter_regca_dependency_tracking
SOURCES
RegcaDependencyTracking.cpp
INCLUDE_DIRECTORIES
PRIVATE ${GRIDKIT_THIRD_PARTY_DIR}/magic-enum/include
LINK_LIBRARIES
PUBLIC GridKit::phasor_dynamics_core
PUBLIC GridKit::phasor_dynamics_signal_dependency_tracking)

target_link_libraries(phasor_dynamics_components
INTERFACE GridKit::phasor_dynamics_converter_regca)
target_link_libraries(phasor_dynamics_components_dependency_tracking
INTERFACE GridKit::phasor_dynamics_converter_regca_dependency_tracking)
12 changes: 6 additions & 6 deletions GridKit/Model/PhasorDynamics/Converter/REGCA/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Symbol | Units | Description
---------------------------------|----------|-------------------------------------------------------|---------------|------
$P_{\mathrm{0}}$ | [p.u.] | Initial active power injection | | On system base
$Q_{\mathrm{0}}$ | [p.u.] | Initial reactive power injection | | On system base
$S^{\mathrm{conv}}$ | [MVA] | Converter/model power base | TBD |
$S^{\text{base}}$ | [MVA] | REGCA model power base | TBD | JSON key: `mva_base`
$T_{\mathrm{g}}$ | [sec] | Converter current-control lag time constant | TBD |
$T_M$ | [sec] | Terminal voltage sensor time constant | TBD | Block name: `Tfltr`
$R_{\mathrm{q}}^{\max}$ | [p.u./s] | Reactive-current recovery positive rate limit | TBD | Block name: `Iqrmax`
Expand All @@ -45,7 +45,7 @@ Implementations should reject or report invalid parameter sets:

```math
\begin{aligned}
S^{\mathrm{conv}} &> 0 &
S^{\text{base}} &> 0 &
T_{\mathrm{g}} &> 0 &
T_M &> 0 \\
R_{\mathrm{p}}^{\max} &> 0 &
Expand Down Expand Up @@ -241,8 +241,8 @@ REGCA currents:

```math
\begin{aligned}
I_{\mathrm{r}}^{\mathrm{inj}} &:= I_{\mathrm{r}}\dfrac{S^{\mathrm{conv}}}{S^{\mathrm{sys}}} \\
I_{\mathrm{i}}^{\mathrm{inj}} &:= I_{\mathrm{i}}\dfrac{S^{\mathrm{conv}}}{S^{\mathrm{sys}}}
I_{\mathrm{r}}^{\mathrm{inj}} &:= I_{\mathrm{r}}\dfrac{S^{\text{base}}}{S^{\text{sys}}} \\
I_{\mathrm{i}}^{\mathrm{inj}} &:= I_{\mathrm{i}}\dfrac{S^{\text{base}}}{S^{\text{sys}}}
\end{aligned}
```

Expand All @@ -257,9 +257,9 @@ steady-state initial values:
\begin{aligned}
V_T &= \sqrt{V_\mathrm{r}^2 + V_\mathrm{i}^2} \\
I_\mathrm{r0} &= \dfrac{P_0 V_\mathrm{r} + Q_0 V_\mathrm{i}}{V_T^2}
\dfrac{S^\mathrm{sys}}{S^\mathrm{conv}} \\
\dfrac{S^{\text{sys}}}{S^{\text{base}}} \\
I_\mathrm{i0} &= \dfrac{P_0 V_\mathrm{i} - Q_0 V_\mathrm{r}}{V_T^2}
\dfrac{S^\mathrm{sys}}{S^\mathrm{conv}} \\
\dfrac{S^{\text{sys}}}{S^{\text{base}}} \\
V_{M0} &= V_T \\
I_{L0} &= \text{linseg}(V_T;\ V_{L0},\ V_{L1},\ I_{L1}) \\
I_\mathrm{p0} &= \dfrac{I_\mathrm{r0}}
Expand Down
27 changes: 27 additions & 0 deletions GridKit/Model/PhasorDynamics/Converter/REGCA/Regca.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @file Regca.cpp
* @author Luke Lowery (lukel@tamu.edu)
* @brief Non-Enzyme instantiation for the REGCA converter model.
*/

#include "RegcaImpl.hpp"

namespace GridKit
{
namespace PhasorDynamics
{
namespace Converter
{
template <class ScalarT, typename IdxT>
int Regca<ScalarT, IdxT>::evaluateJacobian()
{
Log::misc() << "Evaluate Jacobian for Regca..." << std::endl;
Log::misc() << "Jacobian evaluation is not implemented!" << std::endl;
return 0;
}

template class Regca<double, long int>;
template class Regca<double, size_t>;
} // namespace Converter
} // namespace PhasorDynamics
} // namespace GridKit
Loading
Loading