tracer_advect_meridional_one_impl Subroutine

private pure subroutine tracer_advect_meridional_one_impl(nx, ny, nz, dt, iareaT, wet_T, h, hTr, mass_flux_y, Tr_face_left_y, Tr_face_right_y, budget_adv, budget_w)

Meridional half of tracer_advect_one_impl. Same shape as the zonal impl, applied to y. In the split flow, h here is the post-zonal-apply thickness so the Tr = hTr/h reconstruction stays consistent with what continuity used in continuity_meridional_flux. iareaT = inv_dy on uniform metrics; mass_flux_y carries dx_cv. Mirror-T at land neighbours (C2); bit-identical for all-wet.

Optional budget_adv: accumulates −dt·(Tr_face_left_y(i,j+1) −Tr_face_left_y(i,j))·iareaT into budget_adv. Absent ⇒ inert. Called in sequence after the zonal impl so the two directions compose via += into the same accumulator array.

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) :: iareaT(nx,ny)
real(kind=wp), intent(in) :: wet_T(nx,ny)
real(kind=wp), intent(in) :: h(nx,ny,nz)
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(in) :: mass_flux_y(nx,ny+1,nz)
real(kind=wp), intent(inout) :: Tr_face_left_y(nx,ny+1,nz)
real(kind=wp), intent(inout) :: Tr_face_right_y(nx,ny+1,nz)
real(kind=wp), intent(inout), optional :: budget_adv(nx,ny,nz)

Per-cell meridional-advection budget accumulator (PSU·m or °C·m per cell). Added to the same array as the zonal half so the net entry covers both directions. Absent ⇒ inert.

real(kind=wp), intent(in), optional :: budget_w

Bookkeeping weight on the budget_adv increment; see the zonal impl. Absent ⇒ 1, bit-identical.


Calls

proc~~tracer_advect_meridional_one_impl~~CallsGraph proc~tracer_advect_meridional_one_impl tracer_advect_meridional_one_impl local local proc~tracer_advect_meridional_one_impl->local proc~ppm_cell_limiter ppm_cell_limiter proc~tracer_advect_meridional_one_impl->proc~ppm_cell_limiter proc~ppm_limited_slope ppm_limited_slope proc~tracer_advect_meridional_one_impl->proc~ppm_limited_slope proc~ppm_mirror_h ppm_mirror_h proc~tracer_advect_meridional_one_impl->proc~ppm_mirror_h

Called by

proc~~tracer_advect_meridional_one_impl~~CalledByGraph proc~tracer_advect_meridional_one_impl tracer_advect_meridional_one_impl proc~gm_tracer_advect_y gm_tracer_advect_y proc~gm_tracer_advect_y->proc~tracer_advect_meridional_one_impl proc~tracer_advect_meridional tracer_advect_meridional proc~tracer_advect_meridional->proc~tracer_advect_meridional_one_impl proc~continuity_gm_apply continuity_gm_apply proc~continuity_gm_apply->proc~gm_tracer_advect_y proc~continuity_tracer_step_split continuity_tracer_step_split proc~continuity_tracer_step_split->proc~tracer_advect_meridional proc~run_continuity_chain run_continuity_chain proc~run_continuity_chain->proc~continuity_tracer_step_split proc~run_gm_step run_gm_step proc~run_gm_step->proc~continuity_gm_apply 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~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_gm_step proc~run_stage_split run_stage_split proc~ocean_dyn_step_split->proc~run_stage_split proc~run_stage_split->proc~run_continuity_chain 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 :: Tr_0
real(kind=wp), private :: Tr_face
real(kind=wp), private :: Tr_left
real(kind=wp), private :: Tr_m1
real(kind=wp), private :: Tr_m2
real(kind=wp), private :: Tr_p1
real(kind=wp), private :: Tr_p2
real(kind=wp), private :: Tr_right
real(kind=wp), private :: dh_0
real(kind=wp), private :: dh_m1
real(kind=wp), private :: dh_p1
real(kind=wp), private :: dt_b
integer, private :: i
integer, private :: j
integer, private :: k
real(kind=wp), private :: mass_y

Source Code

   pure subroutine tracer_advect_meridional_one_impl(nx, ny, nz, dt, iareaT, wet_T, h, hTr, &
                                                     mass_flux_y, &
                                                     Tr_face_left_y, Tr_face_right_y, &
                                                     budget_adv, budget_w)
      !! Meridional half of `tracer_advect_one_impl`.  Same shape
      !! as the zonal impl, applied to y.  In the split flow, `h`
      !! here is the post-zonal-apply thickness so the Tr = hTr/h
      !! reconstruction stays consistent with what continuity used
      !! in `continuity_meridional_flux`.  `iareaT` = `inv_dy` on
      !! uniform metrics; `mass_flux_y` carries `dx_cv`.  Mirror-T at
      !! land neighbours (C2); bit-identical for all-wet.
      !!
      !! Optional `budget_adv`: accumulates `−dt·(Tr_face_left_y(i,j+1)
      !! −Tr_face_left_y(i,j))·iareaT` into `budget_adv`.  Absent ⇒
      !! inert.  Called in sequence after the zonal impl so the two
      !! directions compose via `+=` into the same accumulator array.
      integer, intent(in) :: nx, ny, nz
      real(wp), intent(in) :: dt
      real(wp), intent(in) :: iareaT(nx, ny)
      real(wp), intent(in) :: wet_T(nx, ny)
      real(wp), intent(in) :: h(nx, ny, nz)
      real(wp), intent(inout) :: hTr(nx, ny, nz)
      real(wp), intent(in) :: mass_flux_y(nx, ny + 1, nz)
      real(wp), intent(inout) :: Tr_face_left_y(nx, ny + 1, nz)
      real(wp), intent(inout) :: Tr_face_right_y(nx, ny + 1, nz)
      real(wp), intent(inout), optional :: budget_adv(nx, ny, nz)
         !! Per-cell meridional-advection budget accumulator (PSU·m or
         !! °C·m per cell).  Added to the same array as the zonal half
         !! so the net entry covers both directions.  Absent ⇒ inert.
      real(wp), intent(in), optional :: budget_w
         !! Bookkeeping weight on the `budget_adv` increment; see the
         !! zonal impl.  Absent ⇒ 1, bit-identical.

      integer :: i, j, k
      real(wp) :: Tr_m2, Tr_m1, Tr_0, Tr_p1, Tr_p2
      real(wp) :: dh_m1, dh_0, dh_p1, Tr_left, Tr_right
      real(wp) :: mass_y, Tr_face, dt_b

      do concurrent(k=1:nz, j=3:ny - 2, i=1:nx) &
         local(Tr_m2, Tr_m1, Tr_0, Tr_p1, Tr_p2, &
               dh_m1, dh_0, dh_p1, Tr_left, Tr_right)
         Tr_0 = hTr(i, j, k)/h(i, j, k)
         Tr_m1 = ppm_mirror_h(hTr(i, j - 1, k)/h(i, j - 1, k), Tr_0, wet_T(i, j - 1))
         Tr_p1 = ppm_mirror_h(hTr(i, j + 1, k)/h(i, j + 1, k), Tr_0, wet_T(i, j + 1))
         Tr_m2 = ppm_mirror_h(hTr(i, j - 2, k)/h(i, j - 2, k), Tr_m1, wet_T(i, j - 2))
         Tr_p2 = ppm_mirror_h(hTr(i, j + 2, k)/h(i, j + 2, k), Tr_p1, wet_T(i, j + 2))
         call ppm_limited_slope(Tr_m2, Tr_m1, Tr_0, dh_m1)
         call ppm_limited_slope(Tr_m1, Tr_0, Tr_p1, dh_0)
         call ppm_limited_slope(Tr_0, Tr_p1, Tr_p2, dh_p1)
         dh_0 = dh_0*wet_T(i, j - 1)*wet_T(i, j)*wet_T(i, j + 1)
         Tr_left = 0.5_wp*(Tr_m1 + Tr_0) - (dh_0 - dh_m1)/6.0_wp
         Tr_right = 0.5_wp*(Tr_0 + Tr_p1) - (dh_p1 - dh_0)/6.0_wp
         call ppm_cell_limiter(Tr_0, Tr_left, Tr_right)
         Tr_face_right_y(i, j, k) = Tr_left
         Tr_face_left_y(i, j + 1, k) = Tr_right
      end do
      do concurrent(k=1:nz, i=1:nx)
         Tr_face_left_y(i, 1, k) = hTr(i, 1, k)/h(i, 1, k)
         Tr_face_right_y(i, 1, k) = hTr(i, 1, k)/h(i, 1, k)
         Tr_face_left_y(i, 2, k) = hTr(i, 1, k)/h(i, 1, k)
         Tr_face_right_y(i, 2, k) = hTr(i, 2, k)/h(i, 2, k)
         Tr_face_left_y(i, 3, k) = hTr(i, 2, k)/h(i, 2, k)
         Tr_face_right_y(i, 3, k) = hTr(i, 2, k)/h(i, 2, k)
         Tr_face_right_y(i, ny - 1, k) = hTr(i, ny - 1, k)/h(i, ny - 1, k)
         Tr_face_left_y(i, ny, k) = hTr(i, ny - 1, k)/h(i, ny - 1, k)
         Tr_face_right_y(i, ny, k) = hTr(i, ny, k)/h(i, ny, k)
         Tr_face_left_y(i, ny + 1, k) = hTr(i, ny, k)/h(i, ny, k)
         Tr_face_right_y(i, ny + 1, k) = hTr(i, ny, k)/h(i, ny, k)
      end do

      do concurrent(k=1:nz, j=1:ny + 1, i=1:nx) local(mass_y, Tr_face)
         mass_y = mass_flux_y(i, j, k)
         if (mass_y >= 0.0_wp) then
            Tr_face = Tr_face_left_y(i, j, k)
         else
            Tr_face = Tr_face_right_y(i, j, k)
         end if
         Tr_face_left_y(i, j, k) = mass_y*Tr_face
      end do

      do concurrent(k=1:nz, j=1:ny, i=1:nx)
         hTr(i, j, k) = hTr(i, j, k) - dt* &
                        (Tr_face_left_y(i, j + 1, k) - Tr_face_left_y(i, j, k))*iareaT(i, j)
      end do

      ! Budget accumulator: same guarded pattern as the zonal half.
      if (present(budget_adv)) then
         dt_b = dt
         if (present(budget_w)) dt_b = dt*budget_w
         do concurrent(k=1:nz, j=1:ny, i=1:nx)
            budget_adv(i, j, k) = budget_adv(i, j, k) - dt_b* &
                                  (Tr_face_left_y(i, j + 1, k) - Tr_face_left_y(i, j, k))*iareaT(i, j)
         end do
      end if
   end subroutine tracer_advect_meridional_one_impl