Geant4 VMC Version 6.6
Loading...
Searching...
No Matches
TG4ComposedPhysicsList.cxx
Go to the documentation of this file.
1//------------------------------------------------
2// The Geant4 Virtual Monte Carlo package
3// Copyright (C) 2007 - 2014 Ivana Hrivnacova
4// All rights reserved.
5//
6// For the licensing terms see geant4_vmc/LICENSE.
7// Contact: root-vmc@cern.ch
8//-------------------------------------------------
9
14
16#include "TG4G3PhysicsManager.h"
17#include "TG4PhysicsManager.h"
19
20#include <G4Electron.hh>
21#include <G4EmParameters.hh>
22#include <G4Gamma.hh>
23#include <G4GammaConversionToMuons.hh>
24#include <G4HadronicProcess.hh>
25#include <G4PhysicsListHelper.hh>
26#include <G4Positron.hh>
27#include <G4ProcessManager.hh>
28#include <G4ProcessTable.hh>
29#include <G4Proton.hh>
30#include <G4RegionStore.hh>
31#include <G4SystemOfUnits.hh>
32#include <G4Transportation.hh>
33#include <G4VUserPhysicsList.hh>
34
35namespace
36{
37
38G4Transportation* FindTransportation(
39 const G4ParticleDefinition* particleDefinition)
40{
41 const auto* processManager = particleDefinition->GetProcessManager();
42 return dynamic_cast<G4Transportation*>(
43 processManager->GetProcess("Transportation"));
44}
45
46G4String GetProcessTypeName(G4int hadronicProcessSubType)
47{
48 switch(hadronicProcessSubType) {
49 // G4HadronicProcessType
50 case fHadronElastic: return "HadronElastic"; break;
51 case fNeutronGeneral: return "NeutronGeneral"; break;
52 case fHadronInelastic: return "HadronInelastic"; break;
53 case fCapture: return "Capture"; break;
54 case fMuAtomicCapture: return "MuAtomicCapture"; break;
55 case fFission: return "Fission"; break;
56 case fHadronAtRest: return "HadronAtRest"; break;
57 case fLeptonAtRest: return "LeptonAtRest"; break;
58 case fChargeExchange: return "ChargeExchange"; break;
59 case fNuOscillation: return "NuOscillation"; break;
60 case fNuElectron: return "NuElectron"; break;
61 case fNuNucleus: return "NuNucleus"; break;
62 case fRadioactiveDecay:return "RadioactiveDecay"; break;
63 case fEMDissociation: return "EMDissociation"; break;
64 // TG4HadronicProcessType
65 case fElectronNuclear: return "ElectronNuclear"; break;
66 case fPositronNuclear: return "PositronNuclear"; break;
67 case fMuonNuclear: return "MuonNuclear"; break;
68 case fPhotoNuclear: return "PhotoNuclear"; break;
69 }
70
71 TString text;
72 text += hadronicProcessSubType;
74 "TG4ComposedPhysicsList", "GetProcessTypeName:",
75 "Unknown hadronic process type: " + text);
76 G4cout << hadronicProcessSubType << G4endl;
77 return "";
78}
79
80G4int GetProcessSubType(
81 const G4String& processTypeName, G4int& errorCode)
82{
83 errorCode = 0;
84
85 // G4HadronicProcessType
86 if (processTypeName == "HadronElastic") return fHadronElastic;
87 if (processTypeName == "NeutronGeneral") return fNeutronGeneral;
88 if (processTypeName == "HadronInelastic") return fHadronInelastic;
89 if (processTypeName == "Capture") return fCapture;
90 if (processTypeName == "MuAtomicCapture") return fMuAtomicCapture;
91 if (processTypeName == "Fission") return fFission;
92 if (processTypeName == "HadronAtRest") return fHadronAtRest;
93 if (processTypeName == "LeptonAtRest") return fLeptonAtRest;
94 if (processTypeName == "ChargeExchange") return fChargeExchange;
95 if (processTypeName == "NuOscillation") return fNuOscillation;
96 if (processTypeName == "NuElectron") return fNuElectron;
97 if (processTypeName == "NuNucleus") return fNuNucleus;
98 if (processTypeName == "RadioactiveDecay") return fRadioactiveDecay;
99 if (processTypeName == "EMDissociation") return fEMDissociation;
100
101 // TG4HadronicProcessType
102 if (processTypeName == "ElectronNuclear") return fElectronNuclear;
103 if (processTypeName == "PositronNuclear") return fPositronNuclear;
104 if (processTypeName == "MuonNuclear") return fMuonNuclear;
105 if (processTypeName == "PhotoNuclear") return fPhotoNuclear;
106
108 "TG4ComposedPhysicsList", "GetProcessSubType:",
109 "Unknown process type name: " + TString(processTypeName.data()));
110 errorCode = 1;
111 return fHadronInelastic;
112}
113
114G4VProcess* GetProcess(G4ParticleDefinition* particle, G4int processSubType)
115{
116 // Find a process of given sub type;
117 // print a warning if no process or more than one process exist
118
119 auto processList = particle->GetProcessManager()->GetProcessList();
120 std::vector<G4VProcess*> foundProcesses;
121 for (std::size_t i = 0; i < processList->size(); ++i) {
122 if ((*processList)[i]->GetProcessSubType() == processSubType) {
123 foundProcesses.push_back((*processList)[i]);
124 }
125 }
126
127 if (foundProcesses.empty()) {
128 TString text;
129 text += processSubType;
131 "TG4ComposedPhysicsList", "GetProcess:",
132 "Unknown process sub type: " + text);
133 return nullptr;
134 }
135
136 if (foundProcesses.size()>1) {
137 TString text;
138 text += processSubType;
140 "TG4ComposedPhysicsList", "GetProcess:",
141 "More than one process of sub type: " + text + " exists.");
142 }
143
144 return foundProcesses[0];
145}
146
147} // namespace
148
150
151//_____________________________________________________________________________
154 TG4Verbose("composedPhysicsList"),
155 fMessenger(this),
156 fPhysicsLists(),
157 fIsProductionCutsTableEnergyRange(false),
158 fProductionCutsTableEnergyMin(0.),
159 fProductionCutsTableEnergyMax(0.),
160 fGammaToMuonsCrossSectionFactor(-1.),
161 fLooperThresholdsLevel(fgkDefautLooperThresholdsLevel)
162{
164
165 if (VerboseLevel() > 1)
166 G4cout << "TG4ComposedPhysicsList::TG4ComposedPhysicsList" << G4endl;
167
168 SetVerboseLevel(TG4Verbose::VerboseLevel());
169}
170
171//_____________________________________________________________________________
173{
175
176 for (G4int i = 0; i < G4int(fPhysicsLists.size()); i++)
177 delete fPhysicsLists[i];
178}
179
180//
181// private methods
182//
183
184//_____________________________________________________________________________
186{
189
191 G4ParticleDefinition* gamma = G4Gamma::Gamma();
192 G4ProcessManager* processManager = gamma->GetProcessManager();
193 G4ProcessVector* processVector = processManager->GetProcessList();
194 G4bool done = false;
195 // get G4GammaConversionToMuons
196 for (size_t i = 0; i < processVector->length(); i++) {
197 G4GammaConversionToMuons* gammaToMuMu =
198 dynamic_cast<G4GammaConversionToMuons*>((*processVector)[i]);
199 if (gammaToMuMu) {
200 if (VerboseLevel() > 0) {
201 G4cout << "### Set gamma to muons cross section factor user value: "
203 }
204 gammaToMuMu->SetCrossSecFactor(fGammaToMuonsCrossSectionFactor);
205 done = true;
206 break;
207 }
208 }
209 if (!done) {
210 TG4Globals::Warning("TG4ComposedPhysicsList",
211 "ApplyGammaToMuonsCrossSectionFactor",
212 "Cannot set gamma to muons cross section factor, GammaToMuons must be "
213 "activated first.");
214 }
215 }
216}
217
218//_____________________________________________________________________________
220 const G4String& particleName, const G4String& processDef, G4double factor,
221 G4bool isProcessName)
222{
224
225 // get particle definition from G4ParticleTable
226 auto particleDefinition =
227 G4ParticleTable::GetParticleTable()->FindParticle(particleName);
228 if (particleDefinition == nullptr) {
229 TG4Globals::Warning("TG4ComposedPhysicsList", "ApplyCrossSectionFactor",
230 "G4ParticleTable::FindParticle() for particle " +
231 TString(particleName.data()) + " failed.");
232 return;
233 }
234
235 G4VProcess* process = nullptr;
236 if (isProcessName) {
237 // get process by name
238 process = particleDefinition->GetProcessManager()->GetProcess(processDef);
239 }
240 else {
241 // get process by type
242 G4int errorCode = 0;
243 auto processSubType = GetProcessSubType(processDef, errorCode);
244 if (errorCode > 0) {
245 TG4Globals::Warning("TG4ComposedPhysicsList", "ApplyCrossSectionFactor",
246 "GetProcessSubType for processTypeName " +
247 TString(processDef.data()) + " failed.");
248 return;
249 }
250 process = GetProcess(particleDefinition, processSubType);
251 // Cannot use G4HadronicProcessStore::FindProcess
252 // as we redefine some processes sub-types with our codes
253 }
254
255 if (process == nullptr) {
256 TString by = (isProcessName) ? " by name" : " by type";
257 TG4Globals::Warning("TG4ComposedPhysicsList", "ApplyCrossSectionFactor",
258 "Get process " + TString(processDef.data()) + by + " failed.");
259 return;
260 }
261
262 // check process type
263 if (process->GetProcessType() != fHadronic) {
264 TG4Globals::Warning("TG4ComposedPhysicsList", "ApplyCrossSectionFactor",
265 "Process " + TString(processDef.data()) + " is not hadronic.");
266 return;
267 }
268
269 // apply factor
270 (static_cast<G4HadronicProcess*>(process))->MultiplyCrossSectionBy(factor);
271
272 if (VerboseLevel() > 0) {
273 G4cout
274 << "### Applied cross section factor " << factor
275 << " for " << particleDefinition->GetParticleName()
276 << " process " << process->GetProcessName()
277 << " process type: " << GetProcessTypeName(process->GetProcessSubType())
278 << G4endl;
279 }
280}
281
282//_____________________________________________________________________________
284{
286
287 for (const auto& [particleName, processType, factor, isProcessName] :
289 ApplyCrossSectionFactor(particleName, processType, factor, isProcessName);
290 }
291}
292
293//_____________________________________________________________________________
295{
297 auto plHelper = G4PhysicsListHelper::GetPhysicsListHelper();
298 if (fLooperThresholdsLevel == 0) {
299 if (VerboseLevel() > 0) {
300 G4cout << "### Use low looper thresholds" << G4endl;
301 }
302 plHelper->UseLowLooperThresholds();
303 }
304 else if (fLooperThresholdsLevel == 1) {
305 // Do nothing: Geant4 defaults
306 }
307 else if (fLooperThresholdsLevel == 2) {
308 if (VerboseLevel() > 0) {
309 G4cout << "### Use high looper thresholds" << G4endl;
310 }
311 plHelper->UseHighLooperThresholds();
312 }
313 else {
314 TString message = "The level";
315 message += fLooperThresholdsLevel;
316 message += " is not supported (the value must be 0, 1 or 2.)";
318 "TG4ComposedPhysicsList", "SetPresetLooperThresholds", message);
319 }
320}
321
322//
323// public methods
324//
325
326//_____________________________________________________________________________
328{
330
331 fPhysicsLists.push_back(physicsList);
332}
333
334//_____________________________________________________________________________
336{
338
339 if (VerboseLevel() > 1)
340 G4cout << "TG4ComposedPhysicsList::ConstructParticle" << G4endl;
341
342 for (G4int i = 0; i < G4int(fPhysicsLists.size()); i++)
344
345 if (VerboseLevel() > 1)
346 G4cout << "TG4ComposedPhysicsList::ConstructParticle done" << G4endl;
347}
348
349//_____________________________________________________________________________
351{
353
354 if (VerboseLevel() > 1)
355 G4cout << "TG4ComposedPhysicsList::ConstructProcess" << G4endl;
356
357 // lock physics manager
359 g3PhysicsManager->Lock();
360
361 // set looper thresholds level
363
364 for (G4int i = 0; i < G4int(fPhysicsLists.size()); i++) {
365 fPhysicsLists[i]->ConstructProcess();
366 }
367
370 }
371
372 if (!fCrossSectionFactors.empty()) {
374 }
375
376 if (VerboseLevel() > 1)
378 // Print looper thresholds
379 auto transportation = FindTransportation(G4Electron::Electron());
380 if (transportation) {
381 transportation->ReportLooperThresholds();
382 }
383 }
384
385 G4cout << "TG4ComposedPhysicsList::ConstructProcess done" << G4endl;
386}
387
388//_____________________________________________________________________________
390{
392
393 if (VerboseLevel() > 1) G4cout << "TG4ComposedPhysicsList::SetCuts" << G4endl;
394
396 G4ProductionCutsTable::GetProductionCutsTable()->SetEnergyRange(
398 }
399
400 // Get default range cut values from physics manager
401 G4double rangeCutGam = TG4PhysicsManager::Instance()->GetCutForGamma();
402 G4double rangeCutEle = TG4PhysicsManager::Instance()->GetCutForElectron();
403 G4double rangeCutPos = TG4PhysicsManager::Instance()->GetCutForPositron();
404 G4double rangeCutPro = TG4PhysicsManager::Instance()->GetCutForProton();
405
406 // Set cut values for gamma at first and for e- second and next for e+,
407 // because some processes for e+/e- need cut values for gamma
408 SetCutValue(rangeCutGam, "gamma");
409 SetCutValue(rangeCutEle, "e-");
410 SetCutValue(rangeCutPos, "e+");
411 SetCutValue(rangeCutPro, "proton");
412
413 // Set the default production cuts to all already created regions.
414 // The cuts can be then further customized via VMC cuts or
415 // via Geant4 UI commands called after G4RunManager initialization
416 // (in VMC examples in g4config2.in macros)
417
418 // Loop over regions
419 G4RegionStore* regionStore = G4RegionStore::GetInstance();
420 for (G4int i = 0; i < G4int(regionStore->size()); i++) {
421 G4Region* region = (*regionStore)[i];
422
423 // skip regions which already have production cuts defined
424 if (region->GetProductionCuts()) continue;
425
426 G4ProductionCuts* cuts = new G4ProductionCuts();
427 cuts->SetProductionCut(rangeCutGam, 0);
428 cuts->SetProductionCut(rangeCutEle, 1);
429 cuts->SetProductionCut(rangeCutPos, 2);
430 cuts->SetProductionCut(rangeCutPro, 3);
431 region->SetProductionCuts(cuts);
432 }
433
434 if (VerboseLevel() > 0) DumpCutValuesTable();
435}
436
437//_____________________________________________________________________________
439{
441
442 SetParticleCuts(cut, G4Gamma::Gamma());
443}
444
445//_____________________________________________________________________________
447{
449
450 SetParticleCuts(cut, G4Electron::Electron());
451}
452
453//_____________________________________________________________________________
455{
457
458 SetParticleCuts(cut, G4Positron::Positron());
459}
460
461//_____________________________________________________________________________
463{
465
466 SetParticleCuts(cut, G4Proton::Proton());
467}
468
469//_____________________________________________________________________________
479
480//_____________________________________________________________________________
482 const G4String& particleName, const G4String& processTypeOrName,
483 G4double factor, G4bool isProcessName)
484{
488
489 fCrossSectionFactors.push_back(
490 std::make_tuple(particleName, processTypeOrName, factor, isProcessName));
491}
492
493//_____________________________________________________________________________
495{
497
498 G4cout << "Instantiated processes: " << G4endl;
499 G4cout << "======================= " << G4endl;
500
501 G4ProcessTable* processTable = G4ProcessTable::GetProcessTable();
502 G4ProcessTable::G4ProcNameVector* processNameList =
503 processTable->GetNameList();
504
505 for (G4int i = 0; i < G4int(processNameList->size()); i++) {
506 G4cout << " " << (*processNameList)[i] << G4endl;
507 }
508}
509
510//_____________________________________________________________________________
512{
514
515 G4cout << "Instantiated particles and processes: " << G4endl;
516 G4cout << "===================================== " << G4endl;
517
518 auto theParticleIterator = GetParticleIterator();
519 theParticleIterator->reset();
520 while ((*theParticleIterator)()) {
521 // print particle name
522 G4cout << "Particle: " << theParticleIterator->value()->GetParticleName()
523 << G4endl;
524
525 // dump particle processes
526 G4ProcessVector* processVector =
527 theParticleIterator->value()->GetProcessManager()->GetProcessList();
528 for (size_t i = 0; i < processVector->length(); i++)
529 (*processVector)[i]->DumpInfo();
530
531 G4cout << G4endl;
532 }
533}
534
535//_____________________________________________________________________________
537{
539
541}
542
543//_____________________________________________________________________________
545{
549
551 SetVerboseLevel(level);
552
553 for (G4int i = 0; i < G4int(fPhysicsLists.size()); i++) {
554 TG4Verbose* verbose = dynamic_cast<TG4Verbose*>(fPhysicsLists[i]);
555 if (verbose)
556 verbose->VerboseLevel(level);
557 else
558 fPhysicsLists[i]->SetVerboseLevel(level);
559 }
560}
Definition of the TG4ComposedPhysicsList class.
Definition of the TG4G3PhysicsManager class.
Definition of the TG4PhysicsManager class.
Definition of the TG4ProcessMapPhysics class.
G4bool fIsProductionCutsTableEnergyRange
Info if the production cuts table energy range is redefined by user.
static const G4double fgkDefautLooperThresholdsLevel
the default cut value
G4double fProductionCutsTableEnergyMax
The production cuts table energy range maximum redefined by user.
G4int fLooperThresholdsLevel
Looper threshold level (can have valuee 0,1,2)
void AddPhysicsList(G4VUserPhysicsList *physicsList)
G4double fProductionCutsTableEnergyMin
The production cuts table energy range minimum redefined by user.
virtual G4int VerboseLevel() const
std::vector< std::tuple< G4String, G4String, G4double, G4bool > > fCrossSectionFactors
Cross section factors by process type or name.
std::vector< G4VUserPhysicsList * > fPhysicsLists
physics lists
G4double fGammaToMuonsCrossSectionFactor
Gamma to muons cross section factor.
void SetProductionCutsTableEnergyRange(G4double min, G4double max)
void ApplyCrossSectionFactor(const G4String &particleName, const G4String &processDef, G4double value, G4bool isProcessName)
void SetCrossSectionFactor(const G4String &particleName, const G4String &processDef, G4double value, G4bool isProcessName)
Provides a Geant3 way control to Geant4 physics.
static TG4G3PhysicsManager * Instance()
static void Warning(const TString &className, const TString &methodName, const TString &text)
G4double GetCutForPositron() const
G4double GetCutForProton() const
static TG4PhysicsManager * Instance()
G4double GetCutForElectron() const
G4double GetCutForGamma() const
Base class for defining the verbose level and a common messenger.
Definition TG4Verbose.h:36
virtual G4int VerboseLevel() const
Definition TG4Verbose.h:78
virtual void VerboseLevel(G4int level)
Definition TG4Verbose.h:72
@ fPositronNuclear
@ fMuonNuclear
@ fElectronNuclear
@ fPhotoNuclear