From c61d0f746317b641ff93a0469d5cdf7b1f6d3646 Mon Sep 17 00:00:00 2001 From: "stefan.schirmeister" Date: Fri, 1 Nov 2024 14:30:17 +0100 Subject: [PATCH 1/3] report: add max_power_in_plw to summary --- simba/costs.py | 31 ++++++++++++++++++++++--------- tests/test_simulate.py | 18 +++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/simba/costs.py b/simba/costs.py index 7a2e0cf..813214a 100644 --- a/simba/costs.py +++ b/simba/costs.py @@ -134,8 +134,10 @@ def get_unit(self, key): :return: Unit associated with the key :rtype: str """ - if "maximum_gc_power" == key: + if "power" in key: return "kW" + elif "station_type" == key: + return "[-]" elif "maximum Nr charging stations" == key: return "[-]" elif "total_km_per_year" == key: @@ -184,7 +186,7 @@ def get_gc_cost_variables(self): """ return [ # various kpis and attributes - "station_type", "maximum_gc_power", "maximum Nr charging stations", + "station_type", "maximum_gc_power", "max_power_in_plw", "maximum Nr charging stations", "total_km_per_year", "annual_kWh_from_grid", "annual_kWh_from_feed_in", # investment costs @@ -372,8 +374,11 @@ def set_electricity_costs(self): 'levies_fees_and_taxes_per_year', error_value) self.costs_per_gc[gcID]["c_el_feed_in_remuneration_annual"] = costs_electricity.get( 'feed_in_remuneration_per_year', error_value) - self.costs_per_gc[gcID]["c_el_annual"] = costs_electricity.get('total_costs_per_year', - error_value) + self.costs_per_gc[gcID]["c_el_annual"] = costs_electricity.get( + 'total_costs_per_year', error_value) + self.costs_per_gc[gcID]["max_power_in_plw"] = costs_electricity.get( + 'peak_power_in_windows', error_value) + return self def set_garage_costs(self): @@ -637,6 +642,9 @@ def cumulate(self): """ # Cumulate gcs variables for key in self.get_gc_cost_variables(): + # skip special attributes + if key in ["station_type", "maximum_gc_power", "max_power_in_plw"]: + continue # Vehicle costs cannot be cumulated since they might be double counted for vehicles # with multiple depots. Instead, the vehicle costs were previously calculated in # set_vehicle_costs_per_gc() @@ -688,9 +696,11 @@ def get_total_annual_km(self): 1) return self.DAYS_PER_YEAR / simulated_days * total_km - def to_csv_lists(self): + def to_csv_lists(self, transpose=False): """ Convert costs to a list of lists easily convertible to a CSV. + :param transpose: swap rows and columns + :type transpose: bool :return: List of lists of parameters, units and costs per gc :rtype: list """ @@ -718,7 +728,10 @@ def to_csv_lists(self): row.append(num) output.append(row) - transposed_output = [] - for column, _ in enumerate(output[0]): - transposed_output.append([row[column] for row in output]) - return transposed_output + if transpose: + transposed_output = [] + for column, _ in enumerate(output[0]): + transposed_output.append([row[column] for row in output]) + output = transposed_output + + return output diff --git a/tests/test_simulate.py b/tests/test_simulate.py index c308daa..7b3a7be 100644 --- a/tests/test_simulate.py +++ b/tests/test_simulate.py @@ -166,15 +166,19 @@ def test_mode_report(self, tmp_path): # read out vehicle costs, procurement price must match with (tmp_path / "report_1/summary_vehicles_costs.csv").open() as csvfile: reader = DictReader(csvfile) + # save procurement costs and annual energy for each Station + station_data = {s: [None, None] for s in reader.fieldnames if s.startswith("Station")} for row in reader: - if row["parameter"] == "unit": - continue - energy = float(row["annual_kWh_from_grid"]) - price = float(row["c_el_procurement_annual"]) - if energy == 0: - assert price == 0 + for i, param in enumerate(["c_el_procurement_annual", "annual_kWh_from_grid"]): + if row["parameter"] == param: + for k, v in station_data.items(): + v[i] = float(row[k]) + # check quotient: no energy must mean no cost, otherwise procurement price + for k, v in station_data.items(): + if v[1] == 0: + assert v[0] == 0, f"{k} has costs without energy" else: - assert pytest.approx(price / energy) == procurement_price + assert pytest.approx(v[0]/v[1]) == procurement_price, f"{k}: procurement price" def test_empty_report(self, tmp_path): # report with no rotations From 163264b742c15c05f0d63ca4091849096a065142 Mon Sep 17 00:00:00 2001 From: "stefan.schirmeister" Date: Wed, 11 Dec 2024 10:46:56 +0100 Subject: [PATCH 2/3] implement suggestions - remove double filter from costs.cumulate - remove transpose argument from costs.to_csv_lists - make test_mode_report more readable --- simba/costs.py | 13 ++----------- tests/test_simulate.py | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/simba/costs.py b/simba/costs.py index 813214a..964d089 100644 --- a/simba/costs.py +++ b/simba/costs.py @@ -648,7 +648,7 @@ def cumulate(self): # Vehicle costs cannot be cumulated since they might be double counted for vehicles # with multiple depots. Instead, the vehicle costs were previously calculated in # set_vehicle_costs_per_gc() - if key in ["c_vehicles", "c_vehicles_annual", "station_type"]: + if key in ["c_vehicles", "c_vehicles_annual"]: continue self.costs_per_gc[self.CUMULATED][key] = 0 for gc in self.costs_per_gc.keys() - [self.CUMULATED]: @@ -696,11 +696,9 @@ def get_total_annual_km(self): 1) return self.DAYS_PER_YEAR / simulated_days * total_km - def to_csv_lists(self, transpose=False): + def to_csv_lists(self): """ Convert costs to a list of lists easily convertible to a CSV. - :param transpose: swap rows and columns - :type transpose: bool :return: List of lists of parameters, units and costs per gc :rtype: list """ @@ -727,11 +725,4 @@ def to_csv_lists(self, transpose=False): except TypeError: row.append(num) output.append(row) - - if transpose: - transposed_output = [] - for column, _ in enumerate(output[0]): - transposed_output.append([row[column] for row in output]) - output = transposed_output - return output diff --git a/tests/test_simulate.py b/tests/test_simulate.py index 7b3a7be..25c546b 100644 --- a/tests/test_simulate.py +++ b/tests/test_simulate.py @@ -167,18 +167,23 @@ def test_mode_report(self, tmp_path): with (tmp_path / "report_1/summary_vehicles_costs.csv").open() as csvfile: reader = DictReader(csvfile) # save procurement costs and annual energy for each Station - station_data = {s: [None, None] for s in reader.fieldnames if s.startswith("Station")} + station_data = {s: {"energy_costs": None, "energy_amount": None} + for s in reader.fieldnames if s.startswith("Station")} for row in reader: - for i, param in enumerate(["c_el_procurement_annual", "annual_kWh_from_grid"]): - if row["parameter"] == param: - for k, v in station_data.items(): - v[i] = float(row[k]) + if row["parameter"] == "c_el_procurement_annual": + for name in station_data: + station_data[name]["energy_costs"] = float(row[name]) + if row["parameter"] == "annual_kWh_from_grid": + for name in station_data: + station_data[name]["energy_amount"] = float(row[name]) # check quotient: no energy must mean no cost, otherwise procurement price - for k, v in station_data.items(): - if v[1] == 0: - assert v[0] == 0, f"{k} has costs without energy" + for name in station_data: + energy = station_data[name]["energy_amount"] + cost = station_data[name]["energy_costs"] + if energy == 0: + assert cost == 0, f"{name} has costs without energy" else: - assert pytest.approx(v[0]/v[1]) == procurement_price, f"{k}: procurement price" + assert pytest.approx(cost/energy) == procurement_price, f"{name}: procurement price" def test_empty_report(self, tmp_path): # report with no rotations From bfe42ee029b56f34d7f78ba13b40cf01e36f001a Mon Sep 17 00:00:00 2001 From: "stefan.schirmeister" Date: Wed, 11 Dec 2024 10:51:21 +0100 Subject: [PATCH 3/3] fix line length --- tests/test_simulate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_simulate.py b/tests/test_simulate.py index 9c31efd..8ca283c 100644 --- a/tests/test_simulate.py +++ b/tests/test_simulate.py @@ -217,7 +217,7 @@ def test_mode_report(self, tmp_path): if energy == 0: assert cost == 0, f"{name} has costs without energy" else: - assert pytest.approx(cost/energy) == procurement_price, f"{name}: procurement price" + assert pytest.approx(cost/energy) == procurement_price, f"{name}: procurement" def test_empty_report(self, tmp_path): # report with no rotations