SIS2 initialize_ice_categories
(SIS_state_initialization.F90:45-78): absent hlim_vals fills
the first min(ncat+1, 8) entries from the default
lower-thickness-limit table HLIM_DFLT_TABLE; a supplied
hlim_vals fills the first min(ncat+1, size(hlim_vals))
entries from IT instead (PR-58 — the SIS2 hLim_vals optional
dummy Roundabout’s port originally declined to carry). Either way,
the remainder extrapolates by constant width,
h_lim(k) = 2*h_lim(k-1) - h_lim(k-2), resuming at ONE PAST
however many entries were actually supplied — not at a fixed
index 9. mh_lim = ICE_RHO_ICE*h_lim (SIS2 mH_cat_bound,
SIS_state_initialization.F90:75-77). h_lim(c)/mh_lim(c) is
the LOWER bound of category c (1-based); index ncat+1 is the
lower bound that WOULD start category ncat+1 — stored (SIS2
keeps it) but never used as an upper cap on category ncat
(ice_adjust_categories’s upward pass stops at c = ncat-1).
No fixed-size local arrays — ncat is unbounded here (unlike
the per-column ICE_NK_MAX-capped layer arrays).
Thickness-distribution discretization: Thorndike, Rothrock, Maykut & Colony (1975), JGR 80, 4501-4513; Bitz, Holland, Weaver & Eby (2001), JGR 106, 2441-2463.
Documented divergences from SIS2’s initialize_ice_categories
(PR-58 plan §4):
D1 — SIS2 silently falls back to the default table for a
1-element hlim_vals (size(hLim_vals) > 1 gate,
:60). Roundabout’s caller (rdb_config%validate_config)
FAILS LOUD instead via ice_hlim_spec_is_valid (house
rule: a wordless no-op is worse than an error). This
routine itself has no opinion — the size floor is
enforced by the caller, not here.
D2 — SIS2’s namelist CALLER truncates to CatIce entries
(ice_model.F90:2110), so its top edge can never be
stated via the namelist. This routine (and Roundabout’s
&ocean_ice_nml hlim) accept the procedure’s own native
range, 2..ncat+1.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | ncat |
Number of ice thickness categories (declared first — decl-order). |
||
| real(kind=wp), | intent(out) | :: | h_lim(ncat+1) |
Category lower thickness limits (m), |
||
| real(kind=wp), | intent(out) | :: | mh_lim(ncat+1) |
Category lower mass limits (kg/m²), |
||
| real(kind=wp), | intent(in), | optional | :: | hlim_vals(:) |
entries, strictly increasing, |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private, | parameter | :: | HLIM_DFLT_TABLE(N_HLIM_DFLT) | = | [1.0e-10_wp, 0.1_wp, 0.3_wp, 0.7_wp, 1.1_wp, 1.5_wp, 2.0_wp, 2.5_wp] | |
| integer, | private, | parameter | :: | N_HLIM_DFLT | = | 8 |
Number of entries in the SIS2 default table (declared before the array that uses it — decl-order). |
| integer, | private | :: | k |
|
|||
| integer, | private | :: | n_given |
|
pure subroutine ice_itd_category_bounds(ncat, h_lim, mh_lim, hlim_vals) !! SIS2 `initialize_ice_categories` !! (`SIS_state_initialization.F90:45-78`): absent `hlim_vals` fills !! the first `min(ncat+1, 8)` entries from the default !! lower-thickness-limit table `HLIM_DFLT_TABLE`; a supplied !! `hlim_vals` fills the first `min(ncat+1, size(hlim_vals))` !! entries from IT instead (PR-58 — the SIS2 `hLim_vals` optional !! dummy Roundabout's port originally declined to carry). Either way, !! the remainder extrapolates by constant width, !! `h_lim(k) = 2*h_lim(k-1) - h_lim(k-2)`, resuming at ONE PAST !! however many entries were actually supplied — not at a fixed !! index 9. `mh_lim = ICE_RHO_ICE*h_lim` (SIS2 `mH_cat_bound`, !! `SIS_state_initialization.F90:75-77`). `h_lim(c)`/`mh_lim(c)` is !! the LOWER bound of category `c` (1-based); index `ncat+1` is the !! lower bound that WOULD start category `ncat+1` — stored (SIS2 !! keeps it) but never used as an upper cap on category `ncat` !! (`ice_adjust_categories`'s upward pass stops at `c = ncat-1`). !! No fixed-size local arrays — `ncat` is unbounded here (unlike !! the per-column `ICE_NK_MAX`-capped layer arrays). !! !! Thickness-distribution discretization: Thorndike, Rothrock, !! Maykut & Colony (1975), JGR 80, 4501-4513; Bitz, Holland, Weaver !! & Eby (2001), JGR 106, 2441-2463. !! !! Documented divergences from SIS2's `initialize_ice_categories` !! (PR-58 plan §4): !! D1 — SIS2 silently falls back to the default table for a !! 1-element `hlim_vals` (`size(hLim_vals) > 1` gate, !! `:60`). Roundabout's caller (`rdb_config%validate_config`) !! FAILS LOUD instead via `ice_hlim_spec_is_valid` (house !! rule: a wordless no-op is worse than an error). This !! routine itself has no opinion — the size floor is !! enforced by the caller, not here. !! D2 — SIS2's namelist CALLER truncates to `CatIce` entries !! (`ice_model.F90:2110`), so its top edge can never be !! stated via the namelist. This routine (and Roundabout's !! `&ocean_ice_nml hlim`) accept the procedure's own native !! range, `2..ncat+1`. integer, intent(in) :: ncat !! Number of ice thickness categories (declared first — !! decl-order). real(wp), intent(out) :: h_lim(ncat + 1) !! Category lower thickness limits (m), `h_lim(1:ncat+1)`. real(wp), intent(out) :: mh_lim(ncat + 1) !! Category lower mass limits (kg/m²), `= ICE_RHO_ICE*h_lim`. real(wp), intent(in), optional :: hlim_vals(:) !! PR-58: optional user-supplied lower edges (m), `2..ncat+1` !! entries, strictly increasing, `hlim_vals(1) > 0` — SIS2 !! `initialize_ice_categories`'s `hLim_vals` !! (`SIS_state_initialization.F90:50`). Assumed-shape is correct !! here: this is a host-side, once-per-run `init` routine with !! no `do concurrent`, not a per-step kernel. Absent => the !! pre-PR-58 behaviour, bit-for-bit (the default-table branch !! below is unmodified). Validated by the caller !! (`ice_hlim_spec_is_valid`) before it ever reaches here — this !! routine trusts its shape. integer, parameter :: N_HLIM_DFLT = 8 !! Number of entries in the SIS2 default table (declared before !! the array that uses it — decl-order). real(wp), parameter :: HLIM_DFLT_TABLE(N_HLIM_DFLT) = & [1.0e-10_wp, 0.1_wp, 0.3_wp, 0.7_wp, 1.1_wp, 1.5_wp, 2.0_wp, 2.5_wp] integer :: n_given, k !! `n_given`: how many entries were actually filled from the !! source (table OR `hlim_vals`) before extrapolation takes !! over. Renamed from the pre-PR-58 `n_dflt` (PR-58 plan §11.1) !! because after this change it no longer means "how many came !! from the table" — it means "how many came from wherever we !! got them", and the extrapolation loop below is only correct !! if it resumes at `n_given + 1` regardless of source. if (present(hlim_vals)) then n_given = min(ncat + 1, size(hlim_vals)) do k = 1, n_given h_lim(k) = hlim_vals(k) end do else n_given = min(ncat + 1, N_HLIM_DFLT) do k = 1, n_given h_lim(k) = HLIM_DFLT_TABLE(k) end do end if do k = n_given + 1, ncat + 1 h_lim(k) = 2.0_wp*h_lim(k - 1) - h_lim(k - 2) end do do k = 1, ncat + 1 mh_lim(k) = ICE_RHO_ICE*h_lim(k) end do end subroutine ice_itd_category_bounds