Open source Complex Logistics Simulation¶
OpenCLSim is a python package for rule driven scheduling of cyclic activities for in-depth comparison of alternative operating strategies
Welcome to OpenCLSim documentation! Please check the contents below for information on installation, getting started and actual example code. If you want to dive straight into the code you can check out our GitHub page or the working examples presented in Jupyter Notebooks.
Installation¶
Stable release¶
To install OpenCLSim, run this command in your terminal:
# Use pip to install OpenCLSim
pip install openclsim
This is the preferred method to install OpenCLSim, as it will always install the most recent stable release.
If you do not pip installed, this Python installation guide can guide you through the process.
From sources¶
The sources for OpenCLSim can be downloaded from the Github repo.
You can either clone the public repository:
# Use git to clone OpenCLSim
git clone git://github.com/TUDelft-CITG/OpenCLSim
Or download the tarball:
# Use curl to obtain the tarball
curl -OL https://github.com/TUDelft-CITG/OpenCLSim/tarball/master
Once you have a copy of the source, you can install it with:
# Use python to install
python setup.py install
Usage¶
Import required components¶
To use OpenCLSim in a project you have to import the following three components:
# Import openclsim for the logistical components
import openclsim.model as model
import openclsim.core as core
# Import simpy for the simulation environment
import simpy
Using Mixins and Metaclasses¶
The Open Complex Logistics Simulation package is developed with the goal of reusable and generic components in mind. A new class can be instatiated by combining mixins from the openclsim.core, such as presented below. The following lines of code demonstrate how a containervessel can be defined:
# Define the core components
# A generic class for an object that can move and transport material
ContainerVessel = type('ContainerVessel',
(core.Identifiable, # Give it a name and unique UUID
core.Log, # Allow logging of all discrete events
core.ContainerDependentMovable,# It can transport an amount
core.HasResource, # Add information on serving equipment
),
{})
# The next step is to define all the required parameters for the defined metaclass
# For more realistic simulation you might want to have speed dependent on the filling degree
v_full = 8 # meters per second
v_empty = 5 # meters per second
def variable_speed(v_empty, v_full):
return lambda x: x * (v_full - v_empty) + v_empty
# Other variables
data_vessel = {
"env": simpy.Environment(), # The simpy environment
"name": "Vessel 01", # Name
"geometry": shapely.geometry.Point(0, 0), # The lat, lon coordinates
"capacity": 5_000, # Capacity of the vessel
"compute_v": variable_speed(v_empty, v_full), # Variable speed
}
# Create an object based on the metaclass and vessel data
vessel_01 = ContainerVessel(**data_vessel)
For more elaboration and examples please check the examples documentation. In-depth Jupyter Notebooks can also be used.
Examples¶
This small example guide will cover the basic start-up and the three main elements of the OpenClSim package:
- Start-Up (Minimal set-up)
- Locations (Sites or stockpiles)
- Resources (Processors and transporters)
- Activities (Rule-based operations)
Once the elements above are explained some small simulations examples are presented.
Start-Up¶
The first part of every OpenClSim simulation is to import the required libraries and to initiate the simulation environment.
Required Libraries¶
Depending on the simulation it might be required to import additional libraries. The minimal set-up of an OpenCLSim project has the following import statements:
# Import openclsim for the logistical components
import openclsim.model as model
import openclsim.core as core
# Import simpy for the simulation environment
import simpy
Simulation Environment¶
OpenClSim continues on the SimPy discrete event simulation package. Some components are modified, such as the resources and container objects, but the simulation environment is pure SimPy. Starting the simulation environment can be done with the following line of code. For more information in SimPy environment please refer to the SimPy documentation.
# Start the SimPy environment
env = simpy.Environment()
Locations¶
Basic processes do not require a location but more comprehensive simulations do. Locations are added to an OpenCLSim environment so that it becomes possible to track all events in both time and space. If a site is initiated with a container it can store materials as well. Adding a processor allows the location to load or unload as well.
Basic Location¶
The code below illustrates how a basic location can be created using OpenClSim. Such a location can be used to add information on events in space, such as tracking movement events or creating paths to follow.
# Import the library required to add coordinates
import shapely.geometry
# Create a location class
Location = type(
"Location",
(
core.Identifiable, # Give it a name and unique UUID
core.Log, # To keep track of all events
core.HasResource, # Add information on the number of resources
core.Locatable, # Add coordinates to extract distance information
),
{},
)
location_data = {
"env": env, # The SimPy environment
"name": "Location 01", # Name of the location
"geometry": shapely.geometry.Point(0, 0), # The lat, lon coordinates
}
location_01 = Location(**location_data)
Storage Location¶
The code below illustrates how a location can be created that is capable of storing an amount. Such a location can be used by the OpenClSim.model activities as origin or destination.
# Import the library required to add coordinates
import shapely.geometry
# Create a location class
StorageLocation = type(
"StorageLocation",
(
core.Identifiable, # Give it a name and unique UUID
core.Log, # To keep track of all events
core.HasResource, # Add information on the number of resources
core.Locatable, # Add coordinates to extract distance information
core.HasContainer, # Add information on storage capacity
),
{},
)
location_data = {
"env": env, # The SimPy environment
"name": "Location 02", # Name of the location
"geometry": shapely.geometry.Point(0, 0), # The lat, lon coordinates
"capacity": 10_000, # The maximum number of units
"level": 10_000, # The number of units in the location
}
location_02 = StorageLocation(**location_data)
Processing Storage Location¶
The code below illustrates how a location can be created that is capable of storing an amount. Additional to the storage location, a processing- and storage location can be used as both the origin and loader or destination and unloader in a OpenClSim.model activity.
# Import the library required to add coordinates
import shapely.geometry
# Create a location class
ProcessingStorageLocation = type(
"ProcessingStorageLocation",
(
core.Identifiable, # Give it a name and unique UUID
core.Log, # To keep track of all events
core.HasResource, # Add information on the number of resources
core.Locatable, # Add coordinates to extract distance information
core.HasContainer, # Add information on storage capacity
core.Processor, # Add information on processing
),
{},
)
# Create a processing function
processing_rate = lambda x: x
location_data = {
"env": env, # The SimPy environment
"name": "Location 03", # Name of the location
"geometry": shapely.geometry.Point(0, 1), # The lat, lon coordinates
"capacity": 10_000, # The maximum number of units
"level": 0, # The number of units in the location
"loading_func": processing_rate, # Loading rate of 1 unit per 1 unit time
"unloading_func": processing_rate, # Unloading rate of 1 unit per 1 unit time
}
location_03 = ProcessingStorageLocation(**location_data)
Optionally a OpenCLSim.core.Log mixin can be added to all locations to keep track of all the events that are taking place.
Resources¶
OpenCLSim resources can be used to process and transport units. The OpenCLSim.model activity class requires a loader, an unloader and a mover, this are examples of resources. A resource will always interact with another resource in an OpenClSim.model activity, but it is possible to initiate a simpy process to keep track of a single resource.
Processing Resource¶
An example of a processing resource is a harbour crane, it processes units from a storage location to a transporting resource or vice versa. In the OpenClSim.model activity such a processing resource could be selected as the loader or unloader. The example code is presented below.
# Create a resource
ProcessingResource = type(
"ProcessingResource",
(
core.Identifiable, # Give it a name and unique UUID
core.Log, # To keep track of all events
core.HasResource, # Add information on the number of resources
core.Locatable, # Add coordinates to extract distance information
core.Processor, # Add information on processing
),
{},
)
# The next step is to define all the required parameters for the defined metaclass
# Create a processing function
processing_rate = lambda x: x
resource_data = {
"env": env, # The SimPy environment
"name": "Resource 01", # Name of the location
"geometry": location_01.geometry, # The lat, lon coordinates
"loading_func": processing_rate, # Loading rate of 1 unit per 1 unit time
"unloading_func": processing_rate, # Unloading rate of 1 unit per 1 unit time
}
# Create an object based on the metaclass and vessel data
resource_01 = ProcessingResource(**resource_data)
Transporting Resource¶
A harbour crane will service transporting resources. To continue with the harbour crane example, basically any vessel is a transporting resource because it is capable of moving units from location A to location B. In the OpenClSim.model activity such a processing resource could be selected as the mover.
# Create a resource
TransportingResource = type(
"TransportingResource",
(
core.Identifiable, # Give it a name and unique UUID
core.Log, # To keep track of all events
core.HasResource, # Add information on the number of resources
core.ContainerDependentMovable, # It can transport an amount
),
{},
)
# The next step is to define all the required parameters for the defined metaclass
# For more realistic simulation you might want to have speed dependent on the filling degree
v_full = 8 # meters per second
v_empty = 5 # meters per second
def variable_speed(v_empty, v_full):
return lambda x: x * (v_full - v_empty) + v_empty
# Other variables
resource_data = {
"env": env, # The SimPy environment
"name": "Resource 02", # Name of the location
"geometry": location_01.geometry, # The lat, lon coordinates
"capacity": 5_000, # Capacity of the vessel
"compute_v": variable_speed(v_empty, v_full), # Variable speed
}
# Create an object based on the metaclass and vessel data
resource_02 = TransportingResource(**resource_data)
Transporting Processing Resource¶
Finally, some resources are capable of both processing and moving units. Examples are dredging vessels or container vessels with deck cranes. These specific vessels have the unique property that they can act as the loader, unloader and mover in the OpenClSim.model activity.
# Create a resource
TransportingProcessingResource = type(
"TransportingProcessingResource",
(
core.Identifiable, # Give it a name and unique UUID
core.Log, # To keep track of all events
core.HasResource, # Add information on the number of resources
core.ContainerDependentMovable, # It can transport an amount
core.Processor, # Add information on processing
),
{},
)
# The next step is to define all the required parameters for the defined metaclass
# For more realistic simulation you might want to have speed dependent on the filling degree
v_full = 8 # meters per second
v_empty = 5 # meters per second
def variable_speed(v_empty, v_full):
return lambda x: x * (v_full - v_empty) + v_empty
# Create a processing function
processing_rate = lambda x: x
# Other variables
resource_data = {
"env": env, # The SimPy environment
"name": "Resource 03", # Name of the location
"geometry": location_01.geometry, # The lat, lon coordinates
"capacity": 5_000, # Capacity of the vessel
"compute_v": variable_speed(v_empty, v_full), # Variable speed
"loading_func": processing_rate, # Loading rate of 1 unit per 1 unit time
"unloading_func": processing_rate, # Unloading rate of 1 unit per 1 unit time
}
# Create an object based on the metaclass and vessel data
resource_03 = TransportingProcessingResource(**resource_data)
Simulations¶
The code below will start the simulation if SimPy processes are added to the environment. These SimPy processes can be added using a combination of SimPy and OpenCLSim, or by using OpenCLSim activities.
env.run()
SimPy processes¶
A SimPy process can be initiated using the code below. The code below will instruct Resource 02, which was a TransportingResource, to sail from Location 01 (at Lat, Long (0, 0)) to Location 02 (at Lat, Long (0, 1)). The simulation will stop as soon as Resource 02 is at Location 02.
# Create the process function
def move_resource(mover, destination):
# the is_at function is part of core.Movable
while not mover.is_at(destination):
# the move function is part of core.Movable
yield from mover.move(destination)
# Add to the SimPy environment
env.process(move_resource(resource_02, location_03))
# Run the simulation
env.run()
Unconditional Activities¶
Activities are at the core of what OpenCLSim adds to SimPy, an activity is a collection of SimPy Processes. These activities schedule cyclic events, which could be production or logistical processes and, but the current OpenCLSim.model.activity assumes the following cycle:
- Loading
- Transporting
- Unloading
- Transporting
This cycle is repeated until a certain condition is met. Between the individual components of the cycle waiting events can occur due to arising queues, equipment failure or weather events. The minimal input for an activity is listed below.
- Origin
- Destination
- Loader
- Mover
- Unloader
If no additional input is provided, the cyclic process will be repeated until either the origin is empty or the destination is full. The example activity below will stop after two cycles because the origin will be empty and the destination will be full.
# Define the activity
activity_01 = model.Activity(
env=env, # The simpy environment defined in the first cel
name="Activity 01", # Name of the activity
origin=location_02, # Location 02 was filled with 10_000 units
destination=location_03, # Location 03 was empty
loader=resource_03, # Resource 03 could load
mover=resource_03, # Resource 03 could move
unloader=resource_03, # Resource 03 could unload
)
# Run the simulation
env.run()
Conditional Activities¶
Additionally, start and stop events can be added to the activity. The process will only start as soon as a start event (or a list of start events) is completed and it will stop as soon as the stop event (or a list of stop events) are completed. These can be any SimPy event, such as a time-out, but OpenClSim provides some additional events as well, such as empty- or full events. The activity in the example below will start as soon as the previous activity is finished, but not sooner than 2 days after the simulation is started.
# Activity starts after both
# - Activity 01 is finished
# - A minimum of 2 days after the simulation starts
start_event = [activity_01.main_process, env.timeout(2 * 24 * 3600)]
# Define the activity
activity_02 = model.Activity(
env=env, # The simpy environment defined in the first cel
name="Activity 02", # Name of the activity
origin=location_03, # Location 03 will be filled
destination=location_02, # Location 02 will be empty
loader=resource_03, # Resource 03 could load
mover=resource_03, # Resource 03 could move
unloader=resource_03, # Resource 03 could unload
start_event=start_event, # Start Event
)
# Run the simulation
env.run()
OpenCLSim¶
This page lists all functions and classes available in the OpenCLSim.model and OpenCLSim.core modules. For examples on how to use these submodules please check out the Examples page, information on installing OpenCLSim can be found on the Installation page.
Submodules¶
The main components are the Model module and the Core module. All of their components are listed below.
openclsim.model module¶
Directory for the simulation activities.
-
class
openclsim.model.
AbstractPluginClass
[source]¶ Bases:
abc.ABC
Abstract class used as the basis for all Classes implementing a plugin for a specific Activity.
Instance checks will be performed on this class level.
-
class
openclsim.model.
PluginActivity
(*args, **kwargs)[source]¶ Bases:
openclsim.core.identifiable.Identifiable
,openclsim.core.log.Log
Base class for all activities which will provide a plugin mechanism.
The plugin mechanism foresees that the plugin function pre_process is called before the activity is executed, while the function post_process is called after the activity has been executed.
-
class
openclsim.model.
GenericActivity
(registry, start_event=None, requested_resources={}, keep_resources=[], *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.PluginActivity
The GenericActivity Class forms a generic class which sets up all activites.
-
class
openclsim.model.
MoveActivity
(mover, destination, duration=None, show=False, engine_order=1, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
MoveActivity Class forms a specific class for a single move activity within a simulation.
It deals with a single origin container, destination container and a single combination of equipment to move substances from the origin to the destination. It will initiate and suspend processes according to a number of specified conditions. To run an activity after it has been initialized call env.run() on the Simpy environment with which it was initialized.
To check when a transportation of substances can take place, the Activity class uses three different condition arguments: start_condition, stop_condition and condition. These condition arguments should all be given a condition object which has a satisfied method returning a boolean value. True if the condition is satisfied, False otherwise.
destination: object inheriting from HasContainer, HasResource, Locatable, Identifiable and Log mover: moves to ‘origin’ if it is not already there, is loaded, then moves to ‘destination’ and is unloaded
should inherit from Movable, HasContainer, HasResource, Identifiable and Log after the simulation is complete, its log will contain entries for each time it started moving, stopped moving, started loading / unloading and stopped loading / unloading- start_event: the activity will start as soon as this event is triggered
- by default will be to start immediately
-
main_process_function
(activity_log, env)[source]¶ Return a generator which can be added as a process to a simpy.Environment.
In the process, a move will be made by the mover, moving it to the destination.
activity_log: the core.Log object in which log_entries about the activities progress will be added. env: the simpy.Environment in which the process will be run mover: moves from its current position to the destination
should inherit from core.Movable- destination: the location the mover will move to
- should inherit from core.Locatable
- engine_order: optional parameter specifying at what percentage of the maximum speed the mover should sail.
- for example, engine_order=0.5 corresponds to sailing at 50% of max speed
-
class
openclsim.model.
BasicActivity
(duration, additional_logs=None, show=False, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
BasicActivity Class is a generic class to describe an activity, which does not require any specific resource, but has a specific duration.
duration: time required to perform the described activity. additional_logs: list of other concepts, where the start and the stop of the basic activity should be recorded. start_event: the activity will start as soon as this event is triggered
by default will be to start immediately-
main_process_function
(activity_log, env)[source]¶ Return a generator which can be added as a process to a simpy.Environment.
The process will report the start of the activity, delay the execution for the provided duration, and finally report the completion of the activiy.
activity_log: the core.Log object in which log_entries about the activities progress will be added. env: the simpy.Environment in which the process will be run stop_event: a simpy.Event object, when this event occurs, the conditional process will finish executing its current
run of its sub_processes and then finish- sub_processes: an Iterable of methods which will be called with the activity_log and env parameters and should
- return a generator which could be added as a process to a simpy.Environment the sub_processes will be executed sequentially, in the order in which they are given as long as the stop_event has not occurred.
-
-
class
openclsim.model.
SequentialActivity
(sub_processes, show=False, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
,openclsim.model.base_activities.RegisterSubProcesses
SequenceActivity Class forms a specific class.
This is for executing multiple activities in a dedicated order within a simulation. It is a structural activity, which does not require specific resources.
- sub_processes:
- a list of activities to be executed in the provided sequence.
- start_event:
- The activity will start as soon as this event is triggered by default will be to start immediately
-
class
openclsim.model.
WhileActivity
(sub_processes, condition_event, show=False, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
,openclsim.model.while_activity.ConditionProcessMixin
,openclsim.model.base_activities.RegisterSubProcesses
WhileActivity Class forms a specific class for executing multiple activities in a dedicated order within a simulation.
The while activity is a structural activity, which does not require specific resources.
- sub_processes
- the sub_processes which is executed in sequence in every iteration
- condition_event
- a condition event provided in the expression language which will stop the iteration as soon as the event is fulfilled.
- start_event
- the activity will start as soon as this event is triggered by default will be to start immediately
-
class
openclsim.model.
RepeatActivity
(sub_processes, repetitions: int, show=False, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
,openclsim.model.while_activity.ConditionProcessMixin
,openclsim.model.base_activities.RegisterSubProcesses
RepeatActivity Class forms a specific class for executing multiple activities in a dedicated order within a simulation.
- sub_processes
- the sub_processes which is executed in sequence in every iteration
- repetitions
- Number of times the subprocess is repeated
- start_event
- the activity will start as soon as this event is triggered by default will be to start immediately
-
openclsim.model.
single_run_process
(env, registry, name, origin, destination, mover, loader, unloader, start_event=None, stop_event=[], requested_resources={})[source]¶ Single run activity for the simulation.
-
class
openclsim.model.
ShiftAmountActivity
(processor, origin, destination, duration=None, amount=None, id_='default', show=False, phase=None, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
ShiftAmountActivity Class forms a specific class for shifting material from an origin to a destination.
It deals with a single origin container, destination container and a single processor to move substances from the origin to the destination. It will initiate and suspend processes according to a number of specified conditions. To run an activity after it has been initialized call env.run() on the Simpy environment with which it was initialized.
origin: container where the source objects are located. destination: container, where the objects are assigned to processor: resource responsible to implement the transfer. amount: the maximum amount of objects to be transfered. duration: time specified in seconds on how long it takes to transfer the objects. id_: in case of MultiContainers the id_ of the container, where the objects should be removed from or assiged to respectively. start_event: the activity will start as soon as this event is triggered
by default will be to start immediately
-
class
openclsim.model.
ParallelActivity
(sub_processes, show=False, *args, **kwargs)[source]¶ Bases:
openclsim.model.base_activities.GenericActivity
,openclsim.model.base_activities.RegisterSubProcesses
ParallelActivity Class forms a specific class.
This is for executing multiple activities in a dedicated order within a simulation. It is a structural activity, which does not require specific resources.
- sub_processes:
- a list of activities to be executed in Parallel.
- start_event:
- The activity will start as soon as this event is triggered by default will be to start immediately
openclsim.core module¶
Core of the simulation Package.
-
class
openclsim.core.
HasContainer
(capacity: float, store_capacity: int = 1, level: float = 0.0, *args, **kwargs)[source]¶ Bases:
openclsim.core.simpy_object.SimpyObject
A class which can hold information about objects of the same type.
- capacity
- amount the container can hold
- level
- Amount the container holds initially
- store_capacity
- The number of different types of information can be stored. In this class it usually is 1.
-
class
openclsim.core.
HasMultiContainer
(initials, store_capacity=10, *args, **kwargs)[source]¶ Bases:
openclsim.core.container.HasContainer
A class which can represent information of objects of multiple types.
store_capacity: The number of different types of information can be stored. In this calss it is usually >1. initials: a list of dictionaries describing the id_ of the container, the level of the individual container and the capacity of the individual container.
-
class
openclsim.core.
EventsContainer
(env, store_capacity: int = 1, *args, **kwargs)[source]¶ Bases:
simpy.resources.store.FilterStore
EventsContainer provide a basic class for managing information which has to be stored in an object.
It is a generic container, which has a default behavior, but can be used for storing arbitrary objects.
- store_capacity
- Number of stores that can be contained by the multicontainer
-
container_list
¶
-
empty_event
¶ Properties that are kept for backwards compatibility. mThey are NOT applicable for MultiContainers.
-
full_event
¶ Properties that are kept for backwards compatibility. mThey are NOT applicable for MultiContainers.
-
get
(amount, id_='default')[source]¶ Request to get an item from the store matching the filter. The request is triggered once there is such an item available in the store.
filter is a function receiving one item. It should return
True
for items matching the filter criterion. The default function returnsTrue
for all items, which makes the request to behave exactly likeStoreGet
.
-
initialize
(init=0, capacity=0)[source]¶ Initialize method is a convenience method for backwards compatibility reasons.
-
class
openclsim.core.
Identifiable
(name: str, ID: str = None, *args, **kwargs)[source]¶ Bases:
object
OpenCLSim Identifiable with tags and a description.
- name
- a name
- ID : UUID
- a unique id generated with uuid
- description
- Text that can be used to describe a simulation object. Note that this field does not influence the simulation.
- tags
- List of tags that can be used to identify objects. Note that this field does not influence the simulation.
-
class
openclsim.core.
Locatable
(geometry, *args, **kwargs)[source]¶ Bases:
object
Something with a geometry (geojson format).
- lat : degrees
- can be a point as well as a polygon
lon : degrees
-
class
openclsim.core.
Log
(*args, **kwargs)[source]¶ Bases:
openclsim.core.simpy_object.SimpyObject
Log class to log the object activities.
-
class
openclsim.core.
LogState
[source]¶ Bases:
enum.Enum
LogState enumeration of all possible states of a Log object.
Access the name using .name and the integer value using .value
-
START
= 1¶
-
STOP
= 2¶
-
UNKNOWN
= -1¶
-
WAIT_START
= 3¶
-
WAIT_STOP
= 4¶
-
-
class
openclsim.core.
Movable
(v: float = 1, *args, **kwargs)[source]¶ Bases:
openclsim.core.simpy_object.SimpyObject
,openclsim.core.locatable.Locatable
Movable class.
Used for object that can move with a fixed speed geometry: point used to track its current location
- v
- speed
-
current_speed
¶
-
class
openclsim.core.
ContainerDependentMovable
(compute_v, *args, **kwargs)[source]¶ Bases:
openclsim.core.movable.Movable
,openclsim.core.container.HasContainer
ContainerDependentMovable class.
Used for objects that move with a speed dependent on the container level compute_v: a function, given the fraction the container is filled (in [0,1]), returns the current speed
- v_empty
- Velocity of the vessel when empty
- v_full
- Velocity of the vessel when full
-
current_speed
¶
-
class
openclsim.core.
MultiContainerDependentMovable
(compute_v, *args, **kwargs)[source]¶ Bases:
openclsim.core.movable.Movable
,openclsim.core.container.HasMultiContainer
MultiContainerDependentMovable class.
Used for objects that move with a speed dependent on the container level. This movable is provided with a MultiContainer, thus can handle container containing different object. compute_v: a function, given the fraction the container is filled (in [0,1]), returns the current speed
-
current_speed
¶
-
-
class
openclsim.core.
Processor
(*args, **kwargs)[source]¶ Bases:
openclsim.core.simpy_object.SimpyObject
Processor class.
Adds the loading and unloading components and checks for possible downtime.
If the processor class is used to allow “loading” or “unloading” the mixins “LoadingFunction” and “UnloadingFunction” should be added as well. If no functions are used a subcycle should be used, which is possible with the mixins “LoadingSubcycle” and “UnloadingSubcycle”.
-
check_possible_shift
(origin, destination, amount, activity, id_='default')[source]¶ Check if all the material is available.
If the amount is not available in the origin or in the destination yield a put or get. Time will move forward until the amount can be retrieved from the origin or placed into the destination.
-
-
class
openclsim.core.
LoadingFunction
(loading_rate: float, load_manoeuvring: float = 0, *args, **kwargs)[source]¶ Bases:
object
Create a loading function and add it a processor.
This is a generic and easy to read function, you can create your own LoadingFunction class and add this as a mixin.
- loading_rate : amount / second
- The rate at which units are loaded per second
- load_manoeuvring : seconds
- The time it takes to manoeuvring in minutes
-
class
openclsim.core.
UnloadingFunction
(unloading_rate: float, unload_manoeuvring: float = 0, *args, **kwargs)[source]¶ Bases:
object
Create an unloading function and add it a processor.
This is a generic and easy to read function, you can create your own LoadingFunction class and add this as a mixin.
- unloading_rate : volume / second
- the rate at which units are loaded per second
- unload_manoeuvring : minutes
- the time it takes to manoeuvring in minutes
-
class
openclsim.core.
HasResource
(nr_resources: int = 1, *args, **kwargs)[source]¶ Bases:
openclsim.core.simpy_object.SimpyObject
HasProcessingLimit class.
Adds a limited Simpy resource which should be requested before the object is used for processing.
- nr_resources
- Number of rescources of the object
openclsim.server module¶
Module contents¶
Top-level package for OpenCLSim.
OpenCLSim API¶
A flask server is part of the OpenCLSim package. This allows using the python code from OpenCLSim from a separate front-end.
Starting the Flask Server¶
The example code below lets you start the Flask server from the windows command line, for other operation systems please check the Flask Documentation.
# Set Flask app
set FLASK_APP=openclsim/server.py
# Set Flask environment
set FLASK_ENV=development
# Run Flask
flask run
Using the Flask Server¶
You can send json strings to the Flask Server using the methods presented in the server module.
Contributing¶
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
You can contribute in many ways:
Types of Contributions¶
Report Bugs¶
Report bugs at https://github.com/TUDelft-CITG/OpenCLSim/issues.
If you are reporting a bug, please include:
- Your operating system name and version.
- Any details about your local setup that might be helpful in troubleshooting.
- Detailed steps to reproduce the bug.
Fix Bugs¶
Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.
Implement Features¶
Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.
Write Documentation¶
OpenCLSim could always use more documentation, whether as part of the official OpenCLSim docs, in docstrings, or even on the web in blog posts, articles, and such.
Submit Feedback¶
The best way to send feedback is to file an issue at https://github.com/TUDelft-CITG/OpenCLSim/issues.
If you are proposing a feature:
- Explain in detail how it would work.
- Keep the scope as narrow as possible, to make it easier to implement.
- Remember that this is a volunteer-driven project, and that contributions are welcome :)
Get Started!¶
Ready to contribute? Here’s how to set up OpenCLSim for local development.
Fork the OpenCLSim repository on GitHub.
Clone your fork locally:
$ git clone git@github.com:your_name_here/OpenCLSim.git
Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:
$ mkvirtualenv openclsim $ cd openclsim/ $ python setup.py develop
Create a branch for local development:
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
When you’re done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:
$ flake8 openclsim tests $ python setup.py test or py.test $ tox
To get flake8 and tox, just pip install them into your virtualenv.
The style of OpenCLSim is according to Black. Format your code using Black witht the following lines of code:
$ black openclsim $ black tests
You can install black using pip.
Commit your changes and push your branch to GitHub:
$ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature
Submit a pull request through the GitHub website.
Pull Request Guidelines¶
Before you submit a pull request, check that it meets these guidelines:
- The pull request should include tests.
- If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.
- The pull request should work for Python 3.4, 3.5 and 3.6, and for PyPy. Check CircleCI and make sure that the tests pass for all supported Python versions.
Tips¶
To run a subset of tests:
$ py.test tests.test_openclsim
To make the documentation pages:
$ make docs # for linux/osx
For windows:
$ del docs\openclsim.rst
$ del docs\modules.rst
$ sphinx-apidoc -o docs/ openclsim
$ cd docs
$ make html
$ start explorer _build\html\index.html
Deploying¶
A reminder for the maintainers on how to deploy. Make sure all your changes are committed (including an entry in HISTORY.rst). Then run:
$ bumpversion patch # possible: major / minor / patch
$ git push
$ git push --tags
Travis will then deploy to PyPI if tests pass.
Credits¶
Development Lead¶
Contributors¶
Various MSc projects
- Joris den Uijl, 2018. Integrating engineering knowledge in logistical optimisation: development of a concept evaluation tool. MSc thesis. Delft University of Technology, Civil Engineering and Geosciences, Hydraulic Engineering. Delft, the Netherlands.
- Vibeke van der Bilt, 2019. Assessing emission performance of dredging projects. MSc thesis. Delft University of Technology, Civil Engineering and Geosciences, Hydraulic Engineering - Ports and Waterways. Delft, the Netherlands.
- Pieter van Halem, 2019. Route optimization in dynamic currents. Navigation system for the North Sea and Wadden Sea. MSc thesis. Delft University of Technology, Civil Engineering and Geosciences, Environmental Fluid Mechanics. Delft, the Netherlands.
- Servaas Kievits, 2019. A framework for the impact assessment of low discharges on the performance of inland waterway transport. MSc thesis. Delft University of Technology, Civil Engineering and Geosciences, Hydraulic Engineering - Ports and Waterways. Delft, the Netherlands.
Ongoing PhD work
- Frederik Vinke, 2019. Climate proofing the inland water transport system in the Netherlands. PhD thesis. Delft University of Technology, Civil Engineering and Geosciences, Hydraulic Engineering - Ports and Waterways. Delft, the Netherlands.
History¶
1.2.3 (2020-05-07)¶
Improved documentation and readme.
1.2.2 (2020-04-10)¶
Fixed a bug raised in GitHub issue #89.
1.2.1 (2020-03-27)¶
Minor bug fixes.
1.2.0 (2020-01-27)¶
- Major updates to the Movable class
- You can now enter multiple origins and destinations in one activity
- Optimisation of the schedule is possible by enhanding the Movable
1.1.1 (2019-12-11)¶
- Minor bug fixes
1.1.0 (2019-08-30)¶
- More generic Movable class
- More generic Routeable class
- Easier to implement own functions and adjustments
1.0.1 (2019-07-26)¶
- Small bug fixes
1.0.0 (2019-07-10)¶
- First formal release
0.3.0 (2019-06-20)¶
- First release to PyPI and rename to OpenCLSim
v0.2.0 (2019-02-14)¶
- Second tag on GitHub
v0.1.0 (2018-08-01)¶
- First tag on GitHub
Version conventions¶
This package is being developed continuously. Branch protection is turned on for the master branch. Useful new features and bugfixes can be developed in a separate branch or fork. Pull requests can be made to integrate updates into the master branch. To keep track of versions, every change to the master branch will receive a version tag. This page outlines the version tags’ naming convention.
Each change to the master branch is stamped with a unique version identifier. We use sequence based version identifiers, that consist of a sequence of three numbers: the first number is a major change identifier, followed by a minor change idenfier and finally a maintenance identifier. This leads to version identifiers of the form:
major.minor.maintenance (example: 1.2.2)
The following guideline gives an idea what types of changes are considered major changes, minor changes and maintenance:
- Major changes (typically breaking changes) -> major + 1
- Minor changes (typically adding of new features) -> minor + 1
- Maintenance (typically bug fixes and updates in documentation -> maintenance + 1