|
| 1 | +# [Branch Rating Limits](@id branch_rating_limits) |
| 2 | + |
| 3 | +This page explains how PowerSimulations derives a flow **rating** for an AC |
| 4 | +transmission element and how that rating is turned into optimization |
| 5 | +constraints. It covers every reduction type produced by |
| 6 | +`PowerNetworkMatrices` (PNM), the formulations that consume the rating, the |
| 7 | +difference between linear and nonlinear network models, the parallel-branch |
| 8 | +aggregation attribute and its defaults, and the branch-rating time series. |
| 9 | + |
| 10 | +For the per-formulation constraint algebra (variable names, slacks, objective |
| 11 | +terms) see the [`PowerSystems.Branch` Formulations](@ref) page in the |
| 12 | +Formulation Library. This page is the conceptual companion: *where the |
| 13 | +constraint branch flow limit on the right-hand side comes from*. |
| 14 | + |
| 15 | +## The single source of truth |
| 16 | + |
| 17 | +All branch flow ratings flow through one type-aware entry point. |
| 18 | +`branch_rating(entry, device_model)` returns the scalar rating for a reduction |
| 19 | +`entry`, and `min_max_flow_limits(entry, device_model)` wraps it into the |
| 20 | +symmetric pair `(min = -rating, max = rating)` used by linear constraints. Every |
| 21 | +constraint builder — linear or nonlinear, static or time series — resolves its |
| 22 | +rating through this path so the same physical element gets the same limit |
| 23 | +regardless of the network model. |
| 24 | + |
| 25 | +`branch_rating` is *type-aware*: it dispatches on the kind of reduction entry |
| 26 | +PNM produced for the element and delegates the aggregation policy to PNM. It |
| 27 | +does **not** reimplement per-type rating math; extend |
| 28 | +`PowerNetworkMatrices.get_equivalent_rating` instead if a new element type needs |
| 29 | +support. |
| 30 | + |
| 31 | +## PNM rating aggregation by reduction type |
| 32 | + |
| 33 | +Network reduction can collapse several physical branches into one equivalent |
| 34 | +element. The rating of that equivalent element depends on its topology: |
| 35 | + |
| 36 | +| Reduction entry | Rating policy | |
| 37 | +|:------------------------------------------------------------------------ |:------------------------------------------------------------------------------------------------------------------------------------------------------------------ | |
| 38 | +| Single line / two-winding transformer (`PSY.ACTransmission`) | `PSY.get_rating` | |
| 39 | +| `PSY.GenericArcImpedance` | `PSY.get_max_flow` (used as a rating proxy) | |
| 40 | +| Three-winding transformer winding (`PNM.ThreeWindingTransformerWinding`) | The winding-specific rating (primary/secondary/tertiary); falls back to the parent transformer rating when the winding rating is `0.0` | |
| 41 | +| Series chain (`PNM.BranchesSeries`) | **Weakest link**: the minimum equivalent rating across the chain members. A parallel block embedded in the chain contributes its single-element-contingency rating | |
| 42 | +| Parallel group (`PNM.BranchesParallel`) | Attribute-driven — see [Parallel-branch aggregation](@ref parallel_branch_aggregation) | |
| 43 | +| Mixed parallel group (`PNM.MixedBranchesParallel`) | Always the plain sum of member ratings (`sum_of_max`); the attribute is ignored | |
| 44 | + |
| 45 | +A **post-contingency** (emergency) rating uses the parallel structure with |
| 46 | +`PSY.rating_b` in place of `PSY.rating`: |
| 47 | +`PowerNetworkMatrices.get_equivalent_emergency_rating` mirrors the normal |
| 48 | +aggregation type-for-type, and for a single `ACTransmission` it returns |
| 49 | +`PSY.get_rating_b` and falls back to `PSY.get_rating` when no `rating_b` is |
| 50 | +defined. Three-winding windings have no `rating_b` in PowerSystems and fall |
| 51 | +back to their normal winding rating. |
| 52 | + |
| 53 | +## [Parallel-branch aggregation](@id parallel_branch_aggregation) |
| 54 | + |
| 55 | +When PNM produces a homogeneous `PNM.BranchesParallel` group, the way the |
| 56 | +individual circuit ratings combine into one limit is a modeling choice carried |
| 57 | +on the `DeviceModel` as an attribute: |
| 58 | + |
| 59 | + - **Attribute key:** `"parallel_branch_max_rating_method"` (the constant |
| 60 | + `PARALLEL_BRANCH_MAX_RATING_KEY`). |
| 61 | + - **Default:** `"single_element_contingency"`. |
| 62 | + |
| 63 | +Valid values: |
| 64 | + |
| 65 | +| Value | Aggregated rating | Meaning | |
| 66 | +|:---------------------------------------- |:-------------------------------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 67 | +| `"single_element_contingency"` (default) | ``\sum_i S_i - \max_i S_i`` | N-1 surviving capacity after the largest-rated circuit trips. A single-circuit group has zero capacity under this policy | |
| 68 | +| `"sum_of_max"` | ``\sum_i S_i`` | Each circuit independently loadable to its own thermal limit (least conservative) | |
| 69 | +| `"impedance_averaged"` | ``\sum_i f_i S_i,\; f_i = b_i / \sum_k b_k`` | Susceptance-weighted average, reflecting how DC flow physically splits across the group. Errors if total series susceptance is zero or non-finite | |
| 70 | + |
| 71 | +`PNM.MixedBranchesParallel` (a parallel group whose members carry different |
| 72 | +`DeviceModel` preferences) always uses `sum_of_max`, because there is no |
| 73 | +defensible way to pick one member's attribute for the whole group. |
| 74 | + |
| 75 | +Security-constrained branch formulations carry one additional default |
| 76 | +attribute, `"include_planned_outages" => false`, alongside the same |
| 77 | +`"single_element_contingency"` parallel default. |
| 78 | + |
| 79 | +## How the rating enters the optimization |
| 80 | + |
| 81 | +### Linear network models |
| 82 | + |
| 83 | +This covers the PTDF family (`PTDFPowerModel`, `AreaPTDFPowerModel`, and other |
| 84 | +`AbstractPTDFModel`s) and the DC power model (`DCPPowerModel` and other |
| 85 | +`PM.AbstractActivePowerModel`s). `CopperPlatePowerModel` and |
| 86 | +`AreaBalancePowerModel` enforce no per-branch flow limits. |
| 87 | + |
| 88 | +The active-power flow is bounded symmetrically by the aggregated rating: |
| 89 | + |
| 90 | +```math |
| 91 | +-R \;\le\; f_{b,t} \;\le\; R |
| 92 | +``` |
| 93 | + |
| 94 | +applied through `FlowRateConstraint` (PTDF and DC) or, for |
| 95 | +`StaticBranchBounds`, directly as variable bounds on the flow variable. |
| 96 | +A **standalone** `MonitoredLine` is the exception — it carries explicit, |
| 97 | +possibly asymmetric `flow_limits`. Note this exception only applies when the |
| 98 | +`MonitoredLine` is *not* collapsed by network reduction: a `MonitoredLine` that |
| 99 | +is a member of a reduction group resolves through the symmetric aggregated |
| 100 | +`branch_rating` like any other reduced element and its `flow_limits` are not |
| 101 | +carried into the equivalent (see [MonitoredLine](@ref monitored_line_rating)). |
| 102 | +`PhaseShiftingTransformer` under `PhaseAngleControl` additionally bounds the |
| 103 | +phase-shifter angle to ``[-\pi/2,\, \pi/2]``. |
| 104 | + |
| 105 | +### Nonlinear network models |
| 106 | + |
| 107 | +For full AC models (any `PM.AbstractPowerModel` that is not an active-power-only |
| 108 | +model) the apparent-power limit is enforced per flow direction: |
| 109 | + |
| 110 | +```math |
| 111 | +(P^{ft}_{b,t})^2 + (Q^{ft}_{b,t})^2 \;\le\; R^2 |
| 112 | +\qquad |
| 113 | +(P^{tf}_{b,t})^2 + (Q^{tf}_{b,t})^2 \;\le\; R^2 |
| 114 | +``` |
| 115 | + |
| 116 | +through `FlowRateConstraintFromTo` and `FlowRateConstraintToFrom`. The rating |
| 117 | +``R`` is the **same** type-aware `branch_rating` value used by the linear path; |
| 118 | +only its application differs (squared, on apparent power). |
| 119 | + |
| 120 | +### Formulation behavior summary |
| 121 | + |
| 122 | +| Formulation | Rating limit behavior | |
| 123 | +|:---------------------------------------------------- |:------------------------------------------------------------ | |
| 124 | +| `StaticBranch` | Flow rate limits enforced (and apparent-power limits for AC) | |
| 125 | +| `StaticBranchBounds` | Rating applied as bounds on the flow variable | |
| 126 | +| `StaticBranchUnbounded` | No flow limits enforced | |
| 127 | +| `AbstractSecurityConstrainedStaticBranch` (SCUC/N-1) | Flow rate limits enforced; pre- and post-contingency ratings | |
| 128 | +| `PhaseAngleControl` | Flow rate limits plus phase-angle limits | |
| 129 | + |
| 130 | +## Branch rating time series |
| 131 | + |
| 132 | +A branch may carry a time series that makes its rating vary per time step (for |
| 133 | +example dynamic line ratings). The time series is **normalized**: its values |
| 134 | +are a per-unit multiplier of a static rating, and the static rating is supplied |
| 135 | +as the parameter *multiplier*. The right-hand side that the solver sees is |
| 136 | +therefore: |
| 137 | + |
| 138 | + - Linear models: `parameter[t] * multiplier`, equal to the time-varying |
| 139 | + rating `rating(t)`. |
| 140 | + - Nonlinear models: `parameter[t] * multiplier`, equal to `rating(t)^2`. |
| 141 | + |
| 142 | +PSI parameter objects are **never squared** in a constraint expression (a |
| 143 | +squared parameter is not a valid parametric term). So for the apparent-power |
| 144 | +limit the right-hand side stays linear in the parameter — `parameter * multiplier` — and the parameter and multiplier are instead configured so their |
| 145 | +product is `rating(t)^2` directly. The simulation update policy refreshes only |
| 146 | +the parameter value each window; the multiplier is fixed at build time. |
| 147 | + |
| 148 | +The multiplier is resolved with the **same type-aware aggregation as the static |
| 149 | +path**, so series chains, three-winding windings and single elements all scale |
| 150 | +the correct equivalent rating. There is one deliberate exception: |
| 151 | + |
| 152 | + - **Parallel groups:** a rating time series attached to one member of a |
| 153 | + parallel group cannot be distributed across the group's other circuits. |
| 154 | + The multiplier is the group's combined rating (`sum_of_max`) **regardless |
| 155 | + of `"parallel_branch_max_rating_method"`**, and a warning is emitted. |
| 156 | + - **Post-contingency** (`PostContingencyBranchRatingTimeSeriesParameter`): |
| 157 | + the multiplier uses the emergency (`rating_b`) aggregation — the summed |
| 158 | + emergency rating for parallel groups, and the type-aware emergency rating |
| 159 | + otherwise. |
| 160 | + |
| 161 | +Support and validation: |
| 162 | + |
| 163 | + - Branch rating time series are only supported with `StaticBranch` and |
| 164 | + `AbstractSecurityConstrainedStaticBranch`. Any other formulation — |
| 165 | + including `StaticBranchUnbounded`, which enforces no flow limits — raises a |
| 166 | + `ConflictingInputsError` rather than silently ignoring the time series. |
| 167 | + - At build a sanity check warns if the normalized series scaled by the |
| 168 | + multiplier ever falls below the device's static rating (i.e. the series is |
| 169 | + expected to represent at-or-above-nominal capacity). |
| 170 | + |
| 171 | +## [MonitoredLine](@id monitored_line_rating) |
| 172 | + |
| 173 | +A **standalone** `PSY.MonitoredLine` (one that is *not* collapsed into a |
| 174 | +reduction group — see below) does not use the symmetric `branch_rating` path |
| 175 | +because it carries explicit `flow_limits` that can be tighter than, and |
| 176 | +asymmetric to, its rating. The asymmetry is **not discarded** — it is enforced |
| 177 | +by the directional constraints; only the single symmetric general rate limit |
| 178 | +cannot represent it and falls back to the tighter of the two: |
| 179 | + |
| 180 | + - General rate limit (`FlowRateConstraint`): a single symmetric bound |
| 181 | + ``\min(\text{rating},\ \text{flow\_limits.from\_to},\ \text{flow\_limits.to\_from})``. |
| 182 | + Because one symmetric constraint structurally cannot encode an asymmetric |
| 183 | + limit, the minimum of the two directions is used and a warning is emitted |
| 184 | + when `from_to` and `to_from` differ — flagging that this particular |
| 185 | + constraint is conservative, not that the asymmetry is lost. |
| 186 | + - Directional limits (`FlowLimitFromToConstraint` / `FlowLimitToFromConstraint`): |
| 187 | + these **preserve the asymmetry**, using `flow_limits.from_to` and |
| 188 | + `flow_limits.to_from` respectively. This is where the asymmetric input is |
| 189 | + actually honored. |
| 190 | + |
| 191 | +### `MonitoredLine` inside a reduction |
| 192 | + |
| 193 | +When a `MonitoredLine` is collapsed by network reduction into an equivalent |
| 194 | +element (`PNM.BranchesParallel`, `PNM.BranchesSeries`, |
| 195 | +`PNM.MixedBranchesParallel`, …), the reduction `entry` is a PNM reduction type, |
| 196 | +**not** a `PSY.MonitoredLine`, so dispatch goes through the type-aware |
| 197 | +`branch_rating` → `PowerNetworkMatrices.get_equivalent_rating` path. That |
| 198 | +aggregation consumes only the scalar `PSY.get_rating` (or `PSY.get_rating_b` |
| 199 | +for the post-contingency rating); the explicit, possibly asymmetric |
| 200 | +`flow_limits` are **not propagated into the reduced equivalent element**. A |
| 201 | +reduced arc that contains a `MonitoredLine` is therefore bounded by the |
| 202 | +symmetric aggregated rating like any other reduced element. The directional |
| 203 | +`FlowLimitFromToConstraint` / `FlowLimitToFromConstraint` are only added when |
| 204 | +the `MonitoredLine` is modeled as a standalone (un-reduced) element. If the |
| 205 | +asymmetric directional limits must be enforced, pin the `MonitoredLine`'s |
| 206 | +endpoints so reduction does not collapse it (e.g. via `irreducible_buses`). |
| 207 | + |
| 208 | +## Defaults at a glance |
| 209 | + |
| 210 | +| Setting | Default | |
| 211 | +|:------------------------------------------------------------------- |:--------------------------------------------------------- | |
| 212 | +| `"parallel_branch_max_rating_method"` (`AbstractBranchFormulation`) | `"single_element_contingency"` | |
| 213 | +| Security-constrained extra attribute | `"include_planned_outages" => false` | |
| 214 | +| `MixedBranchesParallel` aggregation | `sum_of_max` (attribute ignored) | |
| 215 | +| Single branch / transformer rating | `PSY.get_rating` | |
| 216 | +| Series chain rating | weakest link (minimum member rating) | |
| 217 | +| Three-winding winding rating | winding rating, falling back to parent transformer rating | |
| 218 | +| Post-contingency single-branch rating | `PSY.get_rating_b`, falling back to `PSY.get_rating` | |
| 219 | +| Time-series multiplier (parallel) | `sum_of_max` regardless of the attribute (with warning) | |
| 220 | +| Branch rating time series formulation support | `StaticBranch`, `AbstractSecurityConstrainedStaticBranch` | |
0 commit comments