drain_rescale_hTr + the closed-budget fill. The concentration
hold / un-hold pair is NOT content-conserving cell by cell –
hTr := Tr·h moves Σ areaT·hTr by Σ areaT·Tr·δh, which is only
zero when Tr is uniform – so both halves have to be recorded or
the closed budget is only valid on window boundaries and wobbles at
every mid-window report. Recording both makes them cancel exactly,
since the un-hold is the arithmetic inverse of the accumulated hold.
w is DRAIN_BUDGET_IN_STAGE_WEIGHT for the per-stage hold inside
continuity_tracer_step_split and
DRAIN_BUDGET_POST_AVERAGE_WEIGHT for the un-hold in
continuity_tracer_drain (which runs after rk2_average).
The hTr expression is character-for-character the budget-free
twin’s, so the prognostic path stays bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | h_new(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | h_old(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | w | |||
| real(kind=wp), | intent(inout) | :: | hTr(nx,ny,nz) | |||
| real(kind=wp), | intent(inout) | :: | budget_adv(nx,ny,nz) |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | hnew_tr | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | k |
pure subroutine drain_rescale_hTr_budget(nx, ny, nz, h_new, h_old, w, hTr, budget_adv) !! `drain_rescale_hTr` + the closed-budget fill. The concentration !! hold / un-hold pair is NOT content-conserving cell by cell -- !! `hTr := Tr·h` moves `Σ areaT·hTr` by `Σ areaT·Tr·δh`, which is only !! zero when `Tr` is uniform -- so both halves have to be recorded or !! the closed budget is only valid on window boundaries and wobbles at !! every mid-window report. Recording both makes them cancel exactly, !! since the un-hold is the arithmetic inverse of the accumulated hold. !! !! `w` is `DRAIN_BUDGET_IN_STAGE_WEIGHT` for the per-stage hold inside !! `continuity_tracer_step_split` and !! `DRAIN_BUDGET_POST_AVERAGE_WEIGHT` for the un-hold in !! `continuity_tracer_drain` (which runs after `rk2_average`). !! !! The `hTr` expression is character-for-character the budget-free !! twin's, so the prognostic path stays bit-identical. integer, intent(in) :: nx, ny, nz real(wp), intent(in) :: h_new(nx, ny, nz), h_old(nx, ny, nz) real(wp), intent(in) :: w real(wp), intent(inout) :: hTr(nx, ny, nz) real(wp), intent(inout) :: budget_adv(nx, ny, nz) integer :: i, j, k real(wp) :: hnew_tr do concurrent(k=1:nz, j=1:ny, i=1:nx) local(hnew_tr) hnew_tr = hTr(i, j, k)*h_new(i, j, k)/max(h_old(i, j, k), DRAIN_MIN_H) budget_adv(i, j, k) = budget_adv(i, j, k) + w*(hnew_tr - hTr(i, j, k)) hTr(i, j, k) = hnew_tr end do end subroutine drain_rescale_hTr_budget