Fill tau_x with the MOM6 2gyre profile,
tau_x(i,j) = taux_mag · (1 − cos(2π · (y − y_south) / y_len)),
and zero tau_y. In Cartesian terms (y − y_south) / y_len
is the normalised position from the south wall of the physical
domain (0 at south, 1 at north), so the formula reduces to
taux_mag · (1 − cos(2π · ((j_phys − 0.5) / ny_phys))) with
j_phys = j − nghost. Physical-interior rows only; ghost rows
stay at zero so wall faces see no spurious stress. Host only —
call enter_data afterwards (or !$acc update device if
already mapped).
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 (0 and grid%ny_phys), preserving
byte-identical single-rank 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 | :: | 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_rel |
subroutine ocean_surfstress_set_2gyre(this, grid, taux_mag, j_offset, ny_global) !! Fill `tau_x` with the MOM6 2gyre profile, !! `tau_x(i,j) = taux_mag · (1 − cos(2π · (y − y_south) / y_len))`, !! and zero `tau_y`. In Cartesian terms `(y − y_south) / y_len` !! is the normalised position from the south wall of the physical !! domain (0 at south, 1 at north), so the formula reduces to !! `taux_mag · (1 − cos(2π · ((j_phys − 0.5) / ny_phys)))` with !! `j_phys = j − nghost`. Physical-interior rows only; ghost rows !! stay at zero so wall faces see no spurious stress. Host only — !! call `enter_data` afterwards (or `!$acc update device` if !! already mapped). !! !! `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 (`0` and `grid%ny_phys`), preserving !! byte-identical single-rank 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 :: TWO_PI = 8.0_wp*atan(1.0_wp) real(wp) :: y_rel 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, ghost rows included: ! a ghost row beyond an MPI seam is a neighbour's physical row and ! must carry its stress (read by the stress/ustar stencils), not ! the zero a wall ghost gets. Rows beyond the global edges stay 0. if (j_phys + joff < 1 .or. j_phys + joff > nyg) cycle ! Global meridional normalisation: (j_phys + joff) gives the ! global physical row index; ny_global is the global extent. y_rel = (real(j_phys + joff, wp) - 0.5_wp)/real(nyg, wp) do i = 1, size(this%tau_x, 1) this%tau_x(i, j) = taux_mag*(1.0_wp - cos(TWO_PI*y_rel)) end do end do call ocean_surfstress_refresh_stress_mag(this) end subroutine ocean_surfstress_set_2gyre