Shape/monotonicity predicate for a supplied &ocean_ice_nml hlim
list (PR-58). A SUBROUTINE, not a function — a pure FUNCTION may
not carry an intent(out) dummy (reason); pure SUBROUTINES
can. n = ice_hlim_count(hlim); ok iff ALL of:
(a) n >= 2 – one edge gives no width
to extrapolate (SIS2
divergence D1: Roundabout
fails loud here instead
of SIS2’s silent
fallback to the default
table).
(b) n <= ncat + 1 – more edges than the ITD
has bins.
(c) all(hlim(n+1:) < 0) – contiguity: no value
after the first
sentinel.
(d) hlim(1) > 0 – mh_lim(1) > 0 is a live
gate (rdb_ice_itd
ice_adjust_categories).
(e) hlim(k+1) > hlim(k), k = 1..n-1 – strictly increasing.
Checking (d)+(e) on the SUPPLIED list is sufficient for the FULL
h_lim(1..ncat+1): the constant-width extrapolation preserves
both properties by induction
(h_lim(k)-h_lim(k-1) = h_lim(k-1)-h_lim(k-2)), so no redundant
post-extrapolation check is needed.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | hlim(:) | |||
| integer, | intent(in) | :: | ncat | |||
| logical, | intent(out) | :: | ok | |||
| character(len=:), | intent(out), | allocatable | :: | reason |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | k | ||||
| integer, | private | :: | n |
pure subroutine ice_hlim_spec_is_valid(hlim, ncat, ok, reason) !! Shape/monotonicity predicate for a supplied `&ocean_ice_nml hlim` !! list (PR-58). A SUBROUTINE, not a function — a pure FUNCTION may !! not carry an `intent(out)` dummy (`reason`); pure SUBROUTINES !! can. `n = ice_hlim_count(hlim)`; `ok` iff ALL of: !! (a) n >= 2 -- one edge gives no width !! to extrapolate (SIS2 !! divergence D1: Roundabout !! fails loud here instead !! of SIS2's silent !! fallback to the default !! table). !! (b) n <= ncat + 1 -- more edges than the ITD !! has bins. !! (c) all(hlim(n+1:) < 0) -- contiguity: no value !! after the first !! sentinel. !! (d) hlim(1) > 0 -- mh_lim(1) > 0 is a live !! gate (`rdb_ice_itd` !! `ice_adjust_categories`). !! (e) hlim(k+1) > hlim(k), k = 1..n-1 -- strictly increasing. !! Checking (d)+(e) on the SUPPLIED list is sufficient for the FULL !! `h_lim(1..ncat+1)`: the constant-width extrapolation preserves !! both properties by induction !! (`h_lim(k)-h_lim(k-1) = h_lim(k-1)-h_lim(k-2)`), so no redundant !! post-extrapolation check is needed. real(wp), intent(in) :: hlim(:) integer, intent(in) :: ncat logical, intent(out) :: ok character(len=:), allocatable, intent(out) :: reason integer :: n, k n = ice_hlim_count(hlim) ok = .false. reason = "" if (n < 2) then reason = "hlim must supply >= 2 entries (a single edge has no "// & "width to extrapolate); got "//to_string(n) return end if if (n > ncat + 1) then reason = "hlim supplies "//to_string(n)//" entries, more than "// & "ncat+1 ("//to_string(ncat + 1)//")" return end if if (.not. all(hlim(n + 1:) < 0.0_wp)) then reason = "hlim is not a contiguous leading run: a value follows "// & "the first sentinel (entry "//to_string(n + 1)//")" return end if if (hlim(1) <= 0.0_wp) then reason = "hlim(1) must be > 0" return end if do k = 1, n - 1 if (.not. (hlim(k + 1) > hlim(k))) then reason = "hlim must be strictly increasing (violated at entry "// & to_string(k + 1)//")" return end if end do ok = .true. reason = "ok" end subroutine ice_hlim_spec_is_valid