Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Grids (Horizontal · Vertical)

The first step of any CrocoDash workflow is defining the spatial domain: a horizontal grid (Grid) and a vertical grid (VGrid). Bathymetry (Topo), which sits between the two, has its own notebook: see Bathymetry.

CrocoDash re-exports these objects from mom6_forge with no modifications, the full API (class methods, creation patterns, file formats) lives in the mom6_forge documentation. This notebook is the CrocoDash-flavored on-ramp; follow the links in each section for the deeper narrative tutorials and interactive widgets.

This notebook covers:

  • Section 1: build a horizontal grid from scratch

  • Section 2: build a vertical grid

  • Section 3: load a pre-existing grid, or subset a global one

  • Section 4: Arctic/Antarctic polar-projected grids

📖 CrocoDash grids docs · 📖 mom6_forge docs

Section 1: Horizontal Grid, from Scratch

from CrocoDash.grid import Grid

grid = Grid(
  resolution = 0.05, # in degrees
  xstart = 278.0, # min longitude in [0, 360]
  lenx = 3.0, # longitude extent in degrees
  ystart = 7.0, # min latitude in [-90, 90]
  leny = 3.0, # latitude extent in degrees
  name = "panama1",
)

Section 2: Vertical Grid

The vertical grid needs a maximum depth, normally this comes from your finished Topo object’s topo.max_depth (see Bathymetry). Here we use a representative depth directly so this section runs on its own.

from CrocoDash.vgrid import VGrid

max_depth = 5000.0  # in practice: topo.max_depth, once you've built your Topo (see Bathymetry)

vgrid = VGrid.hyperbolic(
    nk = 75, # number of vertical levels
    depth = max_depth,
    ratio=20.0 # target ratio of top to bottom layer thicknesses
)
import matplotlib.pyplot as plt
plt.close()
for depth in vgrid.zi:
    plt.axhline(y=depth, linestyle='-')  # Horizontal lines

plt.ylim(max(vgrid.zi) + 10, min(vgrid.zi) - 10)  # Invert y-axis so deeper values go down
plt.ylabel("Depth")
plt.title("Vertical Grid")
plt.show()

Section 3: Pre-Generated or Subset Grids

Two ways to use a pre-existing horizontal grid instead of generating one from scratch:

  • Section 3.1: load a supergrid directly from a file.

  • Section 3.2: extract a regional sub-grid from a global supergrid by lat/lon bounds.

(Loading or building the matching Topo/VGrid for either of these follows exactly the same pattern shown in Bathymetry and Section 2 above, just swap in the grid object from here.)

Section 3.1: Load Pre-Generated Grid Files

Use this when you already have a MOM6 supergrid (ocean_hgrid.nc), e.g. from a previous run or a shared community grid like NWA12.

from CrocoDash.grid import Grid

grid = Grid.from_supergrid("<NWA_HGRID>")

Section 3.2: Subset a Global Supergrid

Use this when you have a global or basin-scale supergrid and want to extract a regional sub-domain by specifying lower-left and upper-right corner coordinates, via subgrid_from_supergrid:

from CrocoDash.grid import Grid

grid = Grid.subgrid_from_supergrid(
    path="<HGRID_TRIMMED>",   # path to the global supergrid
    llc=(16.0, 192.0),           # (l)ower (l)eft (c)orner (lat, lon)
    urc=(27.0, 209.0),           # (u)pper (r)ight (c)orner (lat, lon)
    name="hawaii_2",
)

Section 4: Polar-Projected Grids (Arctic & Antarctic)

Standard lat/lon grids degrade at high latitudes, cell aspect ratios become extreme, and the MOM6 timestep constraint can become prohibitively tight near the poles. For Arctic or Antarctic domains, mom6_forge can build a grid in a projected coordinate system (e.g. polar stereographic) and reproject it to the geographic coordinates MOM6 expects.

Two approaches are shown here:

  1. Interactive: use the GridCreator widget and select From Projection mode.

  2. Programmatic: call Grid.from_projection() directly.

Approach 1: Interactive GridCreator Widget

Launch the widget, choose From Projection in the method dropdown, select Arctic Polar Stereographic (EPSG:3995) or Antarctic Polar Stereographic (EPSG:3031) from the CRS dropdown, set a resolution, then drag a rectangle on the polar map to define the domain. The widget calls Grid.from_projection() under the hood and saves the result to GridLibrary/.

from mom6_forge.grid_creator import GridCreator

gc = GridCreator()
gc

Approach 2: Programmatic: Grid.from_projection()

Pass a pyproj CRS (as an EPSG string or integer) along with the domain extents in metres in the native projection. The method reprojects to geographic coordinates and computes grid metrics using exact great-circle geometry.

CRSRegion
"EPSG:3995"Arctic Polar Stereographic
"EPSG:3031"Antarctic Polar Stereographic

Arctic domain (EPSG:3995)

EPSG:3995 is centred at the North Pole. Extents are in metres from the pole. The example below creates a 2000 km × 2000 km domain at 50 km resolution.

from mom6_forge.grid import Grid

arctic_grid = Grid.from_projection(
    crs="EPSG:3995",
    x_min=-1_000_000,  # metres from pole
    x_max= 1_000_000,
    y_min=-1_000_000,
    y_max= 1_000_000,
    resolution_m=50_000,  # 50 km
    name="arctic_50km",
)

print(f"Grid size: {arctic_grid.nx} x {arctic_grid.ny}")
print(f"Lat range: {arctic_grid.tlat.values.min():.1f}° to {arctic_grid.tlat.values.max():.1f}°")
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

fig, ax = plt.subplots(subplot_kw={"projection": ccrs.NorthPolarStereo()}, figsize=(6, 6))
ax.set_extent([-180, 180, 45, 90], crs=ccrs.PlateCarree())
ax.coastlines()
ax.gridlines()
ax.pcolormesh(
    arctic_grid.tlon, arctic_grid.tlat,
    arctic_grid.tlat,   # colour by latitude as a sanity check
    transform=ccrs.PlateCarree(), cmap="Blues", alpha=0.6,
)
ax.set_title("Arctic domain (EPSG:3995)")
plt.tight_layout()

Antarctic domain (EPSG:3031)

EPSG:3031 is centred at the South Pole. The example below creates a 3000 km × 3000 km domain (covering most of Antarctica) at 25 km resolution.

antarctic_grid = Grid.from_projection(
    crs="EPSG:3031",
    x_min=-1_500_000,
    x_max= 1_500_000,
    y_min=-1_500_000,
    y_max= 1_500_000,
    resolution_m=25_000,  # 25 km
    name="antarctic_25km",
)

print(f"Grid size: {antarctic_grid.nx} x {antarctic_grid.ny}")
print(f"Lat range: {antarctic_grid.tlat.values.min():.1f}° to {antarctic_grid.tlat.values.max():.1f}°")
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.SouthPolarStereo()}, figsize=(6, 6))
ax.set_extent([-180, 180, -90, -45], crs=ccrs.PlateCarree())
ax.coastlines()
ax.gridlines()
ax.pcolormesh(
    antarctic_grid.tlon, antarctic_grid.tlat,
    antarctic_grid.tlat,
    transform=ccrs.PlateCarree(), cmap="Blues_r", alpha=0.6,
)
ax.set_title("Antarctic domain (EPSG:3031)")
plt.tight_layout()

Next steps

Once you have a Grid and VGrid, build a matching Topo. See Bathymetry , then pass all three to Case: see Case Setup.