ice_frazil_accumulate_impl Subroutine

private pure subroutine ice_frazil_accumulate_impl(hTr_T, hTr_S, h_layer, wet_mask, frazil_heat, heat_budget_frazil, eos, nghost, nz, nx, ny)

Device kernel over PHYSICAL surface cells (ghosts excluded — wall ghosts are inert and seam ghosts are rebuilt by the wrap / exchange, so clamping them would double-count the bank in any area integral). Per wet cell at k = nz:

T = hTr_T/h, S = hTr_S/h, T_f = eos_freezing_point(S, 0) if T < T_f: frazil_heat += ρ·Cp·h·(T_f − T) and hTr_T = h·T_f (exact clamp)

Surface pressure p = 0 (surface-relative hydrostatic zero — same convention as the surface-flux kernels; the in-situ layer-centre depression over h_surf/2 is O(1 mK) and ignored, matching MOM6’s p=0 surface-frazil evaluation). Vanished columns (h <= H_VANISHED) and land (wet_mask = 0) are skipped — the division for a PHYSICAL T/S gates on H_VANISHED per the thin-layer taxonomy. The conditional write uses an inner if, NOT a do concurrent mask header (masked DC headers fail tools/dc_audit.py –strict).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr_T(nx,ny,nz)
real(kind=wp), intent(in) :: hTr_S(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(inout) :: frazil_heat(nx,ny)
real(kind=wp), intent(inout) :: heat_budget_frazil(nx,ny,1)
type(eos_t), intent(in) :: eos
integer, intent(in) :: nghost
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

Calls

proc~~ice_frazil_accumulate_impl~~CallsGraph proc~ice_frazil_accumulate_impl ice_frazil_accumulate_impl local local proc~ice_frazil_accumulate_impl->local proc~eos_freezing_point eos_freezing_point proc~ice_frazil_accumulate_impl->proc~eos_freezing_point

Called by

proc~~ice_frazil_accumulate_impl~~CalledByGraph proc~ice_frazil_accumulate_impl ice_frazil_accumulate_impl proc~ice_frazil_accumulate ice_frazil_accumulate proc~ice_frazil_accumulate->proc~ice_frazil_accumulate_impl proc~engine_step_ice engine_step_ice proc~engine_step_ice->proc~ice_frazil_accumulate proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_step_ice proc~rdb_ocean_step rdb_ocean_step proc~rdb_ocean_step->proc~engine_step_ice proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: d_htr
real(kind=wp), private :: h
integer, private :: i
integer, private :: i_hi
integer, private :: i_lo
integer, private :: j
integer, private :: j_hi
integer, private :: j_lo
real(kind=wp), private :: s_sfc
real(kind=wp), private :: t_f
real(kind=wp), private :: t_sfc

Source Code

   pure subroutine ice_frazil_accumulate_impl(hTr_T, hTr_S, h_layer, wet_mask, &
                                              frazil_heat, heat_budget_frazil, &
                                              eos, nghost, nz, nx, ny)
      !! Device kernel over PHYSICAL surface cells (ghosts excluded —
      !! wall ghosts are inert and seam ghosts are rebuilt by the wrap /
      !! exchange, so clamping them would double-count the bank in any
      !! area integral).  Per wet cell at k = nz:
      !!
      !!   T = hTr_T/h,  S = hTr_S/h,  T_f = eos_freezing_point(S, 0)
      !!   if T < T_f:  frazil_heat += ρ·Cp·h·(T_f − T)  and
      !!                hTr_T = h·T_f   (exact clamp)
      !!
      !! Surface pressure p = 0 (surface-relative hydrostatic zero —
      !! same convention as the surface-flux kernels; the in-situ
      !! layer-centre depression over h_surf/2 is O(1 mK) and ignored,
      !! matching MOM6's p=0 surface-frazil evaluation).  Vanished
      !! columns (`h <= H_VANISHED`) and land (`wet_mask = 0`) are
      !! skipped — the division for a PHYSICAL T/S gates on
      !! `H_VANISHED` per the thin-layer taxonomy.  The conditional
      !! write uses an inner `if`, NOT a `do concurrent` mask header
      !! (masked DC headers fail tools/dc_audit.py --strict).
      integer, intent(in) :: nghost, nz, nx, ny
      real(wp), intent(inout) :: hTr_T(nx, ny, nz)
      real(wp), intent(in) :: hTr_S(nx, ny, nz)
      real(wp), intent(in) :: h_layer(nx, ny, nz)
      real(wp), intent(in) :: wet_mask(nx, ny)
      real(wp), intent(inout) :: frazil_heat(nx, ny)
      real(wp), intent(inout) :: heat_budget_frazil(nx, ny, 1)
      type(eos_t), intent(in) :: eos

      integer :: i, j, i_lo, i_hi, j_lo, j_hi
      real(wp) :: h, t_sfc, s_sfc, t_f, d_htr

      i_lo = nghost + 1
      i_hi = nx - nghost
      j_lo = nghost + 1
      j_hi = ny - nghost

      do concurrent(j=j_lo:j_hi, i=i_lo:i_hi) local(h, t_sfc, s_sfc, t_f, d_htr)
         h = h_layer(i, j, nz)
         if (wet_mask(i, j) > 0.5_wp .and. h > H_VANISHED) then
            t_sfc = hTr_T(i, j, nz)/h
            s_sfc = hTr_S(i, j, nz)/h
            t_f = eos_freezing_point(eos, s_sfc, 0.0_wp)
            if (t_sfc < t_f) then
               d_htr = h*(t_f - t_sfc)
               frazil_heat(i, j) = frazil_heat(i, j) &
                                   + RHO_WATER*SEAWATER_CP*d_htr
               heat_budget_frazil(i, j, 1) = heat_budget_frazil(i, j, 1) + d_htr
               ! Exact clamp: T_after = (h·T_f)/h == T_f.
               hTr_T(i, j, nz) = h*t_f
            end if
         end if
      end do
   end subroutine ice_frazil_accumulate_impl