Fix cvmix_KPP StokesMOST: OBL physical depth (metres) used as vertical level index#947
Open
patrickscholz wants to merge 1 commit into
Open
Fix cvmix_KPP StokesMOST: OBL physical depth (metres) used as vertical level index#947patrickscholz wants to merge 1 commit into
patrickscholz wants to merge 1 commit into
Conversation
… (level index) kpp_obldepth stores the OBL depth in physical metres (e.g. 250 m). kpp_nzobldepth stores the companion level index (e.g. 5.7). Two lines in the StokesMOST second-pass surface layer search were using kpp_obldepth as a level index: nzsfc was set to ~250 and the do-loop ran to int(250), far beyond the 47-level array bound. Without bounds checking this silently reads garbage memory; with bounds checking it segfaults. The line computing sldepth (a physical depth in metres) correctly keeps kpp_obldepth and is unchanged.
suvarchal
approved these changes
Jun 26, 2026
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.
Summary
Affects only cvmix_KPP with
kpp_use_StokesMOST = .true.(the default). Two lines in the second-pass Stokes drift surface layer search were usingkpp_obldepth(physical depth in metres) wherekpp_nzobldepth(vertical level index) is required. This causes an out-of-bounds array access on every timestep in every ocean column where the OBL is deeper than the number of vertical levels.Background: two companion OBL variables
cvmix_kpp_compute_OBL_depthproduces two outputs that are always kept in sync:kpp_obldepthreal47.3 mkpp_nzobldepthreal5.7(between levels 5 and 6)These are fundamentally different quantities.
kpp_obldepthis used for depth comparisons and physical diagnostics.kpp_nzobldepthis used whenever a level index is needed.The bug
After the OBL depth is computed, KPP runs a second Stokes drift pass to find
nzsfc— the level index of the surface layer base:A typical FESOM2 production mesh has 47 vertical levels total. The OBL depth in the open ocean regularly reaches 50–500 m, meaning
int(kpp_obldepth)produces values of 50–500. The loop then accesseszbar_3d_n(nztmp+1, node)fornztmpvalues far beyond the array's allocated size.Why it doesn't always crash
Without compiler bounds checking, Fortran out-of-bounds reads return whatever memory happens to occupy that address. The loop's
exitcondition (-zbar >= sldepth) is eventually satisfied by chance on the garbage values, sonzsfcgets assigned a seemingly plausible but physically wrong level index. The model continues silently with a corrupted surface layer index feeding into the Stokes drift and Langmuir turbulence computation.With bounds checking enabled (debug/development builds), this produces an immediate segfault.
The fix
Replace both erroneous uses of
kpp_obldepthwithkpp_nzobldepth(src/cvmix_driver/gen_modules_cvmix_kpp.F90):The
sldepthline immediately above is unchanged — it correctly useskpp_obldepthfor a physical depth comparison in metres.Scope
kpp_use_StokesMOST = .true.(the default when using the StokesMOST Langmuir turbulence package)kpp_use_StokesMOST = .false.nzsfcaffects the Stokes drift profile and Langmuir enhancement factor in the second-pass surface layer computation — the primary path for Langmuir turbulence in the KPP boundary layer