Skip to content

Commit a717f44

Browse files
authored
Merge pull request #286 from Breakthrough-Energy/daniel/hifld_update_xfmr_params
refactor: update values and logic for representative transformer designs
2 parents 6b446f0 + c7d63cb commit a717f44

File tree

7 files changed

+238
-183
lines changed

7 files changed

+238
-183
lines changed

prereise/gather/griddata/hifld/const.py

-27
Original file line numberDiff line numberDiff line change
@@ -127,33 +127,6 @@
127127
"500": 500,
128128
}
129129

130-
transformer_reactance = { # per-unit
131-
(69, 115): 0.14242,
132-
(69, 138): 0.10895,
133-
(69, 161): 0.14943,
134-
(69, 230): 0.09538,
135-
(69, 345): 0.08896,
136-
(115, 161): 0.04516,
137-
(115, 230): 0.04299,
138-
(115, 345): 0.04020,
139-
(115, 500): 0.06182,
140-
(138, 161): 0.02818,
141-
(138, 230): 0.03679,
142-
(138, 345): 0.03889,
143-
(138, 500): 0.03279,
144-
(138, 765): 0.02284,
145-
(161, 230): 0.06539,
146-
(161, 345): 0.03293,
147-
(161, 500): 0.06978,
148-
(230, 345): 0.02085,
149-
(230, 500): 0.01846,
150-
(230, 765): 0.01616,
151-
(345, 500): 0.01974,
152-
(345, 765): 0.01625,
153-
(500, 765): 0.00436,
154-
}
155-
transformer_rating = 800 # MVA
156-
157130
eia_storage_gen_types = {
158131
"Batteries",
159132
"Flywheels",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
high_kV,x_to_r_ratio
2+
69,20
3+
115,25
4+
138,27
5+
161,28
6+
230,30
7+
345,60
8+
500,70
9+
765,80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
sub_id,low_kV,high_kV,number
2+
300060,69,138,4
3+
300940,69,138,2
4+
304621,69,138,3
5+
308608,69,138,3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
low_kV,high_kV,x,MVA
2+
69,115,0.19,60
3+
69,138,0.14,100
4+
69,161,0.12,85
5+
69,230,0.11,190
6+
69,345,0.07,250
7+
115,161,0.048,180
8+
115,230,0.044,290
9+
115,345,0.046,400
10+
115,500,0.047,300
11+
138,161,0.028,220
12+
138,230,0.041,330
13+
138,345,0.033,480
14+
138,500,0.045,470
15+
138,765,0.024,850
16+
161,230,0.042,330
17+
161,345,0.028,500
18+
161,500,0.016,1100
19+
230,345,0.018,580
20+
230,500,0.013,1100
21+
230,765,0.0165,1250
22+
345,500,0.0105,1100
23+
345,765,0.0085,2100
24+
500,765,0.0045,2100

prereise/gather/griddata/hifld/data_access/load.py

+52
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,58 @@ def get_hifld_electric_power_transmission_lines(path):
336336
return properties.query("STATUS == 'IN SERVICE' or STATUS == 'NOT AVAILABLE'")
337337

338338

339+
def get_transformer_number_overrides(path):
340+
"""Load overrides for the number of transformers between buses.
341+
342+
:param str path: path to a CSV file containing columns: 'sub_id', 'low_kV',
343+
'high_kV', and 'number'.
344+
:return: (*pandas.Series*) -- index is a MultiIndex of
345+
('sub_id', 'low_kV', 'high_kV'), values are 'number' integers.
346+
"""
347+
return pd.read_csv(path).set_index(["sub_id", "low_kV", "high_kV"]).squeeze()
348+
349+
350+
def get_transformer_parameters(
351+
data_dir=None, transformer_designs_path=None, impedance_ratios_path=None
352+
):
353+
"""Load transformer designs (by voltage pairs) and transformer impedance ratios
354+
(by higher voltage) and combine into a single dataframe.
355+
356+
:param str data_dir: if this is not None, two files in this directory will be
357+
loaded: 'transformer_params.csv' and 'transformer_impedance_ratios.csv'.
358+
Required columns for each file are listed in the descriptions of
359+
the ``transformer_designs_path`` and ``impedance_ratios_path`` parameters.
360+
:param str transformer_designs_path: if ``data_dir`` is None, this file will be
361+
loaded. Required columns are 'low_kV', 'high_kV', 'x', and 'MVA'.
362+
:param str impedance_ratios_path: if ``data_dir`` is None, this file will be loaded.
363+
Required columns are 'high_kV' and 'x_to_r_ratio'.
364+
:raises TypeError: if ``data_dir`` is None and either of
365+
``transformer_designs_path`` or ``impedance_ratios_path`` is None.
366+
:return: (*pandas.DataFrame*) -- index is (low_kV, high_kV), columns are 'x', 'r',
367+
and 'MVA'. 'x' and 'r' values are per-unit, 'MVA' is in megawatts.
368+
"""
369+
if data_dir is None and (
370+
transformer_designs_path is None or impedance_ratios_path is None
371+
):
372+
raise TypeError(
373+
"Either data_dir or transformer_designs_path and impedance_ratios_path "
374+
"must be specified."
375+
)
376+
if data_dir is not None:
377+
transformer_designs_path = os.path.join(data_dir, "transformer_params.csv")
378+
impedance_ratios_path = os.path.join(
379+
data_dir, "transformer_impedance_ratios.csv"
380+
)
381+
transformer_designs = pd.read_csv(transformer_designs_path)
382+
transformer_impedance_ratios = pd.read_csv(
383+
impedance_ratios_path, index_col="high_kV"
384+
)
385+
transformer_designs["r"] = transformer_designs["x"] / transformer_designs[
386+
"high_kV"
387+
].map(transformer_impedance_ratios["x_to_r_ratio"])
388+
return transformer_designs.set_index(["low_kV", "high_kV"])[["x", "r", "MVA"]]
389+
390+
339391
def get_zone(path):
340392
"""Read zone CSV file.
341393

prereise/gather/griddata/hifld/data_process/tests/test_transmission.py

+41-68
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
from unittest.mock import Mock
2-
31
import pandas as pd
42
import pytest
53
from pandas.testing import assert_frame_equal, assert_series_equal
64

7-
from prereise.gather.griddata.hifld import const
85
from prereise.gather.griddata.hifld.data_process.transmission import (
96
add_b2bs_to_dc_lines,
10-
add_impedance_and_rating,
7+
add_lines_impedances_ratings,
118
add_substation_info_to_buses,
129
assign_buses_to_lines,
1310
augment_line_voltages,
1411
create_buses,
1512
create_transformers,
16-
estimate_branch_impedance,
17-
estimate_branch_rating,
1813
filter_islands_and_connect_with_mst,
1914
map_lines_to_substations_using_coords,
2015
split_lines_to_ac_and_dc,
@@ -37,7 +32,7 @@ def test_add_b2bs_to_dc_lines():
3732
assert_frame_equal(dc_lines.iloc[2:], expected_new_rows)
3833

3934

40-
def test_add_impedance_and_rating():
35+
def test_add_lines_impedances_ratings():
4136
branch = pd.DataFrame(
4237
{
4338
"VOLTAGE": [69, 75, 75, 138],
@@ -52,7 +47,7 @@ def test_add_impedance_and_rating():
5247
}
5348
)
5449
expected_modified_branch = pd.concat([branch, expected_new_columns], axis=1)
55-
add_impedance_and_rating(branch, bus_voltages=None)
50+
add_lines_impedances_ratings(branch)
5651
assert_frame_equal(branch, expected_modified_branch)
5752

5853

@@ -185,71 +180,49 @@ def test_create_transformers():
185180
},
186181
dtype="float",
187182
)
188-
expected_transformers = pd.DataFrame(
189-
{"from_bus_id": [0, 2, 4, 5], "to_bus_id": [1, 3, 5, 6]}
190-
)
191-
transformers = create_transformers(bus)
192-
assert_frame_equal(transformers, expected_transformers)
193-
194-
195-
def test_estimate_branch_impedance_lines():
196-
resistance = 0.01
197-
reactance = 0.1
198-
fake_lines = [Mock(series_impedance=(resistance + 1j * reactance))] * 3
199-
branch = pd.DataFrame(
200-
{"VOLTAGE": [69, 70, 345], "type": ["Line"] * 3, "line_object": fake_lines}
183+
transformer_designs = pd.DataFrame(
184+
{
185+
"x": [0.19, 0.07, 0.044, 0.018],
186+
"r": [0.01, 0.001, 0.001, 5e-4],
187+
"MVA": [60, 250, 280, 580],
188+
},
189+
index=pd.MultiIndex.from_tuples([(69, 115), (69, 345), (115, 230), (230, 345)]),
201190
)
202-
x = estimate_branch_impedance(branch.iloc[0], pd.Series())
203-
assert x == reactance / (69**2 / const.s_base)
204-
x = estimate_branch_impedance(branch.iloc[1], pd.Series())
205-
assert x == reactance / (70**2 / const.s_base)
206-
x = estimate_branch_impedance(branch.iloc[2], pd.Series())
207-
assert x == reactance / (345**2 / const.s_base)
208-
209-
210-
def test_estimate_branch_impedance_transformers():
211-
transformers = pd.DataFrame(
212-
{"from_bus_id": [0, 1, 2], "to_bus_id": [1, 2, 3], "type": ["Transformer"] * 3}
191+
lines = pd.DataFrame(
192+
[
193+
# One branch to low-voltage side of buses (0, 1) transformer
194+
{"from_bus_id": 100, "to_bus_id": 0, "rateA": 75},
195+
# Two branches to high-voltage side of buses (0, 1) transformer
196+
{"from_bus_id": 1, "to_bus_id": 101, "rateA": 100},
197+
{"from_bus_id": 1, "to_bus_id": 102, "rateA": 300},
198+
# Two branches to low-voltage side of buses (2, 3) transformer
199+
{"from_bus_id": 103, "to_bus_id": 2, "rateA": 50},
200+
{"from_bus_id": 104, "to_bus_id": 2, "rateA": 100},
201+
# One branch to high-voltage side of buses (2, 3) transformer
202+
{"from_bus_id": 3, "to_bus_id": 105, "rateA": 300},
203+
# One branch to each side of buses (5, 6) transformer
204+
# The second of these is also on the high-voltage side of buses (4, 5) xfmr
205+
{"from_bus_id": 6, "to_bus_id": 106, "rateA": 500},
206+
{"from_bus_id": 5, "to_bus_id": 107, "rateA": 250},
207+
# One branch connected to no transformers
208+
{"from_bus_id": 998, "to_bus_id": 999, "rateA": 100e3},
209+
]
213210
)
214-
bus_voltages = pd.Series([69, 230, 350, 500])
215-
x = estimate_branch_impedance(transformers.iloc[0], bus_voltages)
216-
assert x == const.transformer_reactance[(69, 230)]
217-
x = estimate_branch_impedance(transformers.iloc[1], bus_voltages)
218-
assert x == const.transformer_reactance[(230, 345)]
219-
x = estimate_branch_impedance(transformers.iloc[2], bus_voltages)
220-
assert x == const.transformer_reactance[(345, 500)]
221-
222-
223-
def test_estimate_branch_rating_lines():
224-
fake_ratings = pd.Series([10, 20, 30, 40])
225-
fake_thermal_ratings = pd.Series([100, 200, 300, 400])
226-
fake_lines = [Mock(power_rating=i) for i in fake_ratings]
227-
branch = pd.DataFrame(
211+
# One transformer to (0, 1) (only needs to support the low-voltage power)
212+
# Three transformer to (2, 3) (low-voltage side requires 3x transformers in total)
213+
# One transformer to (4, 5) (only needs to support the low-voltage power)
214+
# One transformer to (5, 6) (only needs to support the low-voltage power)
215+
expected_transformers = pd.DataFrame(
228216
{
229-
"VOLTAGE": [69, 140, 345, 499],
230-
"type": ["Line"] * 4,
231-
"line_object": fake_lines,
217+
"from_bus_id": [0, 2, 2, 2, 4, 5],
218+
"to_bus_id": [1, 3, 3, 3, 5, 6],
219+
"x": [0.07, 0.19, 0.19, 0.19, 0.044, 0.018],
220+
"r": [0.001, 0.01, 0.01, 0.01, 0.001, 5e-4],
221+
"rateA": [250.0, 60.0, 60.0, 60.0, 280.0, 580.0],
232222
}
233223
)
234-
assert_series_equal(
235-
fake_ratings,
236-
branch.apply(estimate_branch_rating, args=[None, fake_thermal_ratings], axis=1),
237-
)
238-
239-
240-
def test_estimate_branch_rating_transformers():
241-
thermal_ratings = pd.Series([100, 550, 1655, 2585], index=[69, 230, 345, 500])
242-
transformers = pd.DataFrame(
243-
{"from_bus_id": [0, 1, 2], "to_bus_id": [1, 2, 3], "type": ["Transformer"] * 3}
244-
)
245-
bus_voltages = pd.Series([69, 230, 350, 500])
246-
247-
rating = estimate_branch_rating(transformers.iloc[0], bus_voltages, thermal_ratings)
248-
assert rating == const.transformer_rating
249-
rating = estimate_branch_rating(transformers.iloc[1], bus_voltages, thermal_ratings)
250-
assert rating == const.transformer_rating * 3
251-
rating = estimate_branch_rating(transformers.iloc[2], bus_voltages, thermal_ratings)
252-
assert rating == const.transformer_rating * 4
224+
transformers = create_transformers(bus, lines, transformer_designs)
225+
assert_frame_equal(transformers, expected_transformers)
253226

254227

255228
def test_filter_islands_and_connect_with_mst():

0 commit comments

Comments
 (0)