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.
Logical layout: the i-direction wraps the full 360 deg of
pseudo-longitude (lon_west .. lon_west+360); the j-direction goes
from lat_south up. Corner Bu(i,j) = SW corner of T(i,j) sits at
geographic lon lon_west + (i-ng-1)*dlon BELOW the join. The cap
starts where the corner latitude exceeds phi_join; inside it the
row fraction s = (lat_lonlat - phi_join)/(lat_top - phi_join) in
[0,1] drives the bipolar map (s=0 reproduces the join ring exactly
-> C0 continuity; s=1 is the north-fold line).
Decomposed tile (nx_phys /= nx_global or ny_phys /= ny_global):
the cap map, the supergrid assembler’s edge extrapolation and the
fold/periodic ghost fill are all functions of the WHOLE grid, so a
tile cannot be built from its local extents (it used to be — each
rank then built a complete, wrong globe of its own size). The
tile is instead cut out of the undecomposed grid: the whole grid is
assembled into a temporary ocean_metrics_t exactly as a single
rank would, and the tile’s storage window — ghost rows and columns
included — is copied from it at the global offsets. Every tile’s
metrics are then bit-identical to the matching slice of the
single-rank grid, whatever the tile owns (a south neighbour’s
rows, the folded north ghosts, the periodic columns). Cost: one
transient global-size metric set per rank at configure time
(~20 (ni_global, nj_global) arrays + the 4x supergrid) — fine
for the north-south splits this serves; a distributed (px > 1)
hero-scale grid will want a tile-local construction instead.
| 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 |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| type(hgrid_t), | private | :: | gwhole | ||||
| integer, | private | :: | io | ||||
| integer, | private | :: | jo | ||||
| type(ocean_metrics_t), | private | :: | mwhole |
subroutine metrics_fill_tripolar(this, grid, lon_west, lat_south, & dlon_deg, dlat_deg, rad_earth, phi_join, lon_pole) !! 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. !! !! Logical layout: the i-direction wraps the full 360 deg of !! pseudo-longitude (lon_west .. lon_west+360); the j-direction goes !! from lat_south up. Corner Bu(i,j) = SW corner of T(i,j) sits at !! geographic lon `lon_west + (i-ng-1)*dlon` BELOW the join. The cap !! starts where the corner latitude exceeds `phi_join`; inside it the !! row fraction `s = (lat_lonlat - phi_join)/(lat_top - phi_join)` in !! [0,1] drives the bipolar map (s=0 reproduces the join ring exactly !! -> C0 continuity; s=1 is the north-fold line). !! !! Decomposed tile (`nx_phys /= nx_global` or `ny_phys /= ny_global`): !! the cap map, the supergrid assembler's edge extrapolation and the !! fold/periodic ghost fill are all functions of the WHOLE grid, so a !! tile cannot be built from its local extents (it used to be — each !! rank then built a complete, wrong globe of its own size). The !! tile is instead cut out of the undecomposed grid: the whole grid is !! assembled into a temporary `ocean_metrics_t` exactly as a single !! rank would, and the tile's storage window — ghost rows and columns !! included — is copied from it at the global offsets. Every tile's !! metrics are then bit-identical to the matching slice of the !! single-rank grid, whatever the tile owns (a south neighbour's !! rows, the folded north ghosts, the periodic columns). Cost: one !! transient global-size metric set per rank at configure time !! (~20 `(ni_global, nj_global)` arrays + the 4x supergrid) — fine !! for the north-south splits this serves; a distributed (px > 1) !! hero-scale grid will want a tile-local construction instead. type(ocean_metrics_t), intent(inout) :: this type(hgrid_t), intent(in) :: grid real(wp), intent(in) :: lon_west, lat_south, dlon_deg, dlat_deg real(wp), intent(in) :: rad_earth, phi_join, lon_pole type(hgrid_t) :: gwhole type(ocean_metrics_t) :: mwhole integer :: io, jo if (grid%nx_phys == grid%nx_global .and. grid%ny_phys == grid%ny_global) then call metrics_fill_tripolar_whole(this, grid, lon_west, lat_south, dlat_deg, & rad_earth, phi_join, lon_pole) return end if call gwhole%init(grid%nx_global, grid%ny_global, grid%nghost, grid%dx, grid%dy) call mwhole%init(gwhole) call metrics_fill_tripolar_whole(mwhole, gwhole, lon_west, lat_south, dlat_deg, & rad_earth, phi_join, lon_pole) io = grid%i_offset_global jo = grid%j_offset_global call metrics_window_all(this, mwhole, io, jo) call mwhole%destroy() end subroutine metrics_fill_tripolar