Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // >> 26 // $Id: G4PenelopeAnnihilationModel.cc,v 1.2 2008/12/04 14:09:36 pandola Exp $ >> 27 // GEANT4 tag $Name: geant4-09-02-patch-03 $ 26 // 28 // 27 // Author: Luciano Pandola 29 // Author: Luciano Pandola 28 // 30 // 29 // History: 31 // History: 30 // -------- 32 // -------- 31 // 29 Oct 2008 L Pandola Migration from p 33 // 29 Oct 2008 L Pandola Migration from process to model 32 // 15 Apr 2009 V Ivanchenko Cleanup initiali << 34 // 33 // secondaries: << 34 // - apply internal high-ener << 35 // - do not apply low-energy << 36 // - do not use G4ElementSele << 37 // 02 Oct 2013 L.Pandola Migration to MT << 38 35 39 #include "G4PenelopeAnnihilationModel.hh" 36 #include "G4PenelopeAnnihilationModel.hh" 40 #include "G4PhysicalConstants.hh" << 41 #include "G4SystemOfUnits.hh" << 42 #include "G4ParticleDefinition.hh" 37 #include "G4ParticleDefinition.hh" 43 #include "G4MaterialCutsCouple.hh" 38 #include "G4MaterialCutsCouple.hh" 44 #include "G4ProductionCutsTable.hh" 39 #include "G4ProductionCutsTable.hh" 45 #include "G4DynamicParticle.hh" 40 #include "G4DynamicParticle.hh" 46 #include "G4Gamma.hh" 41 #include "G4Gamma.hh" 47 42 48 //....oooOO0OOooo........oooOO0OOooo........oo 43 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 49 44 50 G4double G4PenelopeAnnihilationModel::fPielr2 << 51 45 52 G4PenelopeAnnihilationModel::G4PenelopeAnnihil << 46 G4PenelopeAnnihilationModel::G4PenelopeAnnihilationModel(const G4ParticleDefinition*, 53 c 47 const G4String& nam) 54 :G4VEmModel(nam),fParticleChange(nullptr),fP << 48 :G4VEmModel(nam),isInitialised(false) 55 { 49 { 56 fIntrinsicLowEnergyLimit = 0.0; << 50 fIntrinsicLowEnergyLimit = 0.0*eV; 57 fIntrinsicHighEnergyLimit = 100.0*GeV; 51 fIntrinsicHighEnergyLimit = 100.0*GeV; >> 52 SetLowEnergyLimit(fIntrinsicLowEnergyLimit); 58 SetHighEnergyLimit(fIntrinsicHighEnergyLimit 53 SetHighEnergyLimit(fIntrinsicHighEnergyLimit); 59 << 54 60 if (part) << 61 SetParticle(part); << 62 << 63 //Calculate variable that will be used later 55 //Calculate variable that will be used later on 64 fPielr2 = pi*classic_electr_radius*classic_e 56 fPielr2 = pi*classic_electr_radius*classic_electr_radius; 65 57 66 fVerboseLevel= 0; << 58 verboseLevel= 0; 67 // Verbosity scale: 59 // Verbosity scale: 68 // 0 = nothing 60 // 0 = nothing 69 // 1 = warning for energy non-conservation 61 // 1 = warning for energy non-conservation 70 // 2 = details of energy budget 62 // 2 = details of energy budget 71 // 3 = calculation of cross sections, file o 63 // 3 = calculation of cross sections, file openings, sampling of atoms 72 // 4 = entering in methods 64 // 4 = entering in methods >> 65 73 } 66 } 74 67 75 //....oooOO0OOooo........oooOO0OOooo........oo 68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 76 69 77 G4PenelopeAnnihilationModel::~G4PenelopeAnnihi 70 G4PenelopeAnnihilationModel::~G4PenelopeAnnihilationModel() 78 {;} 71 {;} 79 72 80 //....oooOO0OOooo........oooOO0OOooo........oo 73 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 81 74 82 void G4PenelopeAnnihilationModel::Initialise(c << 75 void G4PenelopeAnnihilationModel::Initialise(const G4ParticleDefinition* particle, 83 const G4DataVector&) << 76 const G4DataVector& cuts) 84 { 77 { 85 if (fVerboseLevel > 3) << 78 if (verboseLevel > 3) 86 G4cout << "Calling G4PenelopeAnnihilationM 79 G4cout << "Calling G4PenelopeAnnihilationModel::Initialise()" << G4endl; 87 SetParticle(part); << 88 80 89 if (IsMaster() && part == fParticle) << 81 InitialiseElementSelectors(particle,cuts); >> 82 if (LowEnergyLimit() < fIntrinsicLowEnergyLimit) 90 { 83 { 91 << 84 G4cout << "G4PenelopeAnnihilationModel: low energy limit increased from " << 92 if(fVerboseLevel > 0) { << 85 LowEnergyLimit()/eV << " eV to " << fIntrinsicLowEnergyLimit/eV << " eV" << G4endl; 93 G4cout << "Penelope Annihilation model is in << 86 SetLowEnergyLimit(fIntrinsicLowEnergyLimit); 94 << "Energy range: " << 95 << LowEnergyLimit() / keV << " keV - << 96 << HighEnergyLimit() / GeV << " GeV" << 97 << G4endl; << 98 } << 99 } 87 } 100 << 88 if (HighEnergyLimit() > fIntrinsicHighEnergyLimit) 101 if(fIsInitialised) return; << 102 fParticleChange = GetParticleChangeForGamma( << 103 fIsInitialised = true; << 104 } << 105 << 106 //....oooOO0OOooo........oooOO0OOooo........oo << 107 void G4PenelopeAnnihilationModel::InitialiseLo << 108 G4VEmModel* masterModel) << 109 { << 110 if (fVerboseLevel > 3) << 111 G4cout << "Calling G4PenelopeAnnihilationM << 112 << 113 // << 114 //Check that particle matches: one might hav << 115 //for e+ and e-). << 116 // << 117 if (part == fParticle) << 118 { 89 { 119 //Get the const table pointers from the << 90 G4cout << "G4PenelopeAnnihilationModel: high energy limit decreased from " << 120 const G4PenelopeAnnihilationModel* theMo << 91 HighEnergyLimit()/GeV << " GeV to " << fIntrinsicHighEnergyLimit/GeV << " GeV" << G4endl; 121 static_cast<G4PenelopeAnnihilationMode << 92 SetHighEnergyLimit(fIntrinsicHighEnergyLimit); 122 << 123 //Same verbosity for all workers, as the << 124 fVerboseLevel = theModel->fVerboseLevel; << 125 } 93 } >> 94 >> 95 G4cout << "Penelope Annihilation model is initialized " << G4endl >> 96 << "Energy range: " >> 97 << LowEnergyLimit() / keV << " keV - " >> 98 << HighEnergyLimit() / GeV << " GeV" >> 99 << G4endl; >> 100 >> 101 if(isInitialised) return; >> 102 >> 103 if(pParticleChange) >> 104 fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange); >> 105 else >> 106 fParticleChange = new G4ParticleChangeForGamma(); >> 107 isInitialised = true; 126 } 108 } 127 109 128 //....oooOO0OOooo........oooOO0OOooo........oo 110 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 129 111 130 G4double G4PenelopeAnnihilationModel::ComputeC 112 G4double G4PenelopeAnnihilationModel::ComputeCrossSectionPerAtom( 131 const G 113 const G4ParticleDefinition*, 132 G 114 G4double energy, 133 G 115 G4double Z, G4double, 134 G 116 G4double, G4double) 135 { 117 { 136 if (fVerboseLevel > 3) << 118 if (verboseLevel > 3) 137 G4cout << "Calling ComputeCrossSectionPerA 119 G4cout << "Calling ComputeCrossSectionPerAtom() of G4PenelopeAnnihilationModel" << 138 G4endl; 120 G4endl; 139 121 140 G4double cs = Z*ComputeCrossSectionPerElectr 122 G4double cs = Z*ComputeCrossSectionPerElectron(energy); 141 123 142 if (fVerboseLevel > 2) << 124 if (verboseLevel > 2) 143 G4cout << "Annihilation cross Section at " 125 G4cout << "Annihilation cross Section at " << energy/keV << " keV for Z=" << Z << 144 " = " << cs/barn << " barn" << G4endl; 126 " = " << cs/barn << " barn" << G4endl; 145 return cs; 127 return cs; 146 } 128 } 147 129 148 //....oooOO0OOooo........oooOO0OOooo........oo 130 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 149 131 150 void G4PenelopeAnnihilationModel::SampleSecond 132 void G4PenelopeAnnihilationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect, 151 const G4MaterialCutsCouple*, 133 const G4MaterialCutsCouple*, 152 const G4DynamicParticle* aDyna 134 const G4DynamicParticle* aDynamicPositron, 153 G4double, 135 G4double, 154 G4double) 136 G4double) 155 { 137 { 156 // 138 // 157 // Penelope model to sample final state for 139 // Penelope model to sample final state for positron annihilation. 158 // Target eletrons are assumed to be free an 140 // Target eletrons are assumed to be free and at rest. Binding effects enabling 159 // one-photon annihilation are neglected. 141 // one-photon annihilation are neglected. 160 // For annihilation at rest, two back-to-bac 142 // For annihilation at rest, two back-to-back photons are emitted, having energy of 511 keV 161 // and isotropic angular distribution. 143 // and isotropic angular distribution. 162 // For annihilation in flight, it is used th 144 // For annihilation in flight, it is used the theory from 163 // W. Heitler, The quantum theory of radiat 145 // W. Heitler, The quantum theory of radiation, Oxford University Press (1954) 164 // The two photons can have different energy 146 // The two photons can have different energy. The efficiency of the sampling algorithm 165 // of the photon energy from the dSigma/dE d 147 // of the photon energy from the dSigma/dE distribution is practically 100% for 166 // positrons of kinetic energy < 10 keV. It 148 // positrons of kinetic energy < 10 keV. It reaches a minimum (about 80%) at energy 167 // of about 10 MeV. 149 // of about 10 MeV. 168 // The angle theta is kinematically linked t 150 // The angle theta is kinematically linked to the photon energy, to ensure momentum 169 // conservation. The angle phi is sampled is 151 // conservation. The angle phi is sampled isotropically for the first gamma. 170 // 152 // 171 if (fVerboseLevel > 3) << 153 if (verboseLevel > 3) 172 G4cout << "Calling SamplingSecondaries() o 154 G4cout << "Calling SamplingSecondaries() of G4PenelopeAnnihilationModel" << G4endl; 173 155 174 G4double kineticEnergy = aDynamicPositron->G 156 G4double kineticEnergy = aDynamicPositron->GetKineticEnergy(); 175 << 176 // kill primary << 177 fParticleChange->SetProposedKineticEnergy(0. << 178 fParticleChange->ProposeTrackStatus(fStopAnd << 179 157 180 if (kineticEnergy == 0.0) << 158 if (kineticEnergy == 0) 181 { 159 { 182 //Old AtRestDoIt 160 //Old AtRestDoIt 183 G4double cosTheta = -1.0+2.0*G4UniformRa 161 G4double cosTheta = -1.0+2.0*G4UniformRand(); 184 G4double sinTheta = std::sqrt(1.0-cosThe 162 G4double sinTheta = std::sqrt(1.0-cosTheta*cosTheta); 185 G4double phi = twopi*G4UniformRand(); 163 G4double phi = twopi*G4UniformRand(); 186 G4ThreeVector direction (sinTheta*std::c 164 G4ThreeVector direction (sinTheta*std::cos(phi),sinTheta*std::sin(phi),cosTheta); 187 G4DynamicParticle* firstGamma = new G4Dy 165 G4DynamicParticle* firstGamma = new G4DynamicParticle (G4Gamma::Gamma(), 188 direction, electron_mass_c2 166 direction, electron_mass_c2); 189 G4DynamicParticle* secondGamma = new G4D 167 G4DynamicParticle* secondGamma = new G4DynamicParticle (G4Gamma::Gamma(), 190 -direction, electron_mass_ 168 -direction, electron_mass_c2); 191 169 192 fvect->push_back(firstGamma); 170 fvect->push_back(firstGamma); 193 fvect->push_back(secondGamma); 171 fvect->push_back(secondGamma); >> 172 fParticleChange->SetProposedKineticEnergy(0.); >> 173 fParticleChange->ProposeTrackStatus(fStopAndKill); 194 return; 174 return; 195 } 175 } 196 176 197 //This is the "PostStep" case (annihilation 177 //This is the "PostStep" case (annihilation in flight) 198 G4ParticleMomentum positronDirection = 178 G4ParticleMomentum positronDirection = 199 aDynamicPositron->GetMomentumDirection(); 179 aDynamicPositron->GetMomentumDirection(); 200 G4double gamma = 1.0 + std::max(kineticEnerg 180 G4double gamma = 1.0 + std::max(kineticEnergy,1.0*eV)/electron_mass_c2; 201 G4double gamma21 = std::sqrt(gamma*gamma-1); 181 G4double gamma21 = std::sqrt(gamma*gamma-1); 202 G4double ani = 1.0+gamma; 182 G4double ani = 1.0+gamma; 203 G4double chimin = 1.0/(ani+gamma21); 183 G4double chimin = 1.0/(ani+gamma21); 204 G4double rchi = (1.0-chimin)/chimin; 184 G4double rchi = (1.0-chimin)/chimin; 205 G4double gt0 = ani*ani-2.0; 185 G4double gt0 = ani*ani-2.0; 206 G4double test=0.0; 186 G4double test=0.0; 207 G4double epsilon = 0; 187 G4double epsilon = 0; 208 do{ 188 do{ 209 epsilon = chimin*std::pow(rchi,G4UniformRa 189 epsilon = chimin*std::pow(rchi,G4UniformRand()); 210 G4double reject = ani*ani*(1.0-epsilon)+2. 190 G4double reject = ani*ani*(1.0-epsilon)+2.0*gamma-(1.0/epsilon); 211 test = G4UniformRand()*gt0-reject; 191 test = G4UniformRand()*gt0-reject; 212 }while(test>0); 192 }while(test>0); 213 193 214 G4double totalAvailableEnergy = kineticEnerg 194 G4double totalAvailableEnergy = kineticEnergy + 2.0*electron_mass_c2; 215 G4double photon1Energy = epsilon*totalAvaila 195 G4double photon1Energy = epsilon*totalAvailableEnergy; 216 G4double photon2Energy = (1.0-epsilon)*total 196 G4double photon2Energy = (1.0-epsilon)*totalAvailableEnergy; 217 G4double cosTheta1 = (ani-1.0/epsilon)/gamma 197 G4double cosTheta1 = (ani-1.0/epsilon)/gamma21; 218 G4double cosTheta2 = (ani-1.0/(1.0-epsilon)) 198 G4double cosTheta2 = (ani-1.0/(1.0-epsilon))/gamma21; 219 199 >> 200 //G4double localEnergyDeposit = 0.; >> 201 220 G4double sinTheta1 = std::sqrt(1.-cosTheta1* 202 G4double sinTheta1 = std::sqrt(1.-cosTheta1*cosTheta1); 221 G4double phi1 = twopi * G4UniformRand(); 203 G4double phi1 = twopi * G4UniformRand(); 222 G4double dirx1 = sinTheta1 * std::cos(phi1); 204 G4double dirx1 = sinTheta1 * std::cos(phi1); 223 G4double diry1 = sinTheta1 * std::sin(phi1); 205 G4double diry1 = sinTheta1 * std::sin(phi1); 224 G4double dirz1 = cosTheta1; 206 G4double dirz1 = cosTheta1; 225 207 226 G4double sinTheta2 = std::sqrt(1.-cosTheta2* 208 G4double sinTheta2 = std::sqrt(1.-cosTheta2*cosTheta2); 227 G4double phi2 = phi1+pi; 209 G4double phi2 = phi1+pi; 228 G4double dirx2 = sinTheta2 * std::cos(phi2); 210 G4double dirx2 = sinTheta2 * std::cos(phi2); 229 G4double diry2 = sinTheta2 * std::sin(phi2); 211 G4double diry2 = sinTheta2 * std::sin(phi2); 230 G4double dirz2 = cosTheta2; 212 G4double dirz2 = cosTheta2; 231 213 232 G4ThreeVector photon1Direction (dirx1,diry1, 214 G4ThreeVector photon1Direction (dirx1,diry1,dirz1); 233 photon1Direction.rotateUz(positronDirection) 215 photon1Direction.rotateUz(positronDirection); 234 // create G4DynamicParticle object for the p 216 // create G4DynamicParticle object for the particle1 235 G4DynamicParticle* aParticle1= new G4Dynamic 217 G4DynamicParticle* aParticle1= new G4DynamicParticle (G4Gamma::Gamma(), 236 photon1Direction, 218 photon1Direction, 237 photon1Energy); 219 photon1Energy); 238 fvect->push_back(aParticle1); 220 fvect->push_back(aParticle1); 239 221 240 G4ThreeVector photon2Direction(dirx2,diry2,d 222 G4ThreeVector photon2Direction(dirx2,diry2,dirz2); 241 photon2Direction.rotateUz(positronDirection) 223 photon2Direction.rotateUz(positronDirection); 242 // create G4DynamicParticle object for the p << 224 // create G4DynamicParticle object for the particle2 243 G4DynamicParticle* aParticle2= new G4Dynamic 225 G4DynamicParticle* aParticle2= new G4DynamicParticle (G4Gamma::Gamma(), 244 photon2Direction, 226 photon2Direction, 245 photon2Energy); 227 photon2Energy); 246 fvect->push_back(aParticle2); 228 fvect->push_back(aParticle2); >> 229 fParticleChange->SetProposedKineticEnergy(0.); >> 230 fParticleChange->ProposeTrackStatus(fStopAndKill); 247 231 248 if (fVerboseLevel > 1) << 232 if (verboseLevel > 1) 249 { 233 { 250 G4cout << "----------------------------- 234 G4cout << "-----------------------------------------------------------" << G4endl; 251 G4cout << "Energy balance from G4Penelop 235 G4cout << "Energy balance from G4PenelopeAnnihilation" << G4endl; 252 G4cout << "Kinetic positron energy: " << 236 G4cout << "Kinetic positron energy: " << kineticEnergy/keV << " keV" << G4endl; 253 G4cout << "Total available energy: " << 237 G4cout << "Total available energy: " << totalAvailableEnergy/keV << " keV " << G4endl; 254 G4cout << "----------------------------- 238 G4cout << "-----------------------------------------------------------" << G4endl; 255 G4cout << "Photon energy 1: " << photon1 239 G4cout << "Photon energy 1: " << photon1Energy/keV << " keV" << G4endl; 256 G4cout << "Photon energy 2: " << photon2 240 G4cout << "Photon energy 2: " << photon2Energy/keV << " keV" << G4endl; 257 G4cout << "Total final state: " << (phot 241 G4cout << "Total final state: " << (photon1Energy+photon2Energy)/keV << 258 " keV" << G4endl; 242 " keV" << G4endl; 259 G4cout << "----------------------------- 243 G4cout << "-----------------------------------------------------------" << G4endl; 260 } 244 } 261 if (fVerboseLevel > 0) << 245 if (verboseLevel > 0) 262 { << 246 { >> 247 263 G4double energyDiff = std::fabs(totalAva 248 G4double energyDiff = std::fabs(totalAvailableEnergy-photon1Energy-photon2Energy); 264 if (energyDiff > 0.05*keV) 249 if (energyDiff > 0.05*keV) 265 G4cout << "Warning from G4PenelopeAnnihilati 250 G4cout << "Warning from G4PenelopeAnnihilation: problem with energy conservation: " << 266 (photon1Energy+photon2Energy)/keV << 251 (photon1Energy+photon2Energy)/keV << 267 " keV (final) vs. " << 252 " keV (final) vs. " << 268 totalAvailableEnergy/keV << " keV (initial 253 totalAvailableEnergy/keV << " keV (initial)" << G4endl; 269 } 254 } 270 return; 255 return; 271 } 256 } 272 257 273 //....oooOO0OOooo........oooOO0OOooo........oo 258 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 274 259 275 G4double G4PenelopeAnnihilationModel:: Compute 260 G4double G4PenelopeAnnihilationModel:: ComputeCrossSectionPerElectron(G4double energy) 276 { 261 { 277 // 262 // 278 // Penelope model to calculate cross section 263 // Penelope model to calculate cross section for positron annihilation. 279 // The annihilation cross section per electr 264 // The annihilation cross section per electron is calculated according 280 // to the Heitler formula 265 // to the Heitler formula 281 // W. Heitler, The quantum theory of radiat 266 // W. Heitler, The quantum theory of radiation, Oxford University Press (1954) 282 // in the assumptions of electrons free and 267 // in the assumptions of electrons free and at rest. 283 // 268 // 284 G4double gamma = 1.0+std::max(energy,1.0*eV) 269 G4double gamma = 1.0+std::max(energy,1.0*eV)/electron_mass_c2; 285 G4double gamma2 = gamma*gamma; 270 G4double gamma2 = gamma*gamma; 286 G4double f2 = gamma2-1.0; 271 G4double f2 = gamma2-1.0; 287 G4double f1 = std::sqrt(f2); 272 G4double f1 = std::sqrt(f2); 288 G4double crossSection = fPielr2*((gamma2+4.0 << 273 G4double crossSection = fPielr2*((gamma2+4.0*gamma+1.0)*std::log(gamma+f1)/f2 289 - (gamma+3.0)/f1)/(gamma+1.0); 274 - (gamma+3.0)/f1)/(gamma+1.0); 290 return crossSection; 275 return crossSection; 291 } << 292 << 293 //....oooOO0OOooo........oooOO0OOooo........oo << 294 << 295 void G4PenelopeAnnihilationModel::SetParticle( << 296 { << 297 if(!fParticle) { << 298 fParticle = p; << 299 } << 300 } 276 } 301 277