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: G4EmCalculator.cc,v 1.49.2.1 2010/04/06 09:05:17 gcosmo Exp $ >> 27 // GEANT4 tag $Name: geant4-09-03-patch-02 $ 26 // 28 // 27 // ------------------------------------------- 29 // ------------------------------------------------------------------- 28 // 30 // 29 // GEANT4 Class file 31 // GEANT4 Class file 30 // 32 // 31 // 33 // 32 // File name: G4EmCalculator 34 // File name: G4EmCalculator 33 // 35 // 34 // Author: Vladimir Ivanchenko 36 // Author: Vladimir Ivanchenko 35 // 37 // 36 // Creation date: 28.06.2004 38 // Creation date: 28.06.2004 37 // 39 // >> 40 // Modifications: >> 41 // 12.09.2004 Add verbosity (V.Ivanchenko) >> 42 // 17.11.2004 Change signature of methods, add new methods (V.Ivanchenko) >> 43 // 08.04.2005 Major optimisation of internal interfaces (V.Ivantchenko) >> 44 // 08.05.2005 Use updated interfaces (V.Ivantchenko) >> 45 // 23.10.2005 Fix computations for ions (V.Ivantchenko) >> 46 // 11.01.2006 Add GetCSDARange (V.Ivantchenko) >> 47 // 26.01.2006 Rename GetRange -> GetRangeFromRestricteDEDX (V.Ivanchenko) >> 48 // 14.03.2006 correction in GetCrossSectionPerVolume (mma) >> 49 // suppress GetCrossSectionPerAtom >> 50 // elm->GetA() in ComputeCrossSectionPerAtom >> 51 // 22.03.2006 Add ComputeElectronicDEDX and ComputeTotalDEDX (V.Ivanchenko) >> 52 // 13.05.2006 Add Corrections for ion stopping (V.Ivanchenko) >> 53 // 29.09.2006 Uncomment computation of smoothing factor (V.Ivanchenko) >> 54 // 27.10.2006 Change test energy to access lowEnergy model from >> 55 // 10 keV to 1 keV (V. Ivanchenko) >> 56 // 15.03.2007 Add ComputeEnergyCutFromRangeCut methods (V.Ivanchenko) >> 57 // 21.04.2008 Updated computations for ions (V.Ivanchenko) 38 // 58 // 39 // Class Description: V.Ivanchenko & M.Novak << 59 // Class Description: 40 // 60 // 41 // ------------------------------------------- 61 // ------------------------------------------------------------------- 42 // 62 // 43 //....oooOO0OOooo........oooOO0OOooo........oo 63 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 44 //....oooOO0OOooo........oooOO0OOooo........oo 64 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 45 65 46 #include "G4EmCalculator.hh" 66 #include "G4EmCalculator.hh" 47 #include "G4SystemOfUnits.hh" << 48 #include "G4LossTableManager.hh" 67 #include "G4LossTableManager.hh" 49 #include "G4EmParameters.hh" << 50 #include "G4NistManager.hh" << 51 #include "G4DynamicParticle.hh" << 52 #include "G4VEmProcess.hh" 68 #include "G4VEmProcess.hh" 53 #include "G4VEnergyLossProcess.hh" 69 #include "G4VEnergyLossProcess.hh" 54 #include "G4VMultipleScattering.hh" 70 #include "G4VMultipleScattering.hh" 55 #include "G4Material.hh" 71 #include "G4Material.hh" 56 #include "G4MaterialCutsCouple.hh" 72 #include "G4MaterialCutsCouple.hh" 57 #include "G4ParticleDefinition.hh" 73 #include "G4ParticleDefinition.hh" 58 #include "G4ParticleTable.hh" 74 #include "G4ParticleTable.hh" 59 #include "G4IonTable.hh" << 60 #include "G4PhysicsTable.hh" 75 #include "G4PhysicsTable.hh" 61 #include "G4ProductionCutsTable.hh" 76 #include "G4ProductionCutsTable.hh" 62 #include "G4ProcessManager.hh" 77 #include "G4ProcessManager.hh" 63 #include "G4ionEffectiveCharge.hh" 78 #include "G4ionEffectiveCharge.hh" 64 #include "G4RegionStore.hh" 79 #include "G4RegionStore.hh" 65 #include "G4Element.hh" 80 #include "G4Element.hh" 66 #include "G4EmCorrections.hh" 81 #include "G4EmCorrections.hh" 67 #include "G4GenericIon.hh" 82 #include "G4GenericIon.hh" 68 #include "G4ProcessVector.hh" << 69 #include "G4Gamma.hh" << 70 #include "G4Electron.hh" << 71 #include "G4Positron.hh" << 72 #include "G4EmUtility.hh" << 73 83 74 //....oooOO0OOooo........oooOO0OOooo........oo 84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 75 85 76 G4EmCalculator::G4EmCalculator() 86 G4EmCalculator::G4EmCalculator() 77 { 87 { 78 manager = G4LossTableManager::Instance(); 88 manager = G4LossTableManager::Instance(); 79 nist = G4NistManager::Instance(); << 80 theParameters = G4EmParameters::Instance(); << 81 corr = manager->EmCorrections(); 89 corr = manager->EmCorrections(); 82 cutenergy[0] = cutenergy[1] = cutenergy[2] = << 90 nLocalMaterials = 0; 83 theGenericIon = G4GenericIon::GenericIon(); << 91 verbose = 0; 84 ionEffCharge = new G4ionEffectiveCharge(); << 92 currentCoupleIndex = 0; 85 dynParticle = new G4DynamicParticle(); << 93 currentCouple = 0; 86 ionTable = G4ParticleTable::GetParticle << 94 currentMaterial = 0; >> 95 currentParticle = 0; >> 96 baseParticle = 0; >> 97 currentLambda = 0; >> 98 currentModel = 0; >> 99 loweModel = 0; >> 100 chargeSquare = 1.0; >> 101 massRatio = 1.0; >> 102 currentParticleName= ""; >> 103 currentMaterialName= ""; >> 104 theGenericIon = G4GenericIon::GenericIon(); >> 105 ionEffCharge = new G4ionEffectiveCharge(); >> 106 isIon = false; >> 107 isApplicable = false; 87 } 108 } 88 109 89 //....oooOO0OOooo........oooOO0OOooo........oo 110 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 90 111 91 G4EmCalculator::~G4EmCalculator() 112 G4EmCalculator::~G4EmCalculator() 92 { 113 { 93 delete ionEffCharge; 114 delete ionEffCharge; 94 delete dynParticle; << 115 for (G4int i=0; i<nLocalMaterials; i++) { 95 for (G4int i=0; i<nLocalMaterials; ++i) { << 96 delete localCouples[i]; 116 delete localCouples[i]; 97 } 117 } 98 } 118 } 99 119 100 //....oooOO0OOooo........oooOO0OOooo........oo 120 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 101 121 102 G4double G4EmCalculator::GetDEDX(G4double kinE << 122 G4double G4EmCalculator::GetDEDX(G4double kinEnergy, const G4ParticleDefinition* p, 103 const G4Parti << 123 const G4Material* mat, const G4Region* region) 104 const G4Mater << 105 const G4Regio << 106 { 124 { 107 G4double res = 0.0; 125 G4double res = 0.0; 108 const G4MaterialCutsCouple* couple = FindCou 126 const G4MaterialCutsCouple* couple = FindCouple(mat, region); 109 if(nullptr != couple && UpdateParticle(p, ki << 127 if(couple && UpdateParticle(p, kinEnergy) ) { 110 res = manager->GetDEDX(p, kinEnergy, coupl 128 res = manager->GetDEDX(p, kinEnergy, couple); 111 129 112 if(isIon) { 130 if(isIon) { 113 if(FindEmModel(p, currentProcessName, ki 131 if(FindEmModel(p, currentProcessName, kinEnergy)) { 114 G4double length = CLHEP::nm; << 132 G4double length = CLHEP::nm; 115 G4double eloss = res*length; << 133 G4double eloss = res*length; 116 //G4cout << "### GetDEDX: E= " << kinE << 134 //G4cout << "### GetDEDX: E= " << kinEnergy << " dedx0= " << res 117 // << " de= " << eloss << G4endl << 135 // << " de= " << eloss << G4endl;; 118 dynParticle->SetKineticEnergy(kinEnerg << 136 G4double niel = 0.0; >> 137 dynParticle.SetKineticEnergy(kinEnergy); 119 currentModel->GetChargeSquareRatio(p, 138 currentModel->GetChargeSquareRatio(p, mat, kinEnergy); 120 currentModel->CorrectionsAlongStep(cou << 139 currentModel->CorrectionsAlongStep(couple,&dynParticle,eloss,niel,length); 121 res = eloss/length; << 140 res = eloss/length; 122 //G4cout << " de1= " << eloss << << 141 //G4cout << " de1= " << eloss << " res1= " << res 123 // << " " << p->GetParticleName( << 142 // << " " << p->GetParticleName() <<G4endl;; 124 } 143 } 125 } 144 } 126 145 127 if(verbose>0) { 146 if(verbose>0) { 128 G4cout << "G4EmCalculator::GetDEDX: E(Me 147 G4cout << "G4EmCalculator::GetDEDX: E(MeV)= " << kinEnergy/MeV 129 << " DEDX(MeV/mm)= " << res*mm/Me << 148 << " DEDX(MeV/mm)= " << res*mm/MeV 130 << " DEDX(MeV*cm^2/g)= " << res*g << 149 << " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity()) 131 << " " << p->GetParticleName() << 150 << " " << p->GetParticleName() 132 << " in " << mat->GetName() << 151 << " in " << mat->GetName() 133 << " isIon= " << isIon << 152 << " isIon= " << isIon 134 << G4endl; << 153 << G4endl; 135 } 154 } 136 } 155 } 137 return res; 156 return res; 138 } 157 } 139 158 140 //....oooOO0OOooo........oooOO0OOooo........oo 159 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 141 160 >> 161 G4double G4EmCalculator::GetDEDX(G4double kinEnergy, const G4String& particle, >> 162 const G4String& material, const G4String& reg) >> 163 { >> 164 return GetDEDX(kinEnergy,FindParticle(particle), >> 165 FindMaterial(material),FindRegion(reg)); >> 166 } >> 167 >> 168 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 169 142 G4double G4EmCalculator::GetRangeFromRestricte 170 G4double G4EmCalculator::GetRangeFromRestricteDEDX(G4double kinEnergy, 143 << 171 const G4ParticleDefinition* p, 144 << 172 const G4Material* mat, 145 << 173 const G4Region* region) 146 { 174 { 147 G4double res = 0.0; 175 G4double res = 0.0; 148 const G4MaterialCutsCouple* couple = FindCou 176 const G4MaterialCutsCouple* couple = FindCouple(mat,region); 149 if(couple && UpdateParticle(p, kinEnergy)) { 177 if(couple && UpdateParticle(p, kinEnergy)) { 150 res = manager->GetRangeFromRestricteDEDX(p 178 res = manager->GetRangeFromRestricteDEDX(p, kinEnergy, couple); 151 if(verbose>1) { << 179 if(verbose>0) { 152 G4cout << " G4EmCalculator::GetRangeFrom << 180 G4cout << "G4EmCalculator::GetRange: E(MeV)= " << kinEnergy/MeV 153 << kinEnergy/MeV << 181 << " range(mm)= " << res/mm 154 << " range(mm)= " << res/mm << 182 << " " << p->GetParticleName() 155 << " " << p->GetParticleName() << 183 << " in " << mat->GetName() 156 << " in " << mat->GetName() << 184 << G4endl; 157 << G4endl; << 158 } 185 } 159 } 186 } 160 return res; 187 return res; 161 } 188 } 162 189 163 //....oooOO0OOooo........oooOO0OOooo........oo 190 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 164 191 165 G4double G4EmCalculator::GetCSDARange(G4double 192 G4double G4EmCalculator::GetCSDARange(G4double kinEnergy, 166 const G4 << 193 const G4ParticleDefinition* p, 167 const G4 << 194 const G4Material* mat, 168 const G4 << 195 const G4Region* region) 169 { 196 { 170 G4double res = 0.0; 197 G4double res = 0.0; 171 if(!theParameters->BuildCSDARange()) { << 172 G4ExceptionDescription ed; << 173 ed << "G4EmCalculator::GetCSDARange: CSDA << 174 << " use UI command: /process/eLoss/CSD << 175 G4Exception("G4EmCalculator::GetCSDARange" << 176 JustWarning, ed); << 177 return res; << 178 } << 179 << 180 const G4MaterialCutsCouple* couple = FindCou 198 const G4MaterialCutsCouple* couple = FindCouple(mat,region); 181 if(nullptr != couple && UpdateParticle(p, ki << 199 if(couple && UpdateParticle(p, kinEnergy)) { 182 res = manager->GetCSDARange(p, kinEnergy, 200 res = manager->GetCSDARange(p, kinEnergy, couple); 183 if(verbose>1) { << 201 if(verbose>0) { 184 G4cout << " G4EmCalculator::GetCSDARange << 202 G4cout << "G4EmCalculator::GetRange: E(MeV)= " << kinEnergy/MeV 185 << " range(mm)= " << res/mm << 203 << " range(mm)= " << res/mm 186 << " " << p->GetParticleName() << 204 << " " << p->GetParticleName() 187 << " in " << mat->GetName() << 205 << " in " << mat->GetName() 188 << G4endl; << 206 << G4endl; 189 } 207 } 190 } 208 } 191 return res; 209 return res; 192 } 210 } 193 211 194 //....oooOO0OOooo........oooOO0OOooo........oo 212 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 195 213 196 G4double G4EmCalculator::GetRange(G4double kin 214 G4double G4EmCalculator::GetRange(G4double kinEnergy, 197 const G4Part << 215 const G4ParticleDefinition* p, 198 const G4Mate << 216 const G4Material* mat, 199 const G4Regi << 217 const G4Region* region) 200 { 218 { 201 G4double res = 0.0; 219 G4double res = 0.0; 202 if(theParameters->BuildCSDARange()) { << 220 const G4MaterialCutsCouple* couple = FindCouple(mat,region); 203 res = GetCSDARange(kinEnergy, p, mat, regi << 221 if(couple && UpdateParticle(p, kinEnergy)) { 204 } else { << 222 res = manager->GetRange(p, kinEnergy, couple); 205 res = GetRangeFromRestricteDEDX(kinEnergy, << 223 if(verbose>0) { >> 224 G4cout << "G4EmCalculator::GetRange: E(MeV)= " << kinEnergy/MeV >> 225 << " range(mm)= " << res/mm >> 226 << " " << p->GetParticleName() >> 227 << " in " << mat->GetName() >> 228 << G4endl; >> 229 } 206 } 230 } 207 return res; 231 return res; 208 } 232 } 209 233 210 //....oooOO0OOooo........oooOO0OOooo........oo 234 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 211 235 >> 236 G4double G4EmCalculator::GetRangeFromRestricteDEDX(G4double kinEnergy, >> 237 const G4String& particle, >> 238 const G4String& material, >> 239 const G4String& reg) >> 240 { >> 241 return GetRangeFromRestricteDEDX(kinEnergy,FindParticle(particle), >> 242 FindMaterial(material),FindRegion(reg)); >> 243 } >> 244 >> 245 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 246 >> 247 G4double G4EmCalculator::GetCSDARange(G4double kinEnergy, >> 248 const G4String& particle, >> 249 const G4String& material, >> 250 const G4String& reg) >> 251 { >> 252 return GetCSDARange(kinEnergy,FindParticle(particle), >> 253 FindMaterial(material),FindRegion(reg)); >> 254 } >> 255 >> 256 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 257 >> 258 G4double G4EmCalculator::GetRange(G4double kinEnergy, >> 259 const G4String& particle, >> 260 const G4String& material, >> 261 const G4String& reg) >> 262 { >> 263 return GetRange(kinEnergy,FindParticle(particle), >> 264 FindMaterial(material),FindRegion(reg)); >> 265 } >> 266 >> 267 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 268 212 G4double G4EmCalculator::GetKinEnergy(G4double 269 G4double G4EmCalculator::GetKinEnergy(G4double range, 213 const G4 << 270 const G4ParticleDefinition* p, 214 const G4 271 const G4Material* mat, 215 const G4 << 272 const G4Region* region) 216 { 273 { 217 G4double res = 0.0; 274 G4double res = 0.0; 218 const G4MaterialCutsCouple* couple = FindCou 275 const G4MaterialCutsCouple* couple = FindCouple(mat,region); 219 if(nullptr != couple && UpdateParticle(p, 1. << 276 if(couple && UpdateParticle(p, 1.0*GeV)) { 220 res = manager->GetEnergy(p, range, couple) 277 res = manager->GetEnergy(p, range, couple); 221 if(verbose>0) { 278 if(verbose>0) { 222 G4cout << "G4EmCalculator::GetKinEnergy: 279 G4cout << "G4EmCalculator::GetKinEnergy: Range(mm)= " << range/mm 223 << " KinE(MeV)= " << res/MeV << 280 << " KinE(MeV)= " << res/MeV 224 << " " << p->GetParticleName() << 281 << " " << p->GetParticleName() 225 << " in " << mat->GetName() << 282 << " in " << mat->GetName() 226 << G4endl; << 283 << G4endl; 227 } 284 } 228 } 285 } 229 return res; 286 return res; 230 } 287 } 231 288 232 //....oooOO0OOooo........oooOO0OOooo........oo 289 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 233 290 >> 291 G4double G4EmCalculator::GetKinEnergy(G4double range, const G4String& particle, >> 292 const G4String& material, const G4String& reg) >> 293 { >> 294 return GetKinEnergy(range,FindParticle(particle), >> 295 FindMaterial(material),FindRegion(reg)); >> 296 } >> 297 >> 298 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 299 234 G4double G4EmCalculator::GetCrossSectionPerVol 300 G4double G4EmCalculator::GetCrossSectionPerVolume(G4double kinEnergy, 235 co 301 const G4ParticleDefinition* p, 236 co 302 const G4String& processName, 237 co << 303 const G4Material* mat, 238 co << 304 const G4Region* region) 239 { 305 { 240 G4double res = 0.0; 306 G4double res = 0.0; 241 const G4MaterialCutsCouple* couple = FindCou 307 const G4MaterialCutsCouple* couple = FindCouple(mat,region); 242 308 243 if(nullptr != couple && UpdateParticle(p, ki << 309 if(couple && UpdateParticle(p, kinEnergy)) { 244 if(FindEmModel(p, processName, kinEnergy)) << 310 G4int idx = couple->GetIndex(); 245 G4int idx = couple->GetIndex(); << 311 FindLambdaTable(p, processName); 246 G4int procType = -1; << 312 if(currentLambda) { 247 FindLambdaTable(p, processName, kinEnerg << 313 G4double e = kinEnergy*massRatio; 248 << 314 res = (((*currentLambda)[idx])->Value(e))*chargeSquare; 249 G4VEmProcess* emproc = FindDiscreteProce << 250 if(nullptr != emproc) { << 251 res = emproc->GetCrossSection(kinEnergy, cou << 252 } else if(currentLambda) { << 253 // special tables are built for Msc mo << 254 // procType is set in FindLambdaTable << 255 if(procType==2) { << 256 auto mscM = static_cast<G4VMscModel* << 257 mscM->SetCurrentCouple(couple); << 258 G4double tr1Mfp = mscM->GetTransport << 259 if (tr1Mfp<DBL_MAX) { << 260 res = 1./tr1Mfp; << 261 } << 262 } else { << 263 G4double e = kinEnergy*massRatio; << 264 res = (((*currentLambda)[idx])->Valu << 265 } << 266 } else { << 267 res = ComputeCrossSectionPerVolume(kin << 268 } << 269 if(verbose>0) { 315 if(verbose>0) { 270 G4cout << "G4EmCalculator::GetXSPerVol << 316 G4cout << "E(MeV)= " << kinEnergy/MeV 271 << " cross(cm-1)= " << res*cm << 317 << " cross(cm-1)= " << res*cm 272 << " " << p->GetParticleName( << 318 << " " << p->GetParticleName() 273 << " in " << mat->GetName(); << 319 << " in " << mat->GetName(); 274 if(verbose>1) << 320 if(verbose>1) 275 G4cout << " idx= " << idx << " Esc << 321 G4cout << " idx= " << idx << " e(MeV)= " << e 276 << kinEnergy*massRatio << 322 << " q2= " << chargeSquare; 277 << " q2= " << chargeSquare; << 323 G4cout << G4endl; 278 G4cout << G4endl; << 324 } 279 } << 280 } 325 } 281 } 326 } 282 return res; 327 return res; 283 } 328 } 284 329 285 //....oooOO0OOooo........oooOO0OOooo........oo 330 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 286 331 287 G4double G4EmCalculator::GetShellIonisationCro << 332 G4double G4EmCalculator::GetCrossSectionPerVolume(G4double kinEnergy, 288 const << 333 const G4String& particle, 289 G4int << 334 const G4String& processName, 290 G4Ato << 335 const G4String& material, 291 G4dou << 336 const G4String& reg) 292 { 337 { 293 G4double res = 0.0; << 338 return GetCrossSectionPerVolume(kinEnergy,FindParticle(particle),processName, 294 const G4ParticleDefinition* p = FindParticle << 339 FindMaterial(material),FindRegion(reg)); 295 G4VAtomDeexcitation* ad = manager->AtomDeexc << 296 if(nullptr != p && nullptr != ad) { << 297 res = ad->GetShellIonisationCrossSectionPe << 298 } << 299 return res; << 300 } 340 } 301 341 302 //....oooOO0OOooo........oooOO0OOooo........oo 342 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 303 343 304 G4double G4EmCalculator::GetMeanFreePath(G4dou 344 G4double G4EmCalculator::GetMeanFreePath(G4double kinEnergy, 305 const 345 const G4ParticleDefinition* p, 306 const 346 const G4String& processName, 307 const << 347 const G4Material* mat, 308 const 348 const G4Region* region) 309 { 349 { 310 G4double res = DBL_MAX; 350 G4double res = DBL_MAX; 311 G4double x = GetCrossSectionPerVolume(kinEne 351 G4double x = GetCrossSectionPerVolume(kinEnergy,p, processName, mat,region); 312 if(x > 0.0) { res = 1.0/x; } << 352 if(x > 0.0) res = 1.0/x; 313 if(verbose>1) { 353 if(verbose>1) { 314 G4cout << "G4EmCalculator::GetMeanFreePath 354 G4cout << "G4EmCalculator::GetMeanFreePath: E(MeV)= " << kinEnergy/MeV 315 << " MFP(mm)= " << res/mm << 355 << " MFP(mm)= " << res/mm 316 << " " << p->GetParticleName() << 356 << " " << p->GetParticleName() 317 << " in " << mat->GetName() << 357 << " in " << mat->GetName() 318 << G4endl; << 358 << G4endl; 319 } 359 } 320 return res; 360 return res; 321 } 361 } 322 362 323 //....oooOO0OOooo........oooOO0OOooo........oo 363 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 324 364 >> 365 G4double G4EmCalculator::GetMeanFreePath(G4double kinEnergy, >> 366 const G4String& particle, >> 367 const G4String& processName, >> 368 const G4String& material, >> 369 const G4String& reg) >> 370 { >> 371 return GetMeanFreePath(kinEnergy,FindParticle(particle),processName, >> 372 FindMaterial(material),FindRegion(reg)); >> 373 } >> 374 >> 375 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 376 325 void G4EmCalculator::PrintDEDXTable(const G4Pa 377 void G4EmCalculator::PrintDEDXTable(const G4ParticleDefinition* p) 326 { 378 { 327 const G4VEnergyLossProcess* elp = manager->G << 379 const G4VEnergyLossProcess* elp = FindEnergyLossProcess(p); 328 G4cout << "##### DEDX Table for " << p->GetP 380 G4cout << "##### DEDX Table for " << p->GetParticleName() << G4endl; 329 if(nullptr != elp) G4cout << *(elp->DEDXTabl << 381 if(elp) G4cout << *(elp->DEDXTable()) << G4endl; 330 } 382 } 331 383 332 //....oooOO0OOooo........oooOO0OOooo........oo 384 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 333 385 334 void G4EmCalculator::PrintRangeTable(const G4P 386 void G4EmCalculator::PrintRangeTable(const G4ParticleDefinition* p) 335 { 387 { 336 const G4VEnergyLossProcess* elp = manager->G << 388 const G4VEnergyLossProcess* elp = FindEnergyLossProcess(p); 337 G4cout << "##### Range Table for " << p->Get 389 G4cout << "##### Range Table for " << p->GetParticleName() << G4endl; 338 if(nullptr != elp) G4cout << *(elp->RangeTab << 390 if(elp) G4cout << *(elp->RangeTableForLoss()) << G4endl; 339 } 391 } 340 392 341 //....oooOO0OOooo........oooOO0OOooo........oo 393 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 342 394 343 void G4EmCalculator::PrintInverseRangeTable(co 395 void G4EmCalculator::PrintInverseRangeTable(const G4ParticleDefinition* p) 344 { 396 { 345 const G4VEnergyLossProcess* elp = manager->G << 397 const G4VEnergyLossProcess* elp = FindEnergyLossProcess(p); 346 G4cout << "### G4EmCalculator: Inverse Range 398 G4cout << "### G4EmCalculator: Inverse Range Table for " 347 << p->GetParticleName() << G4endl; << 399 << p->GetParticleName() << G4endl; 348 if(nullptr != elp) G4cout << *(elp->InverseR << 400 if(elp) G4cout << *(elp->InverseRangeTable()) << G4endl; 349 } 401 } 350 402 351 //....oooOO0OOooo........oooOO0OOooo........oo 403 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 352 404 353 G4double G4EmCalculator::ComputeDEDX(G4double 405 G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy, 354 const G4P 406 const G4ParticleDefinition* p, 355 const G4S 407 const G4String& processName, 356 const G4M << 408 const G4Material* mat, 357 G4d 409 G4double cut) 358 { 410 { 359 SetupMaterial(mat); << 411 currentMaterial = mat; >> 412 currentMaterialName = mat->GetName(); 360 G4double res = 0.0; 413 G4double res = 0.0; 361 if(verbose > 1) { 414 if(verbose > 1) { 362 G4cout << "### G4EmCalculator::ComputeDEDX 415 G4cout << "### G4EmCalculator::ComputeDEDX: " << p->GetParticleName() 363 << " in " << currentMaterialName 416 << " in " << currentMaterialName 364 << " e(MeV)= " << kinEnergy/MeV << 417 << " e(MeV)= " << kinEnergy/MeV << " cut(MeV)= " << cut/MeV 365 << G4endl; << 418 << G4endl; 366 } 419 } 367 if(UpdateParticle(p, kinEnergy)) { 420 if(UpdateParticle(p, kinEnergy)) { 368 if(FindEmModel(p, processName, kinEnergy)) 421 if(FindEmModel(p, processName, kinEnergy)) { 369 G4double escaled = kinEnergy*massRatio; 422 G4double escaled = kinEnergy*massRatio; 370 if(nullptr != baseParticle) { << 423 if(baseParticle) { 371 res = currentModel->ComputeDEDXPerVolume(mat << 424 res = currentModel->ComputeDEDXPerVolume( 372 << 425 mat, baseParticle, escaled, cut) * chargeSquare; 373 if(verbose > 1) { << 426 if(verbose > 1) { 374 G4cout << "Particle: " << p->GetParticleNa << 427 G4cout << baseParticle->GetParticleName() 375 << " E(MeV)=" << kinEnergy << 428 << " Escaled(MeV)= " << escaled; 376 << " Base particle: " << baseParticle->Ge << 377 << " Escaled(MeV)= " << escaled << 378 << " q2=" << chargeSquare << G4endl; << 379 } << 380 } else { << 381 res = currentModel->ComputeDEDXPerVolume(mat << 382 if(verbose > 1) { << 383 G4cout << "Particle: " << p->GetParticleNa << 384 << " E(MeV)=" << kinEnergy << G4endl; << 385 } 429 } >> 430 } else { >> 431 res = currentModel->ComputeDEDXPerVolume(mat, p, kinEnergy, cut); >> 432 if(verbose > 1) G4cout << " no basePart E(MeV)= " << kinEnergy; 386 } 433 } 387 if(verbose > 1) { 434 if(verbose > 1) { 388 G4cout << currentModel->GetName() << ": DEDX << 435 G4cout << " DEDX(MeV/mm)= " << res*mm/MeV 389 << " DEDX(MeV*cm^2/g)= " 436 << " DEDX(MeV*cm^2/g)= " 390 << res*gram/(MeV*cm2*mat->GetDensity( 437 << res*gram/(MeV*cm2*mat->GetDensity()) 391 << G4endl; 438 << G4endl; 392 } 439 } >> 440 393 // emulate smoothing procedure 441 // emulate smoothing procedure 394 if(applySmoothing && nullptr != loweMode << 442 G4double eth = currentModel->LowEnergyLimit(); 395 G4double eth = currentModel->LowEnergyLimit( << 443 // G4cout << "massRatio= " << massRatio << " eth= " << eth << G4endl; 396 G4double res0 = 0.0; << 444 if(loweModel) { 397 G4double res1 = 0.0; << 445 G4double res0 = 0.0; 398 if(nullptr != baseParticle) { << 446 G4double res1 = 0.0; 399 res1 = chargeSquare* << 447 if(baseParticle) { 400 currentModel->ComputeDEDXPerVolume(mat, << 448 res1 = currentModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut) 401 res0 = chargeSquare* << 449 * chargeSquare; 402 loweModel->ComputeDEDXPerVolume(mat, bas << 450 res0 = loweModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut) >> 451 * chargeSquare; 403 } else { 452 } else { 404 res1 = currentModel->ComputeDEDXPerVolume( 453 res1 = currentModel->ComputeDEDXPerVolume(mat, p, eth, cut); 405 res0 = loweModel->ComputeDEDXPerVolume(mat 454 res0 = loweModel->ComputeDEDXPerVolume(mat, p, eth, cut); 406 } 455 } 407 if(res1 > 0.0 && escaled > 0.0) { << 408 res *= (1.0 + (res0/res1 - 1.0)*eth/escale << 409 } << 410 if(verbose > 1) { 456 if(verbose > 1) { 411 G4cout << "At boundary energy(MeV)= " << e 457 G4cout << "At boundary energy(MeV)= " << eth/MeV 412 << " DEDX(MeV/mm)= " << res0*mm/MeV << " << 458 << " DEDX(MeV/mm)= " << res1*mm/MeV 413 << " after correction DEDX(MeV/mm)=" << r << 459 << G4endl; 414 } 460 } >> 461 /* >> 462 G4cout << "eth= " << eth << " escaled= " << escaled >> 463 << " res0= " << res0 << " res1= " >> 464 << res1 << " q2= " << chargeSquare << G4endl; >> 465 */ >> 466 res += (res0 - res1)*eth/escaled; 415 } 467 } 416 // correction for ions << 468 >> 469 // low energy correction for ions 417 if(isIon) { 470 if(isIon) { 418 const G4double length = CLHEP::nm; << 471 G4double length = CLHEP::nm; 419 if(UpdateCouple(mat, cut)) { << 472 const G4Region* r = 0; 420 G4double eloss = res*length; << 473 const G4MaterialCutsCouple* couple = FindCouple(mat, r); 421 dynParticle->SetKineticEnergy(kinEnergy); << 474 G4double eloss = res*length; 422 currentModel->CorrectionsAlongStep(current << 475 G4double niel = 0.0; 423 l << 476 dynParticle.SetKineticEnergy(kinEnergy); 424 res = eloss/length; << 477 currentModel->GetChargeSquareRatio(p, mat, kinEnergy); 425 << 478 currentModel->CorrectionsAlongStep(couple,&dynParticle,eloss,niel,length); 426 if(verbose > 1) { << 479 res = eloss/length; 427 G4cout << "After Corrections: DEDX(MeV/m << 480 428 << " DEDX(MeV*cm^2/g)= " << 481 if(verbose > 1) { 429 << res*gram/(MeV*cm2*mat->GetDensity()) << 482 G4cout << "After Corrections: DEDX(MeV/mm)= " << res*mm/MeV 430 } << 483 << " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity()) >> 484 << G4endl; 431 } 485 } 432 } 486 } 433 if(verbose > 0) { << 487 } 434 G4cout << "## E(MeV)= " << kinEnergy/MeV << 488 435 << " DEDX(MeV/mm)= " << res*mm/MeV << 489 if(verbose > 0) { 436 << " DEDX(MeV*cm^2/g)= " << res*gram/ << 490 G4cout << "E(MeV)= " << kinEnergy/MeV 437 << " cut(MeV)= " << cut/MeV << 491 << " DEDX(MeV/mm)= " << res*mm/MeV 438 << " " << p->GetParticleName() << 492 << " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity()) 439 << " in " << currentMaterialName << 493 << " cut(MeV)= " << cut/MeV 440 << " Zi^2= " << chargeSquare << 494 << " " << p->GetParticleName() 441 << " isIon=" << isIon << 495 << " in " << currentMaterialName 442 << G4endl; << 496 << " Zi^2= " << chargeSquare 443 } << 497 << " isIon=" << isIon >> 498 << G4endl; 444 } 499 } 445 } 500 } 446 return res; 501 return res; 447 } 502 } 448 503 449 //....oooOO0OOooo........oooOO0OOooo........oo 504 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 450 505 451 G4double G4EmCalculator::ComputeElectronicDEDX 506 G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy, 452 << 507 const G4ParticleDefinition* part, 453 << 508 const G4Material* mat, 454 << 509 G4double cut) 455 { 510 { 456 SetupMaterial(mat); << 511 currentMaterial = mat; >> 512 currentMaterialName = mat->GetName(); 457 G4double dedx = 0.0; 513 G4double dedx = 0.0; 458 if(UpdateParticle(part, kinEnergy)) { 514 if(UpdateParticle(part, kinEnergy)) { 459 << 460 G4LossTableManager* lManager = G4LossTable 515 G4LossTableManager* lManager = G4LossTableManager::Instance(); 461 const std::vector<G4VEnergyLossProcess*> v 516 const std::vector<G4VEnergyLossProcess*> vel = 462 lManager->GetEnergyLossProcessVector(); 517 lManager->GetEnergyLossProcessVector(); 463 std::size_t n = vel.size(); << 518 G4int n = vel.size(); 464 << 519 for(G4int i=0; i<n; ++i) { 465 //G4cout << "ComputeElectronicDEDX for " < << 520 const G4ParticleDefinition* p = (vel[i])->Particle(); 466 // << " n= " << n << G4endl; << 521 if((!isIon && p == part) || (isIon && p == theGenericIon)) { 467 << 522 dedx += ComputeDEDX(kinEnergy,part,(vel[i])->GetProcessName(),mat,cut); 468 for(std::size_t i=0; i<n; ++i) { << 469 if(vel[i]) { << 470 auto p = static_cast<G4VProcess*>(vel[ << 471 if(ActiveForParticle(part, p)) { << 472 //G4cout << "idx= " << i << " " << ( << 473 // << " " << (vel[i])->Particle()- << 474 dedx += ComputeDEDX(kinEnergy,part,( << 475 } << 476 } 523 } 477 } 524 } 478 } 525 } 479 return dedx; 526 return dedx; 480 } 527 } 481 528 482 //....oooOO0OOooo........oooOO0OOooo........oo 529 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 483 530 484 G4double << 531 G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy, const G4String& part, 485 G4EmCalculator::ComputeDEDXForCutInRange(G4dou << 532 const G4String& mat, G4double cut) 486 const << 487 const << 488 G4dou << 489 { 533 { 490 SetupMaterial(mat); << 534 return ComputeElectronicDEDX(kinEnergy,FindParticle(part),FindMaterial(mat),cut); 491 G4double dedx = 0.0; << 535 } 492 if(UpdateParticle(part, kinEnergy)) { << 493 << 494 G4LossTableManager* lManager = G4LossTable << 495 const std::vector<G4VEnergyLossProcess*> v << 496 lManager->GetEnergyLossProcessVector(); << 497 std::size_t n = vel.size(); << 498 536 499 if(mat != cutMaterial) { << 537 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 500 cutMaterial = mat; << 501 cutenergy[0] = << 502 ComputeEnergyCutFromRangeCut(rangecut, << 503 cutenergy[1] = << 504 ComputeEnergyCutFromRangeCut(rangecut, << 505 cutenergy[2] = << 506 ComputeEnergyCutFromRangeCut(rangecut, << 507 } << 508 << 509 //G4cout << "ComputeElectronicDEDX for " < << 510 // << " n= " << n << G4endl; << 511 << 512 for(std::size_t i=0; i<n; ++i) { << 513 if(vel[i]) { << 514 auto p = static_cast<G4VProcess*>(vel[ << 515 if(ActiveForParticle(part, p)) { << 516 //G4cout << "idx= " << i << " " << ( << 517 // << " " << (vel[i])->Particle()-> << 518 const G4ParticleDefinition* sec = (v << 519 std::size_t idx = 0; << 520 if(sec == G4Electron::Electron()) { << 521 else if(sec == G4Positron::Positron( << 522 538 523 dedx += ComputeDEDX(kinEnergy,part,( << 539 G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, 524 mat,cutenergy[id << 540 const G4ParticleDefinition* part, 525 } << 541 const G4Material* mat, 526 } << 542 G4double cut) 527 } << 543 { 528 } << 544 G4double dedx = ComputeElectronicDEDX(kinEnergy,part,mat,cut); >> 545 if(mass > 700.*MeV) dedx += ComputeNuclearDEDX(kinEnergy,part,mat); 529 return dedx; 546 return dedx; 530 } 547 } 531 548 532 //....oooOO0OOooo........oooOO0OOooo........oo 549 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 533 550 534 G4double G4EmCalculator::ComputeTotalDEDX(G4do 551 G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, 535 cons << 552 const G4String& part, 536 cons << 553 const G4String& mat, 537 G4do << 554 G4double cut) 538 { 555 { 539 G4double dedx = ComputeElectronicDEDX(kinEne << 556 return ComputeTotalDEDX(kinEnergy,FindParticle(part),FindMaterial(mat),cut); 540 if(mass > 700.*MeV) { dedx += ComputeNuclear << 557 } 541 return dedx; << 558 >> 559 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 560 >> 561 G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy, >> 562 const G4String& particle, >> 563 const G4String& processName, >> 564 const G4String& material, >> 565 G4double cut) >> 566 { >> 567 return ComputeDEDX(kinEnergy,FindParticle(particle),processName, >> 568 FindMaterial(material),cut); 542 } 569 } 543 570 544 //....oooOO0OOooo........oooOO0OOooo........oo 571 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 545 572 546 G4double G4EmCalculator::ComputeNuclearDEDX(G4 573 G4double G4EmCalculator::ComputeNuclearDEDX(G4double kinEnergy, 547 const G4 574 const G4ParticleDefinition* p, 548 const G4 << 575 const G4Material* mat) 549 { 576 { 550 G4double res = 0.0; << 577 551 G4VEmProcess* nucst = FindDiscreteProcess(p, << 578 G4double res = corr->NuclearDEDX(p, mat, kinEnergy, false); 552 if(nucst) { << 553 G4VEmModel* mod = nucst->EmModel(); << 554 if(mod) { << 555 mod->SetFluctuationFlag(false); << 556 res = mod->ComputeDEDXPerVolume(mat, p, << 557 } << 558 } << 559 579 560 if(verbose > 1) { 580 if(verbose > 1) { 561 G4cout << p->GetParticleName() << " E(MeV 581 G4cout << p->GetParticleName() << " E(MeV)= " << kinEnergy/MeV 562 << " NuclearDEDX(MeV/mm)= " << res* << 582 << " NuclearDEDX(MeV/mm)= " << res*mm/MeV 563 << " NuclearDEDX(MeV*cm^2/g)= " << 583 << " NuclearDEDX(MeV*cm^2/g)= " 564 << res*gram/(MeV*cm2*mat->GetDensit << 584 << res*gram/(MeV*cm2*mat->GetDensity()) 565 << G4endl; << 585 << G4endl; 566 } 586 } 567 return res; 587 return res; 568 } 588 } 569 589 570 //....oooOO0OOooo........oooOO0OOooo........oo 590 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 571 591 >> 592 G4double G4EmCalculator::ComputeNuclearDEDX(G4double kinEnergy, >> 593 const G4String& particle, >> 594 const G4String& material) >> 595 { >> 596 return ComputeNuclearDEDX(kinEnergy,FindParticle(particle), >> 597 FindMaterial(material)); >> 598 } >> 599 >> 600 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 601 572 G4double G4EmCalculator::ComputeCrossSectionPe 602 G4double G4EmCalculator::ComputeCrossSectionPerVolume( 573 603 G4double kinEnergy, 574 c 604 const G4ParticleDefinition* p, 575 c 605 const G4String& processName, 576 c << 606 const G4Material* mat, 577 607 G4double cut) 578 { 608 { 579 SetupMaterial(mat); << 609 currentMaterial = mat; >> 610 currentMaterialName = mat->GetName(); 580 G4double res = 0.0; 611 G4double res = 0.0; 581 if(UpdateParticle(p, kinEnergy)) { 612 if(UpdateParticle(p, kinEnergy)) { 582 if(FindEmModel(p, processName, kinEnergy)) 613 if(FindEmModel(p, processName, kinEnergy)) { 583 G4double e = kinEnergy; 614 G4double e = kinEnergy; 584 G4double aCut = std::max(cut, theParamet << 585 if(baseParticle) { 615 if(baseParticle) { 586 e *= kinEnergy*massRatio; << 616 e *= kinEnergy*massRatio; 587 res = currentModel->CrossSectionPerVol << 617 res = currentModel->CrossSectionPerVolume( 588 mat, baseParticle, e, aCut, e) * << 618 mat, baseParticle, e, cut, e) * chargeSquare; 589 } else { 619 } else { 590 res = currentModel->CrossSectionPerVol << 620 res = currentModel->CrossSectionPerVolume(mat, p, e, cut, e); 591 } 621 } 592 if(verbose>0) { 622 if(verbose>0) { 593 G4cout << "G4EmCalculator::ComputeXSPe << 623 G4cout << "E(MeV)= " << kinEnergy/MeV 594 << kinEnergy/MeV << 624 << " cross(cm-1)= " << res*cm 595 << " cross(cm-1)= " << res*cm << 625 << " " << p->GetParticleName() 596 << " cut(keV)= " << aCut/keV << 626 << " in " << mat->GetName() 597 << " " << p->GetParticleName( << 627 << G4endl; 598 << " in " << mat->GetName() << 599 << G4endl; << 600 } 628 } 601 } 629 } 602 } 630 } 603 return res; 631 return res; 604 } 632 } 605 633 606 //....oooOO0OOooo........oooOO0OOooo........oo 634 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 607 635 608 G4double << 636 G4double G4EmCalculator::ComputeCrossSectionPerVolume( 609 G4EmCalculator::ComputeCrossSectionPerAtom(G4d << 637 G4double kinEnergy, 610 con << 638 const G4String& particle, 611 con << 639 const G4String& processName, 612 G4d << 640 const G4String& material, 613 G4d << 641 G4double cut) 614 { 642 { 615 G4double res = 0.0; << 643 return ComputeCrossSectionPerVolume(kinEnergy,FindParticle(particle), 616 if(UpdateParticle(p, kinEnergy)) { << 644 processName, 617 G4int iz = G4lrint(Z); << 645 FindMaterial(material),cut); 618 CheckMaterial(iz); << 619 if(FindEmModel(p, processName, kinEnergy)) << 620 G4double e = kinEnergy; << 621 G4double aCut = std::max(cut, theParamet << 622 if(baseParticle) { << 623 e *= kinEnergy*massRatio; << 624 currentModel->InitialiseForElement(bas << 625 res = currentModel->ComputeCrossSectio << 626 baseParticle, e, Z, A, aCut) * c << 627 } else { << 628 currentModel->InitialiseForElement(p, << 629 res = currentModel->ComputeCrossSectio << 630 } << 631 if(verbose>0) { << 632 G4cout << "E(MeV)= " << kinEnergy/MeV << 633 << " cross(barn)= " << res/barn << 634 << " " << p->GetParticleName( << 635 << " Z= " << Z << " A= " << A/ << 636 << " cut(keV)= " << aCut/keV << 637 << G4endl; << 638 } << 639 } << 640 } << 641 return res; << 642 } 646 } 643 647 644 //....oooOO0OOooo........oooOO0OOooo........oo 648 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 645 649 646 G4double << 650 G4double G4EmCalculator::ComputeCrossSectionPerAtom( 647 G4EmCalculator::ComputeCrossSectionPerShell(G4 << 651 G4double kinEnergy, 648 co << 652 const G4ParticleDefinition* p, 649 co << 653 const G4String& processName, 650 G4 << 654 G4double Z, G4double A, 651 G4 << 655 G4double cut) 652 { 656 { 653 G4double res = 0.0; 657 G4double res = 0.0; 654 if(UpdateParticle(p, kinEnergy)) { 658 if(UpdateParticle(p, kinEnergy)) { 655 CheckMaterial(Z); << 656 if(FindEmModel(p, processName, kinEnergy)) 659 if(FindEmModel(p, processName, kinEnergy)) { 657 G4double e = kinEnergy; 660 G4double e = kinEnergy; 658 G4double aCut = std::max(cut, theParamet << 661 if(baseParticle) { 659 if(nullptr != baseParticle) { << 662 e *= kinEnergy*massRatio; 660 e *= kinEnergy*massRatio; << 663 res = currentModel->ComputeCrossSectionPerAtom( 661 currentModel->InitialiseForElement(bas << 664 baseParticle, e, Z, A, cut) * chargeSquare; 662 res = << 663 currentModel->ComputeCrossSectionPer << 664 << 665 } else { 665 } else { 666 currentModel->InitialiseForElement(p, << 666 res = currentModel->ComputeCrossSectionPerAtom(p, e, Z, A, cut); 667 res = currentModel->ComputeCrossSectio << 668 } 667 } 669 if(verbose>0) { 668 if(verbose>0) { 670 G4cout << "E(MeV)= " << kinEnergy/MeV << 669 G4cout << "E(MeV)= " << kinEnergy/MeV 671 << " cross(barn)= " << res/barn << 670 << " cross(barn)= " << res/barn 672 << " " << p->GetParticleName( << 671 << " " << p->GetParticleName() 673 << " Z= " << Z << " shellIdx= << 672 << " Z= " << Z << " A= " << A/(g/mole) << " g/mole" 674 << " cut(keV)= " << aCut/keV << 675 << G4endl; 673 << G4endl; 676 } 674 } 677 } 675 } 678 } 676 } 679 return res; 677 return res; 680 } 678 } 681 679 682 //....oooOO0OOooo........oooOO0OOooo........oo 680 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 683 681 684 G4double << 682 G4double G4EmCalculator::ComputeCrossSectionPerAtom(G4double kinEnergy, 685 G4EmCalculator::ComputeGammaAttenuationLength( << 683 const G4String& particle, 686 << 684 const G4String& processName, 687 { << 685 const G4Element* elm, 688 G4double res = 0.0; << 686 G4double cut) 689 const G4ParticleDefinition* gamma = G4Gamma: << 687 { 690 res += ComputeCrossSectionPerVolume(kinEnerg << 688 return ComputeCrossSectionPerAtom(kinEnergy,FindParticle(particle), 691 res += ComputeCrossSectionPerVolume(kinEnerg << 689 processName, 692 res += ComputeCrossSectionPerVolume(kinEnerg << 690 elm->GetZ(),elm->GetN(),cut); 693 res += ComputeCrossSectionPerVolume(kinEnerg << 694 if(res > 0.0) { res = 1.0/res; } << 695 return res; << 696 } << 697 << 698 //....oooOO0OOooo........oooOO0OOooo........oo << 699 << 700 G4double G4EmCalculator::ComputeShellIonisatio << 701 const << 702 G4int << 703 G4Ato << 704 G4dou << 705 const << 706 { << 707 G4double res = 0.0; << 708 const G4ParticleDefinition* p = FindParticle << 709 G4VAtomDeexcitation* ad = manager->AtomDeexc << 710 if(p && ad) { << 711 res = ad->ComputeShellIonisationCrossSecti << 712 << 713 } << 714 return res; << 715 } 691 } 716 692 717 //....oooOO0OOooo........oooOO0OOooo........oo 693 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 718 694 719 G4double G4EmCalculator::ComputeMeanFreePath(G 695 G4double G4EmCalculator::ComputeMeanFreePath(G4double kinEnergy, 720 c 696 const G4ParticleDefinition* p, 721 c 697 const G4String& processName, 722 c << 698 const G4Material* mat, 723 G << 699 G4double cut) 724 { 700 { 725 G4double mfp = DBL_MAX; 701 G4double mfp = DBL_MAX; 726 G4double x = << 702 G4double x = ComputeCrossSectionPerVolume(kinEnergy, p, processName, mat, cut); 727 ComputeCrossSectionPerVolume(kinEnergy, p, << 703 if(x > 0.0) mfp = 1.0/x; 728 if(x > 0.0) { mfp = 1.0/x; } << 729 if(verbose>1) { 704 if(verbose>1) { 730 G4cout << "E(MeV)= " << kinEnergy/MeV 705 G4cout << "E(MeV)= " << kinEnergy/MeV 731 << " MFP(mm)= " << mfp/mm << 706 << " MFP(mm)= " << mfp/mm 732 << " " << p->GetParticleName() << 707 << " " << p->GetParticleName() 733 << " in " << mat->GetName() << 708 << " in " << mat->GetName() 734 << G4endl; << 709 << G4endl; 735 } 710 } 736 return mfp; 711 return mfp; 737 } 712 } 738 713 739 //....oooOO0OOooo........oooOO0OOooo........oo 714 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 740 715 >> 716 G4double G4EmCalculator::ComputeMeanFreePath(G4double kinEnergy, >> 717 const G4String& particle, >> 718 const G4String& processName, >> 719 const G4String& material, >> 720 G4double cut) >> 721 { >> 722 return ComputeMeanFreePath(kinEnergy,FindParticle(particle),processName, >> 723 FindMaterial(material),cut); >> 724 } >> 725 >> 726 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 727 741 G4double G4EmCalculator::ComputeEnergyCutFromR 728 G4double G4EmCalculator::ComputeEnergyCutFromRangeCut( 742 G4double range, 729 G4double range, 743 const G4ParticleDefin << 730 const G4ParticleDefinition* part, 744 const G4Material* mat << 731 const G4Material* mat) 745 { 732 { 746 return G4ProductionCutsTable::GetProductionC 733 return G4ProductionCutsTable::GetProductionCutsTable()-> 747 ConvertRangeToEnergy(part, mat, range); 734 ConvertRangeToEnergy(part, mat, range); 748 } 735 } 749 736 750 //....oooOO0OOooo........oooOO0OOooo........oo 737 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 751 738 >> 739 G4double G4EmCalculator::ComputeEnergyCutFromRangeCut( >> 740 G4double range, >> 741 const G4String& particle, >> 742 const G4String& material) >> 743 { >> 744 return ComputeEnergyCutFromRangeCut(range,FindParticle(particle), >> 745 FindMaterial(material)); >> 746 } >> 747 >> 748 >> 749 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 750 752 G4bool G4EmCalculator::UpdateParticle(const G4 751 G4bool G4EmCalculator::UpdateParticle(const G4ParticleDefinition* p, 753 G4double << 752 G4double kinEnergy) 754 { 753 { 755 if(p != currentParticle) { 754 if(p != currentParticle) { 756 755 757 // new particle 756 // new particle 758 currentParticle = p; 757 currentParticle = p; 759 dynParticle->SetDefinition(const_cast<G4Pa << 758 dynParticle.SetDefinition(const_cast<G4ParticleDefinition*>(p)); 760 dynParticle->SetKineticEnergy(kinEnergy); << 759 dynParticle.SetKineticEnergy(kinEnergy); 761 baseParticle = nullptr; << 760 baseParticle = 0; 762 currentParticleName = p->GetParticleName() 761 currentParticleName = p->GetParticleName(); 763 massRatio = 1.0; 762 massRatio = 1.0; 764 mass = p->GetPDGMass(); 763 mass = p->GetPDGMass(); 765 chargeSquare = 1.0; 764 chargeSquare = 1.0; 766 currentProcess = manager->GetEnergyLossPr << 765 currentProcess = FindEnergyLossProcess(p); 767 currentProcessName = ""; 766 currentProcessName = ""; 768 isIon = false; 767 isIon = false; 769 768 770 // ionisation process exist 769 // ionisation process exist 771 if(nullptr != currentProcess) { << 770 if(currentProcess) { 772 currentProcessName = currentProcess->Get 771 currentProcessName = currentProcess->GetProcessName(); 773 baseParticle = currentProcess->BaseParti 772 baseParticle = currentProcess->BaseParticle(); 774 if(currentProcessName == "ionIoni" && p- << 775 baseParticle = theGenericIon; << 776 isIon = true; << 777 } << 778 773 779 // base particle is used 774 // base particle is used 780 if(nullptr != baseParticle) { << 775 if(baseParticle) { 781 massRatio = baseParticle->GetPDGMass() << 776 massRatio = baseParticle->GetPDGMass()/p->GetPDGMass(); 782 G4double q = p->GetPDGCharge()/basePar << 777 G4double q = p->GetPDGCharge()/baseParticle->GetPDGCharge(); 783 chargeSquare = q*q; << 778 chargeSquare = q*q; 784 } 779 } >> 780 >> 781 if(p->GetParticleType() == "nucleus" >> 782 && currentParticleName != "deuteron" >> 783 && currentParticleName != "triton" >> 784 && currentParticleName != "alpha+" >> 785 && currentParticleName != "helium" >> 786 && currentParticleName != "hydrogen" >> 787 ) { >> 788 isIon = true; >> 789 massRatio = theGenericIon->GetPDGMass()/p->GetPDGMass(); >> 790 baseParticle = theGenericIon; >> 791 // G4cout << p->GetParticleName() >> 792 // << " in " << currentMaterial->GetName() >> 793 // << " e= " << kinEnergy << G4endl; >> 794 } 785 } 795 } 786 } 796 } >> 797 787 // Effective charge for ions 798 // Effective charge for ions 788 if(isIon && nullptr != currentProcess) { << 799 if(isIon) { 789 chargeSquare = 800 chargeSquare = 790 corr->EffectiveChargeSquareRatio(p, curr << 801 corr->EffectiveChargeSquareRatio(p, currentMaterial, kinEnergy) 791 currentProcess->SetDynamicMassCharge(massR << 802 * corr->EffectiveChargeCorrection(p,currentMaterial,kinEnergy); 792 if(verbose>1) { << 803 if(currentProcess) { 793 G4cout <<"\n NewIon: massR= "<< massRati << 804 currentProcess->SetDynamicMassCharge(massRatio,chargeSquare); 794 << chargeSquare << " " << currentProce << 805 //G4cout << "NewP: massR= " << massRatio << " q2= " << chargeSquare << G4endl; 795 } 806 } 796 } 807 } 797 return true; 808 return true; 798 } 809 } 799 810 800 //....oooOO0OOooo........oooOO0OOooo........oo 811 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 801 812 802 const G4ParticleDefinition* G4EmCalculator::Fi 813 const G4ParticleDefinition* G4EmCalculator::FindParticle(const G4String& name) 803 { 814 { 804 const G4ParticleDefinition* p = nullptr; << 815 const G4ParticleDefinition* p = 0; 805 if(name != currentParticleName) { 816 if(name != currentParticleName) { 806 p = G4ParticleTable::GetParticleTable()->F 817 p = G4ParticleTable::GetParticleTable()->FindParticle(name); 807 if(nullptr == p) { << 818 if(!p) { 808 G4cout << "### WARNING: G4EmCalculator:: 819 G4cout << "### WARNING: G4EmCalculator::FindParticle fails to find " 809 << name << G4endl; << 820 << name << G4endl; 810 } 821 } 811 } else { 822 } else { 812 p = currentParticle; 823 p = currentParticle; 813 } 824 } 814 return p; 825 return p; 815 } 826 } 816 827 817 //....oooOO0OOooo........oooOO0OOooo........oo 828 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 818 829 819 const G4ParticleDefinition* G4EmCalculator::Fi 830 const G4ParticleDefinition* G4EmCalculator::FindIon(G4int Z, G4int A) 820 { 831 { 821 const G4ParticleDefinition* p = ionTable->Ge << 832 const G4ParticleDefinition* p = >> 833 G4ParticleTable::GetParticleTable()->FindIon(Z,A,0,Z); 822 return p; 834 return p; 823 } 835 } 824 836 825 //....oooOO0OOooo........oooOO0OOooo........oo 837 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 826 838 827 const G4Material* G4EmCalculator::FindMaterial 839 const G4Material* G4EmCalculator::FindMaterial(const G4String& name) 828 { 840 { 829 if(name != currentMaterialName) { 841 if(name != currentMaterialName) { 830 SetupMaterial(G4Material::GetMaterial(name << 842 currentMaterial = G4Material::GetMaterial(name); 831 if(nullptr == currentMaterial) { << 843 currentMaterialName = name; >> 844 if(!currentMaterial) 832 G4cout << "### WARNING: G4EmCalculator:: 845 G4cout << "### WARNING: G4EmCalculator::FindMaterial fails to find " 833 << name << G4endl; << 846 << name << G4endl; 834 } << 835 } 847 } 836 return currentMaterial; 848 return currentMaterial; 837 } 849 } 838 850 839 //....oooOO0OOooo........oooOO0OOooo........oo 851 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 840 852 841 const G4Region* G4EmCalculator::FindRegion(con 853 const G4Region* G4EmCalculator::FindRegion(const G4String& reg) 842 { 854 { 843 return G4EmUtility::FindRegion(reg); << 855 const G4Region* r = 0; >> 856 if(reg != "" || reg != "world") >> 857 r = G4RegionStore::GetInstance()->GetRegion(reg); >> 858 else >> 859 r = G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld"); >> 860 return r; 844 } 861 } 845 862 846 //....oooOO0OOooo........oooOO0OOooo........oo 863 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 847 864 848 const G4MaterialCutsCouple* G4EmCalculator::Fi 865 const G4MaterialCutsCouple* G4EmCalculator::FindCouple( 849 const G4Material* << 866 const G4Material* material, 850 const G4Region* re << 867 const G4Region* region) 851 { 868 { 852 const G4MaterialCutsCouple* couple = nullptr << 869 if(!material) return 0; 853 SetupMaterial(material); << 870 currentMaterial = material; 854 if(nullptr != currentMaterial) { << 871 currentMaterialName = material->GetName(); 855 // Access to materials << 872 // Access to materials 856 const G4ProductionCutsTable* theCoupleTabl << 873 const G4ProductionCutsTable* theCoupleTable= 857 G4ProductionCutsTable::GetProductionCuts << 874 G4ProductionCutsTable::GetProductionCutsTable(); 858 const G4Region* r = region; << 875 const G4Region* r = region; 859 if(nullptr != r) { << 876 if(!r) 860 couple = theCoupleTable->GetMaterialCuts << 877 r = G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld"); 861 << 878 862 } else { << 879 return theCoupleTable->GetMaterialCutsCouple(material,r->GetProductionCuts()); 863 G4RegionStore* store = G4RegionStore::Ge << 880 864 std::size_t nr = store->size(); << 865 if(0 < nr) { << 866 for(std::size_t i=0; i<nr; ++i) { << 867 couple = theCoupleTable->GetMaterial << 868 material, ((*store)[i])->GetProduc << 869 if(nullptr != couple) { break; } << 870 } << 871 } << 872 } << 873 } << 874 if(nullptr == couple) { << 875 G4ExceptionDescription ed; << 876 ed << "G4EmCalculator::FindCouple: fail fo << 877 << currentMaterialName << ">"; << 878 if(region) { ed << " and region " << regio << 879 G4Exception("G4EmCalculator::FindCouple", << 880 FatalException, ed); << 881 } << 882 return couple; << 883 } 881 } 884 882 885 //....oooOO0OOooo........oooOO0OOooo........oo 883 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 886 884 887 G4bool G4EmCalculator::UpdateCouple(const G4Ma 885 G4bool G4EmCalculator::UpdateCouple(const G4Material* material, G4double cut) 888 { 886 { 889 SetupMaterial(material); << 887 if(!material) return false; 890 if(!currentMaterial) { return false; } << 888 currentMaterial = material; 891 for (G4int i=0; i<nLocalMaterials; ++i) { << 889 currentMaterialName = material->GetName(); >> 890 for (G4int i=0; i<nLocalMaterials; i++) { 892 if(material == localMaterials[i] && cut == 891 if(material == localMaterials[i] && cut == localCuts[i]) { 893 currentCouple = localCouples[i]; 892 currentCouple = localCouples[i]; 894 currentCoupleIndex = currentCouple->GetI 893 currentCoupleIndex = currentCouple->GetIndex(); 895 currentCut = cut; 894 currentCut = cut; 896 return true; 895 return true; 897 } 896 } 898 } 897 } 899 const G4MaterialCutsCouple* cc = new G4Mater 898 const G4MaterialCutsCouple* cc = new G4MaterialCutsCouple(material); 900 localMaterials.push_back(material); 899 localMaterials.push_back(material); 901 localCouples.push_back(cc); 900 localCouples.push_back(cc); 902 localCuts.push_back(cut); 901 localCuts.push_back(cut); 903 ++nLocalMaterials; << 902 nLocalMaterials++; 904 currentCouple = cc; 903 currentCouple = cc; 905 currentCoupleIndex = currentCouple->GetIndex 904 currentCoupleIndex = currentCouple->GetIndex(); 906 currentCut = cut; 905 currentCut = cut; 907 return true; 906 return true; 908 } 907 } 909 908 910 //....oooOO0OOooo........oooOO0OOooo........oo 909 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 911 910 912 void G4EmCalculator::FindLambdaTable(const G4P 911 void G4EmCalculator::FindLambdaTable(const G4ParticleDefinition* p, 913 const G4S << 912 const G4String& processName) 914 G4double << 915 { 913 { 916 // Search for the process 914 // Search for the process 917 if (!currentLambda || p != lambdaParticle || << 915 if (p != currentParticle || processName != currentName) { 918 lambdaName = processName; << 916 currentName = processName; 919 currentLambda = nullptr; << 917 currentLambda = 0; 920 lambdaParticle = p; << 918 921 isApplicable = false; << 919 G4String partname = p->GetParticleName(); 922 << 920 const G4ParticleDefinition* part = p; 923 const G4ParticleDefinition* part = (isIon) << 921 if(isIon) { part = theGenericIon; } 924 << 925 // Search for energy loss process << 926 currentName = processName; << 927 currentModel = nullptr; << 928 loweModel = nullptr; << 929 << 930 G4VEnergyLossProcess* elproc = FindEnLossP << 931 if(nullptr != elproc) { << 932 currentLambda = elproc->LambdaTable(); << 933 proctype = 0; << 934 if(nullptr != currentLambda) { << 935 isApplicable = true; << 936 if(verbose>1) { << 937 G4cout << "G4VEnergyLossProcess is f << 938 << G4endl; << 939 } << 940 } << 941 curProcess = elproc; << 942 return; << 943 } << 944 922 945 // Search for discrete process << 923 // energy loss process 946 G4VEmProcess* proc = FindDiscreteProcess(p << 924 G4LossTableManager* lManager = G4LossTableManager::Instance(); 947 if(nullptr != proc) { << 925 const std::vector<G4VEnergyLossProcess*> vel = 948 currentLambda = proc->LambdaTable(); << 926 lManager->GetEnergyLossProcessVector(); 949 proctype = 1; << 927 G4int n = vel.size(); 950 if(nullptr != currentLambda) { << 928 for(G4int i=0; i<n; i++) { 951 isApplicable = true; << 929 if((vel[i])->GetProcessName() == currentName && 952 if(verbose>1) { << 930 (vel[i])->Particle() == part) 953 G4cout << "G4VEmProcess is found out << 931 { >> 932 currentLambda = (vel[i])->LambdaTable(); >> 933 isApplicable = true; >> 934 break; >> 935 } >> 936 } >> 937 >> 938 // discrete process >> 939 if(!currentLambda) { >> 940 const std::vector<G4VEmProcess*> vem = lManager->GetEmProcessVector(); >> 941 G4int n = vem.size(); >> 942 for(G4int i=0; i<n; i++) { >> 943 if((vem[i])->GetProcessName() == currentName && >> 944 (vem[i])->Particle() == part) >> 945 { >> 946 currentLambda = (vem[i])->LambdaTable(); >> 947 isApplicable = true; >> 948 break; 954 } 949 } 955 } 950 } 956 curProcess = proc; << 957 return; << 958 } 951 } 959 952 960 // Search for msc process << 953 // msc process 961 G4VMultipleScattering* msc = FindMscProces << 954 if(!currentLambda) { 962 if(nullptr != msc) { << 955 const std::vector<G4VMultipleScattering*> vmsc = 963 currentModel = msc->SelectModel(kinEnerg << 956 lManager->GetMultipleScatteringVector(); 964 proctype = 2; << 957 G4int n = vmsc.size(); 965 if(nullptr != currentModel) { << 958 for(G4int i=0; i<n; i++) { 966 currentLambda = currentModel->GetCross << 959 if((vmsc[i])->GetProcessName() == currentName && 967 if(nullptr != currentLambda) { << 960 (vmsc[i])->Particle() == part) 968 isApplicable = true; << 961 { 969 if(verbose>1) { << 962 currentLambda = (vmsc[i])->LambdaTable(); 970 G4cout << "G4VMultipleScattering i << 963 isApplicable = true; 971 << G4endl; << 964 break; 972 } << 973 } 965 } 974 } 966 } 975 curProcess = msc; << 976 } 967 } 977 } 968 } 978 } 969 } 979 970 980 //....oooOO0OOooo........oooOO0OOooo........oo 971 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 981 972 982 G4bool G4EmCalculator::FindEmModel(const G4Par 973 G4bool G4EmCalculator::FindEmModel(const G4ParticleDefinition* p, 983 const G4Str 974 const G4String& processName, 984 G4 << 975 G4double kinEnergy) 985 { 976 { 986 isApplicable = false; 977 isApplicable = false; 987 if(nullptr == p || nullptr == currentMateria << 978 if(!p) { 988 G4cout << "G4EmCalculator::FindEmModel WAR << 979 G4cout << "G4EmCalculator::FindEmModel WARNING: no particle defined" 989 << " or materail defined; particle: << 980 << G4endl; 990 return isApplicable; 981 return isApplicable; 991 } 982 } 992 G4String partname = p->GetParticleName(); 983 G4String partname = p->GetParticleName(); >> 984 const G4ParticleDefinition* part = p; 993 G4double scaledEnergy = kinEnergy*massRatio; 985 G4double scaledEnergy = kinEnergy*massRatio; 994 const G4ParticleDefinition* part = (isIon) ? << 986 if(isIon) { part = theGenericIon; } 995 987 996 if(verbose > 1) { 988 if(verbose > 1) { 997 G4cout << "## G4EmCalculator::FindEmModel << 989 G4cout << "G4EmCalculator::FindEmModel for " << partname 998 << " (type= " << p->GetParticleType 990 << " (type= " << p->GetParticleType() 999 << ") and " << processName << " at << 991 << ") and " << processName << " at E(MeV)= " << scaledEnergy; 1000 << G4endl; << 992 if(p != part) G4cout << " GenericIon is the base particle"; 1001 if(p != part) { G4cout << " GenericIon i << 993 G4cout << G4endl; 1002 } 994 } 1003 995 1004 // Search for energy loss process 996 // Search for energy loss process 1005 currentName = processName; 997 currentName = processName; 1006 currentModel = nullptr; << 998 currentModel = 0; 1007 loweModel = nullptr; << 999 loweModel = 0; 1008 std::size_t idx = 0; << 1000 size_t idx = 0; 1009 << 1001 G4LossTableManager* lManager = G4LossTableManager::Instance(); 1010 G4VEnergyLossProcess* elproc = FindEnLossPr << 1002 const std::vector<G4VEnergyLossProcess*> vel = 1011 if(nullptr != elproc) { << 1003 lManager->GetEnergyLossProcessVector(); >> 1004 G4int n = vel.size(); >> 1005 G4VEnergyLossProcess* elproc = 0; >> 1006 for(G4int i=0; i<n; i++) { >> 1007 // G4cout << "i= " << i << " part= " >> 1008 // << (vel[i])->Particle()->GetParticleName() >> 1009 // << " proc= " << (vel[i])->GetProcessName() << G4endl; >> 1010 if((vel[i])->GetProcessName() == currentName) { >> 1011 if(baseParticle) { >> 1012 if((vel[i])->Particle() == baseParticle) { >> 1013 elproc = vel[i]; >> 1014 break; >> 1015 } >> 1016 } else { >> 1017 if((vel[i])->Particle() == part) { >> 1018 elproc = vel[i]; >> 1019 break; >> 1020 } >> 1021 } >> 1022 } >> 1023 } >> 1024 if(elproc) { 1012 currentModel = elproc->SelectModelForMate 1025 currentModel = elproc->SelectModelForMaterial(scaledEnergy, idx); 1013 currentModel->InitialiseForMaterial(part, << 1014 currentModel->SetupForMaterial(part, curr << 1015 G4double eth = currentModel->LowEnergyLim 1026 G4double eth = currentModel->LowEnergyLimit(); 1016 if(eth > 0.0) { 1027 if(eth > 0.0) { 1017 loweModel = elproc->SelectModelForMater 1028 loweModel = elproc->SelectModelForMaterial(eth - CLHEP::eV, idx); 1018 if(loweModel == currentModel) { loweMod << 1019 else { << 1020 loweModel->InitialiseForMaterial(part << 1021 loweModel->SetupForMaterial(part, cur << 1022 } << 1023 } 1029 } 1024 } 1030 } 1025 1031 1026 // Search for discrete process << 1032 // Search for discrete process 1027 if(nullptr == currentModel) { << 1033 if(!currentModel) { 1028 G4VEmProcess* proc = FindDiscreteProcess( << 1034 const std::vector<G4VEmProcess*> vem = lManager->GetEmProcessVector(); 1029 if(nullptr != proc) { << 1035 G4int n = vem.size(); 1030 currentModel = proc->SelectModelForMate << 1036 for(G4int i=0; i<n; i++) { 1031 currentModel->InitialiseForMaterial(par << 1037 if((vem[i])->GetProcessName() == currentName && 1032 currentModel->SetupForMaterial(part, cu << 1038 (vem[i])->Particle() == part) 1033 G4double eth = currentModel->LowEnergyL << 1039 { 1034 if(eth > 0.0) { << 1040 currentModel = (vem[i])->SelectModelForMaterial(kinEnergy, idx); 1035 loweModel = proc->SelectModelForMater << 1041 G4double eth = currentModel->LowEnergyLimit(); 1036 if(loweModel == currentModel) { loweM << 1042 if(eth > 0.0) { 1037 else { << 1043 loweModel = (vem[i])->SelectModelForMaterial(eth - CLHEP::eV, idx); 1038 loweModel->InitialiseForMaterial(pa << 1044 } 1039 loweModel->SetupForMaterial(part, c << 1045 break; 1040 } << 1041 } 1046 } 1042 } 1047 } 1043 } 1048 } 1044 1049 1045 // Search for msc process 1050 // Search for msc process 1046 if(nullptr == currentModel) { << 1051 if(!currentModel) { 1047 G4VMultipleScattering* proc = FindMscProc << 1052 const std::vector<G4VMultipleScattering*> vmsc = 1048 if(nullptr != proc) { << 1053 lManager->GetMultipleScatteringVector(); 1049 currentModel = proc->SelectModel(kinEne << 1054 G4int n = vmsc.size(); 1050 loweModel = nullptr; << 1055 for(G4int i=0; i<n; i++) { >> 1056 if((vmsc[i])->GetProcessName() == currentName && >> 1057 (vmsc[i])->Particle() == part) >> 1058 { >> 1059 currentModel = (vmsc[i])->SelectModelForMaterial(kinEnergy, idx); >> 1060 G4double eth = currentModel->LowEnergyLimit(); >> 1061 if(eth > 0.0) { >> 1062 loweModel = (vmsc[i])->SelectModelForMaterial(eth - CLHEP::eV, idx); >> 1063 } >> 1064 break; >> 1065 } 1051 } 1066 } 1052 } 1067 } 1053 if(nullptr != currentModel) { << 1068 if(currentModel) { 1054 if(loweModel == currentModel) { loweModel << 1069 if(loweModel == currentModel) { loweModel = 0; } 1055 isApplicable = true; 1070 isApplicable = true; 1056 currentModel->InitialiseForMaterial(part, << 1057 if(loweModel) { << 1058 loweModel->InitialiseForMaterial(part, << 1059 } << 1060 if(verbose > 1) { 1071 if(verbose > 1) { 1061 G4cout << " Model <" << currentModel- << 1072 G4cout << "Model <" << currentModel->GetName() 1062 << "> Emin(MeV)= " << currentMod << 1073 << "> Emin(MeV)= " << currentModel->LowEnergyLimit()/MeV; 1063 << " for " << part->GetParticleN << 1074 if(loweModel) { 1064 if(nullptr != elproc) { << 1075 G4cout << " LowEnergy model <" << loweModel->GetName() << ">"; 1065 G4cout << " and " << elproc->GetProce << 1066 << G4endl; << 1067 } << 1068 if(nullptr != loweModel) { << 1069 G4cout << " LowEnergy model <" << low << 1070 } 1076 } 1071 G4cout << G4endl; 1077 G4cout << G4endl; 1072 } 1078 } 1073 } 1079 } 1074 return isApplicable; 1080 return isApplicable; 1075 } 1081 } 1076 1082 1077 //....oooOO0OOooo........oooOO0OOooo........o 1083 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1078 1084 1079 G4VEnergyLossProcess* << 1085 G4VEnergyLossProcess* G4EmCalculator::FindEnergyLossProcess( 1080 G4EmCalculator::FindEnLossProcess(const G4Par << 1086 const G4ParticleDefinition* p) 1081 const G4Str << 1082 { << 1083 G4VEnergyLossProcess* proc = nullptr; << 1084 const std::vector<G4VEnergyLossProcess*> v << 1085 manager->GetEnergyLossProcessVector(); << 1086 std::size_t n = v.size(); << 1087 for(std::size_t i=0; i<n; ++i) { << 1088 if((v[i])->GetProcessName() == processNam << 1089 auto p = static_cast<G4VProcess*>(v[i]) << 1090 if(ActiveForParticle(part, p)) { << 1091 proc = v[i]; << 1092 break; << 1093 } << 1094 } << 1095 } << 1096 return proc; << 1097 } << 1098 << 1099 //....oooOO0OOooo........oooOO0OOooo........o << 1100 << 1101 G4VEmProcess* << 1102 G4EmCalculator::FindDiscreteProcess(const G4P << 1103 const G4S << 1104 { << 1105 G4VEmProcess* proc = nullptr; << 1106 auto v = manager->GetEmProcessVector(); << 1107 std::size_t n = v.size(); << 1108 for(std::size_t i=0; i<n; ++i) { << 1109 const G4String& pName = v[i]->GetProcessN << 1110 if(pName == "GammaGeneralProc") { << 1111 proc = v[i]->GetEmProcess(processName); << 1112 break; << 1113 } else if(pName == processName) { << 1114 const auto p = static_cast<G4VProcess*> << 1115 if(ActiveForParticle(part, p)) { << 1116 proc = v[i]; << 1117 break; << 1118 } << 1119 } << 1120 } << 1121 return proc; << 1122 } << 1123 << 1124 //....oooOO0OOooo........oooOO0OOooo........o << 1125 << 1126 G4VMultipleScattering* << 1127 G4EmCalculator::FindMscProcess(const G4Partic << 1128 const G4String << 1129 { << 1130 G4VMultipleScattering* proc = nullptr; << 1131 const std::vector<G4VMultipleScattering*> v << 1132 manager->GetMultipleScatteringVector(); << 1133 std::size_t n = v.size(); << 1134 for(std::size_t i=0; i<n; ++i) { << 1135 if((v[i])->GetProcessName() == processNam << 1136 auto p = static_cast<G4VProcess*>(v[i]) << 1137 if(ActiveForParticle(part, p)) { << 1138 proc = v[i]; << 1139 break; << 1140 } << 1141 } << 1142 } << 1143 return proc; << 1144 } << 1145 << 1146 //....oooOO0OOooo........oooOO0OOooo........o << 1147 << 1148 G4VProcess* G4EmCalculator::FindProcess(const << 1149 const << 1150 { << 1151 G4VProcess* proc = nullptr; << 1152 const G4ProcessManager* procman = part->Get << 1153 G4ProcessVector* pv = procman->GetProcessLi << 1154 G4int nproc = (G4int)pv->size(); << 1155 for(G4int i=0; i<nproc; ++i) { << 1156 if(processName == (*pv)[i]->GetProcessNam << 1157 proc = (*pv)[i]; << 1158 break; << 1159 } << 1160 } << 1161 return proc; << 1162 } << 1163 << 1164 //....oooOO0OOooo........oooOO0OOooo........o << 1165 << 1166 G4bool G4EmCalculator::ActiveForParticle(cons << 1167 G4VP << 1168 { 1087 { 1169 G4ProcessManager* pm = part->GetProcessMana << 1088 G4VEnergyLossProcess* elp = 0; 1170 G4ProcessVector* pv = pm->GetProcessList(); << 1089 G4String partname = p->GetParticleName(); 1171 G4int n = (G4int)pv->size(); << 1090 const G4ParticleDefinition* part = p; 1172 G4bool res = false; << 1091 1173 for(G4int i=0; i<n; ++i) { << 1092 if(p->GetParticleType() == "nucleus" 1174 if((*pv)[i] == proc) { << 1093 && currentParticleName != "deuteron" 1175 if(pm->GetProcessActivation(i)) { res = << 1094 && currentParticleName != "triton" >> 1095 && currentParticleName != "alpha+" >> 1096 && currentParticleName != "helium" >> 1097 && currentParticleName != "hydrogen" >> 1098 ) { part = theGenericIon; } >> 1099 >> 1100 G4LossTableManager* lManager = G4LossTableManager::Instance(); >> 1101 const std::vector<G4VEnergyLossProcess*> vel = >> 1102 lManager->GetEnergyLossProcessVector(); >> 1103 G4int n = vel.size(); >> 1104 for(G4int i=0; i<n; i++) { >> 1105 if( (vel[i])->Particle() == part ) { >> 1106 elp = vel[i]; 1176 break; 1107 break; 1177 } 1108 } 1178 } 1109 } 1179 return res; << 1110 return elp; 1180 } << 1181 << 1182 //....oooOO0OOooo........oooOO0OOooo........o << 1183 << 1184 void G4EmCalculator::SetupMaterial(const G4Ma << 1185 { << 1186 if(mat) { << 1187 currentMaterial = mat; << 1188 currentMaterialName = mat->GetName(); << 1189 } else { << 1190 currentMaterial = nullptr; << 1191 currentMaterialName = ""; << 1192 } << 1193 } << 1194 << 1195 //....oooOO0OOooo........oooOO0OOooo........o << 1196 << 1197 void G4EmCalculator::SetupMaterial(const G4St << 1198 { << 1199 SetupMaterial(nist->FindOrBuildMaterial(mna << 1200 } << 1201 << 1202 //....oooOO0OOooo........oooOO0OOooo........o << 1203 << 1204 void G4EmCalculator::CheckMaterial(G4int Z) << 1205 { << 1206 G4bool isFound = false; << 1207 if(nullptr != currentMaterial) { << 1208 G4int nn = (G4int)currentMaterial->GetNum << 1209 for(G4int i=0; i<nn; ++i) { << 1210 if(Z == currentMaterial->GetElement(i)- << 1211 isFound = true; << 1212 break; << 1213 } << 1214 } << 1215 } << 1216 if(!isFound) { << 1217 SetupMaterial(nist->FindOrBuildSimpleMate << 1218 } << 1219 } 1111 } 1220 1112 1221 //....oooOO0OOooo........oooOO0OOooo........o 1113 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1222 1114 1223 void G4EmCalculator::SetVerbose(G4int verb) 1115 void G4EmCalculator::SetVerbose(G4int verb) 1224 { 1116 { 1225 verbose = verb; 1117 verbose = verb; 1226 } 1118 } 1227 1119 1228 //....oooOO0OOooo........oooOO0OOooo........o 1120 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1229 1121 1230 1122