Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-19 09:18:10

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 #ifndef DDG4_GEANT4ISOTROPEGENERATOR_H
0015 #define DDG4_GEANT4ISOTROPEGENERATOR_H
0016 
0017 // Framework include files
0018 #include <DDG4/Geant4ParticleGenerator.h>
0019 
0020 // C/C++ include files
0021 #include <array>
0022 #include <cstdint>
0023 #include <functional>
0024 #include <mutex>
0025 
0026 /// Namespace for the AIDA detector description toolkit
0027 namespace dd4hep {
0028 
0029   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
0030   namespace sim {
0031 
0032     // Forward declarations
0033     class Geant4Random;
0034 
0035     /// Generate particles isotrop in space around origine (0,0,0)
0036     /**
0037      *  Supports both standard PRNG-based sampling and Randomized Quasi-Monte Carlo
0038      *  sampling via scrambled Halton sequences (Cranley-Patterson rotation).
0039      *
0040      *  When Halton mode is enabled (property "Halton" = true), the three sampling
0041      *  dimensions use low-discrepancy Halton sequences in bases 2 (phi), 3 (theta),
0042      *  and 5 (momentum), each additively scrambled by a per-dimension shift derived
0043      *  from the Geant4Random seed.  This provides superior phase-space coverage
0044      *  relative to a PRNG while remaining reproducible and independent across jobs
0045      *  (using different seeds or "HaltonOffset" values).
0046      *
0047      *  Note: the "ffbar" distribution is incompatible with Halton mode because its
0048      *  acceptance-rejection loop cannot be driven by a fixed per-particle Halton point.
0049      *
0050      *  \author  M.Frank
0051      *  \version 1.0
0052      *  \ingroup DD4HEP_SIMULATION
0053      */
0054     class Geant4IsotropeGenerator: public Geant4ParticleGenerator {
0055     protected:
0056       /// Property: Distribution name. Default: "uniform". Allowed: "uniform", "cos(theta)", "ffbar", "eta"
0057       std::string m_distribution;
0058       /// Property: Minimal phi angular value
0059       double      m_phiMin;
0060       /// Property: Maximal phi angular value
0061       double      m_phiMax;
0062       /// Property: Minimal theta angular value
0063       double      m_thetaMin;
0064       /// Property: Maximal theta angular value
0065       double      m_thetaMax;
0066       /// Property: Enable scrambled Halton sequence sampling (RQMC mode)
0067       bool        m_halton;
0068       /// Property: Starting index in the Halton sequence (use for parallel-job partitioning)
0069       uint64_t    m_haltonOffset;
0070       /// Current Halton sequence index (incremented per generated particle)
0071       mutable uint64_t m_haltonIndex;
0072       /// Per-dimension additive scramble shifts in [0,1), sampled from Geant4Random on first use
0073       mutable std::array<double,3> m_haltonShift;
0074       /// Ensures initHalton() runs exactly once across all events
0075       mutable std::once_flag m_haltonOnce;
0076 
0077       /// Initialize Cranley-Patterson shifts using @a rnd; set m_haltonIndex = m_haltonOffset
0078       void initHalton(Geant4Random& rnd) const;
0079       /// Compute the radical inverse of @a index in the given @a base (standard Halton value)
0080       static double haltonValue(uint64_t index, int base);
0081       /// Return the scrambled Halton sample for dimension @a dim (0=phi,1=theta,2=momentum)
0082       double haltonScrambled(uint64_t index, unsigned int dim) const;
0083       /// Build and return a per-particle sampler: either PRNG or Halton, depending on m_halton.
0084       /// For Halton mode, advances m_haltonIndex by one.
0085       std::function<double(unsigned int)> makeSampler(Geant4Random& rnd) const;
0086       /// Sample momentum from [m_momentumMin, m_momentumMax] using a pre-computed [0,1) value @a h
0087       void sampleMomentum(double h, double& momentum) const;
0088 
0089       /// Particle modification. Caller presets defaults to: ( direction = m_direction,  momentum = [m_momentumMin, m_momentumMax])
0090       /** Use this function to implement isotrop guns, multiple guns etc. 
0091           User must return a UNIT vector, which gets scaled with momentum.
0092       */
0093       virtual void getParticleDirection(int num, ROOT::Math::XYZVector& direction, double& momentum) const  override;
0094       /// e+e- --> ffbar particle distribution ~ 1 + cos^2(theta) (PRNG only; incompatible with Halton)
0095       void getParticleDirectionFFbar(int num, ROOT::Math::XYZVector& direction, double& momentum) const;
0096       /// Flat pseudorapidity (eta) distribution
0097       void getParticleDirectionEta(int num, const std::function<double(unsigned int)>& sample, ROOT::Math::XYZVector& direction, double& momentum) const;
0098       /// Particle distribution ~ cos(theta)
0099       void getParticleDirectionCosTheta(int num, const std::function<double(unsigned int)>& sample, ROOT::Math::XYZVector& direction, double& momentum) const;
0100       /// Uniform particle distribution
0101       void getParticleDirectionUniform(int num, const std::function<double(unsigned int)>& sample, ROOT::Math::XYZVector& direction, double& momentum) const;
0102 
0103     public:
0104       /// Inhibit default constructor
0105       Geant4IsotropeGenerator() = delete;
0106       /// Inhibit copy constructor
0107       Geant4IsotropeGenerator(const Geant4IsotropeGenerator& copy) = delete;
0108       /// Standard constructor
0109       Geant4IsotropeGenerator(Geant4Context* context, const std::string& name);
0110       /// Default destructor
0111       virtual ~Geant4IsotropeGenerator();
0112     };
0113   }    // End namespace sim
0114 }      // End namespace dd4hep
0115 #endif // DDG4_GEANT4ISOTROPEGENERATOR_H