ATLAS Offline Software
Loading...
Searching...
No Matches
PhysicsListSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "PhysicsListSvc.h"
6
7#include "G4VUserPhysicsList.hh"
8#include "G4StateManager.hh"
9#include "G4RunManager.hh"
10#include "G4EmParameters.hh"
11#include "G4UImanager.hh"
12#include "G4PhysListFactory.hh"
13#include "G4AntiNeutron.hh"
14#include "G4HadronicProcessStore.hh"
15
16#include "CLHEP/Units/PhysicalConstants.h"
17
19
20#include <limits>
21
22PhysicsListSvc::PhysicsListSvc(const std::string& name, ISvcLocator* pSvcLocator)
23 : base_class(name,pSvcLocator)
24{
25}
26
27
29{
30 ATH_MSG_DEBUG("PhysicsListSvc::initialize()");
31 if (m_phys_option.size())
32 {
33 ATH_MSG_INFO( "Initializing list of " << m_phys_option.size() << " physics options" );
34 CHECK( m_phys_option.retrieve() );
35 }
36
37 if (m_phys_decay.size())
38 {
39 ATH_MSG_INFO( "Initializing list of " << m_phys_decay.size() << " Decays " );
40 CHECK( m_phys_decay.retrieve() );
41 }
42
44
45 return StatusCode::SUCCESS;
46}
47
48
50{
51 ATH_MSG_DEBUG("PhysicsListSvc::CreatePhysicsList()");
52 if (m_physicsListName.value() != ""){
53 G4PhysListFactory factory;
54 if (m_quietMode) { factory.SetVerbose(0); } // HACK
55 AtlasPhysListFactory Atlasfactory;
56 if (m_quietMode) {
57 Atlasfactory.SetVerbose(0); // HACK
58 G4HadronicProcessStore::Instance()->SetVerbose(0);
59 }
61 if (factory.IsReferencePhysList(m_physicsListName.value()))
62 {
63 ATH_MSG_INFO("Creating Geant4 PhysicsList: " << m_physicsListName.value());
64 m_physicsList = factory.GetReferencePhysList(m_physicsListName.value());
65 }
66 else if (Atlasfactory.IsReferencePhysList(m_physicsListName.value()))
67 {
68 ATH_MSG_INFO("Creating ATLAS PhysicsList: " << m_physicsListName.value());
70 }
71 }
72
73 if (!m_physicsList)
74 {
75 ATH_MSG_ERROR("Unable to initialize physics List: " << m_physicsList);
76 throw "PhysicsListInitializationError";
77 }
78 // Call these as functions. As this could be used as a base class, having
79 // these as separate functions lets someone who is inheriting from this use
80 // them...
81
82 // sort m_phys_option list
83 std::vector<IPhysicsOptionTool*> sortedPhysicsOptions;
84 sortedPhysicsOptions.reserve(m_phys_option.size());
85 // Manually sorting ToolHandleArray
86 {
87 // BSM Physics
88 for (auto& physOptTool: m_phys_option) {
89 if (physOptTool->GetOptionType() == G4AtlasPhysicsOption::Type::BSMPhysics) {
90 sortedPhysicsOptions.push_back(&*physOptTool);
91 }
92 }
93
94 // Add particles from the PDG Table not currently known to Geant4
95 for (auto& physOptTool: m_phys_option) {
96 if (physOptTool->GetOptionType() == G4AtlasPhysicsOption::Type::QS_ExtraParticles) {
97 sortedPhysicsOptions.push_back(&*physOptTool);
98 }
99 }
100
101 // Add MSC and Ionisation processes for specific particles (possibly merge with the next one?)
102 for (auto& physOptTool: m_phys_option) {
103 if (physOptTool->GetOptionType() == G4AtlasPhysicsOption::Type::QS_ExtraProc) {
104 sortedPhysicsOptions.push_back(&*physOptTool);
105 }
106 }
107
108 // G4StepLimitation, LUCID Op Process, TRT XTR process
109 for (auto& physOptTool: m_phys_option) {
110 if (physOptTool->GetOptionType() == G4AtlasPhysicsOption::Type::GlobalProcesses) {
111 sortedPhysicsOptions.push_back(&*physOptTool);
112 }
113 }
114
115 // Unknown
116 for (auto& physOptTool: m_phys_option) {
117 if (physOptTool->GetOptionType() == G4AtlasPhysicsOption::Type::UnknownType) {
118 ATH_MSG_ERROR(physOptTool->name() << "set as UnknownType. This tool will not be used to modify the physics list of this job.");
119 }
120 }
121 }
122
123 //Register physics options to the G4VModularPhysicsList
124 for (auto& physOptTool: sortedPhysicsOptions)
125 {
126 ATH_MSG_DEBUG("Registering " << physOptTool->name());
127 m_physicsList->RegisterPhysics(physOptTool->GetPhysicsOption().release());
128 }
129 //Register decays to the G4VModularPhysicsList
130 for (auto& physDecayTool: m_phys_decay)
131 {
132 ATH_MSG_DEBUG("Registering " << physDecayTool->name());
133 m_physicsList->RegisterPhysics(physDecayTool->GetPhysicsOption().release());
134 }
135
136 m_physicsList->RegisterPhysics(m_fastSimulationConstructor->GetPhysicsOption().release());
137
138 //ConstructProcess();
139 ATH_MSG_DEBUG("end of PhysicsListSvc::CreatePhysicsList()");
140}
141
142
144{
145 if (!m_physicsList) {
146 this->CreatePhysicsList();
147 }
148 return m_physicsList;
149}
150
151
153{
154 if(!m_physicsList) {
155 this->CreatePhysicsList();
156 }
157 G4RunManager::GetRunManager()->SetUserInitialization(m_physicsList);
158}
159
160
162{
163 if (!m_physicsList)
164 {
165 ATH_MSG_WARNING("Physics list not initialized before calling ConstructProcess()");
166 return;
167 }
168
169 if(m_generalCut.value() > 0. && std::abs(m_generalCut.value())>std::numeric_limits<double>::epsilon())
170 {
171 m_physicsList->SetDefaultCutValue(m_generalCut.value());
172 }
173
174 std::vector<std::string> g4commands;
175 if (m_neutronTimeCut.value() > 0. && std::abs(m_neutronTimeCut.value())>std::numeric_limits<double>::epsilon())
176 {
177 std::ostringstream oss;
178 oss<<"/physics_engine/neutron/timeLimit "<<m_neutronTimeCut.value()<<" ns";
179 g4commands.push_back(oss.str());
180 }
181
182 if (m_neutronEnergyCut.value() > 0. && std::abs(m_neutronEnergyCut.value())>std::numeric_limits<double>::epsilon())
183 {
184 std::ostringstream oss;
185 oss<<"/physics_engine/neutron/energyLimit "<<m_neutronEnergyCut.value()<<" MeV";
186 g4commands.push_back(oss.str());
187 }
188
189 if(!g4commands.empty()) {
190 // Send UI commands
191 ATH_MSG_DEBUG("G4 Command: Trying in SetPhysicsOptions()");
192 G4UImanager* ui = G4UImanager::GetUIpointer();
193 for (const auto& g4command : g4commands) {
194 int returnCode = ui->ApplyCommand( g4command );
195 CommandLog(returnCode, g4command);
196 }
197 }
198
199 G4EmParameters* emp = G4EmParameters::Instance();
200 if (m_emMaxEnergy.value()>=0) emp->SetMaxEnergy(m_emMaxEnergy.value());
201 if (m_emNumberOfBinsPerDecade.value()>=0) emp->SetNumberOfBinsPerDecade(m_emNumberOfBinsPerDecade.value());
202 if (m_emMinEnergy.value()>=0) emp->SetMinEnergy(m_emMinEnergy.value());
203 if (m_applyEMCuts.value())
204 {
205 emp->SetApplyCuts(true);
206 }
207
209 G4AntiNeutron::Definition()->SetPDGStable(false);
210 }
211
212 return;
213}
214
215
216void PhysicsListSvc::CommandLog(int returnCode, const std::string& commandString) const
217{
218 switch(returnCode) {
219 case 0: { ATH_MSG_DEBUG("G4 Command: " << commandString << " - Command Succeeded"); } break;
220 case 100: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Command Not Found!"); } break;
221 case 200: {
222 auto* stateManager = G4StateManager::GetStateManager();
223 ATH_MSG_DEBUG("G4 Command: " << commandString << " - Illegal Application State (" <<
224 stateManager->GetStateString(stateManager->GetCurrentState()) << ")!");
225 } break;
226 case 300: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Range!"); } break;
227 case 400: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Unreadable!"); } break;
228 case 500: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Candidates!"); } break;
229 case 600: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Alias Not Found!"); } break;
230 default: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Unknown Status!"); } break;
231 }
232
233}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
G4VModularPhysicsList * GetReferencePhysList(const G4String &)
void SetMultipleStepsInMSCTransport(G4bool val)
G4bool IsReferencePhysList(const G4String &)
Gaudi::Property< double > m_neutronEnergyCut
!< Time cut for neutrons (in the neutron killer process)
Gaudi::Property< double > m_emMaxEnergy
!< A general cut - this isn't normally used in our simulation
ToolHandleArray< IPhysicsOptionTool > m_phys_option
virtual void SetPhysicsOptions() override
Gaudi::Property< double > m_emMinEnergy
!< Maximum energy of the pre-calculated EM cross-section tables
Gaudi::Property< double > m_neutronTimeCut
!< Name for the physics list (property to be set in the tool)
Gaudi::Property< bool > m_applyEMCuts
!< Number of bins per Energy decade. Used for both DeDx and for the Lambda binning.
virtual void SetPhysicsList() override
Gaudi::Property< bool > m_multipleStepsInMSCTransport
!< Switch for the G4 "apply cuts" EM physics flag
Gaudi::Property< int > m_emNumberOfBinsPerDecade
!< Minimum energy of the pre-calculated EM cross-section tables
ToolHandle< IPhysicsOptionTool > m_fastSimulationConstructor
virtual StatusCode initialize() override
Gaudi::Property< bool > m_unstableAntiNeutrons
PhysicsListSvc(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< bool > m_quietMode
virtual G4VUserPhysicsList * GetPhysicsList() override
ToolHandleArray< IPhysicsOptionTool > m_phys_decay
Gaudi::Property< std::string > m_physicsListName
!< Handle on the physics list
G4VModularPhysicsList * m_physicsList
virtual void CreatePhysicsList() override
void CommandLog(int returnCode, const std::string &commandString) const
This command prints a message about a G4Command depending on its returnCode.
Gaudi::Property< double > m_generalCut
!< Energy cut for neutrons (in the neutron killer process)