File indexing completed on 2025-01-18 09:14:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DDG4/Geant4PhysicsList.h>
0016 #include <DDG4/Geant4UIMessenger.h>
0017 #include <DDG4/Geant4Particle.h>
0018 #include <DDG4/Geant4Kernel.h>
0019 #include <DD4hep/InstanceCount.h>
0020 #include <DD4hep/Printout.h>
0021 #include <DD4hep/Plugins.h>
0022
0023
0024 #include <G4VPhysicsConstructor.hh>
0025 #include <G4PhysListFactory.hh>
0026 #include <G4ProcessManager.hh>
0027 #include <G4ParticleTable.hh>
0028 #include <G4RunManager.hh>
0029 #include <G4VProcess.hh>
0030 #include <G4Decay.hh>
0031 #include <G4EmParameters.hh>
0032 #include <G4HadronicParameters.hh>
0033
0034
0035 #include <stdexcept>
0036 #include <regex.h>
0037
0038 using namespace dd4hep::sim;
0039
0040 namespace {
0041
0042 struct MyPhysics : G4VUserPhysicsList {
0043 void AddTransportation() { this->G4VUserPhysicsList::AddTransportation(); }
0044 };
0045
0046 struct EmptyPhysics : public G4VModularPhysicsList {
0047 EmptyPhysics() = default;
0048 virtual ~EmptyPhysics() = default;
0049 };
0050 struct ParticlePhysics : public G4VPhysicsConstructor {
0051 Geant4PhysicsListActionSequence* seq;
0052 G4VUserPhysicsList* phys;
0053 ParticlePhysics(Geant4PhysicsListActionSequence* s, G4VUserPhysicsList* p) : seq(s), phys(p) { }
0054 virtual ~ParticlePhysics() = default;
0055 virtual void ConstructProcess() {
0056 seq->constructProcesses(phys);
0057 if ( seq->transportation() ) {
0058 MyPhysics* ph = (MyPhysics*)phys;
0059 ph->AddTransportation();
0060 }
0061 }
0062 virtual void ConstructParticle() {
0063 seq->constructParticles(phys);
0064 }
0065 };
0066 }
0067
0068
0069 Geant4PhysicsList::Process::Process()
0070 : ordAtRestDoIt(-1), ordAlongSteptDoIt(-1), ordPostStepDoIt(-1) {
0071 }
0072
0073 Geant4PhysicsList::Process::Process(const Process& p)
0074 : name(p.name), ordAtRestDoIt(p.ordAtRestDoIt), ordAlongSteptDoIt(p.ordAlongSteptDoIt), ordPostStepDoIt(p.ordPostStepDoIt) {
0075 }
0076
0077
0078 Geant4PhysicsList::Process& Geant4PhysicsList::Process::operator=(const Process& p) {
0079 if ( this != &p ) {
0080 name = p.name;
0081 ordAtRestDoIt = p.ordAtRestDoIt;
0082 ordAlongSteptDoIt = p.ordAlongSteptDoIt;
0083 ordPostStepDoIt = p.ordPostStepDoIt;
0084 }
0085 return *this;
0086 }
0087
0088
0089 Geant4PhysicsList::Geant4PhysicsList(Geant4Context* ctxt, const std::string& nam)
0090 : Geant4Action(ctxt, nam) {
0091 InstanceCount::increment(this);
0092 }
0093
0094
0095 Geant4PhysicsList::~Geant4PhysicsList() {
0096 InstanceCount::decrement(this);
0097 }
0098
0099
0100 void Geant4PhysicsList::installCommandMessenger() {
0101 control()->addCall("dump", "Dump content of " + name(), Callback(this).make(&Geant4PhysicsList::dump));
0102 }
0103
0104
0105 void Geant4PhysicsList::dump() {
0106 if ( !m_physics.empty() && !m_particles.empty() && !m_processes.empty() ) {
0107 printout(ALWAYS,name(),"+++ Geant4PhysicsList Dump");
0108 }
0109 for ( const auto& p : m_physics)
0110 printout(ALWAYS,name(),"+++ PhysicsConstructor: %s",p.c_str());
0111 for ( const auto& p : m_particles )
0112 printout(ALWAYS,name(),"+++ ParticleConstructor: %s",p.c_str());
0113 for ( const auto& p : m_particlegroups )
0114 printout(ALWAYS,name(),"+++ ParticleGroupConstructor: %s",p.c_str());
0115 for ( const auto& [part_name,procs] : m_discreteProcesses ) {
0116 printout(ALWAYS,name(),"+++ DiscretePhysicsProcesses of particle %s",part_name.c_str());
0117 for (ParticleProcesses::const_iterator ip = procs.begin(); ip != procs.end(); ++ip) {
0118 printout(ALWAYS,name(),"+++ Process %s", (*ip).name.c_str());
0119 }
0120 }
0121 for ( const auto& [part_name, procs] : m_processes ) {
0122 printout(ALWAYS,name(),"+++ PhysicsProcesses of particle %s",part_name.c_str());
0123 for ( const Process& p : procs ) {
0124 printout(ALWAYS,name(),"+++ Process %s ordAtRestDoIt=%d ordAlongSteptDoIt=%d ordPostStepDoIt=%d",
0125 p.name.c_str(),p.ordAtRestDoIt,p.ordAlongSteptDoIt,p.ordPostStepDoIt);
0126 }
0127 }
0128 }
0129
0130
0131 void Geant4PhysicsList::addParticleConstructor(const std::string& part_name) {
0132 particles().emplace_back(part_name);
0133 }
0134
0135
0136 void Geant4PhysicsList::addParticleGroup(const std::string& part_name) {
0137 particlegroups().emplace_back(part_name);
0138 }
0139
0140
0141 void Geant4PhysicsList::addParticleProcess(const std::string& part_name,
0142 const std::string& proc_name,
0143 int ordAtRestDoIt,
0144 int ordAlongSteptDoIt,
0145 int ordPostStepDoIt)
0146 {
0147 Process p;
0148 p.name = proc_name;
0149 p.ordAtRestDoIt = ordAtRestDoIt;
0150 p.ordAlongSteptDoIt = ordAlongSteptDoIt;
0151 p.ordPostStepDoIt = ordPostStepDoIt;
0152 processes(part_name).emplace_back(p);
0153 }
0154
0155
0156 void Geant4PhysicsList::addDiscreteParticleProcess(const std::string& part_name,
0157 const std::string& proc_name)
0158 {
0159 Process p;
0160 p.name = proc_name;
0161 discreteProcesses(part_name).emplace_back(p);
0162 }
0163
0164
0165 void Geant4PhysicsList::addPhysicsConstructor(const std::string& phys_name) {
0166 physics().emplace_back(phys_name);
0167 }
0168
0169
0170 Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::processes(const std::string& nam) {
0171 if (auto i = m_processes.find(nam); i != m_processes.end())
0172 return (*i).second;
0173 auto ret = m_processes.emplace(nam, ParticleProcesses());
0174 return (*(ret.first)).second;
0175 }
0176
0177
0178 const Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::processes(const std::string& nam) const {
0179 if (auto i = m_processes.find(nam); i != m_processes.end())
0180 return (*i).second;
0181 except("Failed to access the physics process '%s' [Unknown-Process]", nam.c_str());
0182 throw std::runtime_error("Failed to access the physics process");
0183 }
0184
0185
0186 Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::discreteProcesses(const std::string& nam) {
0187 if (auto i = m_discreteProcesses.find(nam); i != m_discreteProcesses.end())
0188 return (*i).second;
0189 auto ret = m_discreteProcesses.emplace(nam, ParticleProcesses());
0190 return (*(ret.first)).second;
0191 }
0192
0193
0194 const Geant4PhysicsList::ParticleProcesses& Geant4PhysicsList::discreteProcesses(const std::string& nam) const {
0195 if (auto i = m_discreteProcesses.find(nam); i != m_discreteProcesses.end())
0196 return (*i).second;
0197 except("Failed to access the physics process '%s' [Unknown-Process]", nam.c_str());
0198 throw std::runtime_error("Failed to access the physics process");
0199 }
0200
0201
0202 Geant4PhysicsList::PhysicsConstructor Geant4PhysicsList::physics(const std::string& nam) const {
0203 for ( const auto& ctor : m_physics ) {
0204 if ( ctor == nam ) {
0205 if ( nullptr == ctor.pointer )
0206 except("Failed to instaniate the physics for constructor '%s'", nam.c_str());
0207 return ctor;
0208 }
0209 }
0210 except("Failed to access the physics for constructor '%s' [Unknown physics]", nam.c_str());
0211 throw std::runtime_error("Failed to access the physics process");
0212 }
0213
0214
0215 void Geant4PhysicsList::adoptPhysicsConstructor(Geant4Action* action) {
0216 if ( 0 != action ) {
0217 if ( G4VPhysicsConstructor* p = dynamic_cast<G4VPhysicsConstructor*>(action) ) {
0218 PhysicsConstructor ctor(action->name());
0219 ctor.pointer = p;
0220 action->addRef();
0221 m_physics.emplace_back(ctor);
0222 return;
0223 }
0224 except("Failed to adopt action object %s as physics constructor. [Invalid-Base]",action->c_name());
0225 }
0226 except("Failed to adopt invalid Geant4Action as PhysicsConstructor. [Invalid-object]");
0227 }
0228
0229
0230 void Geant4PhysicsList::constructPhysics(G4VModularPhysicsList* physics_pointer) {
0231 debug("constructPhysics %p", physics_pointer);
0232 for ( auto& ctor : m_physics ) {
0233 if ( 0 == ctor.pointer ) {
0234 if ( G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor) )
0235 ctor.pointer = p;
0236 else
0237 except("Failed to create the physics for G4VPhysicsConstructor '%s'", ctor.c_str());
0238 }
0239 physics_pointer->RegisterPhysics(ctor.pointer);
0240 info("Registered Geant4 physics constructor %s to physics list", ctor.c_str());
0241 }
0242 }
0243
0244
0245 void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer) {
0246 debug("constructParticles %p", physics_pointer);
0247
0248 for ( const auto& ctor : m_particles ) {
0249 G4ParticleDefinition* def = PluginService::Create<G4ParticleDefinition*>(ctor);
0250 if ( !def ) {
0251
0252 long* result = (long*) PluginService::Create<long>(ctor);
0253 if ( !result || *result != 1L ) {
0254 except("Failed to create particle type '%s' result=%d", ctor.c_str(), result);
0255 }
0256 info("Constructed Geant4 particle %s [using signature long (*)()]",ctor.c_str());
0257 }
0258 }
0259
0260 for ( const auto& ctor : m_particlegroups ) {
0261
0262 long* result = (long*) PluginService::Create<long>(ctor);
0263 if ( !result || *result != 1L ) {
0264 except("Failed to create particle type '%s' result=%d", ctor.c_str(), result);
0265 }
0266 info("Constructed Geant4 particle group %s [using signature long (*)()]",ctor.c_str());
0267 }
0268 }
0269
0270
0271 void Geant4PhysicsList::constructProcesses(G4VUserPhysicsList* physics_pointer) {
0272 debug("constructProcesses %p", physics_pointer);
0273 for ( const auto& [part_name, procs] : m_discreteProcesses ) {
0274 std::vector<G4ParticleDefinition*> defs(Geant4ParticleHandle::g4DefinitionsRegEx(part_name));
0275 if ( defs.empty() ) {
0276 except("Particle:%s Cannot find the corresponding entry in the particle table.", part_name.c_str());
0277 }
0278 for ( const Process& p : procs ) {
0279 if ( G4VProcess* g4 = PluginService::Create<G4VProcess*>(p.name) ) {
0280 for ( G4ParticleDefinition* particle : defs ) {
0281 G4ProcessManager* mgr = particle->GetProcessManager();
0282 mgr->AddDiscreteProcess(g4);
0283 info("Particle:%s -> [%s] added discrete process %s",
0284 part_name.c_str(), particle->GetParticleName().c_str(), p.name.c_str());
0285 }
0286 continue;
0287 }
0288 except("Cannot create discrete physics process %s", p.name.c_str());
0289 }
0290 }
0291 for ( const auto& [part_name, procs] : m_processes ) {
0292 std::vector<G4ParticleDefinition*> defs(Geant4ParticleHandle::g4DefinitionsRegEx(part_name));
0293 if (defs.empty()) {
0294 except("Particle:%s Cannot find the corresponding entry in the particle table.", part_name.c_str());
0295 }
0296 for ( const Process& p : procs ) {
0297 if ( G4VProcess* g4 = PluginService::Create<G4VProcess*>(p.name) ) {
0298 for ( G4ParticleDefinition* particle : defs ) {
0299 G4ProcessManager* mgr = particle->GetProcessManager();
0300 mgr->AddProcess(g4, p.ordAtRestDoIt, p.ordAlongSteptDoIt, p.ordPostStepDoIt);
0301 info("Particle:%s -> [%s] added process %s with flags (%d,%d,%d)",
0302 part_name.c_str(), particle->GetParticleName().c_str(), p.name.c_str(),
0303 p.ordAtRestDoIt, p.ordAlongSteptDoIt, p.ordPostStepDoIt);
0304 }
0305 continue;
0306 }
0307 except("Cannot create physics process %s", p.name.c_str());
0308 }
0309 }
0310 }
0311
0312
0313 void Geant4PhysicsList::enable(G4VUserPhysicsList* ) {
0314 }
0315
0316
0317 Geant4PhysicsListActionSequence::Geant4PhysicsListActionSequence(Geant4Context* ctxt, const std::string& nam)
0318 : Geant4Action(ctxt, nam), m_rangecut(0.7*CLHEP::mm)
0319 {
0320 declareProperty("transportation", m_transportation);
0321 declareProperty("extends", m_extends);
0322 declareProperty("decays", m_decays);
0323 declareProperty("rangecut", m_rangecut);
0324 declareProperty("verbosity", m_verbosity);
0325 m_needsControl = true;
0326 InstanceCount::increment(this);
0327 }
0328
0329
0330 Geant4PhysicsListActionSequence::~Geant4PhysicsListActionSequence() {
0331 m_actors(&Geant4Action::release);
0332 m_actors.clear();
0333 m_process.clear();
0334 InstanceCount::decrement(this);
0335 }
0336
0337 #include <G4FastSimulationPhysics.hh>
0338
0339
0340 G4VUserPhysicsList* Geant4PhysicsListActionSequence::extensionList() {
0341 G4VModularPhysicsList* physics = ( m_extends.empty() )
0342 ? new EmptyPhysics()
0343 : G4PhysListFactory().GetReferencePhysList(m_extends);
0344
0345 #if 0
0346 G4FastSimulationPhysics* fastSimulationPhysics = new G4FastSimulationPhysics();
0347
0348
0349
0350
0351
0352 fastSimulationPhysics->ActivateFastSimulation("e-");
0353 fastSimulationPhysics->ActivateFastSimulation("e+");
0354
0355
0356
0357
0358
0359 physics->RegisterPhysics( fastSimulationPhysics );
0360 #endif
0361
0362 constructPhysics(physics);
0363
0364
0365
0366
0367 physics->RegisterPhysics(new ParticlePhysics(this,physics));
0368
0369
0370 physics->SetVerboseLevel(m_verbosity);
0371 G4EmParameters::Instance()->SetVerbose(m_verbosity);
0372 G4HadronicParameters::Instance()->SetVerboseLevel(m_verbosity);
0373
0374 return physics;
0375 }
0376
0377
0378 void Geant4PhysicsListActionSequence::installCommandMessenger() {
0379 control()->addCall("dump", "Dump content of " + name(), Callback(this).make(&Geant4PhysicsListActionSequence::dump));
0380 }
0381
0382
0383 void Geant4PhysicsListActionSequence::dump() {
0384 printout(ALWAYS,name(),"+++ Dump of physics list component(s)");
0385 printout(ALWAYS,name(),"+++ Extension name %s",m_extends.c_str());
0386 printout(ALWAYS,name(),"+++ Transportation flag: %d",m_transportation);
0387 printout(ALWAYS,name(),"+++ Program decays: %d",m_decays);
0388 printout(ALWAYS,name(),"+++ RangeCut: %f",m_rangecut);
0389 printout(ALWAYS,name(),"+++ Verbosity: %i",m_verbosity);
0390 m_actors(&Geant4PhysicsList::dump);
0391 }
0392
0393
0394 void Geant4PhysicsListActionSequence::adopt(Geant4PhysicsList* action) {
0395 if (action) {
0396 action->addRef();
0397 m_actors.add(action);
0398 return;
0399 }
0400 except("Geant4EventActionSequence: Attempt to add invalid actor!");
0401 }
0402
0403
0404 void Geant4PhysicsListActionSequence::constructParticles(G4VUserPhysicsList* physics_pointer) {
0405 m_particle(physics_pointer);
0406 m_actors(&Geant4PhysicsList::constructParticles, physics_pointer);
0407 }
0408
0409
0410 void Geant4PhysicsListActionSequence::constructPhysics(G4VModularPhysicsList* physics_pointer) {
0411 m_physics(physics_pointer);
0412 m_actors(&Geant4PhysicsList::constructPhysics, physics_pointer);
0413 }
0414
0415
0416 void Geant4PhysicsListActionSequence::constructProcesses(G4VUserPhysicsList* physics_pointer) {
0417 m_actors(&Geant4PhysicsList::constructProcesses, physics_pointer);
0418 m_process(physics_pointer);
0419 if (m_decays) {
0420 constructDecays(physics_pointer);
0421 }
0422 }
0423
0424
0425 void Geant4PhysicsListActionSequence::constructDecays(G4VUserPhysicsList* physics_pointer) {
0426 G4ParticleTable* pt = G4ParticleTable::GetParticleTable();
0427 G4ParticleTable::G4PTblDicIterator* iter = pt->GetIterator();
0428
0429 G4Decay* decay = new G4Decay();
0430 info("ConstructDecays %p",physics_pointer);
0431 iter->reset();
0432 while ((*iter)()) {
0433 G4ParticleDefinition* p = iter->value();
0434 G4ProcessManager* mgr = p->GetProcessManager();
0435 if (decay->IsApplicable(*p)) {
0436 mgr->AddProcess(decay);
0437
0438 mgr->SetProcessOrdering(decay, idxPostStep);
0439 mgr->SetProcessOrdering(decay, idxAtRest);
0440 }
0441 }
0442 }
0443
0444
0445 void Geant4PhysicsListActionSequence::enable(G4VUserPhysicsList* physics_pointer) {
0446 m_actors(&Geant4PhysicsList::enable, physics_pointer);
0447 }
0448