feeder concept: cutter + barges#
This notebook shows how to implement a basic feeder concept for a cutter suction dredge working with multiple barges.
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
import numpy as np
Site = type(
"Site",
(
core.Identifiable,
core.Log,
core.Locatable,
core.HasContainer,
core.HasResource,
),
{},
)
TransportProcessingResource = type(
"TransportProcessingResource",
(
core.ContainerDependentMovable,
core.Processor,
core.HasResource,
core.Identifiable,
core.Log,
),
{},
)
def run(NR_BARGES, total_amount):
simulation_start = 0
my_env = simpy.Environment(initial_time=simulation_start)
registry = {}
location_from_site = shapely.geometry.Point(4.18055556, 52.18664444)
location_to_site = shapely.geometry.Point(4.25222222, 52.11428333)
data_from_site = {"env": my_env,
"name": "from_site",
"geometry": location_from_site,
"capacity": total_amount,
"level": total_amount,
"nr_resources":1
}
from_site = Site(**data_from_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": total_amount,
"level": 0,
"nr_resources":4
}
to_site = Site(**data_to_site)
vessels = {}
for i in range(NR_BARGES):
vessels[f"vessel{i}"] = TransportProcessingResource(
env=my_env,
name=f"barge_{i}",
geometry=location_from_site,
capacity=10,
compute_v=lambda x: 10
)
cutter = TransportProcessingResource(
env=my_env,
name=f"cutter",
geometry=location_from_site,
capacity=10,
compute_v=lambda x: 10
)
vessels['cutter'] = cutter
activities = {}
for i in range(NR_BARGES):
amount = np.random.randint(4,6) # handle loading
duration=np.random.randint(2000,3000) # sailing and unloading
requested_resources={}
activities[f"activity{i}"] = model.WhileActivity(
env=my_env,
name=f"while_sequential_activity_subcycle{i}",
registry=registry,
sub_processes=[model.SequentialActivity(
env=my_env,
name=f"sequential_activity_subcycle{i}",
registry=registry,
sub_processes=[
model.BasicActivity(
env=my_env,
name=f"basic activity:"+vessels[f"vessel{i}"].name,
registry=registry,
duration=duration,
additional_logs=[vessels[f"vessel{i}"]],
),
model.MoveActivity(
env=my_env,
name=f"sailing empty:"+vessels[f"vessel{i}"].name,
registry=registry,
mover=vessels[f"vessel{i}"],
destination=from_site,
duration=duration,
),
model.ShiftAmountActivity(
env=my_env,
name=f"loading:"+vessels[f"vessel{i}"].name,
registry=registry,
processor=cutter,
origin=from_site,
destination=vessels[f"vessel{i}"],
amount=amount,
duration=500*amount,
requested_resources=requested_resources,
),
model.MoveActivity(
env=my_env,
name=f"sailing full:"+vessels[f"vessel{i}"].name,
registry=registry,
mover=vessels[f"vessel{i}"],
destination=to_site,
duration=duration,
),
model.ShiftAmountActivity(
env=my_env,
name=f"unloading:"+vessels[f"vessel{i}"].name,
registry=registry,
processor=vessels[f"vessel{i}"],
origin=vessels[f"vessel{i}"],
destination=to_site,
amount=amount,
duration=duration,
requested_resources=requested_resources,
),
],
)],
condition_event=[
{
"type": "container",
"concept": to_site,
"state": "full",
"id_":"default_reservations"
}
],
)
model.register_processes(list(activities.values()))
my_env.run()
return {
"vessels": vessels,
"activities":activities,
"from_site":from_site,
"to_site":to_site,
}
%%time
res = run(3,100)
vessels = res['vessels']
activities = res['activities']
cutter = vessels['cutter']
to_site = res['to_site']
from_site = res['from_site']
CPU times: user 43 ms, sys: 0 ns, total: 43 ms
Wall time: 42.3 ms
fig = plot.get_gantt_chart([*vessels.values()], id_map=[activities[x] for x in activities])
fig = plot.get_gantt_chart([from_site, to_site, cutter], id_map=[activities[x] for x in activities])
Plot only activities whose namespace (firt letters) matches load*
def expand(a, namespace):
n = len(namespace)
sa = []
if a.name[0:n]==namespace:
sa.append(a)
if hasattr(a, "sub_processes"):
for s in a.sub_processes:
if s.name[0:n]==namespace:
sa.append(s)
sa+=expand(s,namespace)
return sa
all_activities = []
for a in [*activities]:
all_activities+=expand(activities[a],'load')
all_activities
fig = plot.get_gantt_chart(all_activities)
fig = plot.get_step_chart([from_site, to_site, *vessels.values()])
data = []
for i in range(len(vessels.values()) - 1):
vessel = vessels[f'vessel{i}']
activity = activities[f'activity{i}']
sub_act = activity.sub_processes[0].sub_processes[-1]
log = pd.DataFrame(vessel.log)
nr_trips = len(log[(log.ActivityID == sub_act.id) & (log.ActivityState == "START")])
data.append({
'name':vessel.name,
'trips':nr_trips,
'theoretical production': (sub_act.amount / (4*sub_act.duration+ 5*sub_act.amount)),
'production':(nr_trips * sub_act.amount) / ((log.Timestamp.max() - log.Timestamp.min()).total_seconds()),
})
df = pd.DataFrame(data).sort_values(by=['production'],ascending=False)
df
name | trips | theoretical production | production | |
---|---|---|---|---|
0 | barge_0 | 8 | 0.000558 | 0.000410 |
1 | barge_1 | 8 | 0.000459 | 0.000371 |
2 | barge_2 | 7 | 0.000363 | 0.000292 |