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