DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Geant4Random.cpp
Go to the documentation of this file.
1 // $Id: $
2 //==========================================================================
3 // AIDA Detector description implementation for LCD
4 //--------------------------------------------------------------------------
5 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
6 // All rights reserved.
7 //
8 // For the licensing terms see $DD4hepINSTALL/LICENSE.
9 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
10 //
11 // Author : M.Frank
12 //
13 //==========================================================================
14 
15 // Framework include files
16 #include "DD4hep/Printout.h"
17 #include "DD4hep/InstanceCount.h"
18 #include "DDG4/Geant4Random.h"
19 
20 #include "CLHEP/Random/EngineFactory.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 std;
30 using namespace DD4hep::Simulation;
31 
32 namespace CLHEP {
33  unsigned long crc32ul(const std::string& s);
34 }
35 
36 namespace {
37 
39  class RNDM : public TRandom {
41  Geant4Random* m_generator;
43  CLHEP::HepRandomEngine* m_engine;
44 
45  public:
47  RNDM(Geant4Random* r) : TRandom(), m_generator(r) {
48  m_engine = m_generator->engine();
49  }
51  virtual ~RNDM() { }
53  virtual void SetSeed(UInt_t seed=0) {
54  fSeed = seed;
55  m_generator->setSeed((long)seed);
56  }
58  virtual void SetSeed(ULong_t seed=0) {
59  fSeed = seed;
60  m_generator->setSeed((long)seed);
61  }
63  virtual Double_t Rndm(Int_t=0) {
64  return m_engine->flat();
65  }
67  virtual void RndmArray(Int_t size, Float_t *array) {
68  for (Int_t i=0;i<size;i++) array[i] = m_engine->flat();
69  }
71  virtual void RndmArray(Int_t size, Double_t *array) {
72  m_engine->flatArray(size,array);
73  }
74  };
75  static Geant4Random* s_instance = 0;
76 }
77 
79 Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam)
80  : Geant4Action(ctxt,nam), m_engine(0), m_rootRandom(0), m_rootOLD(0),
81  m_inited(false)
82 {
83  declareProperty("File", m_file="");
84  declareProperty("Type", m_engineType="");
85  declareProperty("Seed", m_seed = 123456789);
86  declareProperty("Luxury", m_luxury = 1);
87  declareProperty("Replace_gRandom", m_replace = true);
88  // Default: static Geant4 random engine.
89  m_engine = CLHEP::HepRandom::getTheEngine();
91 }
92 
95  // Only delete the engine if it is NOT the CLEP default one
96  // BUT: Just cannot delete the engine. Causes havoc with static destructors!
97  //CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
98  //if ( !m_engineType.empty() && m_engine != curr ) deletePtr(m_engine);
99 
100  // Set gRandom to the old value
101  if ( m_rootRandom == gRandom ) gRandom = m_rootOLD;
102  // Reset instance pointer
103  if ( s_instance == this ) s_instance = 0;
104  // Finally delete the TRandom instance wrapper
107 }
108 
110 Geant4Random* Geant4Random::instance(bool throw_exception) {
111  if ( !s_instance && throw_exception ) {
112  throw runtime_error("No global random number generator defined!");
113  }
114  return s_instance;
115 }
116 
119  if ( ptr && !ptr->m_inited ) {
120  ptr->initialize();
121  }
122  if ( s_instance != ptr ) {
123  if ( !ptr ) {
124  throw runtime_error("Attempt to declare invalid Geant4Random instance.");
125  }
126  if ( !ptr->m_inited ) {
127  throw runtime_error("Attempt to declare uninitialized Geant4Random instance.");
128  }
129  Geant4Random* old = s_instance;
130  CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine();
131  if ( ptr->m_engine != curr ) {
132  ptr->printP2("Moving CLHEP random instance from %p to %p",curr,ptr->m_engine);
133  CLHEP::HepRandom::setTheEngine(ptr->m_engine);
134  }
135  if ( ptr->m_replace ) {
136  ptr->m_rootOLD = gRandom;
137  gRandom = ptr->m_rootRandom;
138  }
139  s_instance = ptr;
140  return old;
141  }
142  return 0;
143 }
144 
145 #include "CLHEP/Random/DualRand.h"
146 #include "CLHEP/Random/JamesRandom.h"
147 #include "CLHEP/Random/MTwistEngine.h"
148 #include "CLHEP/Random/RanecuEngine.h"
149 #include "CLHEP/Random/Ranlux64Engine.h"
150 #include "CLHEP/Random/RanluxEngine.h"
151 #include "CLHEP/Random/RanshiEngine.h"
152 #include "CLHEP/Random/NonRandomEngine.h"
153 
156  if ( !m_file.empty() ) {
157  ifstream in(m_file.c_str(), std::ios::in);
158  m_engine = CLHEP::EngineFactory::newEngine(in);
159  if ( !m_engine ) {
160  except("Failed to create CLHEP random engine from file:%s.",m_file.c_str());
161  }
162  m_seed = m_engine->getSeed();
163  }
164  else if ( !m_engineType.empty() ) {
166  if ( m_engineType == CLHEP::HepJamesRandom::engineName() )
167  m_engine = new CLHEP::HepJamesRandom();
168  else if ( m_engineType == CLHEP::RanecuEngine::engineName() )
169  m_engine = new CLHEP::RanecuEngine();
170  else if ( m_engineType == CLHEP::Ranlux64Engine::engineName() )
171  m_engine = new CLHEP::Ranlux64Engine();
172  else if ( m_engineType == CLHEP::MTwistEngine::engineName() )
173  m_engine = new CLHEP::MTwistEngine();
174  else if ( m_engineType == CLHEP::DualRand::engineName() )
175  m_engine = new CLHEP::DualRand();
176  else if ( m_engineType == CLHEP::RanluxEngine::engineName() )
177  m_engine = new CLHEP::RanluxEngine();
178  else if ( m_engineType == CLHEP::RanshiEngine::engineName() )
179  m_engine = new CLHEP::RanshiEngine();
180  else if ( m_engineType == CLHEP::NonRandomEngine::engineName() )
181  m_engine = new CLHEP::NonRandomEngine();
182 
183  if ( !m_engine ) {
184  except("Failed to create CLHEP random engine of type: %s.",m_engineType.c_str());
185  }
186  }
187  m_engine->setSeed(m_seed,m_luxury);
188  m_rootRandom = new RNDM(this);
189  m_inited = true;
190  if ( 0 == s_instance ) {
191  setMainInstance(this);
192  }
193 }
194 
196 void Geant4Random::setSeed(long seed) {
197  if ( !m_inited ) initialize();
198  m_engine->setSeed(m_seed=seed,0);
199 }
200 
202 
206 void Geant4Random::setSeeds(const long* seeds, int size) {
207  if ( !m_inited ) initialize();
208  m_seed = seeds[0];
209  m_engine->setSeeds(seeds, size);
210 }
211 
213 void Geant4Random::saveStatus( const char filename[] ) const {
214  if ( !m_inited ) {
215  except("Failed to save RandomGenerator status. [Not-inited]");
216  }
217  m_engine->saveStatus(filename);
218 }
219 
221 void Geant4Random::restoreStatus( const char filename[] ) {
222  if ( !m_inited ) initialize();
223  m_engine->restoreStatus(filename);
224 }
225 
228  if ( !m_inited ) {
229  error("Failed to show RandomGenerator status. [Not-inited]");
230  return;
231  }
232  printP2("Random engine status of object of type Geant4Random @ 0x%p",this);
233  if ( !m_file.empty() )
234  printP2(" Created from file: %s",m_file.c_str());
235  else if ( !m_engineType.empty() )
236  printP2(" Special instance created of type:%s @ 0x%p",
237  m_engineType.c_str(),m_engine);
238  else
239  printP2(" Reused HepRandom engine instance %s @ 0x%p",
240  m_engine ? m_engine->name().c_str() : "???", m_engine);
241 
242  if ( m_engine == CLHEP::HepRandom::getTheEngine() )
243  printP2(" Instance is identical to Geant4's HepRandom instance.");
244 
245  printP2(" Instance is %sidentical to ROOT's gRandom instance.",
246  gRandom == m_rootRandom ? "" : "NOT ");
247 
248  if ( gRandom != m_rootRandom ) {
249  printP2(" Local TRandom: 0x%p gRandom: 0x%p",m_rootRandom,gRandom);
250  }
251  m_engine->showStatus();
252 }
253 
256  if ( !m_inited ) initialize();
257  return m_engine->flat();
258 }
259 
261 double Geant4Random::rndm(int i) {
262  if ( !m_inited ) initialize();
263  return gRandom->Rndm(i);
264 }
265 
267 void Geant4Random::rndmArray(int n, float *array) {
268  if ( !m_inited ) initialize();
269  gRandom->RndmArray(n,array);
270 }
271 
273 void Geant4Random::rndmArray(int n, double *array) {
274  if ( !m_inited ) initialize();
275  gRandom->RndmArray(n,array);
276 }
277 
279 double Geant4Random::uniform(double x1) {
280  if ( !m_inited ) initialize();
281  return gRandom->Uniform(x1);
282 }
283 
285 double Geant4Random::uniform(double x1, double x2) {
286  if ( !m_inited ) initialize();
287  return gRandom->Uniform(x1,x2);
288 }
289 
291 double Geant4Random::exp(double tau) {
292  if ( !m_inited ) initialize();
293  return gRandom->Exp(tau);
294 }
295 
297 double Geant4Random::gauss(double mean, double sigma) {
298  if ( !m_inited ) initialize();
299  return gRandom->Gaus(mean,sigma);
300 }
301 
303 double Geant4Random::landau(double mean, double sigma) {
304  if ( !m_inited ) initialize();
305  return gRandom->Landau(mean,sigma);
306 }
307 
309 void Geant4Random::circle(double &x, double &y, double r) {
310  if ( !m_inited ) initialize();
311  gRandom->Circle(x,y,r);
312 }
313 
315 void Geant4Random::sphere(double &x, double &y, double &z, double r) {
316  if ( !m_inited ) initialize();
317  gRandom->Sphere(x,y,z,r);
318 }
319 
TRandom * m_rootRandom
Reference to ROOT random instance.
Definition: Geant4Random.h:77
virtual void setSeeds(const long *seeds, int size)
Should initialise the status of the algorithm.
void deletePtr(T *&p)
Helper to delete objects from heap and reset the pointer. Saves many many lines of code...
Definition: Primitives.h:234
double uniform(double x1=1)
Create uniformly disributed random numbers in the interval ]0,x1].
static void decrement(T *)
Decrement count according to type information.
unsigned long crc32ul(const std::string &s)
bool m_inited
Flag to remember initialization.
Definition: Geant4Random.h:79
double exp(double tau)
Create exponentially distributed random numbers.
double landau(double mean=0, double sigma=1)
Create landau distributed random numbers.
double rndm_clhep()
Create flat distributed random numbers in the interval ]0,1] calling CLHEP.
void sphere(double &x, double &y, double &z, double r)
Create tuple of randum number on a sphere with radius r.
TGeoShape * s
Definition: Volumes.cpp:294
void error(const char *fmt,...) const
Support of error messages.
void printP2(const char *fmt,...) const
Support for messages with variable output level using output level+2.
void circle(double &x, double &y, double r)
Create tuple of randum number around a circle with radius r.
double rndm(int i=0)
Create flat distributed random numbers in the interval ]0,1].
void except(const char *fmt,...) const
Support of exceptions: Print fatal message and throw runtime_error.
long m_seed
Property: Initial random seed. Default: 123456789.
Definition: Geant4Random.h:69
static Geant4Random * setMainInstance(Geant4Random *ptr)
Make this random generator instance the one used by Geant4.
virtual void saveStatus(const char filename[]="Config.conf") const
Should save on a file specific to the instantiated engine in use the current status.
void initialize()
Initialize the instance.
static Geant4Random * instance(bool throw_exception=true)
Access the main Geant4 random generator instance. Must be created before used!
bool m_replace
Property: Indicator to replace the ROOT gRandom instance.
Definition: Geant4Random.h:71
void rndmArray(int n, float *array)
Create a float array of flat distributed random numbers in the interval ]0,1].
CLHEP::HepRandomEngine * m_engine
Reference to the CLHEP random number engine (valid only after initialization)
Definition: Geant4Random.h:74
virtual void setSeed(long seed)
Should initialise the status of the algorithm according to seed.
virtual ~Geant4Random()
Default destructor.
double gauss(double mean=0, double sigma=1)
Create gaussian distributed random numbers.
static void increment(T *)
Increment count according to type information.
Definition: InstanceCount.h:98
std::string m_engineType
Property: Engine type. default: "HepJamesRandom".
Definition: Geant4Random.h:67
virtual void restoreStatus(const char filename[]="Config.conf")
Should read from a file and restore the last saved engine configuration.
virtual void showStatus() const
Should dump the current engine status on the screen.
Generic context to extend user, run and event information.
Mini interface to THE random generator of the application.
Definition: Geant4Random.h:60
std::string m_file
Property: File name if initialized from file. If set, engine name and seeds are ignored.
Definition: Geant4Random.h:65
Geant4Action & declareProperty(const std::string &nam, T &val)
Declare property.
Definition: Geant4Action.h:358
Default base class for all Geant 4 actions and derivates thereof.
Definition: Geant4Action.h:91