Skip to content

Commit 07398b5

Browse files
committed
Revise appraoch and syntax
1 parent 0b56d69 commit 07398b5

11 files changed

Lines changed: 264 additions & 89 deletions

File tree

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 `closed` parameter to `Branch` for declaring out-of-service lines in case files.
6566

6667
## v0.1
6768

GridKit/Model/PhasorDynamics/Branch/Branch.hpp

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

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

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

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

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
{
@@ -310,51 +307,46 @@ namespace GridKit
310307
template <typename scalar_type, typename index_type>
311308
void Branch<scalar_type, index_type>::initializeParameters(const ModelDataT& data)
312309
{
313-
readRealParameter(data, ModelDataT::Parameters::R, R_);
314-
readRealParameter(data, ModelDataT::Parameters::X, X_);
315-
readRealParameter(data, ModelDataT::Parameters::G, G_);
316-
readRealParameter(data, ModelDataT::Parameters::B, B_);
317-
readRealParameter(data, ModelDataT::Parameters::tap, tap_);
318-
readRealParameter(data, ModelDataT::Parameters::phase, phase_);
310+
using P = typename ModelDataT::Parameters;
319311

320-
if (data.ports.contains(ModelDataT::Ports::bus1))
312+
if (data.parameters.contains(P::R))
321313
{
322-
bus1_id_ = data.ports.at(ModelDataT::Ports::bus1);
314+
R_ = std::get<RealT>(data.parameters.at(P::R));
323315
}
324-
325-
if (data.ports.contains(ModelDataT::Ports::bus2))
316+
if (data.parameters.contains(P::X))
326317
{
327-
bus2_id_ = data.ports.at(ModelDataT::Ports::bus2);
318+
X_ = std::get<RealT>(data.parameters.at(P::X));
328319
}
329-
}
330-
331-
template <typename scalar_type, typename index_type>
332-
bool Branch<scalar_type, index_type>::readRealParameter(const ModelDataT& data,
333-
typename ModelDataT::Parameters parameter,
334-
RealT& target)
335-
{
336-
if (!data.parameters.contains(parameter))
320+
if (data.parameters.contains(P::G))
337321
{
338-
return false;
322+
G_ = std::get<RealT>(data.parameters.at(P::G));
339323
}
340-
341-
const auto& value = data.parameters.at(parameter);
342-
if (const auto* real_value = std::get_if<RealT>(&value))
324+
if (data.parameters.contains(P::B))
343325
{
344-
target = *real_value;
345-
return true;
326+
B_ = std::get<RealT>(data.parameters.at(P::B));
327+
}
328+
if (data.parameters.contains(P::tap))
329+
{
330+
tap_ = std::get<RealT>(data.parameters.at(P::tap));
331+
}
332+
if (data.parameters.contains(P::phase))
333+
{
334+
phase_ = std::get<RealT>(data.parameters.at(P::phase));
335+
}
336+
if (data.parameters.contains(P::closed))
337+
{
338+
closed_ = std::get<bool>(data.parameters.at(P::closed));
346339
}
347340

348-
if (const auto* integer_value = std::get_if<IdxT>(&value))
341+
if (data.ports.contains(ModelDataT::Ports::bus1))
349342
{
350-
target = static_cast<RealT>(*integer_value);
351-
return true;
343+
bus1_id_ = data.ports.at(ModelDataT::Ports::bus1);
352344
}
353345

354-
Log::error() << "Branch: parameter " << magic_enum::enum_name(parameter)
355-
<< " must be numeric\n";
356-
parameter_error_count_ += 1;
357-
return false;
346+
if (data.ports.contains(ModelDataT::Ports::bus2))
347+
{
348+
bus2_id_ = data.ports.at(ModelDataT::Ports::bus2);
349+
}
358350
}
359351

360352
template <typename scalar_type, typename index_type>
@@ -436,14 +428,15 @@ namespace GridKit
436428
template <typename scalar_type, typename index_type>
437429
void Branch<scalar_type, index_type>::setDerivedParams()
438430
{
439-
g11_ = RealT{0.0};
440-
b11_ = RealT{0.0};
441-
g12_ = RealT{0.0};
442-
b12_ = RealT{0.0};
443-
g21_ = RealT{0.0};
444-
b21_ = RealT{0.0};
445-
g22_ = RealT{0.0};
446-
b22_ = RealT{0.0};
431+
g11_ = RealT{0.0};
432+
b11_ = RealT{0.0};
433+
g12_ = RealT{0.0};
434+
b12_ = RealT{0.0};
435+
g21_ = RealT{0.0};
436+
b21_ = RealT{0.0};
437+
g22_ = RealT{0.0};
438+
b22_ = RealT{0.0};
439+
in_service_factor_ = closed_ ? RealT{1.0} : RealT{0.0};
447440

448441
const RealT denom = R_ * R_ + X_ * X_;
449442
if (denom == RealT{0.0} || tap_ == RealT{0.0})
@@ -460,17 +453,17 @@ namespace GridKit
460453
const RealT g_diag = -(g_br + RealT{0.5} * G_);
461454
const RealT b_diag = -(b_br + RealT{0.5} * B_);
462455

463-
g11_ = g_diag * inv_tap * inv_tap;
464-
b11_ = b_diag * inv_tap * inv_tap;
456+
g11_ = in_service_factor_ * g_diag * inv_tap * inv_tap;
457+
b11_ = in_service_factor_ * b_diag * inv_tap * inv_tap;
465458

466-
g12_ = (g_br * cos_ph - b_br * sin_ph) * inv_tap;
467-
b12_ = (b_br * cos_ph + g_br * sin_ph) * inv_tap;
459+
g12_ = in_service_factor_ * (g_br * cos_ph - b_br * sin_ph) * inv_tap;
460+
b12_ = in_service_factor_ * (b_br * cos_ph + g_br * sin_ph) * inv_tap;
468461

469-
g21_ = (g_br * cos_ph + b_br * sin_ph) * inv_tap;
470-
b21_ = (b_br * cos_ph - g_br * sin_ph) * inv_tap;
462+
g21_ = in_service_factor_ * (g_br * cos_ph + b_br * sin_ph) * inv_tap;
463+
b21_ = in_service_factor_ * (b_br * cos_ph - g_br * sin_ph) * inv_tap;
471464

472-
g22_ = g_diag;
473-
b22_ = b_diag;
465+
g22_ = in_service_factor_ * g_diag;
466+
b22_ = in_service_factor_ * b_diag;
474467
}
475468

476469
} // 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

@@ -25,14 +30,15 @@ $\theta = 0$.
2530

2631
## Model Parameters
2732

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

3743
### Parameter Validation
3844

@@ -41,17 +47,23 @@ Invalid Branch parameter sets are rejected by the following checks:
4147
```math
4248
\begin{aligned}
4349
&R, X, G, B, \tau, \theta \in \mathbb{R}\ \text{and finite} \\
50+
&c_{\mathrm{br}} \in \{\mathrm{true}, \mathrm{false}\} \\
4451
&R^2 + X^2 > 0 \\
4552
&\tau > 0
4653
\end{aligned}
4754
```
4855

4956
### Model Derived Parameters
5057

51-
The series and shunt admittances are:
58+
The closed-status factor and branch admittances are:
5259

5360
```math
5461
\begin{aligned}
62+
s_{\mathrm{br}} &=
63+
\begin{cases}
64+
1, & c_{\mathrm{br}} = \mathrm{true} \\
65+
0, & c_{\mathrm{br}} = \mathrm{false}
66+
\end{cases} \\
5567
Y_{\mathrm{br}} &= \dfrac{1}{R + jX} \\
5668
Y_{\mathrm{sh}} &= G + jB
5769
\end{aligned}
@@ -88,11 +100,47 @@ The off-nominal transformer transformation uses bus 1 as the tap side:
88100
\tau^{-1} & 0 \\
89101
0 & e^{j\theta}
90102
\end{bmatrix} \\
91-
\mathbf{Y} &= \mathbf{M}^{\dagger}\mathbf{Y}_0\mathbf{M}
103+
\mathbf{Y} &= s_{\mathrm{br}}\mathbf{M}^{\dagger}\mathbf{Y}_0\mathbf{M}
92104
\end{aligned}
93105
```
94106

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

97145
## Model Variables
98146

@@ -129,24 +177,19 @@ None.
129177

130178
### Algebraic Equations
131179

132-
The branch current relation is $0 = -\mathbf{I} + \mathbf{Y}\mathbf{V}$.
133-
134180
```math
135181
\begin{aligned}
136-
I_{r1} &= G_{11} V_{r1} - B_{11} V_{i1}
182+
0 &= -I_{r1} + G_{11} V_{r1} - B_{11} V_{i1}
137183
+ G_{12} V_{r2} - B_{12} V_{i2} \\
138-
I_{i1} &= B_{11} V_{r1} + G_{11} V_{i1}
184+
0 &= -I_{i1} + B_{11} V_{r1} + G_{11} V_{i1}
139185
+ B_{12} V_{r2} + G_{12} V_{i2} \\
140-
I_{r2} &= G_{21} V_{r1} - B_{21} V_{i1}
186+
0 &= -I_{r2} + G_{21} V_{r1} - B_{21} V_{i1}
141187
+ G_{22} V_{r2} - B_{22} V_{i2} \\
142-
I_{i2} &= B_{21} V_{r1} + G_{21} V_{i1}
188+
0 &= -I_{i2} + B_{21} V_{r1} + G_{21} V_{i1}
143189
+ B_{22} V_{r2} + G_{22} V_{i2}
144190
\end{aligned}
145191
```
146192

147-
These current contributions are added to the connected bus residuals with
148-
positive sign because branch current is oriented entering the bus.
149-
150193
## Initialization
151194

152195
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)