Stamp inv_scale · Q_field(i,j) · wet_mask(i,j) onto the first
LIVE layer (k_top(i,j)) of a tracer’s hTr array, mirror into
the matching budget contributor. Explicit-shape dummies so
NVHPC stdpar can compile device kernels against static bounds.
Why k_top and not nz. Under a quasi-geopotential
coordinate beneath an ice shelf the layers inside the draft are
inert fillers, so on a covered column k = nz carries
zstar_h_min of water. A flux stamped there is neither
diffused down (the vdiff tracer matrix decouples a vanished row
to the identity) nor kept (the next ALE remap drains it on
h_old <= H_FLOOR) — but the budget mirror on the line below
still counts it, so the column leaks exactly the deposit, every
thermo step. The atmospheric part of Q_field is zero under
cover, but the cavity’s own heat_cavity/salt_cavity pass
through ocean_surface_flux_assemble UNMASKED, which is why
this is the load-bearing site of the whole k_top slice.
inv_scale = dt/(rho0·cp) for heat, dt/rho0 for salt — a
column-invariant multiplier that the caller derives from sf.
Q_field carries any (i,j) spatial variation; for the default
constant-fill case it is uniform, giving arithmetic identical to
the old scalar-broadcast path.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | hTr(nx,ny,nz) | |||
| real(kind=wp), | intent(inout) | :: | budget(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | wet_mask(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | Q_field(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | inv_scale | |||
| integer, | intent(in) | :: | k_top(nx,ny) |
|
||
| integer, | intent(in) | :: | nz | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | cell | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | j |
pure subroutine apply_surface_src_2d_impl(hTr, budget, wet_mask, Q_field, & inv_scale, k_top, nz, nx, ny) !! Stamp `inv_scale · Q_field(i,j) · wet_mask(i,j)` onto the first !! LIVE layer (`k_top(i,j)`) of a tracer's hTr array, mirror into !! the matching budget contributor. Explicit-shape dummies so !! NVHPC stdpar can compile device kernels against static bounds. !! !! **Why `k_top` and not `nz`.** Under a quasi-geopotential !! coordinate beneath an ice shelf the layers inside the draft are !! inert fillers, so on a covered column `k = nz` carries !! `zstar_h_min` of water. A flux stamped there is neither !! diffused down (the vdiff tracer matrix decouples a vanished row !! to the identity) nor kept (the next ALE remap drains it on !! `h_old <= H_FLOOR`) — but the budget mirror on the line below !! still counts it, so the column leaks exactly the deposit, every !! thermo step. The atmospheric part of `Q_field` is zero under !! cover, but the cavity's own `heat_cavity`/`salt_cavity` pass !! through `ocean_surface_flux_assemble` UNMASKED, which is why !! this is the load-bearing site of the whole `k_top` slice. !! !! `inv_scale` = dt/(rho0·cp) for heat, dt/rho0 for salt — a !! column-invariant multiplier that the caller derives from `sf`. !! `Q_field` carries any (i,j) spatial variation; for the default !! constant-fill case it is uniform, giving arithmetic identical to !! the old scalar-broadcast path. !! integer, intent(in) :: nz, nx, ny real(wp), intent(inout) :: hTr(nx, ny, nz) real(wp), intent(inout) :: budget(nx, ny, nz) real(wp), intent(in) :: wet_mask(nx, ny) real(wp), intent(in) :: Q_field(nx, ny) real(wp), intent(in) :: inv_scale integer, intent(in) :: k_top(nx, ny) !! `ms%k_top` — the first LIVE layer counting down from the top. !! `nz` on every column that has no top-side filler (which is !! every column on every coordinate but `z_fixed` under a rigid !! top), so this reads the same memory as the literal `nz` it !! replaced and the arithmetic is bit-identical. integer :: i, j real(wp) :: cell do concurrent(j=1:ny, i=1:nx) local(cell) cell = inv_scale*Q_field(i, j)*wet_mask(i, j) hTr(i, j, k_top(i, j)) = hTr(i, j, k_top(i, j)) + cell budget(i, j, k_top(i, j)) = budget(i, j, k_top(i, j)) + cell end do end subroutine apply_surface_src_2d_impl