OpenTNSim

Contents

OpenTNSim#

This page lists all functions and classes available in the OpenTNSim.model and OpenTNSim.core modules. For examples on how to use these submodules please check out the Examples page, information on installing OpenTNim can be found on the Installation page.

Submodules#

The main components are the Model module and the Core module. All of their components are listed below.

opentnsim.model module#

Vessel generator.

class opentnsim.model.Simulation(graph, simulation_start=datetime.datetime(2025, 8, 29, 14, 42, 0, 616810), simulation_duration=None, simulation_stop=None, hydrodynamic_data=None, vessel_speed_data=None, scenario=None)#

Bases: Identifiable

A class to generate vessels from a database

Parameters#

simulation_start: datetime

The start time of the simulation.

graph: networkx graph

The graph that is used for the simulation.

scenario:

scenario with vessels - should be coupled to the database

add_vessels(origin=None, destination=None, vessel=None, vessel_generator: VesselGenerator = None, fleet_distribution=None, arrival_distribution=1, arrival_process='Markovian')#

Make arrival process in the environment. Add one vessel on one input vessel, or with the vessel generator

Parameters#

vessel_generator: VesselGenerator

The vessel generator that is used to generate vessels. Optional. If not specified, the vessel should be specified. If specified, the vessel should be None, but origin, destination, arrival_distribution and arrival_process should be specified.

origin: str

The origin of the vessel. Must be specified if vessel_generator is specified.

destination: str

The destination of the vessel. Must be specified if vessel_generator is specified.

arrival_distribution: int or list

The amount of vessels that enter the simulation per hour. Must be specified if vessel_generator is specified. If int, it is the average number of vessels per hour over the entire day. If list, it is the average number of vessels per hour for each hour of the day. List must have length of 24 (one entry for each hour).

arrival_process: str

The process of arrivals. Must be specified if vessel_generator is specified. Choose between “Markovian” or “Uniform”.

vessel: Vessel

A vessel object with a route between origin and destination. Optional. If specified, the vessel_generator should be None, and origin, destination, arrival_distribution and arrival_process are ignored.

run(duration=86400)#

Run the simulation

duration: float

specify the duration of the simulation in seconds

class opentnsim.model.VesselGenerator(vessel_type, vessel_database, loaded=None, random_seed=3)#

Bases: object

A class to generate vessels from a database

Parameters#

vessel_type: class of mixins.

The type of vessel to be generated.

vessel_database: ??

The database from which the vessel is generated. Make sure all needed attributes for vessel_type are available in the database.

loaded: optional

whether or not the vessel is loaded. If True, the vessel is loaded. If “Random”, the vessel is randomly loaded or not (50% chance fully loaded, 50% chance empty). If not specified, the vessel is empty.

random_seed: int, optional

The random seed for generating vessels. The default is 3.

arrival_process(environment, origin, destination, arrival_distribution, scenario, arrival_process, fleet_distribution)#

Make arrival process in the simulation environment. Vessels with a route and between origin and destination are generated according to the arrival distribution. The route is calculated using the dijkstra algorithm.

Parameters#

environment: simpy environment

The environment in which the vessel is generated.

origin: str

The origin of the vessel.

destination: str

The destination of the vessel.

arrival_distribution: int or list

The amount of vessels that enter the simulation per hour. If int, it is the average number of vessels per hour over the entire day. If list, it is the average number of vessels per hour for each hour of the day. List must have length of 24 (one entry for each hour).

scenario: str

The scenario that is assigned to the generated vessel.

arrival_process: str

process of arrivals. choose between “Markovian” or “Uniform”.

generate(environment, vessel_name: str, fleet_distribution=None, scenario=None)#

Get a random vessel from self.database

Parameters#

environment: simpy environment

The environment in which the vessel is generated.

vessel_name: str

The name that is assigned to the generated vessel.

scenario: str, optional

The scenario of the generated vessel. If given, the vessel with this scenario is selected from the database.

opentnsim.core module#

class opentnsim.core.ContainerDependentMovable(compute_v, *args, **kwargs)#

Bases: Movable, HasContainer

Mixin class: ContainerDependentMovable class Used for objects that move with a speed dependent on the container level

Parameters#

compute_v: function

a function, given the fraction the container is filled (in [0,1]), returns the current speed

v: float

passed to Movable, speed of the object (in m/s)

geometry: shapely.geometry.Point

passed to Movable. point used to track its current location

node: str, optional

passed to Movable,

route: list, optional

passed to Movable,

complete_path: list, optional

passed to Movable,

Capacity: float

passed to HasContainer, the capacity of the container, which may either be continuous (like water) or discrete (like apples)

level: int, default=0

passed to HasContainer, level of the container at the beginning of the simulation

total_requested: int, default=0

passed to HasContainer, total amount that has been requested at the beginning of the simulation

Attributes#

compute_v: function

a function, given the fraction the container is filled (in [0,1]), returns the current speed

current_speed: float

the current speed of the vessel (in m/s), based on the filling degree of the container

property current_speed#

return the current speed of the vessel, based on the filling degree of the container

class opentnsim.core.ExtraMetadata(*args, **kwargs)#

Bases: object

Mixin class: store all leftover keyword arguments as metadata property (use as last mixin)

class opentnsim.core.HasContainer(capacity: float, level: float = 0, total_requested: float = 0, *args, **kwargs)#

Bases: SimpyObject

Mixin class: Something with a container, modelled as a storage capacity

Parameters#

capacity: float

the capacity of the container, which may either be continuous (like water) or discrete (like apples)

level: int, default=0

level of the container at the beginning of the simulation

total_requested: int, default=0

total amount that has been requested at the beginning of the simulation

args, kwargs:

passed to SimpyObject. Must at least contain parameter env: simpy.Environment.

Attributes#

container: simpy.Container

the container that is used to limit the amount that can be requested.

total_requested: int

total amount that has been requested.

property filling_degree#

return the filling degree of the container

property is_loaded#

Return if the container is loaded

property max_load#

return the maximum cargo to load

class opentnsim.core.HasLength(length: float, remaining_length: float = 0, *args, **kwargs)#

Bases: SimpyObject

Mixin class: Something with a length. The length is modelled as a storage capacity

Parameters#

length: float

length that can be requested

remaining_length: float, default=0

length that is still available at the beginning of the simulation.

args, kwargs:

passed to SimpyObject. Must at least contain parameter env: simpy.Environment.

Attributes#

length: simpy.Container

the container that is used to limit the length that can be requested.

pos_length: simpy.Container

the container that is used to limit the length that can be requested.

class opentnsim.core.HasLoad(H_e, H_f, T_e, T_f, filling_degree=0, *args, **kwargs)#

Bases: object

Mixin class with load dependent height (H) and draught (T). The filling degree (filling_degree: fraction) will interpolate between empty and full height and draught.

Parameters#

H_e: float

height of the vessel when empty

H_f: float

height of the vessel when full

T_e: float

draught of the vessel when empty

T_f: float

draught of the vessel when full

filling_degree: float, default=0

fraction of the vessel that is filled upon creation

property H#

Calculate current height based on filling degree

property T#

Calculate current draught based on filling degree

class opentnsim.core.HasResource(nr_resources: int = 1, priority: bool = False, *args, **kwargs)#

Bases: SimpyObject

Mixin class: Something that has a resource limitation, a resource request must be granted before the object can be used.

Parameters#

nr_resources: int, default=1

nr of requests that can be handled simultaneously, optional, default=1

priority: bool, default=False

if True, prioritized resources can be handled. optional, default=False.

args, kwargs:

passed to SimpyObject. Must at least contain parameter env: simpy.Environment.

Attributes#

resource: simpy.Resource or simpy.PriorityResource

the resource that is used to limit the nr of requests that can be handled simultaneously.

env: simpy.Environment

the simpy environment that is used to run the simulation.

class opentnsim.core.Identifiable(name: str, id: str | None = None, *args, **kwargs)#

Bases: object

OpenCLSim Identifiable with tags and a description.

Parameters#

name

a human readable name to be used in logs and charts

idUUID

a unique id generated with uuid

description

Text that can be used to describe a simulation object. Note that this field does not influence the simulation.

tags

List of tags that can be used to identify objects. Note that this field does not influence the simulation.

class opentnsim.core.Locatable(geometry: BaseGeometry, node: str | None = None, *args, **kwargs)#

Bases: object

Something with a geometry (geojson format). Can be a point as well as a polygon. The object can also be located on a graph (with a node). That requires the extra and optional node attribute. Make sure to also update the geometry when sailing over graphs.

Parameters#

geometry : Shapely Geometry that determines the position of an object. Coordinates are expected to be in wgs84 lon, lat. node: Optional string that locates an object on a graph.

get_state()#
is_at(locatable, tolerance=100)#
class opentnsim.core.Log(*args, **kwargs)#

Bases: SimpyObject

Log class to log the object activities.

get_state()#

empty instance of the get state function.

Add an empty instance of the get state function so that it is always available.

property log#

Return the log in log format (compatible with old log attribute).

The log can contain the following columns:

Timestamp: datetime ActivityID: str ActivityState: dict ObjectState: dict ActivityLabel: dict

log_entry(*args, **kwargs)#

Backward compatible log_entry. Calls the opentnsim variant.

log_entry_v0(log: str, t: float, value, geometry_log: Geometry)#

Log an entry (opentnsim version)

log_entry_v1(t: float, activity_id: str | int | None = None, activity_state: LogState = LogState.UNKNOWN, additional_state: dict | None = None, activity_label: dict | None = None)#

Log an entry (openclsim version).

Parameters#

tfloat

Timestamp in seconds since 1970 in utc.

activity_idUnion[str, int, None], optional

Identifier of the activity, by default None

activity_stateLogState, optional

State of the activity, by default LogState.UNKNOWN

additional_stateOptional[dict], optional

Additional state of the activity, by default None

activity_labelOptional[dict], optional

Label of the activity, by default None

class opentnsim.core.Movable(v: float, *args, **kwargs)#

Bases: Locatable, Routable, Log

Mixin class: Something can move.

Used for object that can move with a fixed speed

Parameters#

v: float

speed of the object (in m/s)

geometry: shapely.geometry.Point

passed to Locatable. point used to track its current location

node: str, optional

passed to Locatable,

route: list, optional

passed to Routable,

complete_path: list, optional

passed to Routable,

Attributes#

v: float

speed of the object (in m/s)

on_pass_edge_functions: list

list of functions to call when passing an edge

on_pass_node_functions: list

list of functions to call when passing a node

wsg84: pyproj.Geod

used for distance computation

req: simpy.Resource request

resource request for passing nodes and edges. saved for using resources over various nodes and edges.

resource: simpy.Resource

resource used for passing nodes and edges. saved for using resources over various nodes and edges.

Notes#

This class can handle a basic graph in env.graph. This will result in a simple simulation.

The class can also handle more complex simulations. For this, extra information is needed in the graph, such as: - Resources on nodes and edges, which can be requested and released.

  • Resources on nodes are saved in env.graph.nodes[node][“Resources”]

  • Resources on edges are saved in env.graph.edges[origin, destination][“Resources”].

  • Several edges and nodes can have the same resource, which is usefull when a segment can only be used by one vessel at a time.

  • When using a digraph, make sure to assign the same resource to both directions of the edge.

  • Current on edges, which can be used to compute the speed of the vessel.
    • Current on edges is saved in env.graph.edges[origin, destination][“Info”][“Current”].

    • Current can only be used in a directed graph (DiGraph).

    • Current is positive in the direction of the edge, and negative in the opposite direction.

    • Make sure to assign current to both directions of the edge in a digraph. (the negative and positive current)

  • Power information, which can be used to compute the speed of the vessel.
    • self must be a mixin of ConsumesEnergy.

    • self must have the attribute P_tot_given and must not be None.

    • general depth of fairway is saved in env.graph.edges[origin, destination][“Info”][“GeneralDepth”].

    • width of fairway is saved in env.graph.edges[origin, destination][“Info”][“Width”]. If not given, we use 150 m.

property current_speed#

return the current speed of the vessel

move()#

Moves vessel over the path defined by self.route.

Assumption is that self.path is in the right order - vessel moves from route[0] to route[-1].

Yields#

time it takes to travel the distance to the destination.

property next_edge#

Return the next edge on the route. based on self.position_on_route.

Returns#

tuple(str, str) or None

(origin, destination) of the next edge on the route.

pass_edge(origin, destination)#

pass an edge and call all on_pass_edge_functions.

Parameters#

origin: str

the origin node of the edge

destination: str

the destination node of the edge

Yields#

The time it takes to pass the edge.

pass_node(node)#

pass a node and call all on_pass_node_functions

Parameters#

node: str

the node to pass

Yields#

The time it takes to pass the node.

class opentnsim.core.Neighbours#

Bases: object

Mixin class: Can be added to a locatable object (list)

Parameters#

travel_to: list

list of locatables to which can be travelled

args, kwargs:

passed to SimpyObject. Must at least contain parameter env: simpy.Environment.

Attributes#

neighbours: list

list of locatables to which can be travelled.

class opentnsim.core.Routable(route, complete_path=None, *args, **kwargs)#

Bases: SimpyObject

Mixin class: Something with a route (networkx format)

Parameters#

route: list

list of node-IDs

complete_path: list, optional

???

args, kwargs:

passed to SimpyObject. Must at least contain parameter env: simpy.Environment.

Attributes#

route: list

list of node-IDs

complete_path: list, optional

???

position_on_route: int

index of position on the route

check_attributes()#

Check if all required attributes are set.

property graph#

Return the graph of the underlying environment.

If it’s multigraph cast to corresponding type If you want the multidigraph use the HasMultiGraph mixin

class opentnsim.core.Routeable(*args, **kwargs)#

Bases: Routable

Old name for Mixin class: renamed to Routable.

class opentnsim.core.SimpyObject(env, *args, **kwargs)#

Bases: object

General object which can be extended by any class requiring a simpy environment.

Parameters#

env

A simpy Environment

class opentnsim.core.VesselProperties(type, B, L, h_min=None, T=None, safety_margin=None, h_squat=None, payload=None, vessel_type=None, renewable_fuel_mass=None, renewable_fuel_volume=None, renewable_fuel_required_space=None, *args, **kwargs)#

Bases: object

Mixin class: Something that has vessel properties This mixin is updated to better accommodate the ConsumesEnergy mixin

Parameters#

type: str

can contain info on vessel type (avv class, cemt_class or other)

B: float

vessel width

L: float

vessel length

h_min: float, optional

vessel minimum water depth. The wather-depth can also be extracted from the network edges if they have the property [‘Info’][‘GeneralDepth’]

T: float, optional

actual draught. If not given, it will be calculated based on the filling degree (use mixin HasLoad) or based on the payload and vessel type

safety_margin: float, optional

the water area above the waterway bed reserved to prevent ship grounding due to ship squatting during sailing the value of safety margin depends on waterway bed material and ship types. For tanker vessel with rocky bed the safety margin is recommended as 0.3 m based on Van Dorsser et al. The value setting for safety margin depends on the risk attitude of the ship captain and shipping companies.

h_squat: boolean, optional

the water depth considering ship squatting while the ship moving (if False, squat is disabled, if True, squat is calculated)

payload: float, optional

cargo load [ton], the actual draught can be determined by knowing payload based on van Dorsser et al’s method. (https://www.researchgate.net/publication/344340126_The_effect_of_low_water_on_loading_capacity_of_inland_ships)

vessel_type: str, optional

vessel_type: vessel type can be selected from “Container”,”Dry_SH”,”Dry_DH”,”Barge”,”Tanker”. (“Dry_SH” means dry bulk single hull, “Dry_DH” means dry bulk double hull), based on van Dorsser et al’s paper. (https://www.researchgate.net/publication/344340126_The_effect_of_low_water_on_loading_capacity_of_inland_ships)

renewable_fuel_mass: float, optional

renewable fuel mass on board [kg]

renewable_fuel_volume: float, optional

renewable fuel volume on board [m3]

renewable_fuel_required_space: float, optional

renewable fuel required storage space (consider packaging factor) on board [m3]

property T#

Compute the actual draught. This will default to using the draught passed by the constructor. If it is None it will try to find one in the super class.

get_route(origin, destination, graph=None, minWidth=None, minHeight=None, minDepth=None, randomSeed=4)#

Calculate a path based on vessel restrictions restrictions are only applied if the graph has the attributes [‘Width’, ‘Height’, ‘Depth’]

Parameters#

origin: str

ID of the starting node

destination: str

ID of the destination node

graph: networkx.Graph, default = self.graph

The graph to use for the pathfinding

minWidth: float, default = 1.1 * self.B

Minimum width of the path

minHeight: float, default = 1.1 * self.H

Minimum height of the path

minDepth: float, default = 1.1 * self.T

Minimum depth of the path

randomSeed: int, default = 4

Seed for the random number generator

property h_min#

get the minimum water depth. if not given, h_min is the minimal water depth of the graph..

opentnsim.energy module#

class opentnsim.energy.ConsumesEnergy(P_installed, L_w, C_year=None, current_year=None, bulbous_bow=False, karpov_correction=False, P_hotel_perc=0.05, P_hotel=None, P_tot_given=None, nu=1e-06, rho=1000, g=9.81, x=2, D_s=1.4, eta_o=0.4, eta_r=1.0, eta_t=0.98, eta_g=0.96, c_stern=0, C_BB=0.2, C_B=0.85, one_k2=2.5, *args, **kwargs)#

Bases: object

Mixin class: Something that consumes energy.

Parameters#

P_installedfloat

Installed engine power in kilowatts (kW).

P_tot_givenfloat

Total power set by captain (includes hotel power). When P_tot_given > P_installed; P_tot_given=P_installed.

karpov_correctionbool, optional

If True, apply Karpovs correction for velocity under the vessel, if False, use the speed to water.

bulbous_bowbool, optional

Indicates if the ship has a bulbous bow. Inland ships generally do not have a bulbous bow, hence the default is False. If a ship has a bulbous bow, set to True.

L_wint

Weight class of the ship depending on carrying capacity. Classes: L1 (=1), L2 (=2), L3 (=3).

current_yearint

The current year.

nufloat

Kinematic viscosity in square meters per second (m^2/s).

rhofloat

Density of the surrounding water in kilograms per cubic meter (kg/m^3).

gfloat

Gravitational acceleration in meters per second squared (m/s^2).

xint

Number of propellers.

eta_ofloat

Open water efficiency of the propeller.

eta_rfloat

Relative rotative efficiency.

eta_tfloat

Transmission efficiency.

eta_gfloat

Gearing efficiency.

c_sternfloat

Determines the shape of the afterbody.

C_BBfloat

Breadth coefficient of the bulbous bow, set to 0.2 according to the paper of Kracht (1970), https://doi.org/10.5957/jsr.1970.14.1.1.

C_Bfloat, optional

Block coefficient (‘fullness’), default to 0.85.

one_k2float

Appendage resistance factor (1+k2).

C_yearint

Construction year of the engine.

SFC_general()#

Specific Fuel Consumption (SFC) is calculated by energy density and energy conversion efficiency. The SFC calculation equation, SFC = 1 / (energy density * energy conversion efficiency), can be found in the paper of Kim et al (2020)(A Preliminary Study on an Alternative Ship Propulsion System Fueled by Ammonia: Environmental and Economic Assessments, https://doi.org/10.3390/jmse8030183).

for diesel SFC, there are 3 kinds of general diesel SFC - SFC_diesel_ICE_mass, calculated by net diesel gravimetric density and ICE energy-power system efficiency, without considering engine performence variation due to engine ages - SFC_diesel_ICE_vol, calculated by net diesel volumetric density and ICE energy-power system efficiency, without considering engine performence variation due to engine ages - SFC_diesel_C_year, a group of SFC considering ICE engine performence variation due to engine ages (C_year), based on TNO (2019)

Please note: later on a correction factor has to be applied to get the total SFC

calculate_SFC_final(v, h_0)#

The final SFC is computed by multiplying the general SFC by the partial engine load correction factor.

The calculation of final SFC below includes - the final SFC of LH2, eLNG, eMethanol, eNH3 in mass and volume while using Fuel Cell Engine (PEMFC, SOFC) - the final SFC of eLNG, eMethanol, eNH3 in mass and volume while using Internal Combustion Engine - the final SFC of diesel in mass and volume while using Internal Combustion Engine - the final SFC of battery in mass and volume while use battery-electric power system

calculate_appendage_resistance(v)#

Appendage resistance

  • 3rd resistance component defined by Holtrop and Mennen (1982)

  • Appendages (like a rudder, shafts, skeg) result in additional frictional resistance

calculate_diesel_use_g_m(v)#

Total diesel fuel use in g/m:

  • The total fuel use in g/m can be computed by total fuel use in g (P_tot * delta_t * self.total_factor_) divided by the sailing distance (v * delt_t)

calculate_diesel_use_g_s()#

Total diesel fuel use in g/s:

  • The total fuel use in g/s can be computed by total emission in g (P_tot * delta_t * self.total_factor_) diveded by the sailing duration (delt_t)

calculate_emission_factors_total(v, h_0)#

Total emission factors:

  • The total emission factors can be computed by multiplying the general emission factor by the correction factor

calculate_emission_rates_g_m(v)#

CO2, PM10, NOX emission rates in g/m:

  • The CO2, PM10, NOX emission rates in g/m can be computed by total fuel use in g (P_tot * delta_t * self.total_factor_) diveded by the sailing distance (v * delt_t)

calculate_emission_rates_g_s()#

CO2, PM10, NOX emission rates in g/s:

  • The CO2, PM10, NOX emission rates in g/s can be computed by total fuel use in g (P_tot * delta_t * self.total_factor_) diveded by the sailing duration (delt_t)

calculate_engine_age()#

Calculate the age of the engine based on the weight class of the ship (L_w).

The age is drawn randomly from a Weibull distribution with parameters k and lmb, which depend on the weight class of the ship. The year of construction is computed from the current year of the simulation and the age of the engine.

Notes#

Uses self.L_w and self.year to compute the age and construction year of the engine. This method sets attributes self.age and self.C_year.

calculate_frictional_resistance(v, h_0)#

Frictional resistance

  • 1st resistance component defined by Holtrop and Mennen (1982)

  • A modification to the original friction line is applied, based on literature of Zeng (2018), to account for shallow water effects

calculate_h_squat(v, h_0, width=150)#

Calculate the water depth in case h_squat is set to True

The amount of water under the keel is calculated h_0 - T. When h_squat is set to True, we estimate a max_sinkage that is subtracted from h_0. This values is returned as h_squat for further calculation.

calculate_max_sinkage(v, h_0, width=150)#

Calculate the maximum sinkage of a moving ship

the calculation equation is described in Barrass, B. & Derrett, R.’s book (2006), Ship Stability for Masters and Mates, chapter 42. https://doi.org/10.1016/B978-0-08-097093-6.00042-6

some explanation for the variables in the equation: - h_0: water depth - v: ship velocity relative to the water - width: river width, default to 150

calculate_properties()#

Calculate a number of basic vessel properties

calculate_residual_resistance(V_2, h_0)#

Residual resistance terms

  • Holtrop and Mennen (1982) defined three residual resistance terms:

    1. Resistance due to immersed transom (R_TR), Karpov corrected velocity V2 is used

    1. Resistance due to model-ship correlation (R_A), Karpov corrected velocity V2 is used

    1. Resistance due to the bulbous bow (R_B), Karpov corrected velocity V2 is used

calculate_total_power_required(v, h_0)#

Total required power:

  • The total required power is the sum of the power for systems on board (P_hotel) + power required for propulsion

  • The power required for propulsion depends on the calculated resistance

Output: - P_propulsion: required power for propulsion, equals to P_d (Delivered Horse Power) - P_tot: required power for propulsion and hotelling - P_given: the power given by the engine to the ship (for propulsion and hotelling), which is the actual power

the ship uses

Note: In this version, we define the propulsion power as P_d (Delivered Horse Power) rather than P_b (Brake Horse Power). The reason we choose P_d as propulsion power is to prevent double use of the same power efficiencies. The details are 1) The P_b calculation involves gearing efficiency and transmission efficiency already while P_d not. 2) P_d is the power delivered to propellers. 3) To estimate the renewable fuel use, we will involve “energy conversion efficiencies” later in the

calculation.

The ‘energy conversion efficiencies’ for renewable fuel powered vessels are commonly measured/given as a whole covering the engine power systems, includes different engine (such as fuel cell engine, battery engine, internal combustion engine, hybrid engine) efficiencies, and corresponding gearbox efficiencies, AC/DC converter efficiencies, excludes the efficiency items of propellers. Therefore, to align with the later use of “energy conversion efficiencies” for fuel use estimation and prevent double use of some power efficiencies such as gearing efficiency, here we choose P_d as propulsion power.

calculate_total_resistance(v, h_0)#

Total resistance:

The total resistance is the sum of all resistance components (Holtrop and Mennen, 1982)

calculate_viscous_resistance()#

Viscous resistance

  • 2nd resistance component defined by Holtrop and Mennen (1982)

  • Form factor (1 + k1) has to be multiplied by the frictional resistance R_f, to account for the effect of viscosity

calculate_wave_resistance(V_2, h_0)#

Wave resistance

  • 4th resistance component defined by Holtrop and Mennen (1982)

  • When the speed or the vessel size increases, the wave making resistance increases

  • In shallow water, the wave resistance shows an asymptotical behaviour by reaching the critical speed

correction_factors(v, h_0)#

Partial engine load correction factors (C_partial_load):

  • The correction factors have to be multiplied by the general emission factors (or general SFC), to get the total emission factors (or final SFC)

  • The correction factor takes into account the effect of the partial engine load

  • When the partial engine load is low, the correction factors for ICE engine are higher (ICE engine is less efficient at lower enegine load)

  • the correction factors for emissions and diesel fuel in ICE engine are based on literature TNO (2019)

  • For fuel cell enegines(PEMFC & SOFC), the correction factors are lower when the partial engine load is low (fuel cell enegine is more efficient at lower enegine load)

  • the correction factors for renewable fuels used in fuel cell engine are based on literature Kim et al (2020) (A Preliminary Study on an Alternative Ship Propulsion System Fueled by Ammonia: Environmental and Economic Assessments, https://doi.org/10.3390/jmse8030183)

emission_factors_general()#

General emission factors:

This function computes general emission factors, based on construction year of the engine. - Based on literature TNO (2019)

Please note: later on a correction factor has to be applied to get the total emission factor

energy_conversion_efficiency()#

energy efficiencies for combinations of different energy source and energy-power conversion systems, including engine and power plant, excluding propellers. This will be used for calculating SFC later.

  • Eeff_FuelCell: the efficiency of the fuel cell energy conversion system on board, includes fuel cells, AC/DC converter, electric motor and gearbox. Generally this value is between 40% - 60%, here we use 45%.

  • Eeff_ICE: the efficiency of the Internal Combustion Engine (ICE) energy conversion system on board, includes ICE and gearbox. This value is approximately 35%.

  • Eeff_Battery: the efficiency of the battery energy conversion system on board. Batteries use 80% capacity to prolong life cycle, and lose efficiency in AC/DC converter, electric motor. Generally this value is between 70% - 95%, here we use 80 %.

data source: Marin report 2019, Energietransitie emissieloze binnenvaart, vooronderzoek ontwerpaspecten, systeem configuraties.(Energy transition zero-emission inland shipping, preliminary research on design aspects, system configurations) add other ref

energy_density()#

net energy density of diesel and renewable energy sources. This will be used for calculating SFC later.

  • Edens_xx_mass: net gravimetric energy density, which is the amount of energy stored in a given energy source in mass [kWh/kg].

  • Edens_xx_vol: net volumetric energy density, which is the amount of energy stored in a given energy source in volume [kWh/m3].

Data source: Table 3-2 from Marin report 2019, Energietransitie emissieloze binnenvaart, vooronderzoek ontwerpaspecten, systeem configuraties.(Energy transition zero-emission inland shipping, preliminary research on design aspects, system configurations

Note: net energy density can be used for calculate fuel consumption in mass and volume, but for required energy source storage space determination, the packaging factors of different energy sources also need to be considered.

karpov(v, h_0)#

Intermediate calculation: Karpov

  • The Karpov method computes a velocity correction that accounts for limited water depth (corrected velocity V2, expressed as “Vs + delta_V” in the paper), but it also can be used for deeper water depth (h_0 / T >= 9.5).

  • V2 has to be implemented in the wave resistance (R_W) and the residual resistance terms (R_res: R_TR, R_A, R_B)

class opentnsim.energy.EnergyCalculation(FG, vessel, *args, **kwargs)#

Bases: object

Add information on energy use and effects on energy use.

calculate_energy_consumption()#

Calculation of energy consumption based on total time in system and properties

opentnsim.energy.karpov_smooth_curves()#

read correction factor from package directory

opentnsim.energy.load_partial_engine_load_correction_factors()#

read correction factor from package directory

Module contents#