tracer_advect_zonal Subroutine

private pure subroutine tracer_advect_zonal(grid, metrics, this, ms, dt, bc)

Zonal half of the direction-split tracer advection. Mirrors tracer_advect but updates hTr using only the x-direction tracer mass flux. Companion to tracer_advect_meridional. Both are called interleaved with the continuity substeps by continuity_tracer_step_split to preserve CWC.

OBC inflow handling: when bc%<edge>%bc_type == OBC_CLAMPED and bc%<edge>%clamped_tracer(it) carries a prescribed value, the ghost-cell hTr is set so the downstream upwind pick reads the prescribed boundary value on inflow. Override is a no-op for OBC_WALL (no flux crosses the face anyway).

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_metrics_t), intent(in) :: metrics
type(continuity_t), intent(inout) :: this
type(multilayer_state_t), intent(inout) :: ms
real(kind=wp), intent(in) :: dt
type(ocean_bc_state_t), intent(in), optional :: bc

Calls

proc~~tracer_advect_zonal~~CallsGraph proc~tracer_advect_zonal tracer_advect_zonal proc~tracer_advect_zonal_one_impl tracer_advect_zonal_one_impl proc~tracer_advect_zonal->proc~tracer_advect_zonal_one_impl local local proc~tracer_advect_zonal_one_impl->local proc~ppm_cell_limiter ppm_cell_limiter proc~tracer_advect_zonal_one_impl->proc~ppm_cell_limiter proc~ppm_limited_slope ppm_limited_slope proc~tracer_advect_zonal_one_impl->proc~ppm_limited_slope proc~ppm_mirror_h ppm_mirror_h proc~tracer_advect_zonal_one_impl->proc~ppm_mirror_h

Called by

proc~~tracer_advect_zonal~~CalledByGraph proc~tracer_advect_zonal tracer_advect_zonal proc~continuity_tracer_step_split continuity_tracer_step_split proc~continuity_tracer_step_split->proc~tracer_advect_zonal 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 :: clamped_tr
integer, private :: i
integer, private :: i_e_ghost
integer, private :: i_w_ghost
integer, private :: it
integer, private :: j
integer, private :: k

Source Code

   pure subroutine tracer_advect_zonal(grid, metrics, this, ms, dt, bc)
      !! Zonal half of the direction-split tracer advection.
      !! Mirrors `tracer_advect` but updates `hTr` using
      !! only the x-direction tracer mass flux.  Companion to
      !! `tracer_advect_meridional`.  Both are called
      !! interleaved with the continuity substeps by
      !! `continuity_tracer_step_split` to preserve CWC.
      !!
      !! OBC inflow handling: when `bc%<edge>%bc_type == OBC_CLAMPED`
      !! and `bc%<edge>%clamped_tracer(it)` carries a prescribed value,
      !! the ghost-cell `hTr` is set so the downstream upwind pick
      !! reads the prescribed boundary value on inflow.  Override is
      !! a no-op for OBC_WALL (no flux crosses the face anyway).
      type(hgrid_t), intent(in) :: grid
      type(ocean_metrics_t), intent(in) :: metrics
      type(continuity_t), intent(inout) :: this
      type(multilayer_state_t), intent(inout) :: ms
      real(wp), intent(in) :: dt
      type(ocean_bc_state_t), intent(in), optional :: bc

      integer :: it, i_w_ghost, i_e_ghost, i, j, k
      real(wp) :: clamped_tr

      if (.not. allocated(ms%tracers)) return

      ! Set ALL ghost columns (i = 1..nghost) on the west side to the
      ! clamped value so the impl's hard-coded boundary-halo writes
      ! (Tr_face_*_x(1..3, ...) all read hTr(1) or hTr(2)) all see the
      ! prescribed value, regardless of which is upwind.
      i_w_ghost = grid%nghost
      i_e_ghost = grid%nghost + grid%nx_phys + 1

      do it = 1, size(ms%tracers)
         if (.not. ms%tracers(it)%do_horizontal_advection) cycle
         if (present(bc)) then
            if (bc%west%bc_type == OBC_CLAMPED .and. bc%has_west .and. &
                allocated(bc%west%clamped_tracer) .and. &
                it <= size(bc%west%clamped_tracer)) then
               clamped_tr = bc%west%clamped_tracer(it)
               do concurrent(k=1:ms%nz_ml, j=1:grid%ny_total, i=1:grid%nghost)
                  ms%tracers(it)%hTr(i, j, k) = clamped_tr*ms%h_layer(i, j, k)
               end do
            end if
            if (bc%east%bc_type == OBC_CLAMPED .and. bc%has_east .and. &
                allocated(bc%east%clamped_tracer) .and. &
                it <= size(bc%east%clamped_tracer)) then
               clamped_tr = bc%east%clamped_tracer(it)
               do concurrent(k=1:ms%nz_ml, j=1:grid%ny_total, &
                             i=grid%nghost + grid%nx_phys + 1:grid%nx_total)
                  ms%tracers(it)%hTr(i, j, k) = clamped_tr*ms%h_layer(i, j, k)
               end do
            end if
         end if
         ! Budget dispatch: pass the matching budget accumulator for whichever
         ! tracer opted into a budget slot (heat/salt); age/passive tracers
         ! (budget_id = NONE) get no budget arg (absent ⇒ inert).
         select case (ms%tracers(it)%budget_id)
         case (TRACER_BUDGET_HEAT)
            call tracer_advect_zonal_one_impl( &
               grid%nx_total, grid%ny_total, ms%nz_ml, &
               dt, metrics%iareaT, metrics%wet_T, &
               ms%h_layer, &
               ms%tracers(it)%hTr, &
               ms%mass_flux_x_layer, &
               this%h_face_left_x%data, &
               this%h_face_right_x%data, &
               budget_adv=ms%heat_budget_horiz_adv)
         case (TRACER_BUDGET_SALT)
            call tracer_advect_zonal_one_impl( &
               grid%nx_total, grid%ny_total, ms%nz_ml, &
               dt, metrics%iareaT, metrics%wet_T, &
               ms%h_layer, &
               ms%tracers(it)%hTr, &
               ms%mass_flux_x_layer, &
               this%h_face_left_x%data, &
               this%h_face_right_x%data, &
               budget_adv=ms%salt_budget_horiz_adv)
         case default
            call tracer_advect_zonal_one_impl( &
               grid%nx_total, grid%ny_total, ms%nz_ml, &
               dt, metrics%iareaT, metrics%wet_T, &
               ms%h_layer, &
               ms%tracers(it)%hTr, &
               ms%mass_flux_x_layer, &
               this%h_face_left_x%data, &
               this%h_face_right_x%data)
         end select
      end do
   end subroutine tracer_advect_zonal