eflips-depot 4.0.1__tar.gz → 4.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/PKG-INFO +2 -2
  2. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/__init__.py +68 -6
  3. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/smart_charging.py +6 -3
  4. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/pyproject.toml +2 -2
  5. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/LICENSE.md +0 -0
  6. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/README.md +0 -0
  7. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/__init__.py +0 -0
  8. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/defaults/default_settings.json +0 -0
  9. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/__init__.py +0 -0
  10. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/depot.py +0 -0
  11. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/util.py +0 -0
  12. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/configuration.py +0 -0
  13. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/depot.py +0 -0
  14. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/evaluation.py +0 -0
  15. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/filters.py +0 -0
  16. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/input_epex_power_price.py +0 -0
  17. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/__init__.py +0 -0
  18. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/doc/__init__.py +0 -0
  19. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/doc/direct_details.pdf +0 -0
  20. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/evaluation.py +0 -0
  21. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/__init__.py +0 -0
  22. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/crossover.py +0 -0
  23. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py +0 -0
  24. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/fitness_util.py +0 -0
  25. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/init.py +0 -0
  26. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/mutation.py +0 -0
  27. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/optimize_c_urfd.py +0 -0
  28. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/packing.py +0 -0
  29. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/settings.py +0 -0
  30. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/template_creation.py +0 -0
  31. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/util.py +0 -0
  32. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/plots.py +0 -0
  33. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/processes.py +0 -0
  34. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/rating.py +0 -0
  35. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/resources.py +0 -0
  36. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/settings_config.py +0 -0
  37. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/simple_vehicle.py +0 -0
  38. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/simulation.py +0 -0
  39. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/smart_charging.py +0 -0
  40. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/standalone.py +0 -0
  41. {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eflips-depot
3
- Version: 4.0.1
3
+ Version: 4.1.0
4
4
  Summary: Depot Simulation for eFLIPS
5
5
  Home-page: https://github.com/mpm-tu-berlin/eflips-depot
6
6
  License: AGPL-3.0-or-later
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Requires-Dist: eflips (>=0.1.3,<0.2.0)
16
- Requires-Dist: eflips-model (>=4.0.0a2,<5.0.0)
16
+ Requires-Dist: eflips-model (>=4.0.0,<5.0.0)
17
17
  Requires-Dist: pandas (>=2.1.4,<3.0.0)
18
18
  Requires-Dist: scipy (>=1.13.1,<2.0.0)
19
19
  Requires-Dist: simpy (>=4.0.1,<5.0.0)
@@ -27,12 +27,12 @@ The following steps are recommended for using the API:
27
27
  import copy
28
28
  import datetime
29
29
  import itertools
30
+ import logging
30
31
  import os
31
32
  import warnings
33
+ from collections import OrderedDict
32
34
  from datetime import timedelta
33
35
  from enum import Enum
34
- from math import ceil
35
- from collections import OrderedDict
36
36
  from typing import Any, Dict, Optional, Union, List
37
37
 
38
38
  import numpy as np
@@ -47,6 +47,7 @@ from eflips.model import (
47
47
  Trip,
48
48
  Vehicle,
49
49
  )
50
+ from math import ceil
50
51
  from sqlalchemy.orm import Session
51
52
  from sqlalchemy.sql import select
52
53
 
@@ -132,6 +133,8 @@ def simple_consumption_simulation(
132
133
 
133
134
  :return: Nothing. The results are added to the database.
134
135
  """
136
+ logger = logging.getLogger(__name__)
137
+
135
138
  with create_session(scenario, database_url) as (session, scenario):
136
139
  rotations = (
137
140
  session.query(Rotation)
@@ -218,6 +221,7 @@ def simple_consumption_simulation(
218
221
  session.flush()
219
222
 
220
223
  for rotation in rotations:
224
+ rotation: Rotation
221
225
  with session.no_autoflush:
222
226
  vehicle_type = rotation.vehicle_type
223
227
  vehicle = rotation.vehicle
@@ -286,6 +290,59 @@ def simple_consumption_simulation(
286
290
  )
287
291
  session.add(current_event)
288
292
 
293
+ # If the vehicle is
294
+ # - Capable of opportunity charging
295
+ # - On a Rotation which allows opportunity charging
296
+ # - Currently at a station which allows opportunity charging
297
+ # - which is not the last trip of the rotation
298
+ # We add a charging event
299
+
300
+ if (
301
+ rotation.vehicle_type.opportunity_charging_capable
302
+ and rotation.allow_opportunity_charging
303
+ and trip.route.arrival_station.is_electrified
304
+ and trip != rotation.trips[-1]
305
+ ):
306
+ logger.debug(
307
+ f"Adding opportunity charging event for trip {trip.id}"
308
+ )
309
+ # Identify the break time between trips
310
+ trip_index = rotation.trips.index(trip)
311
+ next_trip = rotation.trips[trip_index + 1]
312
+ break_time = next_trip.departure_time - trip.arrival_time
313
+
314
+ # How much energy can be charged in this time?
315
+ energy_charged = (
316
+ max([v[1] for v in vehicle_type.charging_curve])
317
+ * break_time.total_seconds()
318
+ / 3600
319
+ )
320
+
321
+ if energy_charged > 0:
322
+ # Calculate the end SoC
323
+ post_charge_soc = min(
324
+ current_soc
325
+ + energy_charged / vehicle_type.battery_capacity,
326
+ 1,
327
+ )
328
+
329
+ # Create the charging event
330
+ current_event = Event(
331
+ scenario_id=scenario.id,
332
+ vehicle_type_id=rotation.vehicle_type_id,
333
+ vehicle=vehicle,
334
+ station_id=trip.route.arrival_station_id,
335
+ time_start=trip.arrival_time,
336
+ time_end=next_trip.departure_time,
337
+ soc_start=current_soc,
338
+ soc_end=post_charge_soc,
339
+ event_type=EventType.CHARGING_OPPORTUNITY,
340
+ description=f"Opportunity charging event for trip {trip.id}.",
341
+ timeseries=None,
342
+ )
343
+ current_soc = post_charge_soc
344
+ session.add(current_event)
345
+
289
346
 
290
347
  def generate_depot_layout(
291
348
  scenario: Union[Scenario, int, Any],
@@ -915,6 +972,7 @@ def _get_finished_schedules_per_vehicle(
915
972
  ):
916
973
  """
917
974
  This function completes the following tasks:
975
+
918
976
  1. It gets the finished non-copy schedules of the current vehicle,
919
977
  which will be used in :func:`_update_vehicle_in_rotation()`.
920
978
 
@@ -986,7 +1044,9 @@ def _generate_vehicle_events(
986
1044
  latest_time: datetime.datetime,
987
1045
  ) -> None:
988
1046
  """
989
- This function generates and ordered dictionary storing the data related to an event. It returns a dictionary. The keys are the start times of the
1047
+ This function generates and ordered dictionary storing the data related to an event.
1048
+
1049
+ It returns a dictionary. The keys are the start times of the
990
1050
  events. The values are also dictionaries containing:
991
1051
  - type: The type of the event.
992
1052
  - end: The end time of the event.
@@ -998,7 +1058,6 @@ def _generate_vehicle_events(
998
1058
 
999
1059
  For waiting events, the slot is not stored for now.
1000
1060
 
1001
-
1002
1061
  :param current_vehicle: a :class:`eflips.depot.simple_vehicle.SimpleVehicle` object.
1003
1062
 
1004
1063
  :param virtual_waiting_area_id: the id of the virtual waiting area. Vehicles waiting for the first process will park here.
@@ -1222,7 +1281,8 @@ def _add_events_into_database(
1222
1281
  db_vehicle, dict_of_events, session, scenario, simulation_start_time
1223
1282
  ) -> None:
1224
1283
  """
1225
- This function generates :class:`eflips.model.Event` objects from the dictionary of events and adds them into the
1284
+ This function generates :class:`eflips.model.Event` objects from the dictionary of events and adds them into the.
1285
+
1226
1286
  database.
1227
1287
 
1228
1288
  :param db_vehicle: vehicle object in the database
@@ -1344,6 +1404,7 @@ def _add_events_into_database(
1344
1404
  def _update_vehicle_in_rotation(session, scenario, list_of_assigned_schedules) -> None:
1345
1405
  """
1346
1406
  This function updates the vehicle id assigned to the rotations and deletes the events that are not depot events.
1407
+
1347
1408
  :param session: a :class:`sqlalchemy.orm.Session` object for database connection.
1348
1409
  :param scenario: the current simulated scenario
1349
1410
  :param list_of_assigned_schedules: a list of tuples containing the rotation id and the vehicle id.
@@ -1381,7 +1442,8 @@ def _update_vehicle_in_rotation(session, scenario, list_of_assigned_schedules) -
1381
1442
 
1382
1443
  def _update_waiting_events(session, scenario, waiting_area_id) -> None:
1383
1444
  """
1384
- This function evaluates the capacity of waiting area and assigns the waiting events to corresponding slots in the
1445
+ This function evaluates the capacity of waiting area and assigns the waiting events to corresponding slots in the.
1446
+
1385
1447
  waiting area.
1386
1448
 
1387
1449
  :param session: a :class:`sqlalchemy.orm.Session` object for database connection.
@@ -253,13 +253,16 @@ def optimize_charging_events_even(charging_events: List[Event]) -> None:
253
253
  socs[socs < event.soc_start] = event.soc_start
254
254
  socs[socs > event.soc_end] = event.soc_end
255
255
 
256
- # Add a timeseries to the event
256
+ # Add a timeseries to the event, removing the first and last index, since they will be the same as the start and
257
+ # end SoC
257
258
  event.timeseries = {
258
259
  "time": [
259
260
  datetime.fromtimestamp(t).astimezone().isoformat()
260
261
  for t in total_time[start_index:end_index]
261
- ],
262
- "soc": socs.tolist(),
262
+ ][
263
+ 1:-1
264
+ ], # Remove the first and last index
265
+ "soc": socs.tolist()[1:-1],
263
266
  }
264
267
  if event.timeseries["time"][0] < event.time_start.isoformat():
265
268
  event.timeseries["time"][0] = event.time_start.isoformat()
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "eflips-depot"
3
- version = "4.0.1"
3
+ version = "4.1.0"
4
4
  description = "Depot Simulation for eFLIPS"
5
5
  authors = ["Enrico Lauth <enrico.lauth@tu-berlin.de>",
6
6
  "Ludger Heide <ludger.heide@tu-berlin.de",
@@ -14,7 +14,7 @@ packages = [{ include = "eflips/depot" }]
14
14
  [tool.poetry.dependencies]
15
15
  python = "^3.10"
16
16
  simpy = "^4.0.1"
17
- eflips-model = "^4.0.0a2"
17
+ eflips-model = "^4.0.0"
18
18
  # Legacy dependencies, which are still needed until we refactor the code
19
19
  eflips = "^0.1.3"
20
20
  xlsxwriter = "^3.1.9"
File without changes
File without changes