Precondition test for one remap column, as a pure predicate so the
caller decides what to do about a violation (audit findings V5, V6).
The overlap sweep every method shares assumes BOTH of
dz_old(k) >= 0 and dz_new(k) >= 0 — a negative source
thickness makes the cumulative interface stack z_old
NON-MONOTONE, and the sweep then integrates the reversed
interval twice, CREATING mass with no NaN and no bounds hit;sum(dz_old) == sum(dz_new) — the sweep integrates the
reconstruction only over the overlap of the two stacks, so a
SHORT target silently deletes the non-overlapping tail and a
LONG target integrates it as q = 0, diluting the outermost
target cell.Neither is checked inside the kernels: they are caller obligations, and a kernel-side check would cost a branch per column in the hot loop for a condition that must never hold. This predicate exists so a cadence-bounded caller can assert them and fail loud.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dz_old(nz) |
Source-column thicknesses. |
||
| real(kind=wp), | intent(in) | :: | dz_new(nz) |
Target-column thicknesses. |
||
| real(kind=wp), | intent(in) | :: | rel_tol |
Relative tolerance on the column-total match, applied against the larger of the two totals (so a land column of zero total passes trivially). |
.true. when both preconditions hold.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | k | ||||
| real(kind=wp), | private | :: | s_new | ||||
| real(kind=wp), | private | :: | s_old |
pure function remap_column_preconditions_ok(nz, dz_old, dz_new, rel_tol) result(ok) !$acc routine seq !! Precondition test for one remap column, as a `pure` predicate so the !! caller decides what to do about a violation (audit findings V5, V6). !! !! The overlap sweep every method shares assumes BOTH of !! !! * `dz_old(k) >= 0` and `dz_new(k) >= 0` — a negative source !! thickness makes the cumulative interface stack `z_old` !! NON-MONOTONE, and the sweep then integrates the reversed !! interval twice, CREATING mass with no NaN and no bounds hit; !! * `sum(dz_old) == sum(dz_new)` — the sweep integrates the !! reconstruction only over the overlap of the two stacks, so a !! SHORT target silently deletes the non-overlapping tail and a !! LONG target integrates it as `q = 0`, diluting the outermost !! target cell. !! !! Neither is checked inside the kernels: they are caller obligations, !! and a kernel-side check would cost a branch per column in the hot !! loop for a condition that must never hold. This predicate exists so !! a cadence-bounded caller can assert them and fail loud. integer, intent(in) :: nz real(wp), intent(in) :: dz_old(nz) !! Source-column thicknesses. real(wp), intent(in) :: dz_new(nz) !! Target-column thicknesses. real(wp), intent(in) :: rel_tol !! Relative tolerance on the column-total match, applied against !! the larger of the two totals (so a land column of zero total !! passes trivially). logical :: ok !! `.true.` when both preconditions hold. real(wp) :: s_old, s_new integer :: k ok = .true. s_old = 0.0_wp s_new = 0.0_wp do k = 1, nz if (dz_old(k) < 0.0_wp) ok = .false. if (dz_new(k) < 0.0_wp) ok = .false. s_old = s_old + dz_old(k) s_new = s_new + dz_new(k) end do if (abs(s_new - s_old) > rel_tol*max(abs(s_old), abs(s_new))) ok = .false. end function remap_column_preconditions_ok