Cosine-ramp tracer relaxation in a west/east sponge band.
Explicit-shape dummies (flat-impl + outer-shim — the per-tracer
slice is passed by the caller, never dereferenced inside the DC).
side = +1 for the west edge (cells wall_face .. wall_face+band-1),
side = -1 for the east edge (cells wall_face-1 .. wall_face-band).
budget (PR-23, optional): when present, mirrors the per-cell
hTr increment into it (salt or heat) so the legacy band sponge’s
tracer relaxation closes the console budget exactly like the
map-driven path (relax_map_tracer_budget_impl) — the caller
passes it only for the salinity/temperature tracer indices.
has_budget is hoisted to a plain host logical and read (never
present()) INSIDE the single do concurrent — splitting on
present() into two separate DC loops is the
nvhpc_split_optional_dc_codegen trap (~25x slower); this is the
one-loop fix.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | hTr(nx_total,ny_total,nz) | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx_total,ny_total,nz) | |||
| integer, | intent(in) | :: | nx_total | |||
| integer, | intent(in) | :: | ny_total | |||
| integer, | intent(in) | :: | nz | |||
| integer, | intent(in) | :: | j0 | |||
| integer, | intent(in) | :: | j1 | |||
| integer, | intent(in) | :: | wall_face | |||
| integer, | intent(in) | :: | band | |||
| integer, | intent(in) | :: | side | |||
| real(kind=wp), | intent(in) | :: | strength | |||
| real(kind=wp), | intent(in) | :: | C_bc | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(inout), | optional | :: | budget(nx_total,ny_total,nz) |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | d | ||||
| logical, | private | :: | has_budget | ||||
| integer, | private | :: | ii | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | k | ||||
| real(kind=wp), | private | :: | new_val |
pure subroutine relax_band_x_impl(hTr, h_layer, nx_total, ny_total, nz, & j0, j1, wall_face, band, side, strength, C_bc, dt, budget) !! Cosine-ramp tracer relaxation in a west/east sponge band. !! Explicit-shape dummies (flat-impl + outer-shim — the per-tracer !! slice is passed by the caller, never dereferenced inside the DC). !! `side = +1` for the west edge (cells wall_face .. wall_face+band-1), !! `side = -1` for the east edge (cells wall_face-1 .. wall_face-band). !! !! `budget` (PR-23, optional): when present, mirrors the per-cell !! `hTr` increment into it (salt or heat) so the legacy band sponge's !! tracer relaxation closes the console budget exactly like the !! map-driven path (`relax_map_tracer_budget_impl`) — the caller !! passes it only for the salinity/temperature tracer indices. !! `has_budget` is hoisted to a plain host logical and read (never !! `present()`) INSIDE the single `do concurrent` — splitting on !! `present()` into two separate DC loops is the !! `nvhpc_split_optional_dc_codegen` trap (~25x slower); this is the !! one-loop fix. integer, intent(in) :: nx_total, ny_total, nz, j0, j1, wall_face, band, side real(wp), intent(inout) :: hTr(nx_total, ny_total, nz) real(wp), intent(in) :: h_layer(nx_total, ny_total, nz) real(wp), intent(in) :: strength, C_bc, dt real(wp), intent(inout), optional :: budget(nx_total, ny_total, nz) integer :: k, j, d, ii real(wp) :: new_val logical :: has_budget has_budget = present(budget) do concurrent(k=1:nz, j=j0:j1, d=0:band - 1) local(ii, new_val) if (side > 0) then ii = wall_face + d else ii = wall_face - d - 1 end if new_val = relax_one(hTr(ii, j, k), C_bc*h_layer(ii, j, k), & strength, d, band, dt) if (has_budget) budget(ii, j, k) = budget(ii, j, k) + (new_val - hTr(ii, j, k)) hTr(ii, j, k) = new_val end do end subroutine relax_band_x_impl