Legacy source patches¶
This page records the small source-level robustness patches applied to the vendored legacy odt1 Fortran sources in this repository.
The purpose of this page is to make one distinction very clear:
these patches are not algorithm redesigns, and
they are not intended to change ODT model physics,
but they do remove compiler-fragile legacy coding patterns that prevented reliable runtime validation in the current environment.
Why patches were needed¶
During direct Fortran-vs-Python validation, the major remaining runtime problem was the original BSnap intercomparison path (ioptions(1)=0).
The unmodified legacy code used a header-writing convention based on negative N:
BSnap.ftemporarily negatedNthen called
BRecordBRecord.fdeclared local arrays usingNand only later normalized with
N = abs(N)
Under the local gfortran 9.4.0 toolchain, this led to crashes in the unmodified path.
A dedicated reproducer remains available:
scripts/investigate_bsnap_intercomparison.py
That reproducer shows:
the original unmodified intercomparison path crashes,
the patched legacy intercomparison path runs,
and the patched output matches the Python implementation numerically.
Files patched¶
The following vendored legacy sources were patched:
external/odt1/source1/BRecord.fexternal/odt1/source1/BSnap.f
What was patched¶
1. BRecord.f¶
Original issue¶
The original routine used the signed incoming N directly in array declarations and only later normalized it:
header mode was indicated by
N < 0local storage depended on
Nnormalization happened afterward via
N = abs(N)
That pattern is compiler-fragile because it allows negative extents to participate in runtime storage logic before the value is sanitized.
Patch applied¶
The patched version now:
treats the incoming array as assumed-size (
s(*))computes
nabs = abs(N)immediatelyuses
nabsfor loop extents and output countuses a fixed local buffer rather than negative-extent local storage
Effect of the patch¶
This preserves the intended record semantics:
negative
Nstill means “write header first”the same record values are written
formatting remains the same
But it removes the fragile dependency on negative extents in local array sizing.
2. BSnap.f¶
Original issue¶
The original intercomparison path used in-place mutation of N:
N = -Ncall BRecord(ifile, N, ht)
This was intended only as a signaling trick for header writing, but it meant the signed argument passed into BRecord could trigger the unsafe behavior described above.
Patch applied¶
The patched version introduces a separate variable:
NWRITE = -Ncall BRecord(ifile, NWRITE, ht)
The physical mesh size N itself is no longer negated in-place.
Effect of the patch¶
This preserves the intended file-format semantics while avoiding mutation of the principal loop/index variable.
What behavior changed¶
The following behavior changed:
the patched legacy intercomparison path now runs successfully under the local toolchain
BSnapintercomparison-mode output can now be directly compared numerically against Pythonthe repository no longer needs temporary generated patched stand-ins for routine-level validation of this path
In practical terms, this means:
patched
BSnapintercomparison mode is now part of the normal comparison workflowsee
scripts/compare_bsnap_intercomparison.py
What behavior did not change¶
The patches are not intended to change:
ODT sampling logic
eddy acceptance logic
triplet-map behavior
deterministic advancement formulas
statistics formulas
output-file semantics for the legacy intercomparison format
output-file semantics for xmgrace mode
The model equations and the intended file contents remain the same.
The patch only changes how the legacy code expresses header signaling and temporary storage, so that the intended behavior runs reliably.
Validation status after patching¶
After patching:
patched
BSnapintercomparison mode runspatched
BSnapxmgrace mode runsdirect comparison against Python shows small floating-point / formatting-level differences only
See:
scripts/compare_bsnap_intercomparison.pyscripts/compare_postprocessing.pyscripts/investigate_bsnap_intercomparison.py
How to describe this in project status¶
The most accurate wording is:
the original unmodified historical intercomparison path is compiler-fragile,
the repository now includes a minimal robustness patch for that path,
and the patched legacy path is directly runtime-validated.
That is more precise than either of the following oversimplifications:
“the original intercomparison path works everywhere”
“intercomparison mode is unsupported”
Neither of those is true anymore.