Meridional half of the direction-split tracer advection.
Reads the post-zonal h_layer (since
continuity_apply_zonal has already updated h
in the split flow) and the just-computed
mass_flux_y_layer from
continuity_meridional_flux.
Same OBC_CLAMPED ghost-cell override as the zonal helper —
see tracer_advect_zonal for the rationale.
| 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 | :: | it | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | j_n_ghost | ||||
| integer, | private | :: | j_s_ghost | ||||
| integer, | private | :: | k |
pure subroutine tracer_advect_meridional(grid, metrics, this, ms, dt, bc) !! Meridional half of the direction-split tracer advection. !! Reads the post-zonal `h_layer` (since !! `continuity_apply_zonal` has already updated h !! in the split flow) and the just-computed !! `mass_flux_y_layer` from !! `continuity_meridional_flux`. !! !! Same OBC_CLAMPED ghost-cell override as the zonal helper — !! see `tracer_advect_zonal` for the rationale. 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, j_s_ghost, j_n_ghost, i, j, k real(wp) :: clamped_tr if (.not. allocated(ms%tracers)) return j_s_ghost = grid%nghost j_n_ghost = grid%nghost + grid%ny_phys + 1 do it = 1, size(ms%tracers) if (.not. ms%tracers(it)%do_horizontal_advection) cycle if (present(bc)) then if (bc%south%bc_type == OBC_CLAMPED .and. bc%has_south .and. & allocated(bc%south%clamped_tracer) .and. & it <= size(bc%south%clamped_tracer)) then clamped_tr = bc%south%clamped_tracer(it) do concurrent(k=1:ms%nz_ml, i=1:grid%nx_total, j=1:grid%nghost) ms%tracers(it)%hTr(i, j, k) = clamped_tr*ms%h_layer(i, j, k) end do end if if (bc%north%bc_type == OBC_CLAMPED .and. bc%has_north .and. & allocated(bc%north%clamped_tracer) .and. & it <= size(bc%north%clamped_tracer)) then clamped_tr = bc%north%clamped_tracer(it) do concurrent(k=1:ms%nz_ml, i=1:grid%nx_total, & j=grid%nghost + grid%ny_phys + 1:grid%ny_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_meridional_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_y_layer, & this%h_face_left_y%data, & this%h_face_right_y%data, & budget_adv=ms%heat_budget_horiz_adv) case (TRACER_BUDGET_SALT) call tracer_advect_meridional_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_y_layer, & this%h_face_left_y%data, & this%h_face_right_y%data, & budget_adv=ms%salt_budget_horiz_adv) case default call tracer_advect_meridional_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_y_layer, & this%h_face_left_y%data, & this%h_face_right_y%data) end select end do end subroutine tracer_advect_meridional