Skip to content

Commit 24068f7

Browse files
authored
Merge pull request #49 from statnett/fix-conductor-temperature-computation
Update thermal_model.py
2 parents 2cd94db + 959ac5a commit 24068f7

File tree

5 files changed

+102
-61
lines changed

5 files changed

+102
-61
lines changed

linerate/models/thermal_model.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ def compute_conductor_temperature(
245245
----------
246246
current:
247247
:math:`I_\text{max}~\left[\text{A}\right]`. The current flowing through the conductor.
248+
NOTE that the current is the total current for all conductors in the span. When
249+
computing the temperature, the current is divided by the number of conductors.
248250
min_temperature:
249251
:math:`T_\text{min}~\left[^\circ\text{C}\right]`. Lower bound for the numerical scheme
250252
for computing the temperature
@@ -262,12 +264,12 @@ def compute_conductor_temperature(
262264
Union[float, float64, ndarray[Any, dtype[float64]]]
263265
:math:`I~\left[\text{A}\right]`. The thermal rating.
264266
"""
267+
n = self.span.num_conductors
265268
T = solver.compute_conductor_temperature(
266269
self.compute_heat_balance,
267-
current=current,
270+
current=current / n,
268271
min_temperature=min_temperature,
269272
max_temperature=max_temperature,
270273
tolerance=tolerance,
271274
)
272-
n = self.span.num_conductors
273-
return T / n
275+
return T

tests/acceptance_tests/test_cigre_ampacity_cases.py

+12-57
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,27 @@
77
import linerate
88

99

10-
@pytest.fixture
11-
def drake_conductor_a():
12-
return linerate.Conductor(
13-
core_diameter=10.4e-3,
14-
conductor_diameter=28.1e-3,
15-
outer_layer_strand_diameter=4.4e-3,
16-
emissivity=0.8,
17-
solar_absorptivity=0.8,
18-
temperature1=25,
19-
temperature2=75,
20-
resistance_at_temperature2=8.688e-5,
21-
resistance_at_temperature1=7.283e-5,
22-
aluminium_cross_section_area=float("nan"),
23-
constant_magnetic_effect=1,
24-
current_density_proportional_magnetic_effect=0,
25-
max_magnetic_core_relative_resistance_increase=1,
26-
)
27-
28-
29-
@pytest.fixture
30-
def example_weather_a():
31-
return linerate.Weather(
32-
air_temperature=40,
33-
wind_direction=np.radians(30), # Conductor azimuth is 90, so 90 - 30 is 30
34-
wind_speed=0.61,
35-
clearness_ratio=1,
36-
)
37-
38-
39-
@pytest.fixture
40-
def example_span_a(drake_conductor_a):
41-
start_tower = linerate.Tower(latitude=30, longitude=0.0001, altitude=0)
42-
end_tower = linerate.Tower(latitude=30, longitude=-0.0001, altitude=0)
43-
return linerate.Span(
44-
conductor=drake_conductor_a,
45-
start_tower=start_tower,
46-
end_tower=end_tower,
47-
ground_albedo=0.1,
48-
num_conductors=1,
49-
)
50-
51-
52-
@pytest.fixture
53-
def example_model_a(example_span_a, example_weather_a):
54-
return linerate.Cigre601(example_span_a, example_weather_a, np.datetime64("2016-06-10 11:00"))
55-
10+
def test_example_a_convective_cooling(example_model_1_conductors):
11+
assert example_model_1_conductors.compute_convective_cooling(100, None) == approx(77.6, abs=0.5)
5612

57-
def test_example_a_convective_cooling(example_model_a):
58-
assert example_model_a.compute_convective_cooling(100, None) == approx(77.6, abs=0.5)
5913

14+
def test_example_a_radiative_cooling(example_model_1_conductors):
15+
assert example_model_1_conductors.compute_radiative_cooling(100, None) == approx(39.1, abs=0.5)
6016

61-
def test_example_a_radiative_cooling(example_model_a):
62-
assert example_model_a.compute_radiative_cooling(100, None) == approx(39.1, abs=0.5)
6317

18+
def test_example_a_solar_heating(example_model_1_conductors):
19+
assert example_model_1_conductors.compute_solar_heating(100, None) == approx(27.2, abs=0.5)
6420

65-
def test_example_a_solar_heating(example_model_a):
66-
assert example_model_a.compute_solar_heating(100, None) == approx(27.2, abs=0.5)
6721

68-
69-
def test_example_a_resistance(example_model_a):
70-
assert example_model_a.compute_resistance(100, None) == approx(9.3905e-5, abs=0.0001e-5)
22+
def test_example_a_resistance(example_model_1_conductors):
23+
assert example_model_1_conductors.compute_resistance(100, None) == approx(
24+
9.3905e-5, abs=0.0001e-5
25+
)
7126

7227

73-
def test_example_a_ampacity(example_model_a):
28+
def test_example_a_ampacity(example_model_1_conductors):
7429
# There are noticable roundoff errors in the report
75-
assert example_model_a.compute_steady_state_ampacity(100, tolerance=1e-8) == approx(
30+
assert example_model_1_conductors.compute_steady_state_ampacity(100, tolerance=1e-8) == approx(
7631
976, abs=1.5
7732
)
7833

tests/conftest.py

+72
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import hypothesis
2+
import numpy as np
23
import pytest
34

5+
import linerate
6+
47
hypothesis.settings.register_profile("default", deadline=None)
58
hypothesis.settings.load_profile("default")
69

@@ -15,3 +18,72 @@ def rng(random_seed):
1518
import numpy as np
1619

1720
return np.random.default_rng(random_seed)
21+
22+
23+
@pytest.fixture
24+
def drake_conductor_a():
25+
return linerate.Conductor(
26+
core_diameter=10.4e-3,
27+
conductor_diameter=28.1e-3,
28+
outer_layer_strand_diameter=4.4e-3,
29+
emissivity=0.8,
30+
solar_absorptivity=0.8,
31+
temperature1=25,
32+
temperature2=75,
33+
resistance_at_temperature2=8.688e-5,
34+
resistance_at_temperature1=7.283e-5,
35+
aluminium_cross_section_area=float("nan"),
36+
constant_magnetic_effect=1,
37+
current_density_proportional_magnetic_effect=0,
38+
max_magnetic_core_relative_resistance_increase=1,
39+
)
40+
41+
42+
@pytest.fixture
43+
def example_weather_a():
44+
return linerate.Weather(
45+
air_temperature=40,
46+
wind_direction=np.radians(30), # Conductor azimuth is 90, so 90 - 30 is 30
47+
wind_speed=0.61,
48+
clearness_ratio=1,
49+
)
50+
51+
52+
@pytest.fixture
53+
def example_span_1_conductor(drake_conductor_a):
54+
start_tower = linerate.Tower(latitude=30, longitude=0.0001, altitude=0)
55+
end_tower = linerate.Tower(latitude=30, longitude=-0.0001, altitude=0)
56+
return linerate.Span(
57+
conductor=drake_conductor_a,
58+
start_tower=start_tower,
59+
end_tower=end_tower,
60+
ground_albedo=0.1,
61+
num_conductors=1,
62+
)
63+
64+
65+
@pytest.fixture
66+
def example_span_2_conductors(drake_conductor_a):
67+
start_tower = linerate.Tower(latitude=30, longitude=0.0001, altitude=0)
68+
end_tower = linerate.Tower(latitude=30, longitude=-0.0001, altitude=0)
69+
return linerate.Span(
70+
conductor=drake_conductor_a,
71+
start_tower=start_tower,
72+
end_tower=end_tower,
73+
ground_albedo=0.1,
74+
num_conductors=2,
75+
)
76+
77+
78+
@pytest.fixture
79+
def example_model_1_conductors(example_span_1_conductor, example_weather_a):
80+
return linerate.Cigre601(
81+
example_span_1_conductor, example_weather_a, np.datetime64("2016-06-10 11:00")
82+
)
83+
84+
85+
@pytest.fixture
86+
def example_model_2_conductors(example_span_2_conductors, example_weather_a):
87+
return linerate.Cigre601(
88+
example_span_2_conductors, example_weather_a, np.datetime64("2016-06-10 11:00")
89+
)

tests/models/test_thermal_model.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""Test cases from Annex E of CIGRE TB 601."""
2+
3+
4+
def test_compute_conductor_temperature(example_model_1_conductors, example_model_2_conductors):
5+
# Check that the ampacity of a span with two conductors is divided
6+
# when computing the conductor temperature.
7+
current_1_conductor = 1000
8+
current_2_conductors = current_1_conductor * 2
9+
# The temperature should stay the same
10+
assert example_model_1_conductors.compute_conductor_temperature(
11+
current_1_conductor
12+
) == example_model_2_conductors.compute_conductor_temperature(current_2_conductors)

tests/test_solver.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def heat_balance(conductor_temperature, current):
1616
assert conductor_temperature == pytest.approx(15, rel=1e-7)
1717

1818

19-
def test_compute_conductor_temperature_computes_correct_ampacity():
19+
def test_compute_conductor_ampacity_computes_correct_ampacity():
2020
def heat_balance(conductor_temperature, current):
2121
A = current
2222
T = conductor_temperature

0 commit comments

Comments
 (0)