Skip to content

Commit

Permalink
Merge pull request #177 from rl-institut/update/1.0.0->1.0.1
Browse files Browse the repository at this point in the history
new version 1.0.1
  • Loading branch information
jakobgemassmer authored Aug 7, 2023
2 parents ba0d765 + 7e6fbe9 commit c841930
Show file tree
Hide file tree
Showing 14 changed files with 47 additions and 23 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ Template:
- [(#)]()
```

## [1.0.1] - Minor Fixes - 2023-08-04

### Changed
- fixed bug if scenario has no timesteps
- fixed bug regarding V2G discharge power computation in balanced_market
- give summary of adjusted event times instead of warning for every affected event
- flake8 compatibility

## [1.0.0] - Initial Release SpiceEV - 2023-05-24

### Added
- first release! 🎉

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="spice_ev",
version="1.0.0",
version="1.0.1",
description="Simulation Program for Individual Charging Events of Electric Vehicles.",
url="https://github.com/rl-institut/spice_ev",
author="Reiner Lemoine Institut",
Expand Down
2 changes: 1 addition & 1 deletion simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def simulate(args):
:raises NotImplementedError: if unknown strategy is given
"""

if type(args) == argparse.Namespace:
if type(args) is argparse.Namespace:
# cast arguments to dictionary for default handling
args = vars(args)

Expand Down
5 changes: 4 additions & 1 deletion spice_ev/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,23 @@ def get_event_steps(self, start_time, n_intervals, interval):
local_generation_list.get_events(name, LocalEnergyGeneration,
has_perfect_foresight=True))

moved = 0
ignored = 0

for event in all_events:
# get ceil of time index (start of next interval)
index = -((start_time - event.signal_time) // interval)

if index < 0:
warn('Event is before start of scenario, placing at first time step: ' + str(event))
moved += 1
steps[0].append(event)
elif index >= n_intervals:
ignored += 1
else:
steps[index].append(event)

if moved:
warn('{} events before start of scenario, placed at first time step'.format(moved))
if ignored:
warn('{} events ignored after end of scenario'.format(ignored))

Expand Down
2 changes: 1 addition & 1 deletion spice_ev/generate/generate_from_simbev.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def generate_from_simbev(args):
pathlist.sort()

def datetime_from_timestep(timestep):
assert type(timestep) == int
assert type(timestep) is int
return start + (interval * timestep)

# take start time from SimBEV metadata
Expand Down
8 changes: 4 additions & 4 deletions spice_ev/generate/generate_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,13 @@ def get_v2g_energy(vehicle):
if idx != 0:
flex["vehicles"].append([])
for event in timestep:
if type(event) == events.FixedLoad and event.grid_connector_id == gcID:
if type(event) is events.FixedLoad and event.grid_connector_id == gcID:
# fixed load event at this GC
gc.current_loads[event.name] = event.value
elif type(event) == events.LocalEnergyGeneration and event.grid_connector_id == gcID:
elif type(event) is events.LocalEnergyGeneration and event.grid_connector_id == gcID:
# local generation event behind this GC
gc.current_loads[event.name] = -event.value
elif type(event) == events.GridOperatorSignal and event.grid_connector_id == gcID:
elif type(event) is events.GridOperatorSignal and event.grid_connector_id == gcID:
# grid op event at this GC
if gc.max_power:
if event.max_power is None:
Expand All @@ -317,7 +317,7 @@ def get_v2g_energy(vehicle):
else:
# connector max power not set
gc.cur_max_power = event.max_power
elif type(event) == events.VehicleEvent:
elif type(event) is events.VehicleEvent:
# vehicle event: check if this GC
vid = event.vehicle_id
vehicle = vehicles[vid]
Expand Down
1 change: 1 addition & 0 deletions spice_ev/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def run(self, strategy_name, options):

begin = datetime.datetime.now()
error = None
step_i = -1
for step_i in range(self.n_intervals):

if options.get("timing", False):
Expand Down
7 changes: 4 additions & 3 deletions spice_ev/strategies/balanced_market.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ def step(self):
# not this timestep
break
event_idx += 1
if type(event) == events.GridOperatorSignal:
if type(event) is events.GridOperatorSignal:
# update GC info
if event.max_power is not None:
cur_max_power = event.max_power
if event.cost is not None:
cur_cost = event.cost
elif type(event) == events.LocalEnergyGeneration:
elif type(event) is events.LocalEnergyGeneration:
cur_local_generation[event.name] = event.value
# vehicle events ignored (use vehicle info such as estimated_time_of_departure)

Expand Down Expand Up @@ -236,7 +236,8 @@ def step(self):

gc_cur_discharge_power_limit = (timesteps[v2g_ts_idx]["power"]
- 2*timesteps[v2g_ts_idx]["max_power"])
p = min(max(gc_cur_discharge_power_limit, p), 0)
cs_cur_discharge_power_limit = -(cs.max_power + cs.current_power)
p = min(max(gc_cur_discharge_power_limit, cs_cur_discharge_power_limit, p), 0)
power[v2g_ts_idx] = p

if v2g_ts_idx == 0:
Expand Down
2 changes: 1 addition & 1 deletion spice_ev/strategies/distributed.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def step(self):
if event.start_time > event.start_time + datetime.timedelta(minutes=self.C_HORIZON):
# not this timestep
break
if type(event) == events.VehicleEvent:
if type(event) is events.VehicleEvent:
if event.vehicle_id == vehicle_id:
# not this vehicle event
continue
Expand Down
4 changes: 2 additions & 2 deletions spice_ev/strategies/flex_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ def step(self):
# not this timestep
break
event_idx += 1
if type(event) == events.GridOperatorSignal:
if type(event) is events.GridOperatorSignal:
# update GC info
cur_max_power = event.max_power or cur_max_power
if event.window is not None:
cur_window = event.window
elif type(event) == events.LocalEnergyGeneration:
elif type(event) is events.LocalEnergyGeneration:
cur_local_generation[event.name] = event.value
# vehicle events ignored (use vehicle info such as estimated_time_of_departure)

Expand Down
6 changes: 3 additions & 3 deletions spice_ev/strategies/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,13 @@ def collect_future_gc_info(self, dt=timedelta(days=1)):
break
# event handled: don't handle again, so increase index
event_idx += 1
if type(event) == events.GridOperatorSignal:
if type(event) is events.GridOperatorSignal:
# update GC info
gc_info[-1]["target"] = \
event.target if event.target is not None else gc_info[-1]["target"]
gc_info[-1]["charge"] = \
event.window if event.window is not None else gc_info[-1]["charge"]
elif type(event) == events.LocalEnergyGeneration:
elif type(event) is events.LocalEnergyGeneration:
gc_info[-1]["current_loads"][event.name] = -event.value
# ignore vehicle events, use vehicle data directly
# ignore local generation for now as well
Expand Down Expand Up @@ -667,7 +667,7 @@ def charge_individually(self):
break
# event handled: don't handle again, so increase index
event_idx += 1
if type(event) == events.VehicleEvent and event.vehicle_id == vid:
if type(event) is events.VehicleEvent and event.vehicle_id == vid:
if event.event_type == 'schedule':
cur_schedule = event.update["schedule"]
elif event.event_type == 'departure':
Expand Down
8 changes: 4 additions & 4 deletions spice_ev/strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,17 @@ def step(self, event_list=[]):
# remove event from list
ev = self.world_state.future_events.pop(0)

if type(ev) == events.FixedLoad:
if type(ev) is events.FixedLoad:
connector = self.world_state.grid_connectors[ev.grid_connector_id]
assert ev.name not in self.world_state.charging_stations, (
"Fixed load must not be from charging station")
connector.current_loads[ev.name] = ev.value # not reset after last event
elif type(ev) == events.LocalEnergyGeneration:
elif type(ev) is events.LocalEnergyGeneration:
assert ev.name not in self.world_state.charging_stations, (
"Local energy generation must not be from charging station")
connector = self.world_state.grid_connectors[ev.grid_connector_id]
connector.current_loads[ev.name] = -ev.value
elif type(ev) == events.GridOperatorSignal:
elif type(ev) is events.GridOperatorSignal:
connector = self.world_state.grid_connectors[ev.grid_connector_id]
if ev.cost is not None:
# set power cost
Expand All @@ -114,7 +114,7 @@ def step(self, event_list=[]):
else:
# connector max power not set
connector.cur_max_power = ev.max_power
elif type(ev) == events.VehicleEvent:
elif type(ev) is events.VehicleEvent:
vehicle = self.world_state.vehicles[ev.vehicle_id]
# update vehicle attributes
for k, v in ev.update.items():
Expand Down
2 changes: 1 addition & 1 deletion spice_ev/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def set_options_from_config(args, check=None, verbose=True):
except IndexError:
raise Exception(f"Unknown option {k}")
# check each item in list individually
v_list = [v] if type(v) != list else v
v_list = [v] if type(v) is not list else v
for v_item in v_list:
# check item. Returns None on success
# may raise ArgumentError if not successful
Expand Down
13 changes: 13 additions & 0 deletions tests/test_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,19 @@ def test_empty(self):
# GC has neither cost nor schedule
strat.step()

def test_zero_intervals(self):
test_json = {
"scenario": {
"start_time": "1970-01-01T00:00:00+00:00",
"interval": 15,
"n_intervals": 0
}
}
s = scenario.Scenario(test_json)
s.run('greedy', {})
assert s.n_intervals == 0
assert s.step_i == 0

def test_file(self):
# open from file
input = TEST_REPO_PATH / 'test_data/input_test_strategies/scenario_A.json'
Expand Down

0 comments on commit c841930

Please sign in to comment.