DD4hep  1.37.0
Detector Description Toolkit for High Energy Physics
Geant4Random.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Printout.h>
16 #include <DD4hep/InstanceCount.h>
17 #include <DDG4/Geant4Random.h>
18 
19 #include <CLHEP/Random/EngineFactory.h>
20 #include <CLHEP/Random/RandGamma.h>
21 #include <CLHEP/Random/Random.h>
22 
23 // ROOT include files
24 #include <TRandom1.h>
25 
26 // C/C++ include files
27 #include <cmath>
28 
29 using namespace dd4hep::sim;
30 
31 namespace CLHEP {
32  unsigned long crc32ul(const std::string& s);
33 }
34 
35 namespace {
36 
38  class RNDM : public TRandom {
40  Geant4Random* m_generator;
42  CLHEP::HepRandomEngine* m_engine;
43 
44  public:
46  RNDM(Geant4Random* r) : TRandom(), m_generator(r) {
47  m_engine = m_generator->engine();
48  }
50  virtual ~RNDM() { }
52  virtual void SetSeed(UInt_t seed=0) final {
53  fSeed = seed;
54  m_generator->setSeed((long)seed);
55  }
57  virtual void SetSeed(ULong_t seed=0) final {
58  fSeed = seed;
59  m_generator->setSeed((long)seed);
60  }
62  virtual Double_t Rndm() final {
63  return m_engine->flat();
64  }
66  virtual Double_t Rndm(Int_t) final {
67  return m_engine->flat();
68  }
70  virtual void RndmArray(Int_t size, Float_t *array) final {
71  for (Int_t i=0;i<size;i++) array[i] = m_engine->flat();
72  }
74  virtual void RndmArray(Int_t size, Double_t *array) final {
75  m_engine->flatArray(size,array);
76  }
77  };
78  // Thread-local so each worker thread has its own Geant4Random instance.
79  static thread_local Geant4Random* s_instance = nullptr;
80 }
81 
83 Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam)
84  : Geant4Action(ctxt,nam), m_engine(0), m_rootRandom(0), m_rootOLD(0),
85  m_inited(false)
86 {
87  declareProperty("File", m_file="");
88  declareProperty("Type", m_engineType="");
89  declareProperty("Seed", m_seed = 123456789);
90  declareProperty("Luxury", m_luxury = 1);
91  declareProperty("Replace_gRandom", m_replace = true);
92  // Default: static Geant4 random engine.
93  m_engine = CLHEP::HepRandom::getTheEngine();
95 }
96 
99  // Only delete the engine if it is NOT the CLEP default one
100  // BUT: Just cannot delete the engine. Causes havoc with static destructors!
101  //CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
102  //if ( !m_engineType.empty() && m_engine != curr ) deletePtr(m_engine);
103 
104  // Set gRandom to the old value
105  if ( m_rootRandom == gRandom ) gRandom = m_rootOLD;
106  // Reset instance pointer
107  if ( s_instance == this ) s_instance = 0;
108  // Finally delete the TRandom instance wrapper
109  detail::deletePtr(m_rootRandom);
111 }
112 
114 Geant4Random* Geant4Random::instance(bool throw_exception) {
115  if ( !s_instance && throw_exception ) {
116  dd4hep::except("Geant4Random", "No global random number generator defined!");
117  }
118  return s_instance;
119 }
120 
123  if ( ptr && !ptr->m_inited ) {
124  ptr->initialize();
125  }
126  if ( s_instance != ptr ) {
127  if ( !ptr ) {
128  dd4hep::except("Geant4Random","Attempt to declare invalid Geant4Random instance.");
129  }
130  if ( !ptr->m_inited ) {
131  dd4hep::except("Geant4Random","Attempt to declare uninitialized Geant4Random instance.");
132  }
133  Geant4Random* old = s_instance;
134  CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
135  if ( ptr->m_engine != curr ) {
136  ptr->printP2("Moving CLHEP random instance from %p to %p",curr,ptr->m_engine);
137  CLHEP::HepRandom::setTheEngine(ptr->m_engine);
138  }
139  if ( ptr->m_replace ) {
140  ptr->m_rootOLD = gRandom;
141  gRandom = ptr->m_rootRandom;
142  }
143  s_instance = ptr;
144  return old;
145  }
146  return 0;
147 }
148 
149 #include <CLHEP/Random/DualRand.h>
150 #include <CLHEP/Random/JamesRandom.h>
151 #include <CLHEP/Random/MTwistEngine.h>
152 #include <CLHEP/Random/RanecuEngine.h>
153 #include <CLHEP/Random/Ranlux64Engine.h>
154 #include <CLHEP/Random/RanluxEngine.h>
155 #include <CLHEP/Random/RanshiEngine.h>
156 #include <CLHEP/Random/NonRandomEngine.h>
157 
160  if ( !m_file.empty() ) {
161  std::ifstream in(m_file.c_str(), std::ios::in);
162  m_engine = CLHEP::EngineFactory::newEngine(in);
163  if ( !m_engine ) {
164  except("Failed to create CLHEP random engine from file:%s.",m_file.c_str());
165  }
166  m_seed = m_engine->getSeed();
167  }
168  else if ( !m_engineType.empty() ) {
170  if ( m_engineType == CLHEP::HepJamesRandom::engineName() )
171  m_engine = new CLHEP::HepJamesRandom();
172  else if ( m_engineType == CLHEP::RanecuEngine::engineName() )
173  m_engine = new CLHEP::RanecuEngine();
174  else if ( m_engineType == CLHEP::Ranlux64Engine::engineName() )
175  m_engine = new CLHEP::Ranlux64Engine();
176  else if ( m_engineType == CLHEP::MTwistEngine::engineName() )
177  m_engine = new CLHEP::MTwistEngine();
178  else if ( m_engineType == CLHEP::DualRand::engineName() )
179  m_engine = new CLHEP::DualRand();
180  else if ( m_engineType == CLHEP::RanluxEngine::engineName() )
181  m_engine = new CLHEP::RanluxEngine();
182  else if ( m_engineType == CLHEP::RanshiEngine::engineName() )
183  m_engine = new CLHEP::RanshiEngine();
184  else if ( m_engineType == CLHEP::NonRandomEngine::engineName() )
185  m_engine = new CLHEP::NonRandomEngine();
186 
187  if ( !m_engine ) {
188  except("Failed to create CLHEP random engine of type: %s.",m_engineType.c_str());
189  }
190  }
191  m_engine->setSeed(m_seed,m_luxury);
192  m_rootRandom = new RNDM(this);
193  m_inited = true;
194  if ( 0 == s_instance ) {
195  setMainInstance(this);
196  }
197 }
198 
200 void Geant4Random::setSeed(long seed) {
201  if ( !m_inited ) initialize();
202  m_engine->setSeed(m_seed=seed,0);
203 }
204 
206 
210 void Geant4Random::setSeeds(const long* seeds, int size) {
211  if ( !m_inited ) initialize();
212  m_seed = seeds[0];
213  m_engine->setSeeds(seeds, size);
214 }
215 
217 void Geant4Random::saveStatus( const char filename[] ) const {
218  if ( !m_inited ) {
219  except("Failed to save RandomGenerator status. [Not-inited]");
220  }
221  m_engine->saveStatus(filename);
222 }
223 
225 void Geant4Random::restoreStatus( const char filename[] ) {
226  if ( !m_inited ) initialize();
227  m_engine->restoreStatus(filename);
228 }
229 
232  if ( !m_inited ) {
233  error("Failed to show RandomGenerator status. [Not-inited]");
234  return;
235  }
236  printP2("Random engine status of object of type Geant4Random @ 0x%p",this);
237  if ( !m_file.empty() )
238  printP2(" Created from file: %s",m_file.c_str());
239  else if ( !m_engineType.empty() )
240  printP2(" Special instance created of type:%s @ 0x%p",
241  m_engineType.c_str(),m_engine);
242  else
243  printP2(" Reused HepRandom engine instance %s @ 0x%p",
244  m_engine ? m_engine->name().c_str() : "???", m_engine);
245 
246  if ( m_engine == CLHEP::HepRandom::getTheEngine() )
247  printP2(" Instance is identical to Geant4's HepRandom instance.");
248 
249  printP2(" Instance is %sidentical to ROOT's gRandom instance.",
250  gRandom == m_rootRandom ? "" : "NOT ");
251 
252  if ( gRandom != m_rootRandom ) {
253  printP2(" Local TRandom: 0x%p gRandom: 0x%p",m_rootRandom,gRandom);
254  }
255  if ( 0 == m_engine ) {
256  error(" Geant4Random instance has not engine attached!");
257  return;
258  }
259  m_engine->showStatus();
260 }
261 
264  if ( !m_inited ) initialize();
265  return m_engine->flat();
266 }
267 
269 double Geant4Random::rndm(int i) {
270  if ( !m_inited ) initialize();
271  return m_rootRandom->Rndm(i);
272 }
273 
275 void Geant4Random::rndmArray(int n, float *array) {
276  if ( !m_inited ) initialize();
277  m_rootRandom->RndmArray(n,array);
278 }
279 
281 void Geant4Random::rndmArray(int n, double *array) {
282  if ( !m_inited ) initialize();
283  m_rootRandom->RndmArray(n,array);
284 }
285 
287 double Geant4Random::uniform(double x1) {
288  if ( !m_inited ) initialize();
289  return m_rootRandom->Uniform(x1);
290 }
291 
293 double Geant4Random::uniform(double x1, double x2) {
294  if ( !m_inited ) initialize();
295  return m_rootRandom->Uniform(x1,x2);
296 }
297 
299 double Geant4Random::exp(double tau) {
300  if ( !m_inited ) initialize();
301  return m_rootRandom->Exp(tau);
302 }
303 
305 double Geant4Random::gauss(double mean, double sigma) {
306  if ( !m_inited ) initialize();
307  return m_rootRandom->Gaus(mean,sigma);
308 }
309 
311 double Geant4Random::landau(double mean, double sigma) {
312  if ( !m_inited ) initialize();
313  return m_rootRandom->Landau(mean,sigma);
314 }
315 
317 void Geant4Random::circle(double &x, double &y, double r) {
318  if ( !m_inited ) initialize();
319  m_rootRandom->Circle(x,y,r);
320 }
321 
323 void Geant4Random::sphere(double &x, double &y, double &z, double r) {
324  if ( !m_inited ) initialize();
325  m_rootRandom->Sphere(x,y,z,r);
326 }
327 
329 double Geant4Random::poisson(double mean) {
330  if ( !m_inited ) initialize();
331  return m_rootRandom->PoissonD(mean);
332 }
333 
335 double Geant4Random::breit_wigner(double mean, double gamma) {
336  if ( !m_inited ) initialize();
337  return m_rootRandom->BreitWigner(mean, gamma);
338 }
339 
341 double Geant4Random::gamma(double k, double lambda) {
342  if ( !m_inited ) initialize();
343  return CLHEP::RandGamma::shoot(this->m_engine, k, lambda);
344 }
dd4hep::sim::Geant4Random::poisson
double poisson(double mean=1e0)
Create poisson distributed random numbers.
Definition: Geant4Random.cpp:329
dd4hep::sim::Geant4Action::printP2
void printP2(const char *fmt,...) const
Support for messages with variable output level using output level+2.
Definition: Geant4Action.cpp:188
dd4hep::sim::Geant4Random::m_replace
bool m_replace
Property: Indicator to replace the ROOT gRandom instance.
Definition: Geant4Random.h:70
dd4hep::sim::Geant4Random::rndm
double rndm(int i=0)
Create flat distributed random numbers in the interval ]0,1].
Definition: Geant4Random.cpp:269
dd4hep::sim::Geant4Random::instance
static Geant4Random * instance(bool throw_exception=true)
Access the main Geant4 random generator instance. Must be created before used!
Definition: Geant4Random.cpp:114
dd4hep::sim::Geant4Random::sphere
void sphere(double &x, double &y, double &z, double r)
Create tuple of randum number on a sphere with radius r.
Definition: Geant4Random.cpp:323
dd4hep::sim::Geant4Random::engine
CLHEP::HepRandomEngine * engine()
CLHEP random number engine (valid after initialization only)
Definition: Geant4Random.h:116
dd4hep::sim::Geant4Random::uniform
double uniform(double x1=1)
Create uniformly disributed random numbers in the interval ]0,x1].
Definition: Geant4Random.cpp:287
dd4hep::sim::Geant4Random::m_file
std::string m_file
Property: File name if initialized from file. If set, engine name and seeds are ignored.
Definition: Geant4Random.h:64
dd4hep::InstanceCount::increment
static void increment(T *)
Increment count according to type information.
Definition: InstanceCount.h:98
dd4hep::sim::Geant4Random::rndm_clhep
double rndm_clhep()
Create flat distributed random numbers in the interval ]0,1] calling CLHEP.
Definition: Geant4Random.cpp:263
dd4hep::sim::Geant4Random::setSeed
virtual void setSeed(long seed)
Should initialise the status of the algorithm according to seed.
Definition: Geant4Random.cpp:200
dd4hep::sim::Geant4Action::except
void except(const char *fmt,...) const
Support of exceptions: Print fatal message and throw runtime_error.
Definition: Geant4Action.cpp:256
Geant4Random.h
dd4hep::sim::Geant4Random::m_luxury
long m_luxury
Definition: Geant4Random.h:68
dd4hep::sim::Geant4Action::error
void error(const char *fmt,...) const
Support of error messages.
Definition: Geant4Action.cpp:231
dd4hep::sim::Geant4Random::gamma
double gamma(double k, double lambda)
Create gamma distributed random numbers.
Definition: Geant4Random.cpp:341
dd4hep::sim::Geant4Random::showStatus
virtual void showStatus() const
Should dump the current engine status on the screen.
Definition: Geant4Random.cpp:231
dd4hep::sim::Geant4Random::~Geant4Random
virtual ~Geant4Random()
Default destructor.
Definition: Geant4Random.cpp:98
dd4hep::sim::Geant4Random::breit_wigner
double breit_wigner(double mean=0e0, double gamma=1e0)
Create breit wigner distributed random numbers.
Definition: Geant4Random.cpp:335
CLHEP
CLHEP namespace.
Definition: Geant4Random.h:26
dd4hep::sim::Geant4Random::setMainInstance
static Geant4Random * setMainInstance(Geant4Random *ptr)
Make this random generator instance the one used by Geant4.
Definition: Geant4Random.cpp:122
CLHEP::crc32ul
unsigned long crc32ul(const std::string &s)
dd4hep::sim::Geant4Action::declareProperty
Geant4Action & declareProperty(const std::string &nam, T &val)
Declare property.
Definition: Geant4Action.h:366
dd4hep::InstanceCount::decrement
static void decrement(T *)
Decrement count according to type information.
Definition: InstanceCount.h:102
dd4hep::sim::Geant4Random::Geant4Random
Geant4Random(Geant4Context *context, const std::string &name)
Standard constructor.
Definition: Geant4Random.cpp:83
dd4hep::sim::Geant4Random
Mini interface to THE random generator of the application.
Definition: Geant4Random.h:59
dd4hep::sim::Geant4Action
Default base class for all Geant 4 actions and derivates thereof.
Definition: Geant4Action.h:113
dd4hep::sim::Geant4Random::rndmArray
void rndmArray(int n, float *array)
Create a float array of flat distributed random numbers in the interval ]0,1].
Definition: Geant4Random.cpp:275
dd4hep::sim::Geant4Random::saveStatus
virtual void saveStatus(const char filename[]="Config.conf") const
Should save on a file specific to the instantiated engine in use the current status.
Definition: Geant4Random.cpp:217
dd4hep::sim::Geant4Random::circle
void circle(double &x, double &y, double r)
Create tuple of randum number around a circle with radius r.
Definition: Geant4Random.cpp:317
dd4hep::sim::Geant4Random::gauss
double gauss(double mean=0, double sigma=1)
Create gaussian distributed random numbers.
Definition: Geant4Random.cpp:305
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: EDM4hepFileReader.cpp:46
dd4hep::sim::Geant4Random::m_rootRandom
TRandom * m_rootRandom
Reference to ROOT random instance.
Definition: Geant4Random.h:76
dd4hep::sim::Geant4Random::m_engine
CLHEP::HepRandomEngine * m_engine
Reference to the CLHEP random number engine (valid only after initialization)
Definition: Geant4Random.h:73
dd4hep::sim::Geant4Random::setSeeds
virtual void setSeeds(const long *seeds, int size)
Should initialise the status of the algorithm.
Definition: Geant4Random.cpp:210
dd4hep::sim::Geant4Random::m_rootOLD
TRandom * m_rootOLD
Definition: Geant4Random.h:76
dd4hep::sim::Geant4Random::m_engineType
std::string m_engineType
Property: Engine type. default: "HepJamesRandom".
Definition: Geant4Random.h:66
dd4hep::sim::Geant4Random::restoreStatus
virtual void restoreStatus(const char filename[]="Config.conf")
Should read from a file and restore the last saved engine configuration.
Definition: Geant4Random.cpp:225
dd4hep::sim::Geant4Random::m_seed
long m_seed
Property: Initial random seed. Default: 123456789.
Definition: Geant4Random.h:68
InstanceCount.h
dd4hep::sim::Geant4Random::m_inited
bool m_inited
Flag to remember initialization.
Definition: Geant4Random.h:78
dd4hep::sim::Geant4Random::exp
double exp(double tau)
Create exponentially distributed random numbers.
Definition: Geant4Random.cpp:299
dd4hep::sim::Geant4Random::initialize
void initialize()
Initialize the instance.
Definition: Geant4Random.cpp:159
Printout.h
dd4hep::sim::Geant4Random::landau
double landau(double mean=0, double sigma=1)
Create landau distributed random numbers.
Definition: Geant4Random.cpp:311
dd4hep::sim::Geant4Context
Generic context to extend user, run and event information.
Definition: Geant4Context.h:201