REL-3.1.6: remove the RTV_Create zero-fill, AOD Skip_Profile, multi-sensor fix, pin fix_REL-3.1.6.0, bump to v3.1.6 - #375
Open
BenjaminTJohnson wants to merge 16 commits into
Open
BenjaminTJohnson wants to merge 16 commits into
BenjaminTJohnson wants to merge 16 commits into
Conversation
…ff/ACCoeff sibling files (previously skipped silently, disabling the non-LTE and antenna corrections for netCDF-coefficient users); adds test_NLTE_Verification to guard the sibling load.
) RTV_Create is called once per profile from every CRTM entry point and, since v3.x, explicitly zero-filled every array it allocated: ~40 MB at n_Stokes=1. glibc hands memory of that size back to the kernel on RTV_Destroy, so each call faulted the whole footprint back in. That page faulting plus the memset was the dominant cost of a cloudy CRTM_Forward or CRTM_K_Matrix call and made them up to ~45x slower than v2.4.1, whose RTV_Create never zeroed these arrays. This removes the 73 zero-fill assignments and the comments about them, and documents why in the routine. No other code changes. Validation, gfortran 13.3 -O3, release/REL-3.1.5 build: - full ctest suite: 196/196 pass before and after - every RTSolution .nc the suite writes is bit-identical before/after - test_Simple amsua_metop-a (1 cloud, 1 aerosol), OMP_NUM_THREADS=1: 9.7 ms/call -> 0.8 ms/call Not exercised by the suite: RT_VMOM and n_Stokes > 1. The structural fix (allocate once per call, on-demand solver groups) remains #368. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit a383119)
#370) 5652d0a removed the zero-fill of every RTV work array. One array is read before it is written: the ADA solvers (CRTM_ADA, CRTM_ADA_TL, CRTM_ADA_AD) guard each layer with IF(w(k) > SCATTERING_ALBEDO_THRESHOLD .and. maxval(abs(RTV%Pff(1:nZ,1:nZ,k))) > ZERO) and at n_Stokes=1 CRTM_Phase_Matrix fills Pff only for scattering layers. Fortran .and. does not short-circuit, so gfortran 13.3 -O3 evaluates the maxval over unwritten memory for the non-scattering layers. The IF result is unchanged (w(k) decides it), so outputs are identical, but a NaN bit pattern in recycled memory raises FE_INVALID and aborts runs with FP trapping enabled: with NaN-filled allocations and -ffpe-trap=invalid, the branch head before this commit stops with SIGFPE at ADA_Module.f90:167 where v3.1.5 runs. Zeroing Pff (~200 KB at n_Stokes=1, against the 40 MiB previously zeroed) restores exactly the v3.1.5 contents for this array. Validated against v3.1.5 (d5e5d8e) with gfortran 13.3, ifort 2021.13 and ifx 2024.2: ctest 196/196 with all 367 suite outputs bit-identical; ADA/VMOM/SOI forward and K spot checks bit-identical; valgrind memcheck clean in all 30 spot cases (12 reported uninitialised reads before this change). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CRTM_Version.inc had reported v3.1.2 since v3.1.3. The string is used only by CRTM_Version() (program banners and the SpcCoeff/CloudCoeff converter metadata), not in any radiative-transfer output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs CRTM_AOD, _TL, _AD and _K on three aerosol profiles (v.abi_g18), then again with profile 2 given a negative pressure and flagged with Options%Skip_Profile, and asserts that all four functions return SUCCESS, that profiles 1 and 3 are bit-identical to the unflagged run, and that the flagged profile's outputs are left as the caller set them. Writes no result files. Against the v3.1.5 library (d5e5d8e) 6 of the 10 assertions fail: _TL, _AD and _K return FAILURE ("Input data check failed for profile #2"). With this branch all 10 pass, and the full suite is 197/197 with every suite output bit-identical to v3.1.5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d per-sensor RTV re-create
A single CRTM call with multiple ChannelInfo entries computed the
per-thread channel index as ln = (start_ch-1) - n_inactive_channels(nt),
an absolute per-sensor value: for the 2nd+ sensor every thread restarted
at the array base and overwrote sensor 1's RTSolution (and, in K,
Atmosphere_K/Surface_K rows), leaving the tail of the arrays untouched.
ln enters the FIRSTPRIVATE clause already holding the previous sensors'
cumulative count, so the fix is to offset from it (Forward/TL/K; the
Adjoint's purely-cumulative loop was already correct). Preexisting on
develop; invisible to the suite, which passes one sensor per call.
Also gate RTV_Create on RTV_Associated: RTV is per-profile, so the 2nd+
sensor re-ALLOCATE'd already-allocated arrays ('error in allocate Pff
5014' noise) and relied on the failed-allocate path leaving the old
allocation in place. Dims are invariant within a profile, and channel
loops already reuse the arrays without re-zeroing, so skipping is sound.
New test_Unit_MultiSensor_SingleCall pins one amsua_metop-a+mhs_n19 call
bit-for-bit to the per-sensor calls for FWD, TL and K (verified to FAIL
against the unfixed code).
(cherry picked from commit 50ca243, with the
conflicts in the Adjoint, K-Matrix and Tangent-Linear modules resolved for the
3.1.x code; the RTV_Create guard and the ln offset are the same change.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…+ d43acb9) Completes the multi-sensor fix (previous commit) as 3.2.0 did: - 13cd613: the channel PARALLEL DO accumulated ln FIRSTPRIVATE across Thread_Loop iterations, which is correct only when every thread runs exactly one iteration. Capture ln_base before the region, make ln PRIVATE, and rebuild ln = ln_base + (start_ch - 1) - n_inactive_channels(nt) each iteration. - d43acb9: on a serial channel loop the loop body mutates the outer ln, so the post-loop advance double-counted. Derive it from ln_base. In 3.1.x this is the path CRTM_K_Matrix always takes: its channel threading is compiled out by the #231 gate (#if 1). Applied to CRTM_Forward, CRTM_Tangent_Linear and CRTM_K_Matrix (CRTM_Adjoint has no channel threading). (backported from commits 13cd613 and d43acb9) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test arrived with the 50ca243 backport but was not registered. It pins one amsua_metop-a + mhs_n19 CRTM_Forward/TL/K_Matrix call bit-for-bit to the per-sensor calls. Registered as on feature/btj_REL-3.2.0, through ADD_CRTM_UNIT_TEST so it also gets OMP_NUM_THREADS like the other unit tests. Fails on the branch before the backport (9 of 20 assertions pass, at 1 and 4 threads); passes 20 of 20 with it, including a bounds-checked build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix_REL-3.1.6.0.tgz (md5 b0de48587aa0bf731a4aa41fd4094ecc) is fix_REL-3.1.2.1 plus the 3.1.x-usable content of the pinned fix_REL-3.2.0.0 tarball. It has Little- and Big-Endian binaries regenerated for every new or changed sensor, the GOCART-GEOS5 brown-carbon/backscatter table that test_AOD looks for, the v.viirs-m_j2 correction, and the OMPS AllFOV j2 files removed. Its README and CHANGES list are inside the tarball. Also drops the duplicated cris-fsr_n21 SpcCoeff/TauCoeff entries from crtm_test_input. The GOCART-GEOS5 BRC staging line stays: the file now exists. Push only together with publishing the tarball at bin.ssec.wisc.edu/pub/s4/CRTM/. Changing the pinned md5 makes every existing local copy re-download (see #325). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 of 11 tasks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Also point the coefficient download path at fix_REL-3.1.6.0, which the tests are now pinned to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…NT (#370) With the zero-fill removed, the aircraft observer reads RTV elements that no solver writes: - SOI with Options%Aircraft_Pressure > 0 returns s_Level_Rad_UP at the aircraft level, which SOI does not compute. v3.1.5 returned 0 there (from the zero-fill); without it the radiance came from whatever the memory held. - ADA/VMOM with the aircraft observer at n_Stokes > 1 initialise only the Stokes-I rows of level 0 of s_Level_Rad_DOWN/DOWNT, then read and copy every row. Zero the three arrays (nZ x (n_Layers+1) each, a few KB) so these paths see the same values as in v3.1.5. Found with an RTV_Create that sets each array to a NaN carrying the array's index, and with NaN-filled allocations, on aircraft cases.
fix_REL-3.1.6.0.tgz is re-rolled under the same name: md5 ecfba7bb866f2a34b6281ae03740b161, was b0de48587aa0bf731a4aa41fd4094ecc. The 39 ABI files with value changes are restored to their fix_REL-3.1.2.1 contents, which are byte-identical to fix_REL-3.1.2.0: SpcCoeff and ODPS TauCoeff for abi_g16, abi_g17, abi_g18, abi_g19, abi_gr and abi-81K_g17, and v.abi_g18 SpcCoeff, in netCDF, Little- and Big-Endian form. The regenerated ABI TauCoeff from fix_REL-3.2.0.0 is a model refit, not a defect fix, so it stays in fix_REL-3.2.0.x. It moved JEDI GOES-16 ABI H(x) by about 0.3 K RMS. Existing extractions of the first roll are not refreshed: CMake skips the download when test-data-release/fix_REL-3.1.6.0 already exists.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The CRTM v3.1.6 maintenance release, on top of
release/REL-3.1.5. Tracking issue: #374.Changes
RTV_Createno longer zero-fills its work arrays ([v3.1.6 / v3.2.0] Remove the RTV_Create zero-fill: cloudy CRTM_Forward/K_Matrix ~45x slower than v2.4.1 (backport of #368, minimal fix) #370).n_Stokes = 1(603 MiB atn_Stokes = 4), plus the page faults it caused, dominated every call with clouds, aerosols or a visible/UV sensor.RTV%Pff(e98576f): the ADA guard readsmaxval(abs(Pff))for non-scattering layers. That read never changes a result, but on recycled memory it could raise FE_INVALID under FP trapping.s_Level_Rad_UP,s_Level_Rad_DOWN,s_Level_Rad_DOWNT(171e86c, a few KB each): read by the aircraft observer (Options%Aircraft_Pressure > 0). SOI returnss_Level_Rad_UPat the aircraft level, which it never computes. ADA/VMOM atn_Stokes > 1leave the Q/U/V rows of the top level unset. Without the zeroing these cases returned whatever the memory held, instead of the v3.1.5 values.CRTM_AOD_TL,CRTM_AOD_ADandCRTM_AOD_KhonourOptions%Skip_Profile(add profile skipping for AOD_TL/AOD_AD/AOD_K #372).-x).test_AOD_Skip_Profile(dc77d99) guards it.ChannelInfo, sensor 2 overwrote sensor 1'sRTSolution, and in K its Atmosphere and Surface Jacobians.error in allocate Pff 5014).test_Unit_MultiSensor_SingleCallis now registered in ctest (f1093de).CRTM_VERSIONand the CMake and README versions now report v3.1.6 (e573c23, e84db3a, f5df98a).CRTM_VERSIONhad reported v3.1.2 since v3.1.3. The README release line is dated October 2, 2026 and lists all four changes, and its coefficient download path names fix_REL-3.1.6.0 (8670c3d, 43aec7a).fix_REL-3.1.6.0(a8f9702; re-pinned to the second roll in fa8ac7c).https://bin.ssec.wisc.edu/pub/s4/CRTM/fix_REL-3.1.6.0.tgz(md5ecfba7bb866f2a34b6281ae03740b161). This second roll replaces the first (md5b0de48587aa0bf731a4aa41fd4094ecc).Output compatibility
With the same coefficient files, v3.1.6 output is bit-identical to v3.1.5 for every single-sensor call, with two intended exceptions:
Skip_Profile;Validation
Cloud_Fractionset) and aerosol profiles;n_Stokes2/4; OpenMP 1/4/8 threads.MALLOC_PERTURB_, forced heap reuse, and NaN-filled allocations with FP trapping.RTV_Createfills each work array with a NaN marking that array also matches v3.1.5. So no other work array is read before it is written in these cases.Before or at merge
test-data-release/fix_REL-3.1.6.0exists, and it checks the md5 only when it downloads. Delete or rename that directory before building.v3.1.6tag, therelease/REL-3.1.6branch and the GitHub release will be created by hand after the merge.🤖 Generated with Claude Code