Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
48ade08
Use relative errors by default when comparing output files
PhilipFackler May 22, 2026
9bc043c
Avoid adding monitor sink when not intended
PhilipFackler Jun 16, 2026
1af2973
Document ESDC1A exciter model
lukelowry May 31, 2026
2b42a2d
Implement ESDC1A exciter model
lukelowry Jun 1, 2026
3fce76c
Apply pre-commmit fixes
lukelowry Jun 2, 2026
f7b5020
Add HYGOV phasor dynamics governor
lukelowry May 29, 2026
cb8ce73
Add GASTPTI phasor dynamics governor
lukelowry May 28, 2026
13f6d15
Add REECB phasor dynamics model
lukelowry May 30, 2026
bc74cd2
Add discriminating type for upper and lower limits
lukelowry Jun 11, 2026
87719b5
Add REPCA phasor dynamics model
lukelowry May 28, 2026
12c248f
Use system base for governor-machine power signals
lukelowry Jun 5, 2026
0f3ca5a
Support zero IEEET1 transducer time constant
lukelowry Jun 5, 2026
50d4f69
Add zero tol inequality for Tr
lukelowry Jun 7, 2026
3d0bd28
Remove old exciter scaling
lukelowry Jun 8, 2026
6d68902
Fix bad parameter initialization and polish docs
lukelowry Jun 8, 2026
509506c
Update Docs
lukelowry Jun 8, 2026
47d55cc
REGCA skeleton
lukelowry May 17, 2026
b03c8bf
REGCA Implementation and Tests
lukelowry May 17, 2026
315004e
Doc polish, Corrections and Update CHANGELOG
lukelowry Jun 2, 2026
8540726
Add default PhasorDynamics component tolerances
lukelowry Jun 22, 2026
bdc47a0
Add default PhasorDynamics component tolerances
lukelowry Jun 22, 2026
a3c5d2f
Add default PhasorDynamics component tolerances
lukelowry Jun 22, 2026
3e43519
Add default PhasorDynamics component tolerances
lukelowry Jun 22, 2026
72db549
Add default PhasorDynamics component tolerances
lukelowry Jun 22, 2026
406aad9
Add default PhasorDynamics component tolerances
lukelowry Jun 22, 2026
1feb650
Merge remote-tracking branch 'origin/PhilipFackler/fix-disabled-monit…
lukelowry Jun 23, 2026
c3eee16
Merge remote-tracking branch 'origin/PhilipFackler/rel-errors' into l…
lukelowry Jun 23, 2026
64151c0
Merge remote-tracking branch 'origin/lukel/gov-mva-dev' into lukel/te…
lukelowry Jun 23, 2026
d55dcc1
Merge remote-tracking branch 'origin/lukel/ieeet1-tr-zero-safety' int…
lukelowry Jun 23, 2026
4731bb7
Merge remote-tracking branch 'origin/lukel/ieeest-dev' into lukel/ten…
lukelowry Jun 23, 2026
82875eb
Merge remote-tracking branch 'origin/lukel/reecb-dev' into lukel/tenK…
lukelowry Jun 23, 2026
b7f4eaa
Merge remote-tracking branch 'origin/lukel/regca-impl' into lukel/ten…
lukelowry Jun 23, 2026
e6eb2b2
Merge remote-tracking branch 'origin/lukel/repca-dev' into lukel/tenK…
lukelowry Jun 23, 2026
23e3081
Merge remote-tracking branch 'origin/lukel/esdc1a-dev' into lukel/ten…
lukelowry Jun 23, 2026
d4341ff
Merge remote-tracking branch 'origin/lukel/gastpti-dev' into lukel/te…
lukelowry Jun 23, 2026
6d5e7d6
Merge remote-tracking branch 'origin/lukel/hygov-dev' into lukel/tenK…
lukelowry Jun 23, 2026
c27490f
Add converter stack initialization regression
lukelowry Jun 23, 2026
6d95c02
10k WECC case successful sim but not steady at init
lukelowry Jun 23, 2026
3b63148
Working without new models, steady
lukelowry Jun 23, 2026
1ef6666
tenk full non steady but working
lukelowry Jun 23, 2026
51ce2a0
esdc1a fix
lukelowry Jun 23, 2026
56bf8be
complete 10k case
lukelowry Jun 23, 2026
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
- Added component model developer checklist to a README file.
- Added `IEEEST` Stabilizer Model
- Added `SEXS-PTI` Exciter Model
- Added `ESDC1A` Exciter Model
- Added `GENSAL` Machine Model
- Added 200 Bus Synthetic Illinois Case
- Added node objects to `PowerElectronics` module & updated all examples to make use of them.
Expand All @@ -64,6 +65,11 @@
- Added off-nominal tap ratio and phase shift support to the PhasorDynamics `Branch` model.
- Added portable Vector class to GridKit
- Added support for running IDA with fixed time steps
- Added `REECB` converter model implementation for PhasorDynamics.
- Added `REGCA` converter model implementation for PhasorDynamics.
- Added `REPCA` converter model implementation for PhasorDynamics.
- Added `GASTPTI` governor model implementation for PhasorDynamics.
- Added `HYGOV` governor model implementation for PhasorDynamics.

## v0.1

Expand Down
56 changes: 45 additions & 11 deletions GridKit/CommonMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,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 @@ -173,10 +197,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 Expand Up @@ -315,22 +339,28 @@ namespace GridKit
* @brief Smooth anti-windup indicator for a limited state variable
*
* @tparam ScalarT - Scalar data type
* @tparam RealT - Real data type (see GridKit::ScalarTraits<ScalarT>::RealT)
* @tparam LowerT - data type of the lower limit
* @tparam UpperT - data type of the upper limit
*
* @param[in] x - State variable
* @param[in] f - Pre-limit derivative of the state variable
* @param[in] limit_min - Minimum limit
* @param[in] limit_max - Maximum limit
* @return Scalar value in [0, 1]: 1 when dynamics should pass through,
* 0 when integration should be blocked.
*
* @note The limit types intentionally may differ from the scalar type so
* that constant Real limits and algebraic-variable limits both work.
*/
template <class ScalarT, typename RealT>
template <class ScalarT, typename LowerT, typename UpperT>
__attribute__((always_inline)) inline ScalarT indicator(
const ScalarT x,
const ScalarT f,
const RealT limit_min,
const RealT limit_max)
const LowerT limit_min,
const UpperT limit_max)
{
using RealT = typename GridKit::ScalarTraits<ScalarT>::RealT;

assert(limit_min <= limit_max);

ScalarT above_min = above(x, limit_min);
Expand All @@ -350,20 +380,24 @@ namespace GridKit
* and blocks motion that would push further into saturation.
*
* @tparam ScalarT - Scalar data type
* @tparam RealT - Real data type (see GridKit::ScalarTraits<ScalarT>::RealT)
* @tparam LowerT - data type of the lower limit
* @tparam UpperT - data type of the upper limit
*
* @param[in] x - Limited state or limited output signal
* @param[in] f - Pre-limit derivative
* @param[in] limit_min - Minimum limit
* @param[in] limit_max - Maximum limit
* @return Smooth anti-windup limited derivative
*
* @note The limit types intentionally may differ from the scalar type so
* that constant Real limits and algebraic-variable limits both work.
*/
template <class ScalarT, typename RealT>
template <class ScalarT, typename LowerT, typename UpperT>
__attribute__((always_inline)) inline ScalarT antiwindup(
const ScalarT x,
const ScalarT f,
const RealT limit_min,
const RealT limit_max)
const LowerT limit_min,
const UpperT limit_max)
{
return indicator(x, f, limit_min, limit_max) * f;
}
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 @@ -33,6 +33,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
10 changes: 10 additions & 0 deletions GridKit/Model/PhasorDynamics/Component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ namespace GridKit
return abs_tol_;
}

int setAbsoluteTolerance(RealT rel_tol) override
{
abs_tol_.resize(static_cast<size_t>(size_));
for (IdxT i = 0; i < size_; ++i)
{
abs_tol_[static_cast<size_t>(i)] = rel_tol;
}
return 0;
}

std::vector<ScalarT>& getResidual() override
{
return f_;
Expand Down
6 changes: 6 additions & 0 deletions GridKit/Model/PhasorDynamics/ComponentLibrary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
#include <GridKit/Model/PhasorDynamics/Bus/BusInfinite.hpp>
#include <GridKit/Model/PhasorDynamics/BusFault/BusFault.hpp>
#include <GridKit/Model/PhasorDynamics/BusToSignalAdapter/BusToSignalAdapter.hpp>
#include <GridKit/Model/PhasorDynamics/Converter/REECB/Reecb.hpp>
#include <GridKit/Model/PhasorDynamics/Converter/REGCA/Regca.hpp>
#include <GridKit/Model/PhasorDynamics/Converter/REPCA/Repca.hpp>
#include <GridKit/Model/PhasorDynamics/Exciter/ESDC1A/Esdc1a.hpp>
#include <GridKit/Model/PhasorDynamics/Exciter/IEEET1/Ieeet1.hpp>
#include <GridKit/Model/PhasorDynamics/Exciter/SEXS-PTI/SexsPti.hpp>
#include <GridKit/Model/PhasorDynamics/Governor/GASTPTI/GastPti.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
8 changes: 8 additions & 0 deletions GridKit/Model/PhasorDynamics/Converter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# [[
# Author(s):
# - Luke Lowery <lukel@tamu.edu>
# ]]

add_subdirectory(REGCA)
add_subdirectory(REECB)
add_subdirectory(REPCA)
2 changes: 2 additions & 0 deletions GridKit/Model/PhasorDynamics/Converter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ The GridKit converter documentation includes:
- Renewable Energy Generator/Converter Model REGCA (See [REGCA](REGCA/README.md))
- Renewable Energy Generator/Converter Model REGCB (See [REGCB](REGCB/README.md))
- Renewable Energy Electrical Control Model REECA (See [REECA](REECA/README.md))
- Renewable Energy Electrical Control Model REECB (See [REECB](REECB/README.md))
- Renewable Energy Plant Control Model REPCA (See [REPCA](REPCA/README.md))
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 @@ -159,7 +159,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 @@ -260,7 +260,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 @@ -288,7 +288,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 @@ -322,7 +322,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
54 changes: 54 additions & 0 deletions GridKit/Model/PhasorDynamics/Converter/REECB/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# [[
# Author(s):
# - Luke Lowery <lukel@tamu.edu>
# ]]

set(_install_headers Reecb.hpp ReecbData.hpp)

if(GRIDKIT_ENABLE_ENZYME)
gridkit_add_library(
phasor_dynamics_converter_reecb
SOURCES ReecbEnzyme.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_reecb
SOURCES Reecb.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_reecb_dependency_tracking
SOURCES ReecbDependencyTracking.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_reecb)
target_link_libraries(
phasor_dynamics_components_dependency_tracking
INTERFACE GridKit::phasor_dynamics_converter_reecb_dependency_tracking)
Loading
Loading