aegir-genie
GENIE neutrino event generation for the SHiP experiment's aegir framework.
Loading...
Searching...
No Matches
ship_geom_analyzer.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// ship_geom_analyzer.hpp — GENIE geometry analyzer over the SHiP geometry
6// service
7//
8// Implements genie::GeomAnalyzerI directly on the GeoModel-built Geant4
9// geometry (ship::IGeometryService + ship::G4RayScanner), so GENIE sees the
10// exact same geometry the Geant4 simulation tracks through — no GDML/TGeo
11// conversion in between. The contract mirrors GENIE's ROOTGeomAnalyzer:
12// - path lengths are density-weighted (rho x length x element mass
13// fraction) in SI kg/m2, one entry per target nucleus;
14// - target nuclei are one averaged-A ion per element,
15// IonPdgCode(Nint(N), Z) — no isotope expansion, keeping the
16// genie-splines-ship target list valid;
17// - positions arrive and leave in SI meters (the GFluxI frame);
18// - max path lengths come from a flux-ray scan (SetScannerFlux) with a
19// safety factor, and the scan ends with flux->Clear("CycleHistory") so
20// scan rays do not count as delivered POT.
21//
22// All Geant4 work (GeoModel->G4 conversion, navigation, teardown) is
23// confined to one process-wide geometry thread shared by all analyzers: the
24// conda Geant4 is an MT build, whose logical/physical volumes keep
25// per-thread state usable only on the creating thread — and only a single
26// thread per process may create geometry at all (see geometry_thread() in
27// the implementation) — while phlex may run even a serial source on
28// changing TBB threads.
29
30#pragma once
31
32#include <TLorentzVector.h>
33#include <TVector3.h>
34
35#include <memory>
36#include <string>
37
38#include "Framework/EventGen/GeomAnalyzerI.h"
39#include "Framework/EventGen/PathLengthList.h"
40#include "Framework/ParticleData/PDGCodeList.h"
41
42namespace genie {
43class GFluxI;
44}
45namespace ship {
46class IGeometryService;
47}
48
49namespace aegir {
50
51class ShipGeomAnalyzer final : public genie::GeomAnalyzerI {
52 public:
53 enum class G4Teardown {
54 // The process (e.g. aegir's geant4_module) owns Geant4 store cleanup.
56 // Clean the Geant4 stores on the geometry thread in the destructor —
57 // required when nothing else does it (gevgen_ship), because the store
58 // singletons otherwise delete thread-local volume state from the main
59 // thread at exit (aegir issue #68).
61 };
62
63 // `top_volume` empty: scan the full world. Otherwise the named logical
64 // volume becomes the scan world; it must exist and be placed exactly once,
65 // and flux-frame coordinates are mapped through its placement transform.
66 // Must be constructed after the GENIE tune (PDGLibrary) is initialized.
67 // Takes ownership of the service and keeps it (and with it the GeoModel
68 // tree) alive for the analyzer's lifetime — GeoModel2G4 caches conversions
69 // in static maps keyed by GeoModel pointers, so freeing the tree early
70 // would poison any later conversion in the same process.
71 ShipGeomAnalyzer(std::unique_ptr<ship::IGeometryService> geometry,
72 std::string const& top_volume, G4Teardown teardown);
73 ~ShipGeomAnalyzer() override;
74
79
80 // ROOTGeomAnalyzer-compatible knobs, used by make_genie_driver. The flux
81 // scanner is the only max-path-lengths strategy: a box scanner never
82 // samples beam-like axial paths and underestimates the maxima.
83 void SetScannerFlux(genie::GFluxI* flux) { scanner_flux_ = flux; }
84 void SetScannerNParticles(int n) { scanner_particles_ = n; }
85 void SetMaxPlSafetyFactor(double sf) { safety_factor_ = sf; }
86 genie::PathLengthList const& GetMaxPathLengths() const {
87 return max_path_lengths_;
88 }
89
90 // Bounding box of the scan volume in the master (flux) frame, SI meters —
91 // for the startup frame check against the first flux ray.
92 struct Extents {
93 TVector3 lo, hi;
94 };
95 Extents const& extents() const { return extents_; }
96
97 // GeomAnalyzerI
98 genie::PDGCodeList const& ListOfTargetNuclei() override { return targets_; }
99 genie::PathLengthList const& ComputeMaxPathLengths() override;
100 genie::PathLengthList const& ComputePathLengths(
101 TLorentzVector const& x, TLorentzVector const& p) override;
102 TVector3 const& GenerateVertex(TLorentzVector const& x,
103 TLorentzVector const& p, int tgtpdg) override;
104
105 private:
106 struct Impl; // all Geant4 state (used only on the geometry thread)
107 std::unique_ptr<Impl> impl_;
108
109 // Both run on the geometry thread.
110 void init(std::unique_ptr<ship::IGeometryService> geometry,
111 std::string const& top_volume);
112 static void teardown_geant4(Impl& impl);
113
114 genie::GFluxI* scanner_flux_ = nullptr;
115 int scanner_particles_ = 10000;
116 double safety_factor_ = 1.1; // as ROOTGeomAnalyzer's default
117
118 genie::PDGCodeList targets_;
119 genie::PathLengthList path_lengths_;
120 genie::PathLengthList max_path_lengths_;
121 TVector3 vertex_;
122 Extents extents_;
123};
124
125} // namespace aegir
Definition ship_geom_analyzer.hpp:51
ShipGeomAnalyzer(ShipGeomAnalyzer const &)=delete
genie::PDGCodeList const & ListOfTargetNuclei() override
Definition ship_geom_analyzer.hpp:98
void SetMaxPlSafetyFactor(double sf)
Definition ship_geom_analyzer.hpp:85
~ShipGeomAnalyzer() override
Definition ship_geom_analyzer.cpp:301
void SetScannerFlux(genie::GFluxI *flux)
Definition ship_geom_analyzer.hpp:83
Extents const & extents() const
Definition ship_geom_analyzer.hpp:95
void SetScannerNParticles(int n)
Definition ship_geom_analyzer.hpp:84
G4Teardown
Definition ship_geom_analyzer.hpp:53
genie::PathLengthList const & ComputeMaxPathLengths() override
Definition ship_geom_analyzer.cpp:331
TVector3 const & GenerateVertex(TLorentzVector const &x, TLorentzVector const &p, int tgtpdg) override
Definition ship_geom_analyzer.cpp:360
ShipGeomAnalyzer & operator=(ShipGeomAnalyzer const &)=delete
ShipGeomAnalyzer & operator=(ShipGeomAnalyzer &&)=delete
genie::PathLengthList const & ComputePathLengths(TLorentzVector const &x, TLorentzVector const &p) override
Definition ship_geom_analyzer.cpp:305
genie::PathLengthList const & GetMaxPathLengths() const
Definition ship_geom_analyzer.hpp:86
ShipGeomAnalyzer(ShipGeomAnalyzer &&)=delete
Definition genie_config.hpp:22
Definition genie_driver_setup.hpp:26
Definition ship_geom_analyzer.hpp:45
Definition ship_geom_analyzer.hpp:92
TVector3 hi
Definition ship_geom_analyzer.hpp:93
TVector3 lo
Definition ship_geom_analyzer.hpp:93