Repository navigation
Integrate a channel whose matrix element is identically zero - #135
Merged
Merged
Conversation
`p p > t t~ DIM6=0` in dim6top_LO_UFO aborted the mg7/madspace survey with RuntimeError: non-finite integral in channel '2.0' after 1000 samples (mean=nan, variance=nan) while madevent integrated the same process fine. dim6top carries an FCNC coupling order that DIM6=0 does not constrain, so MG5 keeps the four flavour-off-diagonal channels (u c~, c u~, d s~, s d~ > t t~). They have 7 diagrams each but an amplitude of exactly zero, because their Wilson coefficients are zero in the default param card. A channel like that should contribute nothing; instead it poisoned the whole run. The chain, all of it 0/0 on a channel with no amplitude anywhere: umami.cc built the per-diagram amp2 madspace samples from as numerator/denominator, the denominator being the sum of the numerators. kernel_collect_channel_weights then normalised the channel weights by the sum of those amp2. survey() divided by the subprocess mean to get its relative spread, which is a plain ZeroDivisionError once the nan above is gone and the channel correctly integrates to zero. The matrix-element multichannel weights in process_sigmaKin_function.inc and process_function_definitions.inc had the same division; they are guarded too, for the consumers that ask for mulChannelWeight (mg7 does not, so only the three above were load-bearing for this reproducer). NONE OF THE C++ GUARDS MAY BE WRITTEN AS A TEST FOR ZERO. The generated code is compiled with -ffast-math, and its -ffinite-math-only lets the compiler assume the quotient is finite and delete such a guard as dead -- an explicit `denominator == 0. ? 0. : ...` in umami.cc was silently removed, and only reappeared when a printf next to it perturbed the optimiser. This is the same trap as #117 and #516, which is why CrossSectionKernels.o is already built -fno-fast-math. The denominators here are sums of |amp|^2 and so never negative, so they are floored by adding the smallest normal instead: 0/tiny is 0, and every denominator a real amplitude produces is unchanged bit for bit. That keeps the guard robust without taking -ffast-math off a hot file. madspace's own kernel is not compiled that way, so it substitutes the norm and falls back to the uniform distribution -- the channel weights have to remain a normalised distribution, and with no amplitude to prefer one, none is. Verified with dim6top_LO_UFO, ctG = 1, 13 TeV, fixed mu = 91.188, NNPDF23_lo_as_0130_qed: p p > t t~ DIM6=0 mg7 736.223 +- 1.686 pb madevent 736.2 +- 0.61 pb and no regression: plain `sm` `p p > t t~` gives 718.8675807362097 pb, bit identical to the same run before this change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
theoheimel
added a commit
that referenced
this pull request
Sep 11, 2026
fix the changes from #135 on GPU
roiser
pushed a commit
to roiser/MadGraph7
that referenced
this pull request
Sep 11, 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.
The bug
p p > t t~ DIM6=0indim6top_LO_UFOaborted the mg7/madspace survey:output madeventintegrated the same process fine.dim6top carries an
FCNCcoupling order thatDIM6=0does not constrain, so MG5 keeps the four flavour-off-diagonal channels (u c~,c u~,d s~,s d~ > t t~). Each has 7 diagrams but an amplitude of exactly zero, because their Wilson coefficients are zero in the default param card. A channel like that should contribute nothing; instead it poisoned the whole run.This is not specific to dim6top — any process with a subprocess whose matrix element vanishes identically hits it.
Three 0/0 divisions in series
All of them on a channel with no amplitude anywhere, each only visible once the one before it was fixed:
umami.ccbuilds the per-diagramamp2that madspace samples from asnumerator/denominator, the denominator being the sum of the numerators.kernel_collect_channel_weightsnormalises the channel weights by the sum of thoseamp2.survey()divides by the subprocess mean to get its relative spread — a plainZeroDivisionErroronce the nan is gone and the channel correctly integrates to zero.The matrix-element multichannel weights in
process_sigmaKin_function.incandprocess_function_definitions.inccarry the same division and are guarded too, for the consumers that ask formulChannelWeight. mg7 does not, so only the three above were load-bearing for this reproducer.Reviewers: the C++ guards must not become a test for zero
This is the part that will look wrong and isn't.
The generated code is compiled with
-ffast-math, and its-ffinite-math-onlylets the compiler assume the quotient is finite — and therefore delete a zero-check as dead code. An explicitdenominator == 0. ? 0. : ...inumami.ccwas silently removed, and only began working when a debugprintfnext to it perturbed the optimiser. That is the same trap as #117 and #516, which is whyCrossSectionKernels.ois already built-fno-fast-math.These denominators are sums of
|amp|^2and so never negative, so they are floored by adding the smallest normal instead:numerator / ( denominator + std::numeric_limits<double>::min() )0/tinyis0, and every denominator a real amplitude produces is unchanged bit for bit. That keeps the guard robust without taking-ffast-mathoff a hot file. Rewriting it as anifwould compile to nothing and silently reintroduce the bug.madspace's own kernel is not built that way, so it substitutes the norm and falls back to the uniform distribution — the channel weights have to remain a normalised distribution over the channels, and with no amplitude to prefer one, none is preferred.Verification
dim6top,
ctG = 1, 13 TeV, fixedmu = 91.188,NNPDF23_lo_as_0130_qed:p p > t t~ DIM6=0(9 subprocesses, 4 identically zero)Each guard was confirmed load-bearing by reverting it and rebuilding — reverting the madspace one alone brings the nan straight back.
No regression: plain
smp p > t t~gives718.8675807362097 pb, bit-identical to the same run before this change.🤖 Generated with Claude Code