relax_band_x_impl Subroutine

private 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.

Arguments

Type IntentOptional 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)

Calls

proc~~relax_band_x_impl~~CallsGraph proc~relax_band_x_impl relax_band_x_impl local local proc~relax_band_x_impl->local proc~relax_one relax_one proc~relax_band_x_impl->proc~relax_one proc~relax_toward relax_toward proc~relax_one->proc~relax_toward

Called by

proc~~relax_band_x_impl~~CalledByGraph proc~relax_band_x_impl relax_band_x_impl proc~sponge_relax_band_x_tracer sponge_relax_band_x_tracer proc~sponge_relax_band_x_tracer->proc~relax_band_x_impl proc~ocean_sponge_apply_tracers ocean_sponge_apply_tracers proc~ocean_sponge_apply_tracers->proc~sponge_relax_band_x_tracer proc~run_stage_split run_stage_split proc~run_stage_split->proc~ocean_sponge_apply_tracers proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_stage_split proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step_split

Variables

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

Source Code

   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