source: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeComptonModel.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: 27.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: G4PenelopeComptonModel.cc,v 1.8 2009/10/23 09:29:24 pandola Exp $
27// GEANT4 tag $Name: geant4-09-03-cand-01 $
28//
29// Author: Luciano Pandola
30//
31// History:
32// --------
33// 02 Oct 2008 L Pandola Migration from process to model
34// 28 Oct 2008 L Pandola Treat the database data from Penelope according to the
35// original model, namely merging levels below 15 eV in
36// a single one. Still, it is not fully compliant with the
37// original Penelope model, because plasma excitation is not
38// considered.
39// 22 Nov 2008 L Pandola Make unit of measurements explicit for binding energies
40// that are read from the external files.
41// 24 Nov 2008 L Pandola Find a cleaner way to delete vectors.
42// 16 Apr 2009 V Ivanchenko Cleanup initialisation and generation of secondaries:
43// - apply internal high-energy limit only in constructor
44// - do not apply low-energy limit (default is 0)
45// - do not apply production threshold on level of the model
46// 21 Oct 2009 L Pandola Remove un-necessary fUseAtomicDeexcitation flag - now managed by
47// G4VEmModel::DeexcitationFlag()
48// Add ActivateAuger() method
49//
50
51#include "G4PenelopeComptonModel.hh"
52#include "G4ParticleDefinition.hh"
53#include "G4MaterialCutsCouple.hh"
54#include "G4ProductionCutsTable.hh"
55#include "G4DynamicParticle.hh"
56#include "G4VEMDataSet.hh"
57#include "G4PhysicsTable.hh"
58#include "G4ElementTable.hh"
59#include "G4Element.hh"
60#include "G4PhysicsLogVector.hh"
61#include "G4PenelopeIntegrator.hh"
62#include "G4AtomicTransitionManager.hh"
63#include "G4AtomicShell.hh"
64#include "G4Gamma.hh"
65#include "G4Electron.hh"
66
67//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
68
69
70G4PenelopeComptonModel::G4PenelopeComptonModel(const G4ParticleDefinition*,
71 const G4String& nam)
72 :G4VEmModel(nam),ionizationEnergy(0),hartreeFunction(0),
73 occupationNumber(0),isInitialised(false)
74{
75 fIntrinsicLowEnergyLimit = 100.0*eV;
76 fIntrinsicHighEnergyLimit = 100.0*GeV;
77 // SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
78 SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
79 //
80 energyForIntegration = 0.0;
81 ZForIntegration = 1;
82
83 //by default, the model will use atomic deexcitation
84 SetDeexcitationFlag(true);
85 ActivateAuger(false);
86
87 verboseLevel= 0;
88 // Verbosity scale:
89 // 0 = nothing
90 // 1 = warning for energy non-conservation
91 // 2 = details of energy budget
92 // 3 = calculation of cross sections, file openings, sampling of atoms
93 // 4 = entering in methods
94
95 //These vectors do not change when materials or cut change.
96 //Therefore I can read it at the constructor
97 ionizationEnergy = new std::map<G4int,G4DataVector*>;
98 hartreeFunction = new std::map<G4int,G4DataVector*>;
99 occupationNumber = new std::map<G4int,G4DataVector*>;
100
101 ReadData(); //Read data from file
102
103}
104
105//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
106
107G4PenelopeComptonModel::~G4PenelopeComptonModel()
108{
109 std::map <G4int,G4DataVector*>::iterator i;
110 for (i=ionizationEnergy->begin();i != ionizationEnergy->end();i++)
111 if (i->second) delete i->second;
112 for (i=hartreeFunction->begin();i != hartreeFunction->end();i++)
113 if (i->second) delete i->second;
114 for (i=occupationNumber->begin();i != occupationNumber->end();i++)
115 if (i->second) delete i->second;
116
117
118 if (ionizationEnergy)
119 delete ionizationEnergy;
120 if (hartreeFunction)
121 delete hartreeFunction;
122 if (occupationNumber)
123 delete occupationNumber;
124}
125
126//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
127
128void G4PenelopeComptonModel::Initialise(const G4ParticleDefinition* particle,
129 const G4DataVector& cuts)
130{
131 if (verboseLevel > 3)
132 G4cout << "Calling G4PenelopeComptonModel::Initialise()" << G4endl;
133
134 InitialiseElementSelectors(particle,cuts);
135
136 if (verboseLevel > 0) {
137 G4cout << "Penelope Compton model is initialized " << G4endl
138 << "Energy range: "
139 << LowEnergyLimit() / keV << " keV - "
140 << HighEnergyLimit() / GeV << " GeV"
141 << G4endl;
142 }
143
144 if(isInitialised) return;
145 fParticleChange = GetParticleChangeForGamma();
146 isInitialised = true;
147}
148
149//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
150
151G4double G4PenelopeComptonModel::ComputeCrossSectionPerAtom(
152 const G4ParticleDefinition*,
153 G4double energy,
154 G4double Z, G4double,
155 G4double, G4double)
156{
157 // Penelope model to calculate the Compton scattering cross section:
158 // D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
159 //
160 // The cross section for Compton scattering is calculated according to the Klein-Nishina
161 // formula for energy > 5 MeV.
162 // For E < 5 MeV it is used a parametrization for the differential cross-section dSigma/dOmega,
163 // which is integrated numerically in cos(theta), G4PenelopeComptonModel::DifferentialCrossSection().
164 // The parametrization includes the J(p)
165 // distribution profiles for the atomic shells, that are tabulated from Hartree-Fock calculations
166 // from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201
167 //
168 if (verboseLevel > 3)
169 G4cout << "Calling ComputeCrossSectionPerAtom() of G4PenelopeComptonModel" << G4endl;
170
171 G4int iZ = (G4int) Z;
172 G4double cs=0.0;
173 energyForIntegration=energy;
174 ZForIntegration = iZ;
175 if (energy< 5*MeV)
176 {
177 // numerically integrate differential cross section dSigma/dOmega
178 G4PenelopeIntegrator<G4PenelopeComptonModel,G4double (G4PenelopeComptonModel::*)(G4double)>
179 theIntegrator;
180 cs = theIntegrator.Calculate(this,&G4PenelopeComptonModel::DifferentialCrossSection,-1.0,1.0,1e-05);
181 }
182 else
183 {
184 // use Klein-Nishina formula
185 G4double ki=energy/electron_mass_c2;
186 G4double ki3=ki*ki;
187 G4double ki2=1.0+2*ki;
188 G4double ki1=ki3-ki2-1.0;
189 G4double t0=1.0/(ki2);
190 G4double csl = 0.5*ki3*t0*t0+ki2*t0+ki1*std::log(t0)-(1.0/t0);
191 G4int nosc = occupationNumber->find(iZ)->second->size();
192 for (G4int i=0;i<nosc;i++)
193 {
194 G4double ionEnergy = (*(ionizationEnergy->find(iZ)->second))[i];
195 G4double tau=(energy-ionEnergy)/energy;
196 if (tau > t0)
197 {
198 G4double csu = 0.5*ki3*tau*tau+ki2*tau+ki1*std::log(tau)-(1.0/tau);
199 G4int f = (G4int) (*(occupationNumber->find(iZ)->second))[i];
200 cs = cs + f*(csu-csl);
201 }
202 }
203 cs=pi*classic_electr_radius*classic_electr_radius*cs/(ki*ki3);
204 }
205
206 if (verboseLevel > 2)
207 G4cout << "Compton cross Section at " << energy/keV << " keV for Z=" << Z <<
208 " = " << cs/barn << " barn" << G4endl;
209 return cs;
210}
211
212//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
213
214void G4PenelopeComptonModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
215 const G4MaterialCutsCouple* couple,
216 const G4DynamicParticle* aDynamicGamma,
217 G4double,
218 G4double)
219{
220
221 // Penelope model to sample the Compton scattering final state.
222 // D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
223 // The model determines also the original shell from which the electron is expelled,
224 // in order to produce fluorescence de-excitation (from G4DeexcitationManager)
225 //
226 // The final state for Compton scattering is calculated according to the Klein-Nishina
227 // formula for energy > 5 MeV. In this case, the Doppler broadening is negligible and
228 // one can assume that the target electron is at rest.
229 // For E < 5 MeV it is used the parametrization for the differential cross-section dSigma/dOmega,
230 // to sample the scattering angle and the energy of the emerging electron, which is
231 // G4PenelopeComptonModel::DifferentialCrossSection(). The rejection method is
232 // used to sample cos(theta). The efficiency increases monotonically with photon energy and is
233 // nearly independent on the Z; typical values are 35%, 80% and 95% for 1 keV, 1 MeV and 10 MeV,
234 // respectively.
235 // The parametrization includes the J(p) distribution profiles for the atomic shells, that are
236 // tabulated
237 // from Hartree-Fock calculations from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201.
238 // Doppler broadening is included.
239 //
240
241 if (verboseLevel > 3)
242 G4cout << "Calling SampleSecondaries() of G4PenelopeComptonModel" << G4endl;
243
244 G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
245
246 if (photonEnergy0 <= fIntrinsicLowEnergyLimit)
247 {
248 fParticleChange->ProposeTrackStatus(fStopAndKill);
249 fParticleChange->SetProposedKineticEnergy(0.);
250 fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
251 return ;
252 }
253
254 G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
255
256 // Select randomly one element in the current material
257 if (verboseLevel > 2)
258 G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl;
259 // atom can be selected effitiantly if element selectors are initialised
260 const G4Element* anElement =
261 SelectRandomAtom(couple,G4Gamma::GammaDefinition(),photonEnergy0);
262 G4int Z = (G4int) anElement->GetZ();
263 if (verboseLevel > 2)
264 G4cout << "Selected " << anElement->GetName() << G4endl;
265
266 const G4int nmax = 64;
267 G4double rn[nmax],pac[nmax];
268
269 G4double ki,ki1,ki2,ki3,taumin,a1,a2;
270 G4double tau,TST;
271 G4double S=0.0;
272 G4double epsilon,cosTheta;
273 G4double harFunc = 0.0;
274 G4int occupNb= 0;
275 G4double ionEnergy=0.0;
276 G4int nosc = occupationNumber->find(Z)->second->size();
277 G4int iosc = nosc;
278 ki = photonEnergy0/electron_mass_c2;
279 ki2 = 2*ki+1.0;
280 ki3 = ki*ki;
281 ki1 = ki3-ki2-1.0;
282 taumin = 1.0/ki2;
283 a1 = std::log(ki2);
284 a2 = a1+2.0*ki*(1.0+ki)/(ki2*ki2);
285 //If the incoming photon is above 5 MeV, the quicker approach based on the
286 //pure Klein-Nishina formula is used
287 if (photonEnergy0 > 5*MeV)
288 {
289 do{
290 do{
291 if ((a2*G4UniformRand()) < a1)
292 {
293 tau = std::pow(taumin,G4UniformRand());
294 }
295 else
296 {
297 tau = std::sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));
298 }
299 //rejection function
300 TST = (1+tau*(ki1+tau*(ki2+tau*ki3)))/(ki3*tau*(1.0+tau*tau));
301 }while (G4UniformRand()> TST);
302 epsilon=tau;
303 cosTheta = 1.0 - (1.0-tau)/(ki*tau);
304 //Target shell electrons
305 TST = Z*G4UniformRand();
306 iosc = nosc;
307 S=0.0;
308 for (G4int j=0;j<nosc;j++)
309 {
310 occupNb = (G4int) (*(occupationNumber->find(Z)->second))[j];
311 S = S + occupNb;
312 if (S > TST) iosc = j;
313 if (S > TST) break;
314 }
315 ionEnergy = (*(ionizationEnergy->find(Z)->second))[iosc];
316 }while((epsilon*photonEnergy0-photonEnergy0+ionEnergy) >0);
317 }
318 else //photonEnergy0 < 5 MeV
319 {
320 //Incoherent scattering function for theta=PI
321 G4double s0=0.0;
322 G4double pzomc=0.0,rni=0.0;
323 G4double aux=0.0;
324 for (G4int i=0;i<nosc;i++){
325 ionEnergy = (*(ionizationEnergy->find(Z)->second))[i];
326 if (photonEnergy0 > ionEnergy)
327 {
328 G4double aux = photonEnergy0*(photonEnergy0-ionEnergy)*2.0;
329 harFunc = (*(hartreeFunction->find(Z)->second))[i]/fine_structure_const;
330 occupNb = (G4int) (*(occupationNumber->find(Z)->second))[i];
331 pzomc = harFunc*(aux-electron_mass_c2*ionEnergy)/
332 (electron_mass_c2*std::sqrt(2.0*aux+ionEnergy*ionEnergy));
333 if (pzomc > 0)
334 {
335 rni = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
336 (std::sqrt(0.5)+std::sqrt(2.0)*pzomc));
337 }
338 else
339 {
340 rni = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
341 (std::sqrt(0.5)-std::sqrt(2.0)*pzomc));
342 }
343 s0 = s0 + occupNb*rni;
344 }
345 }
346
347 //Sampling tau
348 G4double cdt1;
349 do
350 {
351 if ((G4UniformRand()*a2) < a1)
352 {
353 tau = std::pow(taumin,G4UniformRand());
354 }
355 else
356 {
357 tau = std::sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));
358 }
359 cdt1 = (1.0-tau)/(ki*tau);
360 S=0.0;
361 //Incoherent scattering function
362 for (G4int i=0;i<nosc;i++){
363 ionEnergy = (*(ionizationEnergy->find(Z)->second))[i];
364 if (photonEnergy0 > ionEnergy) //sum only on excitable levels
365 {
366 aux = photonEnergy0*(photonEnergy0-ionEnergy)*cdt1;
367 harFunc = (*(hartreeFunction->find(Z)->second))[i]/fine_structure_const;
368 occupNb = (G4int) (*(occupationNumber->find(Z)->second))[i];
369 pzomc = harFunc*(aux-electron_mass_c2*ionEnergy)/
370 (electron_mass_c2*std::sqrt(2.0*aux+ionEnergy*ionEnergy));
371 if (pzomc > 0)
372 {
373 rn[i] = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
374 (std::sqrt(0.5)+std::sqrt(2.0)*pzomc));
375 }
376 else
377 {
378 rn[i] = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
379 (std::sqrt(0.5)-std::sqrt(2.0)*pzomc));
380 }
381 S = S + occupNb*rn[i];
382 pac[i] = S;
383 }
384 else
385 {
386 pac[i] = S-(1e-06);
387 }
388 }
389 //Rejection function
390 TST = S*(1.0+tau*(ki1+tau*(ki2+tau*ki3)))/(ki3*tau*(1.0+tau*tau));
391 }while ((G4UniformRand()*s0) > TST);
392 //Target electron shell
393 cosTheta = 1.0 - cdt1;
394 G4double fpzmax=0.0,fpz=0.0;
395 G4double A=0.0;
396 do
397 {
398 do
399 {
400 TST =S*G4UniformRand();
401 iosc=nosc;
402 for (G4int i=0;i<nosc;i++){
403 if (pac[i]>TST) iosc = i;
404 if (pac[i]>TST) break;
405 }
406 A = G4UniformRand()*rn[iosc];
407 harFunc = (*(hartreeFunction->find(Z)->second))[iosc]/fine_structure_const;
408 occupNb = (G4int) (*(occupationNumber->find(Z)->second))[iosc];
409 if (A < 0.5) {
410 pzomc = (std::sqrt(0.5)-std::sqrt(0.5-std::log(2.0*A)))/
411 (std::sqrt(2.0)*harFunc);
412 }
413 else
414 {
415 pzomc = (std::sqrt(0.5-std::log(2.0-2.0*A))-std::sqrt(0.5))/
416 (std::sqrt(2.0)*harFunc);
417 }
418 } while (pzomc < -1);
419 // F(EP) rejection
420 G4double XQC = 1.0+tau*(tau-2.0*cosTheta);
421 G4double AF = std::sqrt(XQC)*(1.0+tau*(tau-cosTheta)/XQC);
422 if (AF > 0) {
423 fpzmax = 1.0+AF*0.2;
424 }
425 else
426 {
427 fpzmax = 1.0-AF*0.2;
428 }
429 fpz = 1.0+AF*std::max(std::min(pzomc,0.2),-0.2);
430 }while ((fpzmax*G4UniformRand())>fpz);
431
432 //Energy of the scattered photon
433 G4double T = pzomc*pzomc;
434 G4double b1 = 1.0-T*tau*tau;
435 G4double b2 = 1.0-T*tau*cosTheta;
436 if (pzomc > 0.0)
437 {
438 epsilon = (tau/b1)*(b2+std::sqrt(std::abs(b2*b2-b1*(1.0-T))));
439 }
440 else
441 {
442 epsilon = (tau/b1)*(b2-std::sqrt(std::abs(b2*b2-b1*(1.0-T))));
443 }
444 }
445
446
447 //Ok, the kinematics has been calculated.
448 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
449 G4double phi = twopi * G4UniformRand() ;
450 G4double dirx = sinTheta * std::cos(phi);
451 G4double diry = sinTheta * std::sin(phi);
452 G4double dirz = cosTheta ;
453
454 // Update G4VParticleChange for the scattered photon
455 G4ThreeVector photonDirection1(dirx,diry,dirz);
456 photonDirection1.rotateUz(photonDirection0);
457 fParticleChange->ProposeMomentumDirection(photonDirection1) ;
458 G4double photonEnergy1 = epsilon * photonEnergy0;
459
460 if (photonEnergy1 > 0.)
461 {
462 fParticleChange->SetProposedKineticEnergy(photonEnergy1) ;
463 }
464 else
465 {
466 fParticleChange->SetProposedKineticEnergy(0.) ;
467 fParticleChange->ProposeTrackStatus(fStopAndKill);
468 }
469
470 //Create scattered electron
471 G4double diffEnergy = photonEnergy0*(1-epsilon);
472 ionEnergy = (*(ionizationEnergy->find(Z)->second))[iosc];
473 G4double Q2 =
474 photonEnergy0*photonEnergy0+photonEnergy1*(photonEnergy1-2.0*photonEnergy0*cosTheta);
475 G4double cosThetaE; //scattering angle for the electron
476 if (Q2 > 1.0e-12)
477 {
478 cosThetaE = (photonEnergy0-photonEnergy1*cosTheta)/std::sqrt(Q2);
479 }
480 else
481 {
482 cosThetaE = 1.0;
483 }
484 G4double sinThetaE = std::sqrt(1-cosThetaE*cosThetaE);
485
486 //initialize here, then check photons created by Atomic-Deexcitation, and the final state e-
487 std::vector<G4DynamicParticle*>* photonVector=0;
488
489 const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
490 const G4AtomicShell* shell = transitionManager->Shell(Z,iosc);
491 G4double bindingEnergy = shell->BindingEnergy();
492 G4int shellId = shell->ShellId();
493 G4double ionEnergyInPenelopeDatabase = ionEnergy;
494 //protection against energy non-conservation
495 ionEnergy = std::max(bindingEnergy,ionEnergyInPenelopeDatabase);
496
497 //subtract the excitation energy. If not emitted by fluorescence
498 //the ionization energy is deposited as local energy deposition
499 G4double eKineticEnergy = diffEnergy - ionEnergy;
500 G4double localEnergyDeposit = ionEnergy;
501 G4double energyInFluorescence = 0.; //testing purposes only
502
503 if (eKineticEnergy < 0)
504 {
505 //It means that there was some problem/mismatch between the two databases.
506 //Try to make it work
507 //In this case available Energy (diffEnergy) < ionEnergy
508 //Full residual energy is deposited locally
509 localEnergyDeposit = diffEnergy;
510 eKineticEnergy = 0.0;
511 }
512
513 //the local energy deposit is what remains: part of this may be spent for fluorescence.
514 if(DeexcitationFlag() && Z > 5) {
515
516 const G4ProductionCutsTable* theCoupleTable=
517 G4ProductionCutsTable::GetProductionCutsTable();
518
519 size_t index = couple->GetIndex();
520 G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
521 G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
522
523 // Generation of fluorescence
524 // Data in EADL are available only for Z > 5
525 // Protection to avoid generating photons in the unphysical case of
526 // shell binding energy > photon energy
527 if (localEnergyDeposit > cutg || localEnergyDeposit > cute)
528 {
529 G4DynamicParticle* aPhoton;
530 deexcitationManager.SetCutForSecondaryPhotons(cutg);
531 deexcitationManager.SetCutForAugerElectrons(cute);
532
533 photonVector = deexcitationManager.GenerateParticles(Z,shellId);
534 if(photonVector)
535 {
536 size_t nPhotons = photonVector->size();
537 for (size_t k=0; k<nPhotons; k++)
538 {
539 aPhoton = (*photonVector)[k];
540 if (aPhoton)
541 {
542 G4double itsEnergy = aPhoton->GetKineticEnergy();
543 if (itsEnergy <= localEnergyDeposit)
544 {
545 localEnergyDeposit -= itsEnergy;
546 if (aPhoton->GetDefinition() == G4Gamma::Gamma())
547 energyInFluorescence += itsEnergy;;
548 fvect->push_back(aPhoton);
549 }
550 else
551 {
552 delete aPhoton;
553 (*photonVector)[k]=0;
554 }
555 }
556 }
557 delete photonVector;
558 }
559 }
560 }
561
562 //Produce explicitely the electron only if its proposed kinetic energy is
563 //above the cut, otherwise add local energy deposition
564 G4DynamicParticle* electron = 0;
565 // if (eKineticEnergy > cutE) // VI: may be consistency problem if cut is applied here
566 if (eKineticEnergy > 0.0)
567 {
568 G4double xEl = sinThetaE * std::cos(phi+pi);
569 G4double yEl = sinThetaE * std::sin(phi+pi);
570 G4double zEl = cosThetaE;
571 G4ThreeVector eDirection(xEl,yEl,zEl); //electron direction
572 eDirection.rotateUz(photonDirection0);
573 electron = new G4DynamicParticle (G4Electron::Electron(),
574 eDirection,eKineticEnergy) ;
575 fvect->push_back(electron);
576 }
577 else
578 {
579 localEnergyDeposit += eKineticEnergy;
580 }
581
582 if (localEnergyDeposit < 0)
583 {
584 G4cout << "WARNING-"
585 << "G4PenelopeComptonModel::SampleSecondaries - Negative energy deposit"
586 << G4endl;
587 localEnergyDeposit=0.;
588 }
589 fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
590
591 G4double electronEnergy = 0.;
592 if (verboseLevel > 1)
593 {
594 G4cout << "-----------------------------------------------------------" << G4endl;
595 G4cout << "Energy balance from G4PenelopeCompton" << G4endl;
596 G4cout << "Incoming photon energy: " << photonEnergy0/keV << " keV" << G4endl;
597 G4cout << "-----------------------------------------------------------" << G4endl;
598 G4cout << "Scattered photon: " << photonEnergy1/keV << " keV" << G4endl;
599 if (electron)
600 electronEnergy = eKineticEnergy;
601 G4cout << "Scattered electron " << electronEnergy/keV << " keV" << G4endl;
602 G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
603 G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
604 G4cout << "Total final state: " << (photonEnergy1+electronEnergy+energyInFluorescence+
605 localEnergyDeposit)/keV <<
606 " keV" << G4endl;
607 G4cout << "-----------------------------------------------------------" << G4endl;
608 }
609 if (verboseLevel > 0)
610 {
611 G4double energyDiff = std::fabs(photonEnergy1+
612 electronEnergy+energyInFluorescence+
613 localEnergyDeposit-photonEnergy0);
614 if (energyDiff > 0.05*keV)
615 G4cout << "Warning from G4PenelopeCompton: problem with energy conservation: " <<
616 (photonEnergy1+electronEnergy+energyInFluorescence+localEnergyDeposit)/keV <<
617 " keV (final) vs. " <<
618 photonEnergy0/keV << " keV (initial)" << G4endl;
619 }
620}
621
622//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
623
624void G4PenelopeComptonModel::ReadData()
625{
626 char* path = getenv("G4LEDATA");
627 if (!path)
628 {
629 G4String excep = "G4PenelopeComptonModel - G4LEDATA environment variable not set!";
630 G4Exception(excep);
631 }
632 G4String pathString(path);
633 G4String pathFile = pathString + "/penelope/compton-pen.dat";
634 std::ifstream file(pathFile);
635
636 if (!file.is_open())
637 {
638 G4String excep = "G4PenelopeComptonModel - data file " + pathFile + " not found!";
639 G4Exception(excep);
640 }
641
642 G4int k1,test,test1;
643 G4double a1,a2;
644 G4int Z=1,nLevels=0;
645
646 if (!ionizationEnergy || !hartreeFunction || !occupationNumber)
647 {
648 G4String excep = "G4PenelopeComptonModel: problem with reading data from file";
649 G4Exception(excep);
650 }
651
652 do{
653 G4double harOfElectronsBelowThreshold = 0;
654 G4int nbOfElectronsBelowThreshold = 0;
655 G4DataVector* occVector = new G4DataVector;
656 G4DataVector* harVector = new G4DataVector;
657 G4DataVector* bindingEVector = new G4DataVector;
658 file >> Z >> nLevels;
659 for (G4int h=0;h<nLevels;h++)
660 {
661 file >> k1 >> a1 >> a2;
662 //Make explicit unit of measurements for ionisation energy, which is MeV
663 a1 *= MeV;
664 if (a1 > 15*eV)
665 {
666 occVector->push_back((G4double) k1);
667 bindingEVector->push_back(a1);
668 harVector->push_back(a2);
669 }
670 else
671 {
672 nbOfElectronsBelowThreshold += k1;
673 harOfElectronsBelowThreshold += k1*a2;
674 }
675 }
676 //Add the "final" level
677 if (nbOfElectronsBelowThreshold)
678 {
679 occVector->push_back(nbOfElectronsBelowThreshold);
680 bindingEVector->push_back(0*eV);
681 G4double averageHartree =
682 harOfElectronsBelowThreshold/((G4double) nbOfElectronsBelowThreshold);
683 harVector->push_back(averageHartree);
684 }
685 //Ok, done for element Z
686 occupationNumber->insert(std::make_pair(Z,occVector));
687 ionizationEnergy->insert(std::make_pair(Z,bindingEVector));
688 hartreeFunction->insert(std::make_pair(Z,harVector));
689 file >> test >> test1; //-1 -1 close the data for each Z
690 if (test > 0) {
691 G4String excep = "G4PenelopeComptonModel - data file corrupted!";
692 G4Exception(excep);
693 }
694 }while (test != -2); //the very last Z is closed with -2 instead of -1
695 file.close();
696 if (verboseLevel > 2)
697 {
698 G4cout << "Data from G4PenelopeComptonModel read " << G4endl;
699 }
700}
701
702//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
703
704G4double G4PenelopeComptonModel::DifferentialCrossSection(G4double cosTheta)
705{
706 //
707 // Penelope model for the Compton scattering differential cross section
708 // dSigma/dOmega.
709 // D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
710 // The parametrization includes the J(p) distribution profiles for the atomic shells,
711 // that are tabulated from Hartree-Fock calculations
712 // from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201
713 //
714 const G4double k2 = std::sqrt(2.0);
715 const G4double k1 = std::sqrt(0.5);
716 const G4double k12 = 0.5;
717 G4double cdt1 = 1.0-cosTheta;
718 G4double energy = energyForIntegration;
719 G4int Z = ZForIntegration;
720 //energy of Compton line;
721 G4double EOEC = 1.0+(energy/electron_mass_c2)*cdt1;
722 G4double ECOE = 1.0/EOEC;
723 //Incoherent scattering function (analytical profile)
724 G4double sia = 0.0;
725 G4int nosc = occupationNumber->find(Z)->second->size();
726 for (G4int i=0;i<nosc;i++){
727 G4double ionEnergy = (*(ionizationEnergy->find(Z)->second))[i];
728 //Sum only of those shells for which E>Eion
729 if (energy > ionEnergy)
730 {
731 G4double aux = energy * (energy-ionEnergy)*cdt1;
732 G4double Pzimax =
733 (aux - electron_mass_c2*ionEnergy)/(electron_mass_c2*std::sqrt(2*aux+ionEnergy*ionEnergy));
734 G4double harFunc = (*(hartreeFunction->find(Z)->second))[i]/fine_structure_const;
735 G4int occupNb = (G4int) (*(occupationNumber->find(Z)->second))[i];
736 G4double x = harFunc*Pzimax;
737 G4double siap = 0;
738 if (x > 0)
739 {
740 siap = 1.0-0.5*std::exp(k12-(k1+k2*x)*(k1+k2*x));
741 }
742 else
743 {
744 siap = 0.5*std::exp(k12-(k1-k2*x)*(k1-k2*x));
745 }
746 sia = sia + occupNb*siap; //sum of all contributions;
747 }
748 }
749 G4double XKN = EOEC+ECOE-1+cosTheta*cosTheta;
750 G4double diffCS = pi*classic_electr_radius*classic_electr_radius*ECOE*ECOE*XKN*sia;
751 return diffCS;
752}
753
754//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
755
756void G4PenelopeComptonModel::ActivateAuger(G4bool augerbool)
757{
758 if (!DeexcitationFlag() && augerbool)
759 {
760 G4cout << "WARNING - G4PenelopeComptonModel" << G4endl;
761 G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
762 G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
763 }
764 deexcitationManager.ActivateAugerElectronProduction(augerbool);
765 if (verboseLevel > 1)
766 G4cout << "Auger production set to " << augerbool << G4endl;
767}
768
769//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
Note: See TracBrowser for help on using the repository browser.