configure_ocean_metrics Subroutine

public subroutine configure_ocean_metrics(cfg, ocean_state, grid, compute_rank, ierr)

Fill the ocean_metrics_t slot per cfg%ocean%grid%grid_config, then single-source the inverses + hvisc ratio bundle (metrics_finalize). Must run BEFORE ocean_state_enter_data (the host fill is what the GPU copyin captures). For “spherical”, the &grid_nml dx/dy are reinterpreted as dlon/dlat in degrees.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg
type(ocean_state_t), intent(inout) :: ocean_state
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: compute_rank
integer, intent(out), optional :: ierr

Non-zero on a grid/geometry configuration failure when present; absent behaves as today (error stop).


Calls

proc~~configure_ocean_metrics~~CallsGraph proc~configure_ocean_metrics configure_ocean_metrics info info proc~configure_ocean_metrics->info proc~fail fail proc~configure_ocean_metrics->proc~fail proc~metrics_fill_cartesian metrics_fill_cartesian proc~configure_ocean_metrics->proc~metrics_fill_cartesian proc~metrics_fill_from_supergrid metrics_fill_from_supergrid proc~configure_ocean_metrics->proc~metrics_fill_from_supergrid proc~metrics_fill_spherical metrics_fill_spherical proc~configure_ocean_metrics->proc~metrics_fill_spherical proc~metrics_fill_tripolar metrics_fill_tripolar proc~configure_ocean_metrics->proc~metrics_fill_tripolar proc~metrics_finalize metrics_finalize proc~configure_ocean_metrics->proc~metrics_finalize proc~parse_grid_config parse_grid_config proc~configure_ocean_metrics->proc~parse_grid_config proc~tags_north_fold tags_north_fold proc~configure_ocean_metrics->proc~tags_north_fold proc~tags_periodic_x tags_periodic_x proc~configure_ocean_metrics->proc~tags_periodic_x to_string to_string proc~configure_ocean_metrics->to_string error error proc~fail->error proc~error_ring_push error_ring_push proc~fail->proc~error_ring_push proc~metrics_fill_from_supergrid->info proc~metrics_fill_from_supergrid->proc~fail proc~metrics_fill_from_supergrid->to_string nf90_inq_varid nf90_inq_varid proc~metrics_fill_from_supergrid->nf90_inq_varid proc~grid_init hgrid_t%grid_init proc~metrics_fill_from_supergrid->proc~grid_init proc~metrics_assemble_from_supergrid_arrays metrics_assemble_from_supergrid_arrays proc~metrics_fill_from_supergrid->proc~metrics_assemble_from_supergrid_arrays proc~metrics_fold_periodic_ghosts metrics_fold_periodic_ghosts proc~metrics_fill_from_supergrid->proc~metrics_fold_periodic_ghosts proc~metrics_window_all metrics_window_all proc~metrics_fill_from_supergrid->proc~metrics_window_all proc~nc_close nc_close proc~metrics_fill_from_supergrid->proc~nc_close proc~nc_get_dim_len nc_get_dim_len proc~metrics_fill_from_supergrid->proc~nc_get_dim_len proc~nc_get_var_slab_2d nc_get_var_slab_2d proc~metrics_fill_from_supergrid->proc~nc_get_var_slab_2d proc~nc_get_varid~2 nc_get_varid proc~metrics_fill_from_supergrid->proc~nc_get_varid~2 proc~nc_open_read nc_open_read proc~metrics_fill_from_supergrid->proc~nc_open_read proc~ocean_metrics_destroy ocean_metrics_t%ocean_metrics_destroy proc~metrics_fill_from_supergrid->proc~ocean_metrics_destroy proc~supergrid_angle_dx_from_geography supergrid_angle_dx_from_geography proc~metrics_fill_from_supergrid->proc~supergrid_angle_dx_from_geography proc~supergrid_io_ok supergrid_io_ok proc~metrics_fill_from_supergrid->proc~supergrid_io_ok proc~supergrid_top_row_folds supergrid_top_row_folds proc~metrics_fill_from_supergrid->proc~supergrid_top_row_folds 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_fill_tripolar->proc~metrics_window_all proc~metrics_fill_tripolar->proc~ocean_metrics_destroy proc~adcroft_recip adcroft_recip proc~metrics_finalize->proc~adcroft_recip proc~ocean_bc_type_from_string ocean_bc_type_from_string proc~tags_north_fold->proc~ocean_bc_type_from_string proc~tags_periodic_x->proc~ocean_bc_type_from_string 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 proc~metrics_fill_tripolar_whole->proc~metrics_assemble_from_supergrid_arrays proc~metrics_fill_tripolar_whole->proc~metrics_fold_periodic_ghosts 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 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~metrics_window_2d metrics_window_2d proc~metrics_window_all->proc~metrics_window_2d nf90_close nf90_close proc~nc_close->nf90_close proc~nc_check nc_check proc~nc_close->proc~nc_check nf90_inq_dimid nf90_inq_dimid proc~nc_get_dim_len->nf90_inq_dimid nf90_inquire_dimension nf90_inquire_dimension proc~nc_get_dim_len->nf90_inquire_dimension proc~nc_get_dim_len->proc~nc_check nf90_get_var nf90_get_var proc~nc_get_var_slab_2d->nf90_get_var proc~nc_get_var_slab_2d->proc~nc_check proc~nc_get_varid~2->nf90_inq_varid proc~nc_get_varid~2->proc~nc_check nf90_open nf90_open proc~nc_open_read->nf90_open proc~nc_open_read->proc~nc_check to_lower to_lower proc~ocean_bc_type_from_string->to_lower proc~supergrid_io_ok->proc~nc_close none~unit_vector unit_vector proc~supergrid_top_row_folds->none~unit_vector 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~nc_check->proc~fail nf90_strerror nf90_strerror proc~nc_check->nf90_strerror 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_corner_2d fold_north_corner_2d interface~fold_north_corner->proc~fold_north_corner_2d 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

Called by

proc~~configure_ocean_metrics~~CalledByGraph proc~configure_ocean_metrics configure_ocean_metrics 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
integer, private :: gc
integer, private :: local_ierr

Source Code

   subroutine configure_ocean_metrics(cfg, ocean_state, grid, compute_rank, ierr)
      !! Fill the `ocean_metrics_t` slot per `cfg%ocean%grid%grid_config`,
      !! then single-source the inverses + hvisc ratio bundle
      !! (`metrics_finalize`).  Must run BEFORE `ocean_state_enter_data`
      !! (the host fill is what the GPU copyin captures).  For
      !! "spherical", the `&grid_nml dx`/`dy` are reinterpreted as
      !! dlon/dlat in degrees.
      type(config_t), intent(in) :: cfg
      type(ocean_state_t), intent(inout) :: ocean_state
      type(hgrid_t), intent(in) :: grid
      integer, intent(in) :: compute_rank
      integer, intent(out), optional :: ierr
         !! Non-zero on a grid/geometry configuration failure when present;
         !! absent behaves as today (`error stop`).

      integer :: gc, local_ierr

      gc = parse_grid_config(cfg%ocean%grid%grid_config)
      select case (gc)
      case (GRID_CONFIG_SPHERICAL)
         ! Validation the schema can't express (cross-knob domain check).
         if (cfg%ocean%grid%rad_earth <= 0.0_wp) then
            call fail("configure_ocean_metrics: spherical grid needs rad_earth > 0", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         ! Include ghost rows: the generator fills ghost rows beyond the physical
         ! edge by formula (see metrics_fill_spherical), so the most extreme
         ! latitude reached is lat_south - (nghost+0.5)*dlat (south ghost centre)
         ! and lat_south + (ny_phys+nghost+0.5)*dlat (north ghost centre).
         ! Near-pole sectors need tripolar treatment (M3 follow-up).
         if (cfg%ocean%grid%lat_south - (real(grid%nghost, wp) + 0.5_wp)*grid%dy < -90.0_wp .or. &
             cfg%ocean%grid%lat_south + real(grid%ny_phys + grid%nghost, wp)*grid%dy + &
             0.5_wp*grid%dy > 90.0_wp) then
            call fail("configure_ocean_metrics: spherical domain (including ghost rows) "// &
                      "exceeds |lat| <= 90. Near-pole sectors need tripolar treatment (M3).", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         ! grid%dx / grid%dy are dlon / dlat in DEGREES here.
         call metrics_fill_spherical(ocean_state%metrics, grid, &
                                     cfg%ocean%grid%lon_west, cfg%ocean%grid%lat_south, &
                                     grid%dx, grid%dy, cfg%ocean%grid%rad_earth)
         if (compute_rank == 0) then
            call logger%info("Grid config:      spherical lon-lat sector")
         end if
      case (GRID_CONFIG_SUPERGRID)
         if (len_trim(cfg%ocean%grid%supergrid_file) == 0) then
            call fail("configure_ocean_metrics: grid_config='supergrid' "// &
                      "requires supergrid_file to be set in &ocean_grid_nml", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         ! ierr threaded down ONLY when THIS routine's own ierr is
         ! present: otherwise metrics_fill_from_supergrid must keep
         ! reaching its own `error stop` (specific dimension-mismatch /
         ! NetCDF-failure text) rather than the generic wrapper message
         ! below (P0.1 review F2).
         !
         ! The edge tags decide the ghost-metric topology (periodic-x wrap,
         ! tripolar fold) exactly as they do for the analytic tripolar; the
         ! reader cross-checks the fold against the file's own top row.
         if (present(ierr)) then
            call metrics_fill_from_supergrid(ocean_state%metrics, grid, &
                                             cfg%ocean%grid%supergrid_file, ierr=local_ierr, &
                                             periodic_x=tags_periodic_x(cfg), &
                                             north_fold=tags_north_fold(cfg))
            if (local_ierr /= 0) then
               ierr = local_ierr
               return
            end if
         else
            call metrics_fill_from_supergrid(ocean_state%metrics, grid, &
                                             cfg%ocean%grid%supergrid_file, &
                                             periodic_x=tags_periodic_x(cfg), &
                                             north_fold=tags_north_fold(cfg))
         end if
         if (compute_rank == 0) then
            call logger%info("Grid config:      supergrid (mosaic) from "// &
                             trim(cfg%ocean%grid%supergrid_file))
         end if
      case (GRID_CONFIG_TRIPOLAR)
         ! Cross-knob domain checks the schema can't express.
         if (cfg%ocean%grid%rad_earth <= 0.0_wp) then
            call fail("configure_ocean_metrics: tripolar grid needs rad_earth > 0", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         if (cfg%ocean%grid%phi_join <= cfg%ocean%grid%lat_south) then
            call fail("configure_ocean_metrics: tripolar phi_join must be "// &
                      "north of lat_south (the cap sits above the lon-lat region)", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         ! Tripolar requires an east-west PERIODIC grid: the i-direction
         ! wraps the full 360 deg of pseudo-longitude and the north fold
         ! identifies the two halves of the top row.  Without periodic-x
         ! the wrap + fold exchange (M4c) is ill-defined.
         if (trim(cfg%ocean%bc%west) /= "periodic" .or. &
             trim(cfg%ocean%bc%east) /= "periodic") then
            call fail("configure_ocean_metrics: grid_config='tripolar' requires "// &
                      "periodic east-west BCs (&ocean_bc_nml west='periodic' east='periodic')", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         ! A tripolar grid MUST close the top with the north fold; otherwise
         ! the duplicated top-row DOFs are never reconciled and the cap
         ! diverges.  (The reverse — fold tag requires a tripolar grid — is
         ! enforced by ocean_bc_validate_fold's periodic-w/e requirement plus
         ! this check.)
         if (trim(cfg%ocean%bc%north) /= "tripolar_fold") then
            call fail("configure_ocean_metrics: grid_config='tripolar' requires "// &
                      "north='tripolar_fold' (&ocean_bc_nml north='tripolar_fold')", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         ! grid%dx / grid%dy are dlon / dlat in DEGREES here (as spherical).
         call metrics_fill_tripolar(ocean_state%metrics, grid, &
                                    cfg%ocean%grid%lon_west, cfg%ocean%grid%lat_south, &
                                    grid%dx, grid%dy, cfg%ocean%grid%rad_earth, &
                                    cfg%ocean%grid%phi_join, cfg%ocean%grid%lon_pole)
         if (compute_rank == 0) then
            call logger%info("Grid config:      tripolar (Murray 1996), phi_join="// &
                             to_string(cfg%ocean%grid%phi_join)//" lon_pole="// &
                             to_string(cfg%ocean%grid%lon_pole))
         end if
      case default   ! GRID_CONFIG_CARTESIAN
         call metrics_fill_cartesian(ocean_state%metrics, grid, grid%dx, grid%dy)
      end select

      call metrics_finalize(ocean_state%metrics)
      if (present(ierr)) ierr = OCEAN_STATUS_OK
   end subroutine configure_ocean_metrics