Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4eeToTwoGammaModel.cc
Go to the documentation of this file.
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$
27//
28// -------------------------------------------------------------------
29//
30// GEANT4 Class file
31//
32//
33// File name: G4eeToTwoGammaModel
34//
35// Author: Vladimir Ivanchenko on base of Michel Maire code
36//
37// Creation date: 02.08.2004
38//
39// Modifications:
40// 08-04-05 Major optimisation of internal interfaces (V.Ivanchenko)
41// 18-04-05 Compute CrossSectionPerVolume (V.Ivanchenko)
42// 06-02-06 ComputeCrossSectionPerElectron, ComputeCrossSectionPerAtom (mma)
43// 29-06-06 Fix problem for zero energy incident positron (V.Ivanchenko)
44// 20-10-06 Add theGamma as a member (V.Ivanchenko)
45//
46//
47// Class Description:
48//
49// Implementation of e+ annihilation into 2 gamma
50//
51// The secondaries Gamma energies are sampled using the Heitler cross section.
52//
53// A modified version of the random number techniques of Butcher & Messel
54// is used (Nuc Phys 20(1960),15).
55//
56// GEANT4 internal units.
57//
58// Note 1: The initial electron is assumed free and at rest.
59//
60// Note 2: The annihilation processes producing one or more than two photons are
61// ignored, as negligible compared to the two photons process.
62
63
64
65//
66// -------------------------------------------------------------------
67//
68//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
69//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
70
73#include "G4SystemOfUnits.hh"
74#include "G4TrackStatus.hh"
75#include "G4Electron.hh"
76#include "G4Positron.hh"
77#include "G4Gamma.hh"
78#include "Randomize.hh"
80
81//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
82
83using namespace std;
84
86 const G4String& nam)
87 : G4VEmModel(nam),
88 pi_rcl2(pi*classic_electr_radius*classic_electr_radius),
89 isInitialised(false)
90{
91 theGamma = G4Gamma::Gamma();
92 fParticleChange = 0;
93}
94
95//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
96
98{}
99
100//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
101
103 const G4DataVector&)
104{
105 if(isInitialised) { return; }
106 fParticleChange = GetParticleChangeForGamma();
107 isInitialised = true;
108}
109
110//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
111
114 G4double kineticEnergy,
116{
117 // Calculates the cross section per electron of annihilation into two photons
118 // from the Heilter formula.
119
120 G4double ekin = std::max(eV,kineticEnergy);
121
122 G4double tau = ekin/electron_mass_c2;
123 G4double gam = tau + 1.0;
124 G4double gamma2= gam*gam;
125 G4double bg2 = tau * (tau+2.0);
126 G4double bg = sqrt(bg2);
127
128 G4double cross = pi_rcl2*((gamma2+4*gam+1.)*log(gam+bg) - (gam+3.)*bg)
129 / (bg2*(gam+1.));
130 return cross;
131}
132
133//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
134
136 const G4ParticleDefinition* p,
137 G4double kineticEnergy, G4double Z,
139{
140 // Calculates the cross section per atom of annihilation into two photons
141
142 G4double cross = Z*ComputeCrossSectionPerElectron(p,kineticEnergy);
143 return cross;
144}
145
146//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
147
149 const G4Material* material,
150 const G4ParticleDefinition* p,
151 G4double kineticEnergy,
153{
154 // Calculates the cross section per volume of annihilation into two photons
155
156 G4double eDensity = material->GetElectronDensity();
157 G4double cross = eDensity*ComputeCrossSectionPerElectron(p,kineticEnergy);
158 return cross;
159}
160
161//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
162
163void G4eeToTwoGammaModel::SampleSecondaries(vector<G4DynamicParticle*>* vdp,
165 const G4DynamicParticle* dp,
166 G4double,
167 G4double)
168{
169 G4double PositKinEnergy = dp->GetKineticEnergy();
170 G4DynamicParticle *aGamma1, *aGamma2;
171
172 // Case at rest
173 if(PositKinEnergy == 0.0) {
174 G4double cost = 2.*G4UniformRand()-1.;
175 G4double sint = sqrt((1. - cost)*(1. + cost));
176 G4double phi = twopi * G4UniformRand();
177 G4ThreeVector dir(sint*cos(phi), sint*sin(phi), cost);
178 phi = twopi * G4UniformRand();
179 G4ThreeVector pol(cos(phi), sin(phi), 0.0);
180 pol.rotateUz(dir);
181 aGamma1 = new G4DynamicParticle(theGamma, dir, electron_mass_c2);
182 aGamma1->SetPolarization(pol.x(),pol.y(),pol.z());
183 aGamma2 = new G4DynamicParticle(theGamma,-dir, electron_mass_c2);
184 aGamma1->SetPolarization(-pol.x(),-pol.y(),-pol.z());
185
186 } else {
187
188 G4ThreeVector PositDirection = dp->GetMomentumDirection();
189
190 G4double tau = PositKinEnergy/electron_mass_c2;
191 G4double gam = tau + 1.0;
192 G4double tau2 = tau + 2.0;
193 G4double sqgrate = sqrt(tau/tau2)*0.5;
194 G4double sqg2m1 = sqrt(tau*tau2);
195
196 // limits of the energy sampling
197 G4double epsilmin = 0.5 - sqgrate;
198 G4double epsilmax = 0.5 + sqgrate;
199 G4double epsilqot = epsilmax/epsilmin;
200
201 //
202 // sample the energy rate of the created gammas
203 //
204 G4double epsil, greject;
205
206 do {
207 epsil = epsilmin*pow(epsilqot,G4UniformRand());
208 greject = 1. - epsil + (2.*gam*epsil-1.)/(epsil*tau2*tau2);
209 } while( greject < G4UniformRand() );
210
211 //
212 // scattered Gamma angles. ( Z - axis along the parent positron)
213 //
214
215 G4double cost = (epsil*tau2-1.)/(epsil*sqg2m1);
216 if(std::abs(cost) > 1.0) {
217 G4cout << "### G4eeToTwoGammaModel WARNING cost= " << cost
218 << " positron Ekin(MeV)= " << PositKinEnergy
219 << " gamma epsil= " << epsil
220 << G4endl;
221 if(cost > 1.0) cost = 1.0;
222 else cost = -1.0;
223 }
224 G4double sint = sqrt((1.+cost)*(1.-cost));
225 G4double phi = twopi * G4UniformRand();
226
227 //
228 // kinematic of the created pair
229 //
230
231 G4double TotalAvailableEnergy = PositKinEnergy + 2.0*electron_mass_c2;
232 G4double Phot1Energy = epsil*TotalAvailableEnergy;
233
234 G4ThreeVector Phot1Direction(sint*cos(phi), sint*sin(phi), cost);
235 Phot1Direction.rotateUz(PositDirection);
236 aGamma1 = new G4DynamicParticle (theGamma,Phot1Direction, Phot1Energy);
237 phi = twopi * G4UniformRand();
238 G4ThreeVector pol1(cos(phi), sin(phi), 0.0);
239 pol1.rotateUz(Phot1Direction);
240 aGamma1->SetPolarization(pol1.x(),pol1.y(),pol1.z());
241
242 G4double Phot2Energy =(1.-epsil)*TotalAvailableEnergy;
243 G4double PositP= sqrt(PositKinEnergy*(PositKinEnergy+2.*electron_mass_c2));
244 G4ThreeVector dir = PositDirection*PositP - Phot1Direction*Phot1Energy;
245 G4ThreeVector Phot2Direction = dir.unit();
246
247 // create G4DynamicParticle object for the particle2
248 aGamma2 = new G4DynamicParticle (theGamma,Phot2Direction, Phot2Energy);
249
250 //!!! likely problematic direction to be checked
251 aGamma2->SetPolarization(-pol1.x(),-pol1.y(),-pol1.z());
252 }
253 /*
254 G4cout << "Annihilation in fly: e0= " << PositKinEnergy
255 << " m= " << electron_mass_c2
256 << " e1= " << Phot1Energy
257 << " e2= " << Phot2Energy << " dir= " << dir
258 << " -> " << Phot1Direction << " "
259 << Phot2Direction << G4endl;
260 */
261
262 vdp->push_back(aGamma1);
263 vdp->push_back(aGamma2);
264 fParticleChange->SetProposedKineticEnergy(0.);
265 fParticleChange->ProposeTrackStatus(fStopAndKill);
266}
267
268//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@ fStopAndKill
double G4double
Definition: G4Types.hh:64
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
double z() const
Hep3Vector unit() const
double x() const
double y() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:72
const G4ThreeVector & GetMomentumDirection() const
void SetPolarization(G4double polX, G4double polY, G4double polZ)
G4double GetKineticEnergy() const
static G4Gamma * Gamma()
Definition: G4Gamma.cc:86
G4double GetElectronDensity() const
Definition: G4Material.hh:216
void SetProposedKineticEnergy(G4double proposedKinEnergy)
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:109
void ProposeTrackStatus(G4TrackStatus status)
virtual G4double ComputeCrossSectionPerElectron(const G4ParticleDefinition *, G4double kinEnergy, G4double cutEnergy=0., G4double maxEnergy=DBL_MAX)
G4eeToTwoGammaModel(const G4ParticleDefinition *p=0, const G4String &nam="eplus2gg")
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cutEnergy=0., G4double maxEnergy=DBL_MAX)