source: trunk/source/processes/electromagnetic/lowenergy/src/G4LowEnergyCompton.cc@ 968

Last change on this file since 968 was 961, checked in by garnier, 17 years ago

update processes

File size: 12.3 KB
RevLine 
[819]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//
[961]26// $Id: G4LowEnergyCompton.cc,v 1.47 2008/12/18 13:01:28 gunter Exp $
27// GEANT4 tag $Name: geant4-09-02-ref-02 $
[819]28//
29// Author: A. Forti
30// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
31//
32// History:
33// --------
34// Added Livermore data table construction methods A. Forti
35// Modified BuildMeanFreePath to read new data tables A. Forti
36// Modified PostStepDoIt to insert sampling with EPDL97 data A. Forti
37// Added SelectRandomAtom A. Forti
38// Added map of the elements A. Forti
39// 24.04.2001 V.Ivanchenko - Remove RogueWave
40// 06.08.2001 MGP - Revised according to a design iteration
41// 22.01.2003 V.Ivanchenko - Cut per region
42// 10.03.2003 V.Ivanchenko - Remove CutPerMaterial warning
43// 24.04.2003 V.Ivanchenko - Cut per region mfpt
44//
45// -------------------------------------------------------------------
46
47#include "G4LowEnergyCompton.hh"
48#include "Randomize.hh"
49#include "G4ParticleDefinition.hh"
50#include "G4Track.hh"
51#include "G4Step.hh"
52#include "G4ForceCondition.hh"
53#include "G4Gamma.hh"
54#include "G4Electron.hh"
55#include "G4DynamicParticle.hh"
56#include "G4VParticleChange.hh"
57#include "G4ThreeVector.hh"
58#include "G4EnergyLossTables.hh"
59#include "G4VCrossSectionHandler.hh"
60#include "G4CrossSectionHandler.hh"
61#include "G4VEMDataSet.hh"
62#include "G4CompositeEMDataSet.hh"
63#include "G4VDataSetAlgorithm.hh"
64#include "G4LogLogInterpolation.hh"
65#include "G4VRangeTest.hh"
66#include "G4RangeTest.hh"
[961]67#include "G4RangeNoTest.hh"
[819]68#include "G4MaterialCutsCouple.hh"
69
70
71G4LowEnergyCompton::G4LowEnergyCompton(const G4String& processName)
72 : G4VDiscreteProcess(processName),
73 lowEnergyLimit(250*eV),
74 highEnergyLimit(100*GeV),
75 intrinsicLowEnergyLimit(10*eV),
76 intrinsicHighEnergyLimit(100*GeV)
77{
78 if (lowEnergyLimit < intrinsicLowEnergyLimit ||
79 highEnergyLimit > intrinsicHighEnergyLimit)
80 {
81 G4Exception("G4LowEnergyCompton::G4LowEnergyCompton - energy outside intrinsic process validity range");
82 }
83
84 crossSectionHandler = new G4CrossSectionHandler;
85
86 G4VDataSetAlgorithm* scatterInterpolation = new G4LogLogInterpolation;
87 G4String scatterFile = "comp/ce-sf-";
88 scatterFunctionData = new G4CompositeEMDataSet(scatterInterpolation, 1., 1.);
89 scatterFunctionData->LoadData(scatterFile);
90
91 meanFreePathTable = 0;
92
[961]93 rangeTest = new G4RangeNoTest;
[819]94
[961]95 // For Doppler broadening
96 shellData.SetOccupancyData();
97
[819]98 if (verboseLevel > 0)
99 {
100 G4cout << GetProcessName() << " is created " << G4endl
101 << "Energy range: "
102 << lowEnergyLimit / keV << " keV - "
103 << highEnergyLimit / GeV << " GeV"
104 << G4endl;
105 }
106}
107
108G4LowEnergyCompton::~G4LowEnergyCompton()
109{
110 delete meanFreePathTable;
111 delete crossSectionHandler;
112 delete scatterFunctionData;
113 delete rangeTest;
114}
115
116void G4LowEnergyCompton::BuildPhysicsTable(const G4ParticleDefinition& )
117{
118
119 crossSectionHandler->Clear();
120 G4String crossSectionFile = "comp/ce-cs-";
121 crossSectionHandler->LoadData(crossSectionFile);
122
123 delete meanFreePathTable;
124 meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
[961]125
126 // For Doppler broadening
127 G4String file = "/doppler/shell-doppler";
128 shellData.LoadData(file);
[819]129}
130
131G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
132 const G4Step& aStep)
133{
134 // The scattered gamma energy is sampled according to Klein - Nishina formula.
135 // then accepted or rejected depending on the Scattering Function multiplied
136 // by factor from Klein - Nishina formula.
137 // Expression of the angular distribution as Klein Nishina
138 // angular and energy distribution and Scattering fuctions is taken from
139 // D. E. Cullen "A simple model of photon transport" Nucl. Instr. Meth.
140 // Phys. Res. B 101 (1995). Method of sampling with form factors is different
141 // data are interpolated while in the article they are fitted.
142 // Reference to the article is from J. Stepanek New Photon, Positron
143 // and Electron Interaction Data for GEANT in Energy Range from 1 eV to 10
144 // TeV (draft).
145 // The random number techniques of Butcher & Messel are used
146 // (Nucl Phys 20(1960),15).
147
148 aParticleChange.Initialize(aTrack);
149
150 // Dynamic particle quantities
151 const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
152 G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
153
154 if (photonEnergy0 <= lowEnergyLimit)
155 {
156 aParticleChange.ProposeTrackStatus(fStopAndKill);
157 aParticleChange.ProposeEnergy(0.);
158 aParticleChange.ProposeLocalEnergyDeposit(photonEnergy0);
159 return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
160 }
161
162 G4double e0m = photonEnergy0 / electron_mass_c2 ;
163 G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
164 G4double epsilon0 = 1. / (1. + 2. * e0m);
165 G4double epsilon0Sq = epsilon0 * epsilon0;
166 G4double alpha1 = -std::log(epsilon0);
167 G4double alpha2 = 0.5 * (1. - epsilon0Sq);
168 G4double wlPhoton = h_Planck*c_light/photonEnergy0;
169
[961]170 // Select randomly one element in the current material
171 const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
172 G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy0);
173
[819]174 // Sample the energy of the scattered photon
175 G4double epsilon;
176 G4double epsilonSq;
177 G4double oneCosT;
178 G4double sinT2;
179 G4double gReject;
180 do
181 {
182 if ( alpha1/(alpha1+alpha2) > G4UniformRand())
183 {
184 epsilon = std::exp(-alpha1 * G4UniformRand()); // std::pow(epsilon0,G4UniformRand())
185 epsilonSq = epsilon * epsilon;
186 }
187 else
188 {
189 epsilonSq = epsilon0Sq + (1. - epsilon0Sq) * G4UniformRand();
190 epsilon = std::sqrt(epsilonSq);
191 }
192
193 oneCosT = (1. - epsilon) / ( epsilon * e0m);
194 sinT2 = oneCosT * (2. - oneCosT);
195 G4double x = std::sqrt(oneCosT/2.) / (wlPhoton/cm);
196 G4double scatteringFunction = scatterFunctionData->FindValue(x,Z-1);
197 gReject = (1. - epsilon * sinT2 / (1. + epsilonSq)) * scatteringFunction;
198
199 } while(gReject < G4UniformRand()*Z);
200
201 G4double cosTheta = 1. - oneCosT;
202 G4double sinTheta = std::sqrt (sinT2);
203 G4double phi = twopi * G4UniformRand() ;
[961]204 G4double dirX = sinTheta * std::cos(phi);
205 G4double dirY = sinTheta * std::sin(phi);
206 G4double dirZ = cosTheta ;
[819]207
[961]208 // Doppler broadening - Method based on:
209 // Y. Namito, S. Ban and H. Hirayama,
210 // "Implementation of the Doppler Broadening of a Compton-Scattered Photon Into the EGS4 Code"
211 // NIM A 349, pp. 489-494, 1994
212
213 // Maximum number of sampling iterations
214 G4int maxDopplerIterations = 1000;
215 G4double bindingE = 0.;
216 G4double photonEoriginal = epsilon * photonEnergy0;
217 G4double photonE = -1.;
218 G4int iteration = 0;
219 G4double eMax = photonEnergy0;
220 do
221 {
222 iteration++;
223 // Select shell based on shell occupancy
224 G4int shell = shellData.SelectRandomShell(Z);
225 bindingE = shellData.BindingEnergy(Z,shell);
226
227 eMax = photonEnergy0 - bindingE;
228
229 // Randomly sample bound electron momentum (memento: the data set is in Atomic Units)
230 G4double pSample = profileData.RandomSelectMomentum(Z,shell);
231 // Rescale from atomic units
232 G4double pDoppler = pSample * fine_structure_const;
233 G4double pDoppler2 = pDoppler * pDoppler;
234 G4double var2 = 1. + oneCosT * e0m;
235 G4double var3 = var2*var2 - pDoppler2;
236 G4double var4 = var2 - pDoppler2 * cosTheta;
237 G4double var = var4*var4 - var3 + pDoppler2 * var3;
238 if (var > 0.)
239 {
240 G4double varSqrt = std::sqrt(var);
241 G4double scale = photonEnergy0 / var3;
242 // Random select either root
243 if (G4UniformRand() < 0.5) photonE = (var4 - varSqrt) * scale;
244 else photonE = (var4 + varSqrt) * scale;
245 }
246 else
247 {
248 photonE = -1.;
249 }
250 } while ( iteration <= maxDopplerIterations &&
251 (photonE < 0. || photonE > eMax || photonE < eMax*G4UniformRand()) );
252
253 // End of recalculation of photon energy with Doppler broadening
254 // Revert to original if maximum number of iterations threshold has been reached
255 if (iteration >= maxDopplerIterations)
256 {
257 photonE = photonEoriginal;
258 bindingE = 0.;
259 }
260
[819]261 // Update G4VParticleChange for the scattered photon
262
[961]263 G4ThreeVector photonDirection1(dirX,dirY,dirZ);
[819]264 photonDirection1.rotateUz(photonDirection0);
[961]265 aParticleChange.ProposeMomentumDirection(photonDirection1);
266
267 G4double photonEnergy1 = photonE;
268 //G4cout << "--> PHOTONENERGY1 = " << photonE/keV << G4endl;
[819]269
270 if (photonEnergy1 > 0.)
271 {
272 aParticleChange.ProposeEnergy(photonEnergy1) ;
273 }
274 else
275 {
276 aParticleChange.ProposeEnergy(0.) ;
277 aParticleChange.ProposeTrackStatus(fStopAndKill);
278 }
279
280 // Kinematics of the scattered electron
[961]281 G4double eKineticEnergy = photonEnergy0 - photonEnergy1 - bindingE;
282 G4double eTotalEnergy = eKineticEnergy + electron_mass_c2;
[819]283
[961]284 G4double electronE = photonEnergy0 * (1. - epsilon) + electron_mass_c2;
285 G4double electronP2 = electronE*electronE - electron_mass_c2*electron_mass_c2;
286 G4double sinThetaE = -1.;
287 G4double cosThetaE = 0.;
288 if (electronP2 > 0.)
289 {
290 cosThetaE = (eTotalEnergy + photonEnergy1 )* (1. - epsilon) / std::sqrt(electronP2);
291 sinThetaE = -1. * std::sqrt(1. - cosThetaE * cosThetaE);
292 }
293
294 G4double eDirX = sinThetaE * std::cos(phi);
295 G4double eDirY = sinThetaE * std::sin(phi);
296 G4double eDirZ = cosThetaE;
297
[819]298 // Generate the electron only if with large enough range w.r.t. cuts and safety
299
300 G4double safety = aStep.GetPostStepPoint()->GetSafety();
301
302 if (rangeTest->Escape(G4Electron::Electron(),couple,eKineticEnergy,safety))
303 {
[961]304 G4ThreeVector eDirection(eDirX,eDirY,eDirZ);
305 eDirection.rotateUz(photonDirection0);
306
307 G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),eDirection,eKineticEnergy) ;
[819]308 aParticleChange.SetNumberOfSecondaries(1);
309 aParticleChange.AddSecondary(electron);
[961]310 // Binding energy deposited locally
311 aParticleChange.ProposeLocalEnergyDeposit(bindingE);
[819]312 }
313 else
314 {
315 aParticleChange.SetNumberOfSecondaries(0);
[961]316 aParticleChange.ProposeLocalEnergyDeposit(eKineticEnergy + bindingE);
[819]317 }
318
319 return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
320}
321
322G4bool G4LowEnergyCompton::IsApplicable(const G4ParticleDefinition& particle)
323{
324 return ( &particle == G4Gamma::Gamma() );
325}
326
327G4double G4LowEnergyCompton::GetMeanFreePath(const G4Track& track,
328 G4double, // previousStepSize
329 G4ForceCondition*)
330{
331 const G4DynamicParticle* photon = track.GetDynamicParticle();
332 G4double energy = photon->GetKineticEnergy();
333 const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
334 size_t materialIndex = couple->GetIndex();
335
336 G4double meanFreePath;
337 if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
338 else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
339 else meanFreePath = meanFreePathTable->FindValue(energy,materialIndex);
340 return meanFreePath;
341}
Note: See TracBrowser for help on using the repository browser.