config

  1import os
  2import pandas as pd
  3
  4# set directory
  5directory = os.getcwd()  
  6
  7# set simulation IDs and run characteristics
  8WARMUP_ITERS = 1000  # Number of ships to ignore while calculating means, recommended: first 1,000
  9NUM_MONTHS = 6  # Number of months to run the simulation
 10SIMULATION_TIME = int(NUM_MONTHS*30*24) # Total time to run the simulation for, in hours
 11
 12LOG_NUM = 10
 13NUM_RUNS = 4  # How many unique replications of different seeds to conduct for a given run
 14NUM_CORES = 4  # How many CPU cores to run individual seeds on simultaneously (set depending on local hardware capabilities)
 15START_SEED = 100  # Initial random seed for the simulation
 16
 17# Cleans output result folders
 18DELETE_EVERYTHING = False # Cleans all existing result folders, including collated results (SAVE ALL DESIRED DATA PRIOR TO RUNNING AS TRUE)
 19DELETE_RESULTS_FOLDER = True  # Cleans the results folder only
 20
 21SCENARIO_NAME = "Base"  # Set to "Base" for base conditions, or set to "BottleneckDetection" for bottleneck analysis, or "BreakpointAnalysis" for breakpoint analysis
 22
 23# Set "what-if" scenarios. Set all as "False" for base conditions
 24MODEL_HURRICANE = False
 25SEVERE_HURRICANE = False  # If True, models a more severe hurricane with longer port closure and more resource damage
 26TROPICAL_STORM = False  # If True, models a tropical storm with shorter port closure and less resource damage
 27MODEL_FOG = True
 28EXPANDED_CHANNEL = False  
 29
 30if MODEL_HURRICANE == False:
 31    if SEVERE_HURRICANE == True or TROPICAL_STORM == True:
 32        raise ValueError("If MODEL_HURRICANE is False, both SEVERE_HURRICANE and TROPICAL_STORM must be False; update the config file.")
 33if MODEL_HURRICANE == True:
 34    if SEVERE_HURRICANE == False and TROPICAL_STORM == False:
 35        raise ValueError("If MODEL_HURRICANE is True, either SEVERE_HURRICANE or TROPICAL_STORM must be True; update the config file.")
 36
 37# Set truck and pipeline overrides to ensure terminal storage capacities remain
 38CTR_TRUCK_OVERRIDE = False # Set False if running bottleneck analysis; True for stable yard queue
 39LIQ_PIPELINE_OVERRIDE = False # Set False if running bottleneck analysis; True for stable yard queue
 40
 41########################################################################################
 42# The following variables have been calibrated for a simulation of the a random port   #
 43# Change with ACTUAL port data.                                                        #
 44########################################################################################
 45
 46if MODEL_FOG == True:
 47    INBOUND_CLOSED = [(1500, 1520), (1664, 1695), (1932, 1972)]
 48    OUTBOUND_CLOSED = [(1500, 1515), (1673, 1695),  (2002, 2023)]
 49    FOG_CLOSURES = []  # BOTH INBOUND AND OUTBOUND CLOSURES
 50else:
 51    INBOUND_CLOSED = []
 52    OUTBOUND_CLOSED = []
 53    FOG_CLOSURES = []
 54
 55if MODEL_HURRICANE == True:
 56    HURRICANE_START = int(30*1.5*24) # in hours from start of simulation 1.5 months
 57    if SEVERE_HURRICANE == False and TROPICAL_STORM == False:
 58        raise ValueError("If MODEL_HURRICANE is True, either SEVERE_HURRICANE or TROPICAL_STORM must be True; update the config file.")
 59else:
 60    HURRICANE_START = None
 61
 62# set as 1.0 for most cases, values change directly if running breakpoint analysis
 63ARRIVAL_INCREASE_FACTOR_CTR = 1.0
 64ARRIVAL_INCREASE_FACTOR_LIQ = 1.0
 65ARRIVAL_INCREASE_FACTOR_DRYBULK = 1.0
 66
 67ARRIVAL_INCREASE_FACTOR = ARRIVAL_INCREASE_FACTOR_CTR
 68
 69if ARRIVAL_INCREASE_FACTOR != 1.0:
 70    print(f"\n\nWARNING!: Arrival increase factor set to {ARRIVAL_INCREASE_FACTOR} for all cargo types.")
 71
 72ARRIVAL_INCREASE_FACTOR = round(ARRIVAL_INCREASE_FACTOR, 2)
 73
 74# percent of total vessel tonnage accounted for as vessel weight
 75NON_CARGO_DEAD_WEIGHT_PERCENT_CTR = 0.2
 76NON_CARGO_DEAD_WEIGHT_PERCENT_DK = 0.1
 77NON_CARGO_DEAD_WEIGHT_PERCENT_LIQ = 0.1
 78
 79# anchorage waiting times calibrated to each cargo type 
 80# These are unexplained wait times (additional waiting times account for factors not modelled
 81# in simulation explicitely. First run with 0 values then caliberate based on observed
 82# data and simulation outputs. 
 83ANCHORAGE_WAITING_CONTAINER = 0
 84ANCHORAGE_WAITING_LIQUID = 0
 85ANCHORAGE_WAITING_DRYBULK = 0
 86
 87# terminal efficiency times, used to extend the vessel time in port for each cargo type
 88# These are efficiency factors for each terminal. Should be between 0 and 1
 89# A Value of one means terminal is fully efficient and no delays.
 90# First run with 0 values then caliberate based on observed
 91# data and simulation outputs. 
 92CTR_TERMINAL_EFFICIENCY = 1.0
 93LIQ_TERMINAL_EFFICIENCY = 1.0
 94DRYBULK_TERMINAL_EFFICIENCY = 1.0
 95
 96# removes combined beam and draft restrictions if set to "True"
 97CHANNEL_SAFETWOWAY = False
 98
 99# set number of pilots and tugs
100# Dummy values, set as actual port values
101NUM_PILOTS_DAY = (50, 60)
102NUM_PILOTS_NIGHT = (20, 30)
103NUM_TUGBOATS = (50, 100)
104
105# set channel entrance and navigation times
106TIME_COMMON_CHANNEL = (2, 3)  # in hours 
107TIME_FOR_TUG_STEER = (0.2, 0.4)  # in hours
108TIME_FOR_UTURN = (0.2, 0.4)  # in hours
109
110# set min and max range for arriving truck wait times, in hours
111TRUCK_WAITING_TIME = (1/60, 5/60)
112
113# interarrival times derived from AIS data.
114# Look for Bathgate et al. (2026) for procedure to obtain these values.
115# Currently values set as dummy values. (All values in hours)
116mean_interarrival_time_container = 10 * 1/ARRIVAL_INCREASE_FACTOR_CTR
117mean_interarrival_time_gencargo = 5 * 1/ARRIVAL_INCREASE_FACTOR_DRYBULK
118mean_interarrival_time_tanker = 1 * 1/ARRIVAL_INCREASE_FACTOR_LIQ
119mean_interarrival_time_total = mean_interarrival_time_container + mean_interarrival_time_gencargo + mean_interarrival_time_tanker
120base_arrival_rate = 1/10 + 1/5 + 1/1
121
122# set truncation values for 
123max_interaarival_ctr = 100000000000000000
124max_interaarival_liq = 100000000000000000
125max_interaarival_drybulk = 100000000000000000
126
127min_interarrival_liquid = 0.0001
128
129# Set terminals with no truck or rail connections. 
130# Note: These overrides terminal data; Example shown below:
131# Example: TERMINALS_WITH_NO_TRUCKS = {"Liquid": [1]}
132TERMINALS_WITH_NO_TRUCKS = {"Liquid": [], "DryBulk": [], "Liquid": []}
133TERMINALS_WITH_NO_TRAINS = {"Container": [], "Liquid": [], "DryBulk": []}  
134
135# Rate for landside pipelines connection (these act as sorce or sink)
136# Note this is different from pipelines that connects to vessels.
137PIPELINE_RATE = 100  # cbm/timestep
138
139# Model the channel
140NUM_CHANNEL_SECTIONS = 10
141
142# Model portion after which wider ships are not allowed.
143# Helps in modelling channels that become narrower. 
144# certain channel segments might only accessible to smaller vessels, list the start terminal for these conditions here
145# Set as large number if not applicable
146NO_LARGE_SHIP_BEYOND_THIS_TERMINAL_CTR = 2
147NO_LARGE_SHIP_BEYOND_THIS_TERMINAL_LIQ = 10
148NO_LARGE_SHIP_BEYOND_THIS_TERMINAL_DRYBULK = 10
149
150# Set what beam determines when wider ships are not allowed 
151MAX_BEAM_SMALL_SHIP = 106
152
153# common liquid bulk cargo density conversion factors for more accurate cargo payload estimation
154LIQUID_CONVERSION_FACTORS = [
155    1.0,    # Water (1 ton = 1 CBM)
156    1.18,   # Crude oil (1 ton = 1.18 CBM)
157    1.16,   # Diesel (1 ton = 1.16 CBM)
158    1.38,   # Gasoline (1 ton = 1.38 CBM)
159    0.92,   # Liquid ammonia (1 ton = 0.92 CBM)
160    0.78,   # Molasses (1 ton = 0.78 CBM)
161    0.87,   # Vegetable oil (1 ton = 0.87 CBM)
162    1.11,   # Ethanol (1 ton = 1.11 CBM)
163    1.03,   # Jet fuel (1 ton = 1.03 CBM)
164    1.03,   # Kerosene (1 ton = 1.03 CBM)
165    1.22,   # LPG (1 ton = 1.22 CBM)
166    1.25    # LNG (1 ton = 1.25 CBM)
167]
168
169CONTAINER_CONVERSION_FACTORS = [
170    1/24,     # 20' container can carry 24 tons
171    1/33      # 40' container can carry 33 tons
172]
173
174# import terminal data from CSV in "inputs" folder
175df = pd.read_csv('./inputs/terminal_data.csv')
176
177# set daylight restriction hours
178# daylight hours are 7 AM till 7 PM (19:00)
179# hours for daylight restriction due to expanded channel are 4 AM till 9 PM (21:00)
180if EXPANDED_CHANNEL == True:
181    START_DAYLIGHT_RESTRICTION_HR = 4
182    STOP_DAYLIGHT_RESTRICTION_HR = 21
183else:
184    START_DAYLIGHT_RESTRICTION_HR = 7
185    STOP_DAYLIGHT_RESTRICTION_HR = 19
186
187# set channel dimensions (current or expanded)
188if EXPANDED_CHANNEL == True:
189    channel_dimensions = pd.read_csv(
190        './inputs/channel_dimensions_expanded.csv')
191else:
192    channel_dimensions = pd.read_csv('./inputs/channel_dimensions.csv')
193
194# read channel data from CSV in "inputs" folder
195dict_from_csv = channel_dimensions.to_dict(orient="index")
196CHANNEL_SECTION_DIMENSIONS = {list(value.values())[0]: tuple(
197    list(value.values())[1:]) for key, value in dict_from_csv.items()}
198LAST_SECTION_DICT = {cargo: dict(
199    zip(group['Terminal'], group['Segment'])) for cargo, group in df.groupby('Cargo')}
200BERTHS_CTR_TERMINAL = df[df['Cargo'] == 'Container']['Berths'].tolist()
201BERTHS_LIQ_TERMINAL = df[df['Cargo'] == 'Liquid']['Berths'].tolist()
202BERTH_DRYBULK_TERMINAL = df[df['Cargo'] == 'DryBulk']['Berths'].tolist()
203
204# conversion factors
205TIME_FACTOR = 60  # 1 hour = 60 minutes (Channel timestep is in minutes)
206
207# in hours, minimum spacing between entering inbound vessels (5/60 is 5 minutes)
208CHANNEL_ENTRY_SPACING = 5/60