Geant4-11
G4AdjointPhotoElectricModel.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
28
29#include "G4AdjointCSManager.hh"
30#include "G4AdjointElectron.hh"
31#include "G4AdjointGamma.hh"
32#include "G4Gamma.hh"
33#include "G4ParticleChange.hh"
36#include "G4TrackStatus.hh"
37
40 : G4VEmAdjointModel("AdjointPEEffect")
41
42{
43 SetUseMatrix(false);
44 SetApplyCutInRange(false);
45
49 fSecondPartSameType = false;
51}
52
55
58 const G4Track& aTrack, G4bool isScatProjToProj,
59 G4ParticleChange* fParticleChange)
60{
61 if(isScatProjToProj)
62 return;
63
64 // Compute the fTotAdjointCS vectors if not already done for the current
65 // couple and electron energy
66 const G4DynamicParticle* aDynPart = aTrack.GetDynamicParticle();
67 G4double electronEnergy = aDynPart->GetKineticEnergy();
68 G4ThreeVector electronDirection = aDynPart->GetMomentumDirection();
70 fTotAdjointCS; // The last computed CS was at pre step point
71 AdjointCrossSection(aTrack.GetMaterialCutsCouple(), electronEnergy,
72 isScatProjToProj);
74
75 // Sample element
76 const G4ElementVector* theElementVector =
79 G4double rand_CS = G4UniformRand() * fXsec[nelm - 1];
80 for(fIndexElement = 0; fIndexElement < nelm - 1; ++fIndexElement)
81 {
82 if(rand_CS < fXsec[fIndexElement])
83 break;
84 }
85
86 // Sample shell and binding energy
87 G4int nShells = (*theElementVector)[fIndexElement]->GetNbOfAtomicShells();
88 rand_CS = fShellProb[fIndexElement][nShells - 1] * G4UniformRand();
89 G4int i;
90 for(i = 0; i < nShells - 1; ++i)
91 {
92 if(rand_CS < fShellProb[fIndexElement][i])
93 break;
94 }
95 G4double gammaEnergy =
96 electronEnergy + (*theElementVector)[fIndexElement]->GetAtomicShell(i);
97
98 // Sample cos theta
99 // Copy of the G4PEEfectFluoModel cos theta sampling method
100 // ElecCosThetaDistribution. This method cannot be used directly from
101 // G4PEEffectFluoModel because it is a friend method.
102 G4double cos_theta = 1.;
103 G4double gamma = 1. + electronEnergy / electron_mass_c2;
104 if(gamma <= 5.)
105 {
106 G4double beta = std::sqrt(gamma * gamma - 1.) / gamma;
107 G4double b = 0.5 * gamma * (gamma - 1.) * (gamma - 2.);
108
109 G4double rndm, term, greject, grejsup;
110 if(gamma < 2.)
111 grejsup = gamma * gamma * (1. + b - beta * b);
112 else
113 grejsup = gamma * gamma * (1. + b + beta * b);
114
115 do
116 {
117 rndm = 1. - 2. * G4UniformRand();
118 cos_theta = (rndm + beta) / (rndm * beta + 1.);
119 term = 1. - beta * cos_theta;
120 greject = (1. - cos_theta * cos_theta) * (1. + b * term) / (term * term);
121 // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
122 } while(greject < G4UniformRand() * grejsup);
123 }
124
125 // direction of the adjoint gamma electron
126 G4double sin_theta = std::sqrt(1. - cos_theta * cos_theta);
127 G4double phi = twopi * G4UniformRand();
128 G4double dirx = sin_theta * std::cos(phi);
129 G4double diry = sin_theta * std::sin(phi);
130 G4double dirz = cos_theta;
131 G4ThreeVector adjoint_gammaDirection(dirx, diry, dirz);
132 adjoint_gammaDirection.rotateUz(electronDirection);
133
134 // Weight correction
135 CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(), electronEnergy,
136 gammaEnergy, isScatProjToProj);
137
138 // Create secondary and modify fParticleChange
139 G4DynamicParticle* anAdjointGamma = new G4DynamicParticle(
140 G4AdjointGamma::AdjointGamma(), adjoint_gammaDirection, gammaEnergy);
141
142 fParticleChange->ProposeTrackStatus(fStopAndKill);
143 fParticleChange->AddSecondary(anAdjointGamma);
144}
145
148 G4ParticleChange* fParticleChange, G4double old_weight,
149 G4double adjointPrimKinEnergy, G4double projectileKinEnergy, G4bool)
150{
151 G4double new_weight = old_weight;
152
153 G4double w_corr =
157
158 new_weight *= w_corr * projectileKinEnergy / adjointPrimKinEnergy;
159 fParticleChange->SetParentWeightByProcess(false);
160 fParticleChange->SetSecondaryWeightByProcess(false);
161 fParticleChange->ProposeParentWeight(new_weight);
162}
163
166 const G4MaterialCutsCouple* aCouple, G4double electronEnergy,
167 G4bool isScatProjToProj)
168{
169 if(isScatProjToProj)
170 return 0.;
171
172 G4double totBiasedAdjointCS = 0.;
173 if(aCouple != fCurrentCouple || fCurrenteEnergy != electronEnergy)
174 {
175 fTotAdjointCS = 0.;
176 DefineCurrentMaterialAndElectronEnergy(aCouple, electronEnergy);
177 const G4ElementVector* theElementVector =
179 const G4double* theAtomNumDensityVector =
181 size_t nelm = fCurrentMaterial->GetNumberOfElements();
182 for(fIndexElement = 0; fIndexElement < nelm; ++fIndexElement)
183 {
185 (*theElementVector)[fIndexElement], electronEnergy) *
186 theAtomNumDensityVector[fIndexElement];
188 }
189
190 totBiasedAdjointCS = std::min(fTotAdjointCS, 0.01);
191 fFactorCSBiasing = totBiasedAdjointCS / fTotAdjointCS;
192 }
193 return totBiasedAdjointCS;
194}
195
198 const G4Element* anElement, G4double electronEnergy)
199{
200 G4int nShells = anElement->GetNbOfAtomicShells();
201 G4double Z = anElement->GetZ();
202 G4double gammaEnergy = electronEnergy + anElement->GetAtomicShell(0);
204 G4Gamma::Gamma(), gammaEnergy, Z, 0., 0., 0.);
205 G4double adjointCS = 0.;
206 if(CS > 0.)
207 adjointCS += CS / gammaEnergy;
208 fShellProb[fIndexElement][0] = adjointCS;
209 for(G4int i = 1; i < nShells; ++i)
210 {
211 G4double Bi1 = anElement->GetAtomicShell(i - 1);
212 G4double Bi = anElement->GetAtomicShell(i);
213 if(electronEnergy < Bi1 - Bi)
214 {
215 gammaEnergy = electronEnergy + Bi;
217 gammaEnergy, Z, 0., 0., 0.);
218 if(CS > 0.)
219 adjointCS += CS / gammaEnergy;
220 }
221 fShellProb[fIndexElement][i] = adjointCS;
222 }
223 adjointCS *= electronEnergy;
224 return adjointCS;
225}
226
229 const G4MaterialCutsCouple* couple, G4double anEnergy)
230{
231 fCurrentCouple = const_cast<G4MaterialCutsCouple*>(couple);
232 fCurrentMaterial = const_cast<G4Material*>(couple->GetMaterial());
233 fCurrenteEnergy = anEnergy;
235}
std::vector< const G4Element * > G4ElementVector
static constexpr double twopi
Definition: G4SIunits.hh:56
@ fStopAndKill
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
G4double GetPostStepWeightCorrection()
static G4AdjointCSManager * GetAdjointCSManager()
static G4AdjointElectron * AdjointElectron()
static G4AdjointGamma * AdjointGamma()
void CorrectPostStepWeight(G4ParticleChange *fParticleChange, G4double old_weight, G4double adjointPrimKinEnergy, G4double projectileKinEnergy, G4bool isScatProjToProj) override
void DefineCurrentMaterialAndElectronEnergy(const G4MaterialCutsCouple *aCouple, G4double eEnergy)
G4double AdjointCrossSection(const G4MaterialCutsCouple *aCouple, G4double primEnergy, G4bool isScatProjToProj) override
void SampleSecondaries(const G4Track &aTrack, G4bool isScatProjToProj, G4ParticleChange *fParticleChange) override
G4double AdjointCrossSectionPerAtom(const G4Element *anElement, G4double electronEnergy)
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
G4double GetZ() const
Definition: G4Element.hh:131
G4int GetNbOfAtomicShells() const
Definition: G4Element.hh:147
G4double GetAtomicShell(G4int index) const
Definition: G4Element.cc:366
static G4Gamma * Gamma()
Definition: G4Gamma.cc:85
const G4Material * GetMaterial() const
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:186
size_t GetNumberOfElements() const
Definition: G4Material.hh:182
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:202
void AddSecondary(G4Track *aSecondary)
G4double GetWeight() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
G4ParticleDefinition * fAdjEquivDirectSecondPart
void SetUseMatrix(G4bool aBool)
G4ParticleDefinition * fAdjEquivDirectPrimPart
G4MaterialCutsCouple * fCurrentCouple
G4Material * fCurrentMaterial
G4VEmModel * fDirectModel
G4ParticleDefinition * fDirectPrimaryPart
void SetApplyCutInRange(G4bool aBool)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.cc:341
void SetCurrentCouple(const G4MaterialCutsCouple *)
Definition: G4VEmModel.hh:472
void ProposeTrackStatus(G4TrackStatus status)
void SetSecondaryWeightByProcess(G4bool)
void SetParentWeightByProcess(G4bool)
void ProposeParentWeight(G4double finalWeight)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
float electron_mass_c2
Definition: hepunit.py:273