File indexing completed on 2025-01-18 09:14:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/InstanceCount.h>
0017 #include <DDG4/Geant4Random.h>
0018
0019 #include <CLHEP/Random/EngineFactory.h>
0020 #include <CLHEP/Random/RandGamma.h>
0021 #include <CLHEP/Random/Random.h>
0022
0023
0024 #include <TRandom1.h>
0025
0026
0027 #include <cmath>
0028
0029 using namespace dd4hep::sim;
0030
0031 namespace CLHEP {
0032 unsigned long crc32ul(const std::string& s);
0033 }
0034
0035 namespace {
0036
0037
0038 class RNDM : public TRandom {
0039
0040 Geant4Random* m_generator;
0041
0042 CLHEP::HepRandomEngine* m_engine;
0043
0044 public:
0045
0046 RNDM(Geant4Random* r) : TRandom(), m_generator(r) {
0047 m_engine = m_generator->engine();
0048 }
0049
0050 virtual ~RNDM() { }
0051
0052 virtual void SetSeed(UInt_t seed=0) final {
0053 fSeed = seed;
0054 m_generator->setSeed((long)seed);
0055 }
0056
0057 virtual void SetSeed(ULong_t seed=0) final {
0058 fSeed = seed;
0059 m_generator->setSeed((long)seed);
0060 }
0061
0062 virtual Double_t Rndm() final {
0063 return m_engine->flat();
0064 }
0065
0066 virtual Double_t Rndm(Int_t) final {
0067 return m_engine->flat();
0068 }
0069
0070 virtual void RndmArray(Int_t size, Float_t *array) final {
0071 for (Int_t i=0;i<size;i++) array[i] = m_engine->flat();
0072 }
0073
0074 virtual void RndmArray(Int_t size, Double_t *array) final {
0075 m_engine->flatArray(size,array);
0076 }
0077 };
0078 static Geant4Random* s_instance = 0;
0079 }
0080
0081
0082 Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam)
0083 : Geant4Action(ctxt,nam), m_engine(0), m_rootRandom(0), m_rootOLD(0),
0084 m_inited(false)
0085 {
0086 declareProperty("File", m_file="");
0087 declareProperty("Type", m_engineType="");
0088 declareProperty("Seed", m_seed = 123456789);
0089 declareProperty("Luxury", m_luxury = 1);
0090 declareProperty("Replace_gRandom", m_replace = true);
0091
0092 m_engine = CLHEP::HepRandom::getTheEngine();
0093 InstanceCount::increment(this);
0094 }
0095
0096
0097 Geant4Random::~Geant4Random() {
0098
0099
0100
0101
0102
0103
0104 if ( m_rootRandom == gRandom ) gRandom = m_rootOLD;
0105
0106 if ( s_instance == this ) s_instance = 0;
0107
0108 detail::deletePtr(m_rootRandom);
0109 InstanceCount::decrement(this);
0110 }
0111
0112
0113 Geant4Random* Geant4Random::instance(bool throw_exception) {
0114 if ( !s_instance && throw_exception ) {
0115 dd4hep::except("Geant4Random", "No global random number generator defined!");
0116 }
0117 return s_instance;
0118 }
0119
0120
0121 Geant4Random* Geant4Random::setMainInstance(Geant4Random* ptr) {
0122 if ( ptr && !ptr->m_inited ) {
0123 ptr->initialize();
0124 }
0125 if ( s_instance != ptr ) {
0126 if ( !ptr ) {
0127 dd4hep::except("Geant4Random","Attempt to declare invalid Geant4Random instance.");
0128 }
0129 if ( !ptr->m_inited ) {
0130 dd4hep::except("Geant4Random","Attempt to declare uninitialized Geant4Random instance.");
0131 }
0132 Geant4Random* old = s_instance;
0133 CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
0134 if ( ptr->m_engine != curr ) {
0135 ptr->printP2("Moving CLHEP random instance from %p to %p",curr,ptr->m_engine);
0136 CLHEP::HepRandom::setTheEngine(ptr->m_engine);
0137 }
0138 if ( ptr->m_replace ) {
0139 ptr->m_rootOLD = gRandom;
0140 gRandom = ptr->m_rootRandom;
0141 }
0142 s_instance = ptr;
0143 return old;
0144 }
0145 return 0;
0146 }
0147
0148 #include <CLHEP/Random/DualRand.h>
0149 #include <CLHEP/Random/JamesRandom.h>
0150 #include <CLHEP/Random/MTwistEngine.h>
0151 #include <CLHEP/Random/RanecuEngine.h>
0152 #include <CLHEP/Random/Ranlux64Engine.h>
0153 #include <CLHEP/Random/RanluxEngine.h>
0154 #include <CLHEP/Random/RanshiEngine.h>
0155 #include <CLHEP/Random/NonRandomEngine.h>
0156
0157
0158 void Geant4Random::initialize() {
0159 if ( !m_file.empty() ) {
0160 std::ifstream in(m_file.c_str(), std::ios::in);
0161 m_engine = CLHEP::EngineFactory::newEngine(in);
0162 if ( !m_engine ) {
0163 except("Failed to create CLHEP random engine from file:%s.",m_file.c_str());
0164 }
0165 m_seed = m_engine->getSeed();
0166 }
0167 else if ( !m_engineType.empty() ) {
0168
0169 if ( m_engineType == CLHEP::HepJamesRandom::engineName() )
0170 m_engine = new CLHEP::HepJamesRandom();
0171 else if ( m_engineType == CLHEP::RanecuEngine::engineName() )
0172 m_engine = new CLHEP::RanecuEngine();
0173 else if ( m_engineType == CLHEP::Ranlux64Engine::engineName() )
0174 m_engine = new CLHEP::Ranlux64Engine();
0175 else if ( m_engineType == CLHEP::MTwistEngine::engineName() )
0176 m_engine = new CLHEP::MTwistEngine();
0177 else if ( m_engineType == CLHEP::DualRand::engineName() )
0178 m_engine = new CLHEP::DualRand();
0179 else if ( m_engineType == CLHEP::RanluxEngine::engineName() )
0180 m_engine = new CLHEP::RanluxEngine();
0181 else if ( m_engineType == CLHEP::RanshiEngine::engineName() )
0182 m_engine = new CLHEP::RanshiEngine();
0183 else if ( m_engineType == CLHEP::NonRandomEngine::engineName() )
0184 m_engine = new CLHEP::NonRandomEngine();
0185
0186 if ( !m_engine ) {
0187 except("Failed to create CLHEP random engine of type: %s.",m_engineType.c_str());
0188 }
0189 }
0190 m_engine->setSeed(m_seed,m_luxury);
0191 m_rootRandom = new RNDM(this);
0192 m_inited = true;
0193 if ( 0 == s_instance ) {
0194 setMainInstance(this);
0195 }
0196 }
0197
0198
0199 void Geant4Random::setSeed(long seed) {
0200 if ( !m_inited ) initialize();
0201 m_engine->setSeed(m_seed=seed,0);
0202 }
0203
0204
0205
0206
0207
0208
0209 void Geant4Random::setSeeds(const long* seeds, int size) {
0210 if ( !m_inited ) initialize();
0211 m_seed = seeds[0];
0212 m_engine->setSeeds(seeds, size);
0213 }
0214
0215
0216 void Geant4Random::saveStatus( const char filename[] ) const {
0217 if ( !m_inited ) {
0218 except("Failed to save RandomGenerator status. [Not-inited]");
0219 }
0220 m_engine->saveStatus(filename);
0221 }
0222
0223
0224 void Geant4Random::restoreStatus( const char filename[] ) {
0225 if ( !m_inited ) initialize();
0226 m_engine->restoreStatus(filename);
0227 }
0228
0229
0230 void Geant4Random::showStatus() const {
0231 if ( !m_inited ) {
0232 error("Failed to show RandomGenerator status. [Not-inited]");
0233 return;
0234 }
0235 printP2("Random engine status of object of type Geant4Random @ 0x%p",this);
0236 if ( !m_file.empty() )
0237 printP2(" Created from file: %s",m_file.c_str());
0238 else if ( !m_engineType.empty() )
0239 printP2(" Special instance created of type:%s @ 0x%p",
0240 m_engineType.c_str(),m_engine);
0241 else
0242 printP2(" Reused HepRandom engine instance %s @ 0x%p",
0243 m_engine ? m_engine->name().c_str() : "???", m_engine);
0244
0245 if ( m_engine == CLHEP::HepRandom::getTheEngine() )
0246 printP2(" Instance is identical to Geant4's HepRandom instance.");
0247
0248 printP2(" Instance is %sidentical to ROOT's gRandom instance.",
0249 gRandom == m_rootRandom ? "" : "NOT ");
0250
0251 if ( gRandom != m_rootRandom ) {
0252 printP2(" Local TRandom: 0x%p gRandom: 0x%p",m_rootRandom,gRandom);
0253 }
0254 if ( 0 == m_engine ) {
0255 error(" Geant4Random instance has not engine attached!");
0256 return;
0257 }
0258 m_engine->showStatus();
0259 }
0260
0261
0262 double Geant4Random::rndm_clhep() {
0263 if ( !m_inited ) initialize();
0264 return m_engine->flat();
0265 }
0266
0267
0268 double Geant4Random::rndm(int i) {
0269 if ( !m_inited ) initialize();
0270 return gRandom->Rndm(i);
0271 }
0272
0273
0274 void Geant4Random::rndmArray(int n, float *array) {
0275 if ( !m_inited ) initialize();
0276 gRandom->RndmArray(n,array);
0277 }
0278
0279
0280 void Geant4Random::rndmArray(int n, double *array) {
0281 if ( !m_inited ) initialize();
0282 gRandom->RndmArray(n,array);
0283 }
0284
0285
0286 double Geant4Random::uniform(double x1) {
0287 if ( !m_inited ) initialize();
0288 return gRandom->Uniform(x1);
0289 }
0290
0291
0292 double Geant4Random::uniform(double x1, double x2) {
0293 if ( !m_inited ) initialize();
0294 return gRandom->Uniform(x1,x2);
0295 }
0296
0297
0298 double Geant4Random::exp(double tau) {
0299 if ( !m_inited ) initialize();
0300 return gRandom->Exp(tau);
0301 }
0302
0303
0304 double Geant4Random::gauss(double mean, double sigma) {
0305 if ( !m_inited ) initialize();
0306 return gRandom->Gaus(mean,sigma);
0307 }
0308
0309
0310 double Geant4Random::landau(double mean, double sigma) {
0311 if ( !m_inited ) initialize();
0312 return gRandom->Landau(mean,sigma);
0313 }
0314
0315
0316 void Geant4Random::circle(double &x, double &y, double r) {
0317 if ( !m_inited ) initialize();
0318 gRandom->Circle(x,y,r);
0319 }
0320
0321
0322 void Geant4Random::sphere(double &x, double &y, double &z, double r) {
0323 if ( !m_inited ) initialize();
0324 gRandom->Sphere(x,y,z,r);
0325 }
0326
0327
0328 double Geant4Random::poisson(double mean) {
0329 if ( !m_inited ) initialize();
0330 return gRandom->PoissonD(mean);
0331 }
0332
0333
0334 double Geant4Random::breit_wigner(double mean, double gamma) {
0335 if ( !m_inited ) initialize();
0336 return gRandom->BreitWigner(mean, gamma);
0337 }
0338
0339
0340 double Geant4Random::gamma(double k, double lambda) {
0341 if ( !m_inited ) initialize();
0342 return CLHEP::RandGamma::shoot(this->m_engine, k, lambda);
0343 }