metrics_fill_tripolar Subroutine

public 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.

Arguments

Type IntentOptional 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

Calls

proc~~metrics_fill_tripolar~~CallsGraph proc~metrics_fill_tripolar metrics_fill_tripolar proc~grid_init hgrid_t%grid_init proc~metrics_fill_tripolar->proc~grid_init proc~metrics_fill_tripolar_whole metrics_fill_tripolar_whole proc~metrics_fill_tripolar->proc~metrics_fill_tripolar_whole proc~metrics_window_all metrics_window_all proc~metrics_fill_tripolar->proc~metrics_window_all proc~ocean_metrics_destroy ocean_metrics_t%ocean_metrics_destroy proc~metrics_fill_tripolar->proc~ocean_metrics_destroy proc~metrics_assemble_from_supergrid_arrays metrics_assemble_from_supergrid_arrays proc~metrics_fill_tripolar_whole->proc~metrics_assemble_from_supergrid_arrays proc~metrics_fold_periodic_ghosts metrics_fold_periodic_ghosts proc~metrics_fill_tripolar_whole->proc~metrics_fold_periodic_ghosts proc~supergrid_angle_dx_from_geography supergrid_angle_dx_from_geography proc~metrics_fill_tripolar_whole->proc~supergrid_angle_dx_from_geography proc~tripolar_supergrid_arrays tripolar_supergrid_arrays proc~metrics_fill_tripolar_whole->proc~tripolar_supergrid_arrays proc~metrics_window_2d metrics_window_2d proc~metrics_window_all->proc~metrics_window_2d proc~supergrid_ghost_fill_2d supergrid_ghost_fill_2d proc~metrics_assemble_from_supergrid_arrays->proc~supergrid_ghost_fill_2d proc~supergrid_ghost_fill_bu supergrid_ghost_fill_bu proc~metrics_assemble_from_supergrid_arrays->proc~supergrid_ghost_fill_bu proc~supergrid_ghost_fill_cu supergrid_ghost_fill_cu proc~metrics_assemble_from_supergrid_arrays->proc~supergrid_ghost_fill_cu proc~supergrid_ghost_fill_cv supergrid_ghost_fill_cv proc~metrics_assemble_from_supergrid_arrays->proc~supergrid_ghost_fill_cv interface~fold_north_centre fold_north_centre proc~metrics_fold_periodic_ghosts->interface~fold_north_centre proc~metrics_fold_north_faces metrics_fold_north_faces proc~metrics_fold_periodic_ghosts->proc~metrics_fold_north_faces proc~metrics_periodic_x_all metrics_periodic_x_all proc~metrics_fold_periodic_ghosts->proc~metrics_periodic_x_all proc~great_circle great_circle proc~tripolar_supergrid_arrays->proc~great_circle proc~spherical_quad_area spherical_quad_area proc~tripolar_supergrid_arrays->proc~spherical_quad_area proc~tripolar_node_latlon tripolar_node_latlon proc~tripolar_supergrid_arrays->proc~tripolar_node_latlon proc~fold_north_centre_2d fold_north_centre_2d interface~fold_north_centre->proc~fold_north_centre_2d proc~fold_north_centre_3d fold_north_centre_3d interface~fold_north_centre->proc~fold_north_centre_3d interface~fold_north_corner fold_north_corner proc~metrics_fold_north_faces->interface~fold_north_corner proc~metrics_fold_north_cu_scalar metrics_fold_north_cu_scalar proc~metrics_fold_north_faces->proc~metrics_fold_north_cu_scalar proc~metrics_fold_north_cv_scalar metrics_fold_north_cv_scalar proc~metrics_fold_north_faces->proc~metrics_fold_north_cv_scalar proc~metrics_periodic_x_2d metrics_periodic_x_2d proc~metrics_periodic_x_all->proc~metrics_periodic_x_2d proc~metrics_periodic_x_bu metrics_periodic_x_bu proc~metrics_periodic_x_all->proc~metrics_periodic_x_bu proc~metrics_periodic_x_cu metrics_periodic_x_cu proc~metrics_periodic_x_all->proc~metrics_periodic_x_cu proc~metrics_periodic_x_cv metrics_periodic_x_cv proc~metrics_periodic_x_all->proc~metrics_periodic_x_cv proc~spherical_tri_area spherical_tri_area proc~spherical_quad_area->proc~spherical_tri_area proc~bipolar_corner_latlon bipolar_corner_latlon proc~tripolar_node_latlon->proc~bipolar_corner_latlon proc~fold_north_corner_2d fold_north_corner_2d interface~fold_north_corner->proc~fold_north_corner_2d proc~spherical_tri_area->proc~great_circle

Called by

proc~~metrics_fill_tripolar~~CalledByGraph proc~metrics_fill_tripolar metrics_fill_tripolar proc~configure_ocean_metrics configure_ocean_metrics proc~configure_ocean_metrics->proc~metrics_fill_tripolar proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_metrics proc~complete_ocean_create complete_ocean_create proc~complete_ocean_create->proc~engine_setup proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_setup proc~driver_validate driver_validate proc~driver_validate->proc~engine_setup proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean proc~rdb_ocean_create_finalize rdb_ocean_create_finalize proc~rdb_ocean_create_finalize->proc~complete_ocean_create proc~rdb_ocean_create_from_string rdb_ocean_create_from_string proc~rdb_ocean_create_from_string->proc~complete_ocean_create

Variables

Type Visibility Attributes Name Initial
type(hgrid_t), private :: gwhole
integer, private :: io
integer, private :: jo
type(ocean_metrics_t), private :: mwhole

Source Code

   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