diff --git a/DDG4/include/DDG4/Geant4PhysicsList.h b/DDG4/include/DDG4/Geant4PhysicsList.h index c78a723668ac3809b770d5de8d1b7e8ca3fef9fa..6707e21c177f874c8ed85e168f5669b4ab30797e 100644 --- a/DDG4/include/DDG4/Geant4PhysicsList.h +++ b/DDG4/include/DDG4/Geant4PhysicsList.h @@ -24,6 +24,7 @@ // Forward declarations class G4VPhysicsConstructor; +class G4VModularPhysicsList; class G4VUserPhysicsList; /// Namespace for the AIDA detector description toolkit @@ -32,25 +33,6 @@ namespace DD4hep { /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit namespace Simulation { - /// Interface class exposing some of the G4VUserPhysicsList class. - /** - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_SIMULATION - */ - class Geant4UserPhysics { - protected: - /// Standard constructor with initailization parameters - Geant4UserPhysics(); - /// Default destructor - virtual ~Geant4UserPhysics(); - public: - /// Enable transportation - virtual void AddTransportation() = 0; - /// Register physics constructor - virtual void RegisterPhysics(G4VPhysicsConstructor* physics) = 0; - }; - /// Concrete basic implementation of a Geant4 physics list action /** * \author M.Frank @@ -107,14 +89,21 @@ namespace DD4hep { * \ingroup DD4HEP_SIMULATION */ class PhysicsConstructor: public std::string { + public: + /// Pointer to physics constructor object + G4VPhysicsConstructor* pointer; public: /// Default constructor PhysicsConstructor() - : std::string() { + : std::string(), pointer(0) { + } + /// Copy constructor + PhysicsConstructor(const PhysicsConstructor& c) + : std::string(c), pointer(c.pointer) { } /// Initalizing constructor PhysicsConstructor(const std::string& s) - : std::string(s) { + : std::string(s), pointer(0) { } /// Default destructor ~PhysicsConstructor() { @@ -170,17 +159,27 @@ namespace DD4hep { void addParticleProcess(const std::string& part_name, const std::string& proc_name, int ordAtRestDoIt,int ordAlongSteptDoIt,int ordPostStepDoIt); /// Add PhysicsConstructor by name + /** This constructor is used for intrinsic Geant4 defined physics constructors. + * Such physics constructors are only created by the factory and attached + * to the physics list object. + */ void addPhysicsConstructor(const std::string& physics_name); - - /// Callback to construct the physics constructors - virtual void constructProcess(Geant4UserPhysics* interface); + /// Add PhysicsConstructor as Geant4Action object + /** The action object must bve a sub-class of type G4VPhysicsConstructor. + * -- The Geant4Action object to supports properties. + * -- Specific user actions may be implemented in the + * base class calls to 'ConstructParticle' or 'ConstructProcess'. + * Both calls are invoked by the framework when the physics list + * is configured for the use in the run-manager. + */ + void adoptPhysicsConstructor(Geant4Action* action); /// constructParticle callback - virtual void constructParticles(Geant4UserPhysics* particle); + virtual void constructParticles(G4VUserPhysicsList* particle); /// constructPhysics callback - virtual void constructPhysics(Geant4UserPhysics* physics); + virtual void constructPhysics(G4VModularPhysicsList* physics); /// Callback to construct processes (uses the G4 particle table) - virtual void constructProcesses(Geant4UserPhysics* physics); + virtual void constructProcesses(G4VUserPhysicsList* physics); }; /// The implementation of the single Geant4 physics list action sequence @@ -196,15 +195,17 @@ namespace DD4hep { public: protected: - /// Callback sequence for event finalization action + /// Callback sequence for G4 physics constructors + CallbackSequence m_physics; + /// Callback sequence for G4 process constructors CallbackSequence m_process; - /// Callback sequence for event finalization action + /// Callback sequence for G4 particle constructors CallbackSequence m_particle; /// The list of action objects to be called Actors<Geant4PhysicsList> m_actors; /// Callback to construct particle decays - virtual void constructDecays(Geant4UserPhysics* physics); + virtual void constructDecays(G4VUserPhysicsList* physics); public: /// Flag if particle transportation is to be added bool m_transportation; @@ -232,25 +233,32 @@ namespace DD4hep { bool transportation() const { return m_transportation; } + /// Register physics construction callback + template <typename Q, typename T> + void constructPhysics(Q* p, void (T::*f)(G4VModularPhysicsList*)) { + m_physics.add(p, f); + } /// Register process construction callback template <typename Q, typename T> - void constructProcess(Q* p, void (T::*f)(Geant4UserPhysics*)) { + void constructProcess(Q* p, void (T::*f)(G4VUserPhysicsList*)) { m_process.add(p, f); } /// Register particle construction callback template <typename Q, typename T> - void constructParticle(Q* p, void (T::*f)(Geant4UserPhysics*)) { + void constructParticle(Q* p, void (T::*f)(G4VUserPhysicsList*)) { m_particle.add(p, f); } /// Add an actor responding to all callbacks. Sequence takes ownership. void adopt(Geant4PhysicsList* action); - /// begin-of-event callback - virtual void constructProcess(Geant4UserPhysics* physics); - /// begin-of-event callback - virtual void constructParticles(Geant4UserPhysics* physics); + /// Execute sequence of G4 physics constructors + virtual void constructProcesses(G4VUserPhysicsList* physics); + /// Execute sequence of G4 particle constructors + virtual void constructParticles(G4VUserPhysicsList* physics); + /// Execute sequence of G4 physics constructors + virtual void constructPhysics(G4VModularPhysicsList* physics); /// Extend physics list from factory: - G4VUserPhysicsList* extensionList() const; + G4VUserPhysicsList* extensionList(); }; } // End namespace Simulation diff --git a/DDG4/include/DDG4/Geant4UserPhysicsList.h b/DDG4/include/DDG4/Geant4UserPhysicsList.h deleted file mode 100644 index b1495eb06ee0c14408c5839f11a5d96d355e5352..0000000000000000000000000000000000000000 --- a/DDG4/include/DDG4/Geant4UserPhysicsList.h +++ /dev/null @@ -1,77 +0,0 @@ -// $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 DDG4_GEANT4USERPHYSICSLIST_H -#define DDG4_GEANT4USERPHYSICSLIST_H - -#include "DD4hep/InstanceCount.h" -#include "DDG4/Geant4PhysicsList.h" -#include "G4VModularPhysicsList.hh" - -/// Namespace for the AIDA detector description toolkit -namespace DD4hep { - - /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit - namespace Simulation { - - /// Concrete templated implementation of the Geant4 user physics list - /** @class Geant4UserPhysicsList - * - * @author M.Frank - * @version 1.0 - */ - template <typename BASE_IMP> struct Geant4UserPhysicsList: virtual public Geant4UserPhysics, virtual public BASE_IMP { - protected: - /// Action container - Geant4PhysicsListActionSequence* m_sequence; - public: - /// Standard constructor - Geant4UserPhysicsList(Geant4PhysicsListActionSequence* seq, int verbose) - : Geant4UserPhysics(), BASE_IMP(verbose), m_sequence(seq) { - if (m_sequence) - m_sequence->addRef(); - InstanceCount::increment(this); - } - /// Default destructor - virtual ~Geant4UserPhysicsList() { - if (m_sequence) - m_sequence->release(); - m_sequence = 0; - InstanceCount::decrement(this); - } - /// User construction callback - virtual void ConstructProcess() { - this->BASE_IMP::ConstructProcess(); - if (m_sequence) - m_sequence->constructProcess(this); - } - /// User construction callback - virtual void ConstructParticle() { - this->BASE_IMP::ConstructParticle(); - if (m_sequence) - m_sequence->constructParticles(this); - } - /// Enable transportation - virtual void AddTransportation() { - this->G4VUserPhysicsList::AddTransportation(); - } - // Register Physics Constructor - virtual void RegisterPhysics(G4VPhysicsConstructor* physics) { - this->G4VModularPhysicsList::RegisterPhysics(physics); - } - }; - - } // End namespace Simulation -} // End namespace DD4hep - -#endif // DDG4_GEANT4USERPHYSICSLIST_H diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index c30c951912dab6005c59e3f407c5a86569959205..44a6005acd29a2e4eee7361ea6279639bb5f22c9 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -215,6 +215,7 @@ _setup('Geant4DetectorConstructionSequence') _setup('Geant4UserInitializationSequence') _setup('Geant4Sensitive') _setup('Geant4ParticleHandler') +_import_class('Sim','Geant4Action') _import_class('Sim','Geant4Filter') _import_class('Sim','Geant4RunAction') _import_class('Sim','Geant4TrackingAction') diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp index b6dbb97013fa50b62290c16d83564e5d7fbc4fd8..a639e1e3cb25014d89401c977cc15180f3392fc5 100644 --- a/DDG4/src/Geant4Exec.cpp +++ b/DDG4/src/Geant4Exec.cpp @@ -471,7 +471,6 @@ namespace DD4hep { #include "DD4hep/LCDD.h" #include "DD4hep/Plugins.h" #include "DDG4/Geant4DetectorConstruction.h" -#include "DDG4/Geant4UserPhysicsList.h" #include "DDG4/Geant4Kernel.h" using namespace std; diff --git a/DDG4/src/Geant4PhysicsList.cpp b/DDG4/src/Geant4PhysicsList.cpp index adfd4744499e2e93373098d4b52d821bdba22ce4..e518b30574dd39949ff58ddfc229d66d08a896f1 100644 --- a/DDG4/src/Geant4PhysicsList.cpp +++ b/DDG4/src/Geant4PhysicsList.cpp @@ -15,7 +15,6 @@ // Framework include files #include "DDG4/Geant4PhysicsList.h" #include "DDG4/Geant4UIMessenger.h" -#include "DDG4/Geant4UserPhysicsList.h" #include "DD4hep/InstanceCount.h" #include "DD4hep/Printout.h" #include "DD4hep/Plugins.h" @@ -38,12 +37,31 @@ using namespace DD4hep::Simulation; namespace { + struct MyPhysics : G4VUserPhysicsList { + void AddTransportation() { this->G4VUserPhysicsList::AddTransportation(); } + }; + struct EmptyPhysics : public G4VModularPhysicsList { EmptyPhysics() {} virtual ~EmptyPhysics() {} virtual void ConstructProcess() {} virtual void ConstructParticle() {} }; + struct ParticlePhysics : public G4VPhysicsConstructor { + Geant4PhysicsListActionSequence* seq; + G4VUserPhysicsList* phys; + ParticlePhysics(Geant4PhysicsListActionSequence* s, G4VUserPhysicsList* p) + : seq(s), phys(p) {} + virtual ~ParticlePhysics() {} + virtual void ConstructProcess() { + seq->constructProcesses(phys); + if ( seq->transportation() ) { + MyPhysics* ph = (MyPhysics*)phys; + ph->AddTransportation(); + } + } + virtual void ConstructParticle() { seq->constructParticles(phys); } + }; void _findDef(const string& expression, vector<G4ParticleDefinition*>& results) { string exp = expression; //'^'+expression+"$"; @@ -74,16 +92,6 @@ namespace { } } -/// Standard constructor with initailization parameters -Geant4UserPhysics::Geant4UserPhysics() { - InstanceCount::increment(this); -} - -/// Default destructor -Geant4UserPhysics::~Geant4UserPhysics() { - InstanceCount::decrement(this); -} - /// Default constructor Geant4PhysicsList::Process::Process() : ordAtRestDoIt(-1), ordAlongSteptDoIt(-1), ordPostStepDoIt(-1) { @@ -97,9 +105,9 @@ Geant4PhysicsList::Process::Process(const Process& p) Geant4PhysicsList::Process& Geant4PhysicsList::Process::operator=(const Process& p) { if ( this != &p ) { name = p.name; - ordAtRestDoIt = p.ordAtRestDoIt; + ordAtRestDoIt = p.ordAtRestDoIt; ordAlongSteptDoIt = p.ordAlongSteptDoIt; - ordPostStepDoIt = p.ordPostStepDoIt; + ordPostStepDoIt = p.ordPostStepDoIt; } return *this; } @@ -184,30 +192,43 @@ const Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::processes(const s throw runtime_error("Failed to access the physics process"); // never called anyway } -/// Callback to construct the physics list -void Geant4PhysicsList::constructProcess(Geant4UserPhysics* physics_pointer) { - printout(INFO, "Geant4PhysicsList", "%s> constructProcess %p", name().c_str(), physics_pointer); - constructPhysics(physics_pointer); - constructProcesses(physics_pointer); +/// Add PhysicsConstructor by name +void Geant4PhysicsList::adoptPhysicsConstructor(Geant4Action* action) { + if ( 0 != action ) { + G4VPhysicsConstructor* p = dynamic_cast<G4VPhysicsConstructor*>(action); + if ( p ) { + PhysicsConstructor ctor(action->name()); + ctor.pointer = p; + action->addRef(); + m_physics.push_back(ctor); + return; + } + except("Failed to adopt action object %s as physics constructor. [Invalid-Base]",action->c_name()); + } + except("Failed to adopt invalid Geant4Action as PhysicsConstructor. [Invalid-object]"); } /// Callback to construct particle decays -void Geant4PhysicsList::constructPhysics(Geant4UserPhysics* physics_pointer) { - for (PhysicsConstructors::const_iterator i = m_physics.begin(); i != m_physics.end(); ++i) { - const PhysicsConstructors::value_type& ctor = *i; - G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor); - if (!p) { - except("Failed to create the physics entities " - "for the G4VPhysicsConstructor '%s'", ctor.c_str()); +void Geant4PhysicsList::constructPhysics(G4VModularPhysicsList* physics_pointer) { + info("constructPhysics %p", physics_pointer); + for (PhysicsConstructors::iterator i=m_physics.begin(); i != m_physics.end(); ++i) { + PhysicsConstructors::value_type& ctor = *i; + if ( 0 == ctor.pointer ) { + G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor); + if (!p) { + except("Failed to create the physics entities " + "for the G4VPhysicsConstructor '%s'", ctor.c_str()); + } + ctor.pointer = p; } - physics_pointer->RegisterPhysics(p); - info("Registered Geant4 physics %s", ctor.c_str()); + physics_pointer->RegisterPhysics(ctor.pointer); + info("Registered Geant4 physics constructor %s to physics list", ctor.c_str()); } } /// constructParticle callback -void Geant4PhysicsList::constructParticles(Geant4UserPhysics* physics_pointer) { - printout(INFO, "Geant4PhysicsList", "%s> constructParticles %p", name().c_str(), physics_pointer); +void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer) { + info("constructParticles %p", physics_pointer); /// Now define all particles for (ParticleConstructors::const_iterator i = m_particles.begin(); i != m_particles.end(); ++i) { const ParticleConstructors::value_type& ctor = *i; @@ -224,8 +245,8 @@ void Geant4PhysicsList::constructParticles(Geant4UserPhysics* physics_pointer) { } /// Callback to construct processes (uses the G4 particle table) -void Geant4PhysicsList::constructProcesses(Geant4UserPhysics* physics_pointer) { - printout(INFO, "Geant4PhysicsList", "%s> constructProcesses %p", name().c_str(), physics_pointer); +void Geant4PhysicsList::constructProcesses(G4VUserPhysicsList* physics_pointer) { + info("constructProcesses %p", physics_pointer); for (PhysicsProcesses::const_iterator i = m_processes.begin(); i != m_processes.end(); ++i) { const string& part_name = (*i).first; const ParticleProcesses& procs = (*i).second; @@ -257,8 +278,8 @@ void Geant4PhysicsList::constructProcesses(Geant4UserPhysics* physics_pointer) { Geant4PhysicsListActionSequence::Geant4PhysicsListActionSequence(Geant4Context* ctxt, const string& nam) : Geant4Action(ctxt, nam), m_transportation(false), m_decays(false), m_rangecut(0.7*CLHEP::mm) { declareProperty("transportation", m_transportation); - declareProperty("extends", m_extends); - declareProperty("decays", m_decays); + declareProperty("extends", m_extends); + declareProperty("decays", m_decays); declareProperty("rangecut", m_rangecut); m_needsControl = true; InstanceCount::increment(this); @@ -273,10 +294,16 @@ Geant4PhysicsListActionSequence::~Geant4PhysicsListActionSequence() { } /// Extend physics list from factory: -G4VUserPhysicsList* Geant4PhysicsListActionSequence::extensionList() const { +G4VUserPhysicsList* Geant4PhysicsListActionSequence::extensionList() { G4VModularPhysicsList* physics = ( m_extends.empty() ) ? new EmptyPhysics() : G4PhysListFactory().GetReferencePhysList(m_extends); + constructPhysics(physics); + // Ensure the particles and processes declared are also invoked. + // Hence: Create a special physics constructor doing so. + // Ownership is transferred to the physics list. + // Do not delete this pointer afterwards.... + physics->RegisterPhysics(new ParticlePhysics(this,physics)); return physics; } @@ -305,26 +332,29 @@ void Geant4PhysicsListActionSequence::adopt(Geant4PhysicsList* action) { except("Geant4EventActionSequence: Attempt to add invalid actor!"); } -/// begin-of-event callback -void Geant4PhysicsListActionSequence::constructParticles(Geant4UserPhysics* physics_pointer) { +/// Callback to construct particles +void Geant4PhysicsListActionSequence::constructParticles(G4VUserPhysicsList* physics_pointer) { m_particle(physics_pointer); m_actors(&Geant4PhysicsList::constructParticles, physics_pointer); } +/// Callback to execute physics constructors +void Geant4PhysicsListActionSequence::constructPhysics(G4VModularPhysicsList* physics_pointer) { + m_physics(physics_pointer); + m_actors(&Geant4PhysicsList::constructPhysics, physics_pointer); +} + /// constructProcess callback -void Geant4PhysicsListActionSequence::constructProcess(Geant4UserPhysics* physics_pointer) { - m_actors(&Geant4PhysicsList::constructProcess, physics_pointer); +void Geant4PhysicsListActionSequence::constructProcesses(G4VUserPhysicsList* physics_pointer) { + m_actors(&Geant4PhysicsList::constructProcesses, physics_pointer); m_process(physics_pointer); if (m_decays) { constructDecays(physics_pointer); } - if (m_transportation) { - physics_pointer->AddTransportation(); - } } /// Callback to construct particle decays -void Geant4PhysicsListActionSequence::constructDecays(Geant4UserPhysics* physics_pointer) { +void Geant4PhysicsListActionSequence::constructDecays(G4VUserPhysicsList* physics_pointer) { G4ParticleTable* pt = G4ParticleTable::GetParticleTable(); G4ParticleTable::G4PTblDicIterator* iter = pt->GetIterator(); // Add Decay Process