From a85d75b7ad7067f78045c4e2bdd99fdce7873e61 Mon Sep 17 00:00:00 2001 From: Tom Eichlersmith <31970302+tomeichlersmith@users.noreply.github.com> Date: Mon, 23 Oct 2023 09:21:12 -0500 Subject: [PATCH 1/4] get process manager from particle singleton In my adventures with Geant4 developing the G4DarkBreM package, I found that recent versions (at least all since our tag of 10.2) have a method for accessing a particle's process manager from the particle itself. Since the particle is a singleton created when requested, we can always access it and ask for the process manager. If we call the function too early in processing (perhaps if we were to manually call `GammaPhysics::ConstructProcess` at the wrong time during initialization), then the manager would not be created and attached yet, but this will work if we allow G4 to call `ConstructProcess` at the right time. --- src/SimCore/GammaPhysics.cxx | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/SimCore/GammaPhysics.cxx b/src/SimCore/GammaPhysics.cxx index 0f26d168..c0fd2010 100644 --- a/src/SimCore/GammaPhysics.cxx +++ b/src/SimCore/GammaPhysics.cxx @@ -9,31 +9,8 @@ namespace simcore { -// needed for GEANT4 10.3.0 and later -// -// TODO: I (Einar) don't think this really is necessary if we change -// GetGammaProcessManager below -#ifndef aParticleIterator -#define aParticleIterator \ - ((subInstanceManager.offset[g4vpcInstanceID])._aParticleIterator) -#endif - G4ProcessManager* GammaPhysics::GetGammaProcessManager() const { - /** - * Not entirely clear that there isn't a simpler way to do this, but to keep - * this function extraction to a pure refactoring, I'm leaving it here for - * now. /Einar - */ - aParticleIterator->reset(); - - // Loop through all of the particles and find the "gamma". - while ((*aParticleIterator)()) { - auto particle{aParticleIterator->value()}; - auto particleName{particle->GetParticleName()}; - if (particleName == "gamma") { - return particle->GetProcessManager(); - } - } + if (G4Gamma::Gamma()->GetProcessManager()) return G4Gamma::Gamma()->GetProcessManager(); EXCEPTION_RAISE("GammaPhysics", "Was unable to access the process manager for photons, " "something is very wrong!"); From e371de06d6e362dc66dd8ffa432ba32c648b22fc Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Mon, 23 Oct 2023 14:57:51 -0500 Subject: [PATCH 2/4] refactor GammaPhysics to remove extraneous classes --- include/SimCore/GammaPhysics.h | 43 +++++++++++++++------------------ src/SimCore/GammaPhysics.cxx | 44 +++++++++++++++++----------------- 2 files changed, 41 insertions(+), 46 deletions(-) diff --git a/include/SimCore/GammaPhysics.h b/include/SimCore/GammaPhysics.h index c2dcd65f..199d6b6b 100644 --- a/include/SimCore/GammaPhysics.h +++ b/include/SimCore/GammaPhysics.h @@ -3,10 +3,12 @@ * @brief Class used to enhanced the gamma physics list. * @author Jeremy McCormick, SLAC National Accelerator Laboratory * @author Omar Moreno, SLAC National Accelerator Laboratory + * @author Einar Elen, Lund University + * @author Tom Eichlersmith, University of Minnesota */ #ifndef SIMCORE_GAMMAPHYSICS_H_ -#define SIMCORE_GAMMAPHYSICS_H 1_ +#define SIMCORE_GAMMAPHYSICS_H_ //------------// // Geant4 // @@ -16,6 +18,7 @@ #include "G4VPhysicsConstructor.hh" #include "G4VProcess.hh" #include "SimCore/PhotoNuclearModel.h" + namespace simcore { /** @@ -38,11 +41,7 @@ class GammaPhysics : public G4VPhysicsConstructor { * @param parameters The python configuration */ GammaPhysics(const G4String& name, - const framework::config::Parameters& parameters) - : G4VPhysicsConstructor(name), - modelParameters{parameters.getParameter( - "photonuclear_model")} {} - GammaPhysics(const G4String& name = "GammaPhysics"); + const framework::config::Parameters& parameters); /** * Class destructor. @@ -50,30 +49,26 @@ class GammaPhysics : public G4VPhysicsConstructor { virtual ~GammaPhysics() = default; /** - * Construct particles (no-op). + * Construct particles + * + * We don't do anything here since we are just attaching/updating + * the photon physics. */ - void ConstructParticle() {} + void ConstructParticle() final override; /** - * Construct the process (gamma to muons). + * We do two things for this call back during initialization. + * + * 1. We add the muon-conversion process to the photon's process + * table, enabling it to be one of the processes that can happen. + * 2. We move the photonNuclear process to be the first process in + * the photon's ordering so that the bias operator has a chance + * to lower its cross-section before any EM process is called + * (if need be). */ - void ConstructProcess(); - - /** - * Search the list for the process "photoNuclear". When found, - * change the calling order so photonNuclear is called before - * EM processes. The biasing operator needs the photonNuclear - * process to be called first because the cross-section is - * needed to bias down other process. - */ - void SetPhotonNuclearAsFirstProcess() const; + void ConstructProcess() final override; private: - /* - * Returns the process manager object for the G4Gamma class from the list of - * Geant4 particles. - */ - G4ProcessManager* GetGammaProcessManager() const; /** * The gamma to muons process. */ diff --git a/src/SimCore/GammaPhysics.cxx b/src/SimCore/GammaPhysics.cxx index c0fd2010..b75bf487 100644 --- a/src/SimCore/GammaPhysics.cxx +++ b/src/SimCore/GammaPhysics.cxx @@ -9,37 +9,37 @@ namespace simcore { -G4ProcessManager* GammaPhysics::GetGammaProcessManager() const { - if (G4Gamma::Gamma()->GetProcessManager()) return G4Gamma::Gamma()->GetProcessManager(); - EXCEPTION_RAISE("GammaPhysics", - "Was unable to access the process manager for photons, " - "something is very wrong!"); -} +GammaPhysics::GammaPhysics(const G4String& name, + const framework::config::Parameters& parameters) + : G4VPhysicsConstructor(name), + modelParameters{parameters.getParameter( + "photonuclear_model")} {} -void GammaPhysics::SetPhotonNuclearAsFirstProcess() const { - auto processManager{GetGammaProcessManager()}; - // Get the process list associated with the gamma. - const auto processes{processManager->GetProcessList()}; +void GammaPhysics::ConstructParticle() {} - for (int i{0}; i < processes->size(); ++i) { - const auto process{(*processes)[i]}; - const auto processName{process->GetProcessName()}; - if (processName == "photonNuclear") { - processManager->SetProcessOrderingToFirst( - process, G4ProcessVectorDoItIndex::idxAll); - } - } -} void GammaPhysics::ConstructProcess() { - G4ProcessManager* processManager = GetGammaProcessManager(); - + G4ProcessManager* processManager = G4Gamma::Gamma()->GetProcessManager(); + if (processManager == nullptr) { + EXCEPTION_RAISE("GammaPhysics", + "Was unable to access the process manager for photons, " + "something is very wrong!"); + } + // configure our PN model based on runtime parameters auto pn = PhotoNuclearModel::Factory::get().make( modelParameters.getParameter("class_name"), modelParameters.getParameter("instance_name"), modelParameters); pn->removeExistingModel(processManager); pn->ConstructGammaProcess(processManager); - SetPhotonNuclearAsFirstProcess(); + // put the PN process first in the ordering in case PN biasing is happening + const auto processes{processManager->GetProcessList()}; + for (int i{0}; i < processes->size(); i++) { + const auto process{(*processes)[i]}; + if (process->GetProcessName() == "photonNuclear") { + processManager->SetProcessOrderingToFirst( + process, G4ProcessVectorDoItIndex::idxAll); + } + } // Add the gamma -> mumu to the physics list. processManager->AddDiscreteProcess(&gammaConvProcess); } From 55f3cfa3af9dec86a9d9c6d456875cb970142350 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Thu, 26 Oct 2023 15:12:53 -0500 Subject: [PATCH 3/4] no need to override when final implies override --- include/SimCore/GammaPhysics.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/SimCore/GammaPhysics.h b/include/SimCore/GammaPhysics.h index 199d6b6b..0b112afe 100644 --- a/include/SimCore/GammaPhysics.h +++ b/include/SimCore/GammaPhysics.h @@ -54,7 +54,7 @@ class GammaPhysics : public G4VPhysicsConstructor { * We don't do anything here since we are just attaching/updating * the photon physics. */ - void ConstructParticle() final override; + void ConstructParticle() final; /** * We do two things for this call back during initialization. @@ -66,13 +66,14 @@ class GammaPhysics : public G4VPhysicsConstructor { * to lower its cross-section before any EM process is called * (if need be). */ - void ConstructProcess() final override; + void ConstructProcess() final; private: /** * The gamma to muons process. */ G4GammaConversionToMuons gammaConvProcess; + /** * Parameters from the configuration to pass along to the photonuclear model. */ From 9be968a21a0a7f347f0f56e21568b1fffa48cfe6 Mon Sep 17 00:00:00 2001 From: tomeichlersmith Date: Thu, 26 Oct 2023 15:27:31 -0500 Subject: [PATCH 4/4] longer comment about process ordering trying to point future developers in the right direction --- src/SimCore/GammaPhysics.cxx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/SimCore/GammaPhysics.cxx b/src/SimCore/GammaPhysics.cxx index b75bf487..ed65361f 100644 --- a/src/SimCore/GammaPhysics.cxx +++ b/src/SimCore/GammaPhysics.cxx @@ -31,7 +31,24 @@ void GammaPhysics::ConstructProcess() { modelParameters); pn->removeExistingModel(processManager); pn->ConstructGammaProcess(processManager); - // put the PN process first in the ordering in case PN biasing is happening + /** + * Put the PN process first in the ordering in case PN biasing is happening. + * + * Process ordering is a complicated concept and unfortunately + * its affect on biasing is poorly documented. What has been said is + * that some processes _need_ to be called _last_[1]. In addition, + * the practical experience of working on defining a custom + * process for + * [G4DarkBreM](https://github.com/LDMX-Software/G4DarkBreM) + * showed that sometimes Geant4 does + * not get through the full list of processes but it always starts + * at the beginning. For these reasons, we put the PN process first + * in the ordering so that we can insure it is always check by Geant4 + * before continuing. + * + * [1] + * https://indico.cern.ch/event/58317/contributions/2047449/attachments/992300/1411062/PartDef-ProcMan-AS.pdf + */ const auto processes{processManager->GetProcessList()}; for (int i{0}; i < processes->size(); i++) { const auto process{(*processes)[i]};