File indexing completed on 2026-10-02 08:10:31
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.physics_list = nullptr;
0220 ctor.pointer = p;
0221 action->addRef();
0222 m_physics.emplace_back(ctor);
0223 return;
0224 }
0225 except("Failed to adopt action object %s as physics constructor. [Invalid-Base]",action->c_name());
0226 }
0227 except("Failed to adopt invalid Geant4Action as PhysicsConstructor. [Invalid-object]");
0228 }
0229
0230
0231 void Geant4PhysicsList::constructPhysics(G4VModularPhysicsList* physics_pointer) {
0232 debug("constructPhysics %p", physics_pointer);
0233 for ( auto& ctor : m_physics ) {
0234 if ( 0 == ctor.pointer ) {
0235 if ( G4VPhysicsConstructor* p = PluginService::Create<G4VPhysicsConstructor*>(ctor) ) {
0236 ctor.pointer = p;
0237 }
0238 else {
0239 except("Failed to create the physics for G4VPhysicsConstructor '%s'", ctor.c_str());
0240 }
0241 }
0242 if( !ctor.physics_list ) {
0243 ctor.physics_list = physics_pointer;
0244 physics_pointer->RegisterPhysics(ctor.pointer);
0245 info("+++ Registered Geant4 physics constructor %s to modular physics list id:%d",
0246 ctor.c_str(), physics_pointer->GetInstanceID());
0247 }
0248 }
0249 }
0250
0251
0252 G4VPhysicsConstructor* Geant4PhysicsList::addPhysicsConstructorType(const std::string& physics_type) {
0253 debug("addPhysics %s", physics_type.c_str());
0254 for ( auto& ctor : m_physics ) {
0255 if( physics_type == ctor ) {
0256 warning("+++ Physics type %s is already present. [using existing, creation denied]",
0257 physics_type.c_str());
0258 return ctor.pointer;
0259 }
0260 }
0261 PhysicsConstructor ctor(physics_type);
0262 ctor.physics_list = nullptr;
0263 ctor.pointer = PluginService::Create<G4VPhysicsConstructor*>(physics_type);
0264 if( ctor.pointer == nullptr ) {
0265 return nullptr;
0266 }
0267 m_physics.push_back(ctor);
0268 info("+++ Added Geant4 physics constructor %s to physics list", ctor.c_str());
0269 return ctor.pointer;
0270 }
0271
0272
0273 void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer) {
0274 debug("constructParticles %p", physics_pointer);
0275
0276 for ( const auto& ctor : m_particles ) {
0277 G4ParticleDefinition* def = PluginService::Create<G4ParticleDefinition*>(ctor);
0278 if ( !def ) {
0279
0280 long* result = (long*) PluginService::Create<long>(ctor);
0281 if ( !result || *result != 1L ) {
0282 except("Failed to create particle type '%s' result=%d", ctor.c_str(), result);
0283 }
0284 info("Constructed Geant4 particle %s [using signature long (*)()]",ctor.c_str());
0285 }
0286 }
0287
0288 for ( const auto& ctor : m_particlegroups ) {
0289
0290 long* result = (long*) PluginService::Create<long>(ctor);
0291 if ( !result || *result != 1L ) {
0292 except("Failed to create particle type '%s' result=%d", ctor.c_str(), result);
0293 }
0294 info("Constructed Geant4 particle group %s [using signature long (*)()]",ctor.c_str());
0295 }
0296 }
0297
0298
0299 void Geant4PhysicsList::constructProcesses(G4VUserPhysicsList* physics_pointer) {
0300 debug("constructProcesses %p", physics_pointer);
0301 for ( const auto& [part_name, procs] : m_discreteProcesses ) {
0302 std::vector<G4ParticleDefinition*> defs(Geant4ParticleHandle::g4DefinitionsRegEx(part_name));
0303 if ( defs.empty() ) {
0304 except("Particle:%s Cannot find the corresponding entry in the particle table.", part_name.c_str());
0305 }
0306 for ( const Process& p : procs ) {
0307 if ( G4VProcess* g4 = PluginService::Create<G4VProcess*>(p.name) ) {
0308 for ( G4ParticleDefinition* particle : defs ) {
0309 G4ProcessManager* mgr = particle->GetProcessManager();
0310 mgr->AddDiscreteProcess(g4);
0311 info("Particle:%s -> [%s] added discrete process %s",
0312 part_name.c_str(), particle->GetParticleName().c_str(), p.name.c_str());
0313 }
0314 continue;
0315 }
0316 except("Cannot create discrete physics process %s", p.name.c_str());
0317 }
0318 }
0319 for ( const auto& [part_name, procs] : m_processes ) {
0320 std::vector<G4ParticleDefinition*> defs(Geant4ParticleHandle::g4DefinitionsRegEx(part_name));
0321 if (defs.empty()) {
0322 except("Particle:%s Cannot find the corresponding entry in the particle table.", part_name.c_str());
0323 }
0324 for ( const Process& p : procs ) {
0325 if ( G4VProcess* g4 = PluginService::Create<G4VProcess*>(p.name) ) {
0326 for ( G4ParticleDefinition* particle : defs ) {
0327 G4ProcessManager* mgr = particle->GetProcessManager();
0328 mgr->AddProcess(g4, p.ordAtRestDoIt, p.ordAlongSteptDoIt, p.ordPostStepDoIt);
0329 info("Particle:%s -> [%s] added process %s with flags (%d,%d,%d)",
0330 part_name.c_str(), particle->GetParticleName().c_str(), p.name.c_str(),
0331 p.ordAtRestDoIt, p.ordAlongSteptDoIt, p.ordPostStepDoIt);
0332 }
0333 continue;
0334 }
0335 except("Cannot create physics process %s", p.name.c_str());
0336 }
0337 }
0338 }
0339
0340
0341 void Geant4PhysicsList::enable(G4VUserPhysicsList* ) {
0342 }
0343
0344
0345 Geant4PhysicsListActionSequence::Geant4PhysicsListActionSequence(Geant4Context* ctxt, const std::string& nam)
0346 : Geant4Action(ctxt, nam), m_rangecut(0.7*CLHEP::mm)
0347 {
0348 declareProperty("transportation", m_transportation);
0349 declareProperty("extends", m_extends);
0350 declareProperty("decays", m_decays);
0351 declareProperty("rangecut", m_rangecut);
0352 declareProperty("verbosity", m_verbosity);
0353 declareProperty("modular_physics_verbosity", m_physics_verbosity);
0354 m_needsControl = true;
0355 InstanceCount::increment(this);
0356 }
0357
0358
0359 Geant4PhysicsListActionSequence::~Geant4PhysicsListActionSequence() {
0360 m_actors(&Geant4Action::release);
0361 m_actors.clear();
0362 m_process.clear();
0363 InstanceCount::decrement(this);
0364 }
0365
0366 #include <G4FastSimulationPhysics.hh>
0367
0368
0369 G4VUserPhysicsList* Geant4PhysicsListActionSequence::extensionList() {
0370 G4VModularPhysicsList* physics = ( m_extends.empty() )
0371 ? new EmptyPhysics()
0372 : G4PhysListFactory().GetReferencePhysList(m_extends);
0373
0374 #if 0
0375 G4FastSimulationPhysics* fastSimulationPhysics = new G4FastSimulationPhysics();
0376
0377
0378
0379
0380
0381 fastSimulationPhysics->ActivateFastSimulation("e-");
0382 fastSimulationPhysics->ActivateFastSimulation("e+");
0383
0384
0385
0386
0387
0388 physics->RegisterPhysics( fastSimulationPhysics );
0389 #endif
0390
0391 constructPhysics(physics);
0392
0393
0394
0395
0396 physics->RegisterPhysics(new ParticlePhysics(this,physics));
0397
0398
0399 physics->SetVerboseLevel(m_verbosity);
0400 G4EmParameters::Instance()->SetVerbose(m_verbosity);
0401 G4HadronicParameters::Instance()->SetVerboseLevel(m_verbosity);
0402
0403 return physics;
0404 }
0405
0406
0407 void Geant4PhysicsListActionSequence::installCommandMessenger() {
0408 control()->addCall("dump", "Dump content of " + name(), Callback(this).make(&Geant4PhysicsListActionSequence::dump));
0409 }
0410
0411
0412 void Geant4PhysicsListActionSequence::dump() {
0413 printout(ALWAYS,name(),"+++ Dump of physics list component(s)");
0414 printout(ALWAYS,name(),"+++ Extension name %s",m_extends.c_str());
0415 printout(ALWAYS,name(),"+++ Transportation flag: %d",m_transportation);
0416 printout(ALWAYS,name(),"+++ Program decays: %d",m_decays);
0417 printout(ALWAYS,name(),"+++ RangeCut: %f",m_rangecut);
0418 printout(ALWAYS,name(),"+++ Verbosity: %i",m_verbosity);
0419 m_actors(&Geant4PhysicsList::dump);
0420 }
0421
0422
0423 void Geant4PhysicsListActionSequence::adopt(Geant4PhysicsList* action) {
0424 if (action) {
0425 action->addRef();
0426 m_actors.add(action);
0427 return;
0428 }
0429 except("Geant4EventActionSequence: Attempt to add invalid actor!");
0430 }
0431
0432
0433 void Geant4PhysicsListActionSequence::constructParticles(G4VUserPhysicsList* physics_pointer) {
0434 m_particle(physics_pointer);
0435 m_actors(&Geant4PhysicsList::constructParticles, physics_pointer);
0436 }
0437
0438
0439 void Geant4PhysicsListActionSequence::constructPhysics(G4VModularPhysicsList* physics_pointer) {
0440 m_physics(physics_pointer);
0441 m_actors(&Geant4PhysicsList::constructPhysics, physics_pointer);
0442 }
0443
0444
0445 void Geant4PhysicsListActionSequence::constructProcesses(G4VUserPhysicsList* physics_pointer) {
0446 m_actors(&Geant4PhysicsList::constructProcesses, physics_pointer);
0447 m_process(physics_pointer);
0448 if (m_decays) {
0449 constructDecays(physics_pointer);
0450 }
0451 }
0452
0453
0454 void Geant4PhysicsListActionSequence::constructDecays(G4VUserPhysicsList* physics_pointer) {
0455 G4ParticleTable* pt = G4ParticleTable::GetParticleTable();
0456 G4ParticleTable::G4PTblDicIterator* iter = pt->GetIterator();
0457
0458 G4Decay* decay = new G4Decay();
0459 info("ConstructDecays %p",physics_pointer);
0460 iter->reset();
0461 while ((*iter)()) {
0462 G4ParticleDefinition* p = iter->value();
0463 G4ProcessManager* mgr = p->GetProcessManager();
0464 if (decay->IsApplicable(*p)) {
0465 mgr->AddProcess(decay);
0466
0467 mgr->SetProcessOrdering(decay, idxPostStep);
0468 mgr->SetProcessOrdering(decay, idxAtRest);
0469 }
0470 }
0471 }
0472
0473
0474 void Geant4PhysicsListActionSequence::enable(G4VUserPhysicsList* physics_pointer) {
0475 if( m_physics_verbosity >= 0 ) {
0476 physics_pointer->SetVerboseLevel(m_physics_verbosity);
0477 }
0478 m_actors(&Geant4PhysicsList::enable, physics_pointer);
0479 }
0480