Tanks Module

The Tanks module provides functionality for modeling fluid tanks in vessels, including volume calculations, fill level management, and free surface effects.

Tank Class

class pynavaltoolbox.tanks.Tank(file_path: str, fluid_density: float = 1025.0, fill_level: float = 0.0, name: str | None = None)[source]

Bases: object

Represents a tank (reservoir, cuve) with fluid management capabilities.

A tank is defined by a 3D geometry (STL or VTK file), a fluid density, and a fill level. The class calculates fluid mass, center of gravity, and free surface effects based on the current fill state.

polydata

The VTK polydata representing the tank mesh.

Type:

vtk.vtkPolyData

file_path

Path to the original geometry file.

Type:

str

fluid_density

Density of the fluid in kg/m³.

Type:

float

name

Optional name for the tank.

Type:

str

Examples

>>> tank = Tank("fuel_tank.stl", fluid_density=850.0)
>>> tank.set_fill_level(50, unit='percent')
>>> print(f"Fluid mass: {tank.fluid_mass:.2f} kg")
>>> print(f"Free surface moment: {tank.free_surface_moment_t:.4f} m⁴")
WATER_DENSITY = 1025.0
__init__(file_path: str, fluid_density: float = 1025.0, fill_level: float = 0.0, name: str | None = None)[source]

Initialize a Tank by loading geometry from an STL or VTK file.

Parameters:
  • file_path (str) – Path to the STL or VTK file defining the tank geometry.

  • fluid_density (float, optional) – Density of the fluid in kg/m³. Default is 1025.0 (seawater).

  • fill_level (float, optional) – Initial fill level as a fraction (0.0 to 1.0). Default is 0.0.

  • name (str, optional) – Name for the tank. If None, uses the filename stem.

Raises:
classmethod from_box(x_min: float, x_max: float, y_min: float, y_max: float, z_min: float, z_max: float, fluid_density: float = 1025.0, fill_level: float = 0.0, name: str = 'BoxTank') Tank[source]

Create a Tank from parallelepiped (box) dimensions.

This is an alternative constructor for when no STL/VTK file is available. Creates a box-shaped tank from min/max coordinates.

Parameters:
  • x_min (float) – Minimum X coordinate (longitudinal, aft) in meters.

  • x_max (float) – Maximum X coordinate (longitudinal, forward) in meters.

  • y_min (float) – Minimum Y coordinate (transverse, port) in meters.

  • y_max (float) – Maximum Y coordinate (transverse, starboard) in meters.

  • z_min (float) – Minimum Z coordinate (vertical, bottom) in meters.

  • z_max (float) – Maximum Z coordinate (vertical, top) in meters.

  • fluid_density (float, optional) – Density of the fluid in kg/m³. Default is 1025.0 (seawater).

  • fill_level (float, optional) – Initial fill level as a fraction (0.0 to 1.0). Default is 0.0.

  • name (str, optional) – Name for the tank. Default is “BoxTank”.

Returns:

A new Tank instance with box geometry.

Return type:

Tank

Raises:

ValueError – If min values are greater than or equal to max values.

Examples

>>> tank = Tank.from_box(
...     x_min=10.0, x_max=15.0,
...     y_min=-2.0, y_max=2.0,
...     z_min=0.0, z_max=3.0,
...     fluid_density=850.0,
...     name="FuelTank1"
... )
>>> tank.set_fill_level(50, unit='percent')
>>> print(f"Volume: {tank.total_volume:.2f} m³")  # 5×4×3 = 60 m³
classmethod from_box_hull_intersection(hull, x_min: float, x_max: float, y_min: float, y_max: float, z_min: float, z_max: float, fluid_density: float = 1025.0, fill_level: float = 0.0, name: str = 'HullTank') Tank[source]

Create a Tank as the intersection of a box with a hull geometry.

This allows creating tanks that follow the shape of the hull, for example a bottom tank that follows the hull’s curved bottom.

Parameters:
  • hull (Hull) – The hull geometry to intersect with. Can be a Hull object or any object with a polydata attribute.

  • x_min (float) – Minimum X coordinate (longitudinal) in meters.

  • x_max (float) – Maximum X coordinate (longitudinal) in meters.

  • y_min (float) – Minimum Y coordinate (transverse) in meters.

  • y_max (float) – Maximum Y coordinate (transverse) in meters.

  • z_min (float) – Minimum Z coordinate (vertical) in meters.

  • z_max (float) – Maximum Z coordinate (vertical) in meters.

  • fluid_density (float, optional) – Density of the fluid in kg/m³. Default is 1025.0 (seawater).

  • fill_level (float, optional) – Initial fill level as a fraction (0.0 to 1.0). Default is 0.0.

  • name (str, optional) – Name for the tank. Default is “HullTank”.

Returns:

A new Tank instance with geometry that is the intersection of the box and hull.

Return type:

Tank

Raises:

ValueError – If dimensions are invalid or intersection results in empty geometry.

Examples

>>> from pynavaltoolbox import Hull
>>> from pynavaltoolbox.tanks import Tank
>>> hull = Hull("ship.stl")
>>> # Create a double-bottom tank that follows the hull shape
>>> tank = Tank.from_box_hull_intersection(
...     hull,
...     x_min=20.0, x_max=40.0,   # 20m section of hull
...     y_min=-10.0, y_max=10.0,  # Full beam
...     z_min=0.0, z_max=2.0,     # 2m from keel
...     fluid_density=1025.0,
...     name="DoubleBottom1"
... )
property total_volume: float

Total capacity of the tank in m³.

property fill_level: float

Current fill level as a fraction (0.0 to 1.0).

property fill_percent: float

Current fill level as a percentage (0 to 100).

property fill_volume: float

Current filled volume in m³.

property fluid_mass: float

Mass of fluid in the tank in kg.

property center_of_gravity: ndarray

Center of gravity of the fluid [x, y, z] in meters.

Returns zeros if tank is empty.

property free_surface_moment_t: float

Transverse free surface moment (I_t) in m⁴.

This is the second moment of area of the free surface about its centroidal axis parallel to the longitudinal axis. Returns 0 if tank is empty or full (no free surface).

property free_surface_moment_l: float

Longitudinal free surface moment (I_l) in m⁴.

This is the second moment of area of the free surface about its centroidal axis parallel to the transverse axis. Returns 0 if tank is empty or full (no free surface).

property free_surface_correction_t: float

Transverse free surface correction in m⁴.

This is I_t × (ρ_fluid / ρ_water), used in the formula: GG’ = FSC / Δ (where Δ is vessel displacement mass).

property free_surface_correction_l: float

Longitudinal free surface correction in m⁴.

This is I_l × (ρ_fluid / ρ_water), used in the formula: GG’ = FSC / Δ (where Δ is vessel displacement mass).

set_fill_level(level: float, unit: str = 'percent') None[source]

Set the fill level of the tank.

Parameters:
  • level (float) – Fill level value.

  • unit (str, optional) – Unit of the level value: - ‘percent’: 0 to 100 - ‘fraction’: 0.0 to 1.0 - ‘m3’ or ‘volume’: absolute volume in m³

Raises:

ValueError – If the unit is not recognized or value is out of bounds.

get_bounds() Tuple[float, float, float, float, float, float][source]

Return the bounding box of the tank geometry.

Returns:

(xmin, xmax, ymin, ymax, zmin, zmax)

Return type:

tuple

get_state() TankState[source]

Get the current state of the tank.

Returns:

Dataclass containing all tank state information.

Return type:

TankState

__repr__() str[source]

String representation of the tank.

TankState Dataclass

class pynavaltoolbox.tanks.TankState(fill_level_percent: float, fill_volume: float, fluid_mass: float, center_of_gravity: ndarray, free_surface_moment_t: float, free_surface_moment_l: float, free_surface_correction_t: float, free_surface_correction_l: float)[source]

Stores the current state of a tank.

fill_level_percent

Fill level as a percentage (0-100).

Type:

float

fill_volume

Volume of fluid in the tank in m³.

Type:

float

fluid_mass

Mass of fluid in the tank in kg.

Type:

float

center_of_gravity

Center of gravity of the fluid [x, y, z] in meters.

Type:

np.ndarray

free_surface_moment_t

Transverse free surface moment in m⁴. This is the second moment of area (I_t) of the free surface.

Type:

float

free_surface_moment_l

Longitudinal free surface moment in m⁴. This is the second moment of area (I_l) of the free surface.

Type:

float

free_surface_correction_t

Transverse free surface correction in m⁴. This is I_t × (ρ_fluid / ρ_water) for use in GG’ = FSC / Δ.

Type:

float

free_surface_correction_l

Longitudinal free surface correction in m⁴. This is I_l × (ρ_fluid / ρ_water) for use in GG’ = FSC / Δ.

Type:

float

fill_level_percent: float
fill_volume: float
fluid_mass: float
center_of_gravity: ndarray
free_surface_moment_t: float
free_surface_moment_l: float
free_surface_correction_t: float
free_surface_correction_l: float
__init__(fill_level_percent: float, fill_volume: float, fluid_mass: float, center_of_gravity: ndarray, free_surface_moment_t: float, free_surface_moment_l: float, free_surface_correction_t: float, free_surface_correction_l: float) None

Creating Tanks

There are three ways to create a Tank:

From STL/VTK File

from pynavaltoolbox.tanks import Tank

# Load tank geometry from a file
tank = Tank(
    "tank_geometry.stl",
    fluid_density=850.0,    # Fuel oil density
    fill_level=0.5,         # 50% filled
    name="FuelTank1"
)

From Box Dimensions

from pynavaltoolbox.tanks import Tank

# Create a rectangular tank from dimensions
tank = Tank.from_box(
    x_min=10.0, x_max=20.0,   # 10m long
    y_min=-3.0, y_max=3.0,    # 6m wide
    z_min=0.0, z_max=4.0,     # 4m tall
    fluid_density=1025.0,     # Seawater ballast
    fill_level=0.75,          # 75% filled
    name="BallastTank1"
)

From Hull Intersection

Create tanks that follow the shape of the hull (e.g., double-bottom tanks):

from pynavaltoolbox import Hull
from pynavaltoolbox.tanks import Tank

hull = Hull("ship.stl")

# Create a double-bottom tank that follows the hull shape
tank = Tank.from_box_hull_intersection(
    hull,
    x_min=20.0, x_max=40.0,   # Section of hull
    y_min=-10.0, y_max=10.0,  # Full beam
    z_min=0.0, z_max=1.5,     # 1.5m from keel
    fluid_density=1025.0,
    name="DoubleFond1"
)

Managing Fill Level

# Set fill level in different units
tank.set_fill_level(75, unit='percent')     # 75%
tank.set_fill_level(0.5, unit='fraction')   # 50%
tank.set_fill_level(100.0, unit='m³')       # 100 cubic meters

# Get current fill state
print(f"Fill: {tank.fill_percent:.1f}%")
print(f"Volume: {tank.fill_volume:.2f} m³")
print(f"Mass: {tank.fluid_mass:.0f} kg")

Free Surface Effects

Tanks with free surfaces cause a virtual rise in the center of gravity, reducing stability. The module calculates free surface moments (FSM) and free surface corrections (FSC):

# Get free surface properties
I_t = tank.free_surface_moment_t      # Transverse moment (m⁴)
I_l = tank.free_surface_moment_l      # Longitudinal moment (m⁴)
fsc_t = tank.free_surface_correction_t  # GG' correction (m⁴)
fsc_l = tank.free_surface_correction_l  # GG' correction (m⁴)

# Get complete tank state
state = tank.get_state()
print(f"CoG: {state.center_of_gravity}")
print(f"FSC transverse: {state.free_surface_correction_t:.2f} m⁴")

Integration with Vessel

Tanks can be added to a Vessel for combined calculations:

from pynavaltoolbox import Vessel, Hull
from pynavaltoolbox.tanks import Tank

hull = Hull("ship.stl")

# Create tanks
fuel = Tank.from_box(
    x_min=30.0, x_max=40.0,
    y_min=-5.0, y_max=5.0,
    z_min=2.0, z_max=6.0,
    fluid_density=850.0,
    name="Fuel"
)
fuel.set_fill_level(60, unit='percent')

ballast = Tank.from_box(
    x_min=10.0, x_max=30.0,
    y_min=-8.0, y_max=8.0,
    z_min=0.0, z_max=2.0,
    fluid_density=1025.0,
    name="Ballast"
)
ballast.set_fill_level(50, unit='percent')

# Create vessel with tanks
vessel = Vessel(hull, tanks=[fuel, ballast])

# Get combined tank properties
total_mass = vessel.get_total_tanks_mass()
combined_cog = vessel.get_tanks_center_of_gravity()
fsm_t, fsm_l = vessel.get_total_free_surface_moment()
fsc_t, fsc_l = vessel.get_total_free_surface_correction()