Skip to content

Commit

Permalink
Compatibility patch for SpiceEV PR #217
Browse files Browse the repository at this point in the history
refactor costs rl-institut/spice_ev#217
- rename cost_calculation_strategy_X to cost_calculation_method_X
- use cost calc types instead of strategy names
- create window timeseries for PLW costs
- test: remove peak_shaving cost calc test (also fixed_wo_plw, so no different to greedy/balanced), fixed_w_plw generates same el. costs
  • Loading branch information
stefan.schirmeister committed Sep 25, 2024
1 parent 96e0779 commit ac4e9f5
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 50 deletions.
6 changes: 3 additions & 3 deletions data/examples/simba.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ strategy_opps = greedy
strategy_options_deps = {"CONCURRENCY": 1}
strategy_options_opps = {}

# Cost calculation strategy
cost_calculation_strategy_deps = balanced
cost_calculation_strategy_opps = greedy
# Cost calculation to use. Remove to use default for strategy.
cost_calculation_method_deps = fixed_wo_plw
cost_calculation_method_opps = fixed_wo_plw

##### Physical setup of environment #####
### Parametrization of the physical setup ###
Expand Down
16 changes: 8 additions & 8 deletions docs/source/simulation_parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ The example (data/simba.cfg) contains parameter descriptions which are explained
- greedy
- SpiceEV Strategies (greedy, balanced, peak_shaving, peak_load_windows, balanced_market)
- Charging strategy used in opportunity stations.
* - cost_calculation_strategy_deps
- strategy_deps value
- SpiceEV Strategies (greedy, balanced, peak_shaving, peak_load_windows, balanced_market)
- Strategy for cost calculation at depots.
* - cost_calculation_strategy_opps
- strategy_opps value
- SpiceEV Strategies (greedy, balanced, peak_shaving, peak_load_windows, balanced_market)
- Strategy for cost calculation at opportunity stations.
* - cost_calculation_method_deps
- fixed_wo_plw
- SpiceEV cost calculation type
- Method for cost calculation at depots.
* - cost_calculation_method_opps
- fixed_wo_plw
- SpiceEV cost calculation type (fixed_wo_plw, fixed_w_plw, balanced_market, flex_window)
- Method for cost calculation at opportunity stations.
* - preferred_charging_type
- depb
- depb, oppb
Expand Down
36 changes: 20 additions & 16 deletions simba/costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
import traceback
import warnings

import spice_ev.scenario
from spice_ev.costs import calculate_costs as calc_costs_spice_ev

import simba.schedule

import spice_ev.costs
import spice_ev.scenario
import spice_ev.util


def calculate_costs(c_params, scenario, schedule, args):
""" Calculates annual costs of all necessary vehicles and infrastructure.
Expand Down Expand Up @@ -320,21 +321,23 @@ def set_electricity_costs(self):
if pv.parent == gcID])
timeseries = vars(self.scenario).get(f"{gcID}_timeseries")

# Get the calculation strategy / method from args.
# If no value is set, use the same strategy as the charging strategy
default_cost_strategy = vars(self.args)["strategy_" + station.get("type")]

cost_strategy_name = "cost_calculation_strategy_" + station.get("type")
cost_calculation_strategy = (vars(self.args).get(cost_strategy_name)
or default_cost_strategy)
# Get the calculation method from args.
cost_calculation_name = "cost_calculation_method_" + station.get("type")
cost_calculation_method = vars(self.args).get(cost_calculation_name)
if cost_calculation_method is None:
# not given in config: use the same method as the charging strategy
default_strategy = vars(self.args)["strategy_" + station.get("type")]
cost_calculation_method = spice_ev.costs.DEFAULT_COST_CALCULATION[default_strategy]

# calculate costs for electricity
try:
if cost_calculation_strategy == "peak_load_window":
if timeseries.get("window signal [-]") is None:
raise Exception("No peak load window signal provided for cost calculation")
costs_electricity = calc_costs_spice_ev(
strategy=cost_calculation_strategy,
is_peak_load_window = cost_calculation_method.endswith("w_plw")
if is_peak_load_window and timeseries.get("window signal [-]") is None:
logging.info("Generating peak load window signal for cost calculation")
timeseries["window signal [-]"] = spice_ev.util.get_time_windows_from_json(
self.args.time_windows, gc.grid_operator, gc.voltage_level, self.scenario)
costs_electricity = spice_ev.costs.calculate_costs(
cc_type=cost_calculation_method,
voltage_level=gc.voltage_level,
interval=self.scenario.interval,
timestamps_list=timeseries.get("time"),
Expand All @@ -344,9 +347,10 @@ def set_electricity_costs(self):
power_generation_feed_in_list=timeseries.get("generation feed-in [kW]"),
power_v2g_feed_in_list=timeseries.get("V2G feed-in [kW]"),
power_battery_feed_in_list=timeseries.get("battery feed-in [kW]"),
charging_signal_list=timeseries.get("window signal [-]"),
window_signal_list=timeseries.get("window signal [-]"),
price_sheet_path=self.args.cost_parameters_path,
grid_operator=gc.grid_operator,
fee_type=None, # "RLM" or "SLP" or None (based on energy consumption)
power_pv_nominal=pv,
)
except Exception:
Expand Down
11 changes: 6 additions & 5 deletions simba/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import subprocess
from datetime import datetime, timedelta

from spice_ev.costs import COST_CALCULATION
from spice_ev.strategy import STRATEGIES
from spice_ev.util import set_options_from_config

Expand Down Expand Up @@ -531,11 +532,11 @@ def get_parser():
parser.add_argument('--strategy-opps', default='greedy', choices=STRATEGIES,
help='strategy to use at station')

# #### Cost calculation strategy #####
parser.add_argument('--cost-calculation-strategy-deps', choices=STRATEGIES,
help='Strategy for cost calculation to use in depot')
parser.add_argument('--cost-calculation-strategy-opps', choices=STRATEGIES,
help='Strategy for cost calculation to use at station')
# #### Cost calculation method #####
parser.add_argument('--cost-calculation-method-deps', choices=COST_CALCULATION,
help='Cost calculation to use in depot')
parser.add_argument('--cost-calculation-method-opps', choices=COST_CALCULATION,
help='Cost calculation to use at station')

parser.add_argument('--strategy-options-deps', default={},
type=lambda s: s if type(s) is dict else json.loads(s),
Expand Down
31 changes: 13 additions & 18 deletions tests/test_cost_calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ def test_cost_calculation(self):
assert args.strategy_deps == "balanced"
assert args.strategy_opps == "greedy"

args.cost_calculation_strategy_deps = None
args.cost_calculation_strategy_opps = None
args.cost_calculation_method_deps = None
args.cost_calculation_method_opps = None

costs_vanilla = calculate_costs(cost_params, scenario, schedule, args)

assert args.strategy_deps == "balanced"
assert args.strategy_opps == "greedy"

args.cost_calculation_strategy_deps = "balanced"
args.cost_calculation_strategy_opps = "greedy"
args.cost_calculation_method_deps = "fixed_wo_plw"
args.cost_calculation_method_opps = "fixed_wo_plw"
costs_with_same_strat = calculate_costs(cost_params, scenario, schedule, args)

# assert all costs are the same
Expand All @@ -31,8 +31,9 @@ def test_cost_calculation(self):
assert (costs_vanilla.costs_per_gc[station][key] ==
costs_with_same_strat.costs_per_gc[station][key]), station

args.cost_calculation_strategy_opps = "balanced_market"
args.cost_calculation_strategy_deps = "balanced_market"
# test with different method (balanced_market costs for balanced strategy)
args.cost_calculation_method_deps = "balanced_market"
args.cost_calculation_method_opps = "balanced_market"
costs_with_other_strat = calculate_costs(cost_params, scenario, schedule, args)
print(costs_vanilla.costs_per_gc["cumulated"]["c_total_annual"])
print(costs_with_other_strat.costs_per_gc["cumulated"]["c_total_annual"])
Expand All @@ -43,21 +44,15 @@ def test_cost_calculation(self):
assert (costs_vanilla.costs_per_gc[station][key] !=
costs_with_other_strat.costs_per_gc[station][key]), key

args.cost_calculation_strategy_opps = "peak_load_window"
args.cost_calculation_strategy_deps = "peak_load_window"
# PLW: will create window time series before cost calculation
args.cost_calculation_method_deps = "fixed_w_plw"
args.cost_calculation_method_opps = "fixed_w_plw"
costs_with_other_strat = calculate_costs(cost_params, scenario, schedule, args)
"""
station = "cumulated"
for key in costs_vanilla.costs_per_gc[station]:
if "el_energy" not in key:
continue
assert (costs_vanilla.costs_per_gc[station][key] !=
costs_with_other_strat.costs_per_gc[station][key]), key

args.cost_calculation_strategy_opps = "peak_shaving"
args.cost_calculation_strategy_deps = "peak_shaving"
costs_with_other_strat = calculate_costs(cost_params, scenario, schedule, args)
# assert all costs are the same
for station in costs_vanilla.costs_per_gc:
for key in costs_vanilla.costs_per_gc[station]:
assert (costs_vanilla.costs_per_gc[station][key] ==
costs_with_other_strat.costs_per_gc[station][key]), station
costs_with_other_strat.costs_per_gc[station][key]), key
"""

0 comments on commit ac4e9f5

Please sign in to comment.