feeder concept#
This notebook shows how to implement a basic feeder concept. This scenario has two vessels:
transporter01: a vessel that transports the material from from_site, the source of the cargo, to to_site, the site where the cargo should be installed, and
installer01: a vessel that waits at the installation site for material and installs it.
Thus, we also need two processes - one for each vessel. In this notebook the hand over of cargo is done from the transporter01 to installer01.
NB1: in this example there are two types of cargo: Cargo_1 and Cargo_2. This means that the vessels and sites have to have multistore containers that can contain these different cargos.
NB2: For now we only implemented the transport and installation process for Cargo_1. In fact only a quantity of one is shifted each cycle. An example of sequential execution of two types fo cargo transfer is found in in the next example.
0. Import libraries#
import datetime, time
import simpy
import shapely.geometry
import pandas as pd
import openclsim.core as core
import openclsim.model as model
import openclsim.plot as plot
1. Initialise simpy environment#
# setup environment
simulation_start = 0
my_env = simpy.Environment(initial_time=simulation_start)
2. Define object classes#
# create a Site object based on desired mixin classes
Site = type(
"Site",
(
core.Identifiable,
core.Log,
core.Locatable,
core.HasMultiContainer,
core.HasResource,
),
{},
)
# create a TransportProcessingResource object based on desired mixin classes
TransportProcessingResource = type(
"TransportProcessingResource",
(
core.MultiContainerDependentMovable,
core.Processor,
core.HasResource,
core.LoadingFunction,
core.UnloadingFunction,
core.Identifiable,
core.Log,
),
{"key": "MultiStoreHopper"},
)
3. Create objects#
3.1. Create site object(s)#
# prepare input data for from_site
location_from_site = shapely.geometry.Point(4.18055556, 52.18664444)
data_from_site = {"env": my_env,
"name": "from_site",
"geometry": location_from_site,
"store_capacity": 4,
"initials": [
{"id": "Cargo_1", "level": 5, "capacity": 10},
{"id": "Cargo_2", "level": 5, "capacity": 10},
]
}
# instantiate from_site
from_site = Site(**data_from_site)
# prepare input data for to_site
location_to_site = shapely.geometry.Point(4.25222222, 52.11428333)
data_to_site = {"env": my_env,
"name": "to_site",
"geometry": location_to_site,
"store_capacity": 4,
"initials": [
{"id": "Cargo_1", "level": 0, "capacity": 5},
{"id": "Cargo_2", "level": 0, "capacity": 5},
]
}
# instantiate to_site
to_site = Site(**data_to_site)
3.2. Create vessel object(s)#
# prepare input data for transporter01
data_transporter01 = {"env": my_env,
"name": "transporter01",
"geometry": location_from_site,
"loading_rate": 1,
"unloading_rate": 1,
"store_capacity": 4,
"compute_v": lambda x: 10,
"initials": [
{"id": "Cargo_1", "level": 0, "capacity": 2},
{"id": "Cargo_2", "level": 0, "capacity": 2},
],
}
# instantiate transporter01
transporter01 = TransportProcessingResource(**data_transporter01)
# prepare input data for installer01
data_installer01 = {"env": my_env,
"name": "installer01",
"geometry": location_from_site,
"loading_rate": 1,
"unloading_rate": 1,
"store_capacity": 4,
"compute_v": lambda x: 10,
"initials": [
{"id": "Cargo_1", "level": 0, "capacity": 1},
{"id": "Cargo_2", "level": 0, "capacity": 1},
],
}
# instantiate installer01
installer01 = TransportProcessingResource(**data_installer01)
3.3 Create activity/activities#
# initialise registry
registry = {}
3.3.1 Create transporter activity#
# create a list of the sub processes: transport to installation site
sub_processes =[
model.MoveActivity(
env=my_env,
name="sailing empty",
registry=registry,
mover=transporter01,
destination=from_site,
),
model.ShiftAmountActivity(
env=my_env,
name="loading Cargo_1",
registry=registry,
processor=transporter01,
origin=from_site,
destination=transporter01,
amount=1,
duration=120,
id_="Cargo_1",
),
model.MoveActivity(
env=my_env,
name="sailing filled",
registry=registry,
mover=transporter01,
destination=to_site,
),
model.ShiftAmountActivity(
env=my_env,
name="transfer Cargo_1",
registry=registry,
processor=installer01,
origin=transporter01,
destination=installer01,
amount=1,
duration=120,
id_="Cargo_1",
start_event=[{"type": "activity", "name": "preparing for delivery", "state": "done",}],
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity = model.SequentialActivity(
env=my_env,
name="sequential_activity_transport_subcycle",
registry=registry,
sub_processes=sub_processes,
)
# create a while activity that executes the 'sequential activity' while the stop condition is not triggered
transport_activity = model.WhileActivity(
env=my_env,
name="Transporter01 move process",
registry=registry,
sub_processes=[sequential_activity],
condition_event=[{"type": "container", "concept": from_site, "state": "empty", "id_": "Cargo_1"}],
)
3.3.2 Create installer activity (first move, then install)#
# create a list of the sub processes: in field installation
sub_processes =[
model.BasicActivity(
env=my_env,
name="preparing for delivery",
registry=registry,
duration=30,
additional_logs=[installer01],
),
model.BasicActivity(
env=my_env,
name="preparing for unloading",
registry=registry,
duration=60,
additional_logs=[installer01],
start_event=[
{"type": "activity", "name": "sequential_activity_transport_subcycle", "state": "done"}
],
),
model.ShiftAmountActivity(
env=my_env,
name="unload Cargo_1",
registry=registry,
processor=installer01,
origin=installer01,
destination=to_site,
amount=1,
duration=120,
id_="Cargo_1",
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
installer_shift_sequential_activity = model.SequentialActivity(
env=my_env,
name="Installer01 installation process",
registry=registry,
sub_processes=sub_processes,
)
# create a list of the sub processes: in field installation
sub_processes = [
model.MoveActivity(
env=my_env,
name="sailing to site",
registry=registry,
mover=installer01,
destination=to_site,
),
model.WhileActivity(
env=my_env,
name="installer run while",
registry=registry,
sub_processes=[installer_shift_sequential_activity],
condition_event=[
{"type": "container", "concept": to_site, "state": "full", "id_": "Cargo_1"}
],
),
]
installer_move_sequential_activity = model.SequentialActivity(
env=my_env,
name="Installer01 move process",
registry=registry,
sub_processes=sub_processes,
)
4. Register processes and run simpy#
model.register_processes([transport_activity, installer_move_sequential_activity])
my_env.run()
5. Inspect results#
5.1 Inspect logs#
plot.get_log_dataframe(transporter01, [transport_activity])
Activity | Timestamp | ActivityState | container level | geometry | |
---|---|---|---|---|---|
0 | sailing empty | 1970-01-01 00:00:00.000000 | START | {'Cargo_1': 0, 'Cargo_2': 0} | POINT (4.18055556 52.18664444) |
1 | sailing empty | 1970-01-01 00:00:00.000000 | STOP | {'Cargo_1': 0, 'Cargo_2': 0} | POINT (4.18055556 52.18664444) |
2 | loading Cargo_1 | 1970-01-01 00:00:00.000000 | START | {'Cargo_1': 0, 'Cargo_2': 0} | POINT (4.18055556 52.18664444) |
3 | loading Cargo_1 | 1970-01-01 00:02:00.000000 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
4 | sailing filled | 1970-01-01 00:02:00.000000 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
5 | sailing filled | 1970-01-01 00:17:42.824591 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
6 | transfer Cargo_1 | 1970-01-01 00:17:42.824591 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
7 | transfer Cargo_1 | 1970-01-01 00:19:42.824591 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
8 | sailing empty | 1970-01-01 00:19:42.824591 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
9 | sailing empty | 1970-01-01 00:35:25.649183 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
10 | loading Cargo_1 | 1970-01-01 00:35:25.649183 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
11 | loading Cargo_1 | 1970-01-01 00:37:25.649183 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
12 | sailing filled | 1970-01-01 00:37:25.649183 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
13 | sailing filled | 1970-01-01 00:53:08.473774 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
14 | transfer Cargo_1 | 1970-01-01 00:53:08.473774 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
15 | transfer Cargo_1 | 1970-01-01 00:55:08.473774 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
16 | sailing empty | 1970-01-01 00:55:08.473774 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
17 | sailing empty | 1970-01-01 01:10:51.298365 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
18 | loading Cargo_1 | 1970-01-01 01:10:51.298365 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
19 | loading Cargo_1 | 1970-01-01 01:12:51.298365 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
20 | sailing filled | 1970-01-01 01:12:51.298365 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
21 | sailing filled | 1970-01-01 01:28:34.122956 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
22 | transfer Cargo_1 | 1970-01-01 01:28:34.122956 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
23 | transfer Cargo_1 | 1970-01-01 01:30:34.122956 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
24 | sailing empty | 1970-01-01 01:30:34.122956 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
25 | sailing empty | 1970-01-01 01:46:16.947548 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
26 | loading Cargo_1 | 1970-01-01 01:46:16.947548 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
27 | loading Cargo_1 | 1970-01-01 01:48:16.947548 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
28 | sailing filled | 1970-01-01 01:48:16.947548 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
29 | sailing filled | 1970-01-01 02:03:59.772139 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
30 | transfer Cargo_1 | 1970-01-01 02:03:59.772139 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
31 | transfer Cargo_1 | 1970-01-01 02:05:59.772139 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
32 | sailing empty | 1970-01-01 02:05:59.772139 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
33 | sailing empty | 1970-01-01 02:21:42.596730 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
34 | loading Cargo_1 | 1970-01-01 02:21:42.596730 | START | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.18055556 52.18664444) |
35 | loading Cargo_1 | 1970-01-01 02:23:42.596730 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
36 | sailing filled | 1970-01-01 02:23:42.596730 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.18055556 52.18664444) |
37 | sailing filled | 1970-01-01 02:39:25.421321 | STOP | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
38 | transfer Cargo_1 | 1970-01-01 02:39:25.421321 | START | {'Cargo_2': 0, 'Cargo_1': 1} | POINT (4.25222222 52.11428333) |
39 | transfer Cargo_1 | 1970-01-01 02:41:25.421321 | STOP | {'Cargo_2': 0, 'Cargo_1': 0} | POINT (4.25222222 52.11428333) |
5.2 Visualise gantt charts#
plot.get_gantt_chart([transport_activity, installer_move_sequential_activity])
plot.get_gantt_chart([transporter01, installer01, from_site, to_site],id_map=[transport_activity, installer_move_sequential_activity])
5.3 Visualise container volume developments#
fig = plot.get_step_chart([from_site, to_site])
fig = plot.get_step_chart([transporter01, installer01])