VoltageLimits#
- class popo.standards.VoltageLimits(name, lower_pu, upper_pu, coverage=1.0, extreme_lower_pu=None, extreme_upper_pu=None, reference='')#
Bases:
objectA statutory voltage band and the rule for judging compliance with it.
Construct through the named constructors rather than directly, so that a study records which standard it applied instead of which numbers it chose.
- Variables:
name – Human-readable identifier, carried into every report.
lower_pu – Lower bound of the normal band, in per unit of nominal.
upper_pu – Upper bound of the normal band, in per unit of nominal.
coverage – Share of samples that must lie inside the normal band.
1.0admits no exceedance; EN 50160 sets0.95over a week.extreme_lower_pu – Bound that no sample may break, where the standard defines one.
Nonewhere the normal band is already absolute.extreme_upper_pu – The same, above nominal.
reference – The clause or document the limits come from.
- classmethod en_50160()#
European public distribution networks, EN 50160:2022.
95 % of ten-minute mean RMS values over each week must sit within \(U_n \pm 10\%\), and every value within +10 %/-15 %. The coverage rule is the substance of the standard, not a technicality: a feeder may sit below the band for part of a week and still comply.
- Return type:
- classmethod ansi_c84_1_range_a()#
North American service voltage, ANSI C84.1 Range A.
\(\pm 5\%\) of nominal, which utilities are expected to hold under normal conditions. There is no coverage allowance: Range B exists to describe the excursions Range A does not permit.
- Return type:
- classmethod ansi_c84_1_range_b()#
North American service voltage, ANSI C84.1 Range B.
The wider band, -8.3 % to +5.8 %, describing conditions that are infrequent and must be corrected within a reasonable time. Use it to classify how bad an excursion is, not as the operating target.
- Return type:
- check(voltage_pu)#
Judge a per-unit voltage series against this standard.
- Parameters:
voltage_pu (
ArrayLike) – Voltage samples in per unit of nominal, of any shape. Non-finite entries are dropped rather than counted as breaches.- Return type:
- Returns:
A
ComplianceReportcarrying the verdict and what drove it.- Raises:
ValueError – If no finite sample is present, since a verdict on an empty series would be indistinguishable from a pass.
Examples
>>> limits = VoltageLimits.ansi_c84_1_range_a() >>> limits.check([1.0, 0.99, 1.02]).compliant True
- violations(readings, value_col='vmag_pu')#
The readings outside this standard’s normal band, and how far outside.
- Parameters:
- Return type:
- Returns:
The rows of
readingsoutside[lower_pu, upper_pu], with asidecolumn ("low"or"high") and aseverity_pucolumn, the distance past the breached bound, always positive. Non-finite readings are not violations.
Examples
>>> limits = VoltageLimits.ansi_c84_1_range_a() >>> limits.violations(pd.DataFrame({"vmag_pu": [0.94, 1.0, 1.07]}))["side"].tolist() ['low', 'high']
- event_summary(traces)#
Per-trace counts, severities and durations of excursions outside the band.
A single worst value says how bad a trace got; it does not say whether that was one step or the whole afternoon. This counts the steps above and below the band, their mean severity, and the longest unbroken run, so a brief touch and a sustained excursion are told apart.
- Parameters:
traces (
Mapping[str,ArrayLike]) – One per-unit voltage series per name, e.g. per customer bus frompopo.powerflow.SolveReport.voltage_traces(). A non-finite step, such as a diverged solve, counts as neither above nor below.- Return type:
- Returns:
One row per trace –
name,v_mean_pu,v_min_pu,v_max_pu,v_std_pu, thenover_steps,over_severity_puandover_longest_steps, and the same three forunder.
Examples
>>> limits = VoltageLimits.ansi_c84_1_range_a() >>> limits.event_summary({"a": [1.0, 1.06, 1.07, 1.0]})["over_longest_steps"].item() 2