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 | Intent | Optional | 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 |
| 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 |
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