diff --git a/DDG4/examples/CLICMagField.py b/DDG4/examples/CLICMagField.py new file mode 100644 index 0000000000000000000000000000000000000000..0880dbf3ff7c88809ad60f29a00a534926990c18 --- /dev/null +++ b/DDG4/examples/CLICMagField.py @@ -0,0 +1,14 @@ +""" + Subtest using CLICSid showing how to manipulate the magnetic field + + @author M.Frank + @version 1.0 + +""" +if __name__ == "__main__": + import CLICSid + sid = CLICSid.CLICSid().loadGeometry() + # <<-- See this function to know how it's done.... + sid.setupField(quiet=false) + sid.test_run() + diff --git a/DDG4/examples/CLICPhysics.py b/DDG4/examples/CLICPhysics.py new file mode 100644 index 0000000000000000000000000000000000000000..43e2d1d2cb1fc2436f4c2fe91033b1d23d284e37 --- /dev/null +++ b/DDG4/examples/CLICPhysics.py @@ -0,0 +1,13 @@ +""" + Subtest using CLICSid showing how to setup the Geant4 physics list + + @author M.Frank + @version 1.0 + +""" +if __name__ == "__main__": + import CLICSid + sid = CLICSid.CLICSid().loadGeometry() + # <<-- See this function to know how it's done.... + sid.setupPhysics('QGSP_BERT') + sid.test_run() diff --git a/DDG4/examples/CLICRandom.py b/DDG4/examples/CLICRandom.py new file mode 100644 index 0000000000000000000000000000000000000000..338a532b2429cf2d9415d9b4034f59f5f0867938 --- /dev/null +++ b/DDG4/examples/CLICRandom.py @@ -0,0 +1,20 @@ +""" + Subtest using CLICSid showing how to setup the random number generator + + @author M.Frank + @version 1.0 + +""" +if __name__ == "__main__": + import CLICSid + sid = CLICSid.CLICSid() + # <<-- See this function to know how it's done.... + rndm1=sid.setupRandom('R1',seed=987654321,type='MTwistEngine') + rndm2=sid.setupRandom('R2',seed=1234321) + + # Move main geant random instance from rndm1 to rndm2: + # See how gRandom and HepRandom instances move + rndm2.setMainInstance(rndm2.get()) + rndm2.showStatus() + rndm1.showStatus() + sid.test_run(have_geo=False) diff --git a/DDG4/examples/CLICSid.py b/DDG4/examples/CLICSid.py new file mode 100644 index 0000000000000000000000000000000000000000..e581d9fd36b146419a8d8c0b58b3410d43facbf9 --- /dev/null +++ b/DDG4/examples/CLICSid.py @@ -0,0 +1,78 @@ +import sys, DDG4 +from SystemOfUnits import * + +class CLICSid: + def __init__(self): + self.kernel = DDG4.Kernel() + self.lcdd = self.kernel.lcdd() + self.geant4 = DDG4.Geant4(self.kernel) + self.kernel.UI = "" + self.noPhysics() + + def loadGeometry(self): + import os + install_dir = os.environ['DD4hepINSTALL'] + self.kernel.loadGeometry("file:"+install_dir+"/DDDetectors/compact/SiD.xml") + return self + + # Example to show how to configure G4 magnetic field tracking + def setupField(self, quiet=True): + field = self.geant4.addConfig('Geant4FieldTrackingSetupAction/MagFieldTrackingSetup') + field.stepper = "HelixGeant4Runge" + field.equation = "Mag_UsualEqRhs" + field.eps_min = 5e-05 * mm + field.eps_max = 0.001 * mm + field.min_chord_step = 0.01 * mm + field.delta_chord = 0.25 * mm + field.delta_intersection = 1e-05 * mm + field.delta_one_step = 0.001 * mm + if not quiet: + print '+++++> ',field.name,'-> stepper = ',field.stepper + print '+++++> ',field.name,'-> equation = ',field.equation + print '+++++> ',field.name,'-> eps_min = ',field.eps_min + print '+++++> ',field.name,'-> eps_max = ',field.eps_max + print '+++++> ',field.name,'-> delta_one_step = ',field.delta_one_step + return field + + # Example to show how to setup random generator + def setupRandom(self, name, type=None, seed=None, quiet=True): + rndm = DDG4.Action(self.kernel,'Geant4Random/'+name) + if seed: rndm.Seed = seed + if type: rndm.Type = type + rndm.initialize() + if not quiet: rndm.showStatus() + return rndm + + # Example to show how to configure the Geant4 physics list + def setupPhysics(self, model): + phys = self.geant4.setupPhysics(model) + ph = DDG4.PhysicsList(self.kernel,'Geant4PhysicsList/Myphysics') + # Add bosons to the model (redundant if already implemented by the model) + ph.addParticleConstructor('G4BosonConstructor') + # Add leptons to the model (redundant if already implemented by the model) + ph.addParticleConstructor('G4LeptonConstructor') + # Add multiple scattering in the material + ph.addParticleProcess('e[+-]','G4eMultipleScattering',-1,1,1) + # Add optical physics (RICH dets etc) + ph.addPhysicsConstructor('G4OpticalPhysics') + # Interactivity + ph.enableUI() + phys.adopt(ph) + phys.dump() + return phys + + # No physics list wanted for tests ? See how: + def noPhysics(self): + self.geant4.setupPhysics('') + return self + + + # Test runner + def test_run(self, have_geo=True, have_physics=False): + self.kernel.configure() + if have_geo: + self.kernel.initialize() + self.kernel.NumEvents = 0 + self.kernel.run() + self.kernel.terminate() + sys.exit(0) diff --git a/DDG4/examples/CLICSidSimu.py b/DDG4/examples/CLICSidSimu.py index 0e4cdf20767c1c20f04058ec13fbe7a9eae63376..318e26eafff2c41fb12bb241fde680d5afe63b8e 100644 --- a/DDG4/examples/CLICSidSimu.py +++ b/DDG4/examples/CLICSidSimu.py @@ -17,7 +17,6 @@ def run(): kernel = DDG4.Kernel() lcdd = kernel.lcdd() install_dir = os.environ['DD4hepINSTALL'] - example_dir = install_dir+'/examples/DDG4/examples'; kernel.loadGeometry("file:"+install_dir+"/DDDetectors/compact/SiD.xml") DDG4.importConstants(lcdd) @@ -42,6 +41,12 @@ def run(): print '+++++> ',field.name,'-> eps_max = ',field.eps_max print '+++++> ',field.name,'-> delta_one_step = ',field.delta_one_step + # Setup random generator + rndm = DDG4.Action(kernel,'Geant4Random/Random') + rndm.Seed = 987654321 + rndm.initialize() + rndm.showStatus() + rndm.Seed = 987654321 # Configure Run actions run1 = DDG4.RunAction(kernel,'Geant4TestRunAction/RunInit') diff --git a/DDG4/include/DDG4/Factories.h b/DDG4/include/DDG4/Factories.h index a8b7bb13836f263779e55997235836f2d847a153..d0496b01571354d431edf1ce3cf99a0a42f0f71d 100644 --- a/DDG4/include/DDG4/Factories.h +++ b/DDG4/include/DDG4/Factories.h @@ -34,6 +34,7 @@ class G4MagneticField; class G4Mag_EqRhs; class G4VPhysicsConstructor; class G4VUserPhysicsList; +class G4VPrimaryGenerator; class G4VProcess; /// Namespace for the AIDA detector description toolkit @@ -125,6 +126,10 @@ namespace { DD4HEP_PLUGIN_FACTORY_ARGS_0(G4ParticleDefinition*) { return P::Definition(); } + /// Factory to create Geant4 primary generator objects + DD4HEP_PLUGIN_FACTORY_ARGS_0(G4VPrimaryGenerator*) + { return new P(); } + /// Generic particle constructor DD4HEP_PLUGIN_FACTORY_ARGS_0(long) { P::ConstructParticle(); @@ -172,6 +177,8 @@ namespace { #define DECLARE_GEANT4_PROCESS(name) DD4HEP_PLUGINSVC_FACTORY(name,name,G4VProcess*(),__LINE__) /// Plugin definition to create Geant4 physics constructors (G4VPhysicsConstructor) #define DECLARE_GEANT4_PHYSICS(name) DD4HEP_PLUGINSVC_FACTORY(name,name,G4VPhysicsConstructor*(),__LINE__) +/// Plugin definition to create Geant4 physics processes (G4VProcess) +#define DECLARE_GEANT4_GENERATOR(name) DD4HEP_PLUGINSVC_FACTORY(name,name,G4VPrimaryGenerator*(),__LINE__) /// Plugin definition to force particle constructors for GEANT4 (G4ParticleDefinition) #define DECLARE_GEANT4_PARTICLE(name) DD4HEP_PLUGINSVC_FACTORY(name,name,G4ParticleDefinition*(),__LINE__) /// Plugin definition to force particle constructors for GEANT4 (G4XXXXConstructor) diff --git a/DDG4/include/DDG4/Geant4Action.h b/DDG4/include/DDG4/Geant4Action.h index 5e3db52c46fb653cf1b3ca9ce77df2830e491b60..ed5c20ac7875b3a482225085520c6efbf618b7c1 100644 --- a/DDG4/include/DDG4/Geant4Action.h +++ b/DDG4/include/DDG4/Geant4Action.h @@ -119,7 +119,7 @@ namespace DD4hep { /// reference to the context; const Geant4Context* context; /// Constructor - ContextUpdate(const Geant4Context* c=0) : context(c) {} + ContextUpdate(const Geant4Context* c=0) : context(c) {} /// Callback void operator()(Geant4Action* action) const; }; diff --git a/DDG4/include/DDG4/Geant4GeneratorWrapper.h b/DDG4/include/DDG4/Geant4GeneratorWrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..c79655f1edefc575d1ba2df4a16cefb560d2833a --- /dev/null +++ b/DDG4/include/DDG4/Geant4GeneratorWrapper.h @@ -0,0 +1,60 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DD4HEP_DDG4_GEANT4GENERATORWRAPPER_H +#define DD4HEP_DDG4_GEANT4GENERATORWRAPPER_H + +// Framework include files +#include "DDG4/Geant4GeneratorAction.h" + +// Forward declarations +class G4VPrimaryGenerator; + + +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { + + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace Simulation { + + /// Geant4Action to merge several independent interaction to one + /** Wrap native G4 particle ganerators like the generic particle source etc. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class Geant4GeneratorWrapper : public Geant4GeneratorAction { + protected: + /// Property: Type name of the implementation instance. name: "Uses" + std::string m_generatorType; + /// Property: interaction identifier mask. name: "Mask" + int m_mask; + + /// Reference to the implementation instance + G4VPrimaryGenerator* m_generator; + + public: + /// Standard constructor + Geant4GeneratorWrapper(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4GeneratorWrapper(); + /// Access the G4VPrimaryGenerator instance + G4VPrimaryGenerator* generator(); + /// Event generation action callback + virtual void operator()(G4Event* event); + }; + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DD4HEP_DDG4_GEANT4GENERATORWRAPPER_H diff --git a/DDG4/include/DDG4/Geant4InputHandling.h b/DDG4/include/DDG4/Geant4InputHandling.h index 90a238e559e8a9c584fcf2deeca7100b26d47d1a..3bcf54c9076b592bd29496c644da7def9d7b5a7d 100644 --- a/DDG4/include/DDG4/Geant4InputHandling.h +++ b/DDG4/include/DDG4/Geant4InputHandling.h @@ -20,6 +20,9 @@ // Forward declarations class G4Event; +class G4PrimaryVertex; +class G4PrimaryParticle; + /// Namespace for the AIDA detector description toolkit namespace DD4hep { @@ -31,6 +34,17 @@ namespace DD4hep { class Geant4Action; class Geant4Context; + /** Helpers to import and export G4 records */ + + /// Create a vertex object from it's G4 counterpart + Geant4Vertex* createPrimary(const G4PrimaryVertex* g4); + + /// Create a particle object from it's G4 counterpart + Geant4Particle* createPrimary(int particle_id, const Geant4Vertex* v, const G4PrimaryParticle* g4p); + + /// Create a DDG4 interaction record from a Geant4 interaction defined by a primary vertex + Geant4PrimaryInteraction* createPrimary(int mask, const G4PrimaryVertex* gv); + /// Initialize the generation of one event int generationInitialization(const Geant4Action* caller,const Geant4Context* context); diff --git a/DDG4/include/DDG4/Geant4InteractionVertexBoost.h b/DDG4/include/DDG4/Geant4InteractionVertexBoost.h index f7f8e5faf3e114436b3f0aac2584d1cd1dbcb54f..3003fe75e5ece41fb84f6a312736d15f8516d807 100644 --- a/DDG4/include/DDG4/Geant4InteractionVertexBoost.h +++ b/DDG4/include/DDG4/Geant4InteractionVertexBoost.h @@ -34,11 +34,19 @@ namespace DD4hep { * \ingroup DD4HEP_SIMULATION */ class Geant4InteractionVertexBoost: public Geant4GeneratorAction { + public: + /// Interaction definition + typedef Geant4PrimaryInteraction Interaction; + protected: /// Property: The constant Lorentz transformation angle double m_angle; /// Property: Unique identifier of the interaction to be modified int m_mask; + + /// Action routine to boost one single interaction according to the properties + void boost(Interaction* interaction) const; + public: /// Standard constructor Geant4InteractionVertexBoost(Geant4Context* context, const std::string& name); diff --git a/DDG4/include/DDG4/Geant4InteractionVertexSmear.h b/DDG4/include/DDG4/Geant4InteractionVertexSmear.h index e42f6978fb1931cea500bd92753fc0fe929b49bb..ac5762ab23397cd4a85d5f7421a4dde518bd4e05 100644 --- a/DDG4/include/DDG4/Geant4InteractionVertexSmear.h +++ b/DDG4/include/DDG4/Geant4InteractionVertexSmear.h @@ -26,6 +26,9 @@ namespace DD4hep { /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit namespace Simulation { + /// Forward declarations + class Geant4PrimaryInteraction; + /// Action class to smear the primary vertex (and all outgoing particles) of a single interaction /** * The vertex smearing is steered by a 3D gaussian given by a constant offset and @@ -37,6 +40,10 @@ namespace DD4hep { * \ingroup DD4HEP_SIMULATION */ class Geant4InteractionVertexSmear: public Geant4GeneratorAction { + public: + /// Interaction definition + typedef Geant4PrimaryInteraction Interaction; + protected: /// Property: The constant smearing offset ROOT::Math::PxPyPzEVector m_offset; @@ -44,6 +51,10 @@ namespace DD4hep { ROOT::Math::PxPyPzEVector m_sigma; /// Property: Unique identifier of the interaction created int m_mask; + + /// Action routine to smear one single interaction according to the properties + void smear(Interaction* interaction) const; + public: /// Standard constructor Geant4InteractionVertexSmear(Geant4Context* context, const std::string& name); diff --git a/DDG4/include/DDG4/Geant4Primary.h b/DDG4/include/DDG4/Geant4Primary.h index ac49f09eb0e18186b9b543759664e8b4da182c04..5e6352e805271f3649816300e370d100eaee94ab 100644 --- a/DDG4/include/DDG4/Geant4Primary.h +++ b/DDG4/include/DDG4/Geant4Primary.h @@ -102,9 +102,11 @@ namespace DD4hep { ExtensionHandle extension; /// User mask to flag the interaction. Also unique identifier int mask; + /// Flag that the event is locked for G4 native generators + int locked; /// Next PID indentifier int next_particle_identifier; - + public: /// Default constructor Geant4PrimaryInteraction(); @@ -155,6 +157,8 @@ namespace DD4hep { void add(int id, Geant4PrimaryInteraction* interaction); /// Retrieve an interaction by it's ID Geant4PrimaryInteraction* get(int id) const; + /// Number of interaction contained in the primary event + size_t size() const { return m_interactions.size(); } /// Retrieve all intractions std::vector<Geant4PrimaryInteraction*> interactions() const; }; diff --git a/DDG4/include/DDG4/Geant4Random.h b/DDG4/include/DDG4/Geant4Random.h index d7cea8aafefb134eef56de2ab8a50b15ab209af2..6322ee7f56ad778ea017742c573b342c95970daa 100644 --- a/DDG4/include/DDG4/Geant4Random.h +++ b/DDG4/include/DDG4/Geant4Random.h @@ -15,8 +15,16 @@ #define DD4HEP_GEANT4RANDOM_H // Framework include files +#include "DDG4/Geant4Action.h" // C/C++ include files +#include <string> + +// Forward declarations +class TRandom; + +/// CLHEP namespace +namespace CLHEP { class HepRandomEngine; } /// Namespace for the AIDA detector description toolkit namespace DD4hep { @@ -41,29 +49,111 @@ namespace DD4hep { * if the generation functions will have to become virtual.... * Future will tell us. * + * The first instance of the random action is automatically set + * to be the Geant4 instance. If another instance should be used by + * Geant4, use setMainInstance(Geant4Random* ptr). + * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_SIMULATION */ - class Geant4Random { + class Geant4Random : public Geant4Action { friend class Geant4Exec; protected: - /// Default constructor - Geant4Random(); + /// Property: File name if initialized from file. If set, engine name and seeds are ignored + std::string m_file; + /// Property: Engine type. default: "HepJamesRandom" + std::string m_engineType; + /// Property: Initial random seed. Default: 123456789 + long m_seed, m_luxury; + /// Property: Indicator to replace the ROOT gRandom instance + bool m_replace; + + /// Reference to the CLHEP random number engine (valid only after initialization) + CLHEP::HepRandomEngine* m_engine; + + /// Reference to ROOT random instance + TRandom *m_rootRandom, *m_rootOLD; + /// Flag to remember initialization + bool m_inited; + + public: + /// Standard constructor + /** Please Note: + * Should be used only for initialization of the main instance. + * Subsequent usage should be invoked using the class member + * Geant4Random::instance(). + * + * @param context Geant4 context for this action. + * @param name Name of the action object + */ + Geant4Random(Geant4Context* context, const std::string& name); /// Default destructor virtual ~Geant4Random(); - public: - void circle(double &x, double &y, double r); - double exp(double tau); - double gauss(double mean=0, double sigma=1); - double landau(double mean=0, double sigma=1); + + /// Access the main Geant4 random generator instance. Must be created before used! + static Geant4Random* instance(bool throw_exception=true); + /// Make this random generator instance the one used by Geant4. + /** Returns reference to previous instance. It is up to the user + * to manage the reference. + * Caveat: other code may hold references to this instance. + * + * @param ptr Reference to main random number generator + * @return Reference to previous random number generator instance + */ + static Geant4Random* setMainInstance(Geant4Random* ptr); + + /// Initialize the instance. + /** Called either by user or on request of the first random number. + * To propagate the engine to Geant4, initialize MUST be called by + * the user. + */ + void initialize(); + + /** Access to the CLHEP random number engine. For further doc see CLHEP/Random/RandomEngine.h */ + + /// CLHEP random number engine (valid after initialization only) + CLHEP::HepRandomEngine* engine() { return m_engine; } + + /// Should initialise the status of the algorithm according to seed. + virtual void setSeed(long seed); + /// Should initialise the status of the algorithm + /** Initialization according to the zero terminated + * array of seeds. It is allowed to ignore one or + * many seeds in this array. + */ + virtual void setSeeds(const long * seeds, int size); + /// Should save on a file specific to the instantiated engine in use the current status. + virtual void saveStatus( const char filename[] = "Config.conf") const; + /// Should read from a file and restore the last saved engine configuration. + virtual void restoreStatus( const char filename[] = "Config.conf" ); + /// Should dump the current engine status on the screen. + virtual void showStatus() const; + + /** Basic random generator functions */ + + /// 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] void rndmArray(int n, float *array); + /// Create a double array of flat distributed random numbers in the interval ]0,1] void rndmArray(int n, double *array); - void sphere(double &x, double &y, double &z, double r); + /// Create uniformly disributed random numbers in the interval ]0,x1] double uniform(double x1=1); + /// Create uniformly disributed random numbers in the interval ]x1,x2] double uniform(double x1, double x2); + + /// Create exponentially distributed random numbers + double exp(double tau); + /// Create gaussian distributed random numbers + double gauss(double mean=0, double sigma=1); + /// Create landau distributed random numbers + double landau(double mean=0, double sigma=1); + /// Create tuple of randum number around a circle with radius r + void circle(double &x, double &y, double r); + /// Create tuple of randum number on a sphere with radius r + void sphere(double &x, double &y, double &z, double r); }; } // End namespace Simulation diff --git a/DDG4/plugins/Geant4Factories.cpp b/DDG4/plugins/Geant4Factories.cpp index 9ddc2f7f25acf00bc04ff2b5316da1547f98a4a4..03bb7e6054de1eef32acc118e1c35ee9649ad88c 100644 --- a/DDG4/plugins/Geant4Factories.cpp +++ b/DDG4/plugins/Geant4Factories.cpp @@ -16,6 +16,9 @@ #include "DDG4/Factories.h" using namespace DD4hep::Simulation; +#include "DDG4/Geant4Random.h" +DECLARE_GEANT4ACTION(Geant4Random) + #include "DDG4/Geant4ActionPhase.h" DECLARE_GEANT4ACTION(Geant4PhaseAction) @@ -106,6 +109,10 @@ DECLARE_GEANT4ACTION(Geant4PrimaryHandler) #include "DDG4/Geant4InputAction.h" DECLARE_GEANT4ACTION(Geant4InputAction) +//============================= +#include "DDG4/Geant4GeneratorWrapper.h" +DECLARE_GEANT4ACTION(Geant4GeneratorWrapper) + //============================= #include "DDG4/Geant4TestActions.h" namespace DD4hep { namespace Simulation { diff --git a/DDG4/plugins/Geant4PrimaryGenerators.cpp b/DDG4/plugins/Geant4PrimaryGenerators.cpp new file mode 100644 index 0000000000000000000000000000000000000000..018938ec24ca3005fac30bc3123937f6f0ed4169 --- /dev/null +++ b/DDG4/plugins/Geant4PrimaryGenerators.cpp @@ -0,0 +1,27 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DDG4/Factories.h" + +// Geant 4 include files +#include "G4ParticleGun.hh" +#include "G4SingleParticleSource.hh" +#include "G4GeneralParticleSource.hh" +#include "G4AdjointPrimaryGenerator.hh" + +DECLARE_GEANT4_GENERATOR(G4ParticleGun) +DECLARE_GEANT4_GENERATOR(G4SingleParticleSource) +DECLARE_GEANT4_GENERATOR(G4GeneralParticleSource) +//DECLARE_GEANT4_GENERATOR(G4AdjointPrimaryGenerator) diff --git a/DDG4/python/DDG4Dict.C b/DDG4/python/DDG4Dict.C index b51c633b8ee7ec576a53ca056d88509f39fb1118..ea0602cfd31940a22c7527540dd2f6162bdaa155 100644 --- a/DDG4/python/DDG4Dict.C +++ b/DDG4/python/DDG4Dict.C @@ -18,6 +18,7 @@ //==================================================================== // FRamework include files #include "DDG4/Geant4Primary.h" +#include "DDG4/Geant4Random.h" #include "DDG4/DDG4Dict.h" @@ -33,17 +34,17 @@ using namespace DD4hep::Simulation; namespace DD4hep { namespace Simulation { -#define ACTIONHANDLE(x) \ - struct x##Handle { \ - Geant4##x* action; \ +#define ACTIONHANDLE(x) \ + struct x##Handle { \ + Geant4##x* action; \ x##Handle(Geant4##x* a) : action(a) { if ( action ) action->addRef();} \ x##Handle(const x##Handle& h) : action(h.action) { if ( action ) action->addRef();} \ ~x##Handle() { if ( action) action->release(); } \ Geant4##x* release() { Geant4##x* tmp = action; action=0; return tmp; } \ - operator Geant4##x* () const { return action; } \ - Geant4##x* operator->() const { return action; } \ - Geant4##x* get() const { return action; } \ - } + operator Geant4##x* () const { return action; } \ + Geant4##x* operator->() const { return action; } \ + Geant4##x* get() const { return action; } \ + } ACTIONHANDLE(Filter); ACTIONHANDLE(Action); @@ -68,109 +69,109 @@ namespace DD4hep { ACTIONHANDLE(SensDetActionSequence); struct PropertyResult { - string data; - int status; - PropertyResult() : status(0) {} - PropertyResult(const string& d, int s) : data(d), status(s) {} + string data; + int status; + PropertyResult() : status(0) {} + PropertyResult(const string& d, int s) : data(d), status(s) {} PropertyResult(const PropertyResult& c) : data(c.data), status(c.status) {} - ~PropertyResult() {} - }; + ~PropertyResult() {} + }; struct Geant4ActionCreation { - template <typename H,typename T> static H cr(KernelHandle& kernel, const string& name_type) { - T action(*kernel.get(),name_type); - H handle(action.get()); - return handle; - } - static ActionHandle createAction(KernelHandle& kernel, const string& name_type) - { return cr<ActionHandle,Setup::Action>(kernel,name_type); } - static FilterHandle createFilter(KernelHandle& kernel, const string& name_type) - { return cr<FilterHandle,Setup::Filter>(kernel,name_type); } - static PhaseActionHandle createPhaseAction(KernelHandle& kernel, const string& name_type) - { return cr<PhaseActionHandle,Setup::PhaseAction>(kernel,name_type); } - static PhysicsListHandle createPhysicsList(KernelHandle& kernel, const string& name_type) - { return cr<PhysicsListHandle,Setup::PhysicsList>(kernel,name_type); } - static RunActionHandle createRunAction(KernelHandle& kernel, const string& name_type) - { return cr<RunActionHandle,Setup::RunAction>(kernel,name_type); } - static EventActionHandle createEventAction(KernelHandle& kernel, const string& name_type) - { return cr<EventActionHandle,Setup::EventAction>(kernel,name_type); } - static TrackingActionHandle createTrackingAction(KernelHandle& kernel, const string& name_type) - { return cr<TrackingActionHandle,Setup::TrackAction>(kernel,name_type); } - static SteppingActionHandle createSteppingAction(KernelHandle& kernel, const string& name_type) - { return cr<SteppingActionHandle,Setup::StepAction>(kernel,name_type); } - static StackingActionHandle createStackingAction(KernelHandle& kernel, const string& name_type) - { return cr<StackingActionHandle,Setup::StackAction>(kernel,name_type); } - static GeneratorActionHandle createGeneratorAction(KernelHandle& kernel, const string& name_type) - { return cr<GeneratorActionHandle,Setup::GenAction>(kernel,name_type); } - static SensitiveHandle createSensitive(KernelHandle& kernel, const string& name_type, const string& detector) - { return SensitiveHandle(Setup::Sensitive(*kernel.get(),name_type,detector).get()); } - static SensDetActionSequenceHandle createSensDetSequence(KernelHandle& kernel, const string& name_type) - { return cr<SensDetActionSequenceHandle,Setup::SensitiveSeq>(kernel,name_type); } - - static Geant4Action* toAction(Geant4Filter* f) { return f; } - static Geant4Action* toAction(Geant4Action* f) { return f; } - static Geant4Action* toAction(Geant4PhaseAction* f) { return f; } - static Geant4Action* toAction(Geant4Sensitive* f) { return f; } - static Geant4Action* toAction(Geant4PhysicsList* f) { return f; } - static Geant4Action* toAction(Geant4RunAction* f) { return f; } - static Geant4Action* toAction(Geant4EventAction* f) { return f; } - static Geant4Action* toAction(Geant4TrackingAction* f) { return f; } - static Geant4Action* toAction(Geant4SteppingAction* f) { return f; } - static Geant4Action* toAction(Geant4StackingAction* f) { return f; } - static Geant4Action* toAction(Geant4GeneratorAction* f) { return f; } - static Geant4Action* toAction(Geant4GeneratorActionSequence* f) { return f; } - static Geant4Action* toAction(Geant4RunActionSequence* f) { return f; } - static Geant4Action* toAction(Geant4EventActionSequence* f) { return f; } - static Geant4Action* toAction(Geant4TrackingActionSequence* f) { return f; } - static Geant4Action* toAction(Geant4SteppingActionSequence* f) { return f; } - static Geant4Action* toAction(Geant4StackingActionSequence* f) { return f; } - static Geant4Action* toAction(Geant4PhysicsListActionSequence* f){ return f; } - static Geant4Action* toAction(Geant4SensDetActionSequence* f) { return f; } - - static Geant4Action* toAction(FilterHandle f) { return f.action; } - static Geant4Action* toAction(ActionHandle f) { return f.action; } - static Geant4Action* toAction(PhaseActionHandle f) { return f.action; } - static Geant4Action* toAction(SensitiveHandle f) { return f.action; } - static Geant4Action* toAction(PhysicsListHandle f) { return f.action; } - static Geant4Action* toAction(RunActionHandle f) { return f.action; } - static Geant4Action* toAction(EventActionHandle f) { return f.action; } - static Geant4Action* toAction(TrackingActionHandle f) { return f.action; } - static Geant4Action* toAction(SteppingActionHandle f) { return f.action; } - static Geant4Action* toAction(StackingActionHandle f) { return f.action; } - static Geant4Action* toAction(GeneratorActionHandle f) { return f.action; } - static Geant4Action* toAction(GeneratorActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(RunActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(EventActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(TrackingActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(SteppingActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(StackingActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(PhysicsListActionSequenceHandle f) { return f.action; } - static Geant4Action* toAction(SensDetActionSequenceHandle f) { return f.action; } - static PropertyResult getProperty(Geant4Action* action, const string& name) { - if ( action->hasProperty(name) ) { + template <typename H,typename T> static H cr(KernelHandle& kernel, const string& name_type) { + T action(*kernel.get(),name_type); + H handle(action.get()); + return handle; + } + static ActionHandle createAction(KernelHandle& kernel, const string& name_type) + { return cr<ActionHandle,Setup::Action>(kernel,name_type); } + static FilterHandle createFilter(KernelHandle& kernel, const string& name_type) + { return cr<FilterHandle,Setup::Filter>(kernel,name_type); } + static PhaseActionHandle createPhaseAction(KernelHandle& kernel, const string& name_type) + { return cr<PhaseActionHandle,Setup::PhaseAction>(kernel,name_type); } + static PhysicsListHandle createPhysicsList(KernelHandle& kernel, const string& name_type) + { return cr<PhysicsListHandle,Setup::PhysicsList>(kernel,name_type); } + static RunActionHandle createRunAction(KernelHandle& kernel, const string& name_type) + { return cr<RunActionHandle,Setup::RunAction>(kernel,name_type); } + static EventActionHandle createEventAction(KernelHandle& kernel, const string& name_type) + { return cr<EventActionHandle,Setup::EventAction>(kernel,name_type); } + static TrackingActionHandle createTrackingAction(KernelHandle& kernel, const string& name_type) + { return cr<TrackingActionHandle,Setup::TrackAction>(kernel,name_type); } + static SteppingActionHandle createSteppingAction(KernelHandle& kernel, const string& name_type) + { return cr<SteppingActionHandle,Setup::StepAction>(kernel,name_type); } + static StackingActionHandle createStackingAction(KernelHandle& kernel, const string& name_type) + { return cr<StackingActionHandle,Setup::StackAction>(kernel,name_type); } + static GeneratorActionHandle createGeneratorAction(KernelHandle& kernel, const string& name_type) + { return cr<GeneratorActionHandle,Setup::GenAction>(kernel,name_type); } + static SensitiveHandle createSensitive(KernelHandle& kernel, const string& name_type, const string& detector) + { return SensitiveHandle(Setup::Sensitive(*kernel.get(),name_type,detector).get()); } + static SensDetActionSequenceHandle createSensDetSequence(KernelHandle& kernel, const string& name_type) + { return cr<SensDetActionSequenceHandle,Setup::SensitiveSeq>(kernel,name_type); } + + static Geant4Action* toAction(Geant4Filter* f) { return f; } + static Geant4Action* toAction(Geant4Action* f) { return f; } + static Geant4Action* toAction(Geant4PhaseAction* f) { return f; } + static Geant4Action* toAction(Geant4Sensitive* f) { return f; } + static Geant4Action* toAction(Geant4PhysicsList* f) { return f; } + static Geant4Action* toAction(Geant4RunAction* f) { return f; } + static Geant4Action* toAction(Geant4EventAction* f) { return f; } + static Geant4Action* toAction(Geant4TrackingAction* f) { return f; } + static Geant4Action* toAction(Geant4SteppingAction* f) { return f; } + static Geant4Action* toAction(Geant4StackingAction* f) { return f; } + static Geant4Action* toAction(Geant4GeneratorAction* f) { return f; } + static Geant4Action* toAction(Geant4GeneratorActionSequence* f) { return f; } + static Geant4Action* toAction(Geant4RunActionSequence* f) { return f; } + static Geant4Action* toAction(Geant4EventActionSequence* f) { return f; } + static Geant4Action* toAction(Geant4TrackingActionSequence* f) { return f; } + static Geant4Action* toAction(Geant4SteppingActionSequence* f) { return f; } + static Geant4Action* toAction(Geant4StackingActionSequence* f) { return f; } + static Geant4Action* toAction(Geant4PhysicsListActionSequence* f){ return f; } + static Geant4Action* toAction(Geant4SensDetActionSequence* f) { return f; } + + static Geant4Action* toAction(FilterHandle f) { return f.action; } + static Geant4Action* toAction(ActionHandle f) { return f.action; } + static Geant4Action* toAction(PhaseActionHandle f) { return f.action; } + static Geant4Action* toAction(SensitiveHandle f) { return f.action; } + static Geant4Action* toAction(PhysicsListHandle f) { return f.action; } + static Geant4Action* toAction(RunActionHandle f) { return f.action; } + static Geant4Action* toAction(EventActionHandle f) { return f.action; } + static Geant4Action* toAction(TrackingActionHandle f) { return f.action; } + static Geant4Action* toAction(SteppingActionHandle f) { return f.action; } + static Geant4Action* toAction(StackingActionHandle f) { return f.action; } + static Geant4Action* toAction(GeneratorActionHandle f) { return f.action; } + static Geant4Action* toAction(GeneratorActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(RunActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(EventActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(TrackingActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(SteppingActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(StackingActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(PhysicsListActionSequenceHandle f) { return f.action; } + static Geant4Action* toAction(SensDetActionSequenceHandle f) { return f.action; } + static PropertyResult getProperty(Geant4Action* action, const string& name) { + if ( action->hasProperty(name) ) { return PropertyResult(action->property(name).str(),1); - } - return PropertyResult("",0); - } + } + return PropertyResult("",0); + } static int setProperty(Geant4Action* action, const string& name, const string& value) { - if ( action->hasProperty(name) ) { - action->property(name).str(value); - return 1; - } - return 0; + if ( action->hasProperty(name) ) { + action->property(name).str(value); + return 1; + } + return 0; } static PropertyResult getPropertyKernel(Geant4Kernel* kernel, const string& name) { - if ( kernel->hasProperty(name) ) { - return PropertyResult(kernel->property(name).str(),1); - } - return PropertyResult("",0); + if ( kernel->hasProperty(name) ) { + return PropertyResult(kernel->property(name).str(),1); + } + return PropertyResult("",0); } static int setPropertyKernel(Geant4Kernel* kernel, const string& name, const string& value) { - if ( kernel->hasProperty(name) ) { - kernel->property(name).str(value); - return 1; - } - return 0; + if ( kernel->hasProperty(name) ) { + kernel->property(name).str(value); + return 1; + } + return 0; } }; } @@ -241,6 +242,7 @@ namespace { #pragma link C++ class Geant4Kernel::PhaseSelector; #pragma link C++ class Geant4Context; #pragma link C++ class KernelHandle; +#pragma link C++ class Geant4Random; #pragma link C++ class Geant4RunActionSequence; #pragma link C++ class Geant4RunAction; diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp index d4d72c1160bb3e6def6eb2f590650806f7407c93..4a9c59c9da7826010d2d9e568685d5e9f7ed2dca 100644 --- a/DDG4/src/Geant4Exec.cpp +++ b/DDG4/src/Geant4Exec.cpp @@ -51,7 +51,6 @@ namespace DD4hep { namespace { Geant4Context* s_globalContext = 0; - Geant4Random* s_globalRandom = 0; } Geant4Context* ddg4_globalContext() { @@ -77,24 +76,24 @@ namespace DD4hep { void _aquire(T* s) { InstanceCount::increment(this); m_sequence = s; - m_sequence->addRef(); + if ( m_sequence ) m_sequence->addRef(); } void _release() { releasePtr(m_sequence); InstanceCount::decrement(this); } Geant4Context* context() const { - return m_activeContext; + return m_activeContext; } Geant4Kernel& kernel() const { - return context()->kernel(); + return context()->kernel(); } void setContextToClients() { - (Geant4Action::ContextUpdate(m_activeContext))(m_sequence); + if ( m_sequence ) (Geant4Action::ContextUpdate(m_activeContext))(m_sequence); } void releaseContextFromClients() { - Geant4Action::ContextUpdate(0)(m_sequence); + if ( m_sequence ) Geant4Action::ContextUpdate(0)(m_sequence); } void createClientContext(const G4Run* run) { Geant4Run* r = new Geant4Run(run); @@ -110,7 +109,7 @@ namespace DD4hep { } } void createClientContext(const G4Event* evt) { - Geant4Event* e = new Geant4Event(evt,s_globalRandom); + Geant4Event* e = new Geant4Event(evt,Geant4Random::instance()); m_activeContext->setEvent(e); setContextToClients(); } @@ -327,8 +326,13 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine); Geometry::LCDD& lcdd = kernel.lcdd(); Geant4Context* ctx = s_globalContext = new Geant4Context(&kernel); - // For now do this: - /* Geant4Random* rnd = */ s_globalRandom = new Geant4Random(); + Geant4Random* rndm = Geant4Random::instance(false); + + if ( !rndm ) { + rndm = new Geant4Random(ctx, "Geant4Random"); + /// Initialize the engine etc. + rndm->initialize(); + } kernel.executePhase("configure",0); @@ -417,7 +421,7 @@ int Geant4Exec::run(Geant4Kernel& kernel) { Geant4Call* c = dynamic_cast<Geant4Call*>(ui); if ( c ) { (*c)(0); - kernel.executePhase("stop",0); + kernel.executePhase("stop",0); return 1; } ui->except("++ Geant4Exec: Failed to start UI interface."); diff --git a/DDG4/src/Geant4GeneratorWrapper.cpp b/DDG4/src/Geant4GeneratorWrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4016a367cc54b947599ba8eaf1c797d5f9e6308a --- /dev/null +++ b/DDG4/src/Geant4GeneratorWrapper.cpp @@ -0,0 +1,87 @@ +// $Id$ +//========================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DDG4/Geant4GeneratorWrapper.h" + +#include "DD4hep/InstanceCount.h" +#include "DD4hep/Plugins.h" +#include "DD4hep/Printout.h" +#include "DDG4/Geant4Context.h" +//#include "DDG4/Geant4Primary.h" +#include "DDG4/Geant4InputHandling.h" + +// Geant4 include files +#include "G4Event.hh" +#include "G4PrimaryVertex.hh" +//#include "G4PrimaryParticle.hh" +#include "G4VPrimaryGenerator.hh" + +// C/C++ include files +#include <stdexcept> +#include <set> + +using namespace DD4hep::Simulation; +using namespace std; + +/// Standard constructor +Geant4GeneratorWrapper::Geant4GeneratorWrapper(Geant4Context* ctxt, const string& nam) + : Geant4GeneratorAction(ctxt,nam), m_generator(0) +{ + declareProperty("Uses", m_generatorType); + declareProperty("Mask", m_mask = 1); + InstanceCount::increment(this); +} + +/// Default destructor +Geant4GeneratorWrapper::~Geant4GeneratorWrapper() { + deletePtr(m_generator); + InstanceCount::decrement(this); +} + +G4VPrimaryGenerator* Geant4GeneratorWrapper::generator() { + if ( 0 == m_generator ) { + m_generator = PluginService::Create<G4VPrimaryGenerator*>(m_generatorType); + if ( 0 == m_generator ) { + PluginDebug dbg; + m_generator = PluginService::Create<G4VPrimaryGenerator*>(m_generatorType); + if ( !m_generator ) { + throw runtime_error("Geant4GeneratorWrapper: FATAL Failed to " + "create G4VPrimaryGenerator of type " + m_generatorType + "."); + } + } + } + return m_generator; +} + +/// Event generation action callback +void Geant4GeneratorWrapper::operator()(G4Event* event) { + Geant4PrimaryEvent* prim = context()->event().extension<Geant4PrimaryEvent>(); + set<G4PrimaryVertex*> primaries; + + /// Collect all existing interactions (primary vertices) + for(G4PrimaryVertex* v=event->GetPrimaryVertex(); v; v=v->GetNext()) + primaries.insert(v); + + // Now generate the new interaction + generator()->GeneratePrimaryVertex(event); + + /// Add all the missing interactions (primary vertices) to the primary event record. + for(G4PrimaryVertex* v=event->GetPrimaryVertex(); v; v=v->GetNext()) { + if ( primaries.find(v) == primaries.end() ) { + Geant4PrimaryInteraction* inter = createPrimary(m_mask, v); + prim->add(m_mask, inter); + } + } +} diff --git a/DDG4/src/Geant4InputHandling.cpp b/DDG4/src/Geant4InputHandling.cpp index 280b66d8cdc11c2aa97522f13a3da42720b95dcd..5d0be177d391ef809a90a6fe843bf9768e550e2c 100644 --- a/DDG4/src/Geant4InputHandling.cpp +++ b/DDG4/src/Geant4InputHandling.cpp @@ -37,6 +37,90 @@ using namespace DD4hep::Simulation; typedef ReferenceBitMask<int> PropertyMask; + +/// Create a vertex object from the Geant4 primary vertex +Geant4Vertex* DD4hep::Simulation::createPrimary(const G4PrimaryVertex* g4) { + Geant4Vertex* v = new Geant4Vertex(); + v->x = g4->GetX0(); + v->y = g4->GetY0(); + v->z = g4->GetZ0(); + v->time = g4->GetT0(); + return v; +} + +/// Create a particle object from the Geant4 primary particle +Geant4Particle* +DD4hep::Simulation::createPrimary(int particle_id, + const Geant4Vertex* v, + const G4PrimaryParticle* g4p) +{ + Geant4ParticleHandle p = new Geant4Particle(); + p->id = particle_id; + p->reason = 0; + p->pdgID = g4p->GetPDGcode(); + p->psx = g4p->GetPx(); + p->psy = g4p->GetPy(); + p->psz = g4p->GetPz(); + p->time = g4p->GetProperTime(); + p->properTime = g4p->GetProperTime(); + p->vsx = v->x; + p->vsy = v->y; + p->vsz = v->z; + p->vex = v->x; + p->vey = v->y; + p->vez = v->z; + //p->definition = g4p->GetG4code(); + //p->process = 0; + p->spin[0] = 0; + p->spin[1] = 0; + p->spin[2] = 0; + p->colorFlow[0] = 0; + p->colorFlow[0] = 0; + p->mass = g4p->GetMass(); + p->charge = g4p->GetCharge(); + PropertyMask status(p->status); + status.set(G4PARTICLE_GEN_STABLE); + return p; +} + +/// Helper to recursively collect interaction data +void collectPrimaries(Geant4PrimaryInteraction* interaction, + Geant4Vertex* particle_origine, + const G4PrimaryParticle* gp) +{ + int pid = int(interaction->particles.size()); + Geant4Particle* p = createPrimary(pid,particle_origine,gp); + G4PrimaryParticle* dau = gp->GetDaughter(); + int mask = interaction->mask; + + interaction->particles.insert(make_pair(p->id,p)); + p->mask = mask; + particle_origine->out.insert(p->id); + if ( dau ) { + Geant4Vertex* dv = new Geant4Vertex(*particle_origine); + int vid = int(interaction->vertices.size()); + dv->mask = mask; + dv->in.insert(p->id); + interaction->vertices.insert(make_pair(vid,dv)); + for(; dau; dau = dau->GetNext()) + collectPrimaries(interaction, dv, dau); + } +} + +/// Import a Geant4 interaction defined by a primary vertex into a DDG4 interaction record +Geant4PrimaryInteraction* DD4hep::Simulation::createPrimary(int mask, const G4PrimaryVertex* gv) { + Geant4PrimaryInteraction* interaction = new Geant4PrimaryInteraction(); + Geant4Vertex* v = createPrimary(gv); + int vid = int(interaction->vertices.size()); + interaction->locked = true; + interaction->mask = mask; + v->mask = mask; + interaction->vertices.insert(make_pair(vid,v)); + for (G4PrimaryParticle *gp = gv->GetPrimary(); gp; gp = gp->GetNext() ) + collectPrimaries(interaction, v, gp); + return interaction; +} + /// Initialize the generation of one event int DD4hep::Simulation::generationInitialization(const Geant4Action* /* caller */, const Geant4Context* context) @@ -150,7 +234,7 @@ int DD4hep::Simulation::mergeInteractions(const Geant4Action* caller, } /// Boost particles of one interaction identified by its mask -int DD4hep::Simulation::boostInteraction(const Geant4Action* /* caller */, +int DD4hep::Simulation::boostInteraction(const Geant4Action* caller, Geant4PrimaryEvent::Interaction* inter, double alpha) { @@ -160,7 +244,11 @@ int DD4hep::Simulation::boostInteraction(const Geant4Action* /* caller */, double gamma = std::sqrt(1 + SQR(tan(alpha))); double betagamma = std::tan(alpha); - if ( alpha != 0.0 ) { + if ( inter->locked ) { + caller->abortRun("Locked interactions may not be boosted!", + "Cannot boost interactions with a native G4 primary record!"); + } + else if ( alpha != 0.0 ) { // Now move begin and end-vertex of all primary vertices accordingly for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv) { Geant4Vertex* v = (*iv).second; @@ -202,13 +290,18 @@ int DD4hep::Simulation::boostInteraction(const Geant4Action* /* caller */, } /// Smear the primary vertex of an interaction -int DD4hep::Simulation::smearInteraction(const Geant4Action* /* caller */, +int DD4hep::Simulation::smearInteraction(const Geant4Action* caller, Geant4PrimaryEvent::Interaction* inter, double dx, double dy, double dz, double dt) { Geant4PrimaryEvent::Interaction::VertexMap::iterator iv; Geant4PrimaryEvent::Interaction::ParticleMap::iterator ip; + if ( inter->locked ) { + caller->abortRun("Locked interactions may not be smeared!", + "Cannot smear interactions with a native G4 primary record!"); + } + // Now move begin and end-vertex of all primary vertices accordingly for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv) { Geant4Vertex* v = (*iv).second; @@ -319,38 +412,45 @@ int DD4hep::Simulation::generatePrimaries(const Geant4Action* caller, set<int> visited; char text[64]; - Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend; - for(Interaction::VertexMap::const_iterator iend=vm.end(),i=vm.begin(); i!=iend; ++i) { - int num_part = 0; - Geant4Vertex* v = (*i).second; - G4PrimaryVertex* v4 = new G4PrimaryVertex(v->x,v->y,v->z,v->time); - event->AddPrimaryVertex(v4); - caller->print("+++++ G4PrimaryVertex at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]", - v->x/CLHEP::mm,v->y/CLHEP::mm,v->z/CLHEP::mm,v->time/CLHEP::ns); - for(Geant4Vertex::Particles::const_iterator ip=v->out.begin(); ip!=v->out.end(); ++ip) { - Geant4ParticleHandle p = pm[*ip]; - if ( p->daughters.size() > 0 ) { - PropertyMask mask(p->reason); - mask.set(G4PARTICLE_HAS_SECONDARIES); - } - if ( p->parents.size() == 0 ) { - Primaries relevant = getRelevant(visited,prim,pm,p); - for(Primaries::const_iterator j=relevant.begin(); j!= relevant.end(); ++j) { - Geant4ParticleHandle r = (*j).first; - G4PrimaryParticle* p4 = (*j).second; - PropertyMask reason(r->reason); - reason.set(G4PARTICLE_PRIMARY); - v4->SetPrimary(p4); - ::snprintf(text,sizeof(text),"-> G4Primary[%3d]",num_part); - r.dumpWithMomentum(caller->outputLevel()-1,caller->name(),text); - ++num_part; + if ( !interaction->locked ) { + caller->abortRun("Locked interactions may not be used to generate primaries!", + "Cannot handle a native G4 primary record!"); + return 0; + } + else { + Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend; + for(Interaction::VertexMap::const_iterator iend=vm.end(),i=vm.begin(); i!=iend; ++i) { + int num_part = 0; + Geant4Vertex* v = (*i).second; + G4PrimaryVertex* v4 = new G4PrimaryVertex(v->x,v->y,v->z,v->time); + event->AddPrimaryVertex(v4); + caller->print("+++++ G4PrimaryVertex at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]", + v->x/CLHEP::mm,v->y/CLHEP::mm,v->z/CLHEP::mm,v->time/CLHEP::ns); + for(Geant4Vertex::Particles::const_iterator ip=v->out.begin(); ip!=v->out.end(); ++ip) { + Geant4ParticleHandle p = pm[*ip]; + if ( p->daughters.size() > 0 ) { + PropertyMask mask(p->reason); + mask.set(G4PARTICLE_HAS_SECONDARIES); + } + if ( p->parents.size() == 0 ) { + Primaries relevant = getRelevant(visited,prim,pm,p); + for(Primaries::const_iterator j=relevant.begin(); j!= relevant.end(); ++j) { + Geant4ParticleHandle r = (*j).first; + G4PrimaryParticle* p4 = (*j).second; + PropertyMask reason(r->reason); + reason.set(G4PARTICLE_PRIMARY); + v4->SetPrimary(p4); + ::snprintf(text,sizeof(text),"-> G4Primary[%3d]",num_part); + r.dumpWithMomentum(caller->outputLevel()-1,caller->name(),text); + ++num_part; + } } } } - } - for(map<int,G4PrimaryParticle*>::iterator i=prim.begin(); i!=prim.end(); ++i) { - Geant4ParticleHandle p = pm[(*i).first]; - primaries->primaryMap[(*i).second] = p->addRef(); + for(map<int,G4PrimaryParticle*>::iterator i=prim.begin(); i!=prim.end(); ++i) { + Geant4ParticleHandle p = pm[(*i).first]; + primaries->primaryMap[(*i).second] = p->addRef(); + } } return 1; } diff --git a/DDG4/src/Geant4InteractionVertexBoost.cpp b/DDG4/src/Geant4InteractionVertexBoost.cpp index 9b3e6b112bb481dca672c4b2c01b96122d425179..369e6e12d9bf98766fcf9a92a6559be2c7b60b6e 100644 --- a/DDG4/src/Geant4InteractionVertexBoost.cpp +++ b/DDG4/src/Geant4InteractionVertexBoost.cpp @@ -26,7 +26,7 @@ Geant4InteractionVertexBoost::Geant4InteractionVertexBoost(Geant4Context* ctxt, { InstanceCount::increment(this); declareProperty("Angle", m_angle = 0); - declareProperty("Mask", m_mask = 0); + declareProperty("Mask", m_mask = 1); m_needsControl = true; } @@ -35,11 +35,26 @@ Geant4InteractionVertexBoost::~Geant4InteractionVertexBoost() { InstanceCount::decrement(this); } -/// Callback to generate primary particles -void Geant4InteractionVertexBoost::operator()(G4Event*) { - Geant4PrimaryEvent::Interaction* inter = - context()->event().extension<Geant4PrimaryEvent>()->get(m_mask); +/// Action to boost one single interaction according to the properties +void Geant4InteractionVertexBoost::boost(Interaction* inter) const { if ( inter ) { boostInteraction(this, inter, m_angle); + return; + } + print("+++ No interaction of type %d present.",m_mask); +} + +/// Callback to generate primary particles +void Geant4InteractionVertexBoost::operator()(G4Event*) { + typedef std::vector<Geant4PrimaryInteraction*> _I; + Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>(); + + if ( m_mask >= 0 ) { + Interaction* inter = evt->get(m_mask); + boost(inter); + return; } + _I interactions = evt->interactions(); + for(_I::iterator i=interactions.begin(); i != interactions.end(); ++i) + boost(*i); } diff --git a/DDG4/src/Geant4InteractionVertexSmear.cpp b/DDG4/src/Geant4InteractionVertexSmear.cpp index 00254a5d784481f9255f3160a79bf6b86be69344..396f35f9633dd0bd6a73b7e1e1f05634d06ad9ca 100644 --- a/DDG4/src/Geant4InteractionVertexSmear.cpp +++ b/DDG4/src/Geant4InteractionVertexSmear.cpp @@ -32,7 +32,7 @@ Geant4InteractionVertexSmear::Geant4InteractionVertexSmear(Geant4Context* ctxt, InstanceCount::increment(this); declareProperty("Offset", m_offset); declareProperty("Sigma", m_sigma); - declareProperty("Mask", m_mask = 0); + declareProperty("Mask", m_mask = 1); m_needsControl = true; } @@ -41,13 +41,10 @@ Geant4InteractionVertexSmear::~Geant4InteractionVertexSmear() { InstanceCount::decrement(this); } -/// Callback to generate primary particles -void Geant4InteractionVertexSmear::operator()(G4Event*) { - typedef Geant4PrimaryEvent::Interaction Interaction; - Geant4Random& rndm = context()->event().random(); - Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>(); - Interaction* inter = evt->get(m_mask); +/// Action to smear one single interaction according to the properties +void Geant4InteractionVertexSmear::smear(Interaction* inter) const { + Geant4Random& rndm = context()->event().random(); if ( inter ) { double dx = rndm.gauss(m_offset.x(),m_sigma.x()); double dy = rndm.gauss(m_offset.y(),m_sigma.y()); @@ -57,8 +54,22 @@ void Geant4InteractionVertexSmear::operator()(G4Event*) { "by (%+.2e mm, %+.2e mm, %+.2e mm, %+.2e ns)", m_mask,int(inter->vertices.size()),int(inter->particles.size()),dx,dy,dz,dt); smearInteraction(this,inter,dx,dy,dz,dt); + return; } - else { - print("+++ No interaction of type %d present.",m_mask); + print("+++ No interaction of type %d present.",m_mask); +} + +/// Callback to generate primary particles +void Geant4InteractionVertexSmear::operator()(G4Event*) { + typedef std::vector<Geant4PrimaryInteraction*> _I; + Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>(); + + if ( m_mask >= 0 ) { + Interaction* inter = evt->get(m_mask); + smear(inter); + return; } + _I interactions = evt->interactions(); + for(_I::iterator i=interactions.begin(); i != interactions.end(); ++i) + smear(*i); } diff --git a/DDG4/src/Geant4ParticleGun.cpp b/DDG4/src/Geant4ParticleGun.cpp index e4d0be7b626c53058ceb9e9fcedf5c048ede1f0c..40bb01e93b8ac0b2476382db3ccd94166acbd57b 100644 --- a/DDG4/src/Geant4ParticleGun.cpp +++ b/DDG4/src/Geant4ParticleGun.cpp @@ -98,13 +98,14 @@ void Geant4ParticleGun::operator()(G4Event* event) { Geant4Vertex* vtx = new Geant4Vertex(); inter->vertices.insert(make_pair(m_mask,vtx)); prim->add(m_mask, inter); - + vtx->mask = m_mask; vtx->x = m_position.X(); vtx->y = m_position.Y(); vtx->z = m_position.Z(); for(int i=0; i<m_multiplicity; ++i) { Geant4ParticleHandle p = new Geant4Particle(i); p->reason = 0; + p->mask = m_mask; p->pdgID = m_particle->GetPDGEncoding(); p->psx = m_direction.X()*m_energy; p->psy = m_direction.Y()*m_energy; diff --git a/DDG4/src/Geant4Plugins.cpp b/DDG4/src/Geant4Plugins.cpp index ec4513de11dbdbe6d6fce2106aa2ec87ede1ac20..7d58fd1a1cc5bbfd484f0400cad3fe41d851fb97 100644 --- a/DDG4/src/Geant4Plugins.cpp +++ b/DDG4/src/Geant4Plugins.cpp @@ -41,6 +41,7 @@ DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4MagIntegratorStepper*, (G4Mag_EqRhs*)) DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4Mag_EqRhs*, (G4MagneticField*)) DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4VProcess*, ()) DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4VPhysicsConstructor*, ()) +DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4VPrimaryGenerator*, ()) DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4ParticleDefinition*, ()) DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(G4VUserPhysicsList*, (DD4hep::Simulation::Geant4PhysicsListActionSequence*,int)) DD4HEP_IMPLEMENT_PLUGIN_REGISTRY(DD4hep::Simulation::Geant4EventReader*, (std::string)) diff --git a/DDG4/src/Geant4Primary.cpp b/DDG4/src/Geant4Primary.cpp index 1f4773bfbf822ee030feb5fbb05057bb38282598..652c5db3787460149bb4ceeb7a51a7e6d62a1c8f 100644 --- a/DDG4/src/Geant4Primary.cpp +++ b/DDG4/src/Geant4Primary.cpp @@ -35,13 +35,13 @@ Geant4PrimaryMap::~Geant4PrimaryMap() { /// Default constructor Geant4PrimaryInteraction::Geant4PrimaryInteraction() - : mask(0), next_particle_identifier(-1) + : mask(0), locked(0), next_particle_identifier(-1) { } /// Copy constructor Geant4PrimaryInteraction::Geant4PrimaryInteraction(const Geant4PrimaryInteraction&) - : mask(0), next_particle_identifier(-1) + : mask(0), locked(0), next_particle_identifier(-1) { } diff --git a/DDG4/src/Geant4Random.cpp b/DDG4/src/Geant4Random.cpp index da0306366ac0c7968d71488f099e2265c8fcdd73..bdb7aee1142de78a532b208120f59fbf259d3951 100644 --- a/DDG4/src/Geant4Random.cpp +++ b/DDG4/src/Geant4Random.cpp @@ -17,6 +17,9 @@ #include "DD4hep/InstanceCount.h" #include "DDG4/Geant4Random.h" +#include "CLHEP/Random/EngineFactory.h" +#include "CLHEP/Random/Random.h" + // ROOT include files #include "TRandom1.h" @@ -26,63 +29,266 @@ using namespace std; using namespace DD4hep::Simulation; +namespace CLHEP { + unsigned long crc32ul(const std::string& s); +} + +namespace { + + /// Helper class to redirect calls to gRandon to Geant4Random + class RNDM : public TRandom { + /// Reference to the generator object + Geant4Random* m_generator; + /// Reference to HepRandomEngine + CLHEP::HepRandomEngine* m_engine; + + public: + /// Initializing constructor + RNDM(Geant4Random* r) : TRandom(), m_generator(r) { + m_engine = m_generator->engine(); + } + /// Default destructor + virtual ~RNDM() { } + /// Set new seed + virtual void SetSeed(UInt_t seed=0) { + fSeed = seed; + m_generator->setSeed((long)seed); + } + /// Single shot random number creation + virtual Double_t Rndm(Int_t) { + return m_engine->flat(); + } + /// Return an array of n random numbers uniformly distributed in ]0,1]. + virtual void RndmArray(Int_t size, Float_t *array) { + for (Int_t i=0;i<size;i++) array[i] = m_engine->flat(); + } + /// Return an array of n random numbers uniformly distributed in ]0,1]. + virtual void RndmArray(Int_t size, Double_t *array) { + m_engine->flatArray(size,array); + } + }; + static Geant4Random* s_instance = 0; +} + /// Default constructor -Geant4Random::Geant4Random() { - if ( 0 == gRandom ) gRandom = new TRandom1(); +Geant4Random::Geant4Random(Geant4Context* ctxt, const std::string& nam) + : Geant4Action(ctxt,nam), m_engine(0), m_rootRandom(0), m_rootOLD(0), + m_inited(false) +{ + declareProperty("File", m_file=""); + declareProperty("Type", m_engineType=""); + declareProperty("Seed", m_seed = 123456789); + declareProperty("Luxury", m_luxury = 1); + declareProperty("Replace_gRandom", m_replace = true); + // Default: static Geant4 random engine. + m_engine = CLHEP::HepRandom::getTheEngine(); InstanceCount::increment(this); } /// Default destructor Geant4Random::~Geant4Random() { + if ( s_instance == this ) s_instance = 0; + if ( !m_engineType.empty() ) deletePtr(m_engine); + if ( m_rootRandom == gRandom ) gRandom = m_rootOLD; + deletePtr(m_rootRandom); InstanceCount::decrement(this); } -void Geant4Random::circle(double &x, double &y, double r) { - gRandom->Circle(x,y,r); +/// Access the main Geant4 random generator instance. Must be created before used! +Geant4Random* Geant4Random::instance(bool throw_exception) { + if ( !s_instance && throw_exception ) { + throw runtime_error("No global random number generator defined!"); + } + return s_instance; } -// -double Geant4Random::exp(double tau) { - return gRandom->Exp(tau); +/// 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; } -// -double Geant4Random::gauss(double mean, double sigma) { - return gRandom->Gaus(mean,sigma); +#include "CLHEP/Random/DualRand.h" +#include "CLHEP/Random/JamesRandom.h" +#include "CLHEP/Random/MTwistEngine.h" +#include "CLHEP/Random/RanecuEngine.h" +#include "CLHEP/Random/Ranlux64Engine.h" +#include "CLHEP/Random/RanluxEngine.h" +#include "CLHEP/Random/RanshiEngine.h" +#include "CLHEP/Random/NonRandomEngine.h" + +/// Initialize the instance. +void Geant4Random::initialize() { + if ( !m_file.empty() ) { + ifstream in(m_file); + m_engine = CLHEP::EngineFactory::newEngine(in); + if ( !m_engine ) { + except("Failed to create CLHEP random engine from file:%s.",m_file.c_str()); + } + m_seed = m_engine->getSeed(); + } + else if ( !m_engineType.empty() ) { + /// Create new engine if a type is specified + if ( m_engineType == CLHEP::HepJamesRandom::engineName() ) + m_engine = new CLHEP::HepJamesRandom(); + else if ( m_engineType == CLHEP::RanecuEngine::engineName() ) + m_engine = new CLHEP::RanecuEngine(); + else if ( m_engineType == CLHEP::Ranlux64Engine::engineName() ) + m_engine = new CLHEP::Ranlux64Engine(); + else if ( m_engineType == CLHEP::MTwistEngine::engineName() ) + m_engine = new CLHEP::MTwistEngine(); + else if ( m_engineType == CLHEP::DualRand::engineName() ) + m_engine = new CLHEP::DualRand(); + else if ( m_engineType == CLHEP::RanluxEngine::engineName() ) + m_engine = new CLHEP::RanluxEngine(); + else if ( m_engineType == CLHEP::RanshiEngine::engineName() ) + m_engine = new CLHEP::RanshiEngine(); + else if ( m_engineType == CLHEP::NonRandomEngine::engineName() ) + m_engine = new CLHEP::NonRandomEngine(); + + if ( !m_engine ) { + except("Failed to create CLHEP random engine of type: %s.",m_engineType.c_str()); + } + } + m_engine->setSeed(m_seed,m_luxury); + m_rootRandom = new RNDM(this); + m_inited = true; + if ( 0 == s_instance ) { + setMainInstance(this); + } } -// -double Geant4Random::landau(double mean, double sigma) { - return gRandom->Landau(mean,sigma); +/// Should initialise the status of the algorithm according to seed. +void Geant4Random::setSeed(long seed) { + if ( !m_inited ) initialize(); + m_engine->setSeed(m_seed=seed,0); } -// +/// Should initialise the status of the algorithm +/** Initialization according to the zero terminated + * array of seeds. It is allowed to ignore one or + * many seeds in this array. + */ +void Geant4Random::setSeeds(const long* seeds, int size) { + if ( !m_inited ) initialize(); + m_seed = seeds[0]; + m_engine->setSeeds(seeds, size); +} + +/// Should save on a file specific to the instantiated engine in use the current status. +void Geant4Random::saveStatus( const char filename[] ) const { + if ( !m_inited ) { + except("Failed to save RandomGenerator status. [Not-inited]"); + } + m_engine->saveStatus(filename); +} + +/// Should read from a file and restore the last saved engine configuration. +void Geant4Random::restoreStatus( const char filename[] ) { + if ( !m_inited ) initialize(); + m_engine->restoreStatus(filename); +} + +/// Should dump the current engine status on the screen. +void Geant4Random::showStatus() const { + if ( !m_inited ) { + error("Failed to show RandomGenerator status. [Not-inited]"); + return; + } + printP2("Random engine status of object of type Geant4Random @ 0x%p",this); + 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()); + else + printP2(" Reused HepRandom instance @ 0x%p",m_engine); + + if ( m_engine != CLHEP::HepRandom::getTheEngine() ) + printP2(" Instance is identical to Geant4's HepRandom instance."); + + printP2(" Instance is %sidentical to ROOT's gRandom instance.", + gRandom == m_rootRandom ? "" : "NOT "); + + if ( gRandom != m_rootRandom ) { + printP2(" Local TRandom: 0x%p gRandom: 0x%p",m_rootRandom,gRandom); + } + m_engine->showStatus(); +} + +/// Create flat distributed random numbers in the interval ]0,1] double Geant4Random::rndm(int i) { + if ( !m_inited ) initialize(); return gRandom->Rndm(i); } -// +/// Create a float array of flat distributed random numbers in the interval ]0,1] void Geant4Random::rndmArray(int n, float *array) { + if ( !m_inited ) initialize(); gRandom->RndmArray(n,array); } -// +/// Create a double array of flat distributed random numbers in the interval ]0,1] void Geant4Random::rndmArray(int n, double *array) { + if ( !m_inited ) initialize(); gRandom->RndmArray(n,array); } -// -void Geant4Random::sphere(double &x, double &y, double &z, double r) { - gRandom->Sphere(x,y,z,r); -} - -// +/// Create uniformly disributed random numbers in the interval ]0,x1] double Geant4Random::uniform(double x1) { + if ( !m_inited ) initialize(); return gRandom->Uniform(x1); } -// +/// Create uniformly disributed random numbers in the interval ]x1,x2] double Geant4Random::uniform(double x1, double x2) { + if ( !m_inited ) initialize(); return gRandom->Uniform(x1,x2); } +/// Create exponentially distributed random numbers +double Geant4Random::exp(double tau) { + if ( !m_inited ) initialize(); + return gRandom->Exp(tau); +} + +/// Generates random vectors, uniformly distributed over a circle of given radius. +double Geant4Random::gauss(double mean, double sigma) { + if ( !m_inited ) initialize(); + return gRandom->Gaus(mean,sigma); +} + +/// Create landau distributed random numbers +double Geant4Random::landau(double mean, double sigma) { + if ( !m_inited ) initialize(); + return gRandom->Landau(mean,sigma); +} + +/// Create tuple of randum number around a circle with radius r +void Geant4Random::circle(double &x, double &y, double r) { + if ( !m_inited ) initialize(); + gRandom->Circle(x,y,r); +} + +/// Create tuple of randum number on a sphere with radius r +void Geant4Random::sphere(double &x, double &y, double &z, double r) { + if ( !m_inited ) initialize(); + gRandom->Sphere(x,y,z,r); +} + diff --git a/doc/DDG4Manual.pdf b/doc/DDG4Manual.pdf index 48e7b2e76fa04fea785a84bc8d12a4f01f859d6d..b1092bae184bd0aedd3ee8b3119553fae0953d26 100644 Binary files a/doc/DDG4Manual.pdf and b/doc/DDG4Manual.pdf differ diff --git a/doc/LaTex/DDG4Manual.tex b/doc/LaTex/DDG4Manual.tex index e10d5213246f800ba02a0d562ec998eb5c65b61d..83a9c692c540ba872b68fd46c797f0f4e970ea68 100644 --- a/doc/LaTex/DDG4Manual.tex +++ b/doc/LaTex/DDG4Manual.tex @@ -1822,11 +1822,11 @@ interact. \noindent The {\tt{Geant4UIManager}} is a component attached to the {\tt{Geant4Kernel}} object. All properties of all {\tt{Geant4Action}} instances may be exported to -Geant4 messengers and {\em{may}} hence be accessible directly from the Geant4 -prompt. To export properties from any action, call the {\tt{enableUI()}} -method of the action. +\tw{Geant4} messengers and {\em{may}} hence be accessible directly from +the \tw{Geant4} prompt. To export properties from any action, call the +{\tt{enableUI()}} method of the action. \noindent -The callback signature is: void operator()(G4Event* event) +The callback signature is: \tw{void operator()(G4Event* event)}. \vspace{0.5cm} \noindent @@ -1836,23 +1836,87 @@ The callback signature is: void operator()(G4Event* event) \bold{File name} & \tts{DDG4/src/Geant4.cpp} \\ \bold{Type} & \tts{Geant4Action} \\ \hline -\bold{Component Properties:} & defaults apply \\ +\bold{Component Properties:} & defaults apply \\ \hline \bold{SessionType} (string) & Session type (csh, tcsh, etc. \\ \bold{SetupUI} (string) & Name of the UI macro file \\ \bold{SetupVIS} (string) & Name of the visualization macro file \\ \bold{HaveVIS} (bool) & Flag to instantiate Vis manager - (def:false, unless VisSetup set) \\ + (def:false, unless VisSetup set) \\ \bold{HaveUI} (bool) & Flag to instantiate UI (default=true) \\ \end{tabular} +%============================================================================= +\subsubsection{Geant4Random} +%============================================================================= +\noindent +Mini interface to the random generator of the application. +Necessary, that on every object creates its own instance, but accesses +the main instance available through the \tw{Geant4Context}. + +\noindent +This is mandatory to ensure reproducibility of the event generation +process. Particular objects may use a dependent generator from +an experiment framework like \tw{GAUDI}. + +\noindent +internally the engine factory mechanism of \tw{CLHEP} is used. Please refer +there within for valid engine names and the random seeding mechanism, +which may vary between different engines. + +\noindent +Any number of independent random objects may be created and used +in parallel. This however, is not advised to ensure reproducibility. + +\noindent +The first instance of the random action is automatically set +to be the \tw{Geant4} instance. If another instance should be used by +\tw{Geant4}, use \tw{setMainInstance(Geant4Random* ptr)} class method to +override this behavior. +Provision, steered by options, is taken to ensure the \tw{gRandom} +of \tw{ROOT} uses the same random number engine. + +\vspace{0.5cm} +\noindent +\begin{tabular}{ l p{10cm} } +\hline +\bold{Class name} & \tts{Geant4} \\ +\bold{File name} & \tts{DDG4/src/Geant4Random.cpp} \\ +\bold{Type} & \tts{Geant4Random} \\ +\hline +\bold{Component Properties:} & defaults apply \\ +\hline +\bold{File} (string) & File name if initialized from file. \\ + & If set, engine name and seeds are ignored \\ +\bold{Engine} (string) & Engine type name. \\ + & All engines defined in the + \tw{CLHEP::EngineFactory} class are available. + If no type is supplied the engine from the + HepRandom generator instance is taken. \\ +\bold{Seed} (long) & Initial random seed. \\ + & Default: 123456789. \\ + & If not ZERO terminated, termination is added.\\ +\bold{Replace\_gRandom} (bool)& Flag to replace the \tw{ROOT} \tw{gRandom} + instance with this random number engine. + This ensures \tw{ROOT} and \tw{Geant4} use the same + random number engine, hence the same random sequence. + \\ +\end{tabular} + %============================================================================= \subsection{Predefined Geant4 Physics List Objects} %============================================================================= \noindent The physics list may be defined entirely data driven using the factory mechanism -using a variety of predefined objects: +using a variety of predefined objects. Though users are free to define private +physics lists, typically the predefined physics lists from \tw{Geant4} are used. + +\noindent +The inventory changes over time, new lists appear and obsolete lists are purged, +hence we will not list them explicitly here. +For the inventory of available physics lists, please refer to the implementation files: + \noindent \begin{itemize}\itemcompact \item Inventory of predefined physics lists, which may be inherited:\\ @@ -1972,8 +2036,8 @@ These by default are extensions of type: \bold{Type} & \tts{Geant4GeneratorAction} \\ \hline \bold{Component Properties:} & defaults apply \\ -\bold{Angle} (double) & \tts{Lorentz-Angle of boost} \\ -\bold{Mask} (int.bitmask) & \tts{Interaction identifier} \\ +\bold{Angle} (double) & \tts{Lorentz-Angle of boost} \\ +\bold{Mask} (int.bitmask) & \tts{Interaction identifier} \\ \hline \end{tabular} @@ -1983,17 +2047,28 @@ These by default are extensions of type: \noindent Boost the primary vertex and all particles outgoing the primary interaction in X-direction. +\noindent +The interaction to be processed by the component is uniquely identified +by the {\bf{Mask}} property. Two primary interaction may not have the same +mask. + +\noindent +{\bold{Note [special use case]:}}\\ +If all contributing interactions of the one event \bold{registered +in the primary event at the time the action is called} should be handled by +one single component instance, set the {\bf{Mask}} property to {\bold{-1}}. + \vspace{0.5cm} \noindent \begin{tabular}{ l p{10cm} } \hline -\bold{Class name} & \tts{Geant4InteractionVertexBoost} \\ -\bold{File name} & \tts{DDG4/src/Geant4InteractionVertexBoost.cpp} \\ -\bold{Type} & \tts{Geant4GeneratorAction} \\ +\bold{Class name} & \tts{Geant4InteractionVertexBoost} \\ +\bold{File name} & \tts{DDG4/src/Geant4InteractionVertexBoost.cpp} \\ +\bold{Type} & \tts{Geant4GeneratorAction} \\ \hline \bold{Component Properties:} & defaults apply \\ -\bold{Angle} (double) & \tts{Lorentz-Angle of boost} \\ -\bold{Mask} (int.bitmask) & \tts{Interaction identifier} \\ +\bold{Angle} (double) & \tts{Lorentz-Angle of boost} \\ +\bold{Mask} (int.bitmask) & \tts{Interaction identifier} \\ \hline \end{tabular} @@ -2003,17 +2078,28 @@ Boost the primary vertex and all particles outgoing the primary interaction in X \noindent Smear the primary vertex and all particles outgoing the primary interaction. +\noindent +The interaction to be processed by the component is uniquely identified +by the {\bf{Mask}} property. Two primary interaction may not have the same +mask. + +\noindent +{\bold{Note [special use case]:}}\\ +If all contributing interactions of the one event \bold{registered +in the primary event at the time the action is called} should be handled by +one single component instance, set the {\bf{Mask}} property to {\bold{-1}}. + \vspace{0.5cm} \noindent \begin{tabular}{ l p{10cm} } \hline -\bold{Class name} & \tts{Geant4InteractionVertexSmear} \\ -\bold{File name} & \tts{DDG4/src/Geant4InteractionVertexSmear.cpp} \\ +\bold{Class name} & \tts{Geant4InteractionVertexSmear} \\ +\bold{File name} & \tts{DDG4/src/Geant4InteractionVertexSmear.cpp} \\ \hline \bold{Component Properties:} & defaults apply \\ -\bold{Offset} (PxPyPzEVector) & \tts{Smearing offset} \\ -\bold{Sigma} (PxPyPzEVector) & \tts{Sigma on offset} \\ -\bold{Mask} (int.bitmask) & \tts{Interaction identifier} \\ +\bold{Offset} (PxPyPzEVector) & \tts{Smearing offset} \\ +\bold{Sigma} (PxPyPzEVector) & \tts{Sigma (Errors) on offset} \\ +\bold{Mask} (int.bitmask) & \tts{Interaction identifier} \\ \hline \end{tabular} @@ -2030,9 +2116,9 @@ and are merged into the {\tt{Geant4PrimaryInteraction}} object attached to the \noindent \begin{tabular}{ l p{10cm} } \hline -\bold{Class name} & \tts{Geant4InteractionMerger} \\ -\bold{File name} & \tts{DDG4/src/Geant4InteractionMerger.cpp} \\ -\bold{Type} & \tts{Geant4GeneratorAction} \\ +\bold{Class name} & \tts{Geant4InteractionMerger} \\ +\bold{File name} & \tts{DDG4/src/Geant4InteractionMerger.cpp} \\ +\bold{Type} & \tts{Geant4GeneratorAction} \\ \hline \bold{Component Properties:} & defaults apply \\ \hline @@ -2050,9 +2136,9 @@ to Geant4 for simulation. \noindent \begin{tabular}{ l p{10cm} } \hline -\bold{Class name} & \tts{Geant4PrimaryHandler} \\ -\bold{File name} & \tts{DDG4/src/Geant4PrimaryHandler.cpp} \\ -\bold{Type} & \tts{Geant4GeneratorAction} \\ +\bold{Class name} & \tts{Geant4PrimaryHandler} \\ +\bold{File name} & \tts{DDG4/src/Geant4PrimaryHandler.cpp} \\ +\bold{Type} & \tts{Geant4GeneratorAction} \\ \hline \bold{Component Properties:} & defaults apply \\ \hline @@ -2082,23 +2168,28 @@ If there is only one particle gun in use, the property 'Standalone', which by default is set to true invokes the interaction merging and the Geant4 primary generation directly. +\noindent +The interaction to be created by the component is uniquely identified +by the {\bf{Mask}} property. Two primary interaction may not have the same +mask. + \vspace{0.5cm} \noindent \begin{tabular}{ l p{10cm} } \hline -\bold{Class name} & \tts{Geant4PrimaryHandler} \\ -\bold{File name} & \tts{DDG4/src/Geant4PrimaryHandler.cpp} \\ -\bold{Type} & \tts{Geant4GeneratorAction} \\ +\bold{Class name} & \tts{Geant4PrimaryHandler} \\ +\bold{File name} & \tts{DDG4/src/Geant4PrimaryHandler.cpp} \\ +\bold{Type} & \tts{Geant4GeneratorAction} \\ \hline Component Properties: & default \\ -\bold{particle} (string) & Particle type to be shot \\ -\bold{energy} (double) & Particle energy in $MeV$ \\ +\bold{particle} (string) & Particle type to be shot \\ +\bold{energy} (double) & Particle energy in $MeV$ \\ \bold{position} (XYZVector) & Pole position of the generated particles in $mm$\\ \bold{direction} (XYZVector) & Momentum direction of the generated particles\\ -\bold{isotrop} (bool) & Isotropic particle directions in space. \\ -\bold{Mask} (int.bitmask) & Interaction identifier \\ -\bold{Standalone} (bool) & Setup for standalone execution \\ - & including interaction merging etc. \\ +\bold{isotrop} (bool) & Isotropic particle directions in space. \\ +\bold{Mask} (int.bitmask) & Interaction identifier \\ +\bold{Standalone} (bool) & Setup for standalone execution \\ + & including interaction merging etc. \\ \hline \end{tabular} diff --git a/doc/release.notes b/doc/release.notes index 3f6168c1b9dfed585657b33b6e5489630c9dd352..6b0e2321a3331bad0064b792a7896a8882d9162b 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,6 +3,24 @@ DD4hep ---- Release Notes ================================= +2015-10-09 M.Frank + DDG4 + - Extend the functionality of the DDG4 plugins + Geant4InteractionVertexBoost and Geant4InteractionVertexSmear. + If the Mask property is set to -1, all interactions present + at call time are smeared/boosted according to the parameters. + Note, that the position of the plugins within the generation + sequence is important. + - Add a new generator Geant4GeneratorWrapper to allow the use + of native G4 generator classes such as the G4ParticleGun or + the G4GeneralParticleSource. Still to be tested. + - Extend the Geant4Random functionality: May now be instantiated + like any other Geant4Action. Users may set the seed or the + luxury level. + All calls to HepRandom (CLHEP) or gRandom (ROOT) will re-use + this instance. See DDG4/examples/CLICRandom.py for illustration. + - Updated DDG4 manual. + 2015-09-15 F.Gaede - refactoring of Surface classes: - made VolSurface a reference counting handle to