Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak API docstrings/comments #158

Merged
merged 12 commits into from
Apr 22, 2024
73 changes: 38 additions & 35 deletions regional_mom6/regional_mom6.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ def longitude_slicer(data, longitude_extent, longitude_coords):
the information we have about the way the dataset was shifted/rolled.

- Slice the ``data`` index-wise. We know that ``|longitude_extent[1] - longitude_extent[0]| / 360``
multiplied by the number of discrete longitude points will give
the total width of our slice, and we've already set the midpoint
multiplied by the number of discrete longitude points in the global input data will give
the number of longitude points in our slice, and we've already set the midpoint
to be the middle of the target domain.

- Finally re-add the right multiple of 360 so the whole domain matches
- Finally re-add the correct multiple of 360 so the whole domain matches
the target.

Args:
Expand Down Expand Up @@ -120,7 +120,7 @@ def longitude_slicer(data, longitude_extent, longitude_coords):

new_lon[new_seam_index:] += 360

## new_x is used to recentre the midpoint to match that of target domain
## new_x is used to re-centre the midpoint to match that of target domain
new_lon -= i * 360

new_data = new_data.assign_coords({lon: new_lon})
Expand Down Expand Up @@ -163,7 +163,7 @@ def hyperbolictan_thickness_profile(nlayers, ratio, total_depth):
``(1 + ratio * exp(2π)) / (ratio + exp(2π))``. This slight departure comes about
because of the value of the hyperbolic tangent profile at the end-points ``tanh(π)``,
which is approximately 0.9963 and not 1. Note that because ``exp(2π)`` is much greater
than 1, the value of the actual ratio is not that different from prescribed value
than 1, the value of the actual ratio is not that different from the prescribed value
``ratio``, e.g., for ``ratio`` values between 1/100 and 100 the final ratio of the
bottom-most layer to the top-most layer only departs from the prescribed ``ratio``
by ±20%.
Expand Down Expand Up @@ -262,8 +262,8 @@ def hyperbolictan_thickness_profile(nlayers, ratio, total_depth):

def rectangular_hgrid(λ, φ):
"""
Construct a horizontal grid with all the metadata required by MOM6 provided
an array of longitudes (``λ``) and latitudes (``φ``) on the supergrid.
Construct a horizontal grid with all the metadata required by MOM6, based on
arrays of longitudes (``λ``) and latitudes (``φ``) on the supergrid.
Here, 'supergrid' refers to both cell edges and centres, meaning that there
are twice as many points along each axis than for any individual field.

Expand Down Expand Up @@ -368,7 +368,7 @@ class experiment:
from MOM6 variable/coordinate name to the name in the input dataset.

The class can be used to generate the grids for a new experiment, or to read in
an existing one by providing with ``read_existing_grids=True``.
an existing one (with ``read_existing_grids=True``).

Args:
longitude_extent (Tuple[float]): Extent of the region in longitude in degrees.
Expand Down Expand Up @@ -467,16 +467,18 @@ def __getattr__(self, name):
def _make_hgrid(self):
"""
Set up a horizontal grid based on user's specification of the domain.
The default behaviour provides with a grid evenly spaced both in
longitude and in latitude.

The latitudinal resolution is scaled with the cosine of the central latitude of
the domain, i.e., ``Δφ = cos(φ_central) * Δλ``, where ``Δλ`` is the longitudinal
spacing. This way, and given that the domain is small enough, the linear
distances between grid points are nearly identical: ``Δx = R * cos(φ) * Δλ``
and ``Δy = R * Δφ = R * cos(φ_central) * Δλ``. That is, given that the domain is
small enough so that so that ``cos(φ_North_Side)`` is not much different from
``cos(φ_South_Side)`` then ``Δx`` and ``Δy`` are similar.
The default behaviour generates a grid evenly spaced both in longitude
and in latitude.

The latitudinal resolution is scaled with the cosine of the central
latitude of the domain, i.e., ``Δφ = cos(φ_central) * Δλ``, where ``Δλ``
is the longitudinal spacing. This way, for a sufficiently small domain,
the linear distances between grid points are nearly identical:
``Δx = R * cos(φ) * Δλ`` and ``Δy = R * Δφ = R * cos(φ_central) * Δλ``
(here ``R`` is Earth's radius and φ and Δλ are expressed in radians).
That is, if the domain is small enough that so that
``cos(φ_North_Side)`` is not much different from ``cos(φ_South_Side)``,
then ``Δx`` and ``Δy`` are similar.

Note:
The intention is for the horizontal grid (``hgrid``) generation to be very flexible.
Expand Down Expand Up @@ -557,7 +559,7 @@ def _make_vgrid(self):

def initial_condition(self, ic_path, varnames, gridtype="A", vcoord_type="height"):
"""
Read the initial condition files, interpolates to the model grid fixes
Reads the initial condition files, interpolates to the model grid, fixes
up metadata and saves to the input directory.

Args:
Expand Down Expand Up @@ -857,8 +859,8 @@ def rectangular_boundary(
self, path_to_bc, varnames, orientation, segment_number, arakawa_grid="A"
):
"""
Setup a boundary forcing file for a given orientation. Here the term 'rectangular'
implies boundaries along lines of constant latitude or longitude.
Set up a boundary forcing file for a given orientation. Here the term 'rectangular'
means boundaries along lines of constant latitude or longitude.

Args:
path_to_bc (str): Path to boundary forcing file. Ideally this should be a pre cut-out
Expand Down Expand Up @@ -918,9 +920,9 @@ def setup_bathymetry(
bathymetry_path (str): Path to the netCDF file with the bathymetry.
longitude_coordinate_name (Optional[str]): The name of the longitude coordinate in the bathymetry
dataset at ``bathymetry_path``. For example, for GEBCO bathymetry: ``'lon'`` (default).
latitude_coordinate_name (Optional[str]): The name of the longitude coordinate in the bathymetry
latitude_coordinate_name (Optional[str]): The name of the latitude coordinate in the bathymetry
dataset at ``bathymetry_path``. For example, for GEBCO bathymetry: ``'lat'`` (default).
vertical_coordinate_name (Optional[str]): The name of the longitude coordinate in the bathymetry
vertical_coordinate_name (Optional[str]): The name of the height coordinate in the bathymetry
dataset at ``bathymetry_path``. For example, for GEBCO bathymetry: ``'elevation'`` (default).
fill_channels (Optional[bool]): Whether or not to fill in
diagonal channels. This removes more narrow inlets,
Expand Down Expand Up @@ -1080,7 +1082,7 @@ def setup_bathymetry(
+ "directly from a terminal in the input directory via\n\n"
+ "mpirun ESMF_Regrid -s bathymetry_original.nc -d bathymetry_unfinished.nc -m bilinear --src_var elevation --dst_var elevation --netcdf4 --src_regional --dst_regional\n\n"
+ "For details see https://xesmf.readthedocs.io/en/latest/large_problems_on_HPC.html\n\n"
+ "Aftewards, we run 'tidy_bathymetry' method to skip the expensive interpolation step, and finishing metadata, encoding and cleanup."
+ "Afterwards, we run 'tidy_bathymetry' method to skip the expensive interpolation step, and finishing metadata, encoding and cleanup."
)

# If we have a domain large enough for chunks, we'll run regridder with parallel=True
Expand Down Expand Up @@ -1113,19 +1115,19 @@ def tidy_bathymetry(
method from :func:`~setup_bathymetry` allows for the regridding to be done separately,
since regridding can be really expensive for large domains.

If the bathymetry is already regridded and what is left to be done is fixing the metadata,
or fill in some channels then call this function directly to read in the existing
If the bathymetry is already regridded and what is left to be done is fixing the metadata
or fill in some channels, then call this function directly to read in the existing
``bathymetry_unfinished.nc`` file that should be in the input directory.

Args:
fill_channels (Optional[bool]): Whether or not to fill in
fill_channels (Optional[bool]): Whether to fill in
diagonal channels. This removes more narrow inlets,
but can also connect extra islands to land. Default: ``False``.
minimum_layers (Optional[int]): The minimum depth allowed
as an integer number of layers. The default value of ``3``
layers means that anything shallower than the 3rd
layer (as specified by the ``vcoord``) is deemed land.
positive_down (Optional[bool]): If ``True`` (default), it assumes that
positive_down (Optional[bool]): If ``True`` (default), assume that
bathymetry vertical coordinate is positive down.
"""

Expand Down Expand Up @@ -1368,7 +1370,7 @@ def setup_run_directory(
overwrite=False,
):
"""
Setup the run directory for MOM6. Either copy a pre-made set of files, or modify
Set up the run directory for MOM6. Either copy a pre-made set of files, or modify
existing files in the 'rundir' directory for the experiment.

Args:
Expand Down Expand Up @@ -1636,19 +1638,21 @@ class segment:
from the provided startdate. Function ignores the time metadata
and puts it on Julian calendar.

Only supports z-star (z*) vertical coordinate!
Note:
Only supports z-star (z*) vertical coordinate.

Args:
hgrid (xarray.Dataset): The horizontal grid used for domain.
infile (Union[str, Path]): Path to the raw, unprocessed boundary segment.
outfolder (Union[str, Path]): Path to folder where the model inputs will
be stored.
varnames (Dict[str, str]): Mapping between the variable/dimension names and
standard naming convension of this pipeline, e.g., ``{"xq": "longitude,
standard naming convention of this pipeline, e.g., ``{"xq": "longitude,
"yh": "latitude", "salt": "salinity", ...}``. Key "tracers" points to nested
dictionary of tracers to include in boundary.
segment_name (str): Name of the segment, e.g., ``'segment_001'``.
orientation (str): Cardinal direction (lowercase) of the boundary segment.
orientation (str): Cardinal direction (lowercase) of the boundary segment,
i.e., ``'east'``, ``'west'``, ``'north'``, or ``'south'``.
startdate (str): The starting date to use in the segment calendar.
gridtype (Optional[str]): Arakawa staggering of input grid, one of ``'A'``, ``'B'``,
or ``'C'``
Expand Down Expand Up @@ -1713,9 +1717,8 @@ def __init__(

def rectangular_brushcut(self):
"""
Cut out and interpolates tracers. This method assumes that the boundary
is a simple Northern, Southern, Eastern, or Western boundary. Cuts out
and interpolates tracers.
Cut out and interpolate tracers. This method assumes that the boundary
is a simple Northern, Southern, Eastern, or Western boundary.
"""
if self.orientation == "north":
navidcy marked this conversation as resolved.
Show resolved Hide resolved
self.hgrid_seg = self.hgrid.isel(nyp=[-1])
Expand Down
6 changes: 3 additions & 3 deletions regional_mom6/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def vecdot(v1, v2):
"""Return the dot product of vectors ``v1`` and ``v2``.
``v1`` and ``v2`` can be either numpy vectors or numpy.ndarrays
in which case the last dimension is considered the dimension
over which the dot product is taken of.
over which the dot product is taken.
"""
return np.sum(v1 * v2, axis=-1)

Expand Down Expand Up @@ -88,7 +88,7 @@ def quadrilateral_area(v1, v2, v3, v4):


def latlon_to_cartesian(lat, lon, R=1):
"""Convert latitude-longitude (in degrees) to Cartesian coordinates on
"""Convert latitude and longitude (in degrees) to Cartesian coordinates on
a sphere of radius ``R``. By default ``R = 1``.

Args:
Expand Down Expand Up @@ -136,7 +136,7 @@ def quadrilateral_areas(lat, lon, R=1):
Returns:
numpy.array: Array with the areas of the quadrilaterals defined by the ``lat``-``lon`` grid
provided. If the provided ``lat``, ``lon`` arrays are of dimension *m* :math:`\\times` *n*
then return areas array is of dimension (*m-1*) :math:`\\times` (*n-1*).
then returned areas array is of dimension (*m-1*) :math:`\\times` (*n-1*).

Example:

Expand Down
Loading