From d93c2d1298cc59add3b3ba3be603d056638a2fe3 Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Tue, 19 Jan 2016 20:43:33 +0000 Subject: [PATCH] Fix user defined physics constructors --- DDG4/examples/SiDSim.py | 20 +++-- DDG4/include/DDG4/Geant4PhysicsConstructor.h | 91 +++++++++++++++++++ DDG4/include/DDG4/Geant4PhysicsList.h | 4 +- DDG4/plugins/Geant4DefaultRangeCut.cpp | 67 ++++++++++++++ DDG4/plugins/Geant4ExtraParticles.cpp | 43 +++++---- DDG4/plugins/Geant4ExtraParticles.h | 38 ++++---- DDG4/python/DDG4.py | 9 +- DDG4/src/Geant4Exec.cpp | 5 +- DDG4/src/Geant4PhysicsConstructor.cpp | 95 ++++++++++++++++++++ DDG4/src/Geant4PhysicsList.cpp | 13 ++- 10 files changed, 331 insertions(+), 54 deletions(-) create mode 100644 DDG4/include/DDG4/Geant4PhysicsConstructor.h create mode 100644 DDG4/plugins/Geant4DefaultRangeCut.cpp create mode 100644 DDG4/src/Geant4PhysicsConstructor.cpp diff --git a/DDG4/examples/SiDSim.py b/DDG4/examples/SiDSim.py index f43e866fb..b08d81d9f 100644 --- a/DDG4/examples/SiDSim.py +++ b/DDG4/examples/SiDSim.py @@ -176,13 +176,19 @@ def run(): print "# Now build the physics list:" phys = geant4.setupPhysics('QGSP_BERT') - ph = DDG4.PhysicsList(kernel,'Geant4PhysicsList/Myphysics') - ph.addParticleConstructor('G4BosonConstructor') - ph.addParticleConstructor('G4LeptonConstructor') - ph.addParticleProcess('e[+-]','G4eMultipleScattering',-1,1,1) - ph.addPhysicsConstructor('G4OpticalPhysics') - ph.enableUI() - phys.adopt(ph) + ph = geant4.addPhysics('Geant4PhysicsList/Myphysics') + #ph.addParticleConstructor('G4BosonConstructor') + #ph.addParticleConstructor('G4LeptonConstructor') + #ph.addParticleProcess('e[+-]','G4eMultipleScattering',-1,1,1) + #ph.addPhysicsConstructor('G4OpticalPhysics') + + # Add special particle types from specialized physics constructor + part = geant4.addPhysics('Geant4ExtraParticles/ExtraParticles') + part.pdgfile = 'checkout/DDG4/examples/particle.tbl' + + # Add global range cut + rg = geant4.addPhysics('Geant4DefaultRangeCut/GlobalRangeCut') + rg.RangeCut = 0.7*mm phys.dump() diff --git a/DDG4/include/DDG4/Geant4PhysicsConstructor.h b/DDG4/include/DDG4/Geant4PhysicsConstructor.h new file mode 100644 index 000000000..796d85437 --- /dev/null +++ b/DDG4/include/DDG4/Geant4PhysicsConstructor.h @@ -0,0 +1,91 @@ +// 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 Markus Frank +// \date 2016-01-19 +// \version 1.0 +// +//========================================================================== +// $Id$ +#ifndef DDG4_GEANT4PHYSICSCONSTRUCTOR_H +#define DDG4_GEANT4PHYSICSCONSTRUCTOR_H 1 + + +// Framework include files +#include "DDG4/Geant4PhysicsList.h" + +// Geant4 include files +#include "G4ParticleTable.hh" +#include "G4VPhysicsConstructor.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 { + + /// Implementation base of a Geant4 physics constructor + /** + * Concrete base of a Geant4 physics constructor. + * This class is only useful for constructors, which require + * initialization (and hence instantiation) by the user BEFORE + * the G4 physics list is instantiated. + * + * The instantiation of the physics list is delayed, because + * Geant4 does not like the G4VPhysicsConstructor constructor + * to be called before a physics list is attached to the + * G4RunManager. We overcome this problem through the delayed + * instantiation of a helper object made availible to the client. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class Geant4PhysicsConstructor : public Geant4PhysicsList { + public: + + /// Helper class to be used by cleints, by NOT overloaded! + /** + * The concrete instance will be instantiated by the framework in due time! + * Clients NEVER call the constructor directly + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class Constructor : virtual public G4VPhysicsConstructor { + protected: + /// Initializing constructor dealing with the callbacks + Constructor(); + /// Default destructor + virtual ~Constructor(); + public: + /// Access to a fresh (resetted) instance of the particle table iterator + virtual G4ParticleTable::G4PTblDicIterator* particleIterator() const = 0; + }; + + protected: + /// Physics type (Default: 0) + int m_type; + public: + /// Standard constructor with initailization parameters + Geant4PhysicsConstructor(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~Geant4PhysicsConstructor(); + /// constructPhysics callback + virtual void constructPhysics(G4VModularPhysicsList* physics); + /// Callback to construct processes (uses the G4 particle table) + virtual void constructProcess(Constructor& ctor); + /// Callback to construct particles + virtual void constructParticle(Constructor& ctor); + }; + + } // End namespace Simulation +} // End namespace DD4hep + +#endif // DDG4_GEANT4PHYSICSCONSTRUCTOR_H diff --git a/DDG4/include/DDG4/Geant4PhysicsList.h b/DDG4/include/DDG4/Geant4PhysicsList.h index 6707e21c1..b0f5e0acf 100644 --- a/DDG4/include/DDG4/Geant4PhysicsList.h +++ b/DDG4/include/DDG4/Geant4PhysicsList.h @@ -174,10 +174,10 @@ namespace DD4hep { */ void adoptPhysicsConstructor(Geant4Action* action); - /// constructParticle callback - virtual void constructParticles(G4VUserPhysicsList* particle); /// constructPhysics callback virtual void constructPhysics(G4VModularPhysicsList* physics); + /// Callback to construct particles + virtual void constructParticles(G4VUserPhysicsList* physics); /// Callback to construct processes (uses the G4 particle table) virtual void constructProcesses(G4VUserPhysicsList* physics); }; diff --git a/DDG4/plugins/Geant4DefaultRangeCut.cpp b/DDG4/plugins/Geant4DefaultRangeCut.cpp new file mode 100644 index 000000000..016ef1381 --- /dev/null +++ b/DDG4/plugins/Geant4DefaultRangeCut.cpp @@ -0,0 +1,67 @@ +// $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_Geant4DefaultRangeCut_h +#define DDG4_Geant4DefaultRangeCut_h 1 + +// Framework include files +#include "DDG4/Geant4PhysicsList.h" + +// geant4 +#include "G4VUserPhysicsList.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 { + + /// Geant4 physics list action to set global range cuts for secondary productions + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class Geant4DefaultRangeCut : public Geant4PhysicsList { + public: + Geant4DefaultRangeCut(Geant4Context* ctxt, const std::string& nam) + : Geant4PhysicsList(ctxt, nam), m_rangeCut(0.7*CLHEP::mm) + { + declareProperty("RangeCut", m_rangeCut); + } + virtual ~Geant4DefaultRangeCut() { + } + /// Callback to construct processes (uses the G4 particle table) + virtual void constructProcesses(G4VUserPhysicsList* physics_list) { + if ( physics_list ) { + info("+++ Set PhysicsList RangeCut to %f mm",m_rangeCut/CLHEP::mm); + physics_list->SetDefaultCutValue(m_rangeCut); + physics_list->SetCuts(); + if( DEBUG == printLevel() ) physics_list->DumpCutValuesTable(); + return; + } + except("No valid reference to a G4VUserPhysicsList instance!"); + } + + private: + /// global range cut for secondary productions + double m_rangeCut; + }; + } +} +#endif // DDG4_Geant4DefaultRangeCut_h + +#include "DDG4/Factories.h" +using namespace DD4hep::Simulation; +DECLARE_GEANT4ACTION(Geant4DefaultRangeCut) diff --git a/DDG4/plugins/Geant4ExtraParticles.cpp b/DDG4/plugins/Geant4ExtraParticles.cpp index bb1e80dcf..1ca529240 100644 --- a/DDG4/plugins/Geant4ExtraParticles.cpp +++ b/DDG4/plugins/Geant4ExtraParticles.cpp @@ -7,6 +7,8 @@ // $Name: $ #include "Geant4ExtraParticles.h" +#include "DDG4/Geant4PhysicsConstructor.h" +#include "DDG4/Geant4Kernel.h" #include "DDG4/Factories.h" #include "G4ParticleTable.hh" @@ -20,15 +22,21 @@ #include <sstream> #include <string> + +#include "G4RunManager.hh" + using namespace DD4hep::Simulation; Geant4ExtraParticles::Geant4ExtraParticles(Geant4Context* ctxt, const std::string& nam) - : G4VPhysicsConstructor(nam), Geant4Action(ctxt, nam) + : Geant4PhysicsConstructor(ctxt, nam), m_decay(0), m_ionise(0), m_scatter(0) { declareProperty("pdgfile", m_pdgfile); } -Geant4ExtraParticles::~Geant4ExtraParticles() { +Geant4ExtraParticles::~Geant4ExtraParticles() { + deletePtr(m_decay); + deletePtr(m_ionise); + deletePtr(m_scatter); } // bool Geant4ExtraParticles::FileExists() { @@ -36,20 +44,20 @@ Geant4ExtraParticles::~Geant4ExtraParticles() { // return pdgFile.is_open(); // } -void Geant4ExtraParticles::ConstructParticle() { +void Geant4ExtraParticles::constructParticle(Constructor& ) { if (m_pdgfile.empty()) return; - std::cout << "m_pdgfile: " << m_pdgfile << std::endl; + info("pdgfile: %s",m_pdgfile.c_str()); G4ParticleTable *theParticleTable = G4ParticleTable::GetParticleTable(); std::ifstream pdgFile( m_pdgfile.c_str(), std::ifstream::in ); if (!pdgFile.is_open()) { - std::cout << "Could not open m_pdgfile: " << m_pdgfile << std::endl; + except("Could not open pdgfile: %s",m_pdgfile.c_str()); return; } - std::cout << "opened m_pdgfile: " << m_pdgfile << std::endl; + info("opened pdgfile: %s",m_pdgfile.c_str()); while ( !pdgFile.eof() ) { // read line @@ -135,23 +143,22 @@ void Geant4ExtraParticles::ConstructParticle() { G4cout << "Loaded extra particles using file: " << m_pdgfile << G4endl; } -void Geant4ExtraParticles::ConstructProcess() { -#if G4VERSION_NUMBER >= 1000 - ParticleIterator=aParticleIterator; -#else - ParticleIterator=theParticleIterator; +void Geant4ExtraParticles::constructProcess(Constructor& ctor) { + G4ParticleTable::G4PTblDicIterator* ParticleIterator = ctor.particleIterator(); +#if G4VERSION_NUMBER < 940 + if ( 0 == _scatter ) _scatter=new G4hMultipleScattering(); + if ( 0 == _ionise ) _ionise=new G4hIonisation() + if ( 0 == _decay ) _decay=new G4Decay() #endif - - ParticleIterator->reset(); while((*ParticleIterator)()) { G4ParticleDefinition* pdef = ParticleIterator->value(); G4ProcessManager* pmgr = pdef->GetProcessManager(); if (pdef->GetParticleType() == "extra") { if (pdef->GetPDGCharge() != 0) { #if G4VERSION_NUMBER < 940 - pmgr->AddProcess(&_scatter, -1, 1, 1); // multiple scattering - pmgr->AddProcess(&_ionise, -1, 2, 2); // ionisation - pmgr->AddProcess(&_decay, -1, -1, 2); // decay + pmgr->AddProcess(_scatter, -1, 1, 1); // multiple scattering + pmgr->AddProcess(_ionise, -1, 2, 2); // ionisation + pmgr->AddProcess(_decay, -1, -1, 2); // decay #else pmgr->AddProcess(new G4hMultipleScattering(), -1, 1, 1); //multiple scattering pmgr->AddProcess(new G4hIonisation(), -1, 2, 2); // ionisation @@ -161,8 +168,8 @@ void Geant4ExtraParticles::ConstructProcess() { } else { #if G4VERSION_NUMBER < 940 - pmgr->AddProcess(&_scatter, -1, 1, 1); // multiple scattering - pmgr->AddProcess(&_decay, -1, -1, 2); // decay + pmgr->AddProcess(_scatter=new G4hMultipleScattering(), -1, 1, 1); // multiple scattering + pmgr->AddProcess(_decay=new G4Decay(), -1, -1, 2); // decay #else // pmgr->AddProcess(new G4hMultipleScattering(), -1, 1, 1); // multiple scattering pmgr->AddProcess(new G4Decay(), -1, -1, 2); // decay diff --git a/DDG4/plugins/Geant4ExtraParticles.h b/DDG4/plugins/Geant4ExtraParticles.h index e40548067..6c39260a1 100644 --- a/DDG4/plugins/Geant4ExtraParticles.h +++ b/DDG4/plugins/Geant4ExtraParticles.h @@ -9,41 +9,39 @@ #ifndef ExtraParticles_hh #define ExtraParticles_hh 1 -#include "DDG4/Geant4Action.h" +#include "DDG4/Geant4PhysicsConstructor.h" // geant4 -#include "G4VPhysicsConstructor.hh" #include "G4ProcessManager.hh" #include "G4Decay.hh" #include "G4hIonisation.hh" #include "G4hMultipleScattering.hh" #include "G4ParticleTable.hh" -namespace DD4hep { +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { - namespace Simulation { + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace Simulation { - class Geant4ExtraParticles : public G4VPhysicsConstructor, - public Geant4Action - { + class Geant4ExtraParticles : public Geant4PhysicsConstructor { public: + /// Standard constructor with initailization parameters Geant4ExtraParticles(Geant4Context* ctxt, const std::string& nam); + /// Default destructor virtual ~Geant4ExtraParticles(); - void ConstructParticle(); - void ConstructProcess(); - //static bool FileExists(); + /// Callback to construct processes (uses the G4 particle table) + virtual void constructProcess(Constructor& ctor); + /// Callback to construct particles + virtual void constructParticle(Constructor& ctor); private: - - G4ParticleTable::G4PTblDicIterator* ParticleIterator; - - std::string m_pdgfile; - - - G4Decay _decay; - G4hIonisation _ionise; - G4hMultipleScattering _scatter; + std::string m_pdgfile; + G4Decay* m_decay; + G4hIonisation* m_ionise; + G4hMultipleScattering* m_scatter; }; - }} + } +} #endif diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index 44a6005ac..471c0299b 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -533,7 +533,7 @@ class Geant4: print '+++++> ',field.name,'-> largest_step = ',field.largest_step,'[mm]' return field - def setupPhysics(self,name): + def setupPhysics(self, name): phys = self.master().physicsList() phys.extends = name phys.decays = True @@ -541,6 +541,13 @@ class Geant4: phys.dump() return phys + def addPhysics(self, name): + phys = self.master().physicsList() + opt = PhysicsList(self.master(), name) + opt.enableUI() + phys.adopt(opt) + return opt + def setupGun(self, name, particle, energy, isotrop=True, multiplicity=1, position=(0.0,0.0,0.0),**args): gun = GeneratorAction(self.kernel(),"Geant4ParticleGun/"+name,True) for i in args.items(): diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp index a639e1e3c..253f90288 100644 --- a/DDG4/src/Geant4Exec.cpp +++ b/DDG4/src/Geant4Exec.cpp @@ -556,12 +556,13 @@ int Geant4Exec::configure(Geant4Kernel& kernel) { if (0 == physics) { throw runtime_error("Panic! No valid user physics list present!"); } - +#if 0 + /// Not here: Use seperate object to do this! printout(INFO, "Geant4Exec", "+++ PhysicsList RangeCut: %f", phys_seq->m_rangecut ); physics->SetDefaultCutValue(phys_seq->m_rangecut); physics->SetCuts(); if( DEBUG == printLevel() ) physics->DumpCutValuesTable(); - +#endif runManager.SetUserInitialization(physics); // Construct the remaining user initialization in multi-threaded mode diff --git a/DDG4/src/Geant4PhysicsConstructor.cpp b/DDG4/src/Geant4PhysicsConstructor.cpp new file mode 100644 index 000000000..cd58abd56 --- /dev/null +++ b/DDG4/src/Geant4PhysicsConstructor.cpp @@ -0,0 +1,95 @@ +// $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 "DD4hep/InstanceCount.h" +#include "DDG4/Geant4PhysicsConstructor.h" +#include "G4VModularPhysicsList.hh" +#include "G4Version.hh" + +using namespace DD4hep::Simulation; + +namespace { + + /// Concrete implementation + class ConstructorImp : virtual public Geant4PhysicsConstructor::Constructor { + public: + Geant4PhysicsConstructor* ctor; + /// Initializing constructor dealing with the callbacks + ConstructorImp(Geant4PhysicsConstructor* ct, int typ) + : G4VPhysicsConstructor(ct->name(),typ), Geant4PhysicsConstructor::Constructor(), ctor(ct) + {} + /// Default destructor + virtual ~ConstructorImp() {} + /// Access to a fresh (resetted) instance of the particle table iterator + G4ParticleTable::G4PTblDicIterator* particleIterator() const { + G4ParticleTable::G4PTblDicIterator* iter; +#if G4VERSION_NUMBER >= 1000 + iter = aParticleIterator; +#else + iter = theParticleIterator; +#endif + iter->reset(); + return iter; + } + /// G4VPhysicsConstructor overload: This method will be invoked in the Construct() method. + virtual void ConstructParticle() { + ctor->constructParticle(*this); + } + /// G4VPhysicsConstructor overload: This method will be invoked in the Construct() method. + virtual void ConstructProcess() { + ctor->constructProcess(*this); + } + }; +} + + + +/// Standard action constructor +Geant4PhysicsConstructor::Constructor::Constructor() + : G4VPhysicsConstructor() +{ +} + +/// Default destructor +Geant4PhysicsConstructor::Constructor::~Constructor() { +} + +/// Standard action constructor +Geant4PhysicsConstructor::Geant4PhysicsConstructor(Geant4Context* ctxt, const std::string& nam) + : Geant4PhysicsList(ctxt, nam) +{ + InstanceCount::increment(this); + declareProperty("PhysicsType", m_type = 0); +} + +/// Default destructor +Geant4PhysicsConstructor::~Geant4PhysicsConstructor() { + InstanceCount::decrement(this); + // Do NOT delete the constructor ! +} + +/// constructPhysics callback +void Geant4PhysicsConstructor::constructPhysics(G4VModularPhysicsList* physics_list) { + // Register try constructor providing the callbacks + physics_list->RegisterPhysics(new ConstructorImp(this, m_type)); +} + +/// Callback to construct processes (uses the G4 particle table) +void Geant4PhysicsConstructor::constructProcess(Constructor& /* ctor */) { +} + +/// Callback to construct particles +void Geant4PhysicsConstructor::constructParticle(Constructor& /* ctor */) { +} diff --git a/DDG4/src/Geant4PhysicsList.cpp b/DDG4/src/Geant4PhysicsList.cpp index e518b3057..5092fd18f 100644 --- a/DDG4/src/Geant4PhysicsList.cpp +++ b/DDG4/src/Geant4PhysicsList.cpp @@ -15,6 +15,7 @@ // Framework include files #include "DDG4/Geant4PhysicsList.h" #include "DDG4/Geant4UIMessenger.h" +#include "DDG4/Geant4Kernel.h" #include "DD4hep/InstanceCount.h" #include "DD4hep/Printout.h" #include "DD4hep/Plugins.h" @@ -24,6 +25,7 @@ #include "G4PhysListFactory.hh" #include "G4ProcessManager.hh" #include "G4ParticleTable.hh" +#include "G4RunManager.hh" #include "G4VProcess.hh" #include "G4Decay.hh" @@ -130,7 +132,9 @@ void Geant4PhysicsList::installCommandMessenger() { /// Dump content to stdout void Geant4PhysicsList::dump() { - printout(ALWAYS,name(),"+++ Geant4PhysicsList Dump"); + if ( !m_physics.empty() && !m_particles.empty() && !m_processes.empty() ) { + printout(ALWAYS,name(),"+++ Geant4PhysicsList Dump"); + } for (PhysicsConstructors::const_iterator i = m_physics.begin(); i != m_physics.end(); ++i) printout(ALWAYS,name(),"+++ PhysicsConstructor: %s",(*i).c_str()); for (ParticleConstructors::const_iterator i = m_particles.begin(); i != m_particles.end(); ++i) @@ -210,7 +214,7 @@ void Geant4PhysicsList::adoptPhysicsConstructor(Geant4Action* action) { /// Callback to construct particle decays void Geant4PhysicsList::constructPhysics(G4VModularPhysicsList* physics_pointer) { - info("constructPhysics %p", physics_pointer); + debug("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 ) { @@ -228,7 +232,7 @@ void Geant4PhysicsList::constructPhysics(G4VModularPhysicsList* physics_pointer) /// constructParticle callback void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer) { - info("constructParticles %p", physics_pointer); + debug("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; @@ -246,7 +250,7 @@ void Geant4PhysicsList::constructParticles(G4VUserPhysicsList* physics_pointer) /// Callback to construct processes (uses the G4 particle table) void Geant4PhysicsList::constructProcesses(G4VUserPhysicsList* physics_pointer) { - info("constructProcesses %p", physics_pointer); + debug("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; @@ -298,6 +302,7 @@ G4VUserPhysicsList* Geant4PhysicsListActionSequence::extensionList() { G4VModularPhysicsList* physics = ( m_extends.empty() ) ? new EmptyPhysics() : G4PhysListFactory().GetReferencePhysList(m_extends); + // Register all physics constructors with the physics list constructPhysics(physics); // Ensure the particles and processes declared are also invoked. // Hence: Create a special physics constructor doing so. -- GitLab