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 | Intent | Optional | 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 |
| 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 |
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