Skip to content

Commit c02dbe2

Browse files
committed
Add REECB phasor dynamics model
1 parent 56b6e3c commit c02dbe2

26 files changed

Lines changed: 2344 additions & 34 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
- Added cmake-format hooks, including in pre-commit.
6363
- Added off-nominal tap ratio and phase shift support to the PhasorDynamics `Branch` model.
6464
- Added portable Vector class to GridKit
65+
- Added `REECB` converter model implementation for PhasorDynamics.
6566

6667
## v0.1
6768

GridKit/CommonMath.hpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace GridKit
1515
*
1616
* @note The sigmoid constant (mu) value is chosen to balance accuracy
1717
* and finite derivatives. Large values more closely approximate a step
18-
* function, but lead to inf or NaN derivatives.
18+
* function, but can make the transition numerically stiff.
1919
*
2020
* @tparam ScalarT - scalar data type
2121
*
@@ -27,7 +27,7 @@ namespace GridKit
2727
{
2828
using RealT = typename GridKit::ScalarTraits<ScalarT>::RealT;
2929
static constexpr RealT MU = 240.0;
30-
return ONE<RealT> / (ONE<RealT> + std::exp(-MU * x));
30+
return HALF<RealT> * (ONE<RealT> + std::tanh(HALF<RealT> * MU * x));
3131
}
3232

3333
/**
@@ -153,7 +153,32 @@ namespace GridKit
153153
}
154154

155155
/**
156-
* @brief Smooth two-sided deadband function
156+
* @brief Smooth Type 1 no-offset two-sided deadband function
157+
*
158+
* Smooth approximation to a deadband that returns zero inside the band and
159+
* passes the input through unchanged outside the band.
160+
*
161+
* @tparam ScalarT - scalar data type
162+
* @tparam LowerT - data type of the lower limit
163+
* @tparam UpperT - data type of the upper limit
164+
*
165+
* @param[in] x - Input signal
166+
* @param[in] lower - Lower breakpoint
167+
* @param[in] upper - Upper breakpoint
168+
* @return Smooth no-offset deadbanded value
169+
*/
170+
template <class ScalarT, typename RealT>
171+
__attribute__((always_inline)) inline ScalarT deadband1(
172+
const ScalarT x,
173+
const RealT lower,
174+
const RealT upper)
175+
{
176+
assert(lower <= upper);
177+
return x * (sigmoid(lower - x) + sigmoid(x - upper));
178+
}
179+
180+
/**
181+
* @brief Smooth Type 2 offset two-sided deadband function
157182
*
158183
* Smooth approximation to x - min(max(x, lower), upper), composed from the
159184
* smooth ramp function.
@@ -164,10 +189,10 @@ namespace GridKit
164189
* @param[in] x - Input signal
165190
* @param[in] lower - Lower breakpoint
166191
* @param[in] upper - Upper breakpoint
167-
* @return Smooth deadbanded value
192+
* @return Smooth offset deadbanded value
168193
*/
169194
template <class ScalarT, typename RealT>
170-
__attribute__((always_inline)) inline ScalarT deadband(
195+
__attribute__((always_inline)) inline ScalarT deadband2(
171196
const ScalarT x,
172197
const RealT lower,
173198
const RealT upper)
@@ -331,13 +356,15 @@ namespace GridKit
331356
* @return Scalar value in [0, 1]: 1 when dynamics should pass through,
332357
* 0 when integration should be blocked.
333358
*/
334-
template <class ScalarT, typename RealT>
359+
template <class ScalarT, typename LowerT, typename UpperT>
335360
__attribute__((always_inline)) inline ScalarT indicator(
336361
const ScalarT x,
337362
const ScalarT f,
338-
const RealT limit_min,
339-
const RealT limit_max)
363+
const LowerT limit_min,
364+
const UpperT limit_max)
340365
{
366+
using RealT = typename GridKit::ScalarTraits<ScalarT>::RealT;
367+
341368
assert(limit_min <= limit_max);
342369

343370
ScalarT above_min = above(x, limit_min);
@@ -357,20 +384,21 @@ namespace GridKit
357384
* and blocks motion that would push further into saturation.
358385
*
359386
* @tparam ScalarT - Scalar data type
360-
* @tparam RealT - Real data type (see GridKit::ScalarTraits<ScalarT>::RealT)
387+
* @tparam LowerT - data type of the lower limit
388+
* @tparam UpperT - data type of the upper limit
361389
*
362390
* @param[in] x - Limited state or limited output signal
363391
* @param[in] f - Pre-limit derivative
364392
* @param[in] limit_min - Minimum limit
365393
* @param[in] limit_max - Maximum limit
366394
* @return Smooth anti-windup limited derivative
367395
*/
368-
template <class ScalarT, typename RealT>
396+
template <class ScalarT, typename LowerT, typename UpperT>
369397
__attribute__((always_inline)) inline ScalarT antiwindup(
370398
const ScalarT x,
371399
const ScalarT f,
372-
const RealT limit_min,
373-
const RealT limit_max)
400+
const LowerT limit_min,
401+
const UpperT limit_max)
374402
{
375403
return indicator(x, f, limit_min, limit_max) * f;
376404
}

GridKit/CommonMath.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ The scale $\mu=4\cdot f_{\text{sync}}=240$ is chosen so $\sigma$ behaves like a
4949
| `max` | Smooth binary maximum | `REECA` |
5050
| `min` | Smooth binary minimum | `REECA` |
5151
| `clamp` | Bounded saturation | `IEEEST` |
52-
| `deadband` | Signed two-sided deadband | `REECA` |
52+
| `deadband1` | Type 1 no-offset signed two-sided deadband | - |
53+
| `deadband2` | Type 2 offset signed two-sided deadband | `REECA` |
5354
| `slew` | Symmetric slew-rate limiter | - |
5455
| `linseg` | Saturated linear segment contribution | `REGCA`, `REECA` |
5556
| `above` | Above-lower-limit indicator | - |
@@ -84,7 +85,15 @@ x & \ell \le x \le u \\
8485
u & x > u
8586
\end{cases}
8687
\\
87-
\text{deadband}(x;\ell,u)
88+
\text{deadband1}(x;\ell,u)
89+
&=
90+
\begin{cases}
91+
x & x < \ell \\
92+
0 & \ell \le x \le u \\
93+
x & x > u
94+
\end{cases}
95+
\\
96+
\text{deadband2}(x;\ell,u)
8897
&=
8998
\begin{cases}
9099
x-\ell & x < \ell \\
@@ -156,7 +165,8 @@ f & x \ge u \land f < 0 \\
156165
\text{max}(x,y) &= y+\rho(x-y) \\
157166
\text{min}(x,y) &= x-\rho(x-y) \\
158167
\text{clamp}(x;\ell,u) &= \ell+\rho(x-\ell)-\rho(x-u) \\
159-
\text{deadband}(x;\ell,u) &= \rho(x-u)-\rho(\ell-x) \\
168+
\text{deadband1}(x;\ell,u) &= x\left[\sigma(\ell-x)+\sigma(x-u)\right] \\
169+
\text{deadband2}(x;\ell,u) &= \rho(x-u)-\rho(\ell-x) \\
160170
\text{slew}(f;r) &= -r+\rho(f+r)-\rho(f-r) \\
161171
\text{linseg}(x;a,b,h) &= \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right] \\
162172
\text{above}(x;\ell) &= \sigma(x-\ell) \\

GridKit/Model/PhasorDynamics/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_subdirectory(Branch)
4040
add_subdirectory(Bus)
4141
add_subdirectory(BusFault)
4242
add_subdirectory(BusToSignalAdapter)
43+
add_subdirectory(Converter)
4344
add_subdirectory(Exciter)
4445
add_subdirectory(Governor)
4546
add_subdirectory(Load)

GridKit/Model/PhasorDynamics/ComponentLibrary.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <GridKit/Model/PhasorDynamics/Bus/Bus.hpp>
55
#include <GridKit/Model/PhasorDynamics/BusFault/BusFault.hpp>
66
#include <GridKit/Model/PhasorDynamics/BusToSignalAdapter/BusToSignalAdapter.hpp>
7+
#include <GridKit/Model/PhasorDynamics/Converter/REECB/Reecb.hpp>
78
#include <GridKit/Model/PhasorDynamics/Exciter/IEEET1/Ieeet1.hpp>
89
#include <GridKit/Model/PhasorDynamics/Exciter/SEXS-PTI/SexsPti.hpp>
910
#include <GridKit/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# [[
2+
# Author(s):
3+
# - Luke Lowery <lukel@tamu.edu>
4+
# ]]
5+
6+
add_subdirectory(REECB)

GridKit/Model/PhasorDynamics/Converter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ models and the bus equations, typically through commanded active and reactive cu
99

1010
The GridKit converter documentation includes:
1111

12-
- Renewable Energy Generator/Converter Model REGCA (See [REGCA](REGCA/README.md))
1312
- Renewable Energy Generator/Converter Model REGCB (See [REGCB](REGCB/README.md))
1413
- Renewable Energy Electrical Control Model REECA (See [REECA](REECA/README.md))
14+
- Renewable Energy Electrical Control Model REECB (See [REECB](REECB/README.md))
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# [[
2+
# Author(s):
3+
# - Luke Lowery <lukel@tamu.edu>
4+
# ]]
5+
6+
set(_install_headers Reecb.hpp ReecbData.hpp)
7+
8+
if(GRIDKIT_ENABLE_ENZYME)
9+
gridkit_add_library(
10+
phasor_dynamics_converter_reecb
11+
SOURCES ReecbEnzyme.cpp
12+
HEADERS ${_install_headers}
13+
INCLUDE_DIRECTORIES PRIVATE ${GRIDKIT_THIRD_PARTY_DIR}/magic-enum/include
14+
LINK_LIBRARIES
15+
PUBLIC
16+
GridKit::phasor_dynamics_core
17+
PUBLIC
18+
GridKit::phasor_dynamics_signal
19+
PRIVATE
20+
ClangEnzymeFlags
21+
COMPILE_OPTIONS
22+
PRIVATE
23+
-mllvm
24+
-enzyme-auto-sparsity=1
25+
-fno-math-errno)
26+
else()
27+
gridkit_add_library(
28+
phasor_dynamics_converter_reecb
29+
SOURCES Reecb.cpp
30+
HEADERS ${_install_headers}
31+
INCLUDE_DIRECTORIES PRIVATE ${GRIDKIT_THIRD_PARTY_DIR}/magic-enum/include
32+
LINK_LIBRARIES
33+
PUBLIC
34+
GridKit::phasor_dynamics_core
35+
PUBLIC
36+
GridKit::phasor_dynamics_signal)
37+
endif()
38+
39+
gridkit_add_library(
40+
phasor_dynamics_converter_reecb_dependency_tracking
41+
SOURCES ReecbDependencyTracking.cpp
42+
INCLUDE_DIRECTORIES PRIVATE ${GRIDKIT_THIRD_PARTY_DIR}/magic-enum/include
43+
LINK_LIBRARIES
44+
PUBLIC
45+
GridKit::phasor_dynamics_core
46+
PUBLIC
47+
GridKit::phasor_dynamics_signal_dependency_tracking)
48+
49+
target_link_libraries(
50+
phasor_dynamics_components
51+
INTERFACE GridKit::phasor_dynamics_converter_reecb)
52+
target_link_libraries(
53+
phasor_dynamics_components_dependency_tracking
54+
INTERFACE GridKit::phasor_dynamics_converter_reecb_dependency_tracking)

0 commit comments

Comments
 (0)