single_run_process + sub-cycles#
The simulation takes a number of sub_processes, grouped in a SequentialActivity, that is executed while a stop condition is not yet met. The example is basically a single_run_process, but now the loading and unloading steps are made up of subcycles that are executed a fixed number of times.
For this example we work with the following sub processes:
pre cycle activity
sailing empty
repeat loading 5 times
pre loading activity
loading
post loading activity
sailing full
repeat unloading 5 times
pre unloading activity
unloading
post unloading activity
post cycle activity
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.HasContainer,
core.HasResource,
),
{},
)
# create a TransportProcessingResource object based on desired mixin classes
TransportProcessingResource = type(
"TransportProcessingResource",
(
core.ContainerDependentMovable,
core.Processor,
core.HasResource,
core.LoadingFunction,
core.UnloadingFunction,
core.Identifiable,
core.Log,
),
{},
)
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,
"capacity": 100,
"level": 50
}
# 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,
"capacity": 50,
"level": 0
}
# instantiate to_site
to_site = Site(**data_to_site)
3.2. Create vessel object(s)#
# prepare input data for vessel_01
data_vessel01 = {"env": my_env,
"name": "vessel01",
"geometry": location_from_site,
"loading_rate": 0.00001,
"unloading_rate": 0.00001,
"capacity": 5,
"compute_v": lambda x: 10
}
# instantiate vessel_01
vessel01 = TransportProcessingResource(**data_vessel01)
3.3 Create activity/activities#
# initialise registry
registry = {}
# create a list of the sub processes: loading
sub_processes_loading =[
model.BasicActivity(
env=my_env,
name="pre loading activity",
registry=registry,
duration=100,
additional_logs=[vessel01],
),
model.ShiftAmountActivity(
env=my_env,
name="loading",
registry=registry,
processor=vessel01,
origin=from_site,
destination=vessel01,
amount=1,
duration=1000,
),
model.BasicActivity(
env=my_env,
name="post loading activity",
registry=registry,
duration=100,
additional_logs=[vessel01],
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity_loading = model.SequentialActivity(
env=my_env,
name="sequential_activity_loading_subcycle",
registry=registry,
sub_processes=sub_processes_loading,
)
# create a repeat activity that executes the 'sequential activity' a fixed number of times
repeat_loading_activity = model.RepeatActivity(
env=my_env,
name="repeat_sequential_activity_loading_subcycle",
registry=registry,
sub_processes=[sequential_activity_loading],
repetitions=5
)
# create a list of the sub processes: unloading
sub_processes_unloading =[
model.BasicActivity(
env=my_env,
name="pre unloading activity",
registry=registry,
duration=100,
additional_logs=[vessel01],
),
model.ShiftAmountActivity(
env=my_env,
name="unloading",
registry=registry,
processor=vessel01,
origin=vessel01,
destination=to_site,
amount=1,
duration=1000,
),
model.BasicActivity(
env=my_env,
name="post unloading activity",
registry=registry,
duration=100,
additional_logs=[vessel01],
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity_unloading = model.SequentialActivity(
env=my_env,
name="sequential_activity_unloading_subcycle",
registry=registry,
sub_processes=sub_processes_unloading,
)
# create a repeat activity that executes the 'sequential activity' a fixed number of times
repeat_unloading_activity = model.RepeatActivity(
env=my_env,
name="repeat_sequential_activity_unloading_subcycle",
registry=registry,
sub_processes=[sequential_activity_unloading],
repetitions=5
)
# create a list of the sub processes: cycle
sub_processes = [
model.BasicActivity(
env=my_env,
name="pre cycle activity",
registry=registry,
duration=100,
additional_logs=[vessel01],
),
model.MoveActivity(
env=my_env,
name="sailing empty",
registry=registry,
mover=vessel01,
destination=from_site,
duration=500,
),
repeat_loading_activity,
model.MoveActivity(
env=my_env,
name="sailing full",
registry=registry,
mover=vessel01,
duration=500,
destination=to_site,
),
repeat_unloading_activity,
model.BasicActivity(
env=my_env,
name="post cycle activity",
registry=registry,
duration=100,
additional_logs=[vessel01],
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity = model.SequentialActivity(
env=my_env,
name="sequential_activity_subcycle",
registry=registry,
sub_processes=sub_processes,
)
# create a while activity that executes the 'sequential activity' while the stop condition is not triggered
while_activity = model.WhileActivity(
env=my_env,
name="while_sequential_activity_subcycle",
registry=registry,
sub_processes=[sequential_activity],
condition_event=[{"type": "container", "concept": to_site, "state": "full"}],
)
4. Register processes and run simpy#
model.register_processes([while_activity])
my_env.run()
5. Inspect results#
5.1 Inspect logs#
plot.get_log_dataframe(vessel01, [while_activity])
Activity | Timestamp | ActivityState | container level | geometry | type | ref | |
---|---|---|---|---|---|---|---|
0 | pre cycle activity | 1970-01-01 00:00:00 | START | 0.0 | POINT (4.18055556 52.18664444) | additional log | 682d457f-8bf6-416d-92c8-d60e605295fa |
1 | pre cycle activity | 1970-01-01 00:01:40 | STOP | 0.0 | POINT (4.18055556 52.18664444) | additional log | 682d457f-8bf6-416d-92c8-d60e605295fa |
2 | sailing empty | 1970-01-01 00:01:40 | START | 0.0 | POINT (4.18055556 52.18664444) | NaN | NaN |
3 | sailing empty | 1970-01-01 00:10:00 | STOP | 0.0 | POINT (4.18055556 52.18664444) | NaN | NaN |
4 | pre loading activity | 1970-01-01 00:10:00 | START | 0.0 | POINT (4.18055556 52.18664444) | additional log | 5dd67294-ffd0-408d-ae19-d0819b527d78 |
... | ... | ... | ... | ... | ... | ... | ... |
675 | unloading | 1970-01-02 12:36:40 | STOP | 0.0 | POINT (4.25222222 52.11428333) | NaN | NaN |
676 | post unloading activity | 1970-01-02 12:36:40 | START | 0.0 | POINT (4.25222222 52.11428333) | additional log | 0cfa8ee5-791d-4d8e-94dc-af833b72bb63 |
677 | post unloading activity | 1970-01-02 12:38:20 | STOP | 0.0 | POINT (4.25222222 52.11428333) | additional log | 0cfa8ee5-791d-4d8e-94dc-af833b72bb63 |
678 | post cycle activity | 1970-01-02 12:38:20 | START | 0.0 | POINT (4.25222222 52.11428333) | additional log | 9800ac61-7dfd-41e8-855a-3d4ad45b21ce |
679 | post cycle activity | 1970-01-02 12:40:00 | STOP | 0.0 | POINT (4.25222222 52.11428333) | additional log | 9800ac61-7dfd-41e8-855a-3d4ad45b21ce |
680 rows × 7 columns
5.2 Visualise gantt charts#
plot.get_gantt_chart([while_activity, sequential_activity, *sub_processes])
plot.get_gantt_chart([vessel01, from_site, to_site],id_map=[while_activity])
5.3 Visualise container volume developments#
fig = plot.get_step_chart([vessel01, from_site, to_site])