Skip to content

madspace: evaluate the matrix element on the momenta the event is written with - #170

Open
oliviermattelaer wants to merge 1 commit into
mainfrom
claude/madspace-mirror-me-momenta
Open

oliviermattelaer wants to merge 1 commit into
mainfrom
claude/madspace-mirror-me-momenta

Conversation

@oliviermattelaer

Copy link
Copy Markdown
Contributor

The initial-state mirror covers the beam-swapped copy of an asymmetric initial
state by rotating the event by pi about x (py, pz -> -py, -pz,
kernel_mirror_momenta), which moves each leg onto the other beam. Only the
written event was rotated: Integrand::build_common_part kept feeding the
cross section momenta_acc, the momenta as generated.

That is sound only if |M|^2 is invariant under the rotation.

Why it is wrong

It is invariant for any Lorentz invariant matrix element, and for a
longitudinally polarised one. It is not for a transversely polarised
particle evaluated in a frame that holds it at rest: HELAS quantises such a
particle along the frame z axis (the pp == 0 branch of vxxxxx) rather
than along its own momentum, the mirror flips that axis, and the + and - states
swap.

Measured in FP64, |M(mirror p)|^2 / |M(p)|^2 - 1 on g q > z{+} q:

frame the ME is evaluated in unpolarised z{0} z{+}
as generated 6e-16 2e-14 1e-15
partonic CM 4e-16 8e-15 3e-16
rest frame of beam 1 + Z 8e-16 1e-14 6e-15
Z rest frame 6e-15 6e-15 4.8e-01

So it is not "any boosted frame" — it is specifically a transversely polarised
particle held at rest, which is what asking for the Z rest frame does.

What it cost

On a symmetric pp collider the two beams cannot be told apart, and the mirror is
precisely what averages over them, so sigma(p p > z{+} j) and
sigma(p p > z{-} j) have to be equal. They were not:

p p > z{+} j p p > z{-} j split
before 4485 +- 39 pb 6060 +- 54 pb 23 sigma
after 5299 +- 32 pb 5265 +- 33 pb 0.7 sigma

The sum over the three polarisations was always right (10545 +- 67 vs
10564 +- 46), so the bug only misallocated between + and -. That is why no
unpolarised result moves — p p > z j is 12420 +- 69 pb before and
12430 +- 110 pb after — and why nothing ever caught it.

The fix

Evaluate the matrix element on the momenta the event is written with. No
symmetry assumption at all. Two things already assumed this:

  • madevent does the same thing: it flips the momentum array itself and
    passes that same array to both the matrix element and the event record
    (super_auto_dsig_group_v4.inc, "Flip momenta (rotate around x axis)";
    write_leshouche's "flip back particle 1 and 2" only relabels the two beam
    legs, it does not undo the rotation). So this aligns madspace with madevent
    rather than inventing a convention.
  • SystematicsCalculator::matrix_elements reads the momenta back out of the
    event buffer
    , i.e. the mirrored ones, so the nominal weight and its
    scale/PDF variations were computed on different momenta for the same event.

Impact and testing

Half the events of a mirrored subprocess now have their matrix element
evaluated on sign-flipped momenta, so existing results shift in the last bits
and LHE hashes move. The reproducibility tests compare runs to each other and
the xsec references have a 1% tolerance, so nothing should break — the
unpolarised control above is the direct check.

The regression test that guards this needs the me_frame run-card setting to
reach the broken branch at all, so it travels with the follow-up PR that adds
me_frame (test_polarised_mirror_symmetry_mg7, CI job
acceptancetest_mg7_polarised_mirror). It fails on this PR's parent commit and
passes with it.

madspace test suite: 1545 pass. Full unit suite: unchanged against main (the
two reds on main — a missing scipy and a MadLoop IOTest golden drift that only
appears in a full-suite run — reproduce on a clean checkout).

🤖 Generated with Claude Code

…tten with

The initial-state mirror covers the beam-swapped copy of an asymmetric
initial state by rotating the event by pi about x (py, pz -> -py, -pz,
kernel_mirror_momenta), which moves each leg onto the other beam. Only the
written event was rotated: Integrand::build_common_part kept feeding the
cross section the momenta as generated.

That is sound only if |M|^2 is invariant under the rotation. It is for any
Lorentz invariant matrix element, and for a longitudinally polarised one.
It is not for a transversely polarised particle evaluated in a frame that
holds it at rest: HELAS quantises such a particle along the *frame* z axis
(the pp == 0 branch of vxxxxx) rather than along its own momentum, the
mirror flips that axis, and the + and - states swap. Measured in FP64 on
g q > z{+} q evaluated in the Z rest frame: 48% between |M|^2 on the
mirrored and unmirrored momenta, against 1e-15 for the unpolarised process,
for z{0}, and for z{+} in any frame that does not hold the Z at rest.

End to end this broke a symmetry that must hold: on a symmetric pp collider
the two beams cannot be told apart, and the mirror is what averages over
them, so sigma(p p > z{+} j) and sigma(p p > z{-} j) have to be equal. They
came out 4485 +- 39 pb against 6060 +- 54 pb, 23 sigma apart; they now agree
within 1 sigma. The sum over the three polarisations was already correct,
which is why no unpolarised result moves (p p > z j: 12420 +- 69 pb before,
12430 +- 110 pb after) and why nothing caught this.

Two other things already assumed the fixed behaviour:

  - madevent flips the momentum array itself and passes that same array to
    both the matrix element and the event record
    (super_auto_dsig_group_v4.inc, "Flip momenta (rotate around x axis)"),
    so this aligns madspace with it rather than inventing a convention;
  - SystematicsCalculator::matrix_elements reads the momenta back out of the
    event buffer, i.e. the mirrored ones, so the nominal weight and its
    scale/PDF variations were computed on different momenta for the same
    event.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant