Repository navigation
LEAPR discre: idone flag reuse drops all but the first in-range discrete-oscillator delta line (twt = 0) #402
Description
In src/leapr.f90, the delta-function block of discre (the twt <= 0
branch, lines ~1549–1585 in NJOY2016.78) reuses the idone flag for two
different loops — the outer loop over discrete lines and the inner
nearest-beta grid search:
!--add the delta functions to the scattering law
!--delta(0.) is saved for the incoherent elastic
if (twt.le.zero) then
m=0
idone=0
do while (m.lt.n.and.idone.eq.0) ! outer: lines
m=m+1
...
if (bes(m).lt.zero) then
be=-bes(m)
if (be.le.betan(nbeta-1)) then
db=1000
idone=0
j=0
do while (j.lt.nbeta.and.idone.eq.0) ! inner: grid search
j=j+1
jj=j
if (abs(be-betan(j)).gt.db) then
idone=1 ! <-- also exits the OUTER loop
else
db=abs(be-betan(j))
endif
enddo
...
if (add.ge.tiny) sexpb(jj-1)=sexpb(jj-1)+add
endif
endif
enddo
endifWhen the inner search finds the nearest grid point it sets idone = 1,
which also terminates the outer do while (m.lt.n.and.idone.eq.0)
loop. The net behavior: only the first in-range negative delta line is
added to the scattering law, and every subsequent line is silently skipped.
Because the lines were weight-sorted just above (the "sort the discrete
lines" block), "first" means the largest-weight in-range line — the rest of
the oscillator delta weight never reaches S(α,β).
Trigger: any deck with twt = 0 and discrete oscillators whose line
spectrum has two or more in-range downscatter lines — e.g. an
Einstein-solid-style hydride evaluated without a translational component.
Decks with twt > 0 never enter this branch (the lines are convolved
through the translational path instead), which is presumably why the
standard evaluation suite never exposed it.
Reproduction sketch: a minimal one-temperature deck with a small
continuous spectrum (tbeta = 0.5), twt = 0, and two oscillators
(nd = 2, e.g. 0.137 eV and 0.250 eV with weights 0.3/0.2) on a beta grid
reaching past both lines. The resulting S(α,β) carries a delta spike only
at the first oscillator's beta; the second line (and the
oscillator-combination lines) are absent. Note the iprint >= 2
"norm check" printout still reports the full line-weight sum, because it is
computed before this block — so the lost weight is not visible in the
diagnostic output.
Suggested fix: use a separate flag for the inner grid search, e.g.
jdone=0
j=0
do while (j.lt.nbeta.and.jdone.eq.0)
...
jdone=1
...
enddoso the outer loop runs over all n lines. (The early exit on
dwf.lt.vsmall is unaffected and can stay on the outer flag.)
We found this by cross-checking against an independent reimplementation
that convolves every in-range line: on the two-oscillator deck above it
produces distinct delta spikes at both oscillator betas, while NJOY2016.78
produces only the first.
Activity