pyfvcom2 package

Subpackages

Submodules

Module contents

PyFVCOM2: A Python package for processing FVCOM data.

This package provides tools for working with FVCOM (Finite Volume Community Ocean Model) output data, including reading, processing, and analyzing unstructured grid ocean model results.

class pyfvcom2.BathymetrySmoother[source]

Bases: ABC

Abstract base class for FVCOM bathymetry smoothers.

All concrete smoothers must implement smooth(). The shared r_factor() method computes the Haney r-factor distribution for the current grid bathymetry.

Note

Only cold-start workflows are supported. Smoothing the bathymetry after a hot-start restart file has been generated would produce an internally inconsistent restart because the stored 3-D fields are referenced to the original sigma-coordinate depths. Apply smoothing before generating any forcing or restart files.

r_factor(grid: Grid) np.ndarray[source]

Return the Haney r-factor for every inter-element edge.

Edges adjacent to at least one intertidal element (element-mean depth ≤ 0) are returned as numpy.nan and excluded from the assessment. Use numpy.nanmax() / numpy.nanmean() to compute statistics, and note that r > threshold comparisons naturally treat NaN as False.

Args:

grid: Grid instance to evaluate.

Returns:

Array of r-factor values, one per shared edge. Values near zero indicate a smooth transition; values near 1 indicate a near-step change. Intertidal edges are numpy.nan. A commonly used threshold is \(r < 0.2\).

abstractmethod smooth(grid: Grid) None[source]

Smooth the bathymetry of grid in-place.

Modifies grid._h (node depths) and grid._hc (element-centroid depths) directly.

Args:

grid: Grid instance to modify.

class pyfvcom2.CMEMSInterpolator(cmems_reader: CMEMSReader, fvcom_to_cmems_var_names: dict | None = None)[source]

Bases: Interpolator

CMEMS interpolator class

Args:

cmems_reader (CMEMSReader): An instance of CMEMSReader with loaded data. fvcom_name_map (dict): A mapping of variable names between FVCOM and CMEMS. The keys are FVCOM variable names and the values are CMEMS variable names.

interpolate(coordinates: InterpolationCoordinates, fvcom_var_name: str) ndarray[source]

Perform interpolation operation for CMEMS data.

Args:

coordinates (InterpolationCoordinates): Space and time coordinates for the FVCOM grid; i.e., these are the times and locations where we want interpolated data. fvcom_var_name (str): Name of the FVCOM variable that we want interpolated data for. This will be matched to the corresponding CMEMS variable name using the provided mapping.

Returns:

np.ndarray: Interpolated variable on the FVCOM grid. For 2D this will be (time, points), and for 3D this will be (time, depth, points), where points may be either nodes or elements depending on the variable.

class pyfvcom2.CMEMSReader(file_path: str | List[str], reference_var_name: str, dimension_var_names: dict | None = None)[source]

Bases: object

Class to read CMEMS Data files

close()[source]

Close all datasets to free up resources.

contains_date(date_time: datetime) bool[source]

Check if the dataset contains the given date_time.

Args:

date_time (datetime): Date time to check.

Returns:

bool: True if date_time is within the dataset time range, False otherwise.

property dates
property depth_levels
get_bottom_indices() ndarray[source]

Get indices of the deepest unmasked level for each horizontal point.

Returns:

np.ndarray: 2D array of bottom indices (lat, lon)

get_closest_date_index(date_time) int[source]

Get the index of the datetime variable closest to the given date_time.

Args:

date_time (datetime): Date time to find closest index for.

Returns:

int: Index of the closest time variable.

get_filled_2D_var(var_name: str, target_datetime: datetime, tolerance=None) ndarray[source]

Fill masked values in a 2D variable by interpolation.

Uses a Delaunay triangulation of unmasked ocean points to linearly interpolate over land-masked cells on the regular CMEMS grid.

Args:

var_name (str): Variable name. target_datetime (datetime): Target datetime to retrieve data for. tolerance (timedelta, optional): Maximum allowed time difference. Defaults to None.

Returns:

np.ndarray: Filled variable values on the full (lat, lon) grid.

get_filled_3D_var(var_name: str, target_datetime: datetime, tolerance=None) ndarray[source]

Fill masked values in a 3D variable by interpolation

First, use griddata to interpolate over all masked surface values. Then, for each horizontal point, fill masked depth levels by downward extrapolation from the nearest unmasked depth level.

Args:

var_name (str): Variable name. target_datetime (datetime): Target datetime to retrieve data for. tolerance (timedelta, optional): Maximum allowed time difference. Defaults to None.

Returns:

np.ndarray: Filled variable values.

get_filled_3D_var_by_index(var_name: str, time_index: int = 0) ndarray[source]

Backward compatibility method using time index

get_mask(var) ndarray[source]

Get the mask for a variable. Args:

var (xarray.DataArray): Variable to get the mask for.

Returns:

np.ndarray: Boolean mask array, where True indicates a masked value.

get_unmasked_var_by_index(var_name: str, time_index: int = 0, depth_index: int = None) ndarray[source]

Backward compatibility method using time index

get_unmasked_variable(var_name: str, target_datetime: datetime, depth_index: int = None, tolerance=None) ndarray[source]

Get the unmasked values of a variable at a given datetime and depth index.

Args:

var_name (str): Variable name. target_datetime (datetime): Target datetime to retrieve data for. depth_index (int, optional): Depth index for 3D variables. Defaults to None. tolerance (timedelta, optional): Maximum allowed time difference. Defaults to None.

Returns:

np.ndarray: Unmasked variable values.

get_var(var_name: str, target_datetime: datetime, depth_index: int = None, tolerance=None) ndarray[source]

Get the values of a variable at a given datetime and depth index.

Args:

var_name (str): Variable name. target_datetime (datetime): Target datetime to retrieve data for. depth_index (int, optional): Depth index for 3D variables. Defaults to None. tolerance (timedelta, optional): Maximum allowed time difference. Defaults to None.

Returns:

np.ndarray: Variable values.

get_var_by_index(var_name: str, time_index: int = 0, depth_index: int = None) ndarray[source]

Backward compatibility method using time index

get_var_ndims(var_name: str) int[source]

Get the number of dimensions of a variable.

Args:

var_name (str): Variable name.

Returns:

int: Number of dimensions.

property lats
property lats_2D
property lons
property lons_2D
property n_depths
property n_files

Get the number of files being used.

property time_span

Get the time span covered by the dataset.

property unmasked_lats
property unmasked_lons
class pyfvcom2.ExponentialWeightsCalculator[source]

Bases: WeightsCalculator

Exponential weights calculator for different grid bands within a nest

calculate_weights(n: int, n_bands: int, grid_band_index: int) ndarray[source]

Calculate exponential weights based on the grid band index

Args:

n (int): Number of nodes/elements n_bands (int): Total number of grid bands grid_band_index (int): Index of the grid band

Returns:

Array of weights.

class pyfvcom2.FVCOMHarmonicsReader(file_path: str)[source]

Bases: HarmonicsReader

A class to read FVCOM harmonics data from a netCDF file.

read_harmonics(requested_constituents: List[str], var_names: FVCOMHarmonicsNames) HarmonicsData[source]

Read FVCOM harmonics data for the specified constituents and variable.

Args:

requested_constituents: List of tidal constituent names to read. var_names: NamedTuple containing variable names for FVCOM data.

Returns:

HarmonicsData: NamedTuple containing longitude, latitude, amplitudes, phases, and constituents

class pyfvcom2.FVCOMInterpolator(fvcom_reader: FVCOMReader)[source]

Bases: Interpolator

FVCOM interpolator class

There are several methods that could be used for interpolating data:

  1. Nearest-neighbor interpolation

  2. Linear interpolation from a delaunay triangulation

  3. Radial basis function interpolation

These different methods have different trade-offs in terms of speed and accuracy, with RBFs being the most accurate but also the slowest. For now, we only support linear interpolation using scipy’s LinearTriInterpolator. However, this could be extended in future to support other methods.

Further notes: - In nested FVCOM grids, the elements are identical in the overlap zone, meaning there is no need to interpolate from one grid to another. Instead, one can simply extract the data from the parent grid at the locations of the child grid nodes/elements. - For node-based variables (e.g., zeta, h), interpolation is performed using the grid nodes. We use the input grid’s connectivity (triangles) to build a triangulation for the nodes (i.e., the nv array). - For element-based variables (e.g., u, v), we must construct a new triangulation based on the element centroids (xc, yc). - We should allow for extrapolation of values outside the convex hull of the triangulation, which may be necessary when moving from a coarse grid to a finer grid. This is done by testing for NaN values in the interpolated output and filling them using nearest-neighbor interpolation. A warning is issued when this occurs. - Once data has been interpolated onto all horizontal surfaces of the input grid, we then interpolate vertically onto the supplied depth levels. - Options to parallelise the interpolation step are included.

Args:

fvcom_reader (FVCOMReader): An instance of FVCOMReader with loaded data.

generate_land_sea_mask(coordinates: InterpolationCoordinates) ndarray[source]

Generate a land-sea mask for the given interpolation coordinates

The mask indicates which points are within the convex hull of the FVCOM grid and which are not, and thus which are sea points and which are land points.

Args:

coordinates (InterpolationCoordinates): The interpolation coordinates for which to generate the mask.

Returns:

np.ndarray: A boolean array of shape (n_points,) where True indicates a sea point and False indicates a land point.

interpolate(coordinates: InterpolationCoordinates, fvcom_var_name: str, extrapolate_horizontally: bool | None = False, extrapolate_down: bool | None = False, extrapolate_up: bool | None = True, apply_land_sea_mask: bool | None = True, land_sea_mask: ndarray | None = None) ndarray[source]

Perform interpolation operation for FVCOM data.

The land_sea_mask is only applied when extrapolate is False. If not provided and extrapolate is False, it is automatically generated from the supplied coordinates object through a call to self.generate_land_sea_mask. The argument is included to save on computation time in cases where in interpolate is called multiple times with the same coordinates, e.g., when interpolating multiple variables onto the same grid.

Args:

coordinates (InterpolationCoordinates): Coordinates on the FVCOM grid. fvcom_var_name (str): Name of the FVCOM variable to interpolate. extrapolate_horizontally (Optional[bool]): Whether to allow extrapolation outside the horizontal grid. extrapolate_down (Optional[bool]): Whether to allow extrapolation below the bottom grid. extrapolate_up (Optional[bool]): Whether to allow extrapolation above the surface grid. apply_land_sea_mask (Optional[bool]): Whether to apply the land-sea mask during interpolation. land_sea_mask (Optional[np.ndarray]): Optional land-sea mask to apply during interpolation.

Returns:

np.ndarray: Interpolated variable on the FVCOM grid.

property triangulation_elements_cartesian

Triangulation for FVCOM grid elements in cartesian coordinates.

property triangulation_elements_geographic

Triangulation for FVCOM grid elements in geographic coordinates.

property triangulation_nodes_cartesian

Triangulation for FVCOM grid nodes in cartesian coordinates.

property triangulation_nodes_geographic

Triangulation for FVCOM grid nodes in geographic coordinates.

class pyfvcom2.FVCOMReader(file_paths: str | List[str])[source]

Bases: object

A class to read FVCOM model output and restart files.

This class provides methods to read FVCOM netCDF files and extract relevant data.

Attributes:

filepath (str): Path to the FVCOM netCDF file. dataset (xarray.Dataset): The loaded FVCOM dataset.

DAYS_PER_MILLISECOND = 1.1574074074074074e-08
property bathy_elements

Get the bathymetry values at element centroids

property bathy_nodes

Get the bathymetry values at nodes

property dates: List[datetime]

Get the available dates in the dataset(s).

Returns:

List[datetime]: List of available datetime objects.

get_interpolation_coordinates(horizontal_position: str, vertical_position: str, horizontal_coordinate_system: str | None = 'geographic', vertical_coordinate_system: str | None = 'z', dates: ndarray | None = None) InterpolationCoordinates[source]

Get interpolation coordinates for a specific grid position.

Wrapper for Grid.get_interpolation_coordinates.

Args:

horizontal_position: Whether coordinates are at mesh nodes or element centres (‘node’ or ‘element’). vertical_position: Whether depth coordinates are at layer centres or layer interfaces

(‘layer_centre’ or ‘layer_interface’).

horizontal_coordinate_system: The coordinate system (“geographic” or “cartesian”) for the interpolation

coordinates.

vertical_coordinate_system: The vertical coordinate system (“z” or “sigma”) for the interpolation coordinates. dates: Optional array of datetime objects for the interpolation coordinates.

Returns:

InterpolationCoordinates: The interpolation coordinates for the specified grid position.

get_n_depth_levels(var_name: str) int[source]

Get number of z levels/layers

Args:

var_name (str): The name of the variable.

Returns:

int: Number of sigma levels/layers.

get_sigma_levels(var_name: str) ndarray[source]

Get the sigma levels/layers for the variable based on whether it is node or element based.

Args:

var_name (str): The name of the variable.

Returns:

np.ndarray: Sigma levels array.

get_time_dep_z_levels(var_name: str, target_datetime: datetime = None, tolerance: timedelta | None = None, zeta_var_name: str = 'zeta', relative_to_free_surface: bool = False) ndarray[source]

Get time-dependent z levels/layers for the variable based on whether it is node or element based.

Args:

var_name (str): The name of the variable. target_datetime (datetime): The target datetime for which to retrieve the z levels. tolerance (timedelta, optional): The tolerance for matching the target datetime. zeta_var_name (str, optional): The name of the zeta (ssh) variable. Defaults to ‘zeta’. relative_to_free_surface (bool, optional): Whether to return z levels relative to the free surface or the zero geoid. Defaults to False (relative to zero geoid).

Returns:

np.ndarray: Sigma levels array.

get_var(var_name: str, target_datetime: datetime | None = None, tolerance: timedelta | None = None) ndarray[source]

Get the data for a given variable at a specific time.

Args:

var_name (str): The name of the variable to retrieve. target_datetime (datetime): The target datetime for which to retrieve the data.

Returns:

np.ndarray: The data array for the specified variable at the given time.

get_var_dimensions(var_name: str) tuple[source]

Get the dimensions of a variable.

Args:

var_name (str): The name of the variable to check.

Returns:

tuple: The dimensions of the variable.

get_vertical_position(var_name: str) str[source]

Get the sigma coordinate type for a variable.

Args:

var_name (str): The name of the variable.

Returns:

str: ‘layer_centre’ if the variable uses sigma layers, ‘layer_interface’ if it uses sigma levels.

property grid: Grid

Get the Grid object (constructed lazily).

Returns:

Grid: The grid object containing mesh structure and open boundaries.

property lat_elements

Get the latitude values of element centroids.

property lat_nodes

Get the latitude values from the dataset.

property lon_elements

Get the longitude values of element centroids.

property lon_nodes

Get the longitude values from the dataset.

property n_elements

Get the number of elements in the FVCOM grid.

property n_nodes

Get the number of nodes in the FVCOM grid.

property n_sigma_layers

Get the number of sigma layers in the FVCOM grid.

property n_sigma_levels

Get the number of sigma levels in the FVCOM grid.

property sigma_layers_elements

Get the sigma layer values at element centroids (n_layers, n_elements).

property sigma_layers_nodes

Get the sigma layer values at nodes (n_layers, n_nodes).

property sigma_levels_elements

Get the sigma level values at element centroids (n_levels, n_elements).

property sigma_levels_nodes

Get the sigma level values at nodes (n_levels, n_nodes).

var_is_node_based(var_name: str) bool[source]

Check if a variable is node-based.

Args:

var_name (str): The name of the variable to check.

Returns:

bool: True if the variable is node-based, False if element-based.

property x_elements

Get the Cartesian x-coordinates of element centroids.

property x_nodes

Get the Cartesian x-coordinates at nodes.

property y_elements

Get the Cartesian y-coordinates of element centroids.

property y_nodes

Get the Cartesian y-coordinates at nodes.

class pyfvcom2.GlobalBathymetrySmoother(passes: int = 1)[source]

Bases: BathymetrySmoother

Global ping-pong bathymetry smoother.

Applies one or more passes of a two-step linear interpolation:

  1. Interpolate node depths → element-centroid depths (LinearNDInterpolator over the node positions).

  2. Interpolate the smoothed element depths → node depths (LinearNDInterpolator over the centroid positions).

Each pass is mathematically equivalent to one iteration of graph-Laplacian smoothing, reducing sharp depth gradients uniformly across the entire mesh. Boundary nodes that fall outside the convex hull of the centroids (step 2) retain their original depth.

Args:
passes: Number of complete node→centroid→node round-trips to apply.

More passes produce stronger smoothing but progressively erode bathymetric features. Defaults to 1.

smooth(grid: Grid) None[source]

Apply global ping-pong smoothing to grid in-place.

Args:

grid: Grid instance to modify.

class pyfvcom2.Grid(mesh_data: MeshData, sigma_data: SigmaData, coordinate_system: str, epsg_code: str | None = None)[source]

Bases: object

A class to represent a triangular mesh.

Attributes:

n_nodes (int): Number of nodes in the mesh. n_elements (int): Number of elements in the mesh. n_sigma_levels (int): Number of sigma levels in the vertical grid. n_sigma_layers (int): Number of sigma layers in the vertical grid. n_open_boundaries (int): Number of open boundaries. epsg_code (str): EPSG code used for coordinate transformations. lon_nodes (np.ndarray): Longitude of nodes. lat_nodes (np.ndarray): Latitude of nodes. lon_elements (np.ndarray): Longitude of element centroids. lat_elements (np.ndarray): Latitude of element centroids. x_nodes (np.ndarray): Cartesian x-coordinates of nodes. y_nodes (np.ndarray): Cartesian y-coordinates of nodes. x_elements (np.ndarray): Cartesian x-coordinates of element centroids. y_elements (np.ndarray): Cartesian y-coordinates of element centroids. bathy_nodes (np.ndarray): Bathymetry at nodes. bathy_elements (np.ndarray): Bathymetry at element centroids. triangles (np.ndarray): Triangle connectivity array of shape (n_elements, 3), 0-indexed. types_bdy (np.ndarray): Boundary node type codes. nodes_bdy (np.ndarray): Boundary node indices. sigma_config (SigmaConfig): Sigma coordinate configuration. sigma_levels (np.ndarray): Sigma level coordinates at nodes, shape (n_nodes, n_levels). sigma_layers (np.ndarray): Sigma layer coordinates at nodes, shape (n_nodes, n_layers). sigmac_levels (np.ndarray): Sigma level coordinates at element centroids, shape (n_elements, n_levels). sigmac_layers (np.ndarray): Sigma layer coordinates at element centroids, shape (n_elements, n_layers). sigma_levels_nodes (np.ndarray): Sigma level coordinates at nodes, shape (n_levels, n_nodes). sigma_layers_nodes (np.ndarray): Sigma layer coordinates at nodes, shape (n_layers, n_nodes). sigma_levels_elements (np.ndarray): Sigma level coordinates at element centroids, shape (n_levels, n_elements). sigma_layers_elements (np.ndarray): Sigma layer coordinates at element centroids, shape (n_layers, n_elements). z_layers_static (np.ndarray): Static z-coordinates at layer centres for nodes, shape (n_nodes, n_layers). zc_layers_static (np.ndarray): Static z-coordinates at layer centres for element centroids, shape (n_elements, n_layers). z_levels_static (np.ndarray): Static z-coordinates at layer interfaces for nodes, shape (n_nodes, n_levels). zc_levels_static (np.ndarray): Static z-coordinates at layer interfaces for element centroids, shape (n_elements, n_levels). open_boundaries (list[OpenBoundary]): List of open boundary objects.

property bathy_elements

Get the bathymetry values at element centroids.

property bathy_nodes

Get the bathymetry values at nodes.

get_interpolation_coordinates(horizontal_position: str, vertical_position: str, horizontal_coordinate_system: str = 'geographic', vertical_coordinate_system: str = 'z', dates: ndarray | None = None) InterpolationCoordinates[source]

Get interpolation coordinates for a specific grid position.

Args:

horizontal_position: Whether coordinates are at mesh nodes or element centres (‘node’ or ‘element’). vertical_position: Whether depth coordinates are at layer centres or layer interfaces

(‘layer_centre’ or ‘layer_interface’).

horizontal_coordinate_system: The coordinate system (“geographic” or “cartesian”) for the interpolation coordinates. vertical_coordinate_system: The vertical coordinate system (“z” or “sigma”) for the interpolation coordinates. dates: Array of datetime objects for temporal interpolation. If None, returns empty array.

Returns:

InterpolationCoordinates: The interpolation coordinates for the specified grid position.

property lat_elements

Get the latitude values of element centroids.

property lat_nodes

Get the latitude values at nodes.

property lon_elements

Get the longitude values of element centroids.

property lon_nodes

Get the longitude values at nodes.

property n_elements

Get the number of elements in the mesh.

property n_nodes

Get the number of nodes in the mesh.

property n_open_boundaries

Get the number of open boundaries.

property n_sigma_layers

Get the number of sigma layers in the vertical grid.

property n_sigma_levels

Get the number of sigma levels in the vertical grid.

property nodes_bdy

Get the boundary node indices.

set_bed_roughness(z0b: float | ndarray, cbcmin: float | ndarray | None = None) None[source]

Set the bed roughness parameters for the grid.

Args:
z0b: Bottom roughness in metres. A scalar is broadcast to all

elements; an array must have length n_elements.

cbcmin: Minimum bottom drag coefficient (dimensionless), optional.

Same broadcast/validation rules as z0b. If not supplied, cbcmin is not written by write_bed_roughness().

Raises:

PyFVCOM2ValueError: If an array argument has the wrong length.

property sigma_config

Get the sigma configuration.

property sigma_layers

Get sigma layer coordinates at nodes (n_nodes, n_layers).

property sigma_layers_elements

Get the sigma layer values at element centroids (n_layers, n_elements).

property sigma_layers_nodes

Get the sigma layer values at nodes (n_layers, n_nodes).

property sigma_levels

Get sigma level coordinates at nodes (n_nodes, n_levels).

property sigma_levels_elements

Get the sigma level values at element centroids (n_levels, n_elements).

property sigma_levels_nodes

Get the sigma level values at nodes (n_levels, n_nodes).

property sigmac_layers

Get sigma layer coordinates at element centroids (n_elements, n_layers).

property sigmac_levels

Get sigma level coordinates at element centroids (n_elements, n_levels).

property triangles

Get the triangle connectivity array (n_elements, 3), 0-indexed.

property types_bdy

Get the boundary node types array.

write_bed_roughness(roughness_file: str) None[source]

Write the bed roughness to a NetCDF4 file.

Writes the z0b variable (bottom roughness in metres, dimensioned nele) and, if set_bed_roughness() was called with a cbcmin value, a cbcmin variable (minimum drag coefficient, dimensionless).

The output file is consumed by FVCOM via the BEDFRICFILE namelist entry.

Args:

roughness_file: Path to the output NetCDF file.

Raises:
PyFVCOM2ValueError: If set_bed_roughness() has not been

called.

write_coriolis(coriolis_file: str, coordinate_system: str) None[source]

Write an FVCOM-formatted Coriolis file.

Args:

coriolis_file: Path to the output Coriolis file. coordinate_system: Which horizontal coordinates to write alongside latitude,

either ‘geographic’ (lon/lat) or ‘cartesian’ (x/y).

write_grid(grid_file: str, coordinate_system: str, depth_file: str | None = None) None[source]

Write the unstructured grid to an FVCOM-formatted ASCII file.

Args:

grid_file: Path to the output grid file. coordinate_system: Which coordinates to write, either ‘geographic’ (lon/lat) or ‘cartesian’ (x/y). depth_file: If given, also write a separate FVCOM depth file.

write_obc(obc_file: str) None[source]

Write open boundary node IDs and types to an FVCOM-formatted ASCII file.

Args:

obc_file: Path to the output open boundary file.

write_sigma(sigma_file: str) None[source]

Write the sigma coordinate configuration to an FVCOM-formatted ASCII file.

Args:

sigma_file: Path to the output sigma file.

write_sponge(sponge_file: str) None[source]

Write sponge layer parameters to an FVCOM-formatted ASCII file.

Collects sponge radius and coefficient values from every open boundary and writes the Sponge Node Number ASCII file consumed by FVCOM’s SPONGE_FILE namelist entry.

Args:

sponge_file: Path to the output sponge file.

Raises:
PyFVCOM2ValueError: If any open boundary has not had

OpenBoundary.set_sponge() called.

property x_elements

Get the Cartesian x-coordinates of element centroids.

property x_nodes

Get the Cartesian x-coordinates at nodes.

property y_elements

Get the Cartesian y-coordinates of element centroids.

property y_nodes

Get the Cartesian y-coordinates at nodes.

property z_layers_static

Get static z-coordinates at layer centres for nodes (n_nodes, n_layers).

property z_levels_static

Get static z-coordinates at layer interfaces for nodes (n_nodes, n_levels).

property zc_layers_static

Get static z-coordinates at layer centres for element centroids (n_elements, n_layers).

property zc_levels_static

Get static z-coordinates at layer interfaces for element centroids (n_elements, n_levels).

class pyfvcom2.GridBand(nodes: ndarray, elements: ndarray, node_weights: ndarray = None, element_weights: ndarray = None)[source]

Bases: object

Grid band with adjoining nodes and elements and vertical sigma structure.

To be used when constructing an FVCOM nest.

property element_weights: ndarray

Get element weights.

Returns:

Array of element weights.

property elements: ndarray

Get element connectivity.

Returns:

Array of element connectivity.

property node_weights: ndarray

Get node weights.

Returns:

Array of node weights.

property nodes: ndarray

Get node coordinates.

Returns:

Array of node coordinates.

class pyfvcom2.HarmonicsData(longitude, latitude, amplitudes, phases, constituents)

Bases: NamedTuple

amplitudes: ndarray

Alias for field number 2

constituents: List[str]

Alias for field number 4

latitude: ndarray

Alias for field number 1

longitude: ndarray

Alias for field number 0

phases: ndarray

Alias for field number 3

class pyfvcom2.HarmonicsReader(file_path: str | Dict[str, str])[source]

Bases: ABC

Abstract base class for reading tidal harmonics data from netCDF files.

abstractmethod read_harmonics(requested_constituents: List[str], var_names: NamedTuple) HarmonicsData[source]

Read harmonics data for the specified constituents and variable.

Args:

requested_constituents: List of tidal constituent names to read. var_names: NamedTuple containing variable names for the specific data format (FVCOM, TPXO, etc.).

Returns:

HarmonicsData: NamedTuple containing longitude, latitude, amplitudes, phases, and constituents

class pyfvcom2.InterpolationCoordinates(dates: ndarray, x3: ndarray, x2: ndarray, x1: ndarray, horizontal_coordinate_system: str, vertical_coordinate_system: str)[source]

Bases: object

property dates
property horizontal_coordinate_system
property vertical_coordinate_system
property x1
property x2
property x3
class pyfvcom2.Interpolator[source]

Bases: ABC

Abstract base class for interpolation operations.

abstractmethod interpolate(coordinates: InterpolationCoordinates, fvcom_var_name: str) ndarray[source]

Perform interpolation operation.

This method must be implemented by subclasses to define the specific interpolation behavior.

Args:

coordinates (InterpolationCoordinates): Coordinates on the FVCOM grid. fvcom_var_name (str): Name of the FVCOM variable to interpolate.

class pyfvcom2.LinearWeightsCalculator[source]

Bases: WeightsCalculator

Linear weights calculator for different grid bands within a nest

calculate_weights(n: int, n_bands: int, grid_band_index: int) ndarray[source]

Calculate linear weights based on the grid band index

Args:

n (int): Number of nodes/elements n_bands (int): Total number of grid bands grid_band_index (int): Index of the grid band

Returns:

Array of weights.

class pyfvcom2.MeshData(triangle: np.ndarray, nodes: np.ndarray | None, x1: np.ndarray, x2: np.ndarray, x3: np.ndarray | None, types_bdy: np.ndarray | None, nodes_bdy: List[List[int]] | None)[source]

Bases: NamedTuple

Named tuple containing standardized mesh data from all readers

Attrs:

triangles: Array of triangle vertex indices. nodes: Integer identifier for each node (one indexed). x1: Array of node x1-coordinates (x or longitude). x2: Array of node x2-coordinates (y or latitude). x3: Array of node x3-coordinates (if available). types_bdy: Array of boundary types for nodes (if available). nodes_bdy: List of lists of open boundary node indices (if available, zero-indexed).

nodes: ndarray | None

Alias for field number 1

nodes_bdy: List[List[int]] | None

Alias for field number 6

triangle: ndarray

Alias for field number 0

types_bdy: ndarray | None

Alias for field number 5

x1: ndarray

Alias for field number 2

x2: ndarray

Alias for field number 3

x3: ndarray | None

Alias for field number 4

class pyfvcom2.NamelistManager(casename: str = 'casename', fabm: bool = False)[source]

Bases: object

Manager for FVCOM run namelists.

Holds a complete FVCOM namelist configuration with sensible defaults and exposes methods to update individual entries before writing to an ASCII .nml file.

The defaults correspond to a barotropic, tide-only cold-start run with no surface forcing, rivers, or data assimilation. The only mandatory entries that have no defaults are NML_CASE / START_DATE and NML_CASE / END_DATE; everything else is pre-populated.

Args:
casename: Model case name used to construct default file-path strings.

Defaults to 'casename'.

fabm: If True, add FABM output controls to the relevant sections

and append an NML_FABM section. Defaults to False.

Examples:
>>> nml = NamelistManager(casename='tamar_v09')
>>> nml.update('NML_CASE', 'START_DATE', '2020-05-01 00:00:00')
>>> nml.update('NML_CASE', 'END_DATE',   '2020-06-01 00:00:00')
>>> nml.update('NML_INTEGRATION', 'EXTSTEP_SECONDS', 2.0)
>>> nml.update('NML_PHYSICS', 'TEMPERATURE_ACTIVE', True)
>>> nml.update_ramp(24)        # 24-hour ramp
>>> nml.write('tamar_v09_run.nml')
update(section: str, entry: str, value=None, fmt: str | None = None) None[source]

Update the value and/or format specifier of a namelist entry.

Args:
section: Section name (e.g. 'NML_CASE'). A leading '&'

is accepted and stripped.

entry: Entry name within the section. value: New value. bool is converted to 'T'/'F'

automatically. Pass None to leave unchanged.

fmt: New Python format specification string (e.g. 'f',

'.3f', 'd'). Pass None to leave unchanged.

Raises:

KeyError: If section or entry does not exist. PyFVCOM2ValueError: If neither value nor fmt is supplied.

update_nesting_interval(target_interval: int = 900) None[source]

Find and set a NCNEST_OUT_INTERVAL compatible with the model.

Searches candidate intervals from 60 s up to ten times target_interval (in 60 s steps) and selects the valid candidate closest to target_interval.

Args:

target_interval: Target interval in seconds. Defaults to 900 s.

Raises:
PyFVCOM2ValueError: If no suitable interval is found — try a

different target_interval, NCNEST_BLOCKSIZE, or EXTSTEP_SECONDS.

update_nudging(recovery_time: float) None[source]

Set OBC nudging timescales from a physical recovery time.

Computes the dimensionless FVCOM nudging timescale (EXTSTEP_SECONDS / recovery_time_seconds) and applies it to temperature, salinity, and — when FABM is enabled — FABM OBC nudging.

Args:

recovery_time: Recovery time in hours.

update_ramp(duration: float) None[source]

Set IRAMP to the number of external time steps for duration hours.

Args:

duration: Ramp duration in hours.

valid_nesting_timescale(interval: float | None = None) bool[source]

Check whether a nesting output interval is compatible with the model.

The simulation duration must be evenly divisible by NCNEST_OUT_INTERVAL × NCNEST_BLOCKSIZE, and the quotient must be evenly divisible by EXTSTEP_SECONDS.

Args:
interval: Candidate interval in seconds. If None, reads the

current NCNEST_OUT_INTERVAL value from the config.

Returns:

True if the interval is compatible, False otherwise.

value(section: str, entry: str)[source]

Return the current value of a namelist entry.

Args:
section: Section name (e.g. 'NML_CASE'). A leading '&'

is accepted and stripped.

entry: Entry name within the section.

Returns:

The current value (str, int, float, or None).

Raises:

KeyError: If section or entry does not exist.

write(path: str) None[source]

Write the namelist configuration to an ASCII .nml file.

Before writing, None-valued *_FIRST_OUT entries and the dye release start/stop are back-filled from NML_CASE / START_DATE and NML_CASE / END_DATE.

Args:

path: Output file path.

Raises:
PyFVCOM2ValueError: If START_DATE or END_DATE have not

been set, if NCNEST_ON is 'T' but the nesting interval is invalid, or if any other mandatory entry is still None at write time.

class pyfvcom2.Nest(open_boundary: OpenBoundary)[source]

Bases: object

Representation of an FVCOM nest

A nest consists of an open boundary and one or more grid bands which extend away from the open boundary into the interior of the domain.

Attributes:

open_boundary: OpenBoundary instance defining the nest’s open boundary. open_boundary_weights: Weights for the open boundary nodes. grid_bands: List of GridBand instances defining the nest’s grid bands.

add_grid_band(grid_band: GridBand)[source]

Add a GridBand to the nest.

Args:

grid_band: GridBand instance to add.

get_grid_bands() list[source]

Get the list of GridBands in the nest.

Returns:

List of GridBand instances.

class pyfvcom2.NestManager(grid: Grid, num_grid_bands=1, weights_calculation_method: str = 'linear')[source]

Bases: object

Manager for FVCOM nests

add_forcing_data(interpolator: Interpolator, fvcom_var_name: str, horizontal_position: str) None[source]

Add forcing data for the nests

Args:

interpolator: Interpolator instance to use for interpolation. fvcom_var_name: FVCOM name for the forcing variable. horizontal_position: Whether coordinates are at mesh nodes or element centres (‘node’ or ‘element’).

add_nest(nest: Nest)[source]

Add a Nest to the manager.

Args:

nest: Nest instance to add.

add_tidal_data(tide_manager: TideManager) None[source]

Add tidal forcing data using a TideManager.

Computes tidal predictions for zeta at nodes, and u, v at element centres, for all nest positions at the dates set via set_dates. The barotropic tidal velocities are also stored as ua and va.

Args:
tide_manager: TideManager with interpolators registered for

the required variables (zeta, u, v).

apply_ramp(ramp_length: float, initial_ts: list | None = None, ramp_type: str = 'cosine') None[source]

Apply a ramp to forcing (and optionally tidal) data.

Blends each variable smoothly from an initial value at t=0 to the full forcing values, preventing a shock at model start-up.

Velocities (u, v, ua, va) and sea surface elevation (zeta) are always ramped from zero. Temperature and salinity are only ramped when initial_ts is provided.

Must be called after add_forcing_data (and add_tidal_data if tidal data is present) and before create_forcing_file.

Args:
ramp_length: Spin-up duration or timescale in seconds.

For ‘cosine’ and ‘linear’, the ramp reaches full amplitude at exactly t = ramp_length. For ‘tanh’, it is a timescale: the ramp reaches ~76 % at t = ramp_length and ~99.5 % at t = 3 * ramp_length (asymptotic, never strictly reaches 1).

initial_ts: [temp_initial, salinity_initial] scalar values to ramp

from for temperature and salinity. If None those variables are not ramped.

ramp_type: Shape of the ramp function. One of:
  • ‘cosine’ (default): half-cosine, C¹ continuous at both t=0 and t=ramp_length. Reaches full amplitude at t=ramp_length.

  • ‘tanh’: hyperbolic tangent, C∞ everywhere but asymptotic.

  • ‘linear’: linear rise, C⁰ (kinked at t=0 and t=ramp_length).

clear_nests() None[source]

Clear all nests from the manager

create_forcing_file(output_path: str, nest_type: int, adjust_tides: list[str] | None = None, format='NETCDF4', **kwargs) None[source]

Write the nest forcing data to a NetCDF file

Args:

output_path: Path to the output NetCDF file. nest_type: Type of model nesting. adjust_tides: List of variable names to adjust by adding tidal

predictions (e.g. [‘zeta’, ‘u’, ‘v’, ‘ua’, ‘va’]). Requires that add_tidal_data has been called first.

format: NetCDF format to use. Defaults to ‘NETCDF4’. **kwargs: Additional keyword arguments for writing the forcing file.

get_all_element_weights() ndarray[source]

Get all element weights for all nests.

Returns:

Array of element weights.

get_all_nest_elements() ndarray[source]

Get all unique element indices used in all nests.

Returns:

Array of unique element indices.

get_all_nest_nodes() ndarray[source]

Get all unique node indices used in all nests.

Returns:

Array of unique node indices.

get_all_node_weights() ndarray[source]

Get all node weights for all nests.

Returns:

Array of node weights.

get_forcing_data(variable: str | None = None, adjust_tides: bool = False) dict | ndarray[source]

Get forcing data, optionally with tidal adjustment applied.

Args:
variable: If given, return the array for that variable only.

If None, return a dict of all forcing variables.

adjust_tides: If True, add tidal predictions to the applicable

forcing variables (those for which tidal data exists). Requires that add_tidal_data has been called first.

Returns:

Dictionary of variable name to array, or a single array when variable is specified.

Raises:
PyFVCOM2ValueError: If no forcing data has been added, or the

requested variable is not available.

get_interpolation_coordinates(horizontal_position: str, vertical_position: str, horizontal_coordinate_system: str | None = 'geographic', vertical_coordinate_system: str | None = 'z') InterpolationCoordinates[source]

Get interpolation coordinates for a specific grid position.

Args:

horizontal_position: Whether coordinates are at mesh nodes or element centres (‘node’ or ‘element’). vertical_position: Whether depth coordinates are at layer centres or layer interfaces

(‘layer_centre’ or ‘layer_interface’).

horizontal_coordinate_system: The coordinate system (“geographic” or “cartesian”) for the interpolation coordinates. vertical_coordinate_system: The vertical coordinate system (“z” or “sigma”) for the interpolation coordinates.

Returns:

InterpolationCoordinates: The interpolation coordinates for the specified grid position.

get_nests() list[source]

Get the list of Nests managed by the manager.

Returns:

List of Nest instances.

get_tidal_data(variable: str | None = None) dict | ndarray[source]

Get tidal prediction data.

Args:
variable: If given, return the array for that variable only.

If None, return the full dict of all tidal variables.

Returns:

Dictionary of variable name to array, or a single array when variable is specified.

Raises:
PyFVCOM2ValueError: If no tidal data has been added, or the

requested variable is not available.

make_nests(num_grid_bands: int) None[source]

Make nests for each open boundary in the grid

Args:

grid: Grid instance containing open boundaries. num_grid_bands: Number of grid bands to create for each nest.

set_dates(dates: list[datetime]) None[source]

Set the dates for the forcing data

Args:

dates: List of datetime objects.

class pyfvcom2.OpenBoundary(bdy_id: int, node_indices: ndarray, sigma_levels: ndarray, sigma_layers: ndarray)[source]

Bases: object

Represents an open boundary in the mesh.

Args:

bdy_id: Unique identifier for the boundary. node_indices: Array of node indices that form this boundary. sigma_levels: Sigma level coordinates for boundary nodes. sigma_layers: Sigma layer coordinates for boundary nodes.

property bdy_id: int

Get the boundary ID.

Returns:

Unique identifier for this boundary.

property nnodes: int

Get the number of nodes in this boundary.

Returns:

Number of nodes that form this boundary.

property node_indices: ndarray

Get the node indices for this boundary.

Returns:

Array of node indices that form this boundary.

set_sponge(radius: float | ndarray, coefficient: float | ndarray) None[source]

Set the sponge layer parameters for all nodes on this boundary.

A scalar radius or coefficient is broadcast to every node on the boundary. Per-node arrays must have length equal to nnodes.

Args:
radius: Sponge layer radius in metres. A single float applies the

same value to every node; an array must match nnodes.

coefficient: Sponge layer coefficient (dimensionless relaxation

strength). Same broadcasting rules as radius.

Raises:

PyFVCOM2ValueError: If an array argument does not match nnodes.

property sigma_layers: ndarray

Get sigma layers for boundary nodes.

Returns:

Sigma layer coordinates for boundary nodes.

property sigma_levels: ndarray

Get sigma levels for boundary nodes.

Returns:

Sigma level coordinates for boundary nodes.

property sponge_coefficient: ndarray | None

Sponge layer coefficient at each boundary node, or None if not set.

property sponge_radius: ndarray | None

Sponge layer radius at each boundary node (m), or None if not set.

exception pyfvcom2.PyFVCOM2AttributeError[source]

Bases: PyFVCOM2Exception

exception pyfvcom2.PyFVCOM2Exception[source]

Bases: Exception

exception pyfvcom2.PyFVCOM2FileNotFoundError[source]

Bases: PyFVCOM2Exception

exception pyfvcom2.PyFVCOM2RuntimeError[source]

Bases: PyFVCOM2Exception

exception pyfvcom2.PyFVCOM2TypeError[source]

Bases: PyFVCOM2Exception

exception pyfvcom2.PyFVCOM2ValueError[source]

Bases: PyFVCOM2Exception

class pyfvcom2.SigmaConfig(nlev: int, sigtype: str, sigpow: float | None = None, du: float | None = None, dl: float | None = None, min_constant_depth: float | None = None, ku: int | None = None, kl: int | None = None, zku: ndarray | None = None, zkl: ndarray | None = None)[source]

Bases: NamedTuple

Named tuple containing sigma coordinate configuration parameters.

Attributes:

nlev: Number of sigma levels. sigtype: Sigma coordinate type (e.g., ‘uniform’, ‘geometric’, ‘tanh’, ‘generalized’). sigpow: Power value for geometric sigma coordinates. du: Upper depth boundary thickness. dl: Lower depth boundary thickness. min_constant_depth: Minimum water depth for generalized coordinates. ku: Number of levels in upper boundary. kl: Number of levels in lower boundary. zku: Depths of upper boundary layers. zkl: Depths of lower boundary layers.

dl: float | None

Alias for field number 4

du: float | None

Alias for field number 3

kl: int | None

Alias for field number 7

ku: int | None

Alias for field number 6

min_constant_depth: float | None

Alias for field number 5

nlev: int

Alias for field number 0

sigpow: float | None

Alias for field number 2

sigtype: str

Alias for field number 1

zkl: ndarray | None

Alias for field number 9

zku: ndarray | None

Alias for field number 8

class pyfvcom2.SigmaData(sigma_config: SigmaConfig, sigma_levels: ndarray)[source]

Bases: NamedTuple

Named tuple containing sigma coordinate data.

Attrs:

sigma_config: Sigma configuration parameters. sigma_levels: 2D array of sigma levels at each node.

sigma_config: SigmaConfig

Alias for field number 0

sigma_levels: ndarray

Alias for field number 1

class pyfvcom2.TPXOComplexHarmonicsNames(part1_var_name, part2_var_name, lon_var_name, lat_var_name, constituents_var_name, apply_transport_unit_conversion, bathy_var_name)

Bases: NamedTuple

apply_transport_unit_conversion: bool

Alias for field number 5

bathy_var_name: str | None

Alias for field number 6

constituents_var_name: str

Alias for field number 4

lat_var_name: str

Alias for field number 3

lon_var_name: str

Alias for field number 2

part1_var_name: str

Alias for field number 0

part2_var_name: str

Alias for field number 1

class pyfvcom2.TPXOComplexHarmonicsReader(file_path: str | Dict[str, str])[source]

Bases: HarmonicsReader

A class to read TPXO harmonics data stored as complex (real/imaginary) from a netCDF file.

read_harmonics(requested_constituents: List[str], var_names: TPXOComplexHarmonicsNames, fill_land: bool = True, bbox: Tuple[float, float, float, float] | None = None, bbox_margin: float = 1.0, bathy_file: ndarray | None = None) HarmonicsData[source]

Read TPXO complex harmonics data for the specified constituents.

Args:

requested_constituents: List of tidal constituent names to read. var_names: NamedTuple containing variable names for TPXO data. fill_land: Whether to fill land points (where amplitude == 0) by interpolation from ocean points. Defaults to True. bbox: Optional (lon_min, lon_max, lat_min, lat_max) bounding box

to spatially subset the data before loading. Uses the target coordinate system (e.g. -180 to 180). Dramatically reduces memory usage and processing time for high-resolution files.

bbox_margin: Extra margin in degrees around the bbox. Defaults to 1.0. bathy_file: Optional path to a netCDF file containing bathymetry data on the same grid, required if apply_transport_unit_conversion is True.

Returns:

HarmonicsData: NamedTuple containing longitude, latitude, amplitudes, phases, and constituents

class pyfvcom2.TPXOHarmonicsNames(amplitude_var_name, phase_var_name, lon_var_name, lat_var_name, constituents_var_name, apply_transport_unit_conversion, bathy_var_name)

Bases: NamedTuple

amplitude_var_name: str

Alias for field number 0

apply_transport_unit_conversion: bool

Alias for field number 5

bathy_var_name: str | None

Alias for field number 6

constituents_var_name: str

Alias for field number 4

lat_var_name: str

Alias for field number 3

lon_var_name: str

Alias for field number 2

phase_var_name: str

Alias for field number 1

class pyfvcom2.TPXOHarmonicsReader(file_path: str | Dict[str, str])[source]

Bases: HarmonicsReader

A class to read TPXO harmonics data stored as amplitude and phase from a netCDF file.

read_harmonics(requested_constituents: List[str], var_names: TPXOHarmonicsNames, fill_land: bool = True, bbox: Tuple[float, float, float, float] | None = None, bbox_margin: float = 1.0) HarmonicsData[source]

Read TPXO harmonics data for the specified constituents.

Args:

requested_constituents: List of tidal constituent names to read. var_names: NamedTuple containing variable names for TPXO data. fill_land: Whether to fill land points (where amplitude == 0) by interpolation from ocean points. Defaults to True. bbox: Optional (lon_min, lon_max, lat_min, lat_max) bounding box

to spatially subset the data before loading. Uses the target coordinate system (e.g. -180 to 180). Dramatically reduces memory usage and processing time for high-resolution files.

bbox_margin: Extra margin in degrees around the bbox. Defaults to 1.0.

Returns:

HarmonicsData: NamedTuple containing longitude, latitude, amplitudes, phases, and constituents

class pyfvcom2.TideManager(constituents: list[str], parallel: bool = True, pool_size: int | None = None)[source]

Bases: object

Manages tidal harmonics interpolation and prediction.

Orchestrates the pipeline from TPXO tidal harmonic data through interpolation onto target positions to tidal time series prediction via UTide.

Typical usage:
  1. Create a TideManager with the desired constituents.

  2. Register TPXOInterpolator instances for each variable (zeta, u, v) via add_interpolator.

  3. Pass the TideManager to NestManager.add_tidal_data(), which calls predict() for each variable with the appropriate target positions.

Args:

constituents: List of tidal constituent names (e.g. [‘M2’, ‘S2’]). parallel: Whether to run UTide predictions in parallel. Default True. pool_size: Number of parallel processes. Default None (use all CPUs).

add_interpolator(variable: str, interpolator) None[source]

Register a TPXOInterpolator for a tidal variable.

Args:

variable: Tidal variable name (‘zeta’, ‘u’, or ‘v’). interpolator: TPXOInterpolator loaded with harmonics data

for this variable.

property constituents: list[str]

List of tidal constituent names.

predict(variable: str, datetimes: ndarray, longitudes: ndarray, latitudes: ndarray) ndarray[source]

Interpolate harmonics onto target positions and predict tides.

Args:

variable: Variable name (‘zeta’, ‘u’, or ‘v’). datetimes: Array of datetime objects for prediction times. longitudes: Target longitude positions. latitudes: Target latitude positions.

Returns:

Predicted tidal time series, shape (n_times, n_points).

class pyfvcom2.WeightsCalculator[source]

Bases: object

calculate_weights(n: int, n_bands: int, grid_band_index: int) ndarray[source]

Calculate inverse weights based on the grid band index

Args:

n (int): Number of nodes/elements n_bands (int): Total number of grid bands grid_band_index (int): Index of the grid band

Returns:

Array of weights.

pyfvcom2.cart2pol(x: ndarray, y: ndarray, degrees: bool = False) tuple[ndarray, ndarray][source]

Convert from cartesian to polar coordinates.

Args:

x: X-coordinates (cartesian). Can be scalar or array-like. y: Y-coordinates (cartesian). Can be scalar or array-like. degrees: If True, return angles in degrees (-180 to 180°),

otherwise in radians (-π to π). Defaults to False.

Returns:
Tuple containing:
  • rho: Radial distances from origin.

  • phi: Angles from positive x-axis. In radians (-π to π) by default,

    or degrees (-180 to 180°) if degrees=True.

Raises:

PyFVCOM2ValueError: If x and y arrays have different shapes.

pyfvcom2.connectivity(p, t)[source]

Assemble connectivity data for a triangular mesh.

The edge based connectivity is built for a triangular mesh and the boundary nodes identified. This data should be useful when implementing FE/FV methods using triangular meshes.

Args: p : np.ndarray

Nx2 array of nodes coordinates, [[x1, y1], [x2, y2], etc.]

tnp.ndarray

Mx3 array of triangles as indices, [[n11, n12, n13], [n21, n22, n23], etc.]

Returns: e : np.ndarray

Kx2 array of unique mesh edges - [[n11, n12], [n21, n22], etc.]

tenp.ndarray

Mx3 array of triangles as indices into e, [[e11, e12, e13], [e21, e22, e23], etc.]

e2tnp.ndarray

Kx2 array of triangle neighbours for unique mesh edges - [[t11, t12], [t21, t22], etc]. Each row has two entries corresponding to the triangle numbers associated with each edge in e. Boundary edges have e2t[i, 1] = -1.

bndnp.ndarray, bool

Nx1 logical array identifying boundary nodes. p[i, :] is a boundary node if bnd[i] = True.

Notes: Python translation of the MATLAB MESH2D connectivity function by Darren Engwirda. See: https://github.com/dengwirda/MESH2D. Code translated by Pierre Cazenave, PML.

References: .. [1] Darren Engwirda, Locally-optimal Delaunay-refinement and optimisation-based mesh generation, Ph.D. Thesis, School of Mathematics and Statistics, The University of Sydney, September 2014.

pyfvcom2.cp_sw(t, s, p)[source]

Calculate constant pressure specific heat (cp) for seawater.

Calculate constant pressure specific heat (cp) for seawater, from temperature, salinity and pressure.

Args:

t (ndarray): Temperature (1D array) in degrees Celsius. s (ndarray): Salinity (1D array) in practical salinity units (unitless). Must be the

same shape as t.

p (ndarray): Pressure (1D array) in decibars. Must be the same shape as t.

Returns:

ndarray: Constant pressure specific heat (Celsius).

Notes:

Valid temperature range is -2 to 40C and salinity is 0-42 PSU. Warnings are issued if the data fall outside these ranges.

pyfvcom2.dT_adiab_sw(t, s, p)[source]

Calculate adiabatic temperature gradient (degrees Celsius dbar^{-1}).

Args:

t (ndarray): Temperature (Celsius). All three arrays must have the same shape. s (ndarray): Salinity (PSU). All three arrays must have the same shape. p (ndarray): Pressure (decibars). All three arrays must have the same shape.

Returns:

ndarray: Adiabatic temperature gradient.

pyfvcom2.dens_jackett(th, s, p=None)[source]

Compute the in-situ density according to the Jackett et al. (2005) equation of state.

This equation of state for sea water is based on the Gibbs potential developed by Fiestel (2003). The pressure dependence can be switched on (off by default) by giving an absolute pressure value (> 0).

Args:

th (ndarray): Potential temperature (degrees Celsius). s (ndarray): Salinity (PSU). p (ndarray, optional): Gauge pressure (decibar) (absolute pressure - 10.1325 decibar).

Returns:

ndarray: In-situ density (kg m^{-3}).

Notes:

The check value is dens_jackett(20, 20, 1000) = 1017.728868019642.

Adopted from GOTM (www.gotm.net) (Original author(s): Hans Burchard & Karsten Bolding) and the PMLPython script EqS.py.

References:

Feistel, R., A new extended Gibbs thermodynamic potential of seawater, Prog. Oceanogr., 58, 43-115, http://authors.elsevier.com/sd/article/S0079661103000880 corrigendum 61 (2004) 99, 2003.

Jackett, D. R., T. J. McDougall, R. Feistel, D. G. Wright, and S. M. Griffies, Updated algorithms for density, potential temperature, conservative temperature and freezing temperature of seawater, Journal of Atmospheric and Oceanic Technology, submitted, 2005.

pyfvcom2.depth2pressure(z, lat)[source]

Convert from depth in metres to pressure in decibars.

Args:
z (ndarray): Depth (1D array) in metres. Must be positive down (negative values are

set to zero before conversion to pressure).

lat (ndarray): Latitudes for samples in z.

Returns:

ndarray: Pressure in decibars.

pyfvcom2.dissipation(rho, U, Cd=0.0025)[source]

Calculate tidal dissipation for a given tidal harmonic (or harmonics).

Args:
rho (ndarray): Density (kg m^{-3}). See dens_jackett() for calculating density from

temperature and salinity. Must be depth-averaged or a single value.

U (ndarray): Tidal harmonic major axis. Extend the array into the second dimension

to include results from multiple constituents.

Cd (float or ndarray, optional): Value for the quadratic drag coefficient. Defaults to

2.5e-3. Can be an array whose size matches the number of locations in rho.

Returns:

ndarray: Tidal dissipation. Units?

References:

Souza, A. J. “On the Use of the Stokes Number to Explain Frictional Tidal Dynamics and Water Column Structure in Shelf Seas.” Ocean Science 9, no. 2 (April 2, 2013): 391-98. doi:10.5194/os-9-391-2013.

Pingree, R. D., and D. K. Griffiths. “Tidal Fronts on the Shelf Seas around the British Isles.” Journal of Geophysical Research: Oceans 83, no. C9 (1978): 4615-22. doi:10.1029/JC083iC09p04615.

pyfvcom2.find_connected_elements(n, triangles)[source]

Return the IDs of the elements connected to node number `n’.

Parameters:
  • n (int or iterable) – Node ID(s) around which to find the connected elements. If more than one node is given, the unique elements for all nodes are returned. Order of results is not maintained.

  • triangles (np.ndarray) – Triangulation matrix to find the connected elements. Shape is [nele, 3].

Returns:

surroundingidx – Indices of the surrounding elements.

Return type:

np.ndarray

See also

PyFVCOM.grid.find_connected_nodes

pyfvcom2.find_file(dir_name: str, file_stem: str, date_time: datetime, tolerance_hours: int | None = 0) str[source]

Find a file in a directory matching a given stem and containing date_time within a given tolerance.

Args:

dir_name (str): Directory to search for files. file_stem (str): Stem of the file name to match. date_time (datetime): Datetime to match in the file name. tolerance_hours (int, optional): Tolerance in hours for datetime matching. Defaults to 1.

Returns:

str: Path to the matched file. int: Index of the time variable corresponding to the matched datetime.

Raises:

PyFVCOM2FileNotFoundError: If no matching file is found within the tolerance.

pyfvcom2.find_files(dir_name: str, file_stem: str, start_date_time: datetime, end_date_time: datetime, tolerance_hours: int | None = 0) list[str][source]

Find all files in a directory matching a given stem and containing datetimes within a given range.

Args:

dir_name (str): Directory to search for files. file_stem (str): Stem of the file name to match. start_date_time (datetime): Start datetime to match in the file name. end_date_time (datetime): End datetime to match in the file name. tolerance_hours (int, optional): Tolerance in hours for datetime matching. Defaults to 1.

Returns:

list[str]: List of paths to the matched files.

pyfvcom2.get_epsg_code(lon: float, lat: float, datum: str | None = 'WGS 84') str[source]

Calculate EPSG code from longitude and latitude values.

Args:

lon (float): Longitude value. lat (float): Latitude value. datum (str, optional): The datum to use. Defaults to “WGS 84”.

Returns:

str: The EPSG code.

pyfvcom2.get_weights_calculator(calculation_method: str) WeightsCalculator[source]

Factory function to get the appropriate WeightsCalculator instance.

Args:

calculation_method (str): The method of weight calculation (“linear”, “inverse”, “exponential”).

Returns:

WeightsCalculator: An instance of the corresponding WeightsCalculator subclass.

Raises:

ValueError: If an unknown calculation method is provided.

pyfvcom2.hybrid_sigma_coordinate(levels: int, transition_depth: float, upper_layer_depth: float, lower_layer_depth: float, total_upper_layers: int, total_lower_layers: int, h: ndarray) SigmaData[source]

Create a hybrid vertical coordinate system.

Args:

levels: Number of vertical levels. transition_depth: Transition depth of the hybrid coordinates. upper_layer_depth: Upper water boundary thickness (metres). lower_layer_depth: Lower water boundary thickness (metres). total_upper_layers: Number of layers in the DU water column. total_lower_layers: Number of layers in the DL water column. h: Water depth at nodes.

Returns:
SigmaData: A named tuple containing:
  • sigma_config (SigmaConfig): Configuration for the sigma coordinate system.

  • sigma_levels (np.ndarray): Sigma levels at each node.

pyfvcom2.lonlat_from_utm(eastings, northings, epsg_code: str)[source]

Convert UTM coordinates to lat/lon.

East Longitudes are positive, west longitudes are negative. North latitudes are positive, south latitudes are negative. Lat and Long are in decimal degrees.

Args:

eastings (int, float, tuple, list, np.ndarray): Eastings. Can be single values or array like. northings (int, float, tuple, list, np.ndarray): Northings. Can be single values or array like. epsg_code (str): The EPSG code for the utm transformation.

Returns:
tuple: A tuple containing:
  • lons (numpy.ndarray): Longitudes for the given eastings and northings.

  • lats (numpy.ndarray): Latitudes for the given eastings and northings.

pyfvcom2.mixedlayerdepth(rho, depth, thresh=0.03)[source]

Calculate the mixed layer depth based on a threshold in vertical density.

Calculate the mixed layer depth based on a threshold in the vertical density distribution.

Args:

rho (ndarray): Density in kg m^{3} [time, depth, position] or [depth, position] or [depth]. depth (ndarray): Water depth (m, -ve down) corresponding to the positions in rho whose space

matches rho.

thresh (float, optional): Density threshold (use at your own risk!). Defaults to 0.03kg m^{-3}.

Returns:
ndarray: Depth at which the density exceeds the surface value plus the

threshold (m, -ve down).

Notes:

The mixed layer depth is given as the layer depth where the density is greater than the threshold. As such, there is no interpolation between layer depths (for now).

If you have coarse layers, you will resolve the mixed layer depth poorly. You will also get odd patterns where the water depth happens to make the vertical layer which is closest to the actual density threshold jump by one, either up or down.

Really, I need to add a linear interpolation between the two closest layers.

pyfvcom2.nodes2elems(nodes, tri)[source]

Calculate an element-centre value based on the average value for the nodes from which it is formed. This involves an average, so the conversion from nodes to elements cannot be reversed without smoothing.

Parameters:
  • nodes (np.ndarray) – Array of unstructured grid node values to move to the element centres.

  • tri (np.ndarray) – Array of shape (nelem, 3) comprising the list of connectivity for each element.

Returns:

elems – Array of values at the grid nodes.

Return type:

np.ndarray

pyfvcom2.parse_obc_sections(obc_node_array, triangle)[source]

Separates the open boundary nodes of a mesh into the separate contiguous open boundary segments

Args: obc_node_array : array

Array of the nodes which are open boundary nodes, as nodes returned by read_fvcom_obc

triangle3xn array

Triangulation array of nodes, as triangle returned by read_fvcom_mesh

Returns: nodestrings : list of arrays

A list of arrays, each of which is one contiguous section of open boundary

pyfvcom2.pea(temp, salinity, depth, levels)[source]

Calculate potential energy anomaly (stratification index).

Args:

temp (ndarray): Temperature data (depth-resolved). salinity (ndarray): Salinity data (depth-resolved). depth (ndarray): Water depth (positive down). Can be 1D (node) or 3D (time, siglay, node). levels (ndarray): Vertical levels (fractions of 0-1) (FVCOM = siglev).

Returns:

ndarray: Potential energy anomaly (J/m^{3}).

Notes:

As with the zbar code, this could do with cleaning up by transposing the arrays so the depth dimension is always first. This would make calculations which require an axis to always use the 0th one instead of either the 0th or 1st.

pyfvcom2.pol2cart(rho: ndarray, phi: ndarray, degrees: bool = False) tuple[ndarray, ndarray][source]

Convert from polar to cartesian coordinates.

Args:

rho: Radial distances from origin. Can be scalar or array-like. phi: Angles from positive x-axis. Can be scalar or array-like. degrees: If True, input angles are in degrees, otherwise in radians.

Defaults to False.

Returns:
Tuple containing:
  • x: X-coordinates (cartesian).

  • y: Y-coordinates (cartesian).

Raises:

PyFVCOM2ValueError: If rho and phi arrays have different shapes.

pyfvcom2.predict_tide(datetimes: ndarray, constituents: list[str], amplitudes: ndarray, phases: ndarray, latitudes: ndarray, parallel: bool = True, pool_size: int | None = None)[source]

Reconstruct tidal variations in zeta, u, v etc at the provided datetimes and latitudes using the provided tidal constituent amplitudes and phases.

Args: datetimes : np.ndarray

Array of datetime objects for prediction times.

intervalfloat

Time interval between datetimes in days.

constituentslist[str]

List of tidal constituent names to read.

amplitudesnp.ndarray

Amplitude of the relevant constituents shaped [nlocs, nconst].

phasesnp.ndarray

Array of the phase of the relevant constituents shaped [nlocs, nconst].

latitudesnp.ndarray

Latitudes of the positions to predict.

parallelbool, optional

Whether to run the predictions in parallel using multiprocessing. Default is True.

pool_sizeint, optional

Number of parallel processes to use. If 1, runs serially. Default is 1.

Returns: results : list[np.ndarray]

List of predicted zeta time series arrays for each location.

pyfvcom2.pressure2depth(p, lat)[source]

Convert from pressure in decibars to depth in metres.

Args:

p (ndarray): Pressure (1D array) in decibars. lat (ndarray): Latitudes for samples in p.

Returns:

ndarray: Water depth in metres.

Notes:

This implements the UNESCO Technical Papers in Marine Science No. 44 (available from http://unesdoc.unesco.org/images/0005/000598/059832eb.pdf).

pyfvcom2.process_sigma_config(config: SigmaConfig, h: ndarray) SigmaData[source]

Read in a sigma coordinates file and generate sigma coordinate parameters.

Args:

config: Sigma configuration parameters. h: Bathymetry at nodes.

Returns:
SigmaData: A named tuple containing:
  • sigma_config (SigmaConfig): Sigma configuration as read from file.

  • sigma_levels (np.ndarray): Sigma levels at each node.

pyfvcom2.read_fvcom_mesh(mesh: str, obc_filename: str | None = None, depth_filename: str | None = None) MeshData[source]

Reads in the FVCOM unstructured grid format.

Args:
mesh (str): Full path to the FVCOM unstructured grid file (.dat usually). The file

name should also contain ‘_grd’ in the name e.g. ‘my_file_grd.dat’. The file contains information about the triangle indicies and the x, y, z coodinates of the grid nodes. The file header should be two lines:

Node Number = nnn Cell Number = eee

Followed by ‘element_index, tri1, tri2, tri3’ for eee cells Followed by ‘node_index, x, y, z’ for nnn nodes

obc_filename (str, optional): Full path to the FVCOM OBC file. This is

used to read in the open boundary node strings if provided.

depth_filename (str, optional): Full path to the FVCOM dep file. This is

used to overwrite the depth values if provided.

Returns:
MeshData: Named tuple containing:
  • triangle (np.ndarray): Integer array of shape (ntri, 3). Each triangle is composed of three points and this contains the three node numbers (stored in nodes) which refer to the coordinates in `x’ and `y’ (see below).

  • nodes (np.ndarray): Integer number assigned to each node.

  • X (np.ndarray): X coordinates of each grid node.

  • Y (np.ndarray): Y coordinates of each grid node.

  • Z (np.ndarray): Z coordinates and any associated Z value.

  • types (Optional[np.ndarray]): None for FVCOM format (no type information available).

  • nodestrings (Optional[List]): None for FVCOM format (no nodestring information available).

pyfvcom2.read_fvcom_obc(obc)[source]

Read in an FVCOM open boundary file.

Args: obc : str

Path to the casename_obc.dat file from FVCOM.

Returns: nodes : np.ndarray

Node IDs (zero-indexed) for the open boundary.

typesnp.ndarray

Open boundary node types (see the FVCOM manual for more information on what these values mean).

countnp.ndarray

Open boundary node number.

pyfvcom2.read_gmsh_mesh(mesh: str) MeshData[source]

Reads in the GMSH unstructured grid format (version 2.2).

Args:

mesh (str): Full path to the GMSH unstructured grid file (.gmsh usually).

Returns:
MeshData: Named tuple containing:
  • triangle (np.ndarray): Integer array of shape (ntri, 3). Each triangle is composed of three points and this contains the three node numbers (stored in nodes) which refer to the coordinates in `x’ and `y’ (see below).

  • nodes (np.ndarray): Integer number assigned to each node.

  • X (np.ndarray): X coordinates of each grid node.

  • Y (np.ndarray): Y coordinates of each grid node.

  • Z (np.ndarray): Z coordinates and any associated Z value.

  • types (Optional[np.ndarray]): None for GMSH format (no type information available).

  • nodestrings (Optional[List]): None for GMSH format (no nodestring information available).

pyfvcom2.read_mesh_file(filename: str, mesh_type: str, **kwargs) MeshData[source]

Factory method to read mesh files of various formats.

Args:

filename (str): Path to the mesh file. mesh_type (str): Type of mesh file. Supported types are:

  • ‘sms’: SMS unstructured grid format (.2dm)

  • ‘fvcom’: FVCOM unstructured grid format (.dat)

  • ‘smesh’: smesh output format

  • ‘mike’: DHI MIKE21 unstructured grid format (.mesh)

  • ‘gmsh’: GMSH unstructured grid format (.gmsh)

**kwargs: Additional keyword arguments passed to the specific reader function.

For ‘fvcom’: obc_filename (str) - path to FVCOM OBC file. For ‘sms’: nodestrings (bool) - whether to return nodestring information For ‘mike’: flipZ (bool) - whether to flip Z coordinates (default True)

Returns:

MeshData: Named tuple containing standardized mesh data.

Raises:

PyFVCOM2ValueError: If mesh_type is not supported. PyFVCOM2FileNotFoundError: If the mesh file cannot be found or opened.

pyfvcom2.read_mike_mesh(mesh: str, flipZ: bool = True) MeshData[source]

Reads in the MIKE unstructured grid format.

Depth sign is typically reversed (i.e. z*-1) but can be disabled by passing flipZ=False.

Args:

mesh (str): Full path to the DHI MIKE21 unstructured grid file (.mesh usually). flipZ (bool, optional): DHI MIKE21 unstructured grids store the z value as positive down

whereas FVCOM wants negative down. The conversion is automatically applied unless flipZ is set to False. Defaults to True.

Returns:
MeshData: Named tuple containing:
  • triangle (np.ndarray): Integer array of shape (ntri, 3). Each triangle is composed of three points and this contains the three node numbers (stored in nodes) which refer to the coordinates in `x’ and `y’ (see below). Given as a zero-indexed array.

  • nodes (np.ndarray): Integer number assigned to each node.

  • X (np.ndarray): X coordinates of each grid node.

  • Y (np.ndarray): Y coordinates of each grid node.

  • Z (np.ndarray): Z coordinates and any associated Z value.

  • types (np.ndarray): Classification for each open boundary. DHI MIKE21 .mesh format requires unique IDs for each open boundary (with 0 and 1 reserved for land and sea nodes).

  • nodestrings (Optional[List]): None for MIKE format (no nodestring information available).

pyfvcom2.read_sigma_file(filepath: str) SigmaConfig[source]

Read in a sigma coordinates file and return parsed configuration.

Args:

filepath: Path to FVCOM sigma coordinates .dat file.

Returns:

Named tuple containing all sigma coordinate parameters.

Notes:

This is more or less a direct python translation of the original MATLAB fvcom-toolbox function read_sigma.m

pyfvcom2.read_smesh_mesh(mesh: str) MeshData[source]

Reads output of the smeshing tool. This is (close) to the fort.14 file format.

Args:

mesh (str): Full path to the smesh output file.

Returns:
MeshData: Named tuple containing:
  • triangle (np.ndarray): Integer array of shape (ntri, 3). Each triangle is composed of three points and this contains the three node numbers which refer to the coordinates in `x’ and `y’ (see below).

  • nodes (Optional[np.ndarray]): None for smesh format (no node information available).

  • X (np.ndarray): X coordinates of each grid node.

  • Y (np.ndarray): Y coordinates of each grid node.

  • Z (Optional[np.ndarray]): None for smesh format (no Z information available).

  • types (Optional[np.ndarray]): None for smesh format (no type information available).

  • nodestrings (Optional[List]): None for smesh format (no nodestring information available).

pyfvcom2.read_sms_mesh(mesh: str, nodestrings: bool | None = False) MeshData[source]

Reads in the SMS unstructured grid format. Also creates IDs for output to MIKE unstructured grid format.

Args:

mesh (str): Full path to an SMS unstructured grid (.2dm) file. nodestrings (bool, optional): Set to True to return the IDs of the node strings. Defaults to False.

Returns:
MeshData: Named tuple containing:
  • triangle (np.ndarray): Integer array of shape (nele, 3). Each triangle is composed of three points and this contains the three node numbers (stored in nodes) which refer to the coordinates in `x’ and `y’ (see below). Values are python-indexed.

  • nodes (np.ndarray): Integer number assigned to each node.

  • X (np.ndarray): X coordinates of each grid node.

  • Y (np.ndarray): Y coordinates of each grid node.

  • Z (np.ndarray): Z coordinates and any associated Z value.

  • types (np.ndarray): Classification for each node string based on the number of node strings + 2. This is mainly for use if converting from SMS .2dm grid format to DHI MIKE21 .mesh format since the latter requires unique IDs for each boundary (with 0 and 1 reserved for land and sea nodes).

  • nodestrings (Optional[List]): List of lists containing the node IDs (python-indexed) of the node strings in the SMS grid if nodestrings=True, otherwise None.

pyfvcom2.sigma_generalized(levels: int, dl: float, du: float, h: float, hmin: float, kl: int, ku: int, zku: list = [], zkl: list = []) ndarray[source]

Generate a generalised sigma coordinate distribution.

Args:

levels: Number of sigma levels. dl: The lower depth boundary from the bottom, down to which the layers are uniform thickness. du: The upper depth boundary from the surface, up to which the layers are uniform thickness. h: Water depth (positive down). hmin: Minimum water depth (positive down). kl: Number of levels in lower boundary. ku: Number of levels in upper boundary. zku: Depths of upper boundary layers. Calculated evenly if not given. zkl: Depths of lower boundary layers. Calculated evenly if not given.

Returns:

Generalised vertical sigma coordinate distribution.

pyfvcom2.sigma_geometric(levels: int, p_sigma: int) ndarray[source]

Generate a geometric sigma coordinate distribution.

Args:

levels: Number of sigma levels. p_sigma: Power value. 1 for uniform sigma layers, 2 for parabolic function.

See page 308-309 in the FVCOM manual for examples.

Returns:

Geometric vertical sigma coordinate distribution.

pyfvcom2.sigma_tanh(levels: int, dl: float, du: float) ndarray[source]

Generate a hyperbolic tangent vertical sigma coordinate distribution.

Args:

levels: Number of sigma levels (layers + 1). dl: The lower depth boundary from the bottom down to which the coordinates

are parallel with uniform thickness.

du: The upper depth boundary from the surface up to which the coordinates

are parallel with uniform thickness.

Returns:

Hyperbolic tangent vertical sigma coordinate distribution.

pyfvcom2.sigma_to_z_coords(sigma_coords: ndarray, zeta: ndarray, bathymetry: ndarray) ndarray[source]

Convert sigma to z coordinates.

Args:

sigma_coords (np.ndarray): 2D array of sigma coords (n_sigma, n_points). zeta (np.ndarray): 1D array of zeta values at each horizontal point. bathymetry (np.ndarray): 1D array of bathymetry values at each horizontal point.

Returns:

np.ndarray: 2D array of z coordinates (depth levels, horizontal points).

pyfvcom2.simpsonhunter(u, v, depth, levels, sampling=False)[source]

Calculate the Simpson-Hunter parameter (h/u^{3}).

Args:

u (ndarray): Depth-resolved current vector (u-component). v (ndarray): Depth-resolved current vector (v-component). depth (ndarray): Water depth (m, +ve down). Must be on the same grid as u and v. levels (ndarray): Vertical levels (fractions of 0-1) (FVCOM = siglev). sampling (int, optional): If given, calculate the current speed maximum over

sampling indices.

Returns:

ndarray: Simpson-Hunter parameter (np.log10(m^{-2}s^{-3})).

References:
  • Simpson, JH, and JR Hunter. “Fronts in the Irish Sea.” Nature 250 (1974): 404-6.

  • Holt, Jason, and Lars Umlauf. “Modelling the Tidal Mixing Fronts and Seasonal Stratification of the Northwest European Continental Shelf.” Continental Shelf Research 28, no. 7 (April 2008): 887-903. doi:10.1016/j.csr.2008.01.012.

pyfvcom2.stokes(h, U, omega, z0, delta=False, U_star=False)[source]

Calculate the Stokes number for a given data set.

Args:

h (ndarray): Water depth (positive down) in metres. U (float): Constituent of interest’s (e.g. M2) major axis in metres. omega (float): Oscillatory frequency of the constituent of interest (e.g. M2) in

s^{-1}. For M2, omega is 1.4e-4.

z0 (float or ndarray): Roughness length in metres. Either a single value or an array

the same shape as the depth data.

delta (bool, optional): Return the oscillatory boundary layer thickness (delta). U_star (bool, optional): Return the frictional velocity (U_star).

Returns:
ndarray or tuple: Stokes number. If delta or U_star are True, returns tuple with

additional values: - S (ndarray): Stokes number. - delta (ndarray, optional): Oscillatory boundary layer thickness (Lamb, 1932). - U_star (ndarray, optional): Frictional velocity (U_star = Cd^{1/2}U).

Examples:
>>> h = 30
>>> z0 = 0.0025
>>> U = 0.25
>>> omega = 1 / 44714.1647021416
>>> S = stokes(h, U, omega, z0)
>>> S
0.70923635467504365
>>> S, U_star = stokes(h, U, omega, z0, U_star=True)
>>> U_star
0.011915170758540733
References:

Souza, A. J. “On the Use of the Stokes Number to Explain Frictional Tidal Dynamics and Water Column Structure in Shelf Seas.” Ocean Science 9, no. 2 (April 2, 2013): 391-98. doi:10.5194/os-9-391-2013.

Lamb, H. “Hydrodynamics”, 6th Edn., Cambridge University Press, New York, USA, p. 622, 1932.

pyfvcom2.sw_dens(t, s, p)[source]

Convert temperature, salinity and pressure to density.

Args:

t (ndarray): Temperature (1D array) in degrees Celsius. s (ndarray): Salinity (1D array) in practical salinity units (unitless). Must be the

same shape as t.

p (ndarray): Pressure (1D array) in decibars. Must be the same shape as t.

Returns:

ndarray: Density in kg m^{-3}.

Notes:

Valid temperature range is -2 to 40C, salinity is 0-42 and pressure is 0-10000 decibars. Warnings are issued if the data fall outside these ranges.

pyfvcom2.sw_dens0(t, s)[source]

Calculate sea water density at atmospheric surface pressure.

Args:

t (ndarray): Temperature (1D array) in degrees Celsius. s (ndarray): Salinity (PSU). Must be the same size as t.

Returns:

ndarray: Seawater density at atmospheric surface pressure (kg m^{-1}).

pyfvcom2.sw_sal78(c, t, p)[source]

Simplified version of the original SAL78 function from Fofonoff and Millard (1983).

This does only the conversion from conductivity, temperature and pressure to salinity. Returns zero for conductivity values below 0.0005.

Args:

c (ndarray): Conductivity (S m{-1}). t (ndarray): Temperature (degrees Celsius IPTS-68). p (ndarray): Pressure (decibars).

Returns:

ndarray: Salinity (PSU-78).

Notes:
The Conversion from IPTS-68 to ITS90 is:

T90 = 0.99976 * T68 T68 = 1.00024 * T90

These constants are defined here as c90 (0.99976) and c68 (1.00024).

pyfvcom2.sw_sal80(args)[source]

Wrapper for sw_sal78 with compatible interface.

Args:

args (tuple): Tuple containing (conductivity, temperature, pressure) arguments.

Returns:

ndarray: Salinity (PSU-78).

pyfvcom2.sw_salinity(args)[source]

Wrapper for sw_sal78 with compatible interface.

Args:

args (tuple): Tuple containing (conductivity, temperature, pressure) arguments.

Returns:

ndarray: Salinity (PSU-78).

pyfvcom2.sw_seck(t, s, p)[source]

Calculate Secant Bulk Modulus (K) of seawater.

Args:

t (ndarray): Temperature (1D array) in degrees Celsius. s (ndarray): Salinity (1D array) in practical salinity units (unitless). Must be the

same shape as t.

p (ndarray): Pressure (1D array) in decibars. Must be the same shape as t.

Returns:

ndarray: Secant Bulk Modulus of seawater.

pyfvcom2.sw_smow(t)[source]

Calculate the density of Standard Mean Ocean Water (pure water).

Args:

t (ndarray): Temperature (1D array) in degrees Celsius.

Returns:

ndarray: Density in kg m^{-3}.

pyfvcom2.sw_svan(t, s, p)[source]

Calculate the specific volume (steric) anomaly.

Args:

t (ndarray): Temperature (1D array) in degrees Celsius. s (ndarray): Salinity (1D array) in practical salinity units (unitless). Must be the

same shape as t.

p (ndarray): Pressure (1D array) in decibars. Must be the same shape as t.

Returns:

ndarray: Specific Volume Anomaly in kg m^{-3}.

pyfvcom2.theta_sw(t, s, p, pr)[source]

Calculate potential temperature for seawater from temperature, salinity and pressure.

Args:

t (ndarray): Temperature (1D array) in degrees Celsius. s (ndarray): Salinity (1D array) in practical salinity units (unitless). Must be the

same shape as t.

p (ndarray): Pressure (1D array) in decibars. Must be the same shape as t. pr (ndarray): Reference pressure (decibars) either a scalar or the same shape as t.

Returns:

ndarray: Potential temperature (Celsius).

pyfvcom2.utm_from_lonlat(longitude, latitude, epsg_code: str | None = None)[source]

Convert lats and lons to UTM coordinates using pyproj.

East Longitudes are positive, west longitudes are negative. North latitudes are positive, south latitudes are negative. Lats and lons are in decimal degrees.

The desired EPSG code can be found by searching websites such as epsg.io or spatialreference.org. If it is not provided, it will be calculated automatically from the first lon and lat values for the WGS 84 datum using the approach described here: https://tinyurl.com/aa83npwy.

Be careful when using this function for coordinates that span multiple zones as the transformation is specific to the specified EPSG reference system.

Args:

longitude (int, float, tuple, list, np.ndarray): Longitudes. Can be a single value or array like. latitude (int, float, tuple, list, np.ndarray): Latitudes. Can be a single value or array like. epsg_code (str, optional): The EPSG code for the utm transformation.

Returns:
tuple: A tuple containing:
  • eastings (numpy.ndarray): Eastings in the supplied reference system.

  • northings (numpy.ndarray): Northings in the supplied reference system.

  • epsg_code (str): The EPSG code for the utm transformation.

pyfvcom2.write_restart(template_file_path: str, output_path: str, data: dict, new_datetime: datetime | None = None) None[source]

Write data to a FVCOM restart file in NetCDF4 format

Args:

template_file_path (str): Path to the FVCOM restart template file. output_path (str): Path to save the FVCOM restart file. data (dict): Data to write to the restart file. new_datetime (str, optional): New datetime string to use, format ‘YYYY-MM-DD_HH:MM:SS’. Defaults to None.

pyfvcom2.write_sigma_file(sigma_config: SigmaConfig, sigma_file: str)[source]

Write the sigma distribution to file.

Args:

sigma_config: Sigma configuration to write. sigma_file: Path to which to save sigma data.

Todo:

Add support for writing all the sigma file formats.

pyfvcom2.z_to_sigma_coords(z_coords: ndarray, zeta: ndarray, bathymetry: ndarray) ndarray[source]

Convert z to sigma coordinates.

Args:

z_coords (np.ndarray): 2D array of z coords (n_levels, n_points). zeta (np.ndarray): 1D array of zeta values at each horizontal point. bathymetry (np.ndarray): 1D array of bathymetry values at each horizontal point.

Returns:

np.ndarray: 2D array of sigma coordinates (n_levels, n_points).