ocean_surfstress_set_neverworld2 Subroutine

private subroutine ocean_surfstress_set_neverworld2(this, grid, taux_mag, j_offset, ny_global)

Fill tau_x with the Neverworld2 zonal wind-stress profile (Marques et al. 2022, GMD; MOM6-inspired) and zero tau_y. τ_x is a 3-band piecewise function of the normalized meridional position y = (j_phys − 0.5)/ny_phys ∈ [0,1] (which equals MOM6’s (lat − south)/len_lat on a uniform grid), scaled by the peak stress taux_mag (Pa), with off = 0.02:

band 1 y ≤ 0.29: τ = taux·[ (1/0.29)·y − (1/2π)·sin(2π·y/0.29) ] band 2 0.29 < y ≤ 0.8−off: τ = taux·[ 0.35 + 0.65·cos(π·(y−0.29)/(0.51−off)) ] band 3 0.8−off < y ≤ 1−off: τ = taux·[ 1.5·((y−1+off) − (0.1/π)·sin(10π·(y−0.8+off))) ] else (polar): τ = 0

This reproduces the canonical southern-westerlies / trades / polar-easterlies pattern. τ_y ≡ 0. Every storage row inside the GLOBAL domain (seam ghost rows included, as for 2gyre); the rows beyond the global edges stay at zero so wall faces see no spurious stress (land masking is applied downstream via wet_mask in the stress-acceleration kernel). Host only — call enter_data afterwards.

j_offset is the global physical-index offset of this rank’s first physical row (= decomp%j_start - 1). ny_global is the global meridional physical extent. Both default to the single-rank values, preserving byte-identical behaviour.

Type Bound

ocean_surface_stress_t

Arguments

Type IntentOptional Attributes Name
class(ocean_surface_stress_t), intent(inout) :: this
type(hgrid_t), intent(in) :: grid
real(kind=wp), intent(in) :: taux_mag
integer, intent(in), optional :: j_offset
integer, intent(in), optional :: ny_global

Calls

proc~~ocean_surfstress_set_neverworld2~~CallsGraph proc~ocean_surfstress_set_neverworld2 ocean_surface_stress_t%ocean_surfstress_set_neverworld2 proc~ocean_surfstress_refresh_stress_mag ocean_surfstress_refresh_stress_mag proc~ocean_surfstress_set_neverworld2->proc~ocean_surfstress_refresh_stress_mag proc~ocean_surface_stress_refresh_mag ocean_surface_stress_refresh_mag proc~ocean_surfstress_refresh_stress_mag->proc~ocean_surface_stress_refresh_mag proc~ocean_surfstress_derived_impl ocean_surfstress_derived_impl proc~ocean_surface_stress_refresh_mag->proc~ocean_surfstress_derived_impl local local proc~ocean_surfstress_derived_impl->local

Called by

proc~~ocean_surfstress_set_neverworld2~~CalledByGraph proc~ocean_surfstress_set_neverworld2 ocean_surface_stress_t%ocean_surfstress_set_neverworld2 proc~configure_ocean_forcing configure_ocean_forcing proc~configure_ocean_forcing->proc~ocean_surfstress_set_neverworld2 proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_forcing 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
real(kind=wp), private, parameter :: OFF = 0.02_wp
real(kind=wp), private, parameter :: PI = 4.0_wp*atan(1.0_wp)
real(kind=wp), private, parameter :: TWO_PI = 8.0_wp*atan(1.0_wp)
integer, private :: i
integer, private :: j
integer, private :: j_phys
integer, private :: joff
integer, private :: ng
integer, private :: nyg
real(kind=wp), private :: y

Source Code

   subroutine ocean_surfstress_set_neverworld2(this, grid, taux_mag, j_offset, ny_global)
      !! Fill `tau_x` with the **Neverworld2** zonal wind-stress profile
      !! (Marques et al. 2022, GMD; MOM6-inspired) and zero `tau_y`.  τ_x is a
      !! 3-band piecewise function of the normalized meridional position
      !! `y = (j_phys − 0.5)/ny_phys ∈ [0,1]` (which equals MOM6's
      !! `(lat − south)/len_lat` on a uniform grid), scaled by the peak stress
      !! `taux_mag` (Pa), with `off = 0.02`:
      !!
      !!   band 1  y ≤ 0.29:           τ = taux·[ (1/0.29)·y − (1/2π)·sin(2π·y/0.29) ]
      !!   band 2  0.29 < y ≤ 0.8−off: τ = taux·[ 0.35 + 0.65·cos(π·(y−0.29)/(0.51−off)) ]
      !!   band 3  0.8−off < y ≤ 1−off: τ = taux·[ 1.5·((y−1+off) − (0.1/π)·sin(10π·(y−0.8+off))) ]
      !!   else (polar):               τ = 0
      !!
      !! This reproduces the canonical southern-westerlies / trades /
      !! polar-easterlies pattern.  τ_y ≡ 0.  Every storage row inside the
      !! GLOBAL domain (seam ghost rows included, as for 2gyre); the rows
      !! beyond the global edges stay at zero so wall faces see no spurious stress (land
      !! masking is applied downstream via `wet_mask` in the stress-acceleration
      !! kernel).  Host only — call `enter_data` afterwards.
      !!
      !! `j_offset` is the global physical-index offset of this rank's
      !! first physical row (= `decomp%j_start - 1`).  `ny_global` is
      !! the global meridional physical extent.  Both default to the
      !! single-rank values, preserving byte-identical behaviour.
      class(ocean_surface_stress_t), intent(inout) :: this
      type(hgrid_t), intent(in) :: grid
      real(wp), intent(in) :: taux_mag
      integer, intent(in), optional :: j_offset, ny_global
      real(wp), parameter :: PI = 4.0_wp*atan(1.0_wp)
      real(wp), parameter :: TWO_PI = 8.0_wp*atan(1.0_wp)
      real(wp), parameter :: OFF = 0.02_wp
      real(wp) :: y
      integer :: i, j, j_phys, ng
      integer :: joff, nyg

      joff = 0
      if (present(j_offset)) joff = j_offset
      nyg = grid%ny_phys
      if (present(ny_global)) nyg = ny_global

      this%tau_x = 0.0_wp
      this%tau_y = 0.0_wp
      ng = grid%nghost
      do j = 1, size(this%tau_x, 2)
         j_phys = j - ng
         ! Every storage row inside the GLOBAL domain (see the 2gyre setter).
         if (j_phys + joff < 1 .or. j_phys + joff > nyg) cycle
         ! Global meridional normalisation: (j_phys + joff) gives the
         ! global physical row index; nyg is the global extent.
         y = (real(j_phys + joff, wp) - 0.5_wp)/real(nyg, wp)
         do i = 1, size(this%tau_x, 1)
            if (y <= 0.29_wp) then
               this%tau_x(i, j) = taux_mag*((1.0_wp/0.29_wp)*y &
                                            - (1.0_wp/TWO_PI)*sin(TWO_PI*y/0.29_wp))
            else if (y <= 0.8_wp - OFF) then
               this%tau_x(i, j) = taux_mag*(0.35_wp + 0.65_wp*cos(PI*(y - 0.29_wp)/(0.51_wp - OFF)))
            else if (y <= 1.0_wp - OFF) then
               this%tau_x(i, j) = taux_mag*(1.5_wp*((y - 1.0_wp + OFF) &
                                                    - (0.1_wp/PI)*sin(10.0_wp*PI*(y - 0.8_wp + OFF))))
            end if
         end do
      end do
      call ocean_surfstress_refresh_stress_mag(this)
   end subroutine ocean_surfstress_set_neverworld2