aegir-genie
GENIE neutrino event generation for the SHiP experiment's aegir framework.
Loading...
Searching...
No Matches
genie_driver_setup.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// genie_driver_setup.hpp — shared GENIE MC-job assembly
6//
7// One code path builds the GMCJDriver machinery (tune, splines, GeoModel
8// geometry, SHiP flux driver) for both consumers, so their events are
9// directly comparable:
10// - the phlex source plugin (genie_source.cpp), and
11// - the standalone generator app (gevgen_ship.cpp).
12//
13// Initialization order matters (cf. nugen/GENIEHelper): the tune must be
14// set and built before anything touches PDGLibrary; splines load after the
15// tune; the geometry analyzer and flux driver attach to the GMCJDriver last.
16
17#pragma once
18
19#include <cstdint>
20#include <memory>
21#include <string>
22
23#include "genie_config.hpp"
25
26namespace genie {
27class EventRecord;
28class GFluxI;
29class GMCJDriver;
30namespace flux {
31class GFluxExposureI;
32}
33} // namespace genie
34
35namespace aegir {
36
37// The assembled MC-job machinery. GMCJDriver only borrows the flux driver
38// and geometry analyzer, so the bundle owns all three; keep it alive for as
39// long as events are generated. The flux driver is either an
40// aegir::ShipFluxDriver (flux_format 'ship') or a
41// genie::flux::GSimpleNtpFlux ('gsimple'); consumers should use the GFluxI /
42// GFluxExposureI interfaces where possible.
44 std::unique_ptr<ShipGeomAnalyzer> geom;
45 std::unique_ptr<genie::GFluxI> flux;
46 std::unique_ptr<genie::GMCJDriver> driver;
47
48 // Exposure/POT accounting view of the flux driver (both implementations
49 // provide it); nullptr only if a future driver does not.
50 genie::flux::GFluxExposureI* exposure() const;
51
52 // Out of line: the members' types are incomplete here.
55 GenieDriverBundle& operator=(GenieDriverBundle&&) noexcept;
57};
58
59// Validates the config and assembles a fully Configure()d GMCJDriver:
60// tune -> Messenger -> RandGen -> splines -> GeoModel/ShipGeomAnalyzer ->
61// cycling flux driver -> GMCJDriver (UseSplines, ForceSingleProbScale,
62// KeepOnThrowingFluxNeutrinos), with optional XML caching of the expensive
63// max-path-lengths geometry scan. Logs the first flux ray and the geometry
64// bounding box at startup so coordinate-frame mismatches are visible
65// immediately. `context` prefixes error messages (e.g. "genie_source",
66// "gevgen_ship"). `teardown` chooses who cleans the Geant4 stores at the end
67// (see ShipGeomAnalyzer::G4Teardown); standalone apps with no other Geant4
68// user must pass kCleanStores.
69//
70// GENIE is a web of unsynchronized singletons: call this once per process.
72 GenieSourceConfig const& cfg, std::string const& context,
73 ShipGeomAnalyzer::G4Teardown teardown =
74 ShipGeomAnalyzer::G4Teardown::kLeaveToProcess);
75
76// The tune name recorded in a gmkspl spline XML's <genie_tune name="...">
77// header, or an empty string when none is found (also for gzip-compressed
78// files, which are not sniffed). make_genie_driver refuses a spline file
79// whose recorded tune differs from the configured one: GENIE would find no
80// usable splines and silently fall back to computing every cross section
81// numerically — hours to days at 100% CPU before the first event.
82std::string spline_file_tune(std::string const& path);
83
84// Reseed every RNG stream GENIE draws from for one event — GENIE's
85// RandomGen (TRandom3), ROOT's global gRandom, and Pythia6's internal
86// RANMAR generator — with Philox-derived seeds from (base seed, event
87// number). Together with in-order flux consumption this makes each event a
88// pure function of (config, base seed, event number), so the plugin and the
89// standalone app produce identical sequences for identical configs, and
90// re-running a job reproduces it exactly. Caveat for flux_format 'gsimple':
91// GSimpleNtpFlux does not rewind on Clear("CycleHistory"), so the flux
92// position after the max-path-lengths scan — and hence the event sequence —
93// additionally depends on whether the scan ran or a cached
94// max_path_lengths_file was loaded (see make_genie_driver); reuse one cache
95// file across runs for exact reproduction (the cache-building run itself
96// samples the shifted subsequence — compare only cache-loading runs).
97void reseed_event(long base_seed, std::uint32_t event_number);
98
99// Debug aid: when the AEGIR_GENIE_RNG_TRACE environment variable is set,
100// reseed_event and trace_event print per-event RNG/flux/vertex state to
101// stderr, so the plugin and app paths can be diffed line by line.
102void trace_event(std::uint32_t event_number, genie::EventRecord const& event,
103 genie::GFluxI& flux);
104
105} // namespace aegir
Definition ship_geom_analyzer.hpp:52
Definition genie_config.hpp:22
void reseed_event(long base_seed, std::uint32_t event_number)
Definition genie_driver_setup.cpp:252
GenieDriverBundle make_genie_driver(GenieSourceConfig const &cfg, std::string const &context, ShipGeomAnalyzer::G4Teardown teardown)
Definition genie_driver_setup.cpp:116
std::string spline_file_tune(std::string const &path)
Definition genie_driver_setup.cpp:90
void trace_event(std::uint32_t event_number, genie::EventRecord const &event, genie::GFluxI &flux)
Definition genie_driver_setup.cpp:292
Definition genie_driver_setup.hpp:26
Definition genie_driver_setup.hpp:43
std::unique_ptr< genie::GFluxI > flux
Definition genie_driver_setup.hpp:45
genie::flux::GFluxExposureI * exposure() const
Definition genie_driver_setup.cpp:86
std::unique_ptr< ShipGeomAnalyzer > geom
Definition genie_driver_setup.hpp:44
std::unique_ptr< genie::GMCJDriver > driver
Definition genie_driver_setup.hpp:46
GenieDriverBundle(GenieDriverBundle &&) noexcept
Definition genie_config.hpp:46