From 87ea56c102bbc1161ae58bff6ffe413df7fa5383 Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Tue, 8 Mar 2016 14:00:07 +0000 Subject: [PATCH] Extend checks in the CLID random numbers example --- DDG4/include/DDG4/Geant4Random.h | 6 +++ DDG4/python/DDG4.py | 5 +- DDG4/python/DDG4Dict.C | 10 ++++ DDG4/src/Geant4Exec.cpp | 1 + DDG4/src/Geant4IsotropeGenerator.cpp | 8 +-- DDG4/src/Geant4Random.cpp | 70 +++++++++++++++++--------- examples/CLICSiD/scripts/CLICRandom.py | 51 ++++++++++++++++--- 7 files changed, 115 insertions(+), 36 deletions(-) diff --git a/DDG4/include/DDG4/Geant4Random.h b/DDG4/include/DDG4/Geant4Random.h index 6322ee7f5..1085153a4 100644 --- a/DDG4/include/DDG4/Geant4Random.h +++ b/DDG4/include/DDG4/Geant4Random.h @@ -133,6 +133,12 @@ namespace DD4hep { /** Basic random generator functions */ + /// Create flat distributed random numbers in the interval ]0,1] calling CLHEP + /** This is more or less a test function, since the result should be + * identical to calling rndm. + */ + double rndm_clhep(); + /// Create flat distributed random numbers in the interval ]0,1] double rndm(int i=0); /// Create a float array of flat distributed random numbers in the interval ]0,1] diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index 3ee3ac22e..15c9e50f8 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -37,10 +37,10 @@ except Exception,X: print '| %-100s |'%('Try to compile AClick on the fly.',) print '+--%-100s--+'%(100*'-',) DD4hep = compileAClick(dictionary='DDG4Dict.C',g4=True) +from ROOT import CLHEP as CLHEP Core = DD4hep Sim = DD4hep.Simulation Simulation = DD4hep.Simulation - Kernel = Sim.KernelHandle Interface = Sim.Geant4ActionCreation LCDD = Geo.LCDD @@ -225,6 +225,9 @@ _import_class('Sim','Geant4UserParticleHandler') _import_class('Sim','Geant4UserInitialization') _import_class('Sim','Geant4DetectorConstruction') _import_class('Sim','Geant4GeneratorWrapper') +_import_class('Sim','Geant4Random') +_import_class('CLHEP','HepRandom') +_import_class('CLHEP','HepRandomEngine') #--------------------------------------------------------------------------- def _get(self, name): diff --git a/DDG4/python/DDG4Dict.C b/DDG4/python/DDG4Dict.C index dc3829f91..d55afefae 100644 --- a/DDG4/python/DDG4Dict.C +++ b/DDG4/python/DDG4Dict.C @@ -333,6 +333,16 @@ namespace { #endif +// CLHEP stuff +#include "CLHEP/Random/Random.h" +#if defined(__CINT__) || defined(__MAKECINT__) || defined(__CLING__) || defined(__ROOTCLING__) + +#pragma link C++ namespace CLHEP; +#pragma link C++ class CLHEP::HepRandom; +#pragma link C++ class CLHEP::HepRandomEngine; +#endif + + int Geant4Dict() { return 0; } diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp index 253f90288..4eb99beaa 100644 --- a/DDG4/src/Geant4Exec.cpp +++ b/DDG4/src/Geant4Exec.cpp @@ -522,6 +522,7 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { /// Initialize the engine etc. rndm->initialize(); } + Geant4Random::setMainInstance(rndm); kernel.executePhase("configure",0); // Construct the default run manager diff --git a/DDG4/src/Geant4IsotropeGenerator.cpp b/DDG4/src/Geant4IsotropeGenerator.cpp index b6e5bbbea..f8157a4bd 100644 --- a/DDG4/src/Geant4IsotropeGenerator.cpp +++ b/DDG4/src/Geant4IsotropeGenerator.cpp @@ -40,7 +40,7 @@ Geant4IsotropeGenerator::~Geant4IsotropeGenerator() { /// Uniform particle distribution void Geant4IsotropeGenerator::getParticleDirectionUniform(int, ROOT::Math::XYZVector& direction, double& momentum) const { - Geant4Event& evt = context()->event(); + Geant4Event& evt = context()->event(); Geant4Random& rnd = evt.random(); double phi = m_phiMin+(m_phiMax-m_phiMin)*rnd.rndm(); double theta = m_thetaMin+(m_thetaMax-m_thetaMin)*rnd.rndm(); @@ -54,7 +54,7 @@ void Geant4IsotropeGenerator::getParticleDirectionUniform(int, ROOT::Math::XYZVe /// Particle distribution ~ cos(theta) void Geant4IsotropeGenerator::getParticleDirectionCosTheta(int, ROOT::Math::XYZVector& direction, double& momentum) const { - Geant4Event& evt = context()->event(); + Geant4Event& evt = context()->event(); Geant4Random& rnd = evt.random(); double phi = m_phiMin+(m_phiMax-m_phiMin)*rnd.rndm(); double cos_theta = std::cos(m_thetaMin)+(std::cos(m_thetaMax)-std::cos(m_thetaMin))*rnd.rndm(); @@ -72,7 +72,7 @@ void Geant4IsotropeGenerator::getParticleDirectionEta(int, ROOT::Math::XYZVector struct Distribution { static double eta(double x) { return -1.0*std::log(std::tan(x/2.0)); } }; - Geant4Event& evt = context()->event(); + Geant4Event& evt = context()->event(); Geant4Random& rnd = evt.random(); // See https://en.wikipedia.org/wiki/Pseudorapidity const double dmin = std::numeric_limits<double>::epsilon(); @@ -94,7 +94,7 @@ void Geant4IsotropeGenerator::getParticleDirectionFFbar(int, ROOT::Math::XYZVect static double ffbar(double x) { double c = std::cos(x); return 1 + c*c; } //static double integral(double x) { return 1.5*x + sin(2.*x)/4.0; } }; - Geant4Event& evt = context()->event(); + Geant4Event& evt = context()->event(); Geant4Random& rnd = evt.random(); double phi = m_phiMin+(m_phiMax-m_phiMin)*rnd.rndm(); diff --git a/DDG4/src/Geant4Random.cpp b/DDG4/src/Geant4Random.cpp index ad663c8bf..c0fce221f 100644 --- a/DDG4/src/Geant4Random.cpp +++ b/DDG4/src/Geant4Random.cpp @@ -87,9 +87,16 @@ Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam) /// Default destructor Geant4Random::~Geant4Random() { - if ( s_instance == this ) s_instance = 0; - if ( !m_engineType.empty() ) deletePtr(m_engine); + // Only delete the engine if it is NOT the CLEP default one + // BUT: Just cannot delete the engine. Causes havoc with static destructors! + //CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine(); + //if ( !m_engineType.empty() && m_engine != curr ) deletePtr(m_engine); + + // Set gRandom to the old value if ( m_rootRandom == gRandom ) gRandom = m_rootOLD; + // Reset instance pointer + if ( s_instance == this ) s_instance = 0; + // Finally delete the TRandom instance wrapper deletePtr(m_rootRandom); InstanceCount::decrement(this); } @@ -103,26 +110,31 @@ Geant4Random* Geant4Random::instance(bool throw_exception) { } /// Make this random generator instance the one used by Geant4 - Geant4Random* Geant4Random::setMainInstance(Geant4Random* ptr) { - if ( s_instance != ptr ) { - if ( !ptr ) { - throw runtime_error("Attempt to declare invalid Geant4Random instance."); - } - if ( !ptr->m_inited ) { - throw runtime_error("Attempt to declare uninitialized Geant4Random instance."); - } - Geant4Random* old = s_instance; - if ( ptr->m_engine != CLHEP::HepRandom::getTheEngine() ) { - CLHEP::HepRandom::setTheEngine(ptr->m_engine); - } - if ( ptr->m_replace ) { - ptr->m_rootOLD = gRandom; - gRandom = ptr->m_rootRandom; - } - s_instance = ptr; - return old; - } - return 0; +Geant4Random* Geant4Random::setMainInstance(Geant4Random* ptr) { + if ( ptr && !ptr->m_inited ) { + ptr->initialize(); + } + if ( s_instance != ptr ) { + if ( !ptr ) { + throw runtime_error("Attempt to declare invalid Geant4Random instance."); + } + if ( !ptr->m_inited ) { + throw runtime_error("Attempt to declare uninitialized Geant4Random instance."); + } + Geant4Random* old = s_instance; + CLHEP::HepRandomEngine* curr = CLHEP::HepRandom::getTheEngine(); + if ( ptr->m_engine != curr ) { + ptr->printP2("Moving CLHEP random instance from %p to %p",curr,ptr->m_engine); + CLHEP::HepRandom::setTheEngine(ptr->m_engine); + } + if ( ptr->m_replace ) { + ptr->m_rootOLD = gRandom; + gRandom = ptr->m_rootRandom; + } + s_instance = ptr; + return old; + } + return 0; } #include "CLHEP/Random/DualRand.h" @@ -216,11 +228,13 @@ void Geant4Random::showStatus() const { if ( !m_file.empty() ) printP2(" Created from file: %s",m_file.c_str()); else if ( !m_engineType.empty() ) - printP2(" Special instance created of type:%s",m_engineType.c_str()); + printP2(" Special instance created of type:%s @ 0x%p", + m_engineType.c_str(),m_engine); else - printP2(" Reused HepRandom instance @ 0x%p",m_engine); + printP2(" Reused HepRandom engine instance %s @ 0x%p", + m_engine ? m_engine->name().c_str() : "???", m_engine); - if ( m_engine != CLHEP::HepRandom::getTheEngine() ) + if ( m_engine == CLHEP::HepRandom::getTheEngine() ) printP2(" Instance is identical to Geant4's HepRandom instance."); printP2(" Instance is %sidentical to ROOT's gRandom instance.", @@ -232,6 +246,12 @@ void Geant4Random::showStatus() const { m_engine->showStatus(); } +/// Create flat distributed random numbers in the interval ]0,1] +double Geant4Random::rndm_clhep() { + if ( !m_inited ) initialize(); + return m_engine->flat(); +} + /// Create flat distributed random numbers in the interval ]0,1] double Geant4Random::rndm(int i) { if ( !m_inited ) initialize(); diff --git a/examples/CLICSiD/scripts/CLICRandom.py b/examples/CLICSiD/scripts/CLICRandom.py index 338a532b2..247218dbc 100644 --- a/examples/CLICSiD/scripts/CLICRandom.py +++ b/examples/CLICSiD/scripts/CLICRandom.py @@ -5,16 +5,55 @@ @version 1.0 """ +from ROOT import TRandom +from ROOT import gRandom + if __name__ == "__main__": - import CLICSid + import CLICSid, DDG4 sid = CLICSid.CLICSid() + print 'DEFAULT Engine:', DDG4.CLHEP.HepRandom.getTheEngine().name() # <<-- See this function to know how it's done.... - rndm1=sid.setupRandom('R1',seed=987654321,type='MTwistEngine') - rndm2=sid.setupRandom('R2',seed=1234321) + rndm1 = sid.setupRandom('R1',seed=987654321,type='RunluxEngine') + print 'R1:', rndm1.name, ' Default instance:', rndm1.instance().name() + print ' Engine: ', rndm1.engine().name() + print ' DEFAULT:', DDG4.CLHEP.HepRandom.getTheEngine().name() + rndm1.showStatus() + + rndm2 = sid.setupRandom('R2',seed=1234321,type='MTwistEngine') + print 'R2:', rndm2.name, ' Default instance:', rndm2.instance().name() + print ' Engine:', rndm2.engine().name() + print ' DEFAULT:', DDG4.CLHEP.HepRandom.getTheEngine().name() + #rndm2.showStatus() + + DDG4.Geant4Random.setMainInstance(rndm1.get()) + rndm1.showStatus() # Move main geant random instance from rndm1 to rndm2: # See how gRandom and HepRandom instances move - rndm2.setMainInstance(rndm2.get()) - rndm2.showStatus() - rndm1.showStatus() + DDG4.Geant4Random.setMainInstance(rndm1.get()) + print 'DEFAULT Engine:', DDG4.CLHEP.HepRandom.getTheEngine().name() + print 'DDG4 DEFAULT:', DDG4.Geant4Random.instance().engine().name() + rndm = DDG4.Geant4Random.instance() + + rndm.setSeed(1234) + rndm.showStatus() + for i in xrange(10): + print rndm.name(), ' -- 0 gRandome.Rndm() -- Shoot random[',i,']= ',gRandom.Rndm() + + rndm.setSeed(1234) + for i in xrange(10): + print rndm.name(), ' -- 1 gRandome.Rndm() -- Shoot random[',i,']= ',gRandom.Rndm() + + rndm.setSeed(1234) + for i in xrange(10): + print rndm.name(), ' -- 2 Geant4Random(CLHEP) -- Shoot random[',i,']= ',rndm.rndm_clhep() + + rndm.setSeed(1234) + for i in xrange(10): + print rndm.name(), ' -- 3 Geant4Random(CLHEP) -- Shoot random[',i,']= ',rndm.rndm_clhep() + + rndm.setSeed(1234) + for i in xrange(10): + print rndm.name(), ' -- 4 HepRandomEngine(CLHEP) -- Shoot random[',i,']= ',rndm.engine().flat() + sid.test_run(have_geo=False) -- GitLab