ice_cas_to_ist_impl Subroutine

private pure subroutine ice_cas_to_ist_impl(wet_mask, areaT, mca_ice, mca_snow, part_size, m_ice, m_snow, mh_lim, roll_factor, nghost, ncat, nx, ny)

SIS2 cell_ave_state_to_ice_state (:540). Per cell, per category: pre-floor category 1, optional thin-ice rolling (roll_factor > 0), general floor, then re-derive part_size(c) = mca_ice(c)/m_ice(c) and m_snow(c) = m_ice(c)*(mca_snow(c)/mca_ice(c)) (per-ICE-area). part_size(0) = 1 - Sum_c part_size(c) — MAY be negative here; ice_compress_impl (Phase 4) is what restores >= 0.

roll_factor rolling test — VERIFIED against the literal SIS2 source (SIS_transport.F90:572-581, L_to_H = US%L_to_Z*Rho_ice; Roundabout carries no L_to_Z length rescaling, so L_to_H = ICE_RHO_ICE): a VOLUME-vs-VOLUME comparison, NOT a per-area one — areaT does NOT cancel (only the RHS carries it explicitly in SIS2’s actual, non-simplified code): h_eff = m_ice(c)/ICE_RHO_ICE (pre-roll per-ICE-area thickness, a length); if (roll_factor*h_eff**3 > (mca_ice(c)/ICE_RHO_ICE)*areaT(i,j)) — LHS a volume (h_eff cubed), RHS (mca_ice/ICE_RHO_ICE) is a per-CELL-area ice-volume-per-area (a length) times areaT = the cell’s total ice volume; then m_ice(c) = max(mh_lim(1), ICE_RHO_ICE*sqrt((mca_ice(c)* areaT(i,j)/ICE_RHO_ICE) / (roll_factor*h_eff))) — SIS2’s sqrt argument is (m_ice*areaT)/(roll_factor*mH_ice) in ITS pre-division units; converting consistently (dividing the mca_ice*areaT term by ICE_RHO_ICE once, matching the (mca_ice/ICE_RHO_ICE)*areaT volume on the LHS test) gives the expression coded below.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: areaT(nx,ny)
real(kind=wp), intent(in) :: mca_ice(nx,ny,ncat)
real(kind=wp), intent(in) :: mca_snow(nx,ny,ncat)
real(kind=wp), intent(inout) :: part_size(nx,ny,0:ncat)
real(kind=wp), intent(inout) :: m_ice(nx,ny,ncat)
real(kind=wp), intent(inout) :: m_snow(nx,ny,ncat)
real(kind=wp), intent(in) :: mh_lim(ncat+1)
real(kind=wp), intent(in) :: roll_factor
integer, intent(in) :: nghost
integer, intent(in) :: ncat
integer, intent(in) :: nx
integer, intent(in) :: ny

Calls

proc~~ice_cas_to_ist_impl~~CallsGraph proc~ice_cas_to_ist_impl ice_cas_to_ist_impl local local proc~ice_cas_to_ist_impl->local

Called by

proc~~ice_cas_to_ist_impl~~CalledByGraph proc~ice_cas_to_ist_impl ice_cas_to_ist_impl proc~ice_transport_step ice_transport_step proc~ice_transport_step->proc~ice_cas_to_ist_impl proc~engine_step_ice engine_step_ice proc~engine_step_ice->proc~ice_transport_step 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
integer, private :: c
real(kind=wp), private :: h_eff
integer, private :: i
integer, private :: i_hi
integer, private :: i_lo
real(kind=wp), private :: ice_vol
integer, private :: j
integer, private :: j_hi
integer, private :: j_lo
real(kind=wp), private :: part_sum

Source Code

   pure subroutine ice_cas_to_ist_impl(wet_mask, areaT, mca_ice, mca_snow, part_size, m_ice, &
                                       m_snow, mh_lim, roll_factor, nghost, ncat, nx, ny)
      !! SIS2 `cell_ave_state_to_ice_state` (`:540`).  Per cell, per
      !! category: pre-floor category 1, optional thin-ice rolling
      !! (`roll_factor > 0`), general floor, then re-derive
      !! `part_size(c) = mca_ice(c)/m_ice(c)` and
      !! `m_snow(c) = m_ice(c)*(mca_snow(c)/mca_ice(c))` (per-ICE-area).
      !! `part_size(0) = 1 - Sum_c part_size(c)` — MAY be negative here;
      !! `ice_compress_impl` (Phase 4) is what restores >= 0.
      !!
      !! `roll_factor` rolling test — VERIFIED against the literal SIS2
      !! source (`SIS_transport.F90:572-581`, `L_to_H = US%L_to_Z*Rho_ice`;
      !! Roundabout carries no L_to_Z length rescaling, so `L_to_H =
      !! ICE_RHO_ICE`): a VOLUME-vs-VOLUME comparison, NOT a per-area one
      !! — `areaT` does NOT cancel (only the RHS carries it explicitly in
      !! SIS2's actual, non-simplified code):
      !!   `h_eff = m_ice(c)/ICE_RHO_ICE` (pre-roll per-ICE-area thickness,
      !!   a length);
      !!   `if (roll_factor*h_eff**3 > (mca_ice(c)/ICE_RHO_ICE)*areaT(i,j))`
      !!   — LHS a volume (h_eff cubed), RHS `(mca_ice/ICE_RHO_ICE)` is a
      !!   per-CELL-area ice-volume-per-area (a length) times `areaT` =
      !!   the cell's total ice volume;
      !!   then `m_ice(c) = max(mh_lim(1), ICE_RHO_ICE*sqrt((mca_ice(c)*
      !!   areaT(i,j)/ICE_RHO_ICE) / (roll_factor*h_eff)))` — SIS2's sqrt
      !!   argument is `(m_ice*areaT)/(roll_factor*mH_ice)` in ITS
      !!   pre-division units; converting consistently (dividing the
      !!   `mca_ice*areaT` term by `ICE_RHO_ICE` once, matching the
      !!   `(mca_ice/ICE_RHO_ICE)*areaT` volume on the LHS test) gives the
      !!   expression coded below.
      integer, intent(in) :: nghost, ncat, nx, ny
      real(wp), intent(in) :: wet_mask(nx, ny)
      real(wp), intent(in) :: areaT(nx, ny)
      real(wp), intent(in) :: mca_ice(nx, ny, ncat)
      real(wp), intent(in) :: mca_snow(nx, ny, ncat)
      real(wp), intent(inout) :: part_size(nx, ny, 0:ncat)
      real(wp), intent(inout) :: m_ice(nx, ny, ncat)
      real(wp), intent(inout) :: m_snow(nx, ny, ncat)
      real(wp), intent(in) :: mh_lim(ncat + 1)
      real(wp), intent(in) :: roll_factor
      integer :: i, j, c, i_lo, i_hi, j_lo, j_hi
      real(wp) :: h_eff, ice_vol, part_sum

      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, c=1:ncat) local(h_eff, ice_vol)
         if (wet_mask(i, j) > 0.5_wp) then
            if (c == 1 .and. mca_ice(i, j, 1) > 0.0_wp .and. m_ice(i, j, 1) < mh_lim(1)) then
               m_ice(i, j, 1) = mh_lim(1)
            end if
            if (mca_ice(i, j, c) > 0.0_wp) then
               if (roll_factor > 0.0_wp) then
                  h_eff = m_ice(i, j, c)/ICE_RHO_ICE
                  ice_vol = (mca_ice(i, j, c)/ICE_RHO_ICE)*areaT(i, j)
                  if (roll_factor*h_eff**3 > ice_vol) then
                     m_ice(i, j, c) = max(mh_lim(1), &
                                          ICE_RHO_ICE*sqrt(ice_vol/(roll_factor*h_eff)))
                  end if
               end if
               if (m_ice(i, j, c) < mh_lim(1)) m_ice(i, j, c) = mh_lim(1)
               part_size(i, j, c) = mca_ice(i, j, c)/m_ice(i, j, c)
               m_snow(i, j, c) = m_ice(i, j, c)*(mca_snow(i, j, c)/mca_ice(i, j, c))
            else
               part_size(i, j, c) = 0.0_wp
               m_ice(i, j, c) = 0.0_wp
               m_snow(i, j, c) = 0.0_wp
               ! enth/sal held (inert — massless convention)
            end if
         end if
      end do
      do concurrent(j=j_lo:j_hi, i=i_lo:i_hi) local(part_sum, c)
         if (wet_mask(i, j) > 0.5_wp) then
            part_sum = 0.0_wp
            do c = 1, ncat
               part_sum = part_sum + part_size(i, j, c)
            end do
            part_size(i, j, 0) = 1.0_wp - part_sum
         end if
      end do
   end subroutine ice_cas_to_ist_impl