ocean_metrics_t — the full 2D metric arrays the curvilinear ocean
dyn-core reads.
Coordinates are GENERATORS that fill these arrays; kernels consume
the metrics only and never recompute 1/dx or dx*dy themselves.
Storage convention (mirrors the C-grid prognostic sizing exactly,
nx = grid%nx_total, ny = grid%ny_total):
* T (cell centre) arrays: (nx, ny) — like h_layer.
* Cu (WEST u-face of T(i,j)) arrays: (nx+1, ny) — like u_face_x.
* Cv (SOUTH v-face of T(i,j)) arrays: (nx, ny+1) — like v_face_y.
* Bu (SW corner of T(i,j)) arrays: (nx+1, ny+1) — like f_corner.
All staggers are filled INCLUDING ghost rows/columns — the metric
formulae extend naturally and unfilled ghosts are a known
EOS-blowup class of bug (formula bathymetry ghost-fill gotcha).
Inverses + the hvisc ratio bundle are single-sourced: computed ONCE
in metrics_finalize from the arrays a generator wrote, via the
Adcroft reciprocal (1/x with 0 -> 0). Kernels never recompute
them: a round-trip 1/(1/dx) mismatch breaks the exact telescoping
that continuity relies on (D4). areaT is load-bearing and
dx*dy is dead: on supergrid / tripolar grids areaT /= dxT*dyT
(D5), so areas are stored independently.
References: MOM6 grid architecture (MOM_dyn_horgrid / MOM_grid
metric vocabulary, studied 2026-06-11); Adcroft reciprocal. This
is an independent implementation — no source ported.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public, | parameter | :: | CORIOLIS_SCHEME_BETA_PLANE | = | 0 |
|
| integer, | public, | parameter | :: | CORIOLIS_SCHEME_PLANETARY | = | 1 |
|
| integer, | public, | parameter | :: | GRID_CONFIG_CARTESIAN | = | 0 |
Uniform Cartesian: every metric constant (bit-identity gate). |
| integer, | public, | parameter | :: | GRID_CONFIG_SPHERICAL | = | 1 |
Spherical lon-lat sector (analytic-derivative form). |
| integer, | public, | parameter | :: | GRID_CONFIG_SUPERGRID | = | 2 |
MOM6 supergrid (mosaic) NetCDF reader (v1 stub). |
| integer, | public, | parameter | :: | GRID_CONFIG_TRIPOLAR | = | 3 |
Analytic TRIPOLAR (Murray 1996): lon-lat below |
| real(kind=wp), | private, | parameter | :: | DEG2RAD | = | 3.14159265358979323846_wp/180.0_wp | |
| real(kind=wp), | private, | parameter | :: | PI_WP | = | 3.14159265358979323846_wp |
Degrees -> radians. |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | angle_dx(:,:) |
Grid ROTATION at T points (RADIANS), |
||
| real(kind=wp), | public, | allocatable | :: | areaBu(:,:) |
Bu-cell area (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | areaCu(:,:) |
Cu-cell area (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | areaCv(:,:) |
Cv-cell area (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | areaT(:,:) |
T-cell area (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | cover_frac(:,:) |
Ice-covered area fraction (nondimensional, |
||
| real(kind=wp), | public, | allocatable | :: | dx2h(:,:) |
dxT^2 at T (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | dx2q(:,:) |
dxBu^2 at Bu (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | dxBu(:,:) |
Corner (Bu) lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dxCu(:,:) |
u-face (Cu) lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dxCv(:,:) |
v-face (Cv) lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dxT(:,:) |
Cell-centre (T) zonal/meridional grid lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dx_cv(:,:) |
Open meridional width of the v-face for transport (m),
|
||
| real(kind=wp), | public, | allocatable | :: | dx_cv_bt(:,:) |
v-face twin, |
||
| real(kind=wp), | public, | allocatable | :: | dx_dyBu(:,:) |
dxBu/dyBu at Bu (dimensionless), |
||
| real(kind=wp), | public, | allocatable | :: | dx_dyT(:,:) |
dxT/dyT at T (dimensionless), |
||
| real(kind=wp), | public, | allocatable | :: | dy2h(:,:) |
dyT^2 at T (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | dy2q(:,:) |
dyBu^2 at Bu (m^2), |
||
| real(kind=wp), | public, | allocatable | :: | dyBu(:,:) |
Corner (Bu) lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dyCu(:,:) |
u-face (Cu) lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dyCv(:,:) |
v-face (Cv) lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dyT(:,:) |
Cell-centre (T) zonal/meridional grid lengths (m), |
||
| real(kind=wp), | public, | allocatable | :: | dy_cu(:,:) |
Open zonal width of the u-face for transport (m), |
||
| real(kind=wp), | public, | allocatable | :: | dy_cu_bt(:,:) |
Open zonal u-face width the BAROTROPIC substep transports on
(m), |
||
| real(kind=wp), | public, | allocatable | :: | dy_dxBu(:,:) |
dyBu/dxBu at Bu (dimensionless), |
||
| real(kind=wp), | public, | allocatable | :: | dy_dxT(:,:) |
dyT/dxT at T (dimensionless), |
||
| real(kind=wp), | public, | allocatable | :: | geolatBu(:,:) |
Latitude / longitude at Bu corners (degrees), |
||
| real(kind=wp), | public, | allocatable | :: | geolatT(:,:) |
Latitude / longitude at T points (degrees), |
||
| real(kind=wp), | public, | allocatable | :: | geolonBu(:,:) |
Latitude / longitude at Bu corners (degrees), |
||
| real(kind=wp), | public, | allocatable | :: | geolonT(:,:) |
Latitude / longitude at T points (degrees), |
||
| real(kind=wp), | public, | allocatable | :: | iareaBu(:,:) |
1/areaBu (1/m^2), |
||
| real(kind=wp), | public, | allocatable | :: | iareaCu(:,:) |
1/areaCu (1/m^2), |
||
| real(kind=wp), | public, | allocatable | :: | iareaCv(:,:) |
1/areaCv (1/m^2), |
||
| real(kind=wp), | public, | allocatable | :: | iareaT(:,:) |
1/areaT (1/m^2), |
||
| real(kind=wp), | public, | allocatable | :: | idxCu(:,:) |
1/dxCu, 1/dyCu (1/m), |
||
| real(kind=wp), | public, | allocatable | :: | idxCv(:,:) |
1/dxCv, 1/dyCv (1/m), |
||
| real(kind=wp), | public, | allocatable | :: | idxT(:,:) |
1/dxT, 1/dyT (1/m), |
||
| real(kind=wp), | public, | allocatable | :: | idyCu(:,:) |
1/dxCu, 1/dyCu (1/m), |
||
| real(kind=wp), | public, | allocatable | :: | idyCv(:,:) |
1/dxCv, 1/dyCv (1/m), |
||
| real(kind=wp), | public, | allocatable | :: | idyT(:,:) |
1/dxT, 1/dyT (1/m), |
||
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public, | allocatable | :: | open_u(:,:,:) |
u-face per-layer 0/1 OPEN mask, |
||
| real(kind=wp), | public, | allocatable | :: | open_v(:,:,:) |
v-face twin, |
||
| real(kind=wp), | public, | allocatable | :: | p_ice_ref(:,:) |
Boussinesq-isostatic (flotation) ice load |
||
| real(kind=wp), | public, | allocatable | :: | por_bed(:,:) |
Static snapshot of the bottom topographic HEIGHT at cell
centres (m, positive up — i.e. |
||
| real(kind=wp), | public, | allocatable | :: | por_davg_u(:,:) |
u-face along-face deepest / shallowest / mean topographic
height (m, positive up), |
||
| real(kind=wp), | public, | allocatable | :: | por_davg_v(:,:) |
v-face twins, |
||
| real(kind=wp), | public, | allocatable | :: | por_dmax_u(:,:) |
u-face along-face deepest / shallowest / mean topographic
height (m, positive up), |
||
| real(kind=wp), | public, | allocatable | :: | por_dmax_v(:,:) |
v-face twins, |
||
| real(kind=wp), | public, | allocatable | :: | por_dmin_u(:,:) |
u-face along-face deepest / shallowest / mean topographic
height (m, positive up), |
||
| real(kind=wp), | public, | allocatable | :: | por_dmin_v(:,:) |
v-face twins, |
||
| real(kind=wp), | public, | allocatable | :: | por_face_area_u(:,:,:) |
u-face layer-averaged OPEN-AREA fraction (nondim, |
||
| real(kind=wp), | public, | allocatable | :: | por_face_area_v(:,:,:) |
v-face twin, |
||
| integer, | public | :: | porous_eta_interp | = | 0 |
Interface-at-velocity-point rule, a |
|
| real(kind=wp), | public | :: | porous_mask_depth | = | 0.0_wp |
Gate HEIGHT (m, positive up, |
|
| logical, | public | :: | use_cavity | = | .false. |
Master switch ( |
|
| logical, | public | :: | use_closed_faces | = | .false. |
Master switch ( |
|
| logical, | public | :: | use_porous | = | .false. |
Master switch ( |
|
| real(kind=wp), | public, | allocatable | :: | wet_T(:,:) |
T-cell wet (1) / land (0) mask, |
||
| real(kind=wp), | public, | allocatable | :: | wet_q(:,:) |
Corner (Bu) open mask, |
||
| real(kind=wp), | public, | allocatable | :: | wet_u(:,:) |
u-face (Cu) open mask, |
||
| real(kind=wp), | public, | allocatable | :: | wet_v(:,:) |
v-face (Cv) open mask, |
||
| real(kind=wp), | public, | allocatable | :: | z_draft(:,:) |
Prescribed STATIC ice-base depth (m, positive DOWN, |
| procedure, public, non_overridable :: bytes => ocean_metrics_bytes | |
| procedure, public, non_overridable :: destroy => ocean_metrics_destroy | |
| procedure, public, non_overridable :: enter_data => ocean_metrics_enter_data | |
| procedure, public, non_overridable :: exit_data => ocean_metrics_exit_data | |
| procedure, public, non_overridable :: init => ocean_metrics_init |
Adcroft reciprocal: 1/x, but 0 -> 0 (zero-width faces give
zero inverse, no NaN/Inf). Single source for every metric
inverse (D4).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | x |
Map a &ocean_grid_nml coriolis_scheme string onto its enum.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | s |
Map a &ocean_grid_nml grid_config string onto its enum.
Unknown -> cartesian (the schema enum already validates the
set; this is the canonical-name dispatch).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | s |
Grid rotation (DEGREES, counter-clockwise from true east — MOM6’s
angle_dx sense) at every T node (2i, 2j) of a supergrid, from
the node geography alone: the direction of the local +i axis is
the chord from the cell’s west-face node (2i-1, 2j) to its
east-face node (2i+1, 2j), projected onto a local east/north
plane (dx_east = dlon*cos(lat), dy_north = dlat). Other nodes
are left at zero (nothing reads them). Used where the mosaic has
no angle_dx and by the analytic tripolar generator.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | sg_x(:,:) |
Node longitude (degrees), |
||
| real(kind=wp), | intent(in) | :: | sg_y(:,:) |
Node latitude (degrees), |
.true. iff the supergrid’s top node row is a TRIPOLAR FOLD LINE:
every node m coincides geographically with its mirror
nxp + 1 - m (MOM6’s fold pairing, T(i, nj+1) = T(ni+1-i, nj)).
Points are compared as unit vectors on the sphere, so longitude is
modulo 360 and irrelevant at the geographic pole (the OM_1deg fold
row crosses 90N with its two copies stored at longitudes 180 deg
apart). A lon-lat top row fails this everywhere except at the
self-conjugate middle node, so the test cannot be passed by
accident. Tolerance: a 1e-7 chord (~0.6 m on the Earth; MOM6
mosaics pair to round-off).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | sg_x(:,:) |
Node longitude (degrees), |
||
| real(kind=wp), | intent(in) | :: | sg_y(:,:) |
Node latitude (degrees), |
Great-circle distance (m) between two geographic points (deg), via the haversine formula (numerically stable for short arcs).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | r | |||
| real(kind=wp), | intent(in) | :: | lat1 | |||
| real(kind=wp), | intent(in) | :: | lon1 | |||
| real(kind=wp), | intent(in) | :: | lat2 | |||
| real(kind=wp), | intent(in) | :: | lon2 |
Counted allocatable footprint of the grid metrics slot (0 when unallocated). One arr_bytes term per array — add a term here when a new allocatable joins the type.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_metrics_t), | intent(in) | :: | this |
Area (m^2) of a spherical quadrilateral with the four corners (1,2,3,4 counter-clockwise) given in degrees, via L’Huilier’s theorem on the two triangles (1,2,3) and (1,3,4).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | r | |||
| real(kind=wp), | intent(in) | :: | lat1 | |||
| real(kind=wp), | intent(in) | :: | lon1 | |||
| real(kind=wp), | intent(in) | :: | lat2 | |||
| real(kind=wp), | intent(in) | :: | lon2 | |||
| real(kind=wp), | intent(in) | :: | lat3 | |||
| real(kind=wp), | intent(in) | :: | lon3 | |||
| real(kind=wp), | intent(in) | :: | lat4 | |||
| real(kind=wp), | intent(in) | :: | lon4 |
Area (m^2) of a spherical triangle (corners in degrees) via the spherical-excess form of L’Huilier’s theorem. Side lengths are angular (great-circle distance / r).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | r | |||
| real(kind=wp), | intent(in) | :: | lat1 | |||
| real(kind=wp), | intent(in) | :: | lon1 | |||
| real(kind=wp), | intent(in) | :: | lat2 | |||
| real(kind=wp), | intent(in) | :: | lon2 | |||
| real(kind=wp), | intent(in) | :: | lat3 | |||
| real(kind=wp), | intent(in) | :: | lon3 |
Translate a raw nc_check-style status (0 = ok) from one of the
nc_* reader calls in metrics_fill_from_supergrid into the
caller’s ierr contract: .true. on success; on failure,
returns .false. with ierr = OCEAN_STATUS_ERR_IO when ierr
is present (closing ncid first, when given, so a mid-read
failure does not leak the file handle), or error stops with
the SAME generic text nc_check itself would have used had the
caller’s ierr never been threaded through — this is what keeps
the legacy (no ierr) behaviour byte-identical while unblocking
the ierr-present return path (F1/F2 of the P0.1 review).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | local_ierr | |||
| integer, | intent(out), | optional | :: | ierr | ||
| integer, | intent(in), | optional | :: | ncid |
Derive the static C-grid face / corner masks from the T-cell
wet_mask and zero the face metrics at land faces, so every
transport / gradient / circulation operator that rides those
metrics couples across NO land face (MOM6 pre-masks the face
LENGTHS; Adcroft & Hallberg 2006).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | wet_mask(:,:) |
T-cell wet (1) / land (0) mask, |
||
| type(hgrid_t), | intent(in) | :: | grid | |||
| logical, | intent(in) | :: | periodic_x |
Boundary topology of |
||
| logical, | intent(in) | :: | periodic_y |
Boundary topology of |
||
| logical, | intent(in) | :: | north_fold |
Boundary topology of |
||
| logical, | intent(in), | optional | :: | mask_wall_velocity |
Opt-in solid-wall velocity masking (default absent ⇒ .false. ⇒ wall ghosts untouched ⇒ bit-identical to the legacy path). |
|
| logical, | intent(in), | optional | :: | wall_west |
Per-edge solid-WALL flags (an edge that is NOT periodic, NOT
north-fold, NOT open/OBC). Only consulted when
|
|
| logical, | intent(in), | optional | :: | wall_east |
Per-edge solid-WALL flags (an edge that is NOT periodic, NOT
north-fold, NOT open/OBC). Only consulted when
|
|
| logical, | intent(in), | optional | :: | wall_south |
Per-edge solid-WALL flags (an edge that is NOT periodic, NOT
north-fold, NOT open/OBC). Only consulted when
|
|
| logical, | intent(in), | optional | :: | wall_north |
Per-edge solid-WALL flags (an edge that is NOT periodic, NOT
north-fold, NOT open/OBC). Only consulted when
|
Fill all model metric arrays from an in-memory MOM6-style supergrid (2x-refined corner geography + edge segments + sub-cell areas), using the even/odd index sums. This is the battle-tested assembly path the NetCDF reader used inline; the tripolar generator builds the supergrid analytically and feeds it here so tripolar metrics flow through identical index logic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | sg_x(:,:) | |||
| real(kind=wp), | intent(in) | :: | sg_y(:,:) | |||
| real(kind=wp), | intent(in) | :: | sg_dx(:,:) | |||
| real(kind=wp), | intent(in) | :: | sg_dy(:,:) | |||
| real(kind=wp), | intent(in) | :: | sg_area(:,:) | |||
| logical, | intent(in), | optional | :: | periodic_x |
The i-direction is periodic (node column |
|
| real(kind=wp), | intent(in), | optional | :: | sg_angle_dx(:,:) |
Supergrid-node grid rotation in DEGREES, |
Grow the z-level closed-face masks from their (1,1,1)
placeholder to full face size. Call ONLY when
&vcoord_nml zfixed_closed_faces is on, at configure time —
after init and BEFORE ocean_state_enter_data, so the device
map captures the final shapes (a realloc after enter_data
would leave the device pointing at freed host memory).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | nz |
Number of layers ( |
Uniform Cartesian: every length is constant, areaX = dx*dy.
Geography is left at zero (a Cartesian beta-plane has no lat/lon
— the Coriolis fill uses the Cartesian y coordinate, D7). Fills
all ghost rows/columns (constants, trivially). Call
metrics_finalize afterwards.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | dx | |||
| real(kind=wp), | intent(in) | :: | dy |
Fill a corner array AND a centre array with the Coriolis parameter, from one of two schemes (D7). Does NOT touch any existing fill sites in coriolis_adv / EPBL / kappa-shear (that re-routing is M2d); this routine just exists + is tested.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(in) | :: | this | |||
| integer, | intent(in) | :: | scheme | |||
| real(kind=wp), | intent(in) | :: | f_0 | |||
| real(kind=wp), | intent(in) | :: | beta | |||
| real(kind=wp), | intent(in) | :: | y_ref | |||
| real(kind=wp), | intent(in) | :: | omega | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(out) | :: | f_corner(:,:) |
Coriolis at C-grid corners (1/s). |
||
| real(kind=wp), | intent(out) | :: | f_centre(:,:) |
|Coriolis| at cell centres (1/s). |
Load an MOM6 supergrid (mosaic) NetCDF file and fill all metric
arrays. After this call the caller must invoke metrics_finalize
to compute the inverses + hvisc ratio bundle.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Grid metadata — supplies the tile ( |
||
| character(len=*), | intent(in) | :: | supergrid_file |
Path to the MOM6 mosaic supergrid NetCDF file. |
||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a dimension mismatch, an unreadable/missing file,
a topology mismatch, or a missing NetCDF build when present;
absent behaves as today ( |
|
| logical, | intent(in), | optional | :: | periodic_x |
The run is periodic east-west. Absent ⇒ |
|
| logical, | intent(in), | optional | :: | north_fold |
The run closes the north edge with the tripolar fold. Absent ⇒
|
Spherical lon-lat sector. For each stagger, geolat/geolon are evaluated at THAT point’s own location; the metric lengths use the cos of that stagger’s own latitude (the consistency trick that keeps the C-grid metrics compatible, D6): dx = rad_earth * cos(lat) * dlon_rad dy = rad_earth * dlat_rad area = dx * dy (analytic-derivative form, NOT great-circle).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | lon_west | |||
| real(kind=wp), | intent(in) | :: | lat_south | |||
| real(kind=wp), | intent(in) | :: | dlon_deg | |||
| real(kind=wp), | intent(in) | :: | dlat_deg | |||
| real(kind=wp), | intent(in) | :: | rad_earth |
Fill every metric array for an analytic TRIPOLAR grid (Murray
1996): ordinary lon-lat for cell-corner latitude <= phi_join,
and a conformal bipolar Arctic cap above (two grid poles at
(phi_join, lon_pole) and (phi_join, lon_pole+180); see
rdb_ocean_bipolar). The construction generates an in-memory
MOM6-style supergrid (2x-refined corner geography, great-circle
edge lengths, sub-cell areas) from the analytic map, then feeds
the SAME metrics_assemble_from_supergrid_arrays index-sum path
the NetCDF reader uses — so tripolar metrics flow through the
battle-tested supergrid assembly. Call metrics_finalize after.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | lon_west | |||
| real(kind=wp), | intent(in) | :: | lat_south | |||
| real(kind=wp), | intent(in) | :: | dlon_deg | |||
| real(kind=wp), | intent(in) | :: | dlat_deg | |||
| real(kind=wp), | intent(in) | :: | rad_earth | |||
| real(kind=wp), | intent(in) | :: | phi_join | |||
| real(kind=wp), | intent(in) | :: | lon_pole |
Compute every stored inverse + the hvisc ratio bundle ONCE from the length/area arrays a generator already wrote, via the Adcroft reciprocal (D4). No kernel ever recomputes these.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this |
Tripolar ghost-metric fill (M4c): periodic-x wrap of the
east/west ghost columns + north-fold of the north ghost rows,
for EVERY metric + geography array. Replaces the constant
extrapolation the supergrid assembler left on those edges. The
ONE routine both the analytic tripolar generator and the MOM6
mosaic reader (metrics_fill_from_supergrid) use.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| logical, | intent(in), | optional | :: | periodic_x |
Wrap the east/west ghost columns. Absent ⇒ |
|
| logical, | intent(in), | optional | :: | north_fold |
Fold the north ghost rows. Absent ⇒ |
Grow the porous-barrier arrays from their (1,1)/(1,1,1)
placeholder size to full face size. Call ONLY when
&ocean_porous_nml enable is on, at configure time — i.e. after
init and BEFORE ocean_state_enter_data, so the device map
captures the final shapes (a realloc after enter_data would
leave the device pointing at freed host memory).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | nz |
Number of layers ( |
The in-memory MOM6-style supergrid of the analytic tripolar grid
(node geography, great-circle edge lengths, spherical sub-cell
areas) that metrics_fill_tripolar assembles. Public so a test
can write the very same grid as a mosaic file and check that the
NetCDF reader reproduces the generator’s metrics, ghosts included.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | lon_west | |||
| real(kind=wp), | intent(in) | :: | lat_south | |||
| real(kind=wp), | intent(in) | :: | dlat_deg | |||
| real(kind=wp), | intent(in) | :: | rad_earth | |||
| real(kind=wp), | intent(in) | :: | phi_join | |||
| real(kind=wp), | intent(in) | :: | lon_pole | |||
| real(kind=wp), | intent(out), | allocatable | :: | sg_x(:,:) |
Node longitude / latitude (degrees), |
|
| real(kind=wp), | intent(out), | allocatable | :: | sg_y(:,:) |
Node longitude / latitude (degrees), |
|
| real(kind=wp), | intent(out), | allocatable | :: | sg_dx(:,:) |
Along-i segment lengths (m), |
|
| real(kind=wp), | intent(out), | allocatable | :: | sg_dy(:,:) |
Along-j segment lengths (m), |
|
| real(kind=wp), | intent(out), | allocatable | :: | sg_area(:,:) |
Sub-cell areas (m^2), |
The undecomposed tripolar build behind metrics_fill_tripolar:
grid must hold the WHOLE grid (its local extents are the global
ones), so the fold and the periodic seam are both local.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | lon_west | |||
| real(kind=wp), | intent(in) | :: | lat_south | |||
| real(kind=wp), | intent(in) | :: | dlat_deg | |||
| real(kind=wp), | intent(in) | :: | rad_earth | |||
| real(kind=wp), | intent(in) | :: | phi_join | |||
| real(kind=wp), | intent(in) | :: | lon_pole |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
North fold of the face and corner metric arrays (the Cu / Cv / Bu
part of metrics_fold_periodic_ghosts; the T arrays are folded
there).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
West/east ghost columns of a T-array (nx_total,ny_total) by periodic wrap (column i <= ng ← i+ni; i > ng+ni ← i-ni).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Periodic-x wrap of the east/west ghost columns of every metric,
geography and rotation array (the first half of
metrics_fold_periodic_ghosts).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Bu-array (nx_total+1,ny_total+1): face-type in x, same as Cu.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Cu-array (nx_total+1,ny_total): faces 1..ni+1 physical at i=ng+1..ng+ni+1.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Cv-array (nx_total,ny_total+1): centre-type in x, same as T.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
South/north ghost rows of a T-array by periodic wrap (the y
analogue of metrics_periodic_x_2d). Only used by the land-mask
ghost fill; the metric tripolar path wraps x only.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Copy a tile’s storage window (ghosts included) out of the
undecomposed array: tile(i, j) = whole(i + io, j + jo). The
stagger is carried by the shapes — a face/corner array is one
wider on both sides, so the same offsets address it.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | tile(:,:) | |||
| real(kind=wp), | intent(in) | :: | whole(:,:) | |||
| integer, | intent(in) | :: | io |
Global i / j offsets of the tile ( |
||
| integer, | intent(in) | :: | jo |
Global i / j offsets of the tile ( |
Cut a tile’s storage window (ghosts included) out of a larger
assembled metric set, for every array the supergrid assembler and
the fold/periodic ghost fill write: tile%X(i, j) = whole%X(i + io,
j + jo). Shared by the decomposed tripolar generator (whole grid)
and the decomposed supergrid reader (a full-width row band).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | tile | |||
| type(ocean_metrics_t), | intent(in) | :: | whole | |||
| integer, | intent(in) | :: | io | |||
| integer, | intent(in) | :: | jo |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_metrics_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_metrics_t), | intent(inout) | :: | this |
Arrays-only attach. The parent ocean_state_t is mapped by the
orchestrator BEFORE this runs.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_metrics_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(inout) | :: | this |
Allocate + zero every metric array. Always allocates (configure
runs after init, before enter_data); off-cost is ~24
(nx,ny)-class arrays (~2 MB at Tasman size).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_metrics_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Fill ghost rows/columns by constant extrapolation, for a T-point
array (nx_total, ny_total). Interior = [ng+1, ng+ni] x
[ng+1, ng+nj].
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Ghost fill for Bu arrays (nx_total+1, ny_total+1).
Physical i-range [ng+1, ng+ni+1], j-range [ng+1, ng+nj+1].
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Ghost fill for Cu arrays (nx_total+1, ny_total).
Physical i-range is [ng+1, ng+ni+1] (ni+1 faces), j-range
[ng+1, ng+nj].
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Ghost fill for Cv arrays (nx_total, ny_total+1).
Physical i-range [ng+1, ng+ni], j-range [ng+1, ng+nj+1].
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | arr(:,:) | |||
| type(hgrid_t), | intent(in) | :: | grid |
Geographic (lat, lon) of supergrid node (m,n). Below the join (lon-lat corner latitude <= phi_join) it is plain lon-lat; above, the bipolar cap map (s = fraction of the cap row span).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | m | |||
| integer, | intent(in) | :: | n | |||
| real(kind=wp), | intent(in) | :: | lon_west | |||
| real(kind=wp), | intent(in) | :: | lat_south | |||
| real(kind=wp), | intent(in) | :: | dlam | |||
| real(kind=wp), | intent(in) | :: | dlat_sg | |||
| real(kind=wp), | intent(in) | :: | phi_join | |||
| real(kind=wp), | intent(in) | :: | lat_top | |||
| real(kind=wp), | intent(in) | :: | lon_pole | |||
| real(kind=wp), | intent(out) | :: | lat | |||
| real(kind=wp), | intent(out) | :: | lon |