Skip to content

Commit 81dcb76

Browse files
committed
Revise appraoch and syntax
1 parent 0b4ab46 commit 81dcb76

11 files changed

Lines changed: 336 additions & 102 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
- Added off-nominal tap ratio and phase shift support to the PhasorDynamics `Branch` model.
6565
- Added portable Vector class to GridKit
6666
- Added support for running IDA with fixed time steps
67+
- Added `closed` parameter to `Branch` for declaring out-of-service lines in case files.
6768

6869
## v0.1
6970

GridKit/Model/PhasorDynamics/Branch/Branch.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,6 @@ namespace GridKit
131131
void setDerivedParams();
132132
void terminalCurrent1(ScalarT& Ir, ScalarT& Ii);
133133
void terminalCurrent2(ScalarT& Ir, ScalarT& Ii);
134-
bool readRealParameter(const ModelDataT& data,
135-
typename ModelDataT::Parameters parameter,
136-
RealT& target);
137134

138135
static __attribute__((always_inline)) inline void addAdmittanceContribution(RealT G,
139136
RealT B,
@@ -202,6 +199,8 @@ namespace GridKit
202199
RealT B_{0.0};
203200
RealT tap_{1.0};
204201
RealT phase_{0.0};
202+
bool closed_{true};
203+
RealT in_service_factor_{1.0};
205204
IdxT bus1_id_{0};
206205
IdxT bus2_id_{0};
207206

@@ -214,8 +213,6 @@ namespace GridKit
214213
RealT g22_{0.0};
215214
RealT b22_{0.0};
216215

217-
int parameter_error_count_{0};
218-
219216
/// Variable monitor
220217
std::unique_ptr<MonitorT> monitor_;
221218
};

GridKit/Model/PhasorDynamics/Branch/BranchData.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace GridKit
2121
B, ///< Total shunt susceptance
2222
tap, ///< Off-nominal tap magnitude on bus1 side
2323
phase, ///< Phase shift angle in radians
24+
closed ///< In-service flag (true = closed, default true)
2425
};
2526

2627
/// Ports for a branch

GridKit/Model/PhasorDynamics/Branch/BranchImpl.hpp

Lines changed: 45 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
*/
99

1010
#include <cmath>
11-
#include <variant>
12-
13-
#include <magic_enum/magic_enum.hpp>
1411

1512
#include <GridKit/Model/PhasorDynamics/Branch/Branch.hpp>
1613
#include <GridKit/Model/PhasorDynamics/Branch/BranchData.hpp>
@@ -147,7 +144,7 @@ namespace GridKit
147144
template <typename scalar_type, typename index_type>
148145
int Branch<scalar_type, index_type>::verify() const
149146
{
150-
int ret = parameter_error_count_;
147+
int ret = 0;
151148

152149
auto check = [&](bool condition, const char* message)
153150
{
@@ -328,51 +325,46 @@ namespace GridKit
328325
template <typename scalar_type, typename index_type>
329326
void Branch<scalar_type, index_type>::initializeParameters(const ModelDataT& data)
330327
{
331-
readRealParameter(data, ModelDataT::Parameters::R, R_);
332-
readRealParameter(data, ModelDataT::Parameters::X, X_);
333-
readRealParameter(data, ModelDataT::Parameters::G, G_);
334-
readRealParameter(data, ModelDataT::Parameters::B, B_);
335-
readRealParameter(data, ModelDataT::Parameters::tap, tap_);
336-
readRealParameter(data, ModelDataT::Parameters::phase, phase_);
328+
using P = typename ModelDataT::Parameters;
337329

338-
if (data.ports.contains(ModelDataT::Ports::bus1))
330+
if (data.parameters.contains(P::R))
339331
{
340-
bus1_id_ = data.ports.at(ModelDataT::Ports::bus1);
332+
R_ = std::get<RealT>(data.parameters.at(P::R));
341333
}
342-
343-
if (data.ports.contains(ModelDataT::Ports::bus2))
334+
if (data.parameters.contains(P::X))
344335
{
345-
bus2_id_ = data.ports.at(ModelDataT::Ports::bus2);
336+
X_ = std::get<RealT>(data.parameters.at(P::X));
346337
}
347-
}
348-
349-
template <typename scalar_type, typename index_type>
350-
bool Branch<scalar_type, index_type>::readRealParameter(const ModelDataT& data,
351-
typename ModelDataT::Parameters parameter,
352-
RealT& target)
353-
{
354-
if (!data.parameters.contains(parameter))
338+
if (data.parameters.contains(P::G))
355339
{
356-
return false;
340+
G_ = std::get<RealT>(data.parameters.at(P::G));
357341
}
358-
359-
const auto& value = data.parameters.at(parameter);
360-
if (const auto* real_value = std::get_if<RealT>(&value))
342+
if (data.parameters.contains(P::B))
361343
{
362-
target = *real_value;
363-
return true;
344+
B_ = std::get<RealT>(data.parameters.at(P::B));
345+
}
346+
if (data.parameters.contains(P::tap))
347+
{
348+
tap_ = std::get<RealT>(data.parameters.at(P::tap));
349+
}
350+
if (data.parameters.contains(P::phase))
351+
{
352+
phase_ = std::get<RealT>(data.parameters.at(P::phase));
353+
}
354+
if (data.parameters.contains(P::closed))
355+
{
356+
closed_ = std::get<bool>(data.parameters.at(P::closed));
364357
}
365358

366-
if (const auto* integer_value = std::get_if<IdxT>(&value))
359+
if (data.ports.contains(ModelDataT::Ports::bus1))
367360
{
368-
target = static_cast<RealT>(*integer_value);
369-
return true;
361+
bus1_id_ = data.ports.at(ModelDataT::Ports::bus1);
370362
}
371363

372-
Log::error() << "Branch: parameter " << magic_enum::enum_name(parameter)
373-
<< " must be numeric\n";
374-
parameter_error_count_ += 1;
375-
return false;
364+
if (data.ports.contains(ModelDataT::Ports::bus2))
365+
{
366+
bus2_id_ = data.ports.at(ModelDataT::Ports::bus2);
367+
}
376368
}
377369

378370
template <typename scalar_type, typename index_type>
@@ -454,14 +446,15 @@ namespace GridKit
454446
template <typename scalar_type, typename index_type>
455447
void Branch<scalar_type, index_type>::setDerivedParams()
456448
{
457-
g11_ = RealT{0.0};
458-
b11_ = RealT{0.0};
459-
g12_ = RealT{0.0};
460-
b12_ = RealT{0.0};
461-
g21_ = RealT{0.0};
462-
b21_ = RealT{0.0};
463-
g22_ = RealT{0.0};
464-
b22_ = RealT{0.0};
449+
g11_ = RealT{0.0};
450+
b11_ = RealT{0.0};
451+
g12_ = RealT{0.0};
452+
b12_ = RealT{0.0};
453+
g21_ = RealT{0.0};
454+
b21_ = RealT{0.0};
455+
g22_ = RealT{0.0};
456+
b22_ = RealT{0.0};
457+
in_service_factor_ = closed_ ? RealT{1.0} : RealT{0.0};
465458

466459
const RealT denom = R_ * R_ + X_ * X_;
467460
if (denom == RealT{0.0} || tap_ == RealT{0.0})
@@ -478,17 +471,17 @@ namespace GridKit
478471
const RealT g_diag = -(g_br + RealT{0.5} * G_);
479472
const RealT b_diag = -(b_br + RealT{0.5} * B_);
480473

481-
g11_ = g_diag * inv_tap * inv_tap;
482-
b11_ = b_diag * inv_tap * inv_tap;
474+
g11_ = in_service_factor_ * g_diag * inv_tap * inv_tap;
475+
b11_ = in_service_factor_ * b_diag * inv_tap * inv_tap;
483476

484-
g12_ = (g_br * cos_ph - b_br * sin_ph) * inv_tap;
485-
b12_ = (b_br * cos_ph + g_br * sin_ph) * inv_tap;
477+
g12_ = in_service_factor_ * (g_br * cos_ph - b_br * sin_ph) * inv_tap;
478+
b12_ = in_service_factor_ * (b_br * cos_ph + g_br * sin_ph) * inv_tap;
486479

487-
g21_ = (g_br * cos_ph + b_br * sin_ph) * inv_tap;
488-
b21_ = (b_br * cos_ph - g_br * sin_ph) * inv_tap;
480+
g21_ = in_service_factor_ * (g_br * cos_ph + b_br * sin_ph) * inv_tap;
481+
b21_ = in_service_factor_ * (b_br * cos_ph - g_br * sin_ph) * inv_tap;
489482

490-
g22_ = g_diag;
491-
b22_ = b_diag;
483+
g22_ = in_service_factor_ * g_diag;
484+
b22_ = in_service_factor_ * b_diag;
492485
}
493486

494487
} // namespace PhasorDynamics

GridKit/Model/PhasorDynamics/Branch/README.md

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Notes:
1010
- $G$ and $B$ are total branch shunt values split equally between terminals.
1111
- The branch has no solver-owned variables; it contributes current residuals
1212
directly to the connected buses.
13+
- `closed=false` is static case-import status. It removes the branch admittance
14+
contribution but does not insert fake admittance; islanded or underconstrained
15+
topology can still make the system singular.
16+
- Sparse automatic differentiation may materialize zero-valued structural
17+
entries for an open branch; the mathematical Jacobian contribution is zero.
1318

1419
## Circuit Diagram
1520

@@ -23,14 +28,15 @@ Figure 1: Branch equivalent circuit
2328

2429
## Model Parameters
2530

26-
Symbol | Units | Description | Typical Value | Note
27-
------------|---------|--------------------------------------------------|---------------|------
28-
$R$ | [p.u.] | Branch series resistance | |
29-
$X$ | [p.u.] | Branch series reactance | |
30-
$G$ | [p.u.] | Total branch shunt conductance | 0 |
31-
$B$ | [p.u.] | Total branch shunt susceptance | 0 |
32-
$\tau$ | [p.u.] | Off-nominal tap magnitude on bus-1 side | 1 | Parameter name: `tap`
33-
$\theta$ | [rad] | Phase-shift angle | 0 | Parameter name: `phase`
31+
Symbol | Units | JSON | Description | Typical Value | Note
32+
-----------------------|--------|----------|-----------------------------------------|---------------|------
33+
$R$ | [p.u.] | `R` | Branch series resistance | |
34+
$X$ | [p.u.] | `X` | Branch series reactance | |
35+
$G$ | [p.u.] | `G` | Total branch shunt conductance | 0 |
36+
$B$ | [p.u.] | `B` | Total branch shunt susceptance | 0 |
37+
$\tau$ | [p.u.] | `tap` | Off-nominal tap magnitude on bus-1 side | 1 |
38+
$\theta$ | [rad] | `phase` | Phase-shift angle | 0 |
39+
$c_{\mathrm{br}}$ | [-] | `closed` | Static branch closed status | `true` | JSON boolean
3440

3541
### Parameter Validation
3642

@@ -39,17 +45,23 @@ Invalid Branch parameter sets are rejected by the following checks:
3945
```math
4046
\begin{aligned}
4147
&R, X, G, B, \tau, \theta \in \mathbb{R}\ \text{and finite} \\
48+
&c_{\mathrm{br}} \in \{\mathrm{true}, \mathrm{false}\} \\
4249
&R^2 + X^2 > 0 \\
4350
&\tau > 0
4451
\end{aligned}
4552
```
4653

4754
### Model Derived Parameters
4855

49-
The series and shunt admittances are:
56+
The closed-status factor and branch admittances are:
5057

5158
```math
5259
\begin{aligned}
60+
s_{\mathrm{br}} &=
61+
\begin{cases}
62+
1, & c_{\mathrm{br}} = \mathrm{true} \\
63+
0, & c_{\mathrm{br}} = \mathrm{false}
64+
\end{cases} \\
5365
Y_{\mathrm{br}} &= \dfrac{1}{R + jX} \\
5466
Y_{\mathrm{sh}} &= G + jB
5567
\end{aligned}
@@ -86,11 +98,47 @@ The off-nominal transformer transformation uses bus 1 as the tap side:
8698
\tau^{-1} & 0 \\
8799
0 & e^{j\theta}
88100
\end{bmatrix} \\
89-
\mathbf{Y} &= \mathbf{M}^{\dagger}\mathbf{Y}_0\mathbf{M}
101+
\mathbf{Y} &= s_{\mathrm{br}}\mathbf{M}^{\dagger}\mathbf{Y}_0\mathbf{M}
90102
\end{aligned}
91103
```
92104

93-
For the equations below, write each entry as $Y_{mn}=G_{mn}+jB_{mn}$.
105+
For each entry $Y_{mn}=G_{mn}+jB_{mn}$, the real-valued contribution from
106+
terminal $n$ to current at terminal $m$ is:
107+
108+
```math
109+
\begin{aligned}
110+
\begin{bmatrix}
111+
I_{rm} \\
112+
I_{im}
113+
\end{bmatrix}_{n}
114+
=
115+
\begin{bmatrix}
116+
G_{mn} & -B_{mn} \\
117+
B_{mn} & G_{mn}
118+
\end{bmatrix}
119+
\begin{bmatrix}
120+
V_{rn} \\
121+
V_{in}
122+
\end{bmatrix}
123+
\end{aligned}
124+
```
125+
126+
The voltage derivative for the same block is:
127+
128+
```math
129+
\begin{aligned}
130+
\frac{\partial [I_{rm}, I_{im}]^T}
131+
{\partial [V_{rn}, V_{in}]}
132+
=
133+
\begin{bmatrix}
134+
G_{mn} & -B_{mn} \\
135+
B_{mn} & G_{mn}
136+
\end{bmatrix}
137+
\end{aligned}
138+
```
139+
140+
When `closed=false`, $s_{\mathrm{br}}=0$, so $\mathbf{Y}=0$ and every current
141+
block and voltage derivative block is zero.
94142

95143
## Model Variables
96144

@@ -127,24 +175,19 @@ None.
127175

128176
### Algebraic Equations
129177

130-
The branch current relation is $0 = -\mathbf{I} + \mathbf{Y}\mathbf{V}$.
131-
132178
```math
133179
\begin{aligned}
134-
I_{r1} &= G_{11} V_{r1} - B_{11} V_{i1}
180+
0 &= -I_{r1} + G_{11} V_{r1} - B_{11} V_{i1}
135181
+ G_{12} V_{r2} - B_{12} V_{i2} \\
136-
I_{i1} &= B_{11} V_{r1} + G_{11} V_{i1}
182+
0 &= -I_{i1} + B_{11} V_{r1} + G_{11} V_{i1}
137183
+ B_{12} V_{r2} + G_{12} V_{i2} \\
138-
I_{r2} &= G_{21} V_{r1} - B_{21} V_{i1}
184+
0 &= -I_{r2} + G_{21} V_{r1} - B_{21} V_{i1}
139185
+ G_{22} V_{r2} - B_{22} V_{i2} \\
140-
I_{i2} &= B_{21} V_{r1} + G_{21} V_{i1}
186+
0 &= -I_{i2} + B_{21} V_{r1} + G_{21} V_{i1}
141187
+ B_{22} V_{r2} + G_{22} V_{i2}
142188
\end{aligned}
143189
```
144190

145-
These current contributions are added to the connected bus residuals with
146-
positive sign because branch current is oriented entering the bus.
147-
148191
## Initialization
149192

150193
The Branch model has no internal state to initialize. During construction or

GridKit/Model/PhasorDynamics/ComponentDataJSONParser.hpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,10 @@ namespace GridKit
4747
{
4848
c.parameters[key.value()] = raw_parameter.value().template get<bool>();
4949
}
50-
else if (raw_parameter.value().is_number_float())
50+
else if (raw_parameter.value().is_number())
5151
{
5252
c.parameters[key.value()] = raw_parameter.value().template get<RealT>();
5353
}
54-
else if (raw_parameter.value().is_number_integer())
55-
{
56-
c.parameters[key.value()] = raw_parameter.value().template get<IdxT>();
57-
}
5854
else
5955
{
6056
Log::error() << "\n\tInvalid initial parameter value type: "

GridKit/Model/PhasorDynamics/INPUT_FORMAT.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ are specified:
139139

140140
Device class | Description | Ports | Initialization parameters | Variables available to monitor
141141
---------------------|------------------------------------------------------|----------------------------------|---------------------------- | -------------------------
142-
`Branch` | algebraic pi model for a line or off-nominal transformer branch | `bus1`, `bus2` | `R`, `X`, `G`, `B`, `tap`, `phase` | `ir1`, `ii1`, `im1`, `p1`, `q1`, `ir2`, `ii2`, `im2`, `p2`, `q2`
142+
`Branch` | algebraic pi model for a line or off-nominal transformer branch | `bus1`, `bus2` | `R`, `X`, `G`, `B`, `tap`, `phase`, `closed` | `ir1`, `ii1`, `im1`, `p1`, `q1`, `ir2`, `ii2`, `im2`, `p2`, `q2`
143143
`Load` | a basic static impedence load model | `bus` | `R`, `X` | `p`, `q`
144144
`Genrou` | 6th order machine model | `bus`, `pmech`\*, `speed`\*, `efd`\* | `p0`, `q0`, `H`, `D`, `Ra`, `Tdop`, `Tdopp`, `Tqop`, `Tqopp`, `Xd`, `Xdp`, `Xdpp`, `Xq`, `Xqp`, `Xqpp`, `Xl`, `S10`, `S12`, `mva` | `ir`, `ii`, `p`, `q`, `delta`, `omega`, `speed`
145145
`Gensal` | 5th order salient-pole machine model | `bus`, `pmech`\*, `speed`\*, `efd`\* | `p0`, `q0`, `H`, `D`, `Ra`, `Tdop`, `Tdopp`, `Tqopp`, `Xd`, `Xdp`, `Xdpp`, `Xq`, `Xl`, `S10`, `S12`, `mva` | `ir`, `ii`, `p`, `q`, `delta`, `omega`, `speed`, `Eqp`, `psidp`, `psiqpp`, `psidpp`, `vd`, `vq`, `te`, `id`, `iq`
@@ -155,9 +155,10 @@ Ports marked with \* are optional and, if missing, will be assumed to be
155155
connected to a constant value. This list is subject to change.
156156

157157

158-
For `Branch`, `tap` and `phase` are optional parameters. If omitted, `tap`
159-
defaults to `1.0` and `phase` defaults to `0.0` radians. Bus `bus1` is the tap
160-
side for off-nominal transformer branches.
158+
For `Branch`, `tap`, `phase`, and `closed` are optional parameters. If omitted,
159+
`tap` defaults to `1.0`, `phase` defaults to `0.0` radians, and `closed`
160+
defaults to `true`. `closed` must be a JSON boolean; numeric status values are
161+
rejected. Bus `bus1` is the tap side for off-nominal transformer branches.
161162

162163
## Example File for a 2-Bus System
163164

0 commit comments

Comments
 (0)