DD4hep  1.30.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  static Geant4Random* s_instance = 0;
79 }
80 
82 Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam)
83  : Geant4Action(ctxt,nam), m_engine(0), m_rootRandom(0), m_rootOLD(0),
84  m_inited(false)
85 {
86  declareProperty("File", m_file="");
87  declareProperty("Type", m_engineType="");
88  declareProperty("Seed", m_seed = 123456789);
89  declareProperty("Luxury", m_luxury = 1);
90  declareProperty("Replace_gRandom", m_replace = true);
91  // Default: static Geant4 random engine.
92  m_engine = CLHEP::HepRandom::getTheEngine();
94 }
95 
98  // Only delete the engine if it is NOT the CLEP default one
99  // BUT: Just cannot delete the engine. Causes havoc with static destructors!
100  //CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
101  //if ( !m_engineType.empty() && m_engine != curr ) deletePtr(m_engine);
102 
103  // Set gRandom to the old value
104  if ( m_rootRandom == gRandom ) gRandom = m_rootOLD;
105  // Reset instance pointer
106  if ( s_instance == this ) s_instance = 0;
107  // Finally delete the TRandom instance wrapper
108  detail::deletePtr(m_rootRandom);
110 }
111 
113 Geant4Random* Geant4Random::instance(bool throw_exception) {
114  if ( !s_instance && throw_exception ) {
115  dd4hep::except("Geant4Random", "No global random number generator defined!");
116  }
117  return s_instance;
118 }
119 
122  if ( ptr && !ptr->m_inited ) {
123  ptr->initialize();
124  }
125  if ( s_instance != ptr ) {
126  if ( !ptr ) {
127  dd4hep::except("Geant4Random","Attempt to declare invalid Geant4Random instance.");
128  }
129  if ( !ptr->m_inited ) {
130  dd4hep::except("Geant4Random","Attempt to declare uninitialized Geant4Random instance.");
131  }
132  Geant4Random* old = s_instance;
133  CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
134  if ( ptr->m_engine != curr ) {
135  ptr->printP2("Moving CLHEP random instance from %p to %p",curr,ptr->m_engine);
136  CLHEP::HepRandom::setTheEngine(ptr->m_engine);
137  }
138  if ( ptr->m_replace ) {
139  ptr->m_rootOLD = gRandom;
140  gRandom = ptr->m_rootRandom;
141  }
142  s_instance = ptr;
143  return old;
144  }
145  return 0;
146 }
147 
148 #include <CLHEP/Random/DualRand.h>
149 #include <CLHEP/Random/JamesRandom.h>
150 #include <CLHEP/Random/MTwistEngine.h>
151 #include <CLHEP/Random/RanecuEngine.h>
152 #include <CLHEP/Random/Ranlux64Engine.h>
153 #include <CLHEP/Random/RanluxEngine.h>
154 #include <CLHEP/Random/RanshiEngine.h>
155 #include <CLHEP/Random/NonRandomEngine.h>
156 
159  if ( !m_file.empty() ) {
160  std::ifstream in(m_file.c_str(), std::ios::in);
161  m_engine = CLHEP::EngineFactory::newEngine(in);
162  if ( !m_engine ) {
163  except("Failed to create CLHEP random engine from file:%s.",m_file.c_str());
164  }
165  m_seed = m_engine->getSeed();
166  }
167  else if ( !m_engineType.empty() ) {
169  if ( m_engineType == CLHEP::HepJamesRandom::engineName() )
170  m_engine = new CLHEP::HepJamesRandom();
171  else if ( m_engineType == CLHEP::RanecuEngine::engineName() )
172  m_engine = new CLHEP::RanecuEngine();
173  else if ( m_engineType == CLHEP::Ranlux64Engine::engineName() )
174  m_engine = new CLHEP::Ranlux64Engine();
175  else if ( m_engineType == CLHEP::MTwistEngine::engineName() )
176  m_engine = new CLHEP::MTwistEngine();
177  else if ( m_engineType == CLHEP::DualRand::engineName() )
178  m_engine = new CLHEP::DualRand();
179  else if ( m_engineType == CLHEP::RanluxEngine::engineName() )
180  m_engine = new CLHEP::RanluxEngine();
181  else if ( m_engineType == CLHEP::RanshiEngine::engineName() )
182  m_engine = new CLHEP::RanshiEngine();
183  else if ( m_engineType == CLHEP::NonRandomEngine::engineName() )
184  m_engine = new CLHEP::NonRandomEngine();
185 
186  if ( !m_engine ) {
187  except("Failed to create CLHEP random engine of type: %s.",m_engineType.c_str());
188  }
189  }
190  m_engine->setSeed(m_seed,m_luxury);
191  m_rootRandom = new RNDM(this);
192  m_inited = true;
193  if ( 0 == s_instance ) {
194  setMainInstance(this);
195  }
196 }
197 
199 void Geant4Random::setSeed(long seed) {
200  if ( !m_inited ) initialize();
201  m_engine->setSeed(m_seed=seed,0);
202 }
203 
205 
209 void Geant4Random::setSeeds(const long* seeds, int size) {
210  if ( !m_inited ) initialize();
211  m_seed = seeds[0];
212  m_engine->setSeeds(seeds, size);
213 }
214 
216 void Geant4Random::saveStatus( const char filename[] ) const {
217  if ( !m_inited ) {
218  except("Failed to save RandomGenerator status. [Not-inited]");
219  }
220  m_engine->saveStatus(filename);
221 }
222 
224 void Geant4Random::restoreStatus( const char filename[] ) {
225  if ( !m_inited ) initialize();
226  m_engine->restoreStatus(filename);
227 }
228 
231  if ( !m_inited ) {
232  error("Failed to show RandomGenerator status. [Not-inited]");
233  return;
234  }
235  printP2("Random engine status of object of type Geant4Random @ 0x%p",this);
236  if ( !m_file.empty() )
237  printP2(" Created from file: %s",m_file.c_str());
238  else if ( !m_engineType.empty() )
239  printP2(" Special instance created of type:%s @ 0x%p",
240  m_engineType.c_str(),m_engine);
241  else
242  printP2(" Reused HepRandom engine instance %s @ 0x%p",
243  m_engine ? m_engine->name().c_str() : "???", m_engine);
244 
245  if ( m_engine == CLHEP::HepRandom::getTheEngine() )
246  printP2(" Instance is identical to Geant4's HepRandom instance.");
247 
248  printP2(" Instance is %sidentical to ROOT's gRandom instance.",
249  gRandom == m_rootRandom ? "" : "NOT ");
250 
251  if ( gRandom != m_rootRandom ) {
252  printP2(" Local TRandom: 0x%p gRandom: 0x%p",m_rootRandom,gRandom);
253  }
254  if ( 0 == m_engine ) {
255  error(" Geant4Random instance has not engine attached!");
256  return;
257  }
258  m_engine->showStatus();
259 }
260 
263  if ( !m_inited ) initialize();
264  return m_engine->flat();
265 }
266 
268 double Geant4Random::rndm(int i) {
269  if ( !m_inited ) initialize();
270  return gRandom->Rndm(i);
271 }
272 
274 void Geant4Random::rndmArray(int n, float *array) {
275  if ( !m_inited ) initialize();
276  gRandom->RndmArray(n,array);
277 }
278 
280 void Geant4Random::rndmArray(int n, double *array) {
281  if ( !m_inited ) initialize();
282  gRandom->RndmArray(n,array);
283 }
284 
286 double Geant4Random::uniform(double x1) {
287  if ( !m_inited ) initialize();
288  return gRandom->Uniform(x1);
289 }
290 
292 double Geant4Random::uniform(double x1, double x2) {
293  if ( !m_inited ) initialize();
294  return gRandom->Uniform(x1,x2);
295 }
296 
298 double Geant4Random::exp(double tau) {
299  if ( !m_inited ) initialize();
300  return gRandom->Exp(tau);
301 }
302 
304 double Geant4Random::gauss(double mean, double sigma) {
305  if ( !m_inited ) initialize();
306  return gRandom->Gaus(mean,sigma);
307 }
308 
310 double Geant4Random::landau(double mean, double sigma) {
311  if ( !m_inited ) initialize();
312  return gRandom->Landau(mean,sigma);
313 }
314 
316 void Geant4Random::circle(double &x, double &y, double r) {
317  if ( !m_inited ) initialize();
318  gRandom->Circle(x,y,r);
319 }
320 
322 void Geant4Random::sphere(double &x, double &y, double &z, double r) {
323  if ( !m_inited ) initialize();
324  gRandom->Sphere(x,y,z,r);
325 }
326 
328 double Geant4Random::poisson(double mean) {
329  if ( !m_inited ) initialize();
330  return gRandom->PoissonD(mean);
331 }
332 
334 double Geant4Random::breit_wigner(double mean, double gamma) {
335  if ( !m_inited ) initialize();
336  return gRandom->BreitWigner(mean, gamma);
337 }
338 
340 double Geant4Random::gamma(double k, double lambda) {
341  if ( !m_inited ) initialize();
342  return CLHEP::RandGamma::shoot(this->m_engine, k, lambda);
343 }
dd4hep::sim::Geant4Random::poisson
double poisson(double mean=1e0)
Create poisson distributed random numbers.
Definition: Geant4Random.cpp:328
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:268
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:113
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:322
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:286
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:262
dd4hep::sim::Geant4Random::setSeed
virtual void setSeed(long seed)
Should initialise the status of the algorithm according to seed.
Definition: Geant4Random.cpp:199
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:340
dd4hep::sim::Geant4Random::showStatus
virtual void showStatus() const
Should dump the current engine status on the screen.
Definition: Geant4Random.cpp:230
dd4hep::sim::Geant4Random::~Geant4Random
virtual ~Geant4Random()
Default destructor.
Definition: Geant4Random.cpp:97
dd4hep::sim::Geant4Random::breit_wigner
double breit_wigner(double mean=0e0, double gamma=1e0)
Create breit wigner distributed random numbers.
Definition: Geant4Random.cpp:334
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:121
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:82
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:274
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:216
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:316
dd4hep::sim::Geant4Random::gauss
double gauss(double mean=0, double sigma=1)
Create gaussian distributed random numbers.
Definition: Geant4Random.cpp:304
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: Geant4Output2EDM4hep.cpp:49
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:209
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:224
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:298
dd4hep::sim::Geant4Random::initialize
void initialize()
Initialize the instance.
Definition: Geant4Random.cpp:158
Printout.h
dd4hep::sim::Geant4Random::landau
double landau(double mean=0, double sigma=1)
Create landau distributed random numbers.
Definition: Geant4Random.cpp:310
dd4hep::sim::Geant4Context
Generic context to extend user, run and event information.
Definition: Geant4Context.h:201