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 << 26 // 27 #include "G4AdjointPhotoElectricModel.hh" 27 #include "G4AdjointPhotoElectricModel.hh" 28 << 29 #include "G4AdjointCSManager.hh" 28 #include "G4AdjointCSManager.hh" 30 #include "G4AdjointElectron.hh" << 29 31 #include "G4AdjointGamma.hh" << 32 #include "G4Gamma.hh" << 33 #include "G4ParticleChange.hh" << 34 #include "G4PEEffectFluoModel.hh" << 35 #include "G4PhysicalConstants.hh" 30 #include "G4PhysicalConstants.hh" >> 31 #include "G4Integrator.hh" 36 #include "G4TrackStatus.hh" 32 #include "G4TrackStatus.hh" >> 33 #include "G4ParticleChange.hh" >> 34 #include "G4AdjointElectron.hh" >> 35 #include "G4Gamma.hh" >> 36 #include "G4AdjointGamma.hh" >> 37 37 38 38 ////////////////////////////////////////////// 39 //////////////////////////////////////////////////////////////////////////////// 39 G4AdjointPhotoElectricModel::G4AdjointPhotoEle << 40 // 40 : G4VEmAdjointModel("AdjointPEEffect") << 41 G4AdjointPhotoElectricModel::G4AdjointPhotoElectricModel(): >> 42 G4VEmAdjointModel("AdjointPEEffect") 41 43 42 { << 44 { SetUseMatrix(false); 43 SetUseMatrix(false); << 44 SetApplyCutInRange(false); 45 SetApplyCutInRange(false); 45 46 46 fAdjEquivDirectPrimPart = G4AdjointGamma:: << 47 //Initialization 47 fAdjEquivDirectSecondPart = G4AdjointElectro << 48 current_eEnergy =0.; 48 fDirectPrimaryPart = G4Gamma::Gamma() << 49 totAdjointCS=0.; 49 fSecondPartSameType = false; << 50 factorCSBiasing =1.; 50 fDirectModel = new G4PEEffectFl << 51 post_step_AdjointCS =0.; >> 52 pre_step_AdjointCS =0.; >> 53 totBiasedAdjointCS =0.; >> 54 >> 55 index_element=0; >> 56 >> 57 theAdjEquivOfDirectPrimPartDef =G4AdjointGamma::AdjointGamma(); >> 58 theAdjEquivOfDirectSecondPartDef=G4AdjointElectron::AdjointElectron(); >> 59 theDirectPrimaryPartDef=G4Gamma::Gamma(); >> 60 second_part_of_same_type=false; >> 61 theDirectPEEffectModel = new G4PEEffectFluoModel(); 51 } 62 } 52 << 53 ////////////////////////////////////////////// 63 //////////////////////////////////////////////////////////////////////////////// 54 G4AdjointPhotoElectricModel::~G4AdjointPhotoEl << 64 // 55 << 65 G4AdjointPhotoElectricModel::~G4AdjointPhotoElectricModel() 56 ////////////////////////////////////////////// << 66 {;} 57 void G4AdjointPhotoElectricModel::SampleSecond << 67 58 const G4Track& aTrack, G4bool isScatProjToPr << 68 //////////////////////////////////////////////////////////////////////////////// 59 G4ParticleChange* fParticleChange) << 69 // 60 { << 70 void G4AdjointPhotoElectricModel::SampleSecondaries(const G4Track& aTrack, 61 if(isScatProjToProj) << 71 G4bool IsScatProjToProjCase, 62 return; << 72 G4ParticleChange* fParticleChange) 63 << 73 { if (IsScatProjToProjCase) return ; 64 // Compute the fTotAdjointCS vectors if not << 74 65 // couple and electron energy << 75 //Compute the totAdjointCS vectors if not already done for the current couple and electron energy 66 const G4DynamicParticle* aDynPart = aTrack.G << 76 //----------------------------------------------------------------------------------------------- 67 G4double electronEnergy = aDynPart << 77 const G4MaterialCutsCouple* aCouple = aTrack.GetMaterialCutsCouple(); 68 G4ThreeVector electronDirection = aDynPart << 78 const G4DynamicParticle* aDynPart = aTrack.GetDynamicParticle() ; 69 fPreStepAdjointCS = << 79 G4double electronEnergy = aDynPart->GetKineticEnergy(); 70 fTotAdjointCS; // The last computed CS wa << 80 G4ThreeVector electronDirection= aDynPart->GetMomentumDirection() ; 71 AdjointCrossSection(aTrack.GetMaterialCutsCo << 81 pre_step_AdjointCS = totAdjointCS; //The last computed CS was at pre step point 72 isScatProjToProj); << 82 post_step_AdjointCS = AdjointCrossSection(aCouple, electronEnergy,IsScatProjToProjCase); 73 fPostStepAdjointCS = fTotAdjointCS; << 83 post_step_AdjointCS = totAdjointCS; 74 << 84 75 // Sample element << 85 76 const G4ElementVector* theElementVector = << 86 77 fCurrentMaterial->GetElementVector(); << 87 78 size_t nelm = fCurrentMaterial->GetNumb << 88 //Sample element 79 G4double rand_CS = G4UniformRand() * fXsec[n << 89 //------------- 80 for(fIndexElement = 0; fIndexElement < nelm << 90 const G4ElementVector* theElementVector = currentMaterial->GetElementVector(); 81 { << 91 size_t nelm = currentMaterial->GetNumberOfElements(); 82 if(rand_CS < fXsec[fIndexElement]) << 92 G4double rand_CS= G4UniformRand()*xsec[nelm-1]; 83 break; << 93 for (index_element=0; index_element<nelm-1; index_element++){ 84 } << 94 if (rand_CS<xsec[index_element]) break; 85 << 95 } 86 // Sample shell and binding energy << 96 87 G4int nShells = (*theElementVector)[fIndexEl << 97 //Sample shell and binding energy 88 rand_CS = fShellProb[fIndexElement][nS << 98 //------------- 89 G4int i; << 99 G4int nShells = (*theElementVector)[index_element]->GetNbOfAtomicShells(); 90 for(i = 0; i < nShells - 1; ++i) << 100 rand_CS= shell_prob[index_element][nShells-1]*G4UniformRand(); 91 { << 101 G4int i = 0; 92 if(rand_CS < fShellProb[fIndexElement][i]) << 102 for (i=0; i<nShells-1; i++){ 93 break; << 103 if (rand_CS<shell_prob[index_element][i]) break; 94 } << 104 } 95 G4double gammaEnergy = << 105 G4double gammaEnergy= electronEnergy+(*theElementVector)[index_element]->GetAtomicShell(i); 96 electronEnergy + (*theElementVector)[fInde << 106 97 << 107 //Sample cos theta 98 // Sample cos theta << 108 //Copy of the G4PEEfectFluoModel cos theta sampling method ElecCosThetaDistribution. 99 // Copy of the G4PEEfectFluoModel cos theta << 109 //This method cannot be used directly from G4PEEfectFluoModel because it is a friend method. I should ask Vladimir to change that 100 // ElecCosThetaDistribution. This method can << 110 //------------------------------------------------------------------------------------------------ 101 // G4PEEffectFluoModel because it is a frien << 111 //G4double cos_theta = theDirectPEEffectModel->ElecCosThetaDistribution(electronEnergy); 102 G4double cos_theta = 1.; << 112 103 G4double gamma = 1. + electronEnergy / e << 113 G4double cos_theta = 1.; 104 if(gamma <= 5.) << 114 G4double gamma = 1. + electronEnergy/electron_mass_c2; 105 { << 115 if (gamma <= 5.) { 106 G4double beta = std::sqrt(gamma * gamma - << 116 G4double beta = std::sqrt(gamma*gamma-1.)/gamma; 107 G4double b = 0.5 * gamma * (gamma - 1.) << 117 G4double b = 0.5*gamma*(gamma-1.)*(gamma-2); 108 << 118 109 G4double rndm, term, greject, grejsup; << 119 G4double rndm,term,greject,grejsup; 110 if(gamma < 2.) << 120 if (gamma < 2.) grejsup = gamma*gamma*(1.+b-beta*b); 111 grejsup = gamma * gamma * (1. + b - beta << 121 else grejsup = gamma*gamma*(1.+b+beta*b); 112 else << 122 113 grejsup = gamma * gamma * (1. + b + beta << 123 do { rndm = 1.-2*G4UniformRand(); 114 << 124 cos_theta = (rndm+beta)/(rndm*beta+1.); 115 do << 125 term = 1.-beta*cos_theta; 116 { << 126 greject = (1.-cos_theta*cos_theta)*(1.+b*term)/(term*term); 117 rndm = 1. - 2. * G4UniformRand(); << 127 // Loop checking, 07-Aug-2015, Vladimir Ivanchenko 118 cos_theta = (rndm + beta) / (rndm * beta << 128 } while(greject < G4UniformRand()*grejsup); 119 term = 1. - beta * cos_theta; << 120 greject = (1. - cos_theta * cos_theta) * << 121 // Loop checking, 07-Aug-2015, Vladimir << 122 } while(greject < G4UniformRand() * grejsu << 123 } 129 } 124 << 130 125 // direction of the adjoint gamma electron 131 // direction of the adjoint gamma electron 126 G4double sin_theta = std::sqrt(1. - cos_thet << 132 //--------------------------------------- 127 G4double phi = twopi * G4UniformRand() << 133 128 G4double dirx = sin_theta * std::cos(ph << 134 129 G4double diry = sin_theta * std::sin(ph << 135 G4double sin_theta = std::sqrt(1.-cos_theta*cos_theta); 130 G4double dirz = cos_theta; << 136 G4double Phi = twopi * G4UniformRand(); 131 G4ThreeVector adjoint_gammaDirection(dirx, d << 137 G4double dirx = sin_theta*std::cos(Phi),diry = sin_theta*std::sin(Phi),dirz = cos_theta; >> 138 G4ThreeVector adjoint_gammaDirection(dirx,diry,dirz); 132 adjoint_gammaDirection.rotateUz(electronDire 139 adjoint_gammaDirection.rotateUz(electronDirection); 133 << 140 134 // Weight correction << 141 135 CorrectPostStepWeight(fParticleChange, aTrac << 142 136 gammaEnergy, isScatPro << 143 //Weight correction 137 << 144 //----------------------- 138 // Create secondary and modify fParticleChan << 145 CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(), electronEnergy,gammaEnergy,IsScatProjToProjCase); 139 G4DynamicParticle* anAdjointGamma = new G4Dy << 146 140 G4AdjointGamma::AdjointGamma(), adjoint_ga << 147 141 << 148 >> 149 //Create secondary and modify fParticleChange >> 150 //-------------------------------------------- >> 151 G4DynamicParticle* anAdjointGamma = new G4DynamicParticle ( >> 152 G4AdjointGamma::AdjointGamma(),adjoint_gammaDirection, gammaEnergy); >> 153 >> 154 >> 155 >> 156 >> 157 142 fParticleChange->ProposeTrackStatus(fStopAnd 158 fParticleChange->ProposeTrackStatus(fStopAndKill); 143 fParticleChange->AddSecondary(anAdjointGamma << 159 fParticleChange->AddSecondary(anAdjointGamma); 144 } << 160 145 161 146 ////////////////////////////////////////////// << 162 147 void G4AdjointPhotoElectricModel::CorrectPostS << 148 G4ParticleChange* fParticleChange, G4double << 149 G4double adjointPrimKinEnergy, G4double proj << 150 { << 151 G4double new_weight = old_weight; << 152 163 153 G4double w_corr = << 154 G4AdjointCSManager::GetAdjointCSManager()- << 155 fFactorCSBiasing; << 156 w_corr *= fPostStepAdjointCS / fPreStepAdjoi << 157 << 158 new_weight *= w_corr * projectileKinEnergy / << 159 fParticleChange->SetParentWeightByProcess(fa << 160 fParticleChange->SetSecondaryWeightByProcess << 161 fParticleChange->ProposeParentWeight(new_wei << 162 } 164 } 163 165 164 ////////////////////////////////////////////// 166 //////////////////////////////////////////////////////////////////////////////// 165 G4double G4AdjointPhotoElectricModel::AdjointC << 167 // 166 const G4MaterialCutsCouple* aCouple, G4doubl << 168 void G4AdjointPhotoElectricModel::CorrectPostStepWeight(G4ParticleChange* fParticleChange, 167 G4bool isScatProjToProj) << 169 G4double old_weight, 168 { << 170 G4double adjointPrimKinEnergy, 169 if(isScatProjToProj) << 171 G4double projectileKinEnergy , 170 return 0.; << 172 G4bool ) 171 << 173 { 172 G4double totBiasedAdjointCS = 0.; << 174 G4double new_weight=old_weight; 173 if(aCouple != fCurrentCouple || fCurrenteEne << 175 174 { << 176 G4double w_corr =G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection()/factorCSBiasing; 175 fTotAdjointCS = 0.; << 177 w_corr*=post_step_AdjointCS/pre_step_AdjointCS; 176 DefineCurrentMaterialAndElectronEnergy(aCo << 178 177 const G4ElementVector* theElementVector = << 179 178 fCurrentMaterial->GetElementVector(); << 180 new_weight*=w_corr; 179 const G4double* theAtomNumDensityVector = << 181 new_weight*=projectileKinEnergy/adjointPrimKinEnergy; 180 fCurrentMaterial->GetVecNbOfAtomsPerVolu << 182 fParticleChange->SetParentWeightByProcess(false); 181 size_t nelm = fCurrentMaterial->GetNumberO << 183 fParticleChange->SetSecondaryWeightByProcess(false); 182 for(fIndexElement = 0; fIndexElement < nel << 184 fParticleChange->ProposeParentWeight(new_weight); 183 { << 185 } 184 fTotAdjointCS += AdjointCrossSectionPerA << 186 185 (*theElementVector)[f << 187 //////////////////////////////////////////////////////////////////////////////// 186 theAtomNumDensityVector << 188 // 187 fXsec[fIndexElement] = fTotAdjointCS; << 189 188 } << 190 G4double G4AdjointPhotoElectricModel::AdjointCrossSection(const G4MaterialCutsCouple* aCouple, 189 << 191 G4double electronEnergy, 190 totBiasedAdjointCS = std::min(fTotAdjointC << 192 G4bool IsScatProjToProjCase) 191 fFactorCSBiasing = totBiasedAdjointCS / << 193 { >> 194 >> 195 >> 196 if (IsScatProjToProjCase) return 0.; >> 197 >> 198 >> 199 if (aCouple !=currentCouple || current_eEnergy !=electronEnergy) { >> 200 totAdjointCS = 0.; >> 201 DefineCurrentMaterialAndElectronEnergy(aCouple, electronEnergy); >> 202 const G4ElementVector* theElementVector = currentMaterial->GetElementVector(); >> 203 const double* theAtomNumDensityVector = currentMaterial->GetVecNbOfAtomsPerVolume(); >> 204 size_t nelm = currentMaterial->GetNumberOfElements(); >> 205 for (index_element=0;index_element<nelm;index_element++){ >> 206 >> 207 totAdjointCS +=AdjointCrossSectionPerAtom((*theElementVector)[index_element],electronEnergy)*theAtomNumDensityVector[index_element]; >> 208 xsec[index_element] = totAdjointCS; >> 209 } >> 210 >> 211 totBiasedAdjointCS=std::min(totAdjointCS,0.01); >> 212 // totBiasedAdjointCS=totAdjointCS; >> 213 factorCSBiasing = totBiasedAdjointCS/totAdjointCS; >> 214 lastCS=totBiasedAdjointCS; >> 215 >> 216 192 } 217 } 193 return totBiasedAdjointCS; 218 return totBiasedAdjointCS; >> 219 >> 220 194 } 221 } >> 222 //////////////////////////////////////////////////////////////////////////////// >> 223 // 195 224 >> 225 G4double G4AdjointPhotoElectricModel::GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple, >> 226 G4double electronEnergy, >> 227 G4bool IsScatProjToProjCase) >> 228 { return AdjointCrossSection(aCouple,electronEnergy,IsScatProjToProjCase); >> 229 } 196 ////////////////////////////////////////////// 230 //////////////////////////////////////////////////////////////////////////////// 197 G4double G4AdjointPhotoElectricModel::AdjointC << 231 // 198 const G4Element* anElement, G4double electro << 232 199 { << 233 G4double G4AdjointPhotoElectricModel::AdjointCrossSectionPerAtom(const G4Element* anElement,G4double electronEnergy) 200 G4int nShells = anElement->GetNbOfAto << 234 { 201 G4double Z = anElement->GetZ(); << 235 G4int nShells = anElement->GetNbOfAtomicShells(); 202 G4double gammaEnergy = electronEnergy + anEl << 236 G4double Z= anElement->GetZ(); 203 G4double CS = fDirectModel->Compute << 237 G4int i = 0; 204 G4Gamma::Gamma(), gammaEnergy, Z, 0., 0., << 238 G4double B0=anElement->GetAtomicShell(0); 205 G4double adjointCS = 0.; << 239 G4double gammaEnergy = electronEnergy+B0; 206 if(CS > 0.) << 240 G4double CS= theDirectPEEffectModel->ComputeCrossSectionPerAtom(G4Gamma::Gamma(),gammaEnergy,Z,0.,0.,0.); 207 adjointCS += CS / gammaEnergy; << 241 G4double adjointCS =0.; 208 fShellProb[fIndexElement][0] = adjointCS; << 242 if (CS >0) adjointCS += CS/gammaEnergy; 209 for(G4int i = 1; i < nShells; ++i) << 243 shell_prob[index_element][0] = adjointCS; 210 { << 244 for (i=1;i<nShells;i++){ 211 G4double Bi1 = anElement->GetAtomicShell(i << 245 //G4cout<<i<<G4endl; 212 G4double Bi = anElement->GetAtomicShell(i << 246 G4double Bi_= anElement->GetAtomicShell(i-1); 213 if(electronEnergy < Bi1 - Bi) << 247 G4double Bi = anElement->GetAtomicShell(i); 214 { << 248 //G4cout<<Bi_<<'\t'<<Bi<<G4endl; 215 gammaEnergy = electronEnergy + Bi; << 249 if (electronEnergy <Bi_-Bi) { 216 CS = fDirectModel->ComputeCross << 250 gammaEnergy = electronEnergy+Bi; 217 << 251 218 if(CS > 0.) << 252 CS=theDirectPEEffectModel->ComputeCrossSectionPerAtom(G4Gamma::Gamma(),gammaEnergy,Z,0.,0.,0.); 219 adjointCS += CS / gammaEnergy; << 253 if (CS>0) adjointCS +=CS/gammaEnergy; 220 } << 254 } 221 fShellProb[fIndexElement][i] = adjointCS; << 255 shell_prob[index_element][i] = adjointCS; >> 256 222 } 257 } 223 adjointCS *= electronEnergy; << 258 adjointCS*=electronEnergy; 224 return adjointCS; 259 return adjointCS; 225 } << 260 226 << 261 } 227 ////////////////////////////////////////////// 262 //////////////////////////////////////////////////////////////////////////////// 228 void G4AdjointPhotoElectricModel::DefineCurren << 263 // 229 const G4MaterialCutsCouple* couple, G4double << 264 230 { << 265 void G4AdjointPhotoElectricModel::DefineCurrentMaterialAndElectronEnergy(const G4MaterialCutsCouple* couple, G4double anEnergy) 231 fCurrentCouple = const_cast<G4MaterialCuts << 266 { currentCouple = const_cast<G4MaterialCutsCouple*> (couple); 232 fCurrentMaterial = const_cast<G4Material*>(c << 267 currentMaterial = const_cast<G4Material*> (couple->GetMaterial()); 233 fCurrenteEnergy = anEnergy; << 268 currentCoupleIndex = couple->GetIndex(); 234 fDirectModel->SetCurrentCouple(couple); << 269 currentMaterialIndex = currentMaterial->GetIndex(); >> 270 current_eEnergy = anEnergy; >> 271 theDirectPEEffectModel->SetCurrentCouple(couple); 235 } 272 } 236 273