Device kernel: ONE do concurrent(j, i) over PHYSICAL cells
(ghosts excluded), wet_mask > 0.5 inner gate (never a masked DC
header), serial cat loops inside — each cell touches only its
own (i, j, :) slice, race-free. No per-cell gather into local
category-sized arrays (avoids register pressure and any
compile-time ncat cap, unlike the ICE_NK_MAX-capped
PER-LAYER arrays elsewhere in the ice model) — scalar
temporaries only, all declared in local(...).
Decl-order: all integer dims declared before the explicit-shape arrays that use them. No locals named after intrinsics.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | wet_mask(nx,ny) | |||
| 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(inout) | :: | enth_ice(nx,ny,ncat,nk) | |||
| real(kind=wp), | intent(inout) | :: | enth_snow(nx,ny,ncat,1) | |||
| real(kind=wp), | intent(inout) | :: | sal_ice(nx,ny,ncat,nk) | |||
| real(kind=wp), | intent(in) | :: | mh_lim(ncat+1) | |||
| integer, | intent(in) | :: | nghost |
Grid + category + layer extents (declared first — decl-order). |
||
| integer, | intent(in) | :: | ncat |
Grid + category + layer extents (declared first — decl-order). |
||
| integer, | intent(in) | :: | nk |
Grid + category + layer extents (declared first — decl-order). |
||
| integer, | intent(in) | :: | nx |
Grid + category + layer extents (declared first — decl-order). |
||
| integer, | intent(in) | :: | ny |
Grid + category + layer extents (declared first — decl-order). |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | cat | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | i_hi | ||||
| integer, | private | :: | i_lo | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | j_hi | ||||
| integer, | private | :: | j_lo | ||||
| integer, | private | :: | lay | ||||
| real(kind=wp), | private | :: | mca_ice_dst | ||||
| real(kind=wp), | private | :: | mca_ice_src | ||||
| real(kind=wp), | private | :: | mca_snow_dst | ||||
| real(kind=wp), | private | :: | mca_snow_src | ||||
| real(kind=wp), | private | :: | mnew | ||||
| real(kind=wp), | private | :: | msnew | ||||
| real(kind=wp), | private | :: | part_sum | ||||
| real(kind=wp), | private | :: | part_trans | ||||
| logical, | private | :: | resum |
pure subroutine ice_adjust_categories_impl(wet_mask, part_size, m_ice, m_snow, & enth_ice, enth_snow, sal_ice, mh_lim, & nghost, ncat, nk, nx, ny) !! Device kernel: ONE `do concurrent(j, i)` over PHYSICAL cells !! (ghosts excluded), `wet_mask > 0.5` inner gate (never a masked DC !! header), serial `cat` loops inside — each cell touches only its !! own `(i, j, :)` slice, race-free. No per-cell gather into local !! category-sized arrays (avoids register pressure and any !! compile-time `ncat` cap, unlike the `ICE_NK_MAX`-capped !! PER-LAYER arrays elsewhere in the ice model) — scalar !! temporaries only, all declared in `local(...)`. !! !! Decl-order: all integer dims declared before the explicit-shape !! arrays that use them. No locals named after intrinsics. integer, intent(in) :: nghost, ncat, nk, nx, ny !! Grid + category + layer extents (declared first — decl-order). real(wp), intent(in) :: wet_mask(nx, ny) 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(inout) :: enth_ice(nx, ny, ncat, nk) real(wp), intent(inout) :: enth_snow(nx, ny, ncat, 1) real(wp), intent(inout) :: sal_ice(nx, ny, ncat, nk) real(wp), intent(in) :: mh_lim(ncat + 1) integer :: i, j, i_lo, i_hi, j_lo, j_hi integer :: cat, lay logical :: resum real(wp) :: part_trans, part_sum real(wp) :: mca_ice_src, mca_ice_dst, mca_snow_src, mca_snow_dst, mnew, msnew 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(cat, lay, resum, part_trans, part_sum, & mca_ice_src, mca_ice_dst, mca_snow_src, & mca_snow_dst, mnew, msnew) if (wet_mask(i, j) > 0.5_wp) then resum = .false. ! ---- 1. Massless cleanup (SIS2:664-685) ---- do cat = 1, ncat if (m_ice(i, j, cat) <= 0.0_wp) then if (part_size(i, j, cat) > 0.0_wp) resum = .true. part_size(i, j, cat) = 0.0_wp end if end do ! ---- 2. Upward pass, c = 1..ncat-1 ascending (SIS2:714-767) ---- do cat = 1, ncat - 1 if (part_size(i, j, cat)*m_ice(i, j, cat) > 0.0_wp .and. & m_ice(i, j, cat) > mh_lim(cat + 1)) then part_trans = part_size(i, j, cat) mca_snow_src = part_size(i, j, cat)*m_snow(i, j, cat) mca_snow_dst = part_size(i, j, cat + 1)*m_snow(i, j, cat + 1) mca_ice_src = part_trans*m_ice(i, j, cat) mca_ice_dst = part_size(i, j, cat + 1)*m_ice(i, j, cat + 1) m_ice(i, j, cat + 1) = (part_trans*m_ice(i, j, cat) & + part_size(i, j, cat + 1)*m_ice(i, j, cat + 1)) & /(part_trans + part_size(i, j, cat + 1)) m_ice(i, j, cat) = mh_lim(cat + 1) part_size(i, j, cat + 1) = part_size(i, j, cat + 1) + part_trans part_size(i, j, cat) = part_size(i, j, cat) - part_trans m_snow(i, j, cat) = 0.0_wp if (part_size(i, j, cat + 1) > 0.0_wp) then m_snow(i, j, cat + 1) = (mca_snow_src + mca_snow_dst)/part_size(i, j, cat + 1) else m_snow(i, j, cat + 1) = 0.0_wp end if mnew = mca_ice_src + mca_ice_dst if (mca_ice_src > 0.0_wp .and. mnew > 0.0_wp) then do lay = 1, nk enth_ice(i, j, cat + 1, lay) = (mca_ice_src*enth_ice(i, j, cat, lay) & + mca_ice_dst*enth_ice(i, j, cat + 1, lay)) & /mnew sal_ice(i, j, cat + 1, lay) = (mca_ice_src*sal_ice(i, j, cat, lay) & + mca_ice_dst*sal_ice(i, j, cat + 1, lay)) & /mnew end do end if msnew = mca_snow_src + mca_snow_dst if (mca_snow_src > 0.0_wp .and. msnew > 0.0_wp) then enth_snow(i, j, cat + 1, 1) = (mca_snow_src*enth_snow(i, j, cat, 1) & + mca_snow_dst*enth_snow(i, j, cat + 1, 1)) & /msnew end if end if end do ! ---- 3. Downward pass, c = ncat..2 descending (SIS2:786-839) ---- do cat = ncat, 2, -1 if (part_size(i, j, cat)*m_ice(i, j, cat) > 0.0_wp .and. & m_ice(i, j, cat) < mh_lim(cat)) then part_trans = part_size(i, j, cat) mca_snow_src = part_size(i, j, cat)*m_snow(i, j, cat) mca_snow_dst = part_size(i, j, cat - 1)*m_snow(i, j, cat - 1) mca_ice_src = part_trans*m_ice(i, j, cat) mca_ice_dst = part_size(i, j, cat - 1)*m_ice(i, j, cat - 1) m_ice(i, j, cat - 1) = (part_trans*m_ice(i, j, cat) & + part_size(i, j, cat - 1)*m_ice(i, j, cat - 1)) & /(part_trans + part_size(i, j, cat - 1)) m_ice(i, j, cat) = mh_lim(cat) part_size(i, j, cat - 1) = part_size(i, j, cat - 1) + part_trans part_size(i, j, cat) = part_size(i, j, cat) - part_trans m_snow(i, j, cat) = 0.0_wp if (part_size(i, j, cat - 1) > 0.0_wp) then m_snow(i, j, cat - 1) = (mca_snow_src + mca_snow_dst)/part_size(i, j, cat - 1) else m_snow(i, j, cat - 1) = 0.0_wp end if mnew = mca_ice_src + mca_ice_dst if (mca_ice_src > 0.0_wp .and. mnew > 0.0_wp) then do lay = 1, nk enth_ice(i, j, cat - 1, lay) = (mca_ice_src*enth_ice(i, j, cat, lay) & + mca_ice_dst*enth_ice(i, j, cat - 1, lay)) & /mnew sal_ice(i, j, cat - 1, lay) = (mca_ice_src*sal_ice(i, j, cat, lay) & + mca_ice_dst*sal_ice(i, j, cat - 1, lay)) & /mnew end do end if msnew = mca_snow_src + mca_snow_dst if (mca_snow_src > 0.0_wp .and. msnew > 0.0_wp) then enth_snow(i, j, cat - 1, 1) = (mca_snow_src*enth_snow(i, j, cat, 1) & + mca_snow_dst*enth_snow(i, j, cat - 1, 1)) & /msnew end if end if end do ! ---- 4. Cat-1 minimum-thickness compress (SIS2:850-864) ---- if (mh_lim(1) > 0.0_wp) then if (m_ice(i, j, 1)*part_size(i, j, 1) > 0.0_wp .and. m_ice(i, j, 1) < mh_lim(1)) then part_size(i, j, 1) = part_size(i, j, 1)*(m_ice(i, j, 1)/mh_lim(1)) if (m_ice(i, j, 1) > 0.0_wp) then m_snow(i, j, 1) = m_snow(i, j, 1)*(mh_lim(1)/m_ice(i, j, 1)) end if m_ice(i, j, 1) = mh_lim(1) resum = .true. end if end if ! ---- 5. Open-water resum (SIS2:874-889) ---- if (resum) then part_sum = 0.0_wp do cat = 1, ncat part_sum = part_sum + part_size(i, j, cat) end do part_size(i, j, 0) = max(1.0_wp - part_sum, 0.0_wp) end if end if end do end subroutine ice_adjust_categories_impl