Skip to content

Commit

Permalink
Merge branch 'dev' into feature/extended_prices
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan.schirmeister committed Oct 30, 2024
2 parents 392e435 + 40773fe commit b2899ec
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
14 changes: 8 additions & 6 deletions simba/costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class Costs:
GARAGE = "garage"
NOT_ELECTRIFIED = "Non_electrified_station"

DAYS_PER_YEAR = 365.2422
DAYS_PER_YEAR = 365

def __init__(self, schedule: simba.schedule.Schedule, scenario: spice_ev.scenario.Scenario,
args, c_params: dict):
Expand Down Expand Up @@ -117,6 +117,7 @@ def info(self):
:rtype: str
"""
cumulated = self.costs_per_gc[self.CUMULATED]

return ("\nTotal costs:\n"
f"Investment cost: {cumulated['c_invest']} €. \n"
f"Annual investment costs: {cumulated['c_invest_annual']} €/a. \n"
Expand Down Expand Up @@ -492,11 +493,12 @@ def set_various_kpis(self):
"""
all_stations = self.schedule.scenario["components"]["charging_stations"]
stepsPerHour = self.scenario.stepsPerHour
simulated_days = max(
round(self.scenario.n_intervals / self.scenario.stepsPerHour / 24, 0), 1)
# Factor for scaling to a year.
# Expects Schedules to describe whole days, with some overlap allowed
annual_factor = self.DAYS_PER_YEAR / simulated_days
# factor for scaling to a year
scenario_duration_s = self.scenario.n_intervals * self.scenario.interval.total_seconds()
if scenario_duration_s > 0:
annual_factor = (self.DAYS_PER_YEAR * 24 * 60 * 60) / scenario_duration_s
else:
annual_factor = 0
# get dict with costs for specific grid operator
for gcID, gc in self.gcs.items():
station = self.schedule.stations[gcID]
Expand Down
3 changes: 2 additions & 1 deletion simba/simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def _station_optimization(schedule, scenario, args, i, single_step: bool):

@staticmethod
def station_optimization(schedule, scenario, args, i):
return Mode._station_optimization(schedule, scenario, args, i, sinlge_step=False)
return Mode._station_optimization(schedule, scenario, args, i, single_step=False)

@staticmethod
def station_optimization_single_step(schedule, scenario, args, i):
Expand Down Expand Up @@ -263,6 +263,7 @@ def split_negative_depb(schedule, scenario, args, _i):
@staticmethod
def report(schedule, scenario, args, i):
if args.output_path is None:
logging.warning("No output path given, skipping report")
return schedule, scenario

# create report based on all previous modes
Expand Down
21 changes: 21 additions & 0 deletions tests/test_simulate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from argparse import Namespace
from csv import DictReader
import json
import logging
from pathlib import Path
import pytest
Expand Down Expand Up @@ -155,6 +157,25 @@ def test_mode_report(self, tmp_path):
warnings.simplefilter("ignore")
simulate(args)

# get power procurement price from price sheet
with open(args.cost_parameters_path) as file:
cost_params = json.load(file)
procurement_price = cost_params["default_grid_operator"]["power_procurement"]["charge"]
# given in ct/kWh, convert to €/kWh with sign change (direction of grid power)
procurement_price = -procurement_price / 100
# read out vehicle costs, procurement price must match
with (tmp_path / "report_1/summary_vehicles_costs.csv").open() as csvfile:
reader = DictReader(csvfile)
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
else:
assert pytest.approx(price / energy) == procurement_price

def test_empty_report(self, tmp_path):
# report with no rotations
args = self.get_args()
Expand Down

0 comments on commit b2899ec

Please sign in to comment.