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.
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/PKG-INFO +2 -2
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/__init__.py +68 -6
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/smart_charging.py +6 -3
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/pyproject.toml +2 -2
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/LICENSE.md +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/README.md +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/__init__.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/defaults/default_settings.json +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/__init__.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/depot.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/api/private/util.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/configuration.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/depot.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/evaluation.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/filters.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/input_epex_power_price.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/__init__.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/doc/__init__.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/doc/direct_details.pdf +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/evaluation.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/__init__.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/crossover.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/fitness_util.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/init.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/mutation.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/optimize_c_urfd.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/packing.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/settings.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/template_creation.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/util.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/plots.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/processes.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/rating.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/resources.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/settings_config.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/simple_vehicle.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/simulation.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/smart_charging.py +0 -0
- {eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/standalone.py +0 -0
- {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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{eflips_depot-4.0.1 → eflips_depot-4.1.0}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|