Skip to content

McXtrace Mirror_curved: follow-up to #2936 (miss handling, instrument repairs, new targets) - #2941

Merged
willend merged 12 commits into
mainfrom
2026-10-mirror-curved-fixes
Oct 30, 2026
Merged

willend merged 12 commits into
mainfrom
2026-10-mirror-curved-fixes

Conversation

@willend

@willend willend commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #2936. This branch contains antoinepado's commit from #2936 (f9f20b0) and adds the style fixes, the instrument repairs and the new %Example targets announced in the review there. Merging this PR also merges #2936.

Component: Mirror_curved

Instruments (they relied on the old, too-long mirror)

  • SOLEIL_PX1, SOLEIL_SWING, SOLEIL_PX2a: the [rad] grazing angle was passed straight to ROTATED, which takes degrees. In PX2a, the now really tilted pre-focusing Mirror_toroid must be pitched the other way, and its takeoff and the sample stage follow. PX2a's %Example also used unknown parameters (sample=, PX2a_SPLITs=) and had no Detector:, so it never ran.
  • Si lattice constant 5.4909 → 5.4309 Å in 9 SOLEIL instruments and Template_DCM. The DCMs were set off the Bragg angle.
  • SOLEIL_SAMBA: mirror radii computed before the mrad → deg conversion (R = 535 m instead of about 9300 m), and the reflected beams now take off at 2θ.
  • SOLEIL_SIRIUS: the collimating M1 radius, 2θ takeoffs, and the deflection mirror's dimensions describing the wrong plane.
  • SOLEIL_CRISTAL: the DCM is set at the refraction-corrected Bragg angle. With the narrow source band, the kinematic angle only passed rays about 28 µrad off axis, so the beam missed the flat mirrors by 0.5 mm.
  • SOLEIL_PUMA: radii from sin(grazing angle) rather than sin(deflection); the KB VFM is rolled −90° (Mirror_curved deflects in its XZ plane, so the pitched VFM never reflected); the hand-tuned sample offset is removed. The sample focus is now 11 µm (V) × 23 µm (H) rms.

I checked every mirror's footprint (fraction of the beam inside the mirror, and its centring). DISCO, NANOSCOPIUM, XFEL_SPB and MAXIV_Bloch are aligned; their changes come from the component fix itself.

%Example targets (changes simulation results)

Inverse-variance weighted mean of 3 × n (seeds 1001, 2002, 3003) and 1 × 10n (seed 4004, capped at 3e7), using this branch's components. Only targets that moved by more than 5% are changed:

Instrument old new ratio
MAXIV_Bloch (E0=0.6) 1.80435e-21 2.6528e-21 1.47
SOLEIL_CRISTAL 7.0e5 6.2037e5 0.89
SOLEIL_DISCO 1.445e16 1.104e16 0.76
SOLEIL_GALAXIES 6.06e12 1.1407e19 1.9e6 (Si fix alone: DCM now at Bragg)
SOLEIL_NANOSCOPIUM 4.09e10 9.8902e10 2.4 (noisy)
SOLEIL_PUMA (now -n 1e7) 1.83e12 1.2410e11 0.068
SOLEIL_PX1 1.232e20 1.8992e21 15
SOLEIL_PX2a 1.535e20 3.7789e20 2.5
SOLEIL_ROCK 1.61e11 1.4117e11 0.88
SOLEIL_SAMBA 5.69e10 3.4637e12 61
SOLEIL_SIRIUS 6.69e9 1.3905e12 208
SOLEIL_SWING 1.2831e5 1.5393e12 1.2e7 (Si fix alone: 6.1e4 → 1.7e12)
XFEL_SPB 1.95e-3 9.9303e-4 0.51

Test_Mirrors (all 19 examples), MAXII_711/811, FemtoMAX, JJ_SAXS, CASSIOPEE, MARS, PSICHE, LUCIA and Template_DCM still agree within 5% and are unchanged.

Correction to my review on #2936: the MARS, ROCK and DISCO targets on main are not far off. My earlier runs used an installed Bending_magnet older than the flux fix in #2902.

Testing

  • macOS arm64 only (clang, mccode-dev conda env), CPU, no MPI. Not tested on Linux, Windows or GPU.
  • Test_Mirrors, MAXIV_Bloch (default parameters) and SOLEIL_DISCO are bit-identical with and without the miss-handling change.

🤖 Generated with Claude Code

antoinepado and others added 12 commits October 30, 2026 02:21
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… ROTATED needs deg

The [rad] grazing angle (4.1 / 4 mrad) was passed directly to ROTATED,
which takes degrees, so the KB mirrors were tilted by ~0.07 mrad and
the beam landed 0.4-0.7 m off the mirror centre. The old Mirror_curved
bounds check hid this by accepting hits beyond the mirror.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… ABSORB wins

RESTORE_XRAY makes the runtime call particle_restore() after TRACE and
EXTEND, and that clears ABSORBED. An instrument's
EXTEND %{ if (!SCATTERED) ABSORB; %} was therefore cancelled for every
ray the mirror rejected, and those rays continued unreflected (61% of
the beam after SOLEIL_SAMBA M1). Put x, y, z, t, phi back by hand
instead; the ray state on a miss is unchanged, but absorption in EXTEND
now holds.

Results are unchanged for instruments without such an EXTEND block
(Test_Mirrors, MAXIV_Bloch, SOLEIL_DISCO identical to the digit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The DCM Bragg angle in Template_DCM and the SOLEIL beamlines copied
from it used a = 5.4909 AA, a typo for silicon's 5.4309 AA (the value
Bragg_crystal itself uses via V=160.1826 AA^3). The monochromators were
set for a d-spacing 1.1% too large, i.e. detuned by ~1.4 mrad at
15 keV, outside a 0.1 keV source band.

Numerical change: DCM throughput of all these instruments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- M1/M2 radii used the angle while still in mrad as if in degrees
  (R=535 m instead of 9333 m), so M1 did not collimate.
- The M1/M2 takeoff arms were rotated by the grazing angle; the
  reflected beam leaves at twice that, so the DCM axis was 3 mrad off
  the beam.

With the Si lattice fix, the DCM now passes the collimated beam
(2.8e11 vs 2.6e10) and both mirrors are centred on the beam.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l deflection mirror

- M1 radius was a placeholder 1000 m; use the collimating radius
  2*14 m/sin(theta) like SOLEIL_SAMBA (9333 m), as the DCM comment intends.
- M1 and deflection-mirror takeoff arms were rotated by the grazing
  angle; the reflected beam leaves at twice that.
- The deflection Mirror was given yheight, which puts it in the YZ
  plane, while it is tilted about x as a horizontal mirror: the beam ran
  parallel to it and was all absorbed. Use zdepth (same 5 cm length).

Note: a 5 cm mirror at 2 mrad only accepts ~0.1 mm of beam height.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g angle

With the narrow source band, the kinematic angle only passed rays ~28 urad
off axis, so the beam landed 0.5 mm low and off the 0.3 m flat mirrors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…B VFM

- The angles are total deflections; the radii used sin(deflection), not
  sin(grazing angle), so all three mirrors were bent twice too much.
- Mirror_curved deflects in its XZ plane, so the pitched KB VFM did not
  reflect at all. Roll it by -90 deg (concave side) to focus vertically.
- Drop the hand-tuned sample offset that compensated for this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d example

- As in PX1/SWING, the [rad] grazing angle went straight into ROTATED.
- With a real 4 mrad tilt the pre-focusing Mirror_toroid must be pitched
  the other way (it is hit from +y), and its takeoff follows the reflection.
- Re-centre the sample stage on the beam after the KB.
- The %Example used unknown parameters (sample=, PX2a_SPLITs=) and had no
  Detector: label, so it never ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…x and instrument repairs

Inverse-variance weighted mean of 3 x n (seeds 1001, 2002, 3003) and
1 x 10n (seed 4004, capped at 3e7), using this branch's components.
Only targets that moved by more than 5% are changed. The large jumps
(GALAXIES, SWING, SAMBA, SIRIUS, PX1) come from the Si lattice constant
and mirror alignment fixes, which put the DCMs at Bragg and the beams
on the mirrors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The KB now focuses onto the 0.5 mm sample monitor, and a few high-weight
rays dominate: 1e6 runs scatter by 12% (CI got 121% of the weighted
target, which the lowest seed had pulled down). At 1e7 four seeds give
1.12-1.35e11; the target is their mean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@willend
willend merged commit dbb18d8 into main Oct 30, 2026
20 checks passed
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.

2 participants