do concurrent cell driver: PHYSICAL cells only, inner if
gate (never a masked DC header), serial do cat loop inside.
Per (i,j,cat): outputs zeroed unconditionally, then gated on
wet_mask > 0.5 .and. m_ice > ICE_RHO_ICE*H_VANISHED (dynamic-
vanish taxonomy: skip intact, never clamp/divide a vanished
column). part_size is deliberately NOT an argument — thermo
is per unit ice area.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nghost |
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). |
||
| integer, | intent(in) | :: | ncat |
Grid + category + layer extents (declared first — decl-order). |
||
| integer, | intent(in) | :: | nk |
Grid + category + layer extents (declared first — decl-order). |
||
| real(kind=wp), | intent(in) | :: | dtt |
Timestep (s). |
||
| logical, | intent(in) | :: | do_snow_ice |
Archimedes freeboard flood gate ( |
||
| real(kind=wp), | intent(in) | :: | wet_mask(nx,ny) |
Ocean wet mask (>0.5 = wet). |
||
| real(kind=wp), | intent(inout) | :: | m_ice(nx,ny,ncat) |
Total ice mass per unit area per category (kg/m²). |
||
| real(kind=wp), | intent(inout) | :: | m_snow(nx,ny,ncat) |
Snow mass per unit area per category (kg/m²). |
||
| real(kind=wp), | intent(inout) | :: | enth_ice(nx,ny,ncat,nk) |
Ice specific enthalpy (J/kg), BOTTOM-UP (k=1 = ice bottom). |
||
| real(kind=wp), | intent(inout) | :: | enth_snow(nx,ny,ncat,1) |
Snow specific enthalpy (J/kg). |
||
| real(kind=wp), | intent(inout) | :: | sal_ice(nx,ny,ncat,nk) |
Ice bulk salinity (PSU), BOTTOM-UP. |
||
| real(kind=wp), | intent(in) | :: | sf_0(nx,ny) |
Linearized SEB intercept (W/m²), upward-positive. |
||
| real(kind=wp), | intent(in) | :: | dsf_dt(nx,ny) |
Linearized SEB slope (W/m²/K), upward-positive. |
||
| real(kind=wp), | intent(in) | :: | sw_dn(nx,ny) |
Downwelling shortwave at the surface (W/m²). |
||
| real(kind=wp), | intent(in) | :: | fprec(nx,ny) |
Frozen-precipitation rate onto the ice top (kg/m²/s), >= 0 —
PR 26 snowfall seam ( |
||
| real(kind=wp), | intent(in) | :: | tfw(nx,ny) |
Seawater freezing temperature at the ice base (degC). |
||
| real(kind=wp), | intent(in) | :: | fb(nx,ny) |
Ocean -> ice-base heat flux (W/m²). |
||
| real(kind=wp), | intent(in) | :: | sst(nx,ny) |
Sea-surface temperature (degC). |
||
| real(kind=wp), | intent(in) | :: | s_surf(nx,ny) |
Sea-surface salinity (PSU). |
||
| real(kind=wp), | intent(inout) | :: | tsurf_out(nx,ny,ncat) |
Surface skin temperature (degC). |
||
| real(kind=wp), | intent(inout) | :: | h2o_ocn_to_ice(nx,ny,ncat) |
Mass flux frozen from the ocean onto the ice base (kg/m²). |
||
| real(kind=wp), | intent(inout) | :: | h2o_ice_to_ocn(nx,ny,ncat) |
Meltwater mass flux to the ocean (kg/m²). |
||
| real(kind=wp), | intent(inout) | :: | heat_to_ocn(nx,ny,ncat) |
Leftover melt heat dumped to the ocean (J/m²). |
||
| real(kind=wp), | intent(inout) | :: | sw_thru(nx,ny,ncat) |
Shortwave transmitted through the ice to the ocean (W/m²). |
||
| real(kind=wp), | intent(inout) | :: | snow_to_ice(nx,ny,ncat) |
Mass converted from snow to the top ice layer this call
(kg/m²), >= 0 — SIS2 |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | cat | ||||
| real(kind=wp), | private | :: | enth_ice_col(ICE_NK_MAX) | ||||
| real(kind=wp), | private | :: | enth_snow_pt | ||||
| real(kind=wp), | private | :: | h2o_ice_to_ocn_pt | ||||
| real(kind=wp), | private | :: | h2o_ocn_to_ice_pt | ||||
| real(kind=wp), | private | :: | heat_to_ocn_pt | ||||
| 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 | :: | m_ice_pt | ||||
| real(kind=wp), | private | :: | m_snow_pt | ||||
| real(kind=wp), | private | :: | sal_ice_col(ICE_NK_MAX) | ||||
| real(kind=wp), | private | :: | snow_to_ice_pt | ||||
| real(kind=wp), | private | :: | sw_thru_pt | ||||
| real(kind=wp), | private | :: | tsurf_pt |
pure subroutine ice_thermo_columns(nghost, nx, ny, ncat, nk, dtt, do_snow_ice, wet_mask, & m_ice, m_snow, enth_ice, enth_snow, sal_ice, & sf_0, dsf_dt, sw_dn, fprec, tfw, fb, sst, s_surf, & tsurf_out, h2o_ocn_to_ice, h2o_ice_to_ocn, & heat_to_ocn, sw_thru, snow_to_ice) !! `do concurrent` cell driver: PHYSICAL cells only, inner `if` !! gate (never a masked DC header), serial `do cat` loop inside. !! Per (i,j,cat): outputs zeroed unconditionally, then gated on !! `wet_mask > 0.5 .and. m_ice > ICE_RHO_ICE*H_VANISHED` (dynamic- !! vanish taxonomy: skip intact, never clamp/divide a vanished !! column). `part_size` is deliberately NOT an argument — thermo !! is per unit ice area. integer, intent(in) :: nghost, nx, ny, ncat, nk !! Grid + category + layer extents (declared first — decl-order). real(wp), intent(in) :: dtt !! Timestep (s). logical, intent(in) :: do_snow_ice !! Archimedes freeboard flood gate (`&ocean_ice_nml snow_ice`, !! PR 27), captured by value into the DC loop (same treatment !! as `dtt`). `.false.` (the default) is a bit-identical no-op. real(wp), intent(in) :: wet_mask(nx, ny) !! Ocean wet mask (>0.5 = wet). real(wp), intent(inout) :: m_ice(nx, ny, ncat) !! Total ice mass per unit area per category (kg/m²). real(wp), intent(inout) :: m_snow(nx, ny, ncat) !! Snow mass per unit area per category (kg/m²). real(wp), intent(inout) :: enth_ice(nx, ny, ncat, nk) !! Ice specific enthalpy (J/kg), BOTTOM-UP (k=1 = ice bottom). real(wp), intent(inout) :: enth_snow(nx, ny, ncat, 1) !! Snow specific enthalpy (J/kg). real(wp), intent(inout) :: sal_ice(nx, ny, ncat, nk) !! Ice bulk salinity (PSU), BOTTOM-UP. real(wp), intent(in) :: sf_0(nx, ny) !! Linearized SEB intercept (W/m²), upward-positive. real(wp), intent(in) :: dsf_dt(nx, ny) !! Linearized SEB slope (W/m²/K), upward-positive. real(wp), intent(in) :: sw_dn(nx, ny) !! Downwelling shortwave at the surface (W/m²). real(wp), intent(in) :: fprec(nx, ny) !! Frozen-precipitation rate onto the ice top (kg/m²/s), >= 0 — !! PR 26 snowfall seam (`ice%atm_fprec`). Passed to !! `ice_column_step` as `fprec(i,j)*dtt`; 0 (the !! `&ocean_ice_nml snowfall=0` default) is a bit-identical no-op. real(wp), intent(in) :: tfw(nx, ny) !! Seawater freezing temperature at the ice base (degC). real(wp), intent(in) :: fb(nx, ny) !! Ocean -> ice-base heat flux (W/m²). real(wp), intent(in) :: sst(nx, ny) !! Sea-surface temperature (degC). real(wp), intent(in) :: s_surf(nx, ny) !! Sea-surface salinity (PSU). real(wp), intent(inout) :: tsurf_out(nx, ny, ncat) !! Surface skin temperature (degC). real(wp), intent(inout) :: h2o_ocn_to_ice(nx, ny, ncat) !! Mass flux frozen from the ocean onto the ice base (kg/m²). real(wp), intent(inout) :: h2o_ice_to_ocn(nx, ny, ncat) !! Meltwater mass flux to the ocean (kg/m²). real(wp), intent(inout) :: heat_to_ocn(nx, ny, ncat) !! Leftover melt heat dumped to the ocean (J/m²). real(wp), intent(inout) :: sw_thru(nx, ny, ncat) !! Shortwave transmitted through the ice to the ocean (W/m²). real(wp), intent(inout) :: snow_to_ice(nx, ny, ncat) !! Mass converted from snow to the top ice layer this call !! (kg/m²), >= 0 — SIS2 `SN2IC` (PR 27). Zeroed unconditionally !! every thermo step, same lifecycle as `sw_thru`. integer :: i, j, cat, i_lo, i_hi, j_lo, j_hi real(wp) :: m_snow_pt, m_ice_pt, enth_snow_pt real(wp) :: enth_ice_col(ICE_NK_MAX), sal_ice_col(ICE_NK_MAX) real(wp) :: tsurf_pt, h2o_ocn_to_ice_pt, h2o_ice_to_ocn_pt, heat_to_ocn_pt, sw_thru_pt real(wp) :: snow_to_ice_pt 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, m_snow_pt, m_ice_pt, enth_snow_pt, enth_ice_col, sal_ice_col, & tsurf_pt, h2o_ocn_to_ice_pt, h2o_ice_to_ocn_pt, heat_to_ocn_pt, sw_thru_pt, & snow_to_ice_pt) do cat = 1, ncat tsurf_out(i, j, cat) = 0.0_wp h2o_ocn_to_ice(i, j, cat) = 0.0_wp h2o_ice_to_ocn(i, j, cat) = 0.0_wp heat_to_ocn(i, j, cat) = 0.0_wp sw_thru(i, j, cat) = 0.0_wp snow_to_ice(i, j, cat) = 0.0_wp if (wet_mask(i, j) > 0.5_wp .and. m_ice(i, j, cat) > ICE_RHO_ICE*H_VANISHED) then m_snow_pt = m_snow(i, j, cat) m_ice_pt = m_ice(i, j, cat) enth_snow_pt = enth_snow(i, j, cat, 1) enth_ice_col(1:nk) = enth_ice(i, j, cat, 1:nk) sal_ice_col(1:nk) = sal_ice(i, j, cat, 1:nk) call ice_column_step(nk, m_snow_pt, m_ice_pt, enth_snow_pt, & enth_ice_col(1:nk), sal_ice_col(1:nk), & sf_0(i, j), dsf_dt(i, j), sw_dn(i, j), & tfw(i, j), fb(i, j), sst(i, j), s_surf(i, j), dtt, & do_snow_ice, & fprec(i, j)*dtt, tsurf_pt, h2o_ocn_to_ice_pt, & h2o_ice_to_ocn_pt, heat_to_ocn_pt, sw_thru_pt, & snow_to_ice_pt) m_snow(i, j, cat) = m_snow_pt m_ice(i, j, cat) = m_ice_pt enth_snow(i, j, cat, 1) = enth_snow_pt enth_ice(i, j, cat, 1:nk) = enth_ice_col(1:nk) sal_ice(i, j, cat, 1:nk) = sal_ice_col(1:nk) tsurf_out(i, j, cat) = tsurf_pt h2o_ocn_to_ice(i, j, cat) = h2o_ocn_to_ice_pt h2o_ice_to_ocn(i, j, cat) = h2o_ice_to_ocn_pt heat_to_ocn(i, j, cat) = heat_to_ocn_pt sw_thru(i, j, cat) = sw_thru_pt snow_to_ice(i, j, cat) = snow_to_ice_pt end if end do end do end subroutine ice_thermo_columns