aegir
Phlex-based simulation framework for the SHiP experiment.
Loading...
Searching...
No Matches
pythia_philox_engine.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 CERN for the benefit of the SHiP Collaboration
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5// pythia_philox_engine.hpp — Philox random numbers for Pythia, keyed per event
6//
7// Pythia's own generator is one sequential stream, so the event a Pythia
8// instance produces depends on how many events it produced before. Phlex
9// does not hand a serial source its events in event-number order, so with
10// more than one thread the same seed could give different events (issue
11// #133). PhiloxRndmEngine replaces Pythia's generator with a PhiloxRng that
12// the source re-keys before every event to (seed, stream, event number):
13// each event is then a function of the seed and its event number alone, as
14// for the particle gun.
15//
16// Usage: attach with pythia.setRndmEnginePtr() before pythia.init(), and
17// reset() with an initialisation key before init() too, since Pythia draws
18// random numbers while initialising. Then reset() before each next().
19//
20// Kept out of pythia_common.hpp, which the standalone Pythia benchmark
21// includes without Random123.
22
23#pragma once
24
25#include <Pythia8/Basics.h>
26
27#include <SHiP/random/philox_rng.hpp>
28#include <cstdint>
29
30namespace aegir {
31
32// Philox stream keys for the Pythia engines, distinct from the other aegir
33// streams (particle gun 0xBEEFCAFE, fixed-target sampling 0xF14ED0A7,
34// Geant4 0x47345EED).
35inline constexpr std::uint32_t kPythiaEventStream = 0x50595448; // "PYTH"
36inline constexpr std::uint32_t kPythiaInitStream = 0x50594E49; // "PYNI"
37
38class PhiloxRndmEngine : public Pythia8::RndmEngine {
39 public:
40 // Start a fresh stream: (seed, stream) is the Philox key and ctr1 selects
41 // the sub-stream, normally the event number.
42 void reset(std::uint32_t seed, std::uint32_t stream, std::uint32_t ctr1) {
43 rng_ = SHiP::random::PhiloxRng{seed, stream, ctr1};
44 }
45
46 // Uniform in (0, 1): Pythia's own generator never returns 0, and some of
47 // its samplings take a logarithm of the draw. Pythia's own generator has
48 // 48 bits of resolution, so one 32-bit Philox word per draw would be
49 // coarser; uniform53() spends two.
50 double flat() override {
51 double u = rng_.uniform53();
52 while (u == 0.0) {
53 u = rng_.uniform53();
54 }
55 return u;
56 }
57
58 private:
59 SHiP::random::PhiloxRng rng_{0};
60};
61
62} // namespace aegir
Definition pythia_philox_engine.hpp:38
double flat() override
Definition pythia_philox_engine.hpp:50
void reset(std::uint32_t seed, std::uint32_t stream, std::uint32_t ctr1)
Definition pythia_philox_engine.hpp:42
Definition hepmc_status.hpp:17
constexpr std::uint32_t kPythiaEventStream
Definition pythia_philox_engine.hpp:35
constexpr std::uint32_t kPythiaInitStream
Definition pythia_philox_engine.hpp:36