depot.api¶
This package contains the public API for eFLIPS-Depot.
It is to be used in conjunction with the eflips.model package, where the Scenario is defined.
Notes on the usage of the API¶
The following steps are recommended for using the API:
Check if there are already “driving events” in the database. They come from a “consumption simulation” and are associated with a vehicle. If there are no driving events, you may use the
simple_consumption_simulation()(withinitialize_vehicles=True) to create them. This function will also initialize the vehicles in the database with the correct vehicle type and assign them to rotations.Check if there is already a depot layout in the database. If there is not, you may use the
generate_depot_layout()function to create a simple depot layout and plan.- Either use the
simulate_scenario()function to run the whole simulation in one go, or use the following steps: Use the
init_simulation()function to create a simulation host, which is a “black box” object containing all input data for the simulation.Use the
run_simulation()function to run the simulation and obtain the results.Use the
add_evaluation_to_database()function to add the results to the database.
- Either use the
- For the results to be valid, the consumption simulation should now be run again.
If you are using an external consumption model, run it again making sure it does not create new vehicles.
Run the
simple_consumption_simulation()function again, this time withinitialize_vehicles=False.
Optionally (enabled by default in
simulate_scenario()), callshrink_to_peak_usage()to right-size the auto-generated depot Areas to their peak observed concurrency. Note: electrified terminus Stations cannot be shrunk at this point because they have no charging events yet — those are only created by the consumption simulation in step 4. To also shrink terminus Stations, callshrink_to_peak_usage()manually after the consumption simulation in step 4b.
Submodules¶
Classes¶
Enum class for different smart charging strategies. |
Functions¶
|
Generate consumption information for the scenario. |
|
Run a consumption simulation and optionally initialize vehicles in the database. |
|
Generates one or more depots for the scenario. |
|
Takes a scenario where depot simulation has been run and applies smart charging to the depot. |
|
Shrink Areas and electrified terminus Stations to their peak observed usage. |
|
This method simulates a scenario and adds the results to the database. |
|
This methods checks the input data for consistency, initializes a simulation host object and returns it. |
|
Run simulation and return simulation results. |
|
This method adds a simulation result to the database. |
|
Generates an optimal depot layout with the smallest possible size for each depot in the scenario. |
|
This method calculates the duration of a given scenario in days. |
|
This method calculates an optimal depot layout for auto-generated depots and modifies the instance of. |
|
|
|
For each VehicleType ID in vehicle_type_ids, creates a DIESEL copy inside scenario. |
Package Contents¶
- class depot.api.SmartChargingStrategy(*args, **kwds)¶
Bases:
enum.EnumEnum class for different smart charging strategies.
- NONE = 0¶
Do not use smart charging.
Buses are charged with the maximum power available, from the time they arrive at the depot until they are full (or leave the depot).
- EVEN = 1¶
Use smart charging with an even distribution of charging power over the time the bus is at the depot.
This aims to minimize the peak power demand.
- MIN_PRICE = 2¶
Use smart charging in order to minimize the cost of charging.
The price profile can be specified using the PRICE_PROFILE environment variable. If this is not set, the price is loaded using an API.
- depot.api.generate_consumption_result(scenario)¶
Generate consumption information for the scenario.
This function retrieves the consumption LUT and vehicle classes from the database and returns a dictionary containing the consumption information for each vehicle type in the scenario. If a trip has no corresponding consumption LUT, it won’t be included in the results.
- Parameters:
scenario – A
eflips.model.Scenarioobject containing the input data for the simulation.- Returns:
A dictionary containing the consumption information for each vehicle type in the scenario.
- depot.api.simple_consumption_simulation(scenario, initialize_vehicles, database_url=None, calculate_timeseries=False, terminus_deadtime=timedelta(minutes=1), consumption_result=None)¶
Run a consumption simulation and optionally initialize vehicles in the database.
For every trip, this function obtains a
ConsumptionResultand writes the resultingEvent(with optional SoC timeseries) to the database. TheConsumptionResultcomes from one of two sources:The caller’s
consumption_resultdict (preferred when provided).extract_trip_information(), which decomposes the trip into route-aware segments and evaluates the vehicle’s consumption LUT — or, when no LUT is attached, the vehicle type’s flatconsumptionvalue — once per segment.
If
initialize_vehiclesis True, vehicles and an initial STANDBY event (with 100% SoC) are created for each rotation that does not already have a vehicle. If it is False, existing vehicles in the database are assumed, and a check is performed to ensure each rotation has a vehicle.Opportunity charging can optionally be applied at the end of each trip, if the vehicle and station both allow it, and if the rotation is flagged to allow it. This charging event is constrained by a configurable terminus deadtime.
SoC Constraints
The
ConsumptionResult(whether supplied or computed) must have a non-positivedelta_soc_total.delta_socmust be monotonically non-increasing. Otherwise aValueErroris raised.
Timeseries Calculation
If
calculate_timeseriesis True, the per-segment timestamps and SoC values from theConsumptionResultare written toEvent.timeseries.If False, the event’s
timeseriesis set toNone, which may speed up the simulation if you do not need intermediate SoC data.
- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) –
- One of:
A
eflips.model.Scenarioinstance containing the input data for the simulation.An integer specifying the ID of a scenario in the database.
Any other object with an integer
idattribute.
If not passing a
eflips.model.Scenariodirectly, the database_url parameter or the environment variableDATABASE_URLmust point to a valid database.initialize_vehicles (bool) – A boolean flag indicating whether new vehicles should be created and assigned to rotations in the database. Set this to True the first time you run the simulation so that vehicles are initialized. In subsequent runs, set to False if vehicles are already present.
database_url (Optional[str]) – A database connection string (e.g.,
postgresql://user:pass@host/db). If you do not provide this andscenariois not aeflips.model.Scenarioinstance, the environment variableDATABASE_URLmust be set.calculate_timeseries (bool) – If True, each trip’s detailed SoC timeseries is computed and stored in the
timeseriescolumn of the corresponding driving and charging events. If False, only the start/end SoC is recorded, andtimeseriesis set to None.terminus_deadtime (datetime.timedelta) – The total time overhead (attach + detach) for charging at the terminus. If this deadtime exceeds the available layover time, no charging is performed.
consumption_result (Dict[int, eflips.depot.api.private.consumption.ConsumptionResult] | None) –
A dictionary mapping trip IDs to
ConsumptionResultinstances for precomputed SoC changes. If an entry exists for a trip, this function uses those precomputed SoC changes instead of calculating them from distance and consumption. EachConsumptionResultmust have:A non-positive
delta_soc_total(<= 0).Optionally, matching lists of timestamps and delta SoC values that are decreasing (i.e., the vehicle only loses or maintains SoC).
- Returns:
None. All simulation results are written directly to the database aseflips.model.Evententries.- Raises:
ValueError –
If a rotation in the scenario does not have a vehicle when
initialize_vehicles=False.If the vehicle type has no
consumptionvalue.If a provided
ConsumptionResulthas inconsistent list lengths, or if itsdelta_soc_totalis positive.If SoC timeseries are not decreasing when provided via
consumption_result.
- Return type:
None
- depot.api.generate_depot_layout(scenario, charging_power=90, database_url=None, delete_existing_depot=False)¶
Generates one or more depots for the scenario.
First, the rotations are scanned to identify all the spots that serve as start and end of a rotation. Then the set of rotations for these spots are checked for vehicle types that are used there. Next, the amount of vehicles that are simultaneously present at the depot is calculated. Then a depot layout with an arrival and a charging area for each vehicle type is created. The capacity of each area is taken from the calculated amount of vehicles. The depot layout is then added to the database.
A default plan will also be generated, which includes the following default processes: standby_arrival, cleaning, charging and standby_departure. Each vehicle will be processed with this exact order (standby_arrival is optional because it only happens if a vehicle needs to wait for the next process).
The function only deletes the depot if the delete_existing_depot parameter is set to True. If there is already a depot existing in this scenario and this parameter is set to False, a ValueError will be raised.
- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) – Either a
eflips.model.Scenarioobject containing the input data for the simulation. Or an integer specifying the ID of a scenario in the database. Or any other object that has an attributeidthat is an integer. If noeflips.model.Scenarioobject is passed, thedatabase_urlparameter must be set to a valid database URL ot the environment variableDATABASE_URLmust be set to a valid database URL.charging_power (float) – the charging power of the charging area in kW
delete_existing_depot (bool) – if there is already a depot existing in this scenario, set True to delete this existing depot. Set to False and a ValueError will be raised if there is a depot in this scenario.
database_url (Optional[str])
- Returns:
None. The depot layout will be added to the database.
- Return type:
None
- depot.api.apply_even_smart_charging(scenario, database_url=None, standby_departure_duration=timedelta(minutes=5), delete_existing_charging_timeseries=False)¶
Takes a scenario where depot simulation has been run and applies smart charging to the depot.
This modifies the time and power of the charging events in the database. The arrival and departure times and SoCs at these times are not modified.
- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) – A
eflips.model.Scenarioobject containing the input data for the simulation.database_url (Optional[str]) – An optional database URL. If no database URL is passed and the scenario parameter is not a
eflips.model.Scenarioobject, the environment variable DATABASE_URL must be set to a valid database URL.standby_departure_duration (datetime.timedelta) – The duration of the STANDBY_DEPARTURE event. This is the time the vehicle is allowed to wait at the depot before it has to leave. The default is 5 minutes.
delete_existing_timeseries – If True, the existing timeseries in the charging events will be deleted.
delete_existing_charging_timeseries (bool)
- Returns:
None. The results are added to the database.
- Return type:
None
- depot.api.shrink_to_peak_usage(scenario, database_url=None, resolution=timedelta(minutes=5))¶
Shrink Areas and electrified terminus Stations to their peak observed usage.
A freshly generated depot layout is intentionally over-provisioned, but downstream cost estimation counts every slot. This pass walks every
eflips.model.Areain the scenario and reducesArea.capacityto the maximum number of simultaneous events observed at that area (rounded up to the next valid value for the area type). Areas that saw no events at all are deleted. Eacheflips.model.Stationwithis_electrified=Trueandcharge_type=ChargeType.OPPORTUNITYhas itsamount_charging_places(andpower_total) reduced to peak observed CHARGING_OPPORTUNITY concurrency; stations with zero such events are un-electrified.Must be called after
add_evaluation_to_database()so the events are persisted in the database.simulate_scenario()automatically shrinks Areas whenshrink_to_peak_usage=True(the default), but it does not shrink terminus Stations — those have no charging events until the subsequent consumption simulation runs. Call this function manually after that consumption simulation to also right-size the Stations.- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) – A
eflips.model.Scenario, its integer id, or any object with anidattribute pointing to a scenario id.database_url (Optional[str]) – Optional database URL. Falls back to
DATABASE_URLif the scenario is not given as aScenarioobject.resolution (datetime.timedelta) – Time-block resolution used to detect concurrent events. Default 5 minutes.
- Raises:
RuntimeError – If an Area or Station has zero peak concurrency but the database still holds matching events — this indicates an inconsistency and is never silently ignored.
- Return type:
None
- depot.api.simulate_scenario(scenario, repetition_period=None, database_url=None, smart_charging_strategy=SmartChargingStrategy.NONE, ignore_unstable_simulation=False, ignore_delayed_trips=False, shrink_to_peak_usage=True, shrink_resolution=timedelta(minutes=5))¶
This method simulates a scenario and adds the results to the database.
It fills in the “Charging Events” in the
eflips.model.Eventtable and associateseflips.model.Vehicleobjects with all the existing “Driving Events” in theeflips.model.Eventtable. If the simulation becomes unstable, anUnstableSimulationExceptionis raised.- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) – Either a
eflips.model.Scenarioobject containing the input data for the simulation. Or an integer specifying the ID of a scenario in the database. Or any other object that has an attributeidthat is an integer. If noeflips.model.Scenarioobject is passed, thedatabase_urlparameter must be set to a valid database URL or the environment variableDATABASE_URLmust be set to a valid database URL.repetition_period (Optional[datetime.timedelta]) – An optional timedelta object specifying the period of the vehicle schedules. This is needed because the result should be a steady-state result. This can only be achieved by simulating a time period before and after our actual simulation, and then only using the “middle”. eFLIPS tries to automatically detect whether the schedule should be repeated daily or weekly. If this fails, a ValueError is raised and repetition needs to be specified manually.
database_url (Optional[str]) – An optional database URL. If no database URL is passed and the scenario parameter is not a
eflips.model.Scenarioobject, the environment variable DATABASE_URL must be set to a valid database URL.smart_charging_strategy (SmartChargingStrategy) – An optional parameter specifying the smart charging strategy to be used. The default is SmartChargingStrategy.NONE. The following strategies are available: - SmartChargingStrategy.NONE: Do not use smart charging. Buses are charged with the maximum power available, from the time they arrive at the depot until they are full (or leave the depot). - SmartChargingStrategy.EVEN: Use smart charging with an even distribution of charging power over the time the bus is at the depot. This aims to minimize the peak power demand. - SmartChargingStrategy.MIN_PRICE: Not implemented yet.
ignore_unstable_simulation (bool) – If True, the simulation will not raise an exception if it becomes unstable.
ignore_delayed_trips (bool) – If True, the simulation will not raise an exception if there are delayed trips.
shrink_to_peak_usage (bool) – If True (the default), depot Areas are shrunk to their peak observed usage after the events have been written to the database. Electrified terminus Stations are not shrunk here because they have no charging events at this stage — those are only created by the subsequent consumption simulation. To also shrink terminus Stations, call
shrink_to_peak_usage()manually after that consumption simulation. Seeshrink_to_peak_usage()for details.shrink_resolution (datetime.timedelta) – Time-block resolution used when computing peak concurrency for the shrinking step. Default 5 minutes.
- Returns:
Nothing. The results are added to the database.
- Raises:
UnstableSimulationException – If the simulation becomes numerically unstable or if the parameters cause the solver to diverge.
DelayedTripException – If there are delayed trips in the simulation.
- Return type:
None
- depot.api.init_simulation(scenario, session, repetition_period=None, vehicle_count_dict=None)¶
This methods checks the input data for consistency, initializes a simulation host object and returns it.
The simulation host object can then be passed to
run_simulation().- Parameters:
scenario (eflips.model.Scenario) – A
eflips.model.Scenarioobject containing the input data for the simulation.session (sqlalchemy.orm.Session) – A SQLAlchemy session object.
repetition_period (Optional[datetime.timedelta]) – An optional timedelta object specifying the period of the vehicle schedules. This is needed because the result should be a steady-state result. THis can only be achieved by simulating a time period before and after our actual simulation, and then only using the “middle”. eFLIPS tries to automatically detect whether the schedule should be repeated daily or weekly. If this fails, a ValueError is raised and repetition needs to be specified manually.
vehicle_count_dict (Optional[Dict[str, Dict[str, int]]]) –
An optional dictionary specifying the number of vehicles for each vehicle type for each depot. The dictionary should have the following structure:
{ "1" (depot.id as str): { "1" (vehicle_type.id as str): 10, "2" (vehicle_type.id as str): 20, ... }, "2" (depot.id as str): { "1" (vehicle_type.id as str): 10, "2" (vehicle_type.id as str): 20, ... },
- Returns:
A
eflips.depot.Simulation.SimulationHostobject. This object should be reagrded as a “black box” by the user. It should be passed torun_simulation()to run the simulation and obtain the results.- Return type:
eflips.depot.SimulationHost
- depot.api.run_simulation(simulation_host)¶
Run simulation and return simulation results.
- Parameters:
simulation_host (eflips.depot.SimulationHost) – A “black box” object containing all input data for the simulation.
- Returns:
A dictionary of
eflips.depot.evaluation.DepotEvaluationobjects. The keys are the depot IDs, as strings.- Return type:
Dict[str, eflips.depot.DepotEvaluation]
- depot.api.add_evaluation_to_database(scenario, depot_evaluations, session)¶
This method adds a simulation result to the database.
- It reads the simulation results from the
eflips.depot.evaluation.DepotEvaluationobject and adds them into the database. Tables of Event, Rotation and Vehicle will be updated.
- Parameters:
scenario (eflips.model.Scenario) – A
eflips.model.Scenarioobject containing the input data for the simulation.depot_evaluations (Dict[str, eflips.depot.DepotEvaluation]) – A dictionary of
eflips.depot.evaluation.DepotEvaluationobjects. The keys are the depot IDs, as strings.session (sqlalchemy.orm.Session) – a SQLAlchemy session object. This is used to add all the simulation results to the database.
- Returns:
Nothing. The results are added to the database.
- Raises:
UnstableSimulationException – If the simulation becomes numerically unstable or if the parameters cause the solver to diverge.
DelayedTripException – If there are delayed trips in the simulation.
- Return type:
None
- It reads the simulation results from the
- depot.api.generate_depot_optimal_size(scenario, standard_block_length=6, charging_power=90, database_url=None, delete_existing_depot=False, use_consumption_lut=False, repetition_period=None)¶
Generates an optimal depot layout with the smallest possible size for each depot in the scenario.
- Line charging areas
with given block length area preferred. The existing depot will be deleted if delete_existing_depot is set to True.
- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) – Either a
eflips.model.Scenarioobject containing the input data for the simulation. Or an integer specifying the ID of a scenario in the database. Or any other object that has an attribute “id” containing an integer pointing to a unique scenario id.standard_block_length (int) – The standard block length for the depot layout in meters. Default is 6.
charging_power (float) – The charging power of the charging area in kW. Default is 90.
database_url (Optional[str]) – An optional database URL. Used if no database url is given by the environment variable.
delete_existing_depot (bool) – If there is already a depot existing in this scenario, set True to delete this existing depot. Set to False and a ValueError will be raised if there is a depot in this scenario.
use_consumption_lut (bool) – If True, the depot layout will be generated based on the consumption lookup table. If False, constant consumption stored in VehicleType table will be used.
repetition_period (Optional[datetime.timedelta]) – An optional timedelta object specifying the period of the vehicle schedules. If not specified, a default repetition period will be generated in simulate_scenario(). If the depot layout generated in this function will be used for further simulations, make sure that the repetition period is set to the same value as in the simulation.
- Returns:
None. The depot layout will be added to the database.
- Return type:
None
- depot.api.schedule_duration_days(scenario, database_url=None)¶
This method calculates the duration of a given scenario in days.
This is the duration between the first departure of the first day, and the last departure on the last day, rounded up to full days.
Most of the time, this is the “natural” repetition period of the scenario. We are simulating one full period, and this period – continuously repeated – is what happens in reality.
This method can be used to show the user what the detected repetition period is and to auto-set the repetition period if none is provided.
- Parameters:
scenario (Union[eflips.model.Scenario, int, Any]) – Either a
eflips.model.Scenarioobject containing the input data for the simulation. Or an integer specifying the ID of a scenario in the database. Or any other object that has an attribute “id” containing an integer pointing to a unique scenario id.database_url (Optional[str]) – An optional database URL. Used if no database url is given by the environment variable.
- Returns:
a timedelta object representing the duration in days.
- Return type:
datetime.timedelta
- depot.api.auto_generate_depot_inplace(depot_wish, session, scenario)¶
This method calculates an optimal depot layout for auto-generated depots and modifies the instance of.
eflips.depot.api.private.depot.DepotConfigurationWishobjects in place.- Parameters:
depot_wish (eflips.depot.api.private.depot.DepotConfigurationWish) – a
eflips.depot.api.private.depot.DepotConfigurationWishobject. It represents a depot to be generated by eflips calulation.session – a :class:’sqlalchemy.orm.Session’ object.
scenario – a
eflips.model.Scenarioobject containing the input data for the simulation.
- Returns:
None. The depot layout will be written inplace to the depot_wish object.
- Return type:
None
- depot.api.generate_optimal_depot_layout(depot_config_wishes, scenario, database_url=None, delete_existing_depot=False)¶
- Parameters:
depot_config_wishes (List[eflips.depot.api.private.depot.DepotConfigurationWish]) – a list of
eflips.depot.api.private.depot.DepotConfigurationWishobjects.scenario (Union[eflips.model.Scenario, int, Any]) – Either a
eflips.model.Scenarioobject containing the input data for the simulation. Or an integer specifying the ID of a scenario in the database. Or any other object that has an attribute “id” containing an integer pointing to a unique scenario id.database_url (Optional[str]) – An optional database URL. Used if no database url is given by the environment variable.
delete_existing_depot (bool) – If there is already a depot existing in this scenario, set True to delete this existing depot. Set to False and a ValueError will be raised if there is a depot
- Returns:
None. The depot layout will be added to the database.
- Return type:
None
- depot.api.create_diesel_vehicle_type_copies(vehicle_type_ids, scenario, session)¶
For each VehicleType ID in vehicle_type_ids, creates a DIESEL copy inside scenario.
and returns a mapping
{original_vt_id: diesel_vt_id}.The original vehicle types are left unchanged. The caller is responsible for reassigning rotations using the returned mapping and for removing any orphaned vehicle types afterwards.
- Parameters:
vehicle_type_ids (set) – IDs of the vehicle types to copy as diesel.
scenario (Any) – The
eflips.model.Scenariothe copies belong to.session (sqlalchemy.orm.Session) – An active SQLAlchemy session.
- Returns:
Dict mapping each original vehicle type ID to its new diesel copy ID.
- Return type:
Dict[int, int]