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

Last change on this file since 1346 was 1337, checked in by garnier, 15 years ago

tag geant4.9.4 beta 1 + modifs locales

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