Skip to content

Commit

Permalink
v0.1.5 (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinBelthle authored Aug 21, 2024
1 parent 651d85b commit 5756352
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 56 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

v0.1.5 (2023-08-21)
-------------------

### Refactoring
* transpose all output matrices to fit with Antares expected time-series shape

v0.1.4 (2023-08-09)
-------------------

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "antares-timeseries-generation"
version = "0.1.4"
version = "0.1.5"
license = {text="MPL-2.0"}
description = 'Timeseries generation library aiming at creating input data for Antares simulator studies.'
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sonar.projectVersion=0.1.4
sonar.projectVersion=0.1.5
sonar.organization=antaressimulatorteam
sonar.projectKey=AntaresSimulatorTeam_antares-timeseries-generation
sonar.sources=src
Expand Down
30 changes: 15 additions & 15 deletions src/antares/tsgen/ts_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,17 @@ def _check_cluster(cluster: ThermalCluster) -> None:

class OutputTimeseries:
def __init__(self, ts_count: int, days: int) -> None:
self.available_units = np.zeros(shape=(ts_count, days), dtype=int)
self.available_units = np.zeros(shape=(days, ts_count), dtype=int)
# available power each hours
self.available_power = np.zeros((ts_count, 24 * days), dtype=float)
self.available_power = np.zeros((24 * days, ts_count), dtype=float)
# number of pure planed, pure forced and mixed outage each day
self.planned_outages = np.zeros((ts_count, days), dtype=int)
self.forced_outages = np.zeros((ts_count, days), dtype=int)
self.mixed_outages = np.zeros((ts_count, days), dtype=int)
self.planned_outages = np.zeros((days, ts_count), dtype=int)
self.forced_outages = np.zeros((days, ts_count), dtype=int)
self.mixed_outages = np.zeros((days, ts_count), dtype=int)
# number of pure planed and pure forced outage duration each day
# (mixed outage duration = pod + fod)
self.planned_outage_durations = np.zeros((ts_count, days), dtype=int)
self.forced_outage_durations = np.zeros((ts_count, days), dtype=int)
self.planned_outage_durations = np.zeros((days, ts_count), dtype=int)
self.forced_outage_durations = np.zeros((days, ts_count), dtype=int)


def _column_powers(column: FloatArray, width: int) -> npt.NDArray:
Expand All @@ -140,7 +140,7 @@ def _daily_to_hourly(daily_data: npt.NDArray) -> npt.NDArray:
"""
if daily_data.ndim != 2:
raise ValueError("Daily data must be a 2D-array")
return np.repeat(daily_data, 24, axis=1)
return np.repeat(daily_data, 24, axis=0)


def _categorize_outages(available_units: int, po_candidates: int, fo_candidates: int) -> Tuple[int, int, int]:
Expand Down Expand Up @@ -391,16 +391,16 @@ def generate_time_series(

# = storing output in output arrays =
if ts_index >= 0: # drop the 2 first generated timeseries
output.planned_outages[ts_index, day] = planned_outages
output.forced_outages[ts_index, day] = forced_outages
output.mixed_outages[ts_index, day] = mixed_outages
output.planned_outage_durations[ts_index, day] = po_duration
output.forced_outage_durations[ts_index, day] = fo_duration
output.available_units[ts_index, day] = current_available_units
output.planned_outages[day, ts_index] = planned_outages
output.forced_outages[day, ts_index] = forced_outages
output.mixed_outages[day, ts_index] = mixed_outages
output.planned_outage_durations[day, ts_index] = po_duration
output.forced_outage_durations[day, ts_index] = fo_duration
output.available_units[day, ts_index] = current_available_units

now = (now + 1) % log_size

hourly_available_units = _daily_to_hourly(output.available_units)
output.available_power = hourly_available_units * cluster.nominal_power * cluster.modulation
output.available_power = hourly_available_units * cluster.nominal_power * cluster.modulation[:, np.newaxis]
np.round(output.available_power)
return output
16 changes: 8 additions & 8 deletions tests/test_ts_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def test_one_unit_cluster(cluster_1, output_directory):
tot_po = 0
tot_fo = 0
for i in range(365 * ts_nb):
tot_po += results.planned_outages[i // 365][i % 365] * 2
tot_fo += results.forced_outages[i // 365][i % 365] * 8
tot_po += results.planned_outages[i % 365][i // 365] * 2
tot_fo += results.forced_outages[i % 365][i // 365] * 8
true_por = tot_po / (365 * ts_nb)
true_for = tot_fo / (365 * ts_nb)

Expand All @@ -66,8 +66,8 @@ def test_hundred_unit_cluster(cluster_100, output_directory):
tot_po = 0
tot_fo = 0
for i in range(365 * ts_nb):
tot_po += results.planned_outages[i // 365][i % 365] * 2
tot_fo += results.forced_outages[i // 365][i % 365] * 8
tot_po += results.planned_outages[i % 365][i // 365] * 2
tot_fo += results.forced_outages[i % 365][i // 365] * 8
true_por = tot_po / (365 * ts_nb)
true_for = tot_fo / (365 * ts_nb)

Expand All @@ -76,8 +76,8 @@ def test_hundred_unit_cluster(cluster_100, output_directory):
cursor = [0] * 10
tot_simult_po = 0
for i in range(365 * ts_nb):
po = results.planned_outages[i // 365][i % 365]
mo = results.mixed_outages[i // 365][i % 365]
po = results.planned_outages[i % 365][i // 365]
mo = results.mixed_outages[i % 365][i // 365]

tot_simult_po += po
tot_simult_po += mo
Expand Down Expand Up @@ -117,8 +117,8 @@ def test_max_po(cluster_high_por, output_directory):
cursor = [0] * 10
tot_simult_po = 0
for i in range(365 * ts_nb):
po = results.planned_outages[i // 365][i % 365]
mo = results.mixed_outages[i // 365][i % 365]
po = results.planned_outages[i % 365][i // 365]
mo = results.mixed_outages[i % 365][i // 365]

tot_simult_po += po
tot_simult_po += mo
Expand Down
66 changes: 35 additions & 31 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
def test_daily_to_hourly():
daily = np.array([[1, 2]])
hourly = _daily_to_hourly(daily)
expected = [[1] * 24 + [2] * 24]
expected = [[1, 2]] * 24
npt.assert_equal(hourly, expected)


Expand Down Expand Up @@ -186,17 +186,18 @@ def test_forced_outages(rng):
generator = ThermalDataGenerator(rng=rng, days=days)
results = generator.generate_time_series(cluster, 1)
# 2 forced outages occur on day 5, with duration 10
npt.assert_equal(results.forced_outages[0][:6], [0, 0, 0, 0, 2, 0])
npt.assert_equal(results.forced_outage_durations[0][:6], [0, 0, 0, 0, 10, 0])
npt.assert_equal(results.forced_outages.T[0][:6], [0, 0, 0, 0, 2, 0])
npt.assert_equal(results.forced_outage_durations.T[0][:6], [0, 0, 0, 0, 10, 0])
# No planned outage
npt.assert_equal(results.planned_outages[0], np.zeros(365))
npt.assert_equal(results.planned_outage_durations[0], np.zeros(365))
npt.assert_equal(results.planned_outages.T[0], np.zeros(365))
npt.assert_equal(results.planned_outage_durations.T[0], np.zeros(365))

npt.assert_equal(results.available_units[0][:5], [9, 9, 9, 9, 8])
npt.assert_equal(results.available_units.T[0][:5], [9, 9, 9, 9, 8])
# Check available power consistency with available units and modulation
assert results.available_power[0][0] == 900
assert results.available_power[0][12] == 450 # Modulation is 0.5 for hour 12
assert results.available_power[0][4 * 24] == 800
available_power = results.available_power.T
assert available_power[0][0] == 900
assert available_power[0][12] == 450 # Modulation is 0.5 for hour 12
assert available_power[0][4 * 24] == 800


def test_planned_outages(rng):
Expand All @@ -221,15 +222,16 @@ def test_planned_outages(rng):
generator = ThermalDataGenerator(rng=rng, days=days)
results = generator.generate_time_series(cluster, 1)
# 0 forced outage
npt.assert_equal(results.forced_outages[0], np.zeros(365))
npt.assert_equal(results.forced_outage_durations[0], np.zeros(365))
npt.assert_equal(results.forced_outages.T[0], np.zeros(365))
npt.assert_equal(results.forced_outage_durations.T[0], np.zeros(365))
# No planned outage
npt.assert_equal(results.planned_outages[0][:6], [0, 0, 0, 0, 2, 0])
npt.assert_equal(results.available_units[0][:5], [9, 9, 9, 9, 8])
npt.assert_equal(results.planned_outages.T[0][:6], [0, 0, 0, 0, 2, 0])
npt.assert_equal(results.available_units.T[0][:5], [9, 9, 9, 9, 8])
# Check available power consistency with available units and modulation
assert results.available_power[0][0] == 900
assert results.available_power[0][12] == 450 # Modulation is 0.5 for hour 12
assert results.available_power[0][4 * 24] == 800
available_power = results.available_power.T
assert available_power[0][0] == 900
assert available_power[0][12] == 450 # Modulation is 0.5 for hour 12
assert available_power[0][4 * 24] == 800


def test_planned_outages_limitation(rng):
Expand All @@ -254,15 +256,16 @@ def test_planned_outages_limitation(rng):
generator = ThermalDataGenerator(rng=rng, days=days)
results = generator.generate_time_series(cluster, 1)
# No forced outage
npt.assert_equal(results.forced_outages[0], np.zeros(365))
npt.assert_equal(results.forced_outage_durations[0], np.zeros(365))
npt.assert_equal(results.forced_outages.T[0], np.zeros(365))
npt.assert_equal(results.forced_outage_durations.T[0], np.zeros(365))
# Maxmimum one planned outage at a time
npt.assert_equal(results.planned_outages[0][:6], [1, 0, 1, 0, 1, 0])
npt.assert_equal(results.planned_outage_durations[0][:6], [2, 0, 2, 0, 2, 0])
npt.assert_equal(results.available_units[0][:5], [9, 9, 9, 9, 9])
npt.assert_equal(results.planned_outages.T[0][:6], [1, 0, 1, 0, 1, 0])
npt.assert_equal(results.planned_outage_durations.T[0][:6], [2, 0, 2, 0, 2, 0])
npt.assert_equal(results.available_units.T[0][:5], [9, 9, 9, 9, 9])
# Check available power consistency with available units and modulation
assert results.available_power[0][0] == 900
assert results.available_power[0][4 * 24] == 900
available_power = results.available_power.T
assert available_power[0][0] == 900
assert available_power[0][4 * 24] == 900


def test_planned_outages_min_limitation(rng):
Expand All @@ -287,15 +290,16 @@ def test_planned_outages_min_limitation(rng):
generator = ThermalDataGenerator(rng=rng, days=days)
results = generator.generate_time_series(cluster, 1)
# No forced outage
npt.assert_equal(results.forced_outages[0], np.zeros(365))
npt.assert_equal(results.forced_outage_durations[0], np.zeros(365))
npt.assert_equal(results.forced_outages.T[0], np.zeros(365))
npt.assert_equal(results.forced_outage_durations.T[0], np.zeros(365))
# Maxmimum one planned outage at a time
npt.assert_equal(results.planned_outages[0][:6], [0, 0, 1, 0, 0, 1])
npt.assert_equal(results.planned_outage_durations[0][:6], [0, 0, 10, 0, 0, 10])
npt.assert_equal(results.available_units[0][:5], [8, 8, 8, 8, 8])
npt.assert_equal(results.planned_outages.T[0][:6], [0, 0, 1, 0, 0, 1])
npt.assert_equal(results.planned_outage_durations.T[0][:6], [0, 0, 10, 0, 0, 10])
npt.assert_equal(results.available_units.T[0][:5], [8, 8, 8, 8, 8])
# Check available power consistency with available units and modulation
assert results.available_power[0][0] == 800
assert results.available_power[0][4 * 24] == 800
available_power = results.available_power.T
assert available_power[0][0] == 800
assert available_power[0][4 * 24] == 800


def test_with_long_fo_and_po_duration(data_directory):
Expand Down Expand Up @@ -333,4 +337,4 @@ def test_with_long_fo_and_po_duration(data_directory):
expected_matrix = np.loadtxt(
data_directory.joinpath(f"expected_result_long_po_and_fo_duration.txt"), delimiter="\t"
)
assert np.array_equal(results.available_power.T, expected_matrix)
assert np.array_equal(results.available_power, expected_matrix)

0 comments on commit 5756352

Please sign in to comment.