Skip to content

Commit f60bec2

Browse files
committed
fix branch check bug
1 parent 3b62f66 commit f60bec2

2 files changed

Lines changed: 121 additions & 2 deletions

File tree

src/utils/IO/branchdata_checks.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function line_rating_calculation(l::Union{Line, MonitoredLine})
127127
to_voltage_limits = get_voltage_limits(get_arc(l).to)
128128

129129
fr_vmin = isnothing(from_voltage_limits) ? 0.9 : from_voltage_limits.min
130-
to_vmin = isnothing(to_voltage_limits) ? 0.9 : from_voltage_limits.min
130+
to_vmin = isnothing(to_voltage_limits) ? 0.9 : to_voltage_limits.min
131131

132132
c_max = sqrt(fr_vmin^2 + to_vmin^2 - 2 * fr_vmin * to_vmin * cos(theta_max))
133133
new_rate = y_mag * max(fr_vmin, to_vmin) * c_max
@@ -144,7 +144,9 @@ function correct_rate_limits!(branch::Union{Line, MonitoredLine}, basemva::Float
144144
continue
145145
end
146146
if rating_value < 0.0
147-
@error "PowerSystems does not support negative line rates. $(field): $(rating)"
147+
@error "PowerSystems does not support negative line rates for \
148+
$(summary(branch)) $(field): $(rating_value)." _group =
149+
IS.LOG_GROUP_PARSING maxlog = PS_MAX_LOG
148150
return false
149151
end
150152
if rating_value == INFINITE_BOUND
@@ -204,6 +206,12 @@ function check_rating_values(
204206
@assert field [:rating_b, :rating_c]
205207
continue
206208
end
209+
if rating_value < 0.0
210+
@error "PowerSystems does not support negative transformer rates for \
211+
$(summary(xfrm)) $(field): $(rating_value)." _group =
212+
IS.LOG_GROUP_PARSING maxlog = PS_MAX_LOG
213+
return false
214+
end
207215
if (rating_value * device_base_power >= 2.0 * closest_rate_range.max)
208216
@warn "$(field) $(round(rating_value*device_base_power; digits=2)) MW for $(get_name(xfrm)) is 2x larger than the max expected rating $(closest_rate_range.max) MW for Transformer at a $(closest_v_level) kV Voltage level." _group =
209217
IS.LOG_GROUP_PARSING maxlog = PS_MAX_LOG

test/test_branchchecks_testing.jl

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,114 @@ end
178178
PowerSystems.sanitize_angle_limits!(bad_angle_limits)
179179
)
180180
end
181+
182+
@testset "Negative branch rating fails validation cleanly" begin
183+
# Two buses at equal base voltage so the endpoint-voltage check passes and
184+
# validation reaches correct_rate_limits!.
185+
bus_from = ACBus(
186+
1, "from", true, ACBusTypes.REF, 0, 1.0, (min = 0.9, max = 1.05), 230,
187+
nothing, nothing,
188+
)
189+
bus_to = ACBus(
190+
2, "to", true, ACBusTypes.PQ, 0, 1.0, (min = 0.9, max = 1.05), 230,
191+
nothing, nothing,
192+
)
193+
sys = System(100.0; runchecks = false)
194+
add_component!(sys, bus_from)
195+
add_component!(sys, bus_to)
196+
neg_line = Line(
197+
"negline",
198+
true,
199+
0.0,
200+
0.0,
201+
Arc(; from = bus_from, to = bus_to),
202+
0.01,
203+
0.1,
204+
(from = 0.00356, to = 0.00356),
205+
-1.0, # negative rating
206+
(min = -pi / 2, max = pi / 2),
207+
)
208+
add_component!(sys, neg_line)
209+
210+
# An IS.MultiLogger is enabled at Error and rethrows log-record-generation
211+
# errors (catch_exceptions(::MultiLogger) == false), exactly like the loggers
212+
# Sienna test suites install. Under such a logger the previous `$(rating)`
213+
# typo raised UndefVarError instead of the intended IS.InvalidValue. A
214+
# NullLogger would *not* catch this regression because Julia never evaluates a
215+
# disabled log message.
216+
test_logger = IS.MultiLogger([ConsoleLogger(devnull, Logging.Error)])
217+
Logging.with_logger(test_logger) do
218+
@test_throws IS.InvalidValue PowerSystems.check_component(sys, neg_line)
219+
end
220+
end
221+
222+
@testset "line_rating_calculation uses to-side minimum voltage" begin
223+
# Asymmetric endpoint voltage limits expose whether the to-side minimum
224+
# voltage is read from the correct bus.
225+
bus_from = ACBus(
226+
1, "from", true, ACBusTypes.REF, 0, 1.0, (min = 0.9, max = 1.05), 230,
227+
nothing, nothing,
228+
)
229+
bus_to = ACBus(
230+
2, "to", true, ACBusTypes.PQ, 0, 1.0, (min = 0.5, max = 1.05), 230,
231+
nothing, nothing,
232+
)
233+
line = Line(
234+
"l",
235+
true,
236+
0.0,
237+
0.0,
238+
Arc(; from = bus_from, to = bus_to),
239+
0.01,
240+
0.1,
241+
(from = 0.00356, to = 0.00356),
242+
100.0,
243+
(min = -0.2, max = 0.3),
244+
)
245+
246+
r, x = 0.01, 0.1
247+
g = r / (r^2 + x^2)
248+
b = -x / (r^2 + x^2)
249+
y_mag = sqrt(g^2 + b^2)
250+
fr_vmin, to_vmin = 0.9, 0.5
251+
theta_max = 0.3
252+
c_max = sqrt(fr_vmin^2 + to_vmin^2 - 2 * fr_vmin * to_vmin * cos(theta_max))
253+
expected = y_mag * max(fr_vmin, to_vmin) * c_max
254+
255+
@test PowerSystems.line_rating_calculation(line) expected
256+
end
257+
258+
@testset "Negative transformer rating fails validation cleanly" begin
259+
bus_from = ACBus(
260+
1, "from", true, ACBusTypes.REF, 0, 1.0, (min = 0.9, max = 1.05), 230,
261+
nothing, nothing,
262+
)
263+
bus_to = ACBus(
264+
2, "to", true, ACBusTypes.PQ, 0, 1.0, (min = 0.9, max = 1.05), 230,
265+
nothing, nothing,
266+
)
267+
sys = System(100.0; runchecks = false)
268+
add_component!(sys, bus_from)
269+
add_component!(sys, bus_to)
270+
# rating_b has no descriptor valid_range, so only the PSY-level guard can
271+
# reject a negative secondary rating.
272+
xfrm = Transformer2W(;
273+
name = "negxfrm",
274+
available = true,
275+
active_power_flow = 0.0,
276+
reactive_power_flow = 0.0,
277+
arc = Arc(; from = bus_from, to = bus_to),
278+
r = 0.01,
279+
x = 0.1,
280+
primary_shunt = 0.0,
281+
rating = 1.0,
282+
base_power = 100.0,
283+
rating_b = -1.0, # negative secondary rating
284+
)
285+
add_component!(sys, xfrm)
286+
287+
test_logger = IS.MultiLogger([ConsoleLogger(devnull, Logging.Error)])
288+
Logging.with_logger(test_logger) do
289+
@test_throws IS.InvalidValue PowerSystems.check_component(sys, xfrm)
290+
end
291+
end

0 commit comments

Comments
 (0)