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 GridKit/Model/PhasorDynamics/Branch/Branch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ namespace GridKit
RealT X_{0.0};
RealT G_{0.0};
RealT B_{0.0};
RealT Gmag_{0.0};
RealT Bmag_{0.0};
RealT tap_{1.0};
RealT phase_{0.0};
IdxT bus1_id_{0};
Expand Down
6 changes: 4 additions & 2 deletions GridKit/Model/PhasorDynamics/Branch/BranchData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ namespace GridKit
{
R, ///< Line series resistance
X, ///< Line series reactance
G, ///< Total shunt conductance
B, ///< Total shunt susceptance
G, ///< Total line shunt conductance
B, ///< Total line shunt susceptance
Gmag, ///< Magnetizing shunt conductance at bus 1 (from bus, tapped side)
Bmag, ///< Magnetizing shunt susceptance at bus 1 (from bus, tapped side)
tap, ///< Off-nominal tap magnitude on bus1 side
phase, ///< Phase shift angle in radians
};
Expand Down
20 changes: 12 additions & 8 deletions GridKit/Model/PhasorDynamics/Branch/BranchImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ namespace GridKit
* @param bus2 - pointer to bus-2
* @param R - line series resistance
* @param X - line series reactance
* @param G - total shunt conductance
* @param B - total shunt susceptance
* @param G - total line shunt conductance
* @param B - total line shunt susceptance
* @param tap - off-nominal tap magnitude on bus1 side
* @param phase - phase shift angle in radians
*/
Expand Down Expand Up @@ -165,6 +165,8 @@ namespace GridKit
check(std::isfinite(X_), "X must be finite");
check(std::isfinite(G_), "G must be finite");
check(std::isfinite(B_), "B must be finite");
check(std::isfinite(Gmag_), "Gmag must be finite");
check(std::isfinite(Bmag_), "Bmag must be finite");
check(std::isfinite(tap_), "tap must be finite");
check(std::isfinite(phase_), "phase must be finite");
check(R_ * R_ + X_ * X_ > RealT{0.0}, "R and X cannot both be zero");
Expand Down Expand Up @@ -335,6 +337,8 @@ namespace GridKit
readRealParameter(data, Parameter::X, X_);
readRealParameter(data, Parameter::G, G_);
readRealParameter(data, Parameter::B, B_);
readRealParameter(data, Parameter::Gmag, Gmag_);
readRealParameter(data, Parameter::Bmag, Bmag_);
readRealParameter(data, Parameter::tap, tap_);
readRealParameter(data, Parameter::phase, phase_);

Expand Down Expand Up @@ -478,20 +482,20 @@ namespace GridKit
const RealT cos_ph = std::cos(phase_);
const RealT sin_ph = std::sin(phase_);

const RealT g_diag = -(g_br + RealT{0.5} * G_);
const RealT b_diag = -(b_br + RealT{0.5} * B_);
const RealT g_diag = -g_br;
const RealT b_diag = -b_br;

g11_ = g_diag * inv_tap * inv_tap;
b11_ = b_diag * inv_tap * inv_tap;
g11_ = g_diag * inv_tap * inv_tap - RealT{0.5} * G_ - Gmag_;
b11_ = b_diag * inv_tap * inv_tap - RealT{0.5} * B_ - Bmag_;

g12_ = (g_br * cos_ph - b_br * sin_ph) * inv_tap;
b12_ = (b_br * cos_ph + g_br * sin_ph) * inv_tap;

g21_ = (g_br * cos_ph + b_br * sin_ph) * inv_tap;
b21_ = (b_br * cos_ph - g_br * sin_ph) * inv_tap;

g22_ = g_diag;
b22_ = b_diag;
g22_ = g_diag - RealT{0.5} * G_;
b22_ = b_diag - RealT{0.5} * B_;
}

} // namespace PhasorDynamics
Expand Down
75 changes: 47 additions & 28 deletions GridKit/Model/PhasorDynamics/Branch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,51 @@ contributions are oriented entering the adjacent buses.
Notes:
- Setting $\tau = 1$ and $\theta = 0$ gives the ordinary symmetric
transmission-line $\pi$ model.
- $G$ and $B$ are total branch shunt values split equally between terminals.
- The total line shunt $G + jB$ is split equally between the two terminals,
while the magnetizing shunt $G_\text{mag} + jB_\text{mag}$ is connected at
bus 1; both shunts are added outside the $\mathbf{M}$ transformation.
- The branch has no solver-owned variables; it contributes current residuals
directly to the connected buses.

## Circuit Diagram

An ideal complex tap is placed on the bus-1 side of the branch equivalent. The
ordinary transmission-line $\pi$ model is recovered with $\tau = 1$ and
$\theta = 0$.

![](../../../../docs/Figures/transformer-branch.png)

Figure 1: Branch equivalent circuit

## Model Parameters

Symbol | Units | Description | Typical Value | Note
------------|---------|--------------------------------------------------|---------------|------
$R$ | [p.u.] | Branch series resistance | |
$X$ | [p.u.] | Branch series reactance | |
$G$ | [p.u.] | Total branch shunt conductance | 0 |
$B$ | [p.u.] | Total branch shunt susceptance | 0 |
$\tau$ | [p.u.] | Off-nominal tap magnitude on bus-1 side | 1 | Parameter name: `tap`
$\theta$ | [rad] | Phase-shift angle | 0 | Parameter name: `phase`
Symbol | Units | JSON | Description | Typical Value | Note
---------------------|--------|---------|-----------------------------------------|---------------|------
$R$ | [p.u.] | `R` | Branch series resistance | |
$X$ | [p.u.] | `X` | Branch series reactance | |
$G$ | [p.u.] | `G` | Total line shunt conductance | 0.0 |
$B$ | [p.u.] | `B` | Total line shunt susceptance | 0.0 |
$G_\text{mag}$ | [p.u.] | `Gmag` | Magnetizing shunt conductance at bus 1 | 0.0 |
$B_\text{mag}$ | [p.u.] | `Bmag` | Magnetizing shunt susceptance at bus 1 | 0.0 |
$\tau$ | [p.u.] | `tap` | Off-nominal tap magnitude on bus-1 side | 1.0 |
$\theta$ | [rad] | `phase` | Phase-shift angle | 0.0 |

### Parameter Validation

Invalid Branch parameter sets are rejected by the following checks:

```math
\begin{aligned}
&R, X, G, B, \tau, \theta \in \mathbb{R}\ \text{and finite} \\
&R, X, G, B, G_\text{mag}, B_\text{mag}, \tau, \theta
\in \mathbb{R}\ \text{and finite} \\
&R^2 + X^2 > 0 \\
&\tau > 0
\end{aligned}
```

### Model Derived Parameters

The series and shunt admittances are:
The series, magnetizing shunt, and line shunt admittances are:

```math
\begin{aligned}
Y_{\mathrm{br}} &= \dfrac{1}{R + jX} \\
Y_{\mathrm{sh}} &= G + jB
Y_{\mathrm{br}} &= \dfrac{1}{R + jX} \\
Y_{\mathrm{mag}} &= G_\text{mag} + jB_\text{mag} \\
Y_{\mathrm{sh}} &= G + jB
\end{aligned}
```

The nominal $\pi$-branch admittance matrix is the sum of the series and shunt
admittance contributions:
The series, magnetizing shunt, and line shunt admittance matrices are:

```math
\begin{aligned}
Expand All @@ -67,7 +62,16 @@ admittance contributions:
Y_{\mathrm{br}}
& -Y_{\mathrm{br}}
\end{bmatrix}
+
\\
\mathbf{Y}_\text{mag}
&=
\begin{bmatrix}
-Y_{\mathrm{mag}} & 0 \\
0 & 0
\end{bmatrix}
\\
\mathbf{Y}_\text{sh}
&=
\dfrac{1}{2}
\begin{bmatrix}
-Y_{\mathrm{sh}} & 0 \\
Expand All @@ -85,8 +89,23 @@ The off-nominal transformer transformation uses bus 1 as the tap side:
\begin{bmatrix}
\tau^{-1} & 0 \\
0 & e^{j\theta}
\end{bmatrix} \\
\mathbf{Y} &= \mathbf{M}^{\dagger}\mathbf{Y}_0\mathbf{M}
\end{bmatrix}
\end{aligned}
```

The magnetizing and line shunts are added outside the transformation:

```math
\begin{aligned}
\mathbf{Y}
&=
\mathbf{M}^{\dagger}
\mathbf{Y}_0
\mathbf{M}
+
\mathbf{Y}_\text{mag}
+
\mathbf{Y}_\text{sh}
\end{aligned}
```

Expand Down
2 changes: 1 addition & 1 deletion GridKit/Model/PhasorDynamics/INPUT_FORMAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ are specified:

Device class | Description | Ports | Initialization parameters | Variables available to monitor
---------------------|------------------------------------------------------|----------------------------------|---------------------------- | -------------------------
`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`
`Branch` | algebraic pi model for a line or off-nominal transformer branch | `bus1`, `bus2` | `R`, `X`, `G`, `B`, `Gmag`, `Bmag`, `tap`, `phase` | `ir1`, `ii1`, `im1`, `p1`, `q1`, `ir2`, `ii2`, `im2`, `p2`, `q2`
`Load` | a basic static impedence load model | `bus` | `R`, `X` | `p`, `q`
`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`
`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`
Expand Down
37 changes: 26 additions & 11 deletions tests/UnitTests/PhasorDynamics/BranchTests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,15 @@ namespace GridKit

TestOutcome offNominalResidual()
{
// Verifies tap and phase-shift current residual contributions.
// Verifies tap, phase-shift, line-shunt, and bus-1 magnetizing-shunt contributions.
TestStatus success = true;

RealT R{2.0};
RealT X{4.0};
RealT G{0.2};
RealT B{1.2};
RealT G{0.4};
RealT B{0.8};
RealT Gmag{0.2};
RealT Bmag{1.2};
RealT tap{1.25};
RealT phase{0.3};

Expand All @@ -107,10 +109,10 @@ namespace GridKit
ScalarT Vr2{30.0};
ScalarT Vi2{40.0};

const ScalarT Ir1{12.719793434963478};
const ScalarT Ii1{-4.047960563981182};
const ScalarT Ir2{13.821345956502421};
const ScalarT Ii2{-21.182080826645354};
const ScalarT Ir1{33.679793434963472};
const ScalarT Ii1{-22.927960563981181};
const ScalarT Ir2{2.821345956502423};
const ScalarT Ii2{-19.182080826645358};

PhasorDynamics::Bus<ScalarT, IdxT> bus1(Vr1, Vi1);
PhasorDynamics::Bus<ScalarT, IdxT> bus2(Vr2, Vi2);
Expand All @@ -121,7 +123,20 @@ namespace GridKit
bus2.initialize();
bus2.evaluateResidual();

PhasorDynamics::Branch<ScalarT, IdxT> branch(&bus1, &bus2, R, X, G, B, tap, phase);
using Data = typename PhasorDynamics::Branch<ScalarT, IdxT>::ModelDataT;
using Parameter = typename Data::Parameters;

Data data;
data.parameters[Parameter::R] = R;
data.parameters[Parameter::X] = X;
data.parameters[Parameter::G] = G;
data.parameters[Parameter::B] = B;
data.parameters[Parameter::Gmag] = Gmag;
data.parameters[Parameter::Bmag] = Bmag;
data.parameters[Parameter::tap] = tap;
data.parameters[Parameter::phase] = phase;

PhasorDynamics::Branch<ScalarT, IdxT> branch(&bus1, &bus2, data);
branch.allocate();
branch.evaluateResidual();

Expand Down Expand Up @@ -385,12 +400,12 @@ namespace GridKit
const std::complex<RealT> ybr{g, b};
const std::complex<RealT> ysh{G, B};
const std::complex<RealT> rotation{std::cos(phase), std::sin(phase)};
const std::complex<RealT> ydiag = -(ybr + RealT{0.5} * ysh);
const std::complex<RealT> ydiag = -ybr;

const std::complex<RealT> y11 = ydiag * inv_tap * inv_tap;
const std::complex<RealT> y11 = ydiag * inv_tap * inv_tap - RealT{0.5} * ysh;
const std::complex<RealT> y12 = ybr * rotation * inv_tap;
const std::complex<RealT> y21 = ybr * std::conj(rotation) * inv_tap;
const std::complex<RealT> y22 = ydiag;
const std::complex<RealT> y22 = ydiag - RealT{0.5} * ysh;

std::vector<DependencyTracking::Variable::DependencyMap> dependencies(4);
dependencies[0] = {{0, y11.real()}, {1, -y11.imag()}, {2, y12.real()}, {3, -y12.imag()}};
Expand Down
4 changes: 3 additions & 1 deletion tests/UnitTests/Utilities/CaseFormatTests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace GridKit
{ "number": 2, "class": "infinite_bus", "name": "Bus 2", "init": {"Vr":1.0, "Vi":0.0}, "params": {"kv": 115.0} }
],
"devices": [
{ "class": "Branch", "ports": {"bus1":1, "bus2":2}, "id": "1", "params": {"R":0.0, "X":0.1, "G":0.0, "B":0.0, "tap":1.05, "phase":0.1} },
{ "class": "Branch", "ports": {"bus1":1, "bus2":2}, "id": "1", "params": {"R":0.0, "X":0.1, "G":0.0, "B":0.0, "Gmag":0.01, "Bmag":0.02, "tap":1.05, "phase":0.1} },
{ "class": "Genrou", "ports": {"bus":1}, "id": "1", "params": {"p0":1.0, "q0":0.05013, "H":3.0, "D":0.0, "Ra":0.0, "Tdop":7.0, "Tdopp":0.04, "Tqopp":0.05,
"Tqop":0.75, "Xd":2.1, "Xdp":0.2, "Xdpp":0.18, "Xq":0.5, "Xqp": 0.0, "Xqpp":0.18, "Xl":0.15, "S10":0.0, "S12":0.0}, "mon": ["delta", "omega"] },
{ "class": "Gensal", "ports": {"bus":1}, "id": "2", "params": {"p0":1.0, "q0":0.05013, "H":3.0, "D":0.0, "Ra":0.0, "Tdop":7.0, "Tdopp":0.04, "Tqopp":0.05,
Expand Down Expand Up @@ -114,6 +114,8 @@ namespace GridKit
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::X]) == 0.1;
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::G]) == 0.0;
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::B]) == 0.0;
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::Gmag]) == 0.01;
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::Bmag]) == 0.02;
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::tap]) == 1.05;
success *= std::get<RealT>(result.branch[0].parameters[BranchParameters::phase]) == 0.1;
success *= result.branch[0].buses[BranchBuses::bus1] == 1;
Expand Down
Loading