apply_cartesian_degrees Subroutine

private subroutine apply_cartesian_degrees(cfg)

Post-parse Cartesian domain sizing (MOM6 GRID_CONFIG=”cartesian” + AXIS_UNITS / LENLON / LENLAT). When &ocean_grid_nml len_lon/len_lat are set (> 0) on an ocean Cartesian grid, DERIVE the uniform &grid_nml dx/dy (metres) from the domain extent, the physical cell count (nx/ny = MOM6 NIGLOBAL/NJGLOBAL) and axis_units, exactly as MOM6’s set_grid_metrics_cartesian: degrees : dx = rad_earth · len_lon · π/180 / nx (arc length, no cos(lat)) km : dx = 1000 · len_lon / nx meters : dx = len_lon / nx and likewise dy from len_lat / ny. This runs BEFORE grid init, so the metrics, barotropic CFL and Coriolis all see the derived metres. Default (len_lon <= 0) leaves dx/dy untouched ⇒ bit-identical.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(inout) :: cfg

Calls

proc~~apply_cartesian_degrees~~CallsGraph proc~apply_cartesian_degrees apply_cartesian_degrees error error proc~apply_cartesian_degrees->error info info proc~apply_cartesian_degrees->info to_string to_string proc~apply_cartesian_degrees->to_string

Called by

proc~~apply_cartesian_degrees~~CalledByGraph proc~apply_cartesian_degrees apply_cartesian_degrees proc~read_config_from_string_impl read_config_from_string_impl proc~read_config_from_string_impl->proc~apply_cartesian_degrees proc~read_config_impl read_config_impl proc~read_config_impl->proc~apply_cartesian_degrees proc~read_config read_config proc~read_config->proc~read_config_impl proc~read_config_from_string read_config_from_string proc~read_config_from_string->proc~read_config_from_string_impl proc~build_pending_handle build_pending_handle proc~build_pending_handle->proc~read_config_from_string proc~rdb_ocean_create_from_string rdb_ocean_create_from_string proc~rdb_ocean_create_from_string->proc~build_pending_handle proc~rdb_ocean_create_pending rdb_ocean_create_pending proc~rdb_ocean_create_pending->proc~build_pending_handle

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: dx_scale
real(kind=wp), private :: dy_scale

Source Code

   subroutine apply_cartesian_degrees(cfg)
      !! Post-parse Cartesian domain sizing (MOM6 GRID_CONFIG="cartesian" +
      !! AXIS_UNITS / LENLON / LENLAT).  When `&ocean_grid_nml len_lon`/`len_lat`
      !! are set (> 0) on an ocean Cartesian grid, DERIVE the uniform
      !! `&grid_nml dx`/`dy` (metres) from the domain extent, the physical cell
      !! count (`nx`/`ny` = MOM6 NIGLOBAL/NJGLOBAL) and `axis_units`, exactly as
      !! MOM6's `set_grid_metrics_cartesian`:
      !!   degrees : dx = rad_earth · len_lon · π/180 / nx  (arc length, no cos(lat))
      !!   km      : dx = 1000 · len_lon / nx
      !!   meters  : dx =        len_lon / nx
      !! and likewise dy from len_lat / ny.  This runs BEFORE grid init, so the
      !! metrics, barotropic CFL and Coriolis all see the derived metres.
      !! Default (len_lon <= 0) leaves `dx`/`dy` untouched ⇒ bit-identical.
      type(config_t), intent(inout) :: cfg

      real(wp) :: dx_scale, dy_scale

      ! Opt-in: only engage when the extent knobs are set.
      if (cfg%ocean%grid%len_lon <= 0.0_wp .and. cfg%ocean%grid%len_lat <= 0.0_wp) return

      if (trim(cfg%sim_type) /= "ocean") then
         call logger%error("len_lon/len_lat are &ocean_grid_nml knobs; "// &
                           "set sim_type='ocean' to use them")
         return
      end if
      if (trim(cfg%ocean%grid%grid_config) /= "cartesian") then
         call logger%error("len_lon/len_lat (MOM6 LENLON/LENLAT) apply to "// &
                           "grid_config='cartesian' only (got '"// &
                           trim(cfg%ocean%grid%grid_config)//"'); the spherical/"// &
                           "tripolar paths already read &grid_nml dx/dy as degrees")
         return
      end if
      if (cfg%ocean%grid%len_lon <= 0.0_wp .or. cfg%ocean%grid%len_lat <= 0.0_wp) then
         call logger%error("len_lon AND len_lat must both be > 0 to size the "// &
                           "Cartesian domain (got len_lon="// &
                           to_string(cfg%ocean%grid%len_lon)//", len_lat="// &
                           to_string(cfg%ocean%grid%len_lat)//")")
         return
      end if

      ! Per-unit metres-per-degree/km/metre scale (applied to len/N below).
      select case (trim(cfg%ocean%grid%axis_units))
      case ("meters", "meter", "m")
         dx_scale = 1.0_wp
         dy_scale = 1.0_wp
      case ("km", "kilometer", "kilometers")
         dx_scale = 1000.0_wp
         dy_scale = 1000.0_wp
      case ("degrees", "degree", "deg")
         ! Arc length on a sphere of radius rad_earth; NO cos(lat) — MOM6's
         ! Cartesian grid is a flat plane, unlike its spherical grid.
         dx_scale = cfg%ocean%grid%rad_earth*DEG2RAD
         dy_scale = cfg%ocean%grid%rad_earth*DEG2RAD
      case default
         call logger%error("Invalid axis_units = '"// &
                           trim(cfg%ocean%grid%axis_units)// &
                           "': must be meters/degrees/km")
         return
      end select

      cfg%dx = dx_scale*cfg%ocean%grid%len_lon/real(cfg%nx, wp)
      cfg%dy = dy_scale*cfg%ocean%grid%len_lat/real(cfg%ny, wp)

      call logger%info("Cartesian domain sized from extent (MOM6-style): len_lon="// &
                       to_string(cfg%ocean%grid%len_lon)//", len_lat="// &
                       to_string(cfg%ocean%grid%len_lat)//" "// &
                       trim(cfg%ocean%grid%axis_units)//" over "// &
                       to_string(cfg%nx)//"x"//to_string(cfg%ny)//" cells => dx="// &
                       to_string(cfg%dx)//" m, dy="//to_string(cfg%dy)//" m")
   end subroutine apply_cartesian_degrees