Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4eplusTo2GammaOKVIModel.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//
27// -------------------------------------------------------------------
28//
29// GEANT4 Class file
30//
31//
32// File name: G4eplusTo2GammaOKVIModel
33//
34// Author: Vladimir Ivanchenko and Omrame Kadri
35//
36// Creation date: 29.03.2018
37//
38// -------------------------------------------------------------------
39//
40//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
41//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
42
43
47#include "G4SystemOfUnits.hh"
48#include "G4EmParameters.hh"
49#include "G4TrackStatus.hh"
50#include "G4Electron.hh"
51#include "G4Positron.hh"
52#include "G4Gamma.hh"
53#include "G4DataVector.hh"
54#include "G4PhysicsVector.hh"
55#include "G4PhysicsLogVector.hh"
56#include "Randomize.hh"
58#include "G4Log.hh"
59#include "G4Exp.hh"
60
61//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
62
63using namespace std;
64
65G4PhysicsVector* G4eplusTo2GammaOKVIModel::fCrossSection = nullptr;
66G4PhysicsVector* G4eplusTo2GammaOKVIModel::fCrossSection3G = nullptr;
67G4PhysicsVector* G4eplusTo2GammaOKVIModel::f3GProbability = nullptr;
68
70 const G4String& nam)
71 : G4VEmModel(nam),
72 fDelta(0.001),
73 fGammaTh(MeV)
74{
75 theGamma = G4Gamma::Gamma();
76 fParticleChange = nullptr;
77 fCuts = nullptr;
78 f3GModel = new G4eplusTo3GammaOKVIModel();
79 SetTripletModel(f3GModel);
80}
81
82//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
83
85
86//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
87
89 const G4DataVector& cuts)
90{
91 f3GModel->Initialise(p, cuts);
92 fCuts = &cuts;
94 f3GModel->SetDelta(fDelta);
95
96 if(IsMaster()) {
97 if(!fCrossSection) {
98 G4double emin = 10*eV;
99 G4double emax = 100*TeV;
100 G4int nbins = 20*G4lrint(std::log10(emax/emin));
101 fCrossSection = new G4PhysicsLogVector(emin, emax, nbins, true);
102 fCrossSection3G = new G4PhysicsLogVector(emin, emax, nbins, true);
103 f3GProbability = new G4PhysicsLogVector(emin, emax, nbins, true);
104 for(G4int i=0; i<= nbins; ++i) {
105 G4double e = fCrossSection->Energy(i);
107 G4double cs3 = f3GModel->ComputeCrossSectionPerElectron(e);
108 cs2 += cs3;
109 fCrossSection->PutValue(i, cs2);
110 fCrossSection3G->PutValue(i, cs3);
111 f3GProbability->PutValue(i, cs3/cs2);
112 }
113 fCrossSection->FillSecondDerivatives();
114 fCrossSection3G->FillSecondDerivatives();
115 f3GProbability->FillSecondDerivatives();
116 }
117 }
118 // here particle change is set for the triplet model
119 if(fParticleChange) { return; }
120 fParticleChange = GetParticleChangeForGamma();
121}
122
123//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
124
127{
128 // Calculates the cross section per electron of annihilation into two
129 // photons from the Heilter formula with the radiation correction to 3 gamma
130 // annihilation channel. (A.A.) rho is changed
131
132 G4double ekin = std::max(eV,kinEnergy);
133 G4double tau = ekin/electron_mass_c2;
134 G4double gam = tau + 1.0;
135 G4double gamma2 = gam*gam;
136 G4double bg2 = tau * (tau+2.0);
137 G4double bg = sqrt(bg2);
138 G4double rho = (gamma2+4.*gam+1.)*G4Log(gam+bg)/(gamma2-1.)
139 - (gam+3.)/(sqrt(gam*gam - 1.));
140
141 static const G4double pir2 = pi*classic_electr_radius*classic_electr_radius;
142 G4double cross = (pir2*rho + alpha_rcl2*2.*G4Log(fDelta)*rho*rho)/(gam+1.);
143
144 return cross;
145}
146
147//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
148
151 G4double kineticEnergy, G4double Z,
153{
154 // Calculates the cross section per atom of annihilation into two photons
155 G4double cross = Z*fCrossSection->Value(kineticEnergy);
156 return cross;
157}
158
159//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
160
162 const G4Material* material,
164 G4double kineticEnergy,
166{
167 // Calculates the cross section per volume of annihilation into two photons
168 G4double eDensity = material->GetElectronDensity();
169 G4double cross = eDensity*fCrossSection->Value(kineticEnergy);
170 return cross;
171}
172
173//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
174
175// Polarisation of gamma according to M.H.L.Pryce and J.C.Ward,
176// Nature 4065 (1947) 435.
177
178void
179G4eplusTo2GammaOKVIModel::SampleSecondaries(vector<G4DynamicParticle*>* vdp,
180 const G4MaterialCutsCouple* mcc,
181 const G4DynamicParticle* dp,
183{
184 G4double posiKinEnergy = dp->GetKineticEnergy();
185 CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
186
187 if(rndmEngine->flat() < f3GProbability->Value(posiKinEnergy)) {
188 G4double cutd = std::max(fGammaTh,(*fCuts)[mcc->GetIndex()])
189 /(posiKinEnergy + electron_mass_c2);
190 // check cut to avoid production of 3d gamma below
191 if(cutd > fDelta) {
192 G4double cs30 = fCrossSection3G->Value(posiKinEnergy);
193 f3GModel->SetDelta(cutd);
194 G4double cs3 = f3GModel->ComputeCrossSectionPerElectron(posiKinEnergy);
195 if(rndmEngine->flat()*cs30 < cs3) {
196 f3GModel->SampleSecondaries(vdp, mcc, dp);
197 return;
198 }
199 } else {
200 f3GModel->SampleSecondaries(vdp, mcc, dp);
201 return;
202 }
203 }
204
205 G4DynamicParticle *aGamma1, *aGamma2;
206
207 // Case at rest
208 if(posiKinEnergy == 0.0) {
209 G4double cost = 2.*rndmEngine->flat()-1.;
210 G4double sint = sqrt((1. - cost)*(1. + cost));
211 G4double phi = twopi * rndmEngine->flat();
212 G4ThreeVector dir(sint*cos(phi), sint*sin(phi), cost);
213 phi = twopi * rndmEngine->flat();
214 G4double cosphi = cos(phi);
215 G4double sinphi = sin(phi);
216 G4ThreeVector pol(cosphi, sinphi, 0.0);
217 pol.rotateUz(dir);
218 aGamma1 = new G4DynamicParticle(theGamma, dir, electron_mass_c2);
219 aGamma1->SetPolarization(pol.x(),pol.y(),pol.z());
220 aGamma2 = new G4DynamicParticle(theGamma,-dir, electron_mass_c2);
221 pol.set(-sinphi, cosphi, 0.0);
222 pol.rotateUz(dir);
223 aGamma2->SetPolarization(pol.x(),pol.y(),pol.z());
224
225 } else {
226
227 G4ThreeVector posiDirection = dp->GetMomentumDirection();
228
229 G4double tau = posiKinEnergy/electron_mass_c2;
230 G4double gam = tau + 1.0;
231 G4double tau2 = tau + 2.0;
232 G4double sqgrate = sqrt(tau/tau2)*0.5;
233 G4double sqg2m1 = sqrt(tau*tau2);
234
235 // limits of the energy sampling
236 G4double epsilmin = 0.5 - sqgrate;
237 G4double epsilmax = 0.5 + sqgrate;
238 G4double epsilqot = epsilmax/epsilmin;
239
240 //
241 // sample the energy rate of the created gammas
242 //
243 G4double epsil, greject;
244
245 do {
246 epsil = epsilmin*G4Exp(G4Log(epsilqot)*rndmEngine->flat());
247 greject = 1. - epsil + (2.*gam*epsil-1.)/(epsil*tau2*tau2);
248 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
249 } while( greject < rndmEngine->flat());
250
251 //
252 // scattered Gamma angles. ( Z - axis along the parent positron)
253 //
254
255 G4double cost = (epsil*tau2-1.)/(epsil*sqg2m1);
256 if(std::abs(cost) > 1.0) {
257 G4cout << "### G4eplusTo2GammaOKVIModel WARNING cost= " << cost
258 << " positron Ekin(MeV)= " << posiKinEnergy
259 << " gamma epsil= " << epsil
260 << G4endl;
261 if(cost > 1.0) cost = 1.0;
262 else cost = -1.0;
263 }
264 G4double sint = sqrt((1.+cost)*(1.-cost));
265 G4double phi = twopi * rndmEngine->flat();
266
267 //
268 // kinematic of the created pair
269 //
270
271 G4double TotalAvailableEnergy = posiKinEnergy + 2.0*electron_mass_c2;
272 G4double phot1Energy = epsil*TotalAvailableEnergy;
273
274 G4ThreeVector phot1Direction(sint*cos(phi), sint*sin(phi), cost);
275 phot1Direction.rotateUz(posiDirection);
276 aGamma1 = new G4DynamicParticle (theGamma,phot1Direction, phot1Energy);
277 phi = twopi * rndmEngine->flat();
278 G4double cosphi = cos(phi);
279 G4double sinphi = sin(phi);
280 G4ThreeVector pol(cosphi, sinphi, 0.0);
281 pol.rotateUz(phot1Direction);
282 aGamma1->SetPolarization(pol.x(),pol.y(),pol.z());
283
284 G4double phot2Energy =(1.-epsil)*TotalAvailableEnergy;
285 G4double posiP= sqrt(posiKinEnergy*(posiKinEnergy+2.*electron_mass_c2));
286 G4ThreeVector dir = posiDirection*posiP - phot1Direction*phot1Energy;
287 G4ThreeVector phot2Direction = dir.unit();
288
289 // create G4DynamicParticle object for the particle2
290 aGamma2 = new G4DynamicParticle (theGamma,phot2Direction, phot2Energy);
291
292 //!!! likely problematic direction to be checked
293 pol.set(-sinphi, cosphi, 0.0);
294 pol.rotateUz(phot1Direction);
295 cost = pol*phot2Direction;
296 pol -= cost*phot2Direction;
297 pol = pol.unit();
298 aGamma2->SetPolarization(pol.x(),pol.y(),pol.z());
299 }
300 /*
301 G4cout << "Annihilation in fly: e0= " << posiKinEnergy
302 << " m= " << electron_mass_c2
303 << " e1= " << phot1Energy
304 << " e2= " << phot2Energy << " dir= " << dir
305 << " -> " << phot1Direction << " "
306 << phot2Direction << G4endl;
307 */
308
309 vdp->push_back(aGamma1);
310 vdp->push_back(aGamma2);
311
312 // kill primary positron
313 fParticleChange->SetProposedKineticEnergy(0.0);
314 fParticleChange->ProposeTrackStatus(fStopAndKill);
315}
316
317//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
@ fStopAndKill
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
double y() const
void set(double x, double y, double z)
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
virtual double flat()=0
void SetPolarization(const G4ThreeVector &)
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
static G4EmParameters * Instance()
G4double LowestTripletEnergy() const
static G4Gamma * Gamma()
Definition: G4Gamma.cc:85
G4double GetElectronDensity() const
Definition: G4Material.hh:212
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void PutValue(const std::size_t index, const G4double value)
G4double Energy(const std::size_t index) const
G4double Value(const G4double energy, std::size_t &lastidx) const
void FillSecondDerivatives(const G4SplineType=G4SplineType::Base, const G4double dir1=0.0, const G4double dir2=0.0)
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:124
G4bool IsMaster() const
Definition: G4VEmModel.hh:725
void SetTripletModel(G4VEmModel *)
Definition: G4VEmModel.hh:624
void ProposeTrackStatus(G4TrackStatus status)
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4double ComputeCrossSectionPerElectron(G4double kinEnergy)
G4eplusTo2GammaOKVIModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="eplus2ggOKVI")
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double maxEnergy=DBL_MAX) final
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cutEnergy=0., G4double maxEnergy=DBL_MAX) final
~G4eplusTo2GammaOKVIModel() override
G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX) final
G4double ComputeCrossSectionPerElectron(G4double kinEnergy)
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double maxEnergy=DBL_MAX) final
void Initialise(const G4ParticleDefinition *, const G4DataVector &) final
int G4lrint(double ad)
Definition: templates.hh:134