pd_limit_meridional_impl Subroutine

private subroutine pd_limit_meridional_impl(nx, ny, nz, dt, h_lim, iareaT, h_layer, mass_flux_y, theta, n_limited, v_cor)

Positive-definite per-donor outflux limiter — meridional (y) pass (P2). Mirror of pd_limit_zonal_impl; reads the post-zonal-apply h_layer (= h*), which is exactly the availability the second Lie pass must respect, and scales mass_flux_y so h_layer >= h_lim holds after continuity_apply_meridional. Cell (i,j,k) outflow = (north face j+1 when positive) + (south face j when negative); interior face j ∈ 2..ny scaled by its upwind donor’s θ (south cell j−1 when the face flux ≥ 0, else north cell j). See the zonal twin for the θ construction, ghost range, MPI-seam determinism, and the v1.1 v_cor re-matching rationale (MOM6 v_cor scaled by the same per-face θ so it stays consistent with the limited flux).

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nz
real(kind=wp), intent(in) :: dt
real(kind=wp), intent(in) :: h_lim
real(kind=wp), intent(in) :: iareaT(nx,ny)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(inout) :: mass_flux_y(nx,ny+1,nz)
real(kind=wp), intent(inout) :: theta(nx,ny,nz)
integer, intent(inout) :: n_limited
real(kind=wp), intent(inout), optional :: v_cor(nx,ny+1,nz)

MOM6 v_cor capture; when present, re-scaled by the SAME per-face θ as mass_flux_y so it stays consistent with the limited flux the mom6-scheme corrector reads.


Calls

proc~~pd_limit_meridional_impl~~CallsGraph proc~pd_limit_meridional_impl pd_limit_meridional_impl local local proc~pd_limit_meridional_impl->local reduce reduce proc~pd_limit_meridional_impl->reduce

Called by

proc~~pd_limit_meridional_impl~~CalledByGraph proc~pd_limit_meridional_impl pd_limit_meridional_impl proc~continuity_tracer_step_split continuity_tracer_step_split proc~continuity_tracer_step_split->proc~pd_limit_meridional_impl proc~run_continuity_chain run_continuity_chain proc~run_continuity_chain->proc~continuity_tracer_step_split proc~run_stage run_stage proc~run_stage->proc~continuity_tracer_step_split proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage proc~run_stage_split run_stage_split proc~run_stage_split->proc~run_continuity_chain proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step proc~ocean_dyn_step_split ocean_dyn_step_split proc~engine_step->proc~ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_stage_split proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_step proc~rdb_ocean_step rdb_ocean_step proc~rdb_ocean_step->proc~engine_step

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: avail
real(kind=wp), private :: demand
logical, private :: do_vcor
integer, private :: i
integer, private :: j
integer, private :: k
integer, private :: n_lim
real(kind=wp), private :: out_n
real(kind=wp), private :: out_s
real(kind=wp), private :: outflow
real(kind=wp), private :: th_face

Source Code

   subroutine pd_limit_meridional_impl(nx, ny, nz, dt, h_lim, iareaT, h_layer, &
                                       mass_flux_y, theta, n_limited, v_cor)
      !! Positive-definite per-donor outflux limiter — meridional (y) pass
      !! (P2).  Mirror of `pd_limit_zonal_impl`; reads the post-zonal-apply
      !! `h_layer` (= h*), which is exactly the availability the second Lie
      !! pass must respect, and scales `mass_flux_y` so `h_layer >= h_lim`
      !! holds after `continuity_apply_meridional`.  Cell `(i,j,k)` outflow =
      !! (north face `j+1` when positive) + (south face `j` when negative);
      !! interior face `j ∈ 2..ny` scaled by its upwind donor's θ (south cell
      !! `j−1` when the face flux ≥ 0, else north cell `j`).  See the zonal
      !! twin for the θ construction, ghost range, MPI-seam determinism, and
      !! the v1.1 `v_cor` re-matching rationale (MOM6 `v_cor` scaled by the same
      !! per-face θ so it stays consistent with the limited flux).
      integer, intent(in) :: nx, ny, nz
      real(wp), intent(in) :: dt, h_lim
      real(wp), intent(in) :: iareaT(nx, ny)
      real(wp), intent(in) :: h_layer(nx, ny, nz)
      real(wp), intent(inout) :: mass_flux_y(nx, ny + 1, nz)
      real(wp), intent(inout) :: theta(nx, ny, nz)
      integer, intent(inout) :: n_limited
      real(wp), intent(inout), optional :: v_cor(nx, ny + 1, nz)
         !! MOM6 `v_cor` capture; when present, re-scaled by the SAME per-face θ
         !! as `mass_flux_y` so it stays consistent with the limited flux the
         !! mom6-scheme corrector reads.

      integer :: i, j, k, n_lim
      real(wp) :: out_n, out_s, outflow, demand, avail, th_face
      logical :: do_vcor

      do_vcor = present(v_cor)

      do concurrent(k=1:nz, j=1:ny, i=1:nx) &
         local(out_n, out_s, outflow, demand, avail)
         out_n = max(mass_flux_y(i, j + 1, k), 0.0_wp)
         out_s = max(-mass_flux_y(i, j, k), 0.0_wp)
         outflow = out_n + out_s
         demand = dt*outflow*iareaT(i, j)
         avail = max(h_layer(i, j, k) - h_lim, 0.0_wp)
         theta(i, j, k) = merge(avail/max(demand, H_DIV_EPS), 1.0_wp, demand > avail)
      end do

      ! v1.1: re-match v_cor to the limited flux (UNSCALED-flux donor sign),
      ! before the mass-flux sweep.  See the zonal twin.
      if (do_vcor) then
         do concurrent(k=1:nz, j=2:ny, i=1:nx) local(th_face)
            if (mass_flux_y(i, j, k) >= 0.0_wp) then
               th_face = theta(i, j - 1, k)
            else
               th_face = theta(i, j, k)
            end if
            v_cor(i, j, k) = v_cor(i, j, k)*th_face
         end do
      end if

      n_lim = 0
      do concurrent(k=1:nz, j=2:ny, i=1:nx) local(th_face) reduce(+:n_lim)
         if (mass_flux_y(i, j, k) >= 0.0_wp) then
            th_face = theta(i, j - 1, k)
         else
            th_face = theta(i, j, k)
         end if
         if (th_face < 1.0_wp .and. mass_flux_y(i, j, k) /= 0.0_wp) n_lim = n_lim + 1
         mass_flux_y(i, j, k) = mass_flux_y(i, j, k)*th_face
      end do
      n_limited = n_limited + n_lim
   end subroutine pd_limit_meridional_impl