Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4LivermoreIonisationModel.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// $Id$
27//
28// Author: Luciano Pandola
29// on base of G4LowEnergyIonisation developed by A.Forti and V.Ivanchenko
30//
31// History:
32// --------
33// 12 Jan 2009 L Pandola Migration from process to model
34// 03 Mar 2009 L Pandola Bug fix (release memory in the destructor)
35// 15 Apr 2009 V Ivanchenko Cleanup initialisation and generation of secondaries:
36// - apply internal high-energy limit only in constructor
37// - do not apply low-energy limit (default is 0)
38// - simplify sampling of deexcitation by using cut in energy
39// - set activation of Auger "false"
40// - remove initialisation of element selectors
41// 19 May 2009 L Pandola Explicitely set to zero pointers deleted in
42// Initialise(), since they might be checked later on
43// 23 Oct 2009 L Pandola
44// - atomic deexcitation managed via G4VEmModel::DeexcitationFlag() is
45// set as "true" (default would be false)
46// 12 Oct 2010 L Pandola
47// - add debugging information about energy in
48// SampleDeexcitationAlongStep()
49// - generate fluorescence SampleDeexcitationAlongStep() only above
50// the cuts.
51// 01 Jun 2011 V Ivanchenko general cleanup - all old deexcitation code removed
52//
53
56#include "G4SystemOfUnits.hh"
60#include "G4DynamicParticle.hh"
61#include "G4Element.hh"
63#include "G4Electron.hh"
65#include "G4VEMDataSet.hh"
68#include "G4VEnergySpectrum.hh"
71#include "G4AtomicShell.hh"
72
73//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
74
75
77 const G4String& nam) :
78 G4VEmModel(nam), fParticleChange(0),
79 isInitialised(false),
80 crossSectionHandler(0), energySpectrum(0)
81{
82 fIntrinsicLowEnergyLimit = 10.0*eV;
83 fIntrinsicHighEnergyLimit = 100.0*GeV;
84
85 verboseLevel = 0;
86
87 transitionManager = G4AtomicTransitionManager::Instance();
88}
89
90//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
91
93{
94 delete energySpectrum;
95 delete crossSectionHandler;
96}
97
98//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
99
101 const G4DataVector& cuts)
102{
103 //Check that the Livermore Ionisation is NOT attached to e+
104 if (particle != G4Electron::Electron())
105 {
106 G4Exception("G4LivermoreIonisationModel::Initialise",
107 "em0002",FatalException,"Livermore Ionisation Model is applicable only to electrons");
108 }
109
110 //Read energy spectrum
111 if (energySpectrum)
112 {
113 delete energySpectrum;
114 energySpectrum = 0;
115 }
116 energySpectrum = new G4eIonisationSpectrum();
117 if (verboseLevel > 3)
118 G4cout << "G4VEnergySpectrum is initialized" << G4endl;
119
120 //Initialize cross section handler
121 if (crossSectionHandler)
122 {
123 delete crossSectionHandler;
124 crossSectionHandler = 0;
125 }
126
127 const size_t nbins = 20;
128 G4double emin = LowEnergyLimit();
129 G4double emax = HighEnergyLimit();
130 G4int ndec = G4int(std::log10(emax/emin) + 0.5);
131 if(ndec <= 0) { ndec = 1; }
132
133 G4VDataSetAlgorithm* interpolation = new G4SemiLogInterpolation();
134 crossSectionHandler = new G4eIonisationCrossSectionHandler(energySpectrum,interpolation,
135 emin,emax,nbins*ndec);
136 crossSectionHandler->Clear();
137 crossSectionHandler->LoadShellData("ioni/ion-ss-cs-");
138 //This is used to retrieve cross section values later on
139 G4VEMDataSet* emdata =
140 crossSectionHandler->BuildMeanFreePathForMaterials(&cuts);
141 //The method BuildMeanFreePathForMaterials() is required here only to force
142 //the building of an internal table: the output pointer can be deleted
143 delete emdata;
144
145 if (verboseLevel > 0)
146 {
147 G4cout << "Livermore Ionisation model is initialized " << G4endl
148 << "Energy range: "
149 << LowEnergyLimit() / keV << " keV - "
150 << HighEnergyLimit() / GeV << " GeV"
151 << G4endl;
152 }
153
154 if (verboseLevel > 3)
155 {
156 G4cout << "Cross section data: " << G4endl;
157 crossSectionHandler->PrintData();
158 G4cout << "Parameters: " << G4endl;
159 energySpectrum->PrintData();
160 }
161
162 if(isInitialised) { return; }
164 isInitialised = true;
165}
166
167//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
168
171 G4double energy,
173 G4double cutEnergy,
174 G4double)
175{
176 G4int iZ = (G4int) Z;
177 if (!crossSectionHandler)
178 {
179 G4Exception("G4LivermoreIonisationModel::ComputeCrossSectionPerAtom",
180 "em1007",FatalException,"The cross section handler is not correctly initialized");
181 return 0;
182 }
183
184 //The cut is already included in the crossSectionHandler
185 G4double cs =
186 crossSectionHandler->GetCrossSectionAboveThresholdForElement(energy,cutEnergy,iZ);
187
188 if (verboseLevel > 1)
189 {
190 G4cout << "G4LivermoreIonisationModel " << G4endl;
191 G4cout << "Cross section for delta emission > " << cutEnergy/keV << " keV at " <<
192 energy/keV << " keV and Z = " << iZ << " --> " << cs/barn << " barn" << G4endl;
193 }
194 return cs;
195}
196
197
198//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
199
201 const G4ParticleDefinition* ,
202 G4double kineticEnergy,
203 G4double cutEnergy)
204{
205 G4double sPower = 0.0;
206
207 const G4ElementVector* theElementVector = material->GetElementVector();
208 size_t NumberOfElements = material->GetNumberOfElements() ;
209 const G4double* theAtomicNumDensityVector =
210 material->GetAtomicNumDensityVector();
211
212 // loop for elements in the material
213 for (size_t iel=0; iel<NumberOfElements; iel++ )
214 {
215 G4int iZ = (G4int)((*theElementVector)[iel]->GetZ());
216 G4int nShells = transitionManager->NumberOfShells(iZ);
217 for (G4int n=0; n<nShells; n++)
218 {
219 G4double e = energySpectrum->AverageEnergy(iZ, 0.0,cutEnergy,
220 kineticEnergy, n);
221 G4double cs= crossSectionHandler->FindValue(iZ,kineticEnergy, n);
222 sPower += e * cs * theAtomicNumDensityVector[iel];
223 }
224 G4double esp = energySpectrum->Excitation(iZ,kineticEnergy);
225 sPower += esp * theAtomicNumDensityVector[iel];
226 }
227
228 if (verboseLevel > 2)
229 {
230 G4cout << "G4LivermoreIonisationModel " << G4endl;
231 G4cout << "Stopping power < " << cutEnergy/keV << " keV at " <<
232 kineticEnergy/keV << " keV = " << sPower/(keV/mm) << " keV/mm" << G4endl;
233 }
234
235 return sPower;
236}
237
238//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
239
240void G4LivermoreIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
241 const G4MaterialCutsCouple* couple,
242 const G4DynamicParticle* aDynamicParticle,
243 G4double cutE,
244 G4double maxE)
245{
246
247 G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
248
249 if (kineticEnergy <= fIntrinsicLowEnergyLimit)
250 {
253 return;
254 }
255
256 // Select atom and shell
257 G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
258 G4int shellIndex = crossSectionHandler->SelectRandomShell(Z, kineticEnergy);
259 const G4AtomicShell* shell = transitionManager->Shell(Z,shellIndex);
260 G4double bindingEnergy = shell->BindingEnergy();
261
262 // Sample delta energy using energy interval for delta-electrons
263 G4double energyMax =
264 std::min(maxE,energySpectrum->MaxEnergyOfSecondaries(kineticEnergy));
265 G4double energyDelta = energySpectrum->SampleEnergy(Z, cutE, energyMax,
266 kineticEnergy, shellIndex);
267
268 if (energyDelta == 0.) //nothing happens
269 { return; }
270
271 // Transform to shell potential
272 G4double deltaKinE = energyDelta + 2.0*bindingEnergy;
273 G4double primaryKinE = kineticEnergy + 2.0*bindingEnergy;
274
275 // sampling of scattering angle neglecting atomic motion
276 G4double deltaMom = std::sqrt(deltaKinE*(deltaKinE + 2.0*electron_mass_c2));
277 G4double primaryMom = std::sqrt(primaryKinE*(primaryKinE + 2.0*electron_mass_c2));
278
279 G4double cost = deltaKinE * (primaryKinE + 2.0*electron_mass_c2)
280 / (deltaMom * primaryMom);
281 if (cost > 1.) { cost = 1.; }
282 G4double sint = std::sqrt((1. - cost)*(1. + cost));
283 G4double phi = twopi * G4UniformRand();
284 G4double dirx = sint * std::cos(phi);
285 G4double diry = sint * std::sin(phi);
286 G4double dirz = cost;
287
288 // Rotate to incident electron direction
289 G4ThreeVector primaryDirection = aDynamicParticle->GetMomentumDirection();
290 G4ThreeVector deltaDir(dirx,diry,dirz);
291 deltaDir.rotateUz(primaryDirection);
292 //Updated components
293 dirx = deltaDir.x();
294 diry = deltaDir.y();
295 dirz = deltaDir.z();
296
297 // Take into account atomic motion del is relative momentum of the motion
298 // kinetic energy of the motion == bindingEnergy in V.Ivanchenko model
299 cost = 2.0*G4UniformRand() - 1.0;
300 sint = std::sqrt(1. - cost*cost);
301 phi = twopi * G4UniformRand();
302 G4double del = std::sqrt(bindingEnergy *(bindingEnergy + 2.0*electron_mass_c2))
303 / deltaMom;
304 dirx += del* sint * std::cos(phi);
305 diry += del* sint * std::sin(phi);
306 dirz += del* cost;
307
308 // Find out new primary electron direction
309 G4double finalPx = primaryMom*primaryDirection.x() - deltaMom*dirx;
310 G4double finalPy = primaryMom*primaryDirection.y() - deltaMom*diry;
311 G4double finalPz = primaryMom*primaryDirection.z() - deltaMom*dirz;
312
313 //Ok, ready to create the delta ray
314 G4DynamicParticle* theDeltaRay = new G4DynamicParticle();
315 theDeltaRay->SetKineticEnergy(energyDelta);
316 G4double norm = 1.0/std::sqrt(dirx*dirx + diry*diry + dirz*dirz);
317 dirx *= norm;
318 diry *= norm;
319 dirz *= norm;
320 theDeltaRay->SetMomentumDirection(dirx, diry, dirz);
321 theDeltaRay->SetDefinition(G4Electron::Electron());
322 fvect->push_back(theDeltaRay);
323
324 //This is the amount of energy available for fluorescence
325 G4double theEnergyDeposit = bindingEnergy;
326
327 // fill ParticleChange
328 // changed energy and momentum of the actual particle
329 G4double finalKinEnergy = kineticEnergy - energyDelta - theEnergyDeposit;
330 if(finalKinEnergy < 0.0)
331 {
332 theEnergyDeposit += finalKinEnergy;
333 finalKinEnergy = 0.0;
334 }
335 else
336 {
337 G4double normLocal = 1.0/std::sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
338 finalPx *= normLocal;
339 finalPy *= normLocal;
340 finalPz *= normLocal;
341 fParticleChange->ProposeMomentumDirection(finalPx, finalPy, finalPz);
342 }
344
345 if (theEnergyDeposit < 0)
346 {
347 G4cout << "G4LivermoreIonisationModel: Negative energy deposit: "
348 << theEnergyDeposit/eV << " eV" << G4endl;
349 theEnergyDeposit = 0.0;
350 }
351
352 //Assign local energy deposit
354
355 if (verboseLevel > 1)
356 {
357 G4cout << "-----------------------------------------------------------" << G4endl;
358 G4cout << "Energy balance from G4LivermoreIonisation" << G4endl;
359 G4cout << "Incoming primary energy: " << kineticEnergy/keV << " keV" << G4endl;
360 G4cout << "-----------------------------------------------------------" << G4endl;
361 G4cout << "Outgoing primary energy: " << finalKinEnergy/keV << " keV" << G4endl;
362 G4cout << "Delta ray " << energyDelta/keV << " keV" << G4endl;
363 G4cout << "Fluorescence: " << (bindingEnergy-theEnergyDeposit)/keV << " keV" << G4endl;
364 G4cout << "Local energy deposit " << theEnergyDeposit/keV << " keV" << G4endl;
365 G4cout << "Total final state: " << (finalKinEnergy+energyDelta+bindingEnergy)
366 << " keV" << G4endl;
367 G4cout << "-----------------------------------------------------------" << G4endl;
368 }
369 return;
370}
371
372//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
373
std::vector< G4Element * > G4ElementVector
@ FatalException
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
double z() const
double x() const
double y() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:72
G4double BindingEnergy() const
G4AtomicShell * Shell(G4int Z, size_t shellIndex) const
static G4AtomicTransitionManager * Instance()
void SetMomentumDirection(const G4ThreeVector &aDirection)
const G4ThreeVector & GetMomentumDirection() const
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
G4double GetKineticEnergy() const
void SetKineticEnergy(G4double aEnergy)
static G4Electron * Electron()
Definition: G4Electron.cc:94
G4LivermoreIonisationModel(const G4ParticleDefinition *p=0, const G4String &processName="LowEnergyIoni")
G4ParticleChangeForLoss * fParticleChange
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
virtual G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy)
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:189
size_t GetNumberOfElements() const
Definition: G4Material.hh:185
const G4double * GetAtomicNumDensityVector() const
Definition: G4Material.hh:215
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4VEMDataSet * BuildMeanFreePathForMaterials(const G4DataVector *energyCuts=0)
void LoadShellData(const G4String &dataFile)
G4double FindValue(G4int Z, G4double e) const
G4int SelectRandomAtom(const G4MaterialCutsCouple *couple, G4double e) const
G4int SelectRandomShell(G4int Z, G4double e) const
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:529
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:522
G4ParticleChangeForLoss * GetParticleChangeForLoss()
Definition: G4VEmModel.cc:95
virtual G4double SampleEnergy(G4int Z, G4double minKineticEnergy, G4double maxKineticEnergy, G4double kineticEnergy, G4int shell=0, const G4ParticleDefinition *pd=0) const =0
virtual void PrintData() const =0
virtual G4double MaxEnergyOfSecondaries(G4double kineticEnergy, G4int Z=0, const G4ParticleDefinition *pd=0) const =0
virtual G4double Excitation(G4int Z, G4double kineticEnergy) const =0
virtual G4double AverageEnergy(G4int Z, G4double minKineticEnergy, G4double maxKineticEnergy, G4double kineticEnergy, G4int shell=0, const G4ParticleDefinition *pd=0) const =0
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double GetCrossSectionAboveThresholdForElement(G4double energy, G4double cutEnergy, G4int Z)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41