Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VAtomDeexcitation.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// -------------------------------------------------------------------
28//
29// GEANT4 Class class file
30//
31//
32// File name: G4VAtomDeexcitation
33//
34// Author: Alfonso Mantero & Vladimir Ivanchenko
35//
36// Creation date: 21.04.2010
37//
38// Modifications:
39//
40// Class Description:
41//
42// Abstract interface to energy loss models
43
44// -------------------------------------------------------------------
45//
46
48#include "G4SystemOfUnits.hh"
50#include "G4DynamicParticle.hh"
51#include "G4Step.hh"
52#include "G4Region.hh"
53#include "G4RegionStore.hh"
56#include "G4Material.hh"
57#include "G4Element.hh"
58#include "G4ElementVector.hh"
59#include "Randomize.hh"
60#include "G4VParticleChange.hh"
62#include "G4Gamma.hh"
63
64#ifdef G4MULTITHREADED
65 G4Mutex G4VAtomDeexcitation::atomDeexcitationMutex = G4MUTEX_INITIALIZER;
66#endif
67
68//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
69
70G4int G4VAtomDeexcitation::pixeIDg = -1;
71G4int G4VAtomDeexcitation::pixeIDe = -1;
72
74 : verbose(1), name(modname), isActive(false), flagAuger(false),
75 flagAugerCascade(false), flagPIXE(false), ignoreCuts(false),
76 isActiveLocked(false), isAugerLocked(false),
77 isAugerCascadeLocked(false), isPIXELocked(false)
78{
79 theParameters = G4EmParameters::Instance();
80 vdyn.reserve(5);
81 theCoupleTable = nullptr;
82 G4String gg = "gammaPIXE";
83 G4String ee = "e-PIXE";
84 if(pixeIDg < 0) {
85#ifdef G4MULTITHREADED
86 G4MUTEXLOCK(&atomDeexcitationMutex);
87 if(pixeIDg < 0) {
88#endif
91#ifdef G4MULTITHREADED
92 }
93 G4MUTEXUNLOCK(&atomDeexcitationMutex);
94#endif
95 }
96 gamma = G4Gamma::Gamma();
97}
98
99//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
100
102{}
103
104//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
105
107{
108 theParameters->DefineRegParamForDeex(this);
109
110 // Define list of couples
112 G4int numOfCouples = theCoupleTable->GetTableSize();
113
114 // needed for unit tests
115 size_t nn = std::max(numOfCouples, 1);
116 if(activeDeexcitationMedia.size() != nn) {
117 activeDeexcitationMedia.resize(nn, false);
118 activeAugerMedia.resize(nn, false);
119 activePIXEMedia.resize(nn, false);
120 }
121 if(activeZ.size() != 93) { activeZ.resize(93, false); }
122
123 // initialisation of flags and options
124 // normally there is no locksed flags
125 if(!isActiveLocked) { isActive = theParameters->Fluo(); }
126 if(!isAugerLocked) { flagAuger = theParameters->Auger(); }
127 if(!isAugerCascadeLocked) { flagAugerCascade = theParameters->AugerCascade(); }
128 if(!isPIXELocked) { flagPIXE = theParameters->Pixe(); }
129 ignoreCuts = theParameters->DeexcitationIgnoreCut();
130
131 // Define list of regions
132 size_t nRegions = deRegions.size();
133 // check if deexcitation is active for the given run
134 if(!isActive && 0 == nRegions) { return; }
135
136 // if no active regions add a world
137 if(0 == nRegions) {
138 SetDeexcitationActiveRegion("World",isActive,flagAuger,flagPIXE);
139 nRegions = deRegions.size();
140 }
141
142 if(0 < verbose) {
143 G4cout << G4endl;
144 G4cout << "### === Deexcitation model " << name
145 << " is activated for " << nRegions;
146 if(1 == nRegions) { G4cout << " region:" << G4endl; }
147 else { G4cout << " regions:" << G4endl;}
148 }
149
150 // Identify active media
152 for(size_t j=0; j<nRegions; ++j) {
153 const G4Region* reg = regionStore->GetRegion(activeRegions[j], false);
154 if(reg && 0 < numOfCouples) {
155 const G4ProductionCuts* rpcuts = reg->GetProductionCuts();
156 if(0 < verbose) {
157 G4cout << " " << activeRegions[j]
158 << " " << deRegions[j] << " " << AugerRegions[j]
159 << " " << PIXERegions[j] << G4endl;
160 }
161 for(G4int i=0; i<numOfCouples; ++i) {
162 const G4MaterialCutsCouple* couple =
163 theCoupleTable->GetMaterialCutsCouple(i);
164 if (couple->GetProductionCuts() == rpcuts) {
165 activeDeexcitationMedia[i] = deRegions[j];
166 activeAugerMedia[i] = AugerRegions[j];
167 activePIXEMedia[i] = PIXERegions[j];
168 }
169 }
170 }
171 }
173 //G4cout << nelm << G4endl;
174 for(G4int k=0; k<nelm; ++k) {
175 G4int Z = (*(G4Element::GetElementTable()))[k]->GetZasInt();
176 if(Z > 5 && Z < 93) {
177 activeZ[Z] = true;
178 //G4cout << "!!! Active de-excitation Z= " << Z << G4endl;
179 }
180 }
181
182 // Initialise derived class
184
185 if(0 < verbose && flagAuger) {
186 G4cout << "### === Auger cascade flag: " << flagAugerCascade
187 << G4endl;
188 }
189 if(0 < verbose) {
190 G4cout << "### === Ignore cuts flag: " << ignoreCuts
191 << G4endl;
192 }
193 if(0 < verbose && flagPIXE) {
194 G4cout << "### === PIXE model for hadrons: "
195 << theParameters->PIXECrossSectionModel()
196 << G4endl;
197 G4cout << "### === PIXE model for e+-: "
198 << theParameters->PIXEElectronCrossSectionModel()
199 << G4endl;
200 }
201}
202
203//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
204
205void
207 G4bool valDeexcitation,
208 G4bool valAuger,
209 G4bool valPIXE)
210{
211 // no PIXE in parallel world
212 if(rname == "DefaultRegionForParallelWorld") { return; }
213
214 G4String ss = rname;
215 /*
216 G4cout << "### G4VAtomDeexcitation::SetDeexcitationActiveRegion " << ss
217 << " " << valDeexcitation << " " << valAuger
218 << " " << valPIXE << G4endl;
219 */
220 if(ss == "world" || ss == "World" || ss == "WORLD") {
221 ss = "DefaultRegionForTheWorld";
222 }
223 size_t n = deRegions.size();
224 for(size_t i=0; i<n; ++i) {
225
226 // Region already exist
227 if(ss == activeRegions[i]) {
228 deRegions[i] = valDeexcitation;
229 AugerRegions[i] = valAuger;
230 PIXERegions[i] = valPIXE;
231 return;
232 }
233 }
234 // New region
235 activeRegions.push_back(ss);
236 deRegions.push_back(valDeexcitation);
237 AugerRegions.push_back(valAuger);
238 PIXERegions.push_back(valPIXE);
239
240 // if de-excitation defined for the world volume
241 // it should be active for all G4Regions
242 if(ss == "DefaultRegionForTheWorld") {
244 G4int nn = regions->size();
245 for(G4int i=0; i<nn; ++i) {
246 if(ss == (*regions)[i]->GetName()) { continue; }
247 SetDeexcitationActiveRegion((*regions)[i]->GetName(), valDeexcitation,
248 valAuger, valPIXE);
249
250 }
251 }
252}
253
254void G4VAtomDeexcitation::GenerateParticles(std::vector<G4DynamicParticle*>* v,
255 const G4AtomicShell* as,
256 G4int Z, G4int idx)
257{
258 G4double gCut = DBL_MAX;
259 if(ignoreCuts) {
260 gCut = 0.0;
261 } else if (theCoupleTable) {
262 gCut = (*(theCoupleTable->GetEnergyCutsVector(0)))[idx];
263 }
264 if(gCut < as->BindingEnergy()) {
265 G4double eCut = DBL_MAX;
266 if(CheckAugerActiveRegion(idx)) {
267 if(ignoreCuts) {
268 eCut = 0.0;
269 } else if (theCoupleTable) {
270 eCut = (*(theCoupleTable->GetEnergyCutsVector(1)))[idx];
271 }
272 }
273 GenerateParticles(v, as, Z, gCut, eCut);
274 }
275}
276
277//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
278
279void
280G4VAtomDeexcitation::AlongStepDeexcitation(std::vector<G4Track*>& tracks,
281 const G4Step& step,
282 G4double& eLossMax,
283 G4int coupleIndex)
284{
285 G4double truelength = step.GetStepLength();
286 if(!flagPIXE && !activePIXEMedia[coupleIndex]) { return; }
287 if(eLossMax <= 0.0 || truelength <= 0.0) { return; }
288
289 // step parameters
290 const G4StepPoint* preStep = step.GetPreStepPoint();
291 G4ThreeVector prePos = preStep->GetPosition();
292 G4ThreeVector delta = step.GetPostStepPoint()->GetPosition() - prePos;
293 G4double preTime = preStep->GetGlobalTime();
294 G4double dt = step.GetPostStepPoint()->GetGlobalTime() - preTime;
295
296 // particle parameters
297 const G4Track* track = step.GetTrack();
298 const G4ParticleDefinition* part = track->GetDefinition();
299 G4double ekin = preStep->GetKineticEnergy();
300
301 // media parameters
302 G4double gCut = (*theCoupleTable->GetEnergyCutsVector(0))[coupleIndex];
303 if(ignoreCuts) { gCut = 0.0; }
304 G4double eCut = DBL_MAX;
305 if(CheckAugerActiveRegion(coupleIndex)) {
306 eCut = (*theCoupleTable->GetEnergyCutsVector(1))[coupleIndex];
307 if(ignoreCuts) { eCut = 0.0; }
308 }
309
310 //G4cout<<"!Sample PIXE gCut(MeV)= "<<gCut<<" eCut(MeV)= "<<eCut
311 // <<" Ekin(MeV)= " << ekin/MeV << G4endl;
312
313 const G4Material* material = preStep->GetMaterial();
314 const G4ElementVector* theElementVector = material->GetElementVector();
315 const G4double* theAtomNumDensityVector =
316 material->GetVecNbOfAtomsPerVolume();
317 G4int nelm = material->GetNumberOfElements();
318
319 // loop over deexcitations
320 for(G4int i=0; i<nelm; ++i) {
321 G4int Z = (*theElementVector)[i]->GetZasInt();
322 if(activeZ[Z] && Z < 93) {
323 G4int nshells =
324 std::min(9,(*theElementVector)[i]->GetNbOfAtomicShells());
325 G4double rho = truelength*theAtomNumDensityVector[i];
326 //G4cout<<" Z "<< Z <<" is active x(mm)= " << truelength/mm << G4endl;
327 for(G4int ii=0; ii<nshells; ++ii) {
329 const G4AtomicShell* shell = GetAtomicShell(Z, as);
330 G4double bindingEnergy = shell->BindingEnergy();
331
332 if(gCut > bindingEnergy) { break; }
333
334 if(eLossMax > bindingEnergy) {
335 G4double sig = rho*
336 GetShellIonisationCrossSectionPerAtom(part, Z, as, ekin, material);
337
338 // mfp is mean free path in units of step size
339 if(sig > 0.0) {
340 G4double mfp = 1.0/sig;
341 G4double stot = 0.0;
342 //G4cout << " Shell " << ii << " mfp(mm)= " << mfp/mm << G4endl;
343 // sample ionisation points
344 do {
345 stot -= mfp*std::log(G4UniformRand());
346 if( stot > 1.0 || eLossMax < bindingEnergy) { break; }
347 // sample deexcitation
348 vdyn.clear();
349 GenerateParticles(&vdyn, shell, Z, gCut, eCut);
350 G4int nsec = vdyn.size();
351 if(nsec > 0) {
352 G4ThreeVector r = prePos + stot*delta;
353 G4double time = preTime + stot*dt;
354 for(G4int j=0; j<nsec; ++j) {
355 G4DynamicParticle* dp = vdyn[j];
356 G4double e = dp->GetKineticEnergy();
357
358 // save new secondary if there is enough energy
359 if(eLossMax >= e) {
360 eLossMax -= e;
361 G4Track* t = new G4Track(dp, time, r);
362
363 // defined secondary type
364 if(dp->GetDefinition() == gamma) {
365 t->SetCreatorModelIndex(pixeIDg);
366 } else {
367 t->SetCreatorModelIndex(pixeIDe);
368 }
369
370 tracks.push_back(t);
371 } else {
372 delete dp;
373 }
374 }
375 }
376 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
377 } while (stot < 1.0);
378 }
379 }
380 }
381 }
382 }
383 return;
384}
385
386//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4AtomicShellEnumerator
std::vector< G4Element * > G4ElementVector
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
#define G4MUTEXLOCK(mutex)
Definition: G4Threading.hh:251
#define G4MUTEXUNLOCK(mutex)
Definition: G4Threading.hh:254
std::mutex G4Mutex
Definition: G4Threading.hh:81
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
G4double BindingEnergy() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4ElementTable * GetElementTable()
Definition: G4Element.cc:397
static size_t GetNumberOfElements()
Definition: G4Element.cc:404
static G4EmParameters * Instance()
const G4String & PIXECrossSectionModel()
const G4String & PIXEElectronCrossSectionModel()
G4bool Fluo() const
G4bool Pixe() const
void DefineRegParamForDeex(G4VAtomDeexcitation *) const
G4bool AugerCascade() const
G4bool DeexcitationIgnoreCut() const
G4bool Auger() const
static G4Gamma * Gamma()
Definition: G4Gamma.cc:85
G4ProductionCuts * GetProductionCuts() const
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:188
size_t GetNumberOfElements() const
Definition: G4Material.hh:184
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:204
static G4int Register(const G4String &)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
const std::vector< G4double > * GetEnergyCutsVector(std::size_t pcIdx) const
static G4ProductionCutsTable * GetProductionCutsTable()
static G4RegionStore * GetInstance()
G4Region * GetRegion(const G4String &name, G4bool verbose=true) const
G4ProductionCuts * GetProductionCuts() const
G4double GetGlobalTime() const
G4Material * GetMaterial() const
const G4ThreeVector & GetPosition() const
G4double GetKineticEnergy() const
Definition: G4Step.hh:62
G4Track * GetTrack() const
G4StepPoint * GetPreStepPoint() const
G4double GetStepLength() const
G4StepPoint * GetPostStepPoint() const
G4ParticleDefinition * GetDefinition() const
void SetCreatorModelIndex(G4int idx)
G4VAtomDeexcitation(const G4String &modname="Deexcitation")
virtual const G4AtomicShell * GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)=0
const G4String & GetName() const
G4bool CheckAugerActiveRegion(G4int coupleIndex)
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
void AlongStepDeexcitation(std::vector< G4Track * > &tracks, const G4Step &step, G4double &eLoss, G4int coupleIndex)
virtual G4double GetShellIonisationCrossSectionPerAtom(const G4ParticleDefinition *, G4int Z, G4AtomicShellEnumerator shell, G4double kinE, const G4Material *mat=nullptr)=0
void SetDeexcitationActiveRegion(const G4String &rname, G4bool valDeexcitation, G4bool valAuger, G4bool valPIXE)
virtual void InitialiseForNewRun()=0
#define DBL_MAX
Definition: templates.hh:62