Skip to content

Commit

Permalink
Minor bugs fixed and updated version info (minor increment)
Browse files Browse the repository at this point in the history
  • Loading branch information
markvankoningsveld committed Mar 9, 2020
1 parent 22c563b commit 3b1deea
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 82 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -2,6 +2,11 @@
Changelog
=========

Version 0.6.2
===========

- Updated the container code (minor bugs fixed)

Version 0.6.1
===========

Expand Down
5 changes: 5 additions & 0 deletions HISTORY.rst
Expand Up @@ -2,6 +2,11 @@
History
=======

v0.6.2 (2020-03-09)
------------------

* Updated the container code (minor bugs fixed)

v0.6.1 (2020-03-09)
------------------

Expand Down
2 changes: 1 addition & 1 deletion opentisim/__init__.py
Expand Up @@ -4,5 +4,5 @@

__author__ = """Mark van Koningsveld"""
__email__ = 'm.vankoningsveld@tudelft.nl'
__version__ = 'v.0.6.1'
__version__ = 'v0.6.2'

2 changes: 1 addition & 1 deletion opentisim/container_defaults.py
Expand Up @@ -692,4 +692,4 @@
"engineering": 0.05,
"miscellaneous": 0.15,
"electrical_works_fuel_terminal": 0.12,
"electrical_works_power_terminal": 0.15}
"electrical_works_power_terminal": 0.15}
66 changes: 26 additions & 40 deletions opentisim/container_objects.py
Expand Up @@ -82,10 +82,7 @@
{})

# The generic Commodity class
# - Maize
# - Soybean
# - Wheat
# - Laden
# - Container
Commodity = type('Commodity', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.commodity_properties_mixin,
container_mixins.hasscenario_properties_mixin),
Expand All @@ -100,67 +97,59 @@
# - RMG stack
# - SC stack
# - RS stack

Laden_Stack = type('Laden_Stack', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.laden_stack_properties_mixin,
container_mixins.hasopex_properties_mixin,
container_mixins.laden_stack_properties_mixin,
container_mixins.hasopex_properties_mixin,
container_mixins.hascapex_properties_mixin, # Give it capex info
container_mixins.hastriggers_properties_mixin, # Give it investment triggers
container_mixins.hasland_properties_mixin),
{})

# The generic stack equipment class
# - RTG
# - RMG
# - Straddle carrier
# - Reach stacker


Stack_Equipment = type('Stack_Equipment', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.stack_equipment_properties_mixin,
container_mixins.hascapex_properties_mixin, # Give it capex info
container_mixins.hasopex_properties_mixin, # Give it opex info
container_mixins.hastriggers_properties_mixin), # Give it investment triggers
container_mixins.hasland_properties_mixin),
{})



# Empty_stack class

Empty_Stack = type('Empty_Stack', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.empty_stack_properties_mixin,
container_mixins.hasopex_properties_mixin,
container_mixins.empty_stack_properties_mixin,
container_mixins.hasopex_properties_mixin,
container_mixins.hascapex_properties_mixin, # Give it capex info
container_mixins.hastriggers_properties_mixin, # Give it investment triggers
container_mixins.hasland_properties_mixin),
container_mixins.hasland_properties_mixin),
{})

# OOG_stack class

OOG_Stack = type('Empty_Stack', (container_mixins.identifiable_properties_mixin, # Give it a name
OOG_Stack = type('OOG_Stack', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.oog_stack_properties_mixin,
container_mixins.hasopex_properties_mixin,
container_mixins.oog_stack_properties_mixin,
container_mixins.hasopex_properties_mixin,
container_mixins.hascapex_properties_mixin, # Give it capex info
container_mixins.hastriggers_properties_mixin, # Give it investment triggers
container_mixins.hasland_properties_mixin),
container_mixins.hasland_properties_mixin),
{})

# The general Gates class
Gate = type('Gate', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.gate_properties_mixin,
container_mixins.gate_properties_mixin,
container_mixins.hascapex_properties_mixin, # Give it capex info
container_mixins.hasopex_properties_mixin, # Give it opex info
container_mixins.hastriggers_properties_mixin, # Give it investment triggers
container_mixins.hasland_properties_mixin),
container_mixins.hasland_properties_mixin),
{})

# The general Empty Container Handler (ECH) class
# The generic stack equipment class
# - RTG
# - RMG
# - Straddle carrier
# - Reach stacker
Stack_Equipment = type('Stack_Equipment', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.stack_equipment_properties_mixin,
container_mixins.hascapex_properties_mixin, # Give it capex info
container_mixins.hasopex_properties_mixin, # Give it opex info
container_mixins.hastriggers_properties_mixin), # Give it investment triggers
{})

# The general Empty Container Handler (ECH) class
Empty_Handler = type('Empty_Handler', (container_mixins.identifiable_properties_mixin, # Give it a name
container_mixins.history_properties_mixin,
container_mixins.empty_handler_properties_mixin,
Expand All @@ -169,9 +158,6 @@
container_mixins.hastriggers_properties_mixin), # Give it investment triggers
{})




# The general Vessel class
# - Handysize
# - Handymax
Expand Down
95 changes: 56 additions & 39 deletions opentisim/container_system.py
Expand Up @@ -26,13 +26,17 @@ class System:
- the transhipment ratio
"""

def __init__(self, startyear=2019, lifecycle=20, operational_hours=7500, debug=False, elements=[],
def __init__(self, terminal_name='Terminal', startyear=2019, lifecycle=20, operational_hours=7500, debug=False,
elements=[],
crane_type_defaults=container_defaults.sts_crane_data,
stack_equipment='rs', laden_stack='rs',
allowable_waiting_service_time_ratio_berth=0.1, allowable_berth_occupancy=0.6,
laden_perc=0.80, reefer_perc=0.1, empty_perc=0.05, oog_perc=0.05,
transhipment_ratio=0.69,
energy_price=0.17, fuel_price=1, land_price=0):
# identity
self.terminal_name = terminal_name

# time inputs
self.startyear = startyear
self.lifecycle = lifecycle
Expand Down Expand Up @@ -338,7 +342,6 @@ def berth_invest(self, year, fully_cellular, panamax, panamax_max, post_panamax_
quay_walls = len(core.find_elements(self, Quay_wall))
if berths > quay_walls:
# bug fixed, should only take the value of the vessels that actually come
print((not container_defaults.container_data['fully_cellular_perc'] == 0))
Ls_max = max([
int(not container_defaults.container_data['fully_cellular_perc'] == 0) * container_defaults.fully_cellular_data["LOA"],
int(not container_defaults.container_data['panamax_perc'] == 0) * container_defaults.panamax_data["LOA"],
Expand Down Expand Up @@ -438,12 +441,12 @@ def quay_invest(self, year, length, depth):

# add length and depth to the elements (useful for later reporting)
quay_wall.length = length
quay_wall.depth = depth
quay_wall.depth = depth # draught + max_sinkage + wave_motion + safety_margin
quay_wall.retaining_height = 2 * (depth + quay_wall.freeboard)

# - capex
# Todo: check this unit rate estimate
quay_wall.unit_rate = int(quay_wall.Gijt_constant * (2 * (depth + quay_wall.freeboard)) ** quay_wall.Gijt_coefficient)
quay_wall.unit_rate = int(quay_wall.Gijt_constant * quay_wall.retaining_height ** quay_wall.Gijt_coefficient)
mobilisation = int(max((length * quay_wall.unit_rate * quay_wall.mobilisation_perc), quay_wall.mobilisation_min))
apron_pavement = length * quay_wall.apron_width * quay_wall.apron_pavement
cost_of_land = length * quay_wall.apron_width * self.land_price
Expand Down Expand Up @@ -548,47 +551,45 @@ def horizontal_transport_invest(self, year):
tractor = Horizontal_Transport(**container_defaults.tractor_trailer_data)

# when the total number of online horizontal transporters < total number of transporters required by the cranes
if self.stack_equipment != 'sc':

while cranes_planned * tractor.required > hor_transport_planned:
# add a tractor to elements
if self.debug:
print(' *** add tractor trailer to elements')
tractor = Horizontal_Transport(**container_defaults.tractor_trailer_data)

# - capex
unit_rate = tractor.unit_rate
mobilisation = tractor.mobilisation
tractor.capex = int(unit_rate + mobilisation)
while cranes_planned * tractor.required > hor_transport_planned:
# add a tractor to elements
if self.debug:
print(' *** add tractor trailer to elements')
tractor = Horizontal_Transport(**container_defaults.tractor_trailer_data)

# - opex
# Todo: shouldn't the tractor also be insured?
tractor.maintenance = unit_rate * tractor.maintenance_perc
# - capex
unit_rate = tractor.unit_rate
mobilisation = tractor.mobilisation
tractor.capex = int(unit_rate + mobilisation)

# - labour
labour = Labour(**container_defaults.labour_data)
# Todo: check if the number of shifts is calculated properly
tractor.shift = tractor.crew * labour.daily_shifts
tractor.labour = tractor.shift * labour.blue_collar_salary
# - opex
# Todo: shouldn't the tractor also be insured?
tractor.maintenance = unit_rate * tractor.maintenance_perc

# apply proper timing for the crane to come online (in the same year as the latest Quay_wall)
# [element.year_online for element in core.find_elements(self, Quay_wall)]
# years_online = []
# for element in core.find_elements(self, Quay_wall):
# years_online.append(element.year_online)
years_online = [element.year_online for element in core.find_elements(self, Cyclic_Unloader)]
tractor.year_online = max([year + tractor.delivery_time, max(years_online)])
# - labour
labour = Labour(**container_defaults.labour_data)
# Todo: check if the number of shifts is calculated properly
tractor.shift = tractor.crew * labour.daily_shifts
tractor.labour = tractor.shift * labour.blue_collar_salary

# apply proper timing for the crane to come online (in the same year as the latest Quay_wall)
# [element.year_online for element in core.find_elements(self, Quay_wall)]
# years_online = []
# for element in core.find_elements(self, Quay_wall):
# years_online.append(element.year_online)
years_online = [element.year_online for element in core.find_elements(self, Cyclic_Unloader)]
tractor.year_online = max([year + tractor.delivery_time, max(years_online)])

# add cash flow information to tractor object in a dataframe
tractor = core.add_cashflow_data_to_element(self, tractor)
# add cash flow information to tractor object in a dataframe
tractor = core.add_cashflow_data_to_element(self, tractor)

self.elements.append(tractor)
self.elements.append(tractor)

hor_transport_planned += 1
hor_transport_planned += 1

if self.debug:
print(' a total of {} tractor trailers is online; {} tractor trailers still pending'.format(
hor_transport_online, hor_transport_planned - hor_transport_online))
if self.debug:
print(' a total of {} tractor trailers is online; {} tractor trailers still pending'.format(
hor_transport_online, hor_transport_planned - hor_transport_online))

def laden_reefer_stack_invest(self, year):
"""current strategy is to add stacks as soon as trigger is achieved
Expand Down Expand Up @@ -971,6 +972,10 @@ def stack_equipment_invest(self, year):
# add one to planned stack equipment (important for while loop)
stack_equipment_planned += 1

if self.debug:
print(' a total of {} stack equipment is online; {} stack equipment still pending'.format(
stack_equipment_online, stack_equipment_planned - stack_equipment_online))

def empty_handler_invest(self, year):
"""current strategy is to add empty hanlders as soon as a service trigger is achieved
- find out how many empty handlers are online
Expand All @@ -979,7 +984,14 @@ def empty_handler_invest(self, year):
- add empty handlers until service_trigger is no longer exceeded
"""
sts_cranes_planned = len(core.find_elements(self, Cyclic_Unloader))
empty_handlers_planned = len(core.find_elements(self, Empty_Handler))

empty_handlers_planned = 0
empty_handlers_online = 0
for element in self.elements:
if isinstance(element, Empty_Handler):
empty_handlers_planned += 1
if year >= element.year_online:
empty_handlers_online += 1

if self.debug:
print(' Empty handlers planned (@ start of year): {}'.format(empty_handlers_planned))
Expand Down Expand Up @@ -1019,6 +1031,11 @@ def empty_handler_invest(self, year):

empty_handlers_planned += 1

if self.debug:
print(' a total of {} empty handlers is online; {} empty handlers still pending'.format(
empty_handlers_online, empty_handlers_planned - empty_handlers_online))


def gate_invest(self, year):
"""current strategy is to add gates as soon as trigger is achieved
- find out how much gate capacity is online
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -69,6 +69,6 @@
test_suite="tests",
tests_require=tests_require,
url="https://github.com/TUDelft-CITG/OpenTISim",
version="v0.6.1",
version="v0.6.2",
zip_safe=False,
)

0 comments on commit 3b1deea

Please sign in to comment.