source: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeIonisationModel.cc@ 1199

Last change on this file since 1199 was 1196, checked in by garnier, 16 years ago

update CVS release candidate geant4.9.3.01

File size: 60.2 KB
RevLine 
[968]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//
[1192]26// $Id: G4PenelopeIonisationModel.cc,v 1.10 2009/10/23 09:29:24 pandola Exp $
[1196]27// GEANT4 tag $Name: geant4-09-03-cand-01 $
[968]28//
29// Author: Luciano Pandola
30//
31// History:
32// --------
33// 26 Nov 2008 L Pandola Migration from process to model
[1055]34// 17 Apr 2009 V Ivanchenko Cleanup initialisation and generation of secondaries:
35// - apply internal high-energy limit only in constructor
36// - do not apply low-energy limit (default is 0)
37// - added MinEnergyCut method
38// - do not change track status
39// 19 May 2009 L Pandola Explicitely set to zero pointers deleted in
40// Initialise(), since they might be checked later on
[1192]41// 21 Oct 2009 L Pandola Remove un-necessary fUseAtomicDeexcitation flag - now managed by
42// G4VEmModel::DeexcitationFlag()
43// Add ActivateAuger() method
[968]44//
45
46#include "G4PenelopeIonisationModel.hh"
47#include "G4ParticleDefinition.hh"
48#include "G4MaterialCutsCouple.hh"
49#include "G4ProductionCutsTable.hh"
50#include "G4DynamicParticle.hh"
51#include "G4Element.hh"
52#include "G4AtomicTransitionManager.hh"
53#include "G4AtomicDeexcitation.hh"
54#include "G4AtomicShell.hh"
55#include "G4Gamma.hh"
56#include "G4Electron.hh"
57#include "G4Positron.hh"
58#include "G4CrossSectionHandler.hh"
59#include "G4AtomicDeexcitation.hh"
60#include "G4VEMDataSet.hh"
61
62//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
63
64
65G4PenelopeIonisationModel::G4PenelopeIonisationModel(const G4ParticleDefinition*,
66 const G4String& nam)
67 :G4VEmModel(nam),isInitialised(false),
68 kineticEnergy1(0.*eV),
69 cosThetaPrimary(1.0),
70 energySecondary(0.*eV),
71 cosThetaSecondary(0.0),
72 iOsc(-1),
73 crossSectionHandler(0),ionizationEnergy(0),
74 resonanceEnergy(0),occupationNumber(0),shellFlag(0),
75 theXSTable(0)
76{
77 fIntrinsicLowEnergyLimit = 100.0*eV;
78 fIntrinsicHighEnergyLimit = 100.0*GeV;
[1055]79 // SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
[968]80 SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
81 //
[1192]82 // Atomic deexcitation model activated by default
83 SetDeexcitationFlag(true);
[968]84 verboseLevel= 0;
85
86 // Verbosity scale:
87 // 0 = nothing
88 // 1 = warning for energy non-conservation
89 // 2 = details of energy budget
90 // 3 = calculation of cross sections, file openings, sampling of atoms
91 // 4 = entering in methods
92
93 //These vectors do not change when materials or cut change.
94 //Therefore I can read it at the constructor
95 ionizationEnergy = new std::map<G4int,G4DataVector*>;
96 resonanceEnergy = new std::map<G4int,G4DataVector*>;
97 occupationNumber = new std::map<G4int,G4DataVector*>;
98 shellFlag = new std::map<G4int,G4DataVector*>;
99
100 ReadData(); //Read data from file
101
102}
103
104//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
105
106G4PenelopeIonisationModel::~G4PenelopeIonisationModel()
107{
108
109 if (crossSectionHandler) delete crossSectionHandler;
110
111 if (theXSTable)
112 {
113 for (size_t i=0; i<theXSTable->size(); i++)
114 delete (*theXSTable)[i];
115 delete theXSTable;
116 }
117
118
119 std::map <G4int,G4DataVector*>::iterator i;
120 for (i=ionizationEnergy->begin();i != ionizationEnergy->end();i++)
121 if (i->second) delete i->second;
122 for (i=resonanceEnergy->begin();i != resonanceEnergy->end();i++)
123 if (i->second) delete i->second;
124 for (i=occupationNumber->begin();i != occupationNumber->end();i++)
125 if (i->second) delete i->second;
126 for (i=shellFlag->begin();i != shellFlag->end();i++)
127 if (i->second) delete i->second;
128
129 if (ionizationEnergy)
130 delete ionizationEnergy;
131 if (resonanceEnergy)
132 delete resonanceEnergy;
133 if (occupationNumber)
134 delete occupationNumber;
135 if (shellFlag)
136 delete shellFlag;
137}
138
139//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
140
141void G4PenelopeIonisationModel::Initialise(const G4ParticleDefinition* particle,
142 const G4DataVector& cuts)
143{
144 if (verboseLevel > 3)
145 G4cout << "Calling G4PenelopeIonisationModel::Initialise()" << G4endl;
146
147 //Delete and re-initialize the cross section handler
148 if (crossSectionHandler)
149 {
150 crossSectionHandler->Clear();
151 delete crossSectionHandler;
[1055]152 crossSectionHandler = 0;
[968]153 }
154
155 if (theXSTable)
156 {
157 for (size_t i=0; i<theXSTable->size(); i++)
[1055]158 {
159 delete (*theXSTable)[i];
160 (*theXSTable)[i] = 0;
161 }
[968]162 delete theXSTable;
[1055]163 theXSTable = 0;
[968]164 }
165
166 crossSectionHandler = new G4CrossSectionHandler();
167 crossSectionHandler->Clear();
168 G4String crossSectionFile = "NULL";
169
170 if (particle == G4Electron::Electron())
171 crossSectionFile = "penelope/ion-cs-el-";
172 else if (particle == G4Positron::Positron())
173 crossSectionFile = "penelope/ion-cs-po-";
174 crossSectionHandler->LoadData(crossSectionFile);
175 //This is used to retrieve cross section values later on
176 crossSectionHandler->BuildMeanFreePathForMaterials();
[1055]177
178 InitialiseElementSelectors(particle,cuts);
[968]179
[1055]180 if (verboseLevel > 2)
[968]181 G4cout << "Loaded cross section files for PenelopeIonisationModel" << G4endl;
182
[1055]183 if (verboseLevel > 2) {
184 G4cout << "Penelope Ionisation model is initialized " << G4endl
185 << "Energy range: "
186 << LowEnergyLimit() / keV << " keV - "
187 << HighEnergyLimit() / GeV << " GeV"
188 << G4endl;
189 }
[968]190
191 if(isInitialised) return;
[1055]192 fParticleChange = GetParticleChangeForLoss();
[968]193 isInitialised = true;
194}
195
196//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
197
198G4double G4PenelopeIonisationModel::CrossSectionPerVolume(const G4Material* material,
199 const G4ParticleDefinition* theParticle,
200 G4double energy,
201 G4double cutEnergy,
202 G4double)
203{
204 // Penelope model to calculate the cross section for inelastic collisions above the
205 // threshold. It makes use of the Generalised Oscillator Strength (GOS) model from
206 // D. Liljequist, J. Phys. D: Appl. Phys. 16 (1983) 1567
207 //
208 // The total cross section (hard+soft) is read from a database file (element per
209 // element), while the ratio hard-to-total is calculated analytically by taking
210 // into account the atomic oscillators coming into the play for a given threshold.
211 // This is done by the method CalculateCrossSectionsRatio().
212 // For incident e- the maximum energy allowed for the delta-rays is energy/2.
213 // because particles are undistinghishable.
214 //
215 // The contribution is splitted in three parts: distant longitudinal collisions,
216 // distant transverse collisions and close collisions. Each term is described by
217 // its own analytical function.
218 // Fermi density correction is calculated analytically according to
219 // U. Fano, Ann. Rev. Nucl. Sci. 13 (1963),1
220 //
221 if (verboseLevel > 3)
222 G4cout << "Calling CrossSectionPerVolume() of G4PenelopeIonisationModel" << G4endl;
223
224 SetupForMaterial(theParticle, material, energy);
225
[1055]226 // VI - should be check at initialisation not in run time
227 /*
[968]228 if (!crossSectionHandler)
229 {
230 G4cout << "G4PenelopeIonisationModel::CrossSectionPerVolume" << G4endl;
231 G4cout << "The cross section handler is not correctly initialized" << G4endl;
232 G4Exception();
233 }
[1055]234 */
[968]235 if (!theXSTable)
236 {
237 if (verboseLevel > 2)
238 {
239 G4cout << "G4PenelopeIonisationModel::CrossSectionPerVolume" << G4endl;
240 G4cout << "Going to build Cross Section table " << G4endl;
241 }
242 theXSTable = new std::vector<G4VEMDataSet*>;
243 theXSTable = BuildCrossSectionTable(theParticle);
244 }
[1055]245
[968]246 G4double totalCross = 0.0;
247 G4double cross = 0.0;
248 const G4ElementVector* theElementVector = material->GetElementVector();
249 const G4double* theAtomNumDensityVector = material->GetVecNbOfAtomsPerVolume();
250 G4double electronVolumeDensity =
251 material->GetTotNbOfElectPerVolume(); //electron density
252
253 if (verboseLevel > 4)
254 G4cout << "Electron volume density of " << material->GetName() << ": " <<
255 electronVolumeDensity*cm3 << " electrons/cm3" << G4endl;
256
257 G4int nelm = material->GetNumberOfElements();
258 for (G4int i=0; i<nelm; i++)
259 {
260 G4int iZ = (G4int) (*theElementVector)[i]->GetZ();
261 G4double ratio = CalculateCrossSectionsRatio(energy,cutEnergy,iZ,electronVolumeDensity,
262 theParticle);
263 cross += theAtomNumDensityVector[i]*
264 crossSectionHandler->FindValue(iZ,energy)*ratio;
265 totalCross += theAtomNumDensityVector[i]*
266 crossSectionHandler->FindValue(iZ,energy);
267 }
268
269 if (verboseLevel > 2)
270 {
271 G4cout << "G4PenelopeIonisationModel " << G4endl;
272 G4cout << "Mean free path for delta emission > " << cutEnergy/keV << " keV at " <<
273 energy/keV << " keV = " << (1./cross)/mm << " mm" << G4endl;
274 G4cout << "Total free path for ionisation (no threshold) at " <<
275 energy/keV << " keV = " << (1./totalCross)/mm << " mm" << G4endl;
276 }
277 return cross;
278}
279
280//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
281
282G4double G4PenelopeIonisationModel::ComputeDEDXPerVolume(const G4Material* material,
283 const G4ParticleDefinition* theParticle,
284 G4double kineticEnergy,
285 G4double cutEnergy)
286{
287 // Penelope model to calculate the stopping power for soft inelastic collisions
288 // below the threshold. It makes use of the Generalised Oscillator Strength (GOS)
289 // model from
290 // D. Liljequist, J. Phys. D: Appl. Phys. 16 (1983) 1567
291 //
292 // The stopping power is calculated analytically using the dsigma/dW cross
293 // section from the GOS models, which includes separate contributions from
294 // distant longitudinal collisions, distant transverse collisions and
295 // close collisions. Only the atomic oscillators that come in the play
296 // (according to the threshold) are considered for the calculation.
297 // Differential cross sections have a different form for e+ and e-.
298 //
299 // Fermi density correction is calculated analytically according to
300 // U. Fano, Ann. Rev. Nucl. Sci. 13 (1963),1
301
302 if (verboseLevel > 3)
303 G4cout << "Calling ComputeDEDX() of G4PenelopeIonisationModel" << G4endl;
304
305 G4double sPower = 0.0;
306 const G4ElementVector* theElementVector = material->GetElementVector();
307 const G4double* theAtomNumDensityVector = material->GetVecNbOfAtomsPerVolume();
308 G4double electronVolumeDensity =
309 material->GetTotNbOfElectPerVolume(); //electron density
310
311 //Loop on the elements in the material
312 G4int nelm = material->GetNumberOfElements();
313 for (G4int i=0; i<nelm; i++)
314 {
315 G4int iZ = (G4int) (*theElementVector)[i]->GetZ();
316
317 //Calculate stopping power contribution from each element
318 //Constants
319 G4double gamma = 1.0+kineticEnergy/electron_mass_c2;
320 G4double gamma2 = gamma*gamma;
321 G4double beta2 = (gamma2-1.0)/gamma2;
322 G4double constant = pi*classic_electr_radius*classic_electr_radius
323 *2.0*electron_mass_c2/beta2;
324
325 G4double delta = CalculateDeltaFermi(kineticEnergy,iZ,electronVolumeDensity);
326 G4int nbOsc = (G4int) resonanceEnergy->find(iZ)->second->size();
327 G4double stoppingPowerForElement = 0.0;
328 //Loop on oscillators of element Z
329 for (G4int iosc=0;iosc<nbOsc;iosc++)
330 {
331 G4double S1 = 0.0;
332 G4double resEnergy = (*(resonanceEnergy->find(iZ)->second))[iosc];
333 if (theParticle == G4Electron::Electron())
334 S1 = ComputeStoppingPowerForElectrons(kineticEnergy,cutEnergy,delta,resEnergy);
335 else if (theParticle == G4Positron::Positron())
336 S1 = ComputeStoppingPowerForPositrons(kineticEnergy,cutEnergy,delta,resEnergy);
337 G4double occupNb = (*(occupationNumber->find(iZ)->second))[iosc];
338 stoppingPowerForElement += occupNb*constant*S1;
339 }
340
341 sPower += stoppingPowerForElement*theAtomNumDensityVector[i];
342 }
343 if (verboseLevel > 2)
344 {
345 G4cout << "G4PenelopeIonisationModel " << G4endl;
346 G4cout << "Stopping power < " << cutEnergy/keV << " keV at " <<
347 kineticEnergy/keV << " keV = " << sPower/(keV/mm) << " keV/mm" << G4endl;
348 }
349 return sPower;
350}
351
352//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
353
354void G4PenelopeIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
355 const G4MaterialCutsCouple* couple,
356 const G4DynamicParticle* aDynamicParticle,
[1055]357 G4double cutE, G4double)
[968]358{
359 // Penelope model to sample the final state following an hard inelastic interaction.
360 // It makes use of the Generalised Oscillator Strength (GOS) model from
361 // D. Liljequist, J. Phys. D: Appl. Phys. 16 (1983) 1567
362 //
363 // The GOS model is used to calculate the individual cross sections for all
364 // the atomic oscillators coming in the play, taking into account the three
365 // contributions (distant longitudinal collisions, distant transverse collisions and
366 // close collisions). Then the target shell and the interaction channel are
367 // sampled. Final state of the delta-ray (energy, angle) are generated according
368 // to the analytical distributions (dSigma/dW) for the selected interaction
369 // channels.
370 // For e-, the maximum energy for the delta-ray is initialEnergy/2. (because
371 // particles are indistinghusbable), while it is the full initialEnergy for
372 // e+.
373 // The efficiency of the random sampling algorithm (e.g. for close collisions)
374 // decreases when initial and cutoff energy increase (e.g. 87% for 10-keV primary
375 // and 1 keV threshold, 99% for 10-MeV primary and 10-keV threshold).
376 // Differential cross sections have a different form for e+ and e-.
377 //
378 // WARNING: The model provides an _average_ description of inelastic collisions.
379 // Anyway, the energy spectrum associated to distant excitations of a given
380 // atomic shell is approximated as a single resonance. The simulated energy spectra
381 // show _unphysical_ narrow peaks at energies that are multiple of the shell
382 // resonance energies. The spurious speaks are automatically smoothed out after
383 // multiple inelastic collisions.
384 //
385 // The model determines also the original shell from which the delta-ray is expelled,
386 // in order to produce fluorescence de-excitation (from G4DeexcitationManager)
387 //
388 // Fermi density correction is calculated analytically according to
389 // U. Fano, Ann. Rev. Nucl. Sci. 13 (1963),1
390
391 if (verboseLevel > 3)
392 G4cout << "Calling SamplingSecondaries() of G4PenelopeIonisationModel" << G4endl;
393
394 G4double kineticEnergy0 = aDynamicParticle->GetKineticEnergy();
395 const G4ParticleDefinition* theParticle = aDynamicParticle->GetDefinition();
396
[1055]397 if (kineticEnergy0 <= fIntrinsicLowEnergyLimit)
[968]398 {
399 fParticleChange->SetProposedKineticEnergy(0.);
400 fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy0);
401 return ;
402 }
403 const G4double electronVolumeDensity =
404 couple->GetMaterial()->GetTotNbOfElectPerVolume();
405 G4ParticleMomentum particleDirection0 = aDynamicParticle->GetMomentumDirection();
406
407 //Initialise final-state variables. The proper values will be set by the methods
408 // CalculateDiscreteForElectrons() and CalculateDiscreteForPositrons()
409 kineticEnergy1=kineticEnergy0;
410 cosThetaPrimary=1.0;
411 energySecondary=0.0;
412 cosThetaSecondary=1.0;
413
414 // Select randomly one element in the current material
415 if (verboseLevel > 2)
416 G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl;
417
418 //Use sampler of G4CrossSectionHandler for now
419 // atom can be selected effitiantly if element selectors are initialised
420 //const G4Element* anElement = SelectRandomAtom(couple,theParticle,kineticEnergy0);
421
422 G4int iZ = SampleRandomAtom(couple,kineticEnergy0);
423
424 const G4ProductionCutsTable* theCoupleTable=
425 G4ProductionCutsTable::GetProductionCutsTable();
426 size_t indx = couple->GetIndex();
427 G4double cutG = (*(theCoupleTable->GetEnergyCutsVector(0)))[indx];
428
429 if (verboseLevel > 2)
430 G4cout << "Selected Z = " << iZ << G4endl;
431
432 // The method CalculateDiscreteForXXXX() set the private variables:
433 // kineticEnergy1 = energy of the primary electron/positron after the interaction
434 // cosThetaPrimary = std::cos(theta) of the primary after the interaction
435 // energySecondary = energy of the secondary electron
436 // cosThetaSecondary = std::cos(theta) of the secondary
437 if (theParticle == G4Electron::Electron())
438 CalculateDiscreteForElectrons(kineticEnergy0,cutE,iZ,electronVolumeDensity);
439 else if (theParticle == G4Positron::Positron())
440 CalculateDiscreteForPositrons(kineticEnergy0,cutE,iZ,electronVolumeDensity);
441
442 // if (energySecondary == 0) return;
443
444 //Update the primary particle
445 G4double sint = std::sqrt(1. - cosThetaPrimary*cosThetaPrimary);
446 G4double phi = twopi * G4UniformRand();
447 G4double dirx = sint * std::cos(phi);
448 G4double diry = sint * std::sin(phi);
449 G4double dirz = cosThetaPrimary;
450
451 G4ThreeVector electronDirection1(dirx,diry,dirz);
452 electronDirection1.rotateUz(particleDirection0);
453
454 if (kineticEnergy1 > 0)
455 {
456 fParticleChange->ProposeMomentumDirection(electronDirection1);
457 fParticleChange->SetProposedKineticEnergy(kineticEnergy1);
458 }
459 else
460 {
[1055]461 fParticleChange->SetProposedKineticEnergy(0.);
[968]462 }
463
464 //Generate the delta ray
465 G4int iosc2 = 0;
466 G4double ioniEnergy = 0.0;
467 if (iOsc > 0) {
468 ioniEnergy=(*(ionizationEnergy->find(iZ)->second))[iOsc];
469 iosc2 = (ionizationEnergy->find(iZ)->second->size()) - iOsc; //they are in reversed order
470 }
471
472 const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
473 G4double bindingEnergy = 0.0;
474 G4int shellId = 0;
475 if (iOsc > 0)
476 {
477 const G4AtomicShell* shell = transitionManager->Shell(iZ,iosc2-1); // Modified by Alf
478 bindingEnergy = shell->BindingEnergy();
479 shellId = shell->ShellId();
480 }
481
482 G4double ionEnergy = bindingEnergy; //energy spent to ionise the atom according to G4dabatase
483 G4double eKineticEnergy = energySecondary;
484
485 //This is an awful thing: Penelope generates the fluorescence only for L and K shells
486 //(i.e. Osc = 1 --> 4). For high-Z, the other shells can be quite relevant. In this case
487 //one MUST ensure ''by hand'' the energy conservation. Then there is the other problem that
488 //the fluorescence database of Penelope doesn not match that of Geant4.
489
490 G4double energyBalance = kineticEnergy0 - kineticEnergy1 - energySecondary; //Penelope Balance
491
492 if (std::abs(energyBalance) < 1*eV)
493 //in this case Penelope didn't subtract the fluorescence energy: do here by hand
494 eKineticEnergy = energySecondary - bindingEnergy;
495 else
496 //Penelope subtracted the fluorescence, but one has to match the databases
497 eKineticEnergy = energySecondary+ioniEnergy-bindingEnergy;
[1055]498
[968]499 G4double localEnergyDeposit = ionEnergy;
500 G4double energyInFluorescence = 0.0*eV;
501
[1055]502 if(DeexcitationFlag() && iZ > 5)
[968]503 {
[1055]504 if (ionEnergy > cutG || ionEnergy > cutE)
[968]505 {
[1055]506 deexcitationManager.SetCutForSecondaryPhotons(cutG);
507 deexcitationManager.SetCutForAugerElectrons(cutE);
508 std::vector<G4DynamicParticle*> *photonVector =
509 deexcitationManager.GenerateParticles(iZ,shellId);
510 //Check for secondaries
511 if(photonVector)
[968]512 {
[1055]513 for (size_t k=0;k<photonVector->size();k++)
[968]514 {
[1055]515 G4DynamicParticle* aPhoton = (*photonVector)[k];
516 if (aPhoton)
[968]517 {
[1055]518 G4double itsEnergy = aPhoton->GetKineticEnergy();
519 if (itsEnergy <= localEnergyDeposit)
520 {
521 if(aPhoton->GetDefinition() == G4Gamma::Gamma())
522 energyInFluorescence += itsEnergy;
523 localEnergyDeposit -= itsEnergy;
524 fvect->push_back(aPhoton);
525 }
526 else
527 {
528 delete aPhoton;
529 (*photonVector)[k] = 0;
530 }
[968]531 }
532 }
[1055]533 delete photonVector;
[968]534 }
535 }
536 }
537
538 // Generate the delta ray
539 G4double sin2 = std::sqrt(1. - cosThetaSecondary*cosThetaSecondary);
540 G4double phi2 = twopi * G4UniformRand();
541
542 G4double xEl = sin2 * std::cos(phi2);
543 G4double yEl = sin2 * std::sin(phi2);
544 G4double zEl = cosThetaSecondary;
545 G4ThreeVector eDirection(xEl,yEl,zEl); //electron direction
546 eDirection.rotateUz(particleDirection0);
547
548 G4DynamicParticle* deltaElectron = new G4DynamicParticle (G4Electron::Electron(),
549 eDirection,eKineticEnergy) ;
550 fvect->push_back(deltaElectron);
551
552 if (localEnergyDeposit < 0)
553 {
554 G4cout << "WARNING-"
555 << "G4PenelopeIonisationModel::SampleSecondaries - Negative energy deposit"
556 << G4endl;
557 localEnergyDeposit=0.;
558 }
559 fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
560
561 if (verboseLevel > 1)
562 {
563 G4cout << "-----------------------------------------------------------" << G4endl;
564 G4cout << "Energy balance from G4PenelopeIonisation" << G4endl;
565 G4cout << "Incoming primary energy: " << kineticEnergy0/keV << " keV" << G4endl;
566 G4cout << "-----------------------------------------------------------" << G4endl;
567 G4cout << "Outgoing primary energy: " << kineticEnergy1/keV << " keV" << G4endl;
568 G4cout << "Delta ray " << eKineticEnergy/keV << " keV" << G4endl;
569 G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
570 G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
571 G4cout << "Total final state: " << (eKineticEnergy+energyInFluorescence+kineticEnergy1+
572 localEnergyDeposit)/keV <<
573 " keV" << G4endl;
574 G4cout << "-----------------------------------------------------------" << G4endl;
575 }
576 if (verboseLevel > 0)
577 {
578 G4double energyDiff = std::fabs(eKineticEnergy+energyInFluorescence+kineticEnergy1+
579 localEnergyDeposit-kineticEnergy0);
580 if (energyDiff > 0.05*keV)
581 G4cout << "Warning from G4PenelopeIonisation: problem with energy conservation: " <<
582 (eKineticEnergy+energyInFluorescence+kineticEnergy1+localEnergyDeposit)/keV <<
583 " keV (final) vs. " <<
584 kineticEnergy0/keV << " keV (initial)" << G4endl;
585 }
586}
587
588//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
589
590void G4PenelopeIonisationModel::ReadData()
591{
592 if (verboseLevel > 2)
593 {
594 G4cout << "Data from G4PenelopeIonisationModel read " << G4endl;
595 }
596 char* path = getenv("G4LEDATA");
597 if (!path)
598 {
599 G4String excep = "G4PenelopeIonisationModel - G4LEDATA environment variable not set!";
600 G4Exception(excep);
601 }
602 G4String pathString(path);
603 G4String pathFile = pathString + "/penelope/ion-pen.dat";
604 std::ifstream file(pathFile);
605
606 if (!file.is_open())
607 {
608 G4String excep = "G4PenelopeIonisationModel - data file " + pathFile + " not found!";
609 G4Exception(excep);
610 }
611
612 if (!ionizationEnergy || !resonanceEnergy || !occupationNumber || !shellFlag)
613 {
614 G4String excep = "G4PenelopeIonisationModel: problem with reading data from file";
615 G4Exception(excep);
616 }
617
618 G4int Z=1,nLevels=0;
619 G4int test,test1;
620
621 do{
622 G4DataVector* occVector = new G4DataVector;
623 G4DataVector* ionEVector = new G4DataVector;
624 G4DataVector* resEVector = new G4DataVector;
625 G4DataVector* shellIndVector = new G4DataVector;
626 file >> Z >> nLevels;
627 G4double a1,a2,a3,a4;
628 G4int k1,k2,k3;
629 for (G4int h=0;h<nLevels;h++)
630 {
631 //index,occup number,ion energy,res energy,fj0,kz,shell flag
632 file >> k1 >> a1 >> a2 >> a3 >> a4 >> k2 >> k3;
633 //Make explicit unit of measurements for ionisation and resonance energy,
634 // which is MeV
635 a2 *= MeV;
636 a3 *= MeV;
637 //
638 occVector->push_back(a1);
639 ionEVector->push_back(a2);
640 resEVector->push_back(a3);
641 shellIndVector->push_back((G4double) k3);
642 }
643 //Ok, done for element Z
644 occupationNumber->insert(std::make_pair(Z,occVector));
645 ionizationEnergy->insert(std::make_pair(Z,ionEVector));
646 resonanceEnergy->insert(std::make_pair(Z,resEVector));
647 shellFlag->insert(std::make_pair(Z,shellIndVector));
648 file >> test >> test1; //-1 -1 close the data for each Z
649 if (test > 0) {
650 G4String excep = "G4PenelopeIonisationModel - data file corrupted!";
651 G4Exception(excep);
652 }
653 }while (test != -2); //the very last Z is closed with -2 instead of -1
654}
655
656
657//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
658
659G4double G4PenelopeIonisationModel::CalculateDeltaFermi(G4double kinEnergy ,G4int Z,
660 G4double electronVolumeDensity)
661{
662 G4double plasmaEnergyCoefficient = 1.377e-39*(MeV*MeV*m3); //(e*hbar)^2/(epsilon0*electron_mass)
663 G4double plasmaEnergySquared = plasmaEnergyCoefficient*electronVolumeDensity;
664 // std::sqrt(plasmaEnergySquared) is the plasma energy of the solid (MeV)
665 G4double gam = 1.0+kinEnergy/electron_mass_c2;
666 G4double gam2=gam*gam;
667 G4double delta = 0.0;
668
669 //Density effect
670 G4double TST = ((G4double) Z)/(gam2*plasmaEnergySquared);
671
672 G4double wl2 = 0.0;
673 G4double fdel=0.0;
674 G4double wr=0;
675 size_t nbOsc = resonanceEnergy->find(Z)->second->size();
676 for(size_t i=0;i<nbOsc;i++)
677 {
678 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[i];
679 wr = (*(resonanceEnergy->find(Z)->second))[i];
680 fdel += occupNb/(wr*wr+wl2);
681 }
682 if (fdel < TST) return delta;
683 G4double help1 = (*(resonanceEnergy->find(Z)->second))[nbOsc-1];
684 wl2 = help1*help1;
685 do{
686 wl2=wl2*2.0;
687 fdel = 0.0;
688 for (size_t ii=0;ii<nbOsc;ii++){
689 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[ii];
690 wr = (*(resonanceEnergy->find(Z)->second))[ii];
691 fdel += occupNb/(wr*wr+wl2);
692 }
693 }while (fdel > TST);
694 G4double wl2l=0.0;
695 G4double wl2u = wl2;
696 G4double control = 0.0;
697 do{
698 wl2=0.5*(wl2l+wl2u);
699 fdel = 0.0;
700 for (size_t jj=0;jj<nbOsc;jj++){
701 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[jj];
702 wr = (*(resonanceEnergy->find(Z)->second))[jj];
703 fdel += occupNb/(wr*wr+wl2);
704 }
705 if (fdel > TST)
706 wl2l = wl2;
707 else
708 wl2u = wl2;
709 control = wl2u-wl2l-wl2*1e-12;
710 }while(control>0);
711
712 //Density correction effect
713 for (size_t kk=0;kk<nbOsc;kk++){
714 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[kk];
715 wr = (*(resonanceEnergy->find(Z)->second))[kk];
716 delta += occupNb*std::log(1.0+wl2/(wr*wr));
717 }
718 delta = (delta/((G4double) Z))-wl2/(gam2*plasmaEnergySquared);
719 return delta;
720}
721
722//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
723
[1055]724void
725G4PenelopeIonisationModel::CalculateDiscreteForElectrons(G4double kinEnergy,
726 G4double cutoffEnergy,
727 G4int Z,
728 G4double electronVolumeDensity)
[968]729{
730 if (verboseLevel > 2)
731 G4cout << "Entering in CalculateDiscreteForElectrons() for energy " <<
732 kinEnergy/keV << " keV " << G4endl;
733
734 //Initialization of variables to be calculated in this routine
735 kineticEnergy1=kinEnergy;
736 cosThetaPrimary=1.0;
737 energySecondary=0.0;
738 cosThetaSecondary=1.0;
739 iOsc=-1;
740
741 //constants
742 G4double rb=kinEnergy+2.0*electron_mass_c2;
743 G4double gamma = 1.0+kinEnergy/electron_mass_c2;
744 G4double gamma2 = gamma*gamma;
745 G4double beta2 = (gamma2-1.0)/gamma2;
746 G4double amol = (gamma-1.0)*(gamma-1.0)/gamma2;
747 G4double cps = kinEnergy*rb;
748 G4double cp = std::sqrt(cps);
749
750 G4double delta = CalculateDeltaFermi(kinEnergy,Z,electronVolumeDensity);
751 G4double distantTransvCS0 = std::max(std::log(gamma2)-beta2-delta,0.0);
752
753 G4double rl,rl1;
754
755 if (cutoffEnergy > kinEnergy) return; //delta rays are not generated
756
757 G4DataVector* qm = new G4DataVector();
758 G4DataVector* cumulHardCS = new G4DataVector();
759 std::vector<G4int> *typeOfInteraction = new std::vector<G4int>;
760 G4DataVector* nbOfLevel = new G4DataVector();
761
762 //Hard close collisions with outer shells
763 G4double wmaxc = 0.5*kinEnergy;
764 G4double closeCS0 = 0.0;
765 G4double closeCS = 0.0;
766 if (cutoffEnergy>0.1*eV)
767 {
768 rl=cutoffEnergy/kinEnergy;
769 rl1=1.0-rl;
770 if (rl < 0.5)
771 closeCS0 = (amol*(0.5-rl)+(1.0/rl)-(1.0/rl1)+(1.0-amol)*std::log(rl/rl1))/kinEnergy;
772 }
773
774 // Cross sections for the different oscillators
775
776 // totalHardCS contains the cumulative hard interaction cross section for the different
777 // excitable levels and the different interaction channels (close, distant, etc.),
778 // i.e.
779 // cumulHardCS[0] = 0.0
780 // cumulHardCS[1] = 1st excitable level (distant longitudinal only)
781 // cumulHardCS[2] = 1st excitable level (distant longitudinal + transverse)
782 // cumulHardCS[3] = 1st excitable level (distant longitudinal + transverse + close)
783 // cumulHardCS[4] = 1st excitable level (all channels) + 2nd excitable level (distant long only)
784 // etc.
785 // This is used for sampling the atomic level which is ionised and the channel of the
786 // interaction.
787 //
788 // For each index iFill of the cumulHardCS vector,
789 // nbOfLevel[iFill] contains the current excitable atomic level and
790 // typeOfInteraction[iFill] contains the current interaction channel, with the legenda:
791 // 1 = distant longitudinal interaction
792 // 2 = distant transverse interaction
793 // 3 = close collision
794 // 4 = close collision with outer shells (in this case nbOfLevel < 0 --> no binding energy)
795
796
797 G4int nOscil = ionizationEnergy->find(Z)->second->size();
798 G4double totalHardCS = 0.0;
799 G4double involvedElectrons = 0.0;
800 for (G4int i=0;i<nOscil;i++){
801 G4double wi = (*(resonanceEnergy->find(Z)->second))[i];
802 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[i];
803
804 //Distant excitations
805 if (wi>cutoffEnergy && wi<kinEnergy)
806 {
807 if (wi>(1e-6*kinEnergy))
808 {
809 G4double cpp=std::sqrt((kinEnergy-wi)*(kinEnergy-wi+2.0*electron_mass_c2));
810 qm->push_back(std::sqrt((cp-cpp)*(cp-cpp)+electron_mass_c2*electron_mass_c2)-electron_mass_c2);
811 }
812 else
813 {
814 qm->push_back((wi*wi)/(beta2*2.0*electron_mass_c2));
815 }
816 if ((*qm)[i] < wi)
817 {
818
819 G4double distantLongitCS = occupNb*std::log(wi*((*qm)[i]+2.0*electron_mass_c2)/
820 ((*qm)[i]*(wi+2.0*electron_mass_c2)))/wi;
821 cumulHardCS->push_back(totalHardCS);
822 typeOfInteraction->push_back(1); //distant longitudinal
823 nbOfLevel->push_back((G4double) i); //only excitable level are counted
824 totalHardCS += distantLongitCS;
825
826 G4double distantTransvCS = occupNb*distantTransvCS0/wi;
827
828 cumulHardCS->push_back(totalHardCS);
829 typeOfInteraction->push_back(2); //distant tranverse
830 nbOfLevel->push_back((G4double) i);
831 totalHardCS += distantTransvCS;
832 }
833 }
834 else
835 qm->push_back(wi);
836
837 //close collisions
838 if(wi < wmaxc)
839 {
840 if (wi < cutoffEnergy)
841 involvedElectrons += occupNb;
842 else
843 {
844 rl=wi/kinEnergy;
845 rl1=1.0-rl;
846 closeCS = occupNb*(amol*(0.5-rl)+(1.0/rl)-(1.0/rl1)+(1.0-amol)*std::log(rl/rl1))/kinEnergy;
847 cumulHardCS->push_back(totalHardCS);
848 typeOfInteraction->push_back(3); //close
849 nbOfLevel->push_back((G4double) i);
850 totalHardCS += closeCS;
851 }
852 }
853 } // loop on the levels
854
855 cumulHardCS->push_back(totalHardCS);
856 typeOfInteraction->push_back(4); //close interaction with outer shells
857 nbOfLevel->push_back(-1.0);
858 totalHardCS += involvedElectrons*closeCS0;
859 cumulHardCS->push_back(totalHardCS); //this is the final value of the totalHardCS
860
861 if (totalHardCS < 1e-30) {
862 kineticEnergy1=kinEnergy;
863 cosThetaPrimary=1.0;
864 energySecondary=0.0;
865 cosThetaSecondary=0.0;
866 iOsc=-1;
867 delete qm;
868 delete cumulHardCS;
869 delete typeOfInteraction;
870 delete nbOfLevel;
871 return;
872 }
873
874 //Testing purposes
875 if (verboseLevel > 6)
876 {
877 for (size_t t=0;t<cumulHardCS->size();t++)
878 G4cout << (*cumulHardCS)[t] << " " << (*typeOfInteraction)[t] <<
879 " " << (*nbOfLevel)[t] << G4endl;
880 }
881
882 //Selection of the active oscillator on the basis of the cumulative cross sections
883 G4double TST = totalHardCS*G4UniformRand();
884 G4int is=0;
885 G4int js= nbOfLevel->size();
886 do{
887 G4int it=(is+js)/2;
888 if (TST > (*cumulHardCS)[it]) is=it;
889 if (TST <= (*cumulHardCS)[it]) js=it;
890 }while((js-is) > 1);
891
892 G4double UII=0.0;
893 G4double rkc=cutoffEnergy/kinEnergy;
894 G4double dde;
895 G4int kks;
896
897 G4int sampledInteraction = (*typeOfInteraction)[is];
898 iOsc = (G4int) (*nbOfLevel)[is];
899
900 if (verboseLevel > 4)
901 G4cout << "Chosen interaction #:" << sampledInteraction << " on level " << iOsc << G4endl;
902
903 //Generates the final state according to the sampled level and
904 //interaction channel
905
906 if (sampledInteraction == 1) //Hard distant longitudinal collisions
907 {
908 dde= (*(resonanceEnergy->find(Z)->second))[iOsc];
909 kineticEnergy1=kinEnergy-dde;
910 G4double qs=(*qm)[iOsc]/(1.0+((*qm)[iOsc]/(2.0*electron_mass_c2)));
911 G4double q=qs/(std::pow((qs/dde)*(1.0+(0.5*dde/electron_mass_c2)),G4UniformRand())-(0.5*qs/electron_mass_c2));
912 G4double qtrev = q*(q+2.0*electron_mass_c2);
913 G4double cpps = kineticEnergy1*(kineticEnergy1+2.0*electron_mass_c2);
914 cosThetaPrimary = (cpps+cps-qtrev)/(2.0*cp*std::sqrt(cpps));
915 if (cosThetaPrimary>1.0) cosThetaPrimary=1.0;
916 //Energy and emission angle of the delta ray
917 kks = (G4int) (*(shellFlag->find(Z)->second))[iOsc];
918 //kks > 4 means that we are in an outer shell
919 if (kks>4)
920 energySecondary=dde;
921 else
922 energySecondary=dde-(*(ionizationEnergy->find(Z)->second))[iOsc];
923
924 cosThetaSecondary = 0.5*(dde*(kinEnergy+rb-dde)+qtrev)/std::sqrt(cps*qtrev);
925 if (cosThetaSecondary>1.0) cosThetaSecondary=1.0;
926 }
927 else if (sampledInteraction == 2) //Hard distant transverse collisions
928 {
929 dde=(*(resonanceEnergy->find(Z)->second))[iOsc];
930 kineticEnergy1=kinEnergy-dde;
931 cosThetaPrimary=1.0;
932 //Energy and emission angle of the delta ray
933 kks = (G4int) (*(shellFlag->find(Z)->second))[iOsc];
934 if (kks>4)
935 {
936 energySecondary=dde;
937 }
938 else
939 {
940 energySecondary=dde-(*(ionizationEnergy->find(Z)->second))[iOsc];
941 }
942 cosThetaSecondary = 1.0;
943 }
944 else if (sampledInteraction == 3 || sampledInteraction == 4) //Close interaction
945 {
946 if (sampledInteraction == 4) //interaction with inner shells
947 {
948 UII=0.0;
949 rkc = cutoffEnergy/kinEnergy;
950 iOsc = -1;
951 }
952 else
953 {
954 kks = (G4int) (*(shellFlag->find(Z)->second))[iOsc];
955 if (kks > 4) {
956 UII=0.0;
957 }
958 else
959 {
960 UII = (*(ionizationEnergy->find(Z)->second))[iOsc];
961 }
962 rkc = (*(resonanceEnergy->find(Z)->second))[iOsc]/kinEnergy;
963 }
964 G4double A = 0.5*amol;
965 G4double arkc = A*0.5*rkc;
966 G4double phi,rk2,rk,rkf;
967 do{
968 G4double fb = (1.0+arkc)*G4UniformRand();
969 if (fb<1.0)
970 {
971 rk=rkc/(1.0-fb*(1.0-(rkc*2.0)));
972 }
973 else{
974 rk = rkc+(fb-1.0)*(0.5-rkc)/arkc;
975 }
976 rk2 = rk*rk;
977 rkf = rk/(1.0-rk);
978 phi = 1.0+(rkf*rkf)-rkf+amol*(rk2+rkf);
979 }while ((G4UniformRand()*(1.0+A*rk2)) > phi);
980 //Energy and scattering angle (primary electron);
981 kineticEnergy1 = kinEnergy*(1.0-rk);
982 cosThetaPrimary = std::sqrt(kineticEnergy1*rb/(kinEnergy*(rb-(rk*kinEnergy))));
983 //Energy and scattering angle of the delta ray
984 energySecondary = kinEnergy-kineticEnergy1-UII;
985 cosThetaSecondary = std::sqrt(rk*kinEnergy*rb/(kinEnergy*(rk*kinEnergy+2.0*electron_mass_c2)));
986 }
987 else
988 {
989 G4String excep = "G4PenelopeIonisationModel - Error in the calculation of the final state";
990 G4Exception(excep);
991 }
992
993 delete qm;
994 delete cumulHardCS;
995
996 delete typeOfInteraction;
997 delete nbOfLevel;
998
999 return;
1000}
1001
1002//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1003
[1055]1004 void
1005G4PenelopeIonisationModel::CalculateDiscreteForPositrons(G4double kinEnergy,
1006 G4double cutoffEnergy,
1007 G4int Z,
1008 G4double electronVolumeDensity)
[968]1009{
1010 kineticEnergy1=kinEnergy;
1011 cosThetaPrimary=1.0;
1012 energySecondary=0.0;
1013 cosThetaSecondary=1.0;
1014 iOsc=-1;
1015 //constants
1016 G4double rb=kinEnergy+2.0*electron_mass_c2;
1017 G4double gamma = 1.0+kinEnergy/electron_mass_c2;
1018 G4double gamma2 = gamma*gamma;
1019 G4double beta2 = (gamma2-1.0)/gamma2;
1020 G4double amol = (gamma-1.0)*(gamma-1.0)/gamma2;
1021 G4double cps = kinEnergy*rb;
1022 G4double cp = std::sqrt(cps);
1023 G4double help = (gamma+1.0)*(gamma+1.0);
1024 G4double bha1 = amol*(2.0*help-1.0)/(gamma2-1.0);
1025 G4double bha2 = amol*(3.0+1.0/help);
1026 G4double bha3 = amol*2.0*gamma*(gamma-1.0)/help;
1027 G4double bha4 = amol*(gamma-1.0)*(gamma-1.0)/help;
1028
1029 G4double delta = CalculateDeltaFermi(kinEnergy,Z,electronVolumeDensity);
1030 G4double distantTransvCS0 = std::max(std::log(gamma2)-beta2-delta,0.0);
1031
1032 G4double rl,rl1;
1033
1034 if (cutoffEnergy > kinEnergy) return; //delta rays are not generated
1035
1036 G4DataVector* qm = new G4DataVector();
1037 G4DataVector* cumulHardCS = new G4DataVector();
1038 std::vector<G4int> *typeOfInteraction = new std::vector<G4int>;
1039 G4DataVector* nbOfLevel = new G4DataVector();
1040
1041
1042 //Hard close collisions with outer shells
1043 G4double wmaxc = kinEnergy;
1044 G4double closeCS0 = 0.0;
1045 G4double closeCS = 0.0;
1046 if (cutoffEnergy>0.1*eV)
1047 {
1048 rl=cutoffEnergy/kinEnergy;
1049 rl1=1.0-rl;
1050 if (rl < 1.0)
1051 closeCS0 = (((1.0/rl)-1.0) + bha1*std::log(rl) + bha2*rl1
1052 + (bha3/2.0)*((rl*rl)-1.0)
1053 + (bha4/3.0)*(1.0-(rl*rl*rl)))/kinEnergy;
1054 }
1055
1056 // Cross sections for the different oscillators
1057
1058 // totalHardCS contains the cumulative hard interaction cross section for the different
1059 // excitable levels and the different interaction channels (close, distant, etc.),
1060 // i.e.
1061 // cumulHardCS[0] = 0.0
1062 // cumulHardCS[1] = 1st excitable level (distant longitudinal only)
1063 // cumulHardCS[2] = 1st excitable level (distant longitudinal + transverse)
1064 // cumulHardCS[3] = 1st excitable level (distant longitudinal + transverse + close)
1065 // cumulHardCS[4] = 1st excitable level (all channels) + 2nd excitable level (distant long only)
1066 // etc.
1067 // This is used for sampling the atomic level which is ionised and the channel of the
1068 // interaction.
1069 //
1070 // For each index iFill of the cumulHardCS vector,
1071 // nbOfLevel[iFill] contains the current excitable atomic level and
1072 // typeOfInteraction[iFill] contains the current interaction channel, with the legenda:
1073 // 1 = distant longitudinal interaction
1074 // 2 = distant transverse interaction
1075 // 3 = close collision
1076 // 4 = close collision with outer shells (in this case nbOfLevel < 0 --> no binding energy)
1077
1078
1079 G4int nOscil = ionizationEnergy->find(Z)->second->size();
1080 G4double totalHardCS = 0.0;
1081 G4double involvedElectrons = 0.0;
1082 for (G4int i=0;i<nOscil;i++){
1083 G4double wi = (*(resonanceEnergy->find(Z)->second))[i];
1084 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[i];
1085 //Distant excitations
1086 if (wi>cutoffEnergy && wi<kinEnergy)
1087 {
1088 if (wi>(1e-6*kinEnergy)){
1089 G4double cpp=std::sqrt((kinEnergy-wi)*(kinEnergy-wi+2.0*electron_mass_c2));
1090 qm->push_back(std::sqrt((cp-cpp)*(cp-cpp)+ electron_mass_c2 * electron_mass_c2)-electron_mass_c2);
1091 }
1092 else
1093 {
1094 qm->push_back(wi*wi/(beta2+2.0*electron_mass_c2));
1095 }
1096 //verificare che quando arriva qui il vettore ha SEMPRE l'i-esimo elemento
1097 if ((*qm)[i] < wi)
1098 {
1099
1100 G4double distantLongitCS = occupNb*std::log(wi*((*qm)[i]+2.0*electron_mass_c2)/
1101 ((*qm)[i]*(wi+2.0*electron_mass_c2)))/wi;
1102 cumulHardCS->push_back(totalHardCS);
1103 typeOfInteraction->push_back(1); //distant longitudinal
1104 nbOfLevel->push_back((G4double) i); //only excitable level are counted
1105 totalHardCS += distantLongitCS;
1106
1107 G4double distantTransvCS = occupNb*distantTransvCS0/wi;
1108
1109 cumulHardCS->push_back(totalHardCS);
1110 typeOfInteraction->push_back(2); //distant tranverse
1111 nbOfLevel->push_back((G4double) i);
1112 totalHardCS += distantTransvCS;
1113 }
1114 }
1115 else
1116 qm->push_back(wi);
1117
1118 //close collisions
1119 if(wi < wmaxc)
1120 {
1121 if (wi < cutoffEnergy) {
1122 involvedElectrons += occupNb;
1123 }
1124 else
1125 {
1126 rl=wi/kinEnergy;
1127 rl1=1.0-rl;
1128 closeCS = occupNb*(((1.0/rl)-1.0)+bha1*std::log(rl)+bha2*rl1
1129 + (bha3/2.0)*((rl*rl)-1.0)
1130 + (bha4/3.0)*(1.0-(rl*rl*rl)))/kinEnergy;
1131 cumulHardCS->push_back(totalHardCS);
1132 typeOfInteraction->push_back(3); //close
1133 nbOfLevel->push_back((G4double) i);
1134 totalHardCS += closeCS;
1135 }
1136 }
1137 } // loop on the levels
1138
1139 cumulHardCS->push_back(totalHardCS);
1140 typeOfInteraction->push_back(4); //close interaction with outer shells
1141 nbOfLevel->push_back(-1.0);
1142 totalHardCS += involvedElectrons*closeCS0;
1143 cumulHardCS->push_back(totalHardCS); //this is the final value of the totalHardCS
1144
1145 if (totalHardCS < 1e-30) {
1146 kineticEnergy1=kinEnergy;
1147 cosThetaPrimary=1.0;
1148 energySecondary=0.0;
1149 cosThetaSecondary=0.0;
1150 iOsc=-1;
1151 delete qm;
1152 delete cumulHardCS;
1153 delete typeOfInteraction;
1154 delete nbOfLevel;
1155 return;
1156 }
1157
1158 //Selection of the active oscillator on the basis of the cumulative cross sections
1159 G4double TST = totalHardCS*G4UniformRand();
1160 G4int is=0;
1161 G4int js= nbOfLevel->size();
1162 do{
1163 G4int it=(is+js)/2;
1164 if (TST > (*cumulHardCS)[it]) is=it;
1165 if (TST <= (*cumulHardCS)[it]) js=it;
1166 }while((js-is) > 1);
1167
1168 G4double UII=0.0;
1169 G4double rkc=cutoffEnergy/kinEnergy;
1170 G4double dde;
1171 G4int kks;
1172
1173 G4int sampledInteraction = (*typeOfInteraction)[is];
1174 iOsc = (G4int) (*nbOfLevel)[is];
1175
1176 //Generates the final state according to the sampled level and
1177 //interaction channel
1178
1179 if (sampledInteraction == 1) //Hard distant longitudinal collisions
1180 {
1181 dde= (*(resonanceEnergy->find(Z)->second))[iOsc];
1182 kineticEnergy1=kinEnergy-dde;
1183 G4double qs=(*qm)[iOsc]/(1.0+((*qm)[iOsc]/(2.0*electron_mass_c2)));
1184 G4double q=qs/(std::pow((qs/dde)*(1.0+(0.5*dde/electron_mass_c2)),G4UniformRand())-(0.5*qs/electron_mass_c2));
1185 G4double qtrev = q*(q+2.0*electron_mass_c2);
1186 G4double cpps = kineticEnergy1*(kineticEnergy1+2.0*electron_mass_c2);
1187 cosThetaPrimary = (cpps+cps-qtrev)/(2.0*cp*std::sqrt(cpps));
1188 if (cosThetaPrimary>1.0) cosThetaPrimary=1.0;
1189 //Energy and emission angle of the delta ray
1190 kks = (G4int) (*(shellFlag->find(Z)->second))[iOsc];
1191 if (kks>4)
1192 energySecondary=dde;
1193
1194 else
1195 energySecondary=dde-(*(ionizationEnergy->find(Z)->second))[iOsc];
1196 cosThetaSecondary = 0.5*(dde*(kinEnergy+rb-dde)+qtrev)/std::sqrt(cps*qtrev);
1197 if (cosThetaSecondary>1.0) cosThetaSecondary=1.0;
1198 }
1199 else if (sampledInteraction == 2) //Hard distant transverse collisions
1200 {
1201 dde=(*(resonanceEnergy->find(Z)->second))[iOsc];
1202 kineticEnergy1=kinEnergy-dde;
1203 cosThetaPrimary=1.0;
1204 //Energy and emission angle of the delta ray
1205 kks = (G4int) (*(shellFlag->find(Z)->second))[iOsc];
1206 if (kks>4)
1207 {
1208 energySecondary=dde;
1209 }
1210 else
1211 {
1212 energySecondary=dde-(*(ionizationEnergy->find(Z)->second))[iOsc];
1213 }
1214 cosThetaSecondary = 1.0;
1215 }
1216 else if (sampledInteraction == 3 || sampledInteraction == 4) //Close interaction
1217 {
1218 if (sampledInteraction == 4) //interaction with inner shells
1219 {
1220 UII=0.0;
1221 rkc = cutoffEnergy/kinEnergy;
1222 iOsc = -1;
1223 }
1224 else
1225 {
1226 kks = (G4int) (*(shellFlag->find(Z)->second))[iOsc];
1227 if (kks > 4) {
1228 UII=0.0;
1229 }
1230 else
1231 {
1232 UII = (*(ionizationEnergy->find(Z)->second))[iOsc];
1233 }
1234 rkc = (*(resonanceEnergy->find(Z)->second))[iOsc]/kinEnergy;
1235 }
1236 G4double phi,rk;
1237 do{
1238 rk=rkc/(1.0-G4UniformRand()*(1.0-rkc));
1239 phi = 1.0-rk*(bha1-rk*(bha2-rk*(bha3-bha4*rk)));
1240 }while ( G4UniformRand() > phi);
1241 //Energy and scattering angle (primary electron);
1242 kineticEnergy1 = kinEnergy*(1.0-rk);
1243 cosThetaPrimary = std::sqrt(kineticEnergy1*rb/(kinEnergy*(rb-(rk*kinEnergy))));
1244 //Energy and scattering angle of the delta ray
1245 energySecondary = kinEnergy-kineticEnergy1-UII;
1246 cosThetaSecondary = std::sqrt(rk*kinEnergy*rb/(kinEnergy*(rk*kinEnergy+2.0*electron_mass_c2)));
1247 }
1248 else
1249 {
1250 G4String excep = "G4PenelopeIonisationModel - Error in the calculation of the final state";
1251 G4Exception(excep);
1252 }
1253
1254 delete qm;
1255 delete cumulHardCS;
1256 delete typeOfInteraction;
1257 delete nbOfLevel;
1258
1259 return;
1260}
1261
1262//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1263
[1055]1264G4double
1265G4PenelopeIonisationModel::CalculateCrossSectionsRatio(G4double kinEnergy,
1266 G4double cutoffEnergy,
1267 G4int Z, G4double electronVolumeDensity,
1268 const G4ParticleDefinition* theParticle)
[968]1269{
1270 //Constants
1271 G4double gamma = 1.0+kinEnergy/electron_mass_c2;
1272 G4double gamma2 = gamma*gamma;
1273 G4double beta2 = (gamma2-1.0)/gamma2;
1274 G4double constant = pi*classic_electr_radius*classic_electr_radius*2.0*electron_mass_c2/beta2;
1275 G4double delta = CalculateDeltaFermi(kinEnergy,Z,electronVolumeDensity);
1276 G4int nbOsc = (G4int) resonanceEnergy->find(Z)->second->size();
1277 G4double softCS = 0.0;
1278 G4double hardCS = 0.0;
1279 for (G4int i=0;i<nbOsc;i++){
1280 G4double resEnergy = (*(resonanceEnergy->find(Z)->second))[i];
1281 std::pair<G4double,G4double> SoftAndHardXS(0.,0.);
1282 if (theParticle == G4Electron::Electron())
1283 SoftAndHardXS = CrossSectionsRatioForElectrons(kinEnergy,resEnergy,delta,cutoffEnergy);
1284 else if (theParticle == G4Positron::Positron())
1285 SoftAndHardXS = CrossSectionsRatioForPositrons(kinEnergy,resEnergy,delta,cutoffEnergy);
1286 G4double occupNb = (*(occupationNumber->find(Z)->second))[i];
1287 softCS += occupNb*constant*SoftAndHardXS.first;
1288 hardCS += occupNb*constant*SoftAndHardXS.second;
1289 }
1290 G4double ratio = 0.0;
1291
1292 if (softCS+hardCS) ratio = (hardCS)/(softCS+hardCS);
1293 return ratio;
1294}
1295
1296//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1297
[1055]1298std::pair<G4double,G4double>
1299G4PenelopeIonisationModel::CrossSectionsRatioForElectrons(G4double kineticEnergy,
1300 G4double resEnergy,
1301 G4double densityCorrection,
1302 G4double cutoffEnergy)
[968]1303{
1304 std::pair<G4double,G4double> theResult(0.,0.);
1305 if (kineticEnergy < resEnergy) return theResult;
1306
1307 //Calculate constants
1308 G4double gamma = 1.0+kineticEnergy/electron_mass_c2;
1309 G4double gamma2 = gamma*gamma;
1310 G4double beta2 = (gamma2-1.0)/gamma2;
1311 G4double cps = kineticEnergy*(kineticEnergy+2.0*electron_mass_c2);
1312 G4double amol = (kineticEnergy/(kineticEnergy+electron_mass_c2)) * (kineticEnergy/(kineticEnergy+electron_mass_c2)) ;
1313 G4double hardCont = 0.0;
1314 G4double softCont = 0.0;
1315
1316 //Distant interactions
1317 G4double cp1s = (kineticEnergy-resEnergy)*(kineticEnergy-resEnergy+2.0*electron_mass_c2);
1318 G4double cp1 = std::sqrt(cp1s);
1319 G4double cp = std::sqrt(cps);
1320 G4double sdLong=0.0, sdTrans = 0.0, sdDist=0.0;
1321
1322 //Distant longitudinal interactions
1323 G4double qm = 0.0;
1324
1325 if (resEnergy > kineticEnergy*(1e-6))
1326 {
1327 qm = std::sqrt((cp-cp1)*(cp-cp1)+(electron_mass_c2*electron_mass_c2))-electron_mass_c2;
1328 }
1329 else
1330 {
1331 qm = resEnergy*resEnergy/(beta2*2.0*electron_mass_c2);
1332 qm = qm*(1.0-0.5*qm/electron_mass_c2);
1333 }
1334
1335 if (qm < resEnergy)
1336 {
1337 sdLong = std::log(resEnergy*(qm+2.0*electron_mass_c2)/(qm*(resEnergy+2.0*electron_mass_c2)));
1338 }
1339 else
1340 {
1341 sdLong = 0.0;
1342 }
1343
1344 if (sdLong > 0) {
1345 sdTrans = std::max(std::log(gamma2)-beta2-densityCorrection,0.0);
1346 sdDist = sdTrans + sdLong;
1347 if (cutoffEnergy > resEnergy)
1348 {
1349 softCont = sdDist/resEnergy;
1350 }
1351 else
1352 {
1353 hardCont = sdDist/resEnergy;
1354 }
1355 }
1356
1357 // Close collisions (Moeller's cross section)
1358 G4double wl = std::max(cutoffEnergy,resEnergy);
1359 G4double wu = 0.5*kineticEnergy;
1360
1361 if (wl < (wu-1*eV))
1362 {
1363 hardCont += (1.0/(kineticEnergy-wu))-(1.0/(kineticEnergy-wl))
1364 - (1.0/wu)+(1.0/wl)
1365 + (1.0-amol)*std::log(((kineticEnergy-wu)*wl)/((kineticEnergy-wl)*wu))/kineticEnergy
1366 + amol*(wu-wl)/(kineticEnergy*kineticEnergy);
1367 wu=wl;
1368 }
1369
1370 wl = resEnergy;
1371 if (wl > (wu-1*eV))
1372 {
1373 theResult.first = softCont;
1374 theResult.second = hardCont;
1375 return theResult;
1376 }
1377 softCont += (1.0/(kineticEnergy-wu))-(1.0/(kineticEnergy-wl))
1378 - (1.0/wu)+(1.0/wl)
1379 + (1.0-amol)*std::log(((kineticEnergy-wu)*wl)/((kineticEnergy-wl)*wu))/kineticEnergy
1380 + amol*(wu-wl)/(kineticEnergy*kineticEnergy);
1381 theResult.first = softCont;
1382 theResult.second = hardCont;
1383 return theResult;
1384}
1385
1386
1387//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1388
[1055]1389std::pair<G4double,G4double>
1390G4PenelopeIonisationModel::CrossSectionsRatioForPositrons(G4double kineticEnergy,
1391 G4double resEnergy,
1392 G4double densityCorrection,
1393 G4double cutoffEnergy)
[968]1394{
1395
1396 std::pair<G4double,G4double> theResult(0.,0.);
1397 if (kineticEnergy < resEnergy) return theResult;
1398
1399 //Calculate constants
1400 G4double gamma = 1.0+kineticEnergy/electron_mass_c2;
1401 G4double gamma2 = gamma*gamma;
1402 G4double beta2 = (gamma2-1.0)/gamma2;
1403 G4double cps = kineticEnergy*(kineticEnergy+2.0*electron_mass_c2);
1404 G4double amol = (kineticEnergy/(kineticEnergy+electron_mass_c2)) * (kineticEnergy/(kineticEnergy+electron_mass_c2)) ;
1405 G4double help = (gamma+1.0)*(gamma+1.0);
1406 G4double bha1 = amol*(2.0*help-1.0)/(gamma2-1.0);
1407 G4double bha2 = amol*(3.0+1.0/help);
1408 G4double bha3 = amol*2.0*gamma*(gamma-1.0)/help;
1409 G4double bha4 = amol*(gamma-1.0)*(gamma-1.0)/help;
1410 G4double hardCont = 0.0;
1411 G4double softCont = 0.0;
1412
1413 //Distant interactions
1414 G4double cp1s = (kineticEnergy-resEnergy)*(kineticEnergy-resEnergy+2.0*electron_mass_c2);
1415 G4double cp1 = std::sqrt(cp1s);
1416 G4double cp = std::sqrt(cps);
1417 G4double sdLong=0.0, sdTrans = 0.0, sdDist=0.0;
1418
1419 //Distant longitudinal interactions
1420 G4double qm = 0.0;
1421
1422 if (resEnergy > kineticEnergy*(1e-6))
1423 {
1424 qm = std::sqrt((cp-cp1)*(cp-cp1)+(electron_mass_c2*electron_mass_c2))-electron_mass_c2;
1425 }
1426 else
1427 {
1428 qm = resEnergy*resEnergy/(beta2*2.0*electron_mass_c2);
1429 qm = qm*(1.0-0.5*qm/electron_mass_c2);
1430 }
1431
1432 if (qm < resEnergy)
1433 {
1434 sdLong = std::log(resEnergy*(qm+2.0*electron_mass_c2)/(qm*(resEnergy+2.0*electron_mass_c2)));
1435 }
1436 else
1437 {
1438 sdLong = 0.0;
1439 }
1440
1441 if (sdLong > 0) {
1442 sdTrans = std::max(std::log(gamma2)-beta2-densityCorrection,0.0);
1443 sdDist = sdTrans + sdLong;
1444 if (cutoffEnergy > resEnergy)
1445 {
1446 softCont = sdDist/resEnergy;
1447 }
1448 else
1449 {
1450 hardCont = sdDist/resEnergy;
1451 }
1452 }
1453
1454
1455 // Close collisions (Bhabha's cross section)
1456 G4double wl = std::max(cutoffEnergy,resEnergy);
1457 G4double wu = kineticEnergy;
1458
1459 if (wl < (wu-1*eV)) {
1460 hardCont += (1.0/wl)-(1.0/wu)-bha1*std::log(wu/wl)/kineticEnergy
1461 + bha2*(wu-wl)/(kineticEnergy*kineticEnergy)
1462 -bha3*((wu*wu)-(wl*wl))/(2.0*kineticEnergy*kineticEnergy*kineticEnergy)
1463 + bha4*((wu*wu*wu)-(wl*wl*wl))/(3.0*kineticEnergy*kineticEnergy*kineticEnergy*kineticEnergy);
1464 wu=wl;
1465 }
1466 wl = resEnergy;
1467 if (wl > (wu-1*eV))
1468 {
1469 theResult.first = softCont;
1470 theResult.second = hardCont;
1471 return theResult;
1472 }
1473 softCont += (1.0/wl)-(1.0/wu)-bha1*std::log(wu/wl)/kineticEnergy
1474 + bha2*(wu-wl)/(kineticEnergy*kineticEnergy)
1475 -bha3*((wu*wu)-(wl*wl))/(2.0*kineticEnergy*kineticEnergy*kineticEnergy)
1476 + bha4*((wu*wu*wu)-(wl*wl*wl))/(3.0*kineticEnergy*kineticEnergy*kineticEnergy*kineticEnergy);
1477
1478
1479 theResult.first = softCont;
1480 theResult.second = hardCont;
1481 return theResult;
1482
1483}
1484
1485G4double G4PenelopeIonisationModel::ComputeStoppingPowerForElectrons(G4double kinEnergy,
1486 G4double cutEnergy,
1487 G4double deltaFermi,
1488 G4double resEnergy)
1489{
1490 //Calculate constants
1491 G4double gamma = 1.0+kinEnergy/electron_mass_c2;
1492 G4double gamma2 = gamma*gamma;
1493 G4double beta2 = (gamma2-1.0)/gamma2;
1494 G4double cps = kinEnergy*(kinEnergy+2.0*electron_mass_c2);
1495 G4double amol = (gamma-1.0)*(gamma-1.0)/gamma2;
1496 G4double sPower = 0.0;
1497 if (kinEnergy < resEnergy) return sPower;
1498
1499 //Distant interactions
1500 G4double cp1s = (kinEnergy-resEnergy)*(kinEnergy-resEnergy+2.0*electron_mass_c2);
1501 G4double cp1 = std::sqrt(cp1s);
1502 G4double cp = std::sqrt(cps);
1503 G4double sdLong=0.0, sdTrans = 0.0, sdDist=0.0;
1504
1505 //Distant longitudinal interactions
1506 G4double qm = 0.0;
1507
1508 if (resEnergy > kinEnergy*(1e-6))
1509 {
1510 qm = std::sqrt((cp-cp1)*(cp-cp1)+(electron_mass_c2*electron_mass_c2))-electron_mass_c2;
1511 }
1512 else
1513 {
1514 qm = resEnergy*resEnergy/(beta2*2.0*electron_mass_c2);
1515 qm = qm*(1.0-0.5*qm/electron_mass_c2);
1516 }
1517
1518 if (qm < resEnergy)
1519 sdLong = std::log(resEnergy*(qm+2.0*electron_mass_c2)/(qm*(resEnergy+2.0*electron_mass_c2)));
1520 else
1521 sdLong = 0.0;
1522
1523 if (sdLong > 0) {
1524 sdTrans = std::max(std::log(gamma2)-beta2-deltaFermi,0.0);
1525 sdDist = sdTrans + sdLong;
1526 if (cutEnergy > resEnergy) sPower = sdDist;
1527 }
1528
1529
1530 // Close collisions (Moeller's cross section)
1531 G4double wl = std::max(cutEnergy,resEnergy);
1532 G4double wu = 0.5*kinEnergy;
1533
1534 if (wl < (wu-1*eV)) wu=wl;
1535 wl = resEnergy;
1536 if (wl > (wu-1*eV)) return sPower;
1537 sPower += std::log(wu/wl)+(kinEnergy/(kinEnergy-wu))-(kinEnergy/(kinEnergy-wl))
1538 + (2.0 - amol)*std::log((kinEnergy-wu)/(kinEnergy-wl))
1539 + amol*((wu*wu)-(wl*wl))/(2.0*kinEnergy*kinEnergy);
1540 return sPower;
1541}
1542
1543
1544//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1545
1546G4double G4PenelopeIonisationModel::ComputeStoppingPowerForPositrons(G4double kinEnergy,
1547 G4double cutEnergy,
1548 G4double deltaFermi,
1549 G4double resEnergy)
1550{
1551 //Calculate constants
1552 G4double gamma = 1.0+kinEnergy/electron_mass_c2;
1553 G4double gamma2 = gamma*gamma;
1554 G4double beta2 = (gamma2-1.0)/gamma2;
1555 G4double cps = kinEnergy*(kinEnergy+2.0*electron_mass_c2);
1556 G4double amol = (kinEnergy/(kinEnergy+electron_mass_c2)) * (kinEnergy/(kinEnergy+electron_mass_c2));
1557 G4double help = (gamma+1.0)*(gamma+1.0);
1558 G4double bha1 = amol*(2.0*help-1.0)/(gamma2-1.0);
1559 G4double bha2 = amol*(3.0+1.0/help);
1560 G4double bha3 = amol*2.0*gamma*(gamma-1.0)/help;
1561 G4double bha4 = amol*(gamma-1.0)*(gamma-1.0)/help;
1562
1563 G4double sPower = 0.0;
1564 if (kinEnergy < resEnergy) return sPower;
1565
1566 //Distant interactions
1567 G4double cp1s = (kinEnergy-resEnergy)*(kinEnergy-resEnergy+2.0*electron_mass_c2);
1568 G4double cp1 = std::sqrt(cp1s);
1569 G4double cp = std::sqrt(cps);
1570 G4double sdLong=0.0, sdTrans = 0.0, sdDist=0.0;
1571
1572 //Distant longitudinal interactions
1573 G4double qm = 0.0;
1574
1575 if (resEnergy > kinEnergy*(1e-6))
1576 {
1577 qm = std::sqrt((cp-cp1)*(cp-cp1)+(electron_mass_c2*electron_mass_c2))-electron_mass_c2;
1578 }
1579 else
1580 {
1581 qm = resEnergy*resEnergy/(beta2*2.0*electron_mass_c2);
1582 qm = qm*(1.0-0.5*qm/electron_mass_c2);
1583 }
1584
1585 if (qm < resEnergy)
1586 sdLong = std::log(resEnergy*(qm+2.0*electron_mass_c2)/(qm*(resEnergy+2.0*electron_mass_c2)));
1587 else
1588 sdLong = 0.0;
1589
1590 if (sdLong > 0) {
1591 sdTrans = std::max(std::log(gamma2)-beta2-deltaFermi,0.0);
1592 sdDist = sdTrans + sdLong;
1593 if (cutEnergy > resEnergy) sPower = sdDist;
1594 }
1595
1596
1597 // Close collisions (Bhabha's cross section)
1598 G4double wl = std::max(cutEnergy,resEnergy);
1599 G4double wu = kinEnergy;
1600
1601 if (wl < (wu-1*eV)) wu=wl;
1602 wl = resEnergy;
1603 if (wl > (wu-1*eV)) return sPower;
1604 sPower += std::log(wu/wl)-bha1*(wu-wl)/kinEnergy
1605 + bha2*((wu*wu)-(wl*wl))/(2.0*kinEnergy*kinEnergy)
1606 - bha3*((wu*wu*wu)-(wl*wl*wl))/(3.0*kinEnergy*kinEnergy*kinEnergy)
1607 + bha4*((wu*wu*wu*wu)-(wl*wl*wl*wl))/(4.0*kinEnergy*kinEnergy*kinEnergy*kinEnergy);
1608 return sPower;
1609}
1610
1611//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
1612
1613/* Notice: the methods here above are only temporary. They will become obsolete in a while */
1614
1615#include "G4VDataSetAlgorithm.hh"
1616#include "G4LinLogLogInterpolation.hh"
1617#include "G4CompositeEMDataSet.hh"
1618#include "G4EMDataSet.hh"
1619
[1055]1620std::vector<G4VEMDataSet*>*
1621G4PenelopeIonisationModel::BuildCrossSectionTable(const G4ParticleDefinition* theParticle)
[968]1622{
1623 std::vector<G4VEMDataSet*>* set = new std::vector<G4VEMDataSet*>;
1624
1625 size_t nOfBins = 200;
1626 G4PhysicsLogVector* theLogVector = new G4PhysicsLogVector(LowEnergyLimit(),
1627 HighEnergyLimit(),
1628 nOfBins);
1629 G4DataVector* energies;
1630 G4DataVector* cs;
1631
1632 const G4ProductionCutsTable* theCoupleTable=
1633 G4ProductionCutsTable::GetProductionCutsTable();
1634 size_t numOfCouples = theCoupleTable->GetTableSize();
1635
1636
1637 for (size_t m=0; m<numOfCouples; m++)
1638 {
1639 const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(m);
1640 const G4Material* material= couple->GetMaterial();
1641 const G4ElementVector* elementVector = material->GetElementVector();
1642 const G4double* nAtomsPerVolume = material->GetAtomicNumDensityVector();
1643 G4double electronVolumeDensity =
1644 material->GetTotNbOfElectPerVolume(); //electron density
1645 G4int nElements = material->GetNumberOfElements();
1646
1647 G4double tcut = (*(theCoupleTable->GetEnergyCutsVector(1)))[couple->GetIndex()];
1648
1649 G4VDataSetAlgorithm* algo = new G4LinLogLogInterpolation();
1650
1651 G4VEMDataSet* setForMat = new G4CompositeEMDataSet(algo,1.,1.);
1652
1653 for (G4int i=0; i<nElements; i++)
1654 {
1655 G4int iZ = (G4int) (*elementVector)[i]->GetZ();
1656 energies = new G4DataVector;
1657 cs = new G4DataVector;
1658 G4double density = nAtomsPerVolume[i];
1659 for (size_t bin=0; bin<nOfBins; bin++)
1660 {
1661 G4double e = theLogVector->GetLowEdgeEnergy(bin);
1662 energies->push_back(e);
1663 G4double value = 0.0;
1664 if(e > tcut)
1665 {
1666 G4double ratio = CalculateCrossSectionsRatio(e,tcut,iZ,
1667 electronVolumeDensity,
1668 theParticle);
1669 value = crossSectionHandler->FindValue(iZ,e)*ratio*density;
1670 }
1671 cs->push_back(value);
1672 }
1673 G4VDataSetAlgorithm* algo1 = algo->Clone();
1674 G4VEMDataSet* elSet = new G4EMDataSet(i,energies,cs,algo1,1.,1.);
1675 setForMat->AddComponent(elSet);
1676 }
1677 set->push_back(setForMat);
1678 }
1679 return set;
1680}
1681
1682//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
1683
1684G4int G4PenelopeIonisationModel::SampleRandomAtom(const G4MaterialCutsCouple* couple,
1685 G4double e) const
1686{
1687 // Select randomly an element within the material, according to the weight
1688 // determined by the cross sections in the data set
1689
1690 const G4Material* material = couple->GetMaterial();
1691 G4int nElements = material->GetNumberOfElements();
1692
1693 // Special case: the material consists of one element
1694 if (nElements == 1)
1695 {
1696 G4int Z = (G4int) material->GetZ();
1697 return Z;
1698 }
1699
1700 // Composite material
1701 const G4ElementVector* elementVector = material->GetElementVector();
1702 size_t materialIndex = couple->GetIndex();
1703
1704 G4VEMDataSet* materialSet = (*theXSTable)[materialIndex];
1705 G4double materialCrossSection0 = 0.0;
1706 G4DataVector cross;
1707 cross.clear();
1708 for ( G4int i=0; i < nElements; i++ )
1709 {
1710 G4double cr = materialSet->GetComponent(i)->FindValue(e);
1711 materialCrossSection0 += cr;
1712 cross.push_back(materialCrossSection0);
1713 }
1714
1715 G4double random = G4UniformRand() * materialCrossSection0;
1716
1717 for (G4int k=0 ; k < nElements ; k++ )
1718 {
1719 if (random <= cross[k]) return (G4int) (*elementVector)[k]->GetZ();
1720 }
1721 // It should never get here
1722 return 0;
1723}
1724
1725
[1192]1726//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1727
1728void G4PenelopeIonisationModel::ActivateAuger(G4bool augerbool)
1729{
1730 if (!DeexcitationFlag() && augerbool)
1731 {
1732 G4cout << "WARNING - G4PenelopeIonisationModel" << G4endl;
1733 G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
1734 G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
1735 }
1736 deexcitationManager.ActivateAugerElectronProduction(augerbool);
1737 if (verboseLevel > 1)
1738 G4cout << "Auger production set to " << augerbool << G4endl;
1739}
1740
1741//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
Note: See TracBrowser for help on using the repository browser.