vmix_convection_impl Subroutine

private pure subroutine vmix_convection_impl(nx, ny, nzp1, kv, kt, rho_layer, h_layer, bl_depth, kd_conv, prandtl_conv, n2_thresh, rho0)

Flat, explicit-shape kernel (the “vmix incident” module – assumed-shape dummies here produced 1.4M per-launch descriptor- walk memcpys; explicit-shape only, no exceptions). Interior interfaces k = 2..nzp1-1 only; boundary interfaces k=1 (bed) and k=nzp1 (surface) stay at the closed-BC zero and are never touched (same contract as PP81 / vmix_add_kv_ml_invz2).

Depth walk copied verbatim from vmix_add_kv_ml_invz2: z accumulates the cumulative thickness of layers nz, nz-1, … down to interface k – the depth of interface k below the free surface. Masked out (left at the upstream PP81 value) above the active BL (z < bl_depth); the BL owns its own convective response (KPP w_* / EPBL convective TKE) and double-counting would over-mix and defeat that scheme’s own energetics.

N^2 expression is bit-for-bit PP81’s (vmix_compute_pp81): n2 = -g*(rho_k - rho_km1)/(rho0*dz_face), positive when stable. dz_face is gated on H_VANISHED (dynamic-vanish skip), NOT H_DIV_EPS/bare <= 0 – a pinched ZSTAR_FULL interface must be skipped, not divided by (a 0/0 there would otherwise be silently laundered to background by vmix_assemble’s default un-guarded clip).

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nzp1
real(kind=wp), intent(inout) :: kv(nx,ny,nzp1)
real(kind=wp), intent(inout) :: kt(nx,ny,nzp1)
real(kind=wp), intent(in) :: rho_layer(nx,ny,nzp1-1)
real(kind=wp), intent(in) :: h_layer(nx,ny,nzp1-1)
real(kind=wp), intent(in) :: bl_depth(nx,ny)
real(kind=wp), intent(in) :: kd_conv
real(kind=wp), intent(in) :: prandtl_conv
real(kind=wp), intent(in) :: n2_thresh
real(kind=wp), intent(in) :: rho0

Calls

proc~~vmix_convection_impl~~CallsGraph proc~vmix_convection_impl vmix_convection_impl local local proc~vmix_convection_impl->local

Called by

proc~~vmix_convection_impl~~CalledByGraph proc~vmix_convection_impl vmix_convection_impl proc~vmix_apply_convection vmix_apply_convection proc~vmix_apply_convection->proc~vmix_convection_impl proc~vmix_apply_in_stage vmix_apply_in_stage proc~vmix_apply_in_stage->proc~vmix_apply_convection proc~run_stage run_stage proc~run_stage->proc~vmix_apply_in_stage proc~run_stage_split run_stage_split proc~run_stage_split->proc~vmix_apply_in_stage proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_stage_split proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step proc~engine_step->proc~ocean_dyn_step_split

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: dz_face
integer, private :: i
integer, private :: j
integer, private :: k
real(kind=wp), private :: n2
integer, private :: nz
real(kind=wp), private :: z

Source Code

   pure subroutine vmix_convection_impl(nx, ny, nzp1, kv, kt, rho_layer, h_layer, &
                                        bl_depth, kd_conv, prandtl_conv, n2_thresh, rho0)
      !! Flat, explicit-shape kernel (the "vmix incident" module --
      !! assumed-shape dummies here produced 1.4M per-launch descriptor-
      !! walk memcpys; explicit-shape only, no exceptions).  Interior
      !! interfaces k = 2..nzp1-1 only; boundary interfaces k=1 (bed) and
      !! k=nzp1 (surface) stay at the closed-BC zero and are never
      !! touched (same contract as PP81 / `vmix_add_kv_ml_invz2`).
      !!
      !! Depth walk copied verbatim from `vmix_add_kv_ml_invz2`: `z`
      !! accumulates the cumulative thickness of layers nz, nz-1, ...
      !! down to interface k -- the depth of interface k below the free
      !! surface.  Masked out (left at the upstream PP81 value) above
      !! the active BL (`z < bl_depth`); the BL owns its own convective
      !! response (KPP w_* / EPBL convective TKE) and double-counting
      !! would over-mix and defeat that scheme's own energetics.
      !!
      !! N^2 expression is bit-for-bit PP81's (`vmix_compute_pp81`):
      !! `n2 = -g*(rho_k - rho_km1)/(rho0*dz_face)`, positive when
      !! stable.  `dz_face` is gated on `H_VANISHED` (dynamic-vanish
      !! skip), NOT `H_DIV_EPS`/bare `<= 0` -- a pinched ZSTAR_FULL
      !! interface must be skipped, not divided by (a `0/0` there would
      !! otherwise be silently laundered to background by
      !! `vmix_assemble`'s default un-guarded clip).
      integer, intent(in) :: nx, ny, nzp1
      real(wp), intent(inout) :: kv(nx, ny, nzp1)
      real(wp), intent(inout) :: kt(nx, ny, nzp1)
      real(wp), intent(in) :: rho_layer(nx, ny, nzp1 - 1)
      real(wp), intent(in) :: h_layer(nx, ny, nzp1 - 1)
      real(wp), intent(in) :: bl_depth(nx, ny)
      real(wp), intent(in) :: kd_conv, prandtl_conv, n2_thresh, rho0

      integer :: i, j, k, nz
      real(wp) :: dz_face, n2, z

      nz = nzp1 - 1

      do concurrent(j=1:ny, i=1:nx) local(k, z, dz_face, n2)
         z = 0.0_wp
         do k = nz, 2, -1
            z = z + h_layer(i, j, k)
            dz_face = 0.5_wp*(h_layer(i, j, k - 1) + h_layer(i, j, k))
            if (dz_face <= H_VANISHED) cycle
            if (z < bl_depth(i, j)) cycle
            n2 = -GRAVITY*(rho_layer(i, j, k) - rho_layer(i, j, k - 1))/(rho0*dz_face)
            if (n2 < n2_thresh) then
               kt(i, j, k) = max(kt(i, j, k), kd_conv)
               kv(i, j, k) = max(kv(i, j, k), prandtl_conv*kd_conv)
            end if
         end do
      end do
   end subroutine vmix_convection_impl