source: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopePhotoElectricModel.cc@ 1190

Last change on this file since 1190 was 1055, checked in by garnier, 17 years ago

maj sur la beta de geant 4.9.3

File size: 16.0 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// $Id: G4PenelopePhotoElectricModel.cc,v 1.6 2009/05/19 14:57:01 pandola Exp $
27// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
28//
29// Author: Luciano Pandola
30//
31// History:
32// --------
33// 08 Oct 2008 L Pandola Migration from process to model
34// 08 Jan 2009 L Pandola Check shell index to avoid mismatch between
35// the Penelope cross section database and the
36// G4AtomicTransitionManager database. It suppresses
37// a warning from G4AtomicTransitionManager only.
38// Results are unchanged.
39// 25 Mar 2009 L Pandola Small fix to avoid wrong energy-violation warnings
40// 17 Apr 2009 V Ivanchenko Cleanup initialisation and generation of secondaries:
41// - apply internal high-energy limit only in constructor
42// - do not apply low-energy limit (default is 0)
43// - do not apply production threshold on secondaries
44// 19 May 2009 L Pandola Explicitely set to zero pointers deleted in
45// Initialise(), since they might be checked later on
46//
47
48#include "G4PenelopePhotoElectricModel.hh"
49#include "G4ParticleDefinition.hh"
50#include "G4MaterialCutsCouple.hh"
51#include "G4ProductionCutsTable.hh"
52#include "G4DynamicParticle.hh"
53#include "G4PhysicsTable.hh"
54#include "G4ElementTable.hh"
55#include "G4Element.hh"
56#include "G4CrossSectionHandler.hh"
57#include "G4AtomicTransitionManager.hh"
58#include "G4AtomicShell.hh"
59#include "G4Gamma.hh"
60#include "G4Electron.hh"
61
62//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
63
64
65G4PenelopePhotoElectricModel::G4PenelopePhotoElectricModel(const G4ParticleDefinition*,
66 const G4String& nam)
67 :G4VEmModel(nam),isInitialised(false),crossSectionHandler(0),
68 shellCrossSectionHandler(0)
69{
70 fIntrinsicLowEnergyLimit = 100.0*eV;
71 fIntrinsicHighEnergyLimit = 100.0*GeV;
72 // SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
73 SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
74 //
75 fUseAtomicDeexcitation = true;
76 verboseLevel= 0;
77 // Verbosity scale:
78 // 0 = nothing
79 // 1 = warning for energy non-conservation
80 // 2 = details of energy budget
81 // 3 = calculation of cross sections, file openings, sampling of atoms
82 // 4 = entering in methods
83}
84
85//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
86
87G4PenelopePhotoElectricModel::~G4PenelopePhotoElectricModel()
88{
89 if (crossSectionHandler) delete crossSectionHandler;
90 if (shellCrossSectionHandler) delete shellCrossSectionHandler;
91}
92
93//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
94
95void G4PenelopePhotoElectricModel::Initialise(const G4ParticleDefinition*,
96 const G4DataVector& )
97{
98 if (verboseLevel > 3)
99 G4cout << "Calling G4PenelopePhotoElectricModel::Initialise()" << G4endl;
100 if (crossSectionHandler)
101 {
102 crossSectionHandler->Clear();
103 delete crossSectionHandler;
104 crossSectionHandler = 0;
105 }
106 if (shellCrossSectionHandler)
107 {
108 shellCrossSectionHandler->Clear();
109 delete shellCrossSectionHandler;
110 shellCrossSectionHandler =0;
111 }
112
113 //Re-initialize cross section handlers
114 crossSectionHandler = new G4CrossSectionHandler();
115 crossSectionHandler->Clear();
116 G4String crossSectionFile = "penelope/ph-cs-pen-";
117 crossSectionHandler->LoadData(crossSectionFile);
118 shellCrossSectionHandler = new G4CrossSectionHandler();
119 shellCrossSectionHandler->Clear();
120 crossSectionFile = "penelope/ph-ss-cs-pen-";
121 shellCrossSectionHandler->LoadShellData(crossSectionFile);
122 //This is used to retrieve cross section values later on
123 crossSectionHandler->BuildMeanFreePathForMaterials();
124
125 if (verboseLevel > 2)
126 G4cout << "Loaded cross section files for PenelopePhotoElectric" << G4endl;
127
128 if (verboseLevel > 0) {
129 G4cout << "Penelope Photo-Electric model is initialized " << G4endl
130 << "Energy range: "
131 << LowEnergyLimit() / MeV << " MeV - "
132 << HighEnergyLimit() / GeV << " GeV"
133 << G4endl;
134 }
135
136 if(isInitialised) return;
137 fParticleChange = GetParticleChangeForGamma();
138 isInitialised = true;
139}
140
141//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
142
143G4double G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom(
144 const G4ParticleDefinition*,
145 G4double energy,
146 G4double Z, G4double,
147 G4double, G4double)
148{
149 //
150 // Penelope model. Use data-driven approach for cross section estimate (and
151 // also shell sampling from a given atom). Data are from the Livermore database
152 // D.E. Cullen et al., Report UCRL-50400 (1989)
153 //
154
155 if (verboseLevel > 3)
156 G4cout << "Calling ComputeCrossSectionPerAtom() of G4PenelopePhotoElectricModel" << G4endl;
157
158 G4int iZ = (G4int) Z;
159 // if (!crossSectionHandler) // VI: should not be
160 // {
161 // G4cout << "G4PenelopePhotoElectricModel::ComputeCrossSectionPerAtom" << G4endl;
162 // G4cout << "The cross section handler is not correctly initialized" << G4endl;
163 // G4Exception();
164 // }
165 G4double cs = crossSectionHandler->FindValue(iZ,energy);
166
167 if (verboseLevel > 2)
168 G4cout << "Photoelectric cross section at " << energy/MeV << " MeV for Z=" << Z <<
169 " = " << cs/barn << " barn" << G4endl;
170 return cs;
171}
172
173//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
174
175void G4PenelopePhotoElectricModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
176 const G4MaterialCutsCouple* couple,
177 const G4DynamicParticle* aDynamicGamma,
178 G4double,
179 G4double)
180{
181 //
182 // Photoelectric effect, Penelope model
183 //
184 // The target atom and the target shell are sampled according to the Livermore
185 // database
186 // D.E. Cullen et al., Report UCRL-50400 (1989)
187 // The angular distribution of the electron in the final state is sampled
188 // according to the Sauter distribution from
189 // F. Sauter, Ann. Phys. 11 (1931) 454
190 // The energy of the final electron is given by the initial photon energy minus
191 // the binding energy. Fluorescence de-excitation is subsequently produced
192 // (to fill the vacancy) according to the general Geant4 G4DeexcitationManager:
193 // J. Stepanek, Comp. Phys. Comm. 1206 pp 1-1-9 (1997)
194
195 if (verboseLevel > 3)
196 G4cout << "Calling SamplingSecondaries() of G4PenelopePhotoElectricModel" << G4endl;
197
198 G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
199
200 // always kill primary
201 fParticleChange->ProposeTrackStatus(fStopAndKill);
202 fParticleChange->SetProposedKineticEnergy(0.);
203
204 if (photonEnergy <= fIntrinsicLowEnergyLimit)
205 {
206 fParticleChange->ProposeLocalEnergyDeposit(photonEnergy);
207 return ;
208 }
209
210 G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
211
212 // Select randomly one element in the current material
213 if (verboseLevel > 2)
214 G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl;
215 //use crossSectionHandler instead of G4EmElementSelector because in this case
216 //the dimension of the table is equal to the dimension of the database
217 //(less interpolation errors)
218 G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
219 if (verboseLevel > 2)
220 G4cout << "Selected Z = " << Z << G4endl;
221
222 // Select the ionised shell in the current atom according to shell cross sections
223 size_t shellIndex = shellCrossSectionHandler->SelectRandomShell(Z,photonEnergy);
224
225 // Retrieve the corresponding identifier and binding energy of the selected shell
226 const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
227
228 //The number of shell cross section possibly reported in the Penelope database
229 //might be different from the number of shells in the G4AtomicTransitionManager
230 //(namely, Penelope may contain more shell, especially for very light elements).
231 //In order to avoid a warning message from the G4AtomicTransitionManager, I
232 //add this protection. Results are anyway changed, because when G4AtomicTransitionManager
233 //has a shellID>maxID, it sets the shellID to the last valid shell.
234 size_t numberOfShells = (size_t) transitionManager->NumberOfShells(Z);
235 if (shellIndex >= numberOfShells)
236 shellIndex = numberOfShells-1;
237
238 const G4AtomicShell* shell = transitionManager->Shell(Z,shellIndex);
239 G4double bindingEnergy = shell->BindingEnergy();
240 G4int shellId = shell->ShellId();
241
242 G4double localEnergyDeposit = 0.0;
243
244 // Primary outcoming electron
245 G4double eKineticEnergy = photonEnergy - bindingEnergy;
246
247 // There may be cases where the binding energy of the selected shell is > photon energy
248 // In such cases do not generate secondaries
249 if (eKineticEnergy > 0.)
250 {
251 //Now check if the electron is above cuts: if so, it is created explicitely
252 //VI: checking cut here provides inconsistency in testing
253 // if (eKineticEnergy > cutE)
254 // The electron is created
255 // Direction sampled from the Sauter distribution
256 G4double cosTheta = SampleElectronDirection(eKineticEnergy);
257 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
258 G4double phi = twopi * G4UniformRand() ;
259 G4double dirx = sinTheta * std::cos(phi);
260 G4double diry = sinTheta * std::sin(phi);
261 G4double dirz = cosTheta ;
262 G4ThreeVector electronDirection(dirx,diry,dirz); //electron direction
263 electronDirection.rotateUz(photonDirection);
264 G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
265 electronDirection,
266 eKineticEnergy);
267 fvect->push_back(electron);
268 }
269 // else
270 // {
271 // localEnergyDeposit += eKineticEnergy;
272 // eKineticEnergy = 0;
273 // }
274 // }
275 else
276 {
277 bindingEnergy = photonEnergy;
278 }
279 G4double energyInFluorescence = 0; //testing purposes
280
281 //Now, take care of fluorescence, if required
282 if(DeexcitationFlag() && Z > 5)
283 {
284 const G4ProductionCutsTable* theCoupleTable=
285 G4ProductionCutsTable::GetProductionCutsTable();
286 size_t indx = couple->GetIndex();
287 G4double cutG = (*(theCoupleTable->GetEnergyCutsVector(0)))[indx];
288 G4double cutE = (*(theCoupleTable->GetEnergyCutsVector(1)))[indx];
289
290 // Protection to avoid generating photons in the unphysical case of
291 // shell binding energy > photon energy
292 if (bindingEnergy > cutG || bindingEnergy > cutE)
293 {
294 deexcitationManager.SetCutForSecondaryPhotons(cutG);
295 deexcitationManager.SetCutForAugerElectrons(cutE);
296 std::vector<G4DynamicParticle*>* photonVector =
297 deexcitationManager.GenerateParticles(Z,shellId);
298 //Check for secondaries
299 if(photonVector)
300 {
301 for (size_t k=0; k< photonVector->size(); k++)
302 {
303 G4DynamicParticle* aPhoton = (*photonVector)[k];
304 if (aPhoton)
305 {
306 G4double itsEnergy = aPhoton->GetKineticEnergy();
307 if (itsEnergy <= bindingEnergy)
308 {
309 if(aPhoton->GetDefinition() == G4Gamma::Gamma())
310 energyInFluorescence += itsEnergy;
311 bindingEnergy -= itsEnergy;
312 fvect->push_back(aPhoton);
313 }
314 else
315 {
316 delete aPhoton;
317 (*photonVector)[k] = 0;
318 }
319 }
320 }
321 delete photonVector;
322 }
323 }
324 }
325 //Residual energy is deposited locally
326 localEnergyDeposit += bindingEnergy;
327
328 if (localEnergyDeposit < 0)
329 {
330 G4cout << "WARNING - "
331 << "G4PenelopePhotoElectric::PostStepDoIt - Negative energy deposit"
332 << G4endl;
333 localEnergyDeposit = 0;
334 }
335
336 fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
337
338 if (verboseLevel > 1)
339 {
340 G4cout << "-----------------------------------------------------------" << G4endl;
341 G4cout << "Energy balance from G4PenelopePhotoElectric" << G4endl;
342 G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl;
343 G4cout << "-----------------------------------------------------------" << G4endl;
344 if (eKineticEnergy)
345 G4cout << "Outgoing electron " << eKineticEnergy/keV << " keV" << G4endl;
346 G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
347 G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
348 G4cout << "Total final state: " << (eKineticEnergy+energyInFluorescence+localEnergyDeposit)/keV <<
349 " keV" << G4endl;
350 G4cout << "-----------------------------------------------------------" << G4endl;
351 }
352 if (verboseLevel > 0)
353 {
354 G4double energyDiff =
355 std::fabs(eKineticEnergy+energyInFluorescence+localEnergyDeposit-photonEnergy);
356 if (energyDiff > 0.05*keV)
357 G4cout << "Warning from G4PenelopePhotoElectric: problem with energy conservation: " <<
358 (eKineticEnergy+energyInFluorescence+localEnergyDeposit)/keV
359 << " keV (final) vs. " <<
360 photonEnergy/keV << " keV (initial)" << G4endl;
361 }
362}
363
364//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
365
366void G4PenelopePhotoElectricModel::ActivateAuger(G4bool augerbool)
367{
368 if (!fUseAtomicDeexcitation)
369 {
370 G4cout << "WARNING - G4PenelopePhotoElectricModel" << G4endl;
371 G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
372 G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
373 }
374 deexcitationManager.ActivateAugerElectronProduction(augerbool);
375 if (verboseLevel > 1)
376 G4cout << "Auger production set to " << augerbool << G4endl;
377}
378
379//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
380
381G4double G4PenelopePhotoElectricModel::SampleElectronDirection(G4double energy)
382{
383 G4double costheta = 1.0;
384 if (energy>1*GeV) return costheta;
385
386 //1) initialize energy-dependent variables
387 // Variable naming according to Eq. (2.24) of Penelope Manual
388 // (pag. 44)
389 G4double gamma = 1.0 + energy/electron_mass_c2;
390 G4double gamma2 = gamma*gamma;
391 G4double beta = std::sqrt((gamma2-1.0)/gamma2);
392
393 // ac corresponds to "A" of Eq. (2.31)
394 //
395 G4double ac = (1.0/beta) - 1.0;
396 G4double a1 = 0.5*beta*gamma*(gamma-1.0)*(gamma-2.0);
397 G4double a2 = ac + 2.0;
398 G4double gtmax = 2.0*(a1 + 1.0/ac);
399
400 G4double tsam = 0;
401 G4double gtr = 0;
402
403 //2) sampling. Eq. (2.31) of Penelope Manual
404 // tsam = 1-std::cos(theta)
405 // gtr = rejection function according to Eq. (2.28)
406 do{
407 G4double rand = G4UniformRand();
408 tsam = 2.0*ac * (2.0*rand + a2*std::sqrt(rand)) / (a2*a2 - 4.0*rand);
409 gtr = (2.0 - tsam) * (a1 + 1.0/(ac+tsam));
410 }while(G4UniformRand()*gtmax > gtr);
411 costheta = 1.0-tsam;
412 return costheta;
413}
414
Note: See TracBrowser for help on using the repository browser.