Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // ------------------------------------------- 26 // ------------------------------------------------------------------- 27 // 27 // 28 // GEANT4 Class file 28 // GEANT4 Class file 29 // 29 // 30 // 30 // 31 // File name: G4VEmProcess 31 // File name: G4VEmProcess 32 // 32 // 33 // Author: Vladimir Ivanchenko on base 33 // Author: Vladimir Ivanchenko on base of Laszlo Urban code 34 // 34 // 35 // Creation date: 01.10.2003 35 // Creation date: 01.10.2003 36 // 36 // 37 // Modifications: by V.Ivanchenko 37 // Modifications: by V.Ivanchenko 38 // 38 // 39 // Class Description: based class for discrete 39 // Class Description: based class for discrete and rest/discrete EM processes 40 // 40 // 41 41 42 // ------------------------------------------- 42 // ------------------------------------------------------------------- 43 // 43 // 44 //....oooOO0OOooo........oooOO0OOooo........oo 44 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 45 //....oooOO0OOooo........oooOO0OOooo........oo 45 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 46 46 47 #include "G4VEmProcess.hh" 47 #include "G4VEmProcess.hh" 48 #include "G4PhysicalConstants.hh" 48 #include "G4PhysicalConstants.hh" 49 #include "G4SystemOfUnits.hh" 49 #include "G4SystemOfUnits.hh" 50 #include "G4ProcessManager.hh" 50 #include "G4ProcessManager.hh" 51 #include "G4LossTableManager.hh" 51 #include "G4LossTableManager.hh" 52 #include "G4LossTableBuilder.hh" 52 #include "G4LossTableBuilder.hh" 53 #include "G4Step.hh" 53 #include "G4Step.hh" 54 #include "G4ParticleDefinition.hh" 54 #include "G4ParticleDefinition.hh" 55 #include "G4VEmModel.hh" 55 #include "G4VEmModel.hh" 56 #include "G4DataVector.hh" 56 #include "G4DataVector.hh" 57 #include "G4PhysicsTable.hh" 57 #include "G4PhysicsTable.hh" 58 #include "G4EmDataHandler.hh" 58 #include "G4EmDataHandler.hh" 59 #include "G4PhysicsLogVector.hh" 59 #include "G4PhysicsLogVector.hh" 60 #include "G4VParticleChange.hh" 60 #include "G4VParticleChange.hh" 61 #include "G4ProductionCutsTable.hh" 61 #include "G4ProductionCutsTable.hh" 62 #include "G4Region.hh" 62 #include "G4Region.hh" 63 #include "G4Gamma.hh" 63 #include "G4Gamma.hh" 64 #include "G4Electron.hh" 64 #include "G4Electron.hh" 65 #include "G4Positron.hh" 65 #include "G4Positron.hh" 66 #include "G4PhysicsTableHelper.hh" 66 #include "G4PhysicsTableHelper.hh" 67 #include "G4EmBiasingManager.hh" 67 #include "G4EmBiasingManager.hh" 68 #include "G4EmParameters.hh" << 69 #include "G4EmProcessSubType.hh" << 70 #include "G4EmTableUtil.hh" << 71 #include "G4EmUtility.hh" << 72 #include "G4DNAModelSubType.hh" << 73 #include "G4GenericIon.hh" 68 #include "G4GenericIon.hh" 74 #include "G4Log.hh" 69 #include "G4Log.hh" 75 #include <iostream> 70 #include <iostream> 76 71 77 //....oooOO0OOooo........oooOO0OOooo........oo 72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 78 73 79 G4VEmProcess::G4VEmProcess(const G4String& nam 74 G4VEmProcess::G4VEmProcess(const G4String& name, G4ProcessType type): 80 G4VDiscreteProcess(name, type) << 75 G4VDiscreteProcess(name, type), >> 76 secondaryParticle(nullptr), >> 77 buildLambdaTable(true), >> 78 numberOfModels(0), >> 79 theLambdaTable(nullptr), >> 80 theLambdaTablePrim(nullptr), >> 81 integral(false), >> 82 applyCuts(false), >> 83 startFromNull(false), >> 84 splineFlag(true), >> 85 isIon(false), >> 86 currentCouple(nullptr), >> 87 isTheMaster(true), >> 88 masterProc(nullptr), >> 89 theData(nullptr), >> 90 currentModel(nullptr), >> 91 particle(nullptr), >> 92 currentParticle(nullptr) 81 { 93 { 82 theParameters = G4EmParameters::Instance(); 94 theParameters = G4EmParameters::Instance(); 83 SetVerboseLevel(1); 95 SetVerboseLevel(1); 84 96 85 // Size of tables << 97 // Size of tables assuming spline 86 minKinEnergy = 0.1*CLHEP::keV; << 98 minKinEnergy = 0.1*keV; 87 maxKinEnergy = 100.0*CLHEP::TeV; << 99 maxKinEnergy = 100.0*TeV; >> 100 nLambdaBins = 84; >> 101 minKinEnergyPrim = DBL_MAX; >> 102 actBinning = actSpline = actMinKinEnergy = actMaxKinEnergy = false; 88 103 89 // default lambda factor 104 // default lambda factor 90 invLambdaFactor = 1.0/lambdaFactor; << 105 lambdaFactor = 0.8; >> 106 logLambdaFactor = G4Log(lambdaFactor); >> 107 >> 108 // default limit on polar angle >> 109 biasFactor = fFactor = 1.0; 91 110 92 // particle types 111 // particle types 93 theGamma = G4Gamma::Gamma(); << 112 theGamma = G4Gamma::Gamma(); 94 theElectron = G4Electron::Electron(); << 113 theElectron = G4Electron::Electron(); 95 thePositron = G4Positron::Positron(); << 114 thePositron = G4Positron::Positron(); >> 115 >> 116 theCuts = theCutsGamma = theCutsElectron = theCutsPositron = nullptr; 96 117 97 pParticleChange = &fParticleChange; 118 pParticleChange = &fParticleChange; 98 fParticleChange.SetSecondaryWeightByProcess( 119 fParticleChange.SetSecondaryWeightByProcess(true); 99 secParticles.reserve(5); 120 secParticles.reserve(5); 100 121 >> 122 baseMaterial = currentMaterial = nullptr; >> 123 >> 124 preStepLambda = preStepKinEnergy = 0.0; >> 125 preStepLogKinEnergy = LOG_EKIN_MIN; >> 126 mfpKinEnergy = DBL_MAX; >> 127 massRatio = 1.0; >> 128 >> 129 idxLambda = idxLambdaPrim = currentCoupleIndex = basedCoupleIndex = 0; >> 130 101 modelManager = new G4EmModelManager(); 131 modelManager = new G4EmModelManager(); >> 132 biasManager = nullptr; >> 133 biasFlag = false; >> 134 weightFlag = false; 102 lManager = G4LossTableManager::Instance(); 135 lManager = G4LossTableManager::Instance(); 103 lManager->Register(this); 136 lManager->Register(this); 104 isTheMaster = lManager->IsMaster(); << 105 G4LossTableBuilder* bld = lManager->GetTable 137 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 106 theDensityFactor = bld->GetDensityFactors(); 138 theDensityFactor = bld->GetDensityFactors(); 107 theDensityIdx = bld->GetCoupleIndexes(); 139 theDensityIdx = bld->GetCoupleIndexes(); >> 140 >> 141 secID = fluoID = augerID = biasID = -1; >> 142 mainSecondaries = 100; >> 143 if("phot" == GetProcessName() || "compt" == GetProcessName() >> 144 || "e-_G4DNAIonisation" == GetProcessName() >> 145 || "hydrogen_G4DNAIonisation" == GetProcessName() >> 146 || "helium_G4DNAIonisation" == GetProcessName() >> 147 || "alpha_G4DNAIonisation" == GetProcessName() >> 148 || "alpha+_G4DNAIonisation" == GetProcessName() >> 149 || "proton_G4DNAIonisation" == GetProcessName() >> 150 || "GenericIon_G4DNAIonisation" == GetProcessName() ) >> 151 { >> 152 mainSecondaries = 1; >> 153 } 108 } 154 } 109 155 110 //....oooOO0OOooo........oooOO0OOooo........oo 156 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 111 157 112 G4VEmProcess::~G4VEmProcess() 158 G4VEmProcess::~G4VEmProcess() 113 { 159 { >> 160 /* >> 161 if(1 < verboseLevel) { >> 162 G4cout << "G4VEmProcess destruct " << GetProcessName() >> 163 << " " << this << " " << theLambdaTable <<G4endl; >> 164 } >> 165 */ 114 if(isTheMaster) { 166 if(isTheMaster) { 115 delete theData; 167 delete theData; 116 delete theEnergyOfCrossSectionMax; << 168 theData = nullptr; 117 } 169 } 118 delete modelManager; 170 delete modelManager; 119 delete biasManager; 171 delete biasManager; 120 lManager->DeRegister(this); 172 lManager->DeRegister(this); >> 173 //std::cout << "G4VEmProcess removed " << GetProcessName() << G4endl; >> 174 } >> 175 >> 176 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 177 >> 178 void G4VEmProcess::Clear() >> 179 { >> 180 currentCouple = nullptr; >> 181 preStepLambda = 0.0; >> 182 idxLambda = idxLambdaPrim = 0; 121 } 183 } 122 184 123 //....oooOO0OOooo........oooOO0OOooo........oo 185 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 124 186 125 void G4VEmProcess::AddEmModel(G4int order, G4V << 187 G4double G4VEmProcess::MinPrimaryEnergy(const G4ParticleDefinition*, >> 188 const G4Material*) >> 189 { >> 190 return 0.0; >> 191 } >> 192 >> 193 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 194 >> 195 void G4VEmProcess::AddEmModel(G4int order, G4VEmModel* p, 126 const G4Region* 196 const G4Region* region) 127 { 197 { 128 if(nullptr == ptr) { return; } << 129 G4VEmFluctuationModel* fm = nullptr; 198 G4VEmFluctuationModel* fm = nullptr; 130 modelManager->AddEmModel(order, ptr, fm, reg << 199 modelManager->AddEmModel(order, p, fm, region); 131 ptr->SetParticleChange(pParticleChange); << 200 if(p) { p->SetParticleChange(pParticleChange); } 132 } 201 } 133 202 134 //....oooOO0OOooo........oooOO0OOooo........oo 203 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 135 204 136 void G4VEmProcess::SetEmModel(G4VEmModel* ptr, 205 void G4VEmProcess::SetEmModel(G4VEmModel* ptr, G4int) 137 { 206 { 138 if(nullptr == ptr) { return; } << 207 for(auto & em : emModels) { if(em == ptr) { return; } } 139 if(!emModels.empty()) { << 208 emModels.push_back(ptr); 140 for(auto & em : emModels) { if(em == ptr) << 209 } 141 } << 210 142 emModels.push_back(ptr); << 211 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 212 >> 213 G4VEmModel* G4VEmProcess::EmModel(size_t index) const >> 214 { >> 215 return (index < emModels.size()) ? emModels[index] : nullptr; >> 216 } >> 217 >> 218 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 219 >> 220 void G4VEmProcess::UpdateEmModel(const G4String& nam, >> 221 G4double emin, G4double emax) >> 222 { >> 223 modelManager->UpdateEmModel(nam, emin, emax); >> 224 } >> 225 >> 226 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 227 >> 228 G4int G4VEmProcess::GetNumberOfModels() const >> 229 { >> 230 return modelManager->NumberOfModels(); >> 231 } >> 232 >> 233 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 234 >> 235 G4int G4VEmProcess::GetNumberOfRegionModels(size_t couple_index) const >> 236 { >> 237 return modelManager->NumberOfRegionModels(couple_index); >> 238 } >> 239 >> 240 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 241 >> 242 G4VEmModel* G4VEmProcess::GetRegionModel(G4int idx, size_t couple_index) const >> 243 { >> 244 return modelManager->GetRegionModel(idx, couple_index); >> 245 } >> 246 >> 247 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 248 >> 249 G4VEmModel* G4VEmProcess::GetModelByIndex(G4int idx, G4bool ver) const >> 250 { >> 251 return modelManager->GetModel(idx, ver); 143 } 252 } 144 253 145 //....oooOO0OOooo........oooOO0OOooo........oo 254 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 146 255 147 void G4VEmProcess::PreparePhysicsTable(const G 256 void G4VEmProcess::PreparePhysicsTable(const G4ParticleDefinition& part) 148 { 257 { 149 if(nullptr == particle) { SetParticle(&part) << 258 isTheMaster = lManager->IsMaster(); >> 259 >> 260 if(!particle) { SetParticle(&part); } 150 261 151 if(part.GetParticleType() == "nucleus" && 262 if(part.GetParticleType() == "nucleus" && 152 part.GetParticleSubType() == "generic") { 263 part.GetParticleSubType() == "generic") { 153 264 154 G4String pname = part.GetParticleName(); 265 G4String pname = part.GetParticleName(); 155 if(pname != "deuteron" && pname != "triton 266 if(pname != "deuteron" && pname != "triton" && 156 pname != "He3" && pname != "alpha" && p << 267 pname != "alpha" && pname != "He3" && 157 pname != "helium" && pname != "hydrogen << 268 pname != "alpha+" && pname != "helium" && >> 269 pname != "hydrogen") { 158 270 159 particle = G4GenericIon::GenericIon(); 271 particle = G4GenericIon::GenericIon(); 160 isIon = true; 272 isIon = true; 161 } 273 } 162 } 274 } >> 275 >> 276 if(1 < verboseLevel) { >> 277 G4cout << "G4VEmProcess::PreparePhysicsTable() for " >> 278 << GetProcessName() >> 279 << " and particle " << part.GetParticleName() >> 280 << " local particle " << particle->GetParticleName() >> 281 << G4endl; >> 282 } >> 283 163 if(particle != &part) { return; } 284 if(particle != &part) { return; } 164 285 165 lManager->PreparePhysicsTable(&part, this); << 286 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 166 287 167 // for new run << 288 lManager->PreparePhysicsTable(&part, this, isTheMaster); 168 currentCouple = nullptr; << 169 preStepLambda = 0.0; << 170 fLambdaEnergy = 0.0; << 171 289 >> 290 Clear(); 172 InitialiseProcess(particle); 291 InitialiseProcess(particle); 173 292 174 G4LossTableBuilder* bld = lManager->GetTable << 175 const G4ProductionCutsTable* theCoupleTable= 293 const G4ProductionCutsTable* theCoupleTable= 176 G4ProductionCutsTable::GetProductionCutsTa 294 G4ProductionCutsTable::GetProductionCutsTable(); 177 theCutsGamma = theCoupleTable->GetEnergyC << 295 size_t n = theCoupleTable->GetTableSize(); 178 theCutsElectron = theCoupleTable->GetEnergyC << 296 179 theCutsPositron = theCoupleTable->GetEnergyC << 297 theEnergyOfCrossSectionMax.resize(n, 0.0); >> 298 theCrossSectionMax.resize(n, DBL_MAX); 180 299 181 // initialisation of the process 300 // initialisation of the process 182 if(!actMinKinEnergy) { minKinEnergy = thePar 301 if(!actMinKinEnergy) { minKinEnergy = theParameters->MinKinEnergy(); } 183 if(!actMaxKinEnergy) { maxKinEnergy = thePar 302 if(!actMaxKinEnergy) { maxKinEnergy = theParameters->MaxKinEnergy(); } >> 303 if(!actSpline) { splineFlag = theParameters->Spline(); } 184 304 >> 305 if(isTheMaster) { >> 306 SetVerboseLevel(theParameters->Verbose()); >> 307 if(!theData) { theData = new G4EmDataHandler(2); } >> 308 } else { >> 309 SetVerboseLevel(theParameters->WorkerVerbose()); >> 310 } 185 applyCuts = theParameters->ApplyCuts() 311 applyCuts = theParameters->ApplyCuts(); 186 lambdaFactor = theParameters->LambdaFacto 312 lambdaFactor = theParameters->LambdaFactor(); 187 invLambdaFactor = 1.0/lambdaFactor; << 313 logLambdaFactor = G4Log(lambdaFactor); 188 theParameters->DefineRegParamForEM(this); 314 theParameters->DefineRegParamForEM(this); 189 315 190 // integral option may be disabled << 316 // initialisation of models 191 if(!theParameters->Integral()) { fXSType = f << 317 numberOfModels = modelManager->NumberOfModels(); 192 << 318 for(G4int i=0; i<numberOfModels; ++i) { 193 // prepare tables << 319 G4VEmModel* mod = modelManager->GetModel(i); 194 if(isTheMaster) { << 320 if(0 == i) { currentModel = mod; } 195 if(nullptr == theData) { theData = new G4E << 321 mod->SetPolarAngleLimit(theParameters->MscThetaLimit()); 196 << 322 mod->SetMasterThread(isTheMaster); 197 if(buildLambdaTable) { << 323 if(mod->HighEnergyLimit() > maxKinEnergy) { 198 theLambdaTable = theData->MakeTable(0); << 324 mod->SetHighEnergyLimit(maxKinEnergy); 199 bld->InitialiseBaseMaterials(theLambdaTa << 200 } << 201 // high energy table << 202 if(minKinEnergyPrim < maxKinEnergy) { << 203 theLambdaTablePrim = theData->MakeTable( << 204 bld->InitialiseBaseMaterials(theLambdaTa << 205 } 325 } 206 } 326 } 207 // models << 327 208 baseMat = bld->GetBaseMaterialFlag(); << 328 if(lManager->AtomDeexcitation()) { modelManager->SetFluoFlag(true); } 209 numberOfModels = modelManager->NumberOfModel << 329 theCuts = modelManager->Initialise(particle,secondaryParticle, 210 currentModel = modelManager->GetModel(0); << 330 2.,verboseLevel); 211 if(nullptr != lManager->AtomDeexcitation()) << 331 theCutsGamma = theCoupleTable->GetEnergyCutsVector(idxG4GammaCut); 212 modelManager->SetFluoFlag(true); << 332 theCutsElectron = theCoupleTable->GetEnergyCutsVector(idxG4ElectronCut); >> 333 theCutsPositron = theCoupleTable->GetEnergyCutsVector(idxG4PositronCut); >> 334 >> 335 // prepare tables >> 336 if(buildLambdaTable && isTheMaster){ >> 337 theLambdaTable = theData->MakeTable(0); >> 338 bld->InitialiseBaseMaterials(theLambdaTable); >> 339 } >> 340 // high energy table >> 341 if(isTheMaster && minKinEnergyPrim < maxKinEnergy){ >> 342 theLambdaTablePrim = theData->MakeTable(1); >> 343 bld->InitialiseBaseMaterials(theLambdaTablePrim); 213 } 344 } >> 345 bld->InitialiseBaseMaterials(); 214 // forced biasing 346 // forced biasing 215 if(nullptr != biasManager) { << 347 if(biasManager) { 216 biasManager->Initialise(part, GetProcessNa << 348 biasManager->Initialise(part,GetProcessName(),verboseLevel); 217 biasFlag = false; << 349 biasFlag = false; 218 } << 350 } 219 << 351 // defined ID of secondary particles 220 theCuts = << 352 G4String nam1 = GetProcessName(); 221 G4EmTableUtil::PrepareEmProcess(this, part << 353 secID = G4PhysicsModelCatalog::Register(nam1); 222 modelManag << 354 if(100 > mainSecondaries) { 223 secID, tri << 355 G4String nam2 = nam1 + "_fluo" ; 224 verboseLev << 356 G4String nam3 = nam1 + "_auger"; >> 357 G4String nam4 = nam1 + "_split"; >> 358 fluoID = G4PhysicsModelCatalog::Register(nam2); >> 359 augerID = G4PhysicsModelCatalog::Register(nam3); >> 360 biasID = G4PhysicsModelCatalog::Register(nam4); >> 361 } 225 } 362 } 226 363 227 //....oooOO0OOooo........oooOO0OOooo........oo 364 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 228 365 229 void G4VEmProcess::BuildPhysicsTable(const G4P 366 void G4VEmProcess::BuildPhysicsTable(const G4ParticleDefinition& part) 230 { 367 { 231 if(nullptr == masterProc) { << 368 if(!masterProc) { 232 if(isTheMaster) { masterProc = this; } 369 if(isTheMaster) { masterProc = this; } 233 else { masterProc = static_cast<const G4VE 370 else { masterProc = static_cast<const G4VEmProcess*>(GetMasterProcess());} 234 } 371 } 235 G4int nModels = modelManager->NumberOfModels << 372 236 G4bool isLocked = theParameters->IsPrintLock << 373 G4String num = part.GetParticleName(); 237 G4bool toBuild = (buildLambdaTable || minKin << 374 if(1 < verboseLevel) { 238 << 375 G4cout << "### G4VEmProcess::BuildPhysicsTable() for " 239 G4EmTableUtil::BuildEmProcess(this, masterPr << 376 << GetProcessName() 240 nModels, verbo << 377 << " and particle " << num 241 isLocked, toBu << 378 << " buildLambdaTable= " << buildLambdaTable >> 379 << " isTheMaster= " << isTheMaster >> 380 << " " << masterProc >> 381 << G4endl; >> 382 } >> 383 >> 384 if(particle == &part) { >> 385 >> 386 // worker initialisation >> 387 if(!isTheMaster) { >> 388 theLambdaTable = masterProc->LambdaTable(); >> 389 theLambdaTablePrim = masterProc->LambdaTablePrim(); >> 390 >> 391 if(theLambdaTable) { FindLambdaMax(); } >> 392 >> 393 // local initialisation of models >> 394 G4bool printing = true; >> 395 numberOfModels = modelManager->NumberOfModels(); >> 396 for(G4int i=0; i<numberOfModels; ++i) { >> 397 G4VEmModel* mod = GetModelByIndex(i, printing); >> 398 G4VEmModel* mod0= masterProc->GetModelByIndex(i, printing); >> 399 //G4cout << i << ". " << mod << " " << mod0 << " " >> 400 // << particle->GetParticleName() << G4endl; >> 401 mod->InitialiseLocal(particle, mod0); >> 402 } >> 403 // master thread >> 404 } else { >> 405 if(buildLambdaTable || minKinEnergyPrim < maxKinEnergy) { >> 406 BuildLambdaTable(); >> 407 } >> 408 } >> 409 } >> 410 >> 411 // explicitly defined printout by particle name >> 412 if(1 < verboseLevel || >> 413 (0 < verboseLevel && (num == "gamma" || num == "e-" || >> 414 num == "e+" || num == "mu+" || >> 415 num == "mu-" || num == "proton"|| >> 416 num == "pi+" || num == "pi-" || >> 417 num == "kaon+" || num == "kaon-" || >> 418 num == "alpha" || num == "anti_proton" || >> 419 num == "GenericIon"|| num == "alpha++" || >> 420 num == "alpha+" || num == "helium" || >> 421 num == "hydrogen"))) >> 422 { >> 423 StreamInfo(G4cout, part); >> 424 } >> 425 >> 426 if(1 < verboseLevel) { >> 427 G4cout << "### G4VEmProcess::BuildPhysicsTable() done for " >> 428 << GetProcessName() >> 429 << " and particle " << num >> 430 << G4endl; >> 431 } 242 } 432 } 243 433 244 //....oooOO0OOooo........oooOO0OOooo........oo 434 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 245 435 246 void G4VEmProcess::BuildLambdaTable() 436 void G4VEmProcess::BuildLambdaTable() 247 { 437 { >> 438 if(1 < verboseLevel) { >> 439 G4cout << "G4EmProcess::BuildLambdaTable() for process " >> 440 << GetProcessName() << " and particle " >> 441 << particle->GetParticleName() << " " << this >> 442 << G4endl; >> 443 } >> 444 >> 445 // Access to materials >> 446 const G4ProductionCutsTable* theCoupleTable= >> 447 G4ProductionCutsTable::GetProductionCutsTable(); >> 448 size_t numOfCouples = theCoupleTable->GetTableSize(); >> 449 >> 450 G4LossTableBuilder* bld = lManager->GetTableBuilder(); >> 451 >> 452 G4PhysicsLogVector* aVector = nullptr; >> 453 G4PhysicsLogVector* aVectorPrim = nullptr; >> 454 G4PhysicsLogVector* bVectorPrim = nullptr; >> 455 248 G4double scale = theParameters->MaxKinEnergy 456 G4double scale = theParameters->MaxKinEnergy()/theParameters->MinKinEnergy(); 249 G4int nbin = 457 G4int nbin = 250 theParameters->NumberOfBinsPerDecade()*G4l 458 theParameters->NumberOfBinsPerDecade()*G4lrint(std::log10(scale)); >> 459 scale = G4Log(scale); 251 if(actBinning) { nbin = std::max(nbin, nLamb 460 if(actBinning) { nbin = std::max(nbin, nLambdaBins); } 252 scale = nbin/G4Log(scale); << 461 G4double emax1 = std::min(maxKinEnergy, minKinEnergyPrim); 253 << 462 254 G4LossTableBuilder* bld = lManager->GetTable << 463 for(size_t i=0; i<numOfCouples; ++i) { 255 G4EmTableUtil::BuildLambdaTable(this, partic << 464 256 bld, theLamb << 465 if (bld->GetFlag(i)) { 257 minKinEnergy << 466 258 maxKinEnergy << 467 // create physics vector and fill it 259 startFromNul << 468 const G4MaterialCutsCouple* couple = >> 469 theCoupleTable->GetMaterialCutsCouple(i); >> 470 >> 471 // build main table >> 472 if(buildLambdaTable) { >> 473 delete (*theLambdaTable)[i]; >> 474 >> 475 // if start from zero then change the scale >> 476 G4double emin = minKinEnergy; >> 477 G4bool startNull = false; >> 478 if(startFromNull) { >> 479 G4double e = MinPrimaryEnergy(particle,couple->GetMaterial()); >> 480 if(e >= emin) { >> 481 emin = e; >> 482 startNull = true; >> 483 } >> 484 } >> 485 G4double emax = emax1; >> 486 if(emax <= emin) { emax = 2*emin; } >> 487 G4int bin = G4lrint(nbin*G4Log(emax/emin)/scale); >> 488 if(bin < 3) { bin = 3; } >> 489 aVector = new G4PhysicsLogVector(emin, emax, bin); >> 490 aVector->SetSpline(splineFlag); >> 491 modelManager->FillLambdaVector(aVector, couple, startNull); >> 492 if(splineFlag) { aVector->FillSecondDerivatives(); } >> 493 G4PhysicsTableHelper::SetPhysicsVector(theLambdaTable, i, aVector); >> 494 } >> 495 // build high energy table >> 496 if(minKinEnergyPrim < maxKinEnergy) { >> 497 delete (*theLambdaTablePrim)[i]; >> 498 >> 499 // start not from zero >> 500 if(!bVectorPrim) { >> 501 G4int bin = G4lrint(nbin*G4Log(maxKinEnergy/minKinEnergyPrim)/scale); >> 502 if(bin < 3) { bin = 3; } >> 503 aVectorPrim = >> 504 new G4PhysicsLogVector(minKinEnergyPrim, maxKinEnergy, bin); >> 505 bVectorPrim = aVectorPrim; >> 506 } else { >> 507 aVectorPrim = new G4PhysicsLogVector(*bVectorPrim); >> 508 } >> 509 // always use spline >> 510 aVectorPrim->SetSpline(splineFlag); >> 511 modelManager->FillLambdaVector(aVectorPrim, couple, false, >> 512 fIsCrossSectionPrim); >> 513 aVectorPrim->FillSecondDerivatives(); >> 514 G4PhysicsTableHelper::SetPhysicsVector(theLambdaTablePrim, i, >> 515 aVectorPrim); >> 516 } >> 517 } >> 518 } >> 519 >> 520 if(buildLambdaTable) { FindLambdaMax(); } >> 521 >> 522 if(1 < verboseLevel) { >> 523 G4cout << "Lambda table is built for " >> 524 << particle->GetParticleName() >> 525 << G4endl; >> 526 } 260 } 527 } 261 528 262 //....oooOO0OOooo........oooOO0OOooo........oo 529 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 263 530 264 void G4VEmProcess::StreamInfo(std::ostream& ou 531 void G4VEmProcess::StreamInfo(std::ostream& out, 265 const G4ParticleDefinition& 532 const G4ParticleDefinition& part, G4bool rst) const 266 { 533 { 267 G4String indent = (rst ? " " : ""); 534 G4String indent = (rst ? " " : ""); 268 out << std::setprecision(6); 535 out << std::setprecision(6); 269 out << G4endl << indent << GetProcessName() 536 out << G4endl << indent << GetProcessName() << ": "; 270 if (!rst) { 537 if (!rst) { 271 out << " for " << part.GetParticleName(); 538 out << " for " << part.GetParticleName(); >> 539 if (integral) { out << ","; } 272 } 540 } 273 if(fXSType != fEmNoIntegral) { out << " XSt << 541 if(integral) { out << " integral:1 "; } 274 if(applyCuts) { out << " applyCuts:1 "; } 542 if(applyCuts) { out << " applyCuts:1 "; } 275 G4int subtype = GetProcessSubType(); << 543 out << " SubType=" << GetProcessSubType(); 276 out << " SubType=" << subtype; << 544 if(biasFactor != 1.0) { out << " BiasingFactor= " << biasFactor; } 277 if (subtype == fAnnihilation) { << 278 G4int mod = theParameters->PositronAtRestM << 279 const G4String namp[2] = {"Simple", "Allis << 280 out << " AtRestModel:" << namp[mod]; << 281 } << 282 if(biasFactor != 1.0) { out << " BiasingFac << 283 out << " BuildTable=" << buildLambdaTable << 545 out << " BuildTable=" << buildLambdaTable << G4endl; 284 if(buildLambdaTable) { 546 if(buildLambdaTable) { 285 if(particle == &part) { 547 if(particle == &part) { 286 for(auto & v : *theLambdaTable) { << 548 size_t length = theLambdaTable->length(); 287 if(nullptr != v) { << 549 for(size_t i=0; i<length; ++i) { >> 550 G4PhysicsVector* v = (*theLambdaTable)[i]; >> 551 if(v) { 288 out << " Lambda table from "; 552 out << " Lambda table from "; 289 G4double emin = v->Energy(0); 553 G4double emin = v->Energy(0); 290 G4double emax = v->GetMaxEnergy(); 554 G4double emax = v->GetMaxEnergy(); 291 G4int nbin = G4int(v->GetVectorLengt << 555 G4int nbin = v->GetVectorLength() - 1; 292 if(emin > minKinEnergy) { out << "th 556 if(emin > minKinEnergy) { out << "threshold "; } 293 else { out << G4BestUnit(emin,"Energ 557 else { out << G4BestUnit(emin,"Energy"); } 294 out << " to " 558 out << " to " 295 << G4BestUnit(emax,"Energy") 559 << G4BestUnit(emax,"Energy") 296 << ", " << G4lrint(nbin/std::log 560 << ", " << G4lrint(nbin/std::log10(emax/emin)) 297 << " bins/decade, spline: " 561 << " bins/decade, spline: " 298 << splineFlag << G4endl; 562 << splineFlag << G4endl; 299 break; 563 break; 300 } 564 } 301 } 565 } 302 } else { 566 } else { 303 out << " Used Lambda table of " 567 out << " Used Lambda table of " 304 << particle->GetParticleName() << G4endl 568 << particle->GetParticleName() << G4endl; 305 } 569 } 306 } 570 } 307 if(minKinEnergyPrim < maxKinEnergy) { 571 if(minKinEnergyPrim < maxKinEnergy) { 308 if(particle == &part) { << 572 if(particle == &part) { 309 for(auto & v : *theLambdaTablePrim) { << 573 size_t length = theLambdaTablePrim->length(); 310 if(nullptr != v) { << 574 for(size_t i=0; i<length; ++i) { >> 575 G4PhysicsVector* v = (*theLambdaTablePrim)[i]; >> 576 if(v) { 311 out << " LambdaPrime table from 577 out << " LambdaPrime table from " 312 << G4BestUnit(v->Energy(0),"Ener 578 << G4BestUnit(v->Energy(0),"Energy") 313 << " to " 579 << " to " 314 << G4BestUnit(v->GetMaxEnergy(), 580 << G4BestUnit(v->GetMaxEnergy(),"Energy") 315 << " in " << v->GetVectorLength( 581 << " in " << v->GetVectorLength()-1 316 << " bins " << G4endl; 582 << " bins " << G4endl; 317 break; 583 break; 318 } 584 } 319 } 585 } 320 } else { 586 } else { 321 out << " Used LambdaPrime table of 587 out << " Used LambdaPrime table of " 322 << particle->GetParticleName() 588 << particle->GetParticleName() << G4endl; 323 } 589 } 324 } 590 } 325 StreamProcessInfo(out); 591 StreamProcessInfo(out); 326 modelManager->DumpModelList(out, verboseLeve 592 modelManager->DumpModelList(out, verboseLevel); 327 593 328 if(verboseLevel > 2 && buildLambdaTable) { 594 if(verboseLevel > 2 && buildLambdaTable) { 329 out << " LambdaTable address= " << th 595 out << " LambdaTable address= " << theLambdaTable << G4endl; 330 if(theLambdaTable && particle == &part) { 596 if(theLambdaTable && particle == &part) { 331 out << (*theLambdaTable) << G4endl; 597 out << (*theLambdaTable) << G4endl; 332 } 598 } 333 } 599 } 334 } 600 } 335 601 336 //....oooOO0OOooo........oooOO0OOooo........oo 602 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 337 603 338 void G4VEmProcess::StartTracking(G4Track* trac 604 void G4VEmProcess::StartTracking(G4Track* track) 339 { 605 { 340 // reset parameters for the new track 606 // reset parameters for the new track 341 currentParticle = track->GetParticleDefiniti 607 currentParticle = track->GetParticleDefinition(); 342 theNumberOfInteractionLengthLeft = -1.0; 608 theNumberOfInteractionLengthLeft = -1.0; 343 mfpKinEnergy = DBL_MAX; << 609 mfpKinEnergy = DBL_MAX; 344 preStepLambda = 0.0; << 345 << 346 if(isIon) { massRatio = proton_mass_c2/curre 610 if(isIon) { massRatio = proton_mass_c2/currentParticle->GetPDGMass(); } 347 611 348 // forced biasing only for primary particles 612 // forced biasing only for primary particles 349 if(biasManager) { 613 if(biasManager) { 350 if(0 == track->GetParentID()) { 614 if(0 == track->GetParentID()) { 351 // primary particle 615 // primary particle 352 biasFlag = true; 616 biasFlag = true; 353 biasManager->ResetForcedInteraction(); 617 biasManager->ResetForcedInteraction(); 354 } 618 } 355 } 619 } 356 } 620 } 357 621 358 //....oooOO0OOooo........oooOO0OOooo........oo 622 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 359 623 360 G4double G4VEmProcess::PostStepGetPhysicalInte 624 G4double G4VEmProcess::PostStepGetPhysicalInteractionLength( 361 const G4Track& tr 625 const G4Track& track, 362 G4double previo 626 G4double previousStepSize, 363 G4ForceCondition* 627 G4ForceCondition* condition) 364 { 628 { 365 *condition = NotForced; 629 *condition = NotForced; 366 G4double x = DBL_MAX; 630 G4double x = DBL_MAX; 367 631 368 DefineMaterial(track.GetMaterialCutsCouple() 632 DefineMaterial(track.GetMaterialCutsCouple()); 369 preStepKinEnergy = track.GetKineticEnergy(); << 633 preStepKinEnergy = track.GetKineticEnergy(); 370 const G4double scaledEnergy = preStepKinEner << 634 preStepLogKinEnergy = track.GetDynamicParticle()->GetLogKineticEnergy(); >> 635 G4double scaledEnergy = preStepKinEnergy*massRatio; 371 SelectModel(scaledEnergy, currentCoupleIndex 636 SelectModel(scaledEnergy, currentCoupleIndex); 372 /* << 637 373 G4cout << "PostStepGetPhysicalInteractionLen << 374 << " couple: " << currentCouple << G << 375 */ << 376 if(!currentModel->IsActive(scaledEnergy)) { 638 if(!currentModel->IsActive(scaledEnergy)) { 377 theNumberOfInteractionLengthLeft = -1.0; 639 theNumberOfInteractionLengthLeft = -1.0; 378 currentInteractionLength = DBL_MAX; 640 currentInteractionLength = DBL_MAX; 379 mfpKinEnergy = DBL_MAX; << 380 preStepLambda = 0.0; << 381 return x; 641 return x; 382 } 642 } 383 643 384 // forced biasing only for primary particles 644 // forced biasing only for primary particles 385 if(biasManager) { 645 if(biasManager) { 386 if(0 == track.GetParentID()) { 646 if(0 == track.GetParentID()) { 387 if(biasFlag && 647 if(biasFlag && 388 biasManager->ForcedInteractionRegion( << 648 biasManager->ForcedInteractionRegion(currentCoupleIndex)) { 389 return biasManager->GetStepLimit((G4in << 649 return biasManager->GetStepLimit(currentCoupleIndex, previousStepSize); 390 } 650 } 391 } 651 } 392 } 652 } 393 653 394 // compute mean free path 654 // compute mean free path >> 655 if(preStepKinEnergy < mfpKinEnergy) { >> 656 if (integral) { >> 657 ComputeIntegralLambda(preStepKinEnergy, preStepLogKinEnergy); >> 658 } else { >> 659 preStepLambda = GetCurrentLambda(preStepKinEnergy, preStepLogKinEnergy); >> 660 } 395 661 396 ComputeIntegralLambda(preStepKinEnergy, trac << 662 // zero cross section 397 << 663 if(preStepLambda <= 0.0) { 398 // zero cross section << 664 theNumberOfInteractionLengthLeft = -1.0; 399 if(preStepLambda <= 0.0) { << 665 currentInteractionLength = DBL_MAX; 400 theNumberOfInteractionLengthLeft = -1.0; << 666 } 401 currentInteractionLength = DBL_MAX; << 667 } 402 668 403 } else { << 669 // non-zero cross section >> 670 if(preStepLambda > 0.0) { 404 671 405 // non-zero cross section << 406 if (theNumberOfInteractionLengthLeft < 0.0 672 if (theNumberOfInteractionLengthLeft < 0.0) { 407 673 408 // beggining of tracking (or just after 674 // beggining of tracking (or just after DoIt of this process) 409 theNumberOfInteractionLengthLeft = -G4Lo << 675 theNumberOfInteractionLengthLeft = -G4Log( G4UniformRand() ); 410 theInitialNumberOfInteractionLength = th 676 theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft; 411 677 412 } else { << 678 } else if(currentInteractionLength < DBL_MAX) { 413 679 414 theNumberOfInteractionLengthLeft -= 680 theNumberOfInteractionLengthLeft -= 415 previousStepSize/currentInteractionLen 681 previousStepSize/currentInteractionLength; 416 theNumberOfInteractionLengthLeft = 682 theNumberOfInteractionLengthLeft = 417 std::max(theNumberOfInteractionLengthL 683 std::max(theNumberOfInteractionLengthLeft, 0.0); 418 } 684 } 419 685 420 // new mean free path and step limit for t 686 // new mean free path and step limit for the next step 421 currentInteractionLength = 1.0/preStepLamb 687 currentInteractionLength = 1.0/preStepLambda; 422 x = theNumberOfInteractionLengthLeft * cur 688 x = theNumberOfInteractionLengthLeft * currentInteractionLength; 423 } 689 } 424 return x; 690 return x; 425 } 691 } 426 692 427 //....oooOO0OOooo........oooOO0OOooo........oo 693 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 428 694 429 void G4VEmProcess::ComputeIntegralLambda(G4dou << 695 void G4VEmProcess::ComputeIntegralLambda(G4double e, G4double loge) 430 { 696 { 431 if (fXSType == fEmNoIntegral) { << 697 // condition to skip recomputation of cross section 432 preStepLambda = GetCurrentLambda(e, LogEki << 698 const G4double epeak = theEnergyOfCrossSectionMax[currentCoupleIndex]; 433 << 699 if(e <= epeak && e/lambdaFactor >= mfpKinEnergy) { return; } 434 } else if (fXSType == fEmIncreasing) { << 700 435 if(e*invLambdaFactor < mfpKinEnergy) { << 701 // recomputation is needed 436 preStepLambda = GetCurrentLambda(e, LogE << 702 if (e <= epeak) { 437 mfpKinEnergy = (preStepLambda > 0.0) ? e << 703 preStepLambda = GetCurrentLambda(e, loge); 438 } << 704 mfpKinEnergy = e; 439 << 440 } else if(fXSType == fEmDecreasing) { << 441 if(e < mfpKinEnergy) { << 442 const G4double e1 = e*lambdaFactor; << 443 preStepLambda = GetCurrentLambda(e1); << 444 mfpKinEnergy = e1; << 445 } << 446 << 447 } else if(fXSType == fEmOnePeak) { << 448 const G4double epeak = (*theEnergyOfCrossS << 449 if(e <= epeak) { << 450 if(e*invLambdaFactor < mfpKinEnergy) { << 451 preStepLambda = GetCurrentLambda(e, Lo << 452 mfpKinEnergy = (preStepLambda > 0.0) ? << 453 } << 454 } else if(e < mfpKinEnergy) { << 455 const G4double e1 = std::max(epeak, e*la << 456 preStepLambda = GetCurrentLambda(e1); << 457 mfpKinEnergy = e1; << 458 } << 459 } else { 705 } else { 460 preStepLambda = GetCurrentLambda(e, LogEki << 706 const G4double e1 = e*lambdaFactor; >> 707 if (e1 > epeak) { >> 708 preStepLambda = GetCurrentLambda(e, loge); >> 709 mfpKinEnergy = e; >> 710 const G4double preStepLambda1 = GetCurrentLambda(e1,loge+logLambdaFactor); >> 711 if (preStepLambda1 > preStepLambda) { >> 712 mfpKinEnergy = e1; >> 713 preStepLambda = preStepLambda1; >> 714 } >> 715 } else { >> 716 preStepLambda = fFactor*theCrossSectionMax[currentCoupleIndex]; >> 717 mfpKinEnergy = epeak; >> 718 } 461 } 719 } 462 } 720 } 463 721 464 //....oooOO0OOooo........oooOO0OOooo........oo 722 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 465 723 466 G4VParticleChange* G4VEmProcess::PostStepDoIt( 724 G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track, 467 725 const G4Step& step) 468 { 726 { 469 // clear number of interaction lengths in an << 727 // In all cases clear number of interaction lengths 470 theNumberOfInteractionLengthLeft = -1.0; 728 theNumberOfInteractionLengthLeft = -1.0; 471 mfpKinEnergy = DBL_MAX; << 729 mfpKinEnergy = DBL_MAX; 472 730 473 fParticleChange.InitializeForPostStep(track) 731 fParticleChange.InitializeForPostStep(track); 474 732 475 // Do not make anything if particle is stopp 733 // Do not make anything if particle is stopped, the annihilation then 476 // should be performed by the AtRestDoIt! 734 // should be performed by the AtRestDoIt! 477 if (track.GetTrackStatus() == fStopButAlive) 735 if (track.GetTrackStatus() == fStopButAlive) { return &fParticleChange; } 478 736 479 const G4double finalT = track.GetKineticEner << 737 const G4double finalT = track.GetKineticEnergy(); >> 738 const G4double logFinalT = track.GetDynamicParticle()->GetLogKineticEnergy(); 480 739 481 // forced process - should happen only once 740 // forced process - should happen only once per track 482 if(biasFlag) { 741 if(biasFlag) { 483 if(biasManager->ForcedInteractionRegion((G << 742 if(biasManager->ForcedInteractionRegion(currentCoupleIndex)) { 484 biasFlag = false; 743 biasFlag = false; 485 } 744 } 486 } 745 } 487 746 488 // check active and select model << 489 const G4double scaledEnergy = finalT*massRat << 490 SelectModel(scaledEnergy, currentCoupleIndex << 491 if(!currentModel->IsActive(scaledEnergy)) { << 492 << 493 // Integral approach 747 // Integral approach 494 if (fXSType != fEmNoIntegral) { << 748 if (integral) { 495 const G4double logFinalT = << 749 G4double lx = GetLambda(finalT, currentCouple, logFinalT); 496 track.GetDynamicParticle()->GetLogKineti << 750 if(preStepLambda<lx && 1 < verboseLevel) { 497 const G4double lx = std::max(GetCurrentLam << 498 #ifdef G4VERBOSE << 499 if(preStepLambda < lx && 1 < verboseLevel) << 500 G4cout << "WARNING: for " << currentPart 751 G4cout << "WARNING: for " << currentParticle->GetParticleName() 501 << " and " << GetProcessName() << << 752 << " and " << GetProcessName() 502 << " preLambda= " << preStepLambd << 753 << " E(MeV)= " << finalT/MeV 503 << " < " << lx << " (postLambda) << 754 << " preLambda= " << preStepLambda << " < " 504 } << 755 << lx << " (postLambda) " 505 #endif << 756 << G4endl; 506 // if false interaction then use new cross << 757 } 507 // if both values are zero - no interactio << 758 508 if(preStepLambda*G4UniformRand() >= lx) { << 759 if(preStepLambda*G4UniformRand() > lx) { >> 760 ClearNumberOfInteractionLengthLeft(); 509 return &fParticleChange; 761 return &fParticleChange; 510 } 762 } 511 } 763 } 512 764 >> 765 G4double scaledEnergy = finalT*massRatio; >> 766 SelectModel(scaledEnergy, currentCoupleIndex); >> 767 if(!currentModel->IsActive(scaledEnergy)) { return &fParticleChange; } >> 768 513 // define new weight for primary and seconda 769 // define new weight for primary and secondaries 514 G4double weight = fParticleChange.GetParentW 770 G4double weight = fParticleChange.GetParentWeight(); 515 if(weightFlag) { 771 if(weightFlag) { 516 weight /= biasFactor; 772 weight /= biasFactor; 517 fParticleChange.ProposeWeight(weight); 773 fParticleChange.ProposeWeight(weight); 518 } 774 } 519 775 520 #ifdef G4VERBOSE << 776 /* 521 if(1 < verboseLevel) { << 777 if(0 < verboseLevel) { 522 G4cout << "G4VEmProcess::PostStepDoIt: Sam 778 G4cout << "G4VEmProcess::PostStepDoIt: Sample secondary; E= " 523 << finalT/MeV 779 << finalT/MeV 524 << " MeV; model= (" << currentModel 780 << " MeV; model= (" << currentModel->LowEnergyLimit() 525 << ", " << currentModel->HighEnerg 781 << ", " << currentModel->HighEnergyLimit() << ")" 526 << G4endl; 782 << G4endl; 527 } 783 } 528 #endif << 784 */ 529 785 530 // sample secondaries 786 // sample secondaries 531 secParticles.clear(); 787 secParticles.clear(); 532 currentModel->SampleSecondaries(&secParticle 788 currentModel->SampleSecondaries(&secParticles, 533 currentCoupl 789 currentCouple, 534 track.GetDyn 790 track.GetDynamicParticle(), 535 (*theCuts)[c 791 (*theCuts)[currentCoupleIndex]); 536 792 537 G4int num0 = (G4int)secParticles.size(); << 793 G4int num0 = secParticles.size(); 538 794 539 // splitting or Russian roulette 795 // splitting or Russian roulette 540 if(biasManager) { 796 if(biasManager) { 541 if(biasManager->SecondaryBiasingRegion((G4 << 797 if(biasManager->SecondaryBiasingRegion(currentCoupleIndex)) { 542 G4double eloss = 0.0; 798 G4double eloss = 0.0; 543 weight *= biasManager->ApplySecondaryBia 799 weight *= biasManager->ApplySecondaryBiasing( 544 secParticles, track, currentModel, &fP 800 secParticles, track, currentModel, &fParticleChange, eloss, 545 (G4int)currentCoupleIndex, (*theCuts)[ << 801 currentCoupleIndex, (*theCuts)[currentCoupleIndex], 546 step.GetPostStepPoint()->GetSafety()); 802 step.GetPostStepPoint()->GetSafety()); 547 if(eloss > 0.0) { 803 if(eloss > 0.0) { 548 eloss += fParticleChange.GetLocalEnerg 804 eloss += fParticleChange.GetLocalEnergyDeposit(); 549 fParticleChange.ProposeLocalEnergyDepo 805 fParticleChange.ProposeLocalEnergyDeposit(eloss); 550 } 806 } 551 } 807 } 552 } 808 } 553 809 554 // save secondaries 810 // save secondaries 555 G4int num = (G4int)secParticles.size(); << 811 G4int num = secParticles.size(); 556 if(num > 0) { 812 if(num > 0) { 557 813 558 fParticleChange.SetNumberOfSecondaries(num 814 fParticleChange.SetNumberOfSecondaries(num); 559 G4double edep = fParticleChange.GetLocalEn 815 G4double edep = fParticleChange.GetLocalEnergyDeposit(); 560 G4double time = track.GetGlobalTime(); 816 G4double time = track.GetGlobalTime(); 561 << 562 G4int n1(0), n2(0); << 563 if(num0 > mainSecondaries) { << 564 currentModel->FillNumberOfSecondaries(n1 << 565 } << 566 817 567 for (G4int i=0; i<num; ++i) { 818 for (G4int i=0; i<num; ++i) { 568 G4DynamicParticle* dp = secParticles[i]; << 819 if (secParticles[i]) { 569 if (nullptr != dp) { << 820 G4DynamicParticle* dp = secParticles[i]; 570 const G4ParticleDefinition* p = dp->Ge 821 const G4ParticleDefinition* p = dp->GetParticleDefinition(); 571 G4double e = dp->GetKineticEnergy(); 822 G4double e = dp->GetKineticEnergy(); 572 G4bool good = true; 823 G4bool good = true; 573 if(applyCuts) { 824 if(applyCuts) { 574 if (p == theGamma) { 825 if (p == theGamma) { 575 if (e < (*theCutsGamma)[currentCou 826 if (e < (*theCutsGamma)[currentCoupleIndex]) { good = false; } 576 827 577 } else if (p == theElectron) { 828 } else if (p == theElectron) { 578 if (e < (*theCutsElectron)[current 829 if (e < (*theCutsElectron)[currentCoupleIndex]) { good = false; } 579 830 580 } else if (p == thePositron) { 831 } else if (p == thePositron) { 581 if (electron_mass_c2 < (*theCutsGa 832 if (electron_mass_c2 < (*theCutsGamma)[currentCoupleIndex] && 582 e < (*theCutsPositron)[current 833 e < (*theCutsPositron)[currentCoupleIndex]) { 583 good = false; 834 good = false; 584 e += 2.0*electron_mass_c2; 835 e += 2.0*electron_mass_c2; 585 } 836 } 586 } 837 } 587 // added secondary if it is good 838 // added secondary if it is good 588 } 839 } 589 if (good) { 840 if (good) { 590 G4Track* t = new G4Track(dp, time, t 841 G4Track* t = new G4Track(dp, time, track.GetPosition()); 591 t->SetTouchableHandle(track.GetTouch 842 t->SetTouchableHandle(track.GetTouchableHandle()); 592 if (biasManager) { 843 if (biasManager) { 593 t->SetWeight(weight * biasManager- 844 t->SetWeight(weight * biasManager->GetWeight(i)); 594 } else { 845 } else { 595 t->SetWeight(weight); 846 t->SetWeight(weight); 596 } 847 } 597 pParticleChange->AddSecondary(t); 848 pParticleChange->AddSecondary(t); 598 849 599 // define type of secondary 850 // define type of secondary 600 if(i < mainSecondaries) { << 851 if(i < mainSecondaries) { t->SetCreatorModelIndex(secID); } 601 t->SetCreatorModelID(secID); << 852 else if(i < num0) { 602 if(GetProcessSubType() == fCompton << 853 if(p == theGamma) { 603 t->SetCreatorModelID(_ComptonGam << 854 t->SetCreatorModelIndex(fluoID); 604 } << 605 } else if(i < mainSecondaries + n1) << 606 t->SetCreatorModelID(tripletID); << 607 } else if(i < mainSecondaries + n1 + << 608 t->SetCreatorModelID(_IonRecoil); << 609 } else { << 610 if(i < num0) { << 611 if(p == theGamma) { << 612 t->SetCreatorModelID(fluoID); << 613 } else { << 614 t->SetCreatorModelID(augerID); << 615 } << 616 } else { 855 } else { 617 t->SetCreatorModelID(biasID); << 856 t->SetCreatorModelIndex(augerID); 618 } 857 } >> 858 } else { >> 859 t->SetCreatorModelIndex(biasID); 619 } 860 } 620 /* 861 /* 621 G4cout << "Secondary(post step) has 862 G4cout << "Secondary(post step) has weight " << t->GetWeight() 622 << ", Ekin= " << t->GetKineti 863 << ", Ekin= " << t->GetKineticEnergy()/MeV << " MeV " 623 << GetProcessName() << " fluo 864 << GetProcessName() << " fluoID= " << fluoID 624 << " augerID= " << augerID << 865 << " augerID= " << augerID <<G4endl; 625 */ 866 */ 626 } else { 867 } else { 627 delete dp; 868 delete dp; 628 edep += e; 869 edep += e; 629 } 870 } 630 } 871 } 631 } 872 } 632 fParticleChange.ProposeLocalEnergyDeposit( 873 fParticleChange.ProposeLocalEnergyDeposit(edep); 633 } 874 } 634 875 635 if(0.0 == fParticleChange.GetProposedKinetic 876 if(0.0 == fParticleChange.GetProposedKineticEnergy() && 636 fAlive == fParticleChange.GetTrackStatus( 877 fAlive == fParticleChange.GetTrackStatus()) { 637 if(particle->GetProcessManager()->GetAtRes 878 if(particle->GetProcessManager()->GetAtRestProcessVector()->size() > 0) 638 { fParticleChange.ProposeTrackStatus( 879 { fParticleChange.ProposeTrackStatus(fStopButAlive); } 639 else { fParticleChange.ProposeTrackStatus( 880 else { fParticleChange.ProposeTrackStatus(fStopAndKill); } 640 } 881 } 641 882 642 return &fParticleChange; 883 return &fParticleChange; 643 } 884 } 644 885 645 //....oooOO0OOooo........oooOO0OOooo........oo 886 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 646 887 647 G4bool G4VEmProcess::StorePhysicsTable(const G 888 G4bool G4VEmProcess::StorePhysicsTable(const G4ParticleDefinition* part, 648 const G 889 const G4String& directory, 649 G4bool 890 G4bool ascii) 650 { 891 { 651 if(!isTheMaster || part != particle) { retur << 892 G4bool yes = true; 652 if(G4EmTableUtil::StoreTable(this, part, the << 893 if(!isTheMaster) { return yes; } 653 directory, "Lambda", << 894 654 verboseLevel, a << 895 if ( theLambdaTable && part == particle) { 655 G4EmTableUtil::StoreTable(this, part, the << 896 const G4String& nam = 656 directory, "LambdaPrim", << 897 GetPhysicsTableFileName(part,directory,"Lambda",ascii); 657 verboseLevel, a << 898 yes = theLambdaTable->StorePhysicsTable(nam,ascii); 658 return true; << 899 >> 900 if ( yes ) { >> 901 G4cout << "Physics table is stored for " << particle->GetParticleName() >> 902 << " and process " << GetProcessName() >> 903 << " in the directory <" << directory >> 904 << "> " << G4endl; >> 905 } else { >> 906 G4cout << "Fail to store Physics Table for " >> 907 << particle->GetParticleName() >> 908 << " and process " << GetProcessName() >> 909 << " in the directory <" << directory >> 910 << "> " << G4endl; >> 911 } 659 } 912 } 660 return false; << 913 if ( theLambdaTablePrim && part == particle) { >> 914 const G4String& name = >> 915 GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii); >> 916 yes = theLambdaTablePrim->StorePhysicsTable(name,ascii); >> 917 >> 918 if ( yes ) { >> 919 G4cout << "Physics table prim is stored for " >> 920 << particle->GetParticleName() >> 921 << " and process " << GetProcessName() >> 922 << " in the directory <" << directory >> 923 << "> " << G4endl; >> 924 } else { >> 925 G4cout << "Fail to store Physics Table Prim for " >> 926 << particle->GetParticleName() >> 927 << " and process " << GetProcessName() >> 928 << " in the directory <" << directory >> 929 << "> " << G4endl; >> 930 } >> 931 } >> 932 return yes; 661 } 933 } 662 934 663 //....oooOO0OOooo........oooOO0OOooo........oo 935 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 664 936 665 G4bool G4VEmProcess::RetrievePhysicsTable(cons 937 G4bool G4VEmProcess::RetrievePhysicsTable(const G4ParticleDefinition* part, 666 cons << 938 const G4String& directory, 667 G4bo 939 G4bool ascii) 668 { 940 { 669 if(!isTheMaster || part != particle) { retur << 941 if(1 < verboseLevel) { >> 942 G4cout << "G4VEmProcess::RetrievePhysicsTable() for " >> 943 << part->GetParticleName() << " and process " >> 944 << GetProcessName() << G4endl; >> 945 } 670 G4bool yes = true; 946 G4bool yes = true; >> 947 >> 948 if((!buildLambdaTable && minKinEnergyPrim > maxKinEnergy) >> 949 || particle != part) { return yes; } >> 950 >> 951 const G4String particleName = part->GetParticleName(); >> 952 671 if(buildLambdaTable) { 953 if(buildLambdaTable) { 672 yes = G4EmTableUtil::RetrieveTable(this, p << 954 const G4String& filename = 673 "Lambda << 955 GetPhysicsTableFileName(part,directory,"Lambda",ascii); 674 ascii, << 956 yes = G4PhysicsTableHelper::RetrievePhysicsTable(theLambdaTable, 675 } << 957 filename,ascii); 676 if(yes && minKinEnergyPrim < maxKinEnergy) { << 958 if ( yes ) { 677 yes = G4EmTableUtil::RetrieveTable(this, p << 959 if (0 < verboseLevel) { 678 "Lambda << 960 G4cout << "Lambda table for " << particleName 679 ascii, << 961 << " is Retrieved from <" >> 962 << filename << ">" >> 963 << G4endl; >> 964 } >> 965 if(theParameters->Spline()) { >> 966 size_t n = theLambdaTable->length(); >> 967 for(size_t i=0; i<n; ++i) { >> 968 if((* theLambdaTable)[i]) { >> 969 (* theLambdaTable)[i]->SetSpline(true); >> 970 } >> 971 } >> 972 } >> 973 } else { >> 974 if (1 < verboseLevel) { >> 975 G4cout << "Lambda table for " << particleName << " in file <" >> 976 << filename << "> is not exist" >> 977 << G4endl; >> 978 } >> 979 } >> 980 } >> 981 if(minKinEnergyPrim < maxKinEnergy) { >> 982 const G4String& filename = >> 983 GetPhysicsTableFileName(part,directory,"LambdaPrim",ascii); >> 984 yes = G4PhysicsTableHelper::RetrievePhysicsTable(theLambdaTablePrim, >> 985 filename,ascii); >> 986 if ( yes ) { >> 987 if (0 < verboseLevel) { >> 988 G4cout << "Lambda table prim for " << particleName >> 989 << " is Retrieved from <" >> 990 << filename << ">" >> 991 << G4endl; >> 992 } >> 993 if(theParameters->Spline()) { >> 994 size_t n = theLambdaTablePrim->length(); >> 995 for(size_t i=0; i<n; ++i) { >> 996 if((* theLambdaTablePrim)[i]) { >> 997 (* theLambdaTablePrim)[i]->SetSpline(true); >> 998 } >> 999 } >> 1000 } >> 1001 } else { >> 1002 if (1 < verboseLevel) { >> 1003 G4cout << "Lambda table prim for " << particleName << " in file <" >> 1004 << filename << "> is not exist" >> 1005 << G4endl; >> 1006 } >> 1007 } 680 } 1008 } 681 return yes; 1009 return yes; 682 } 1010 } 683 1011 684 //....oooOO0OOooo........oooOO0OOooo........oo 1012 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 685 1013 686 G4double G4VEmProcess::GetCrossSection(G4doubl << 1014 G4double 687 const G << 1015 G4VEmProcess::CrossSectionPerVolume(G4double kineticEnergy, >> 1016 const G4MaterialCutsCouple* couple) 688 { 1017 { 689 CurrentSetup(couple, kinEnergy); << 1018 // Cross section per atom is calculated 690 return GetCurrentLambda(kinEnergy, G4Log(kin << 1019 DefineMaterial(couple); >> 1020 G4double cross = 0.0; >> 1021 if(buildLambdaTable) { >> 1022 cross = GetCurrentLambda(kineticEnergy); >> 1023 } else { >> 1024 SelectModel(kineticEnergy, currentCoupleIndex); >> 1025 if(currentModel) { >> 1026 cross = fFactor*currentModel->CrossSectionPerVolume(currentMaterial, >> 1027 currentParticle, >> 1028 kineticEnergy); >> 1029 } >> 1030 } >> 1031 return std::max(cross, 0.0); 691 } 1032 } 692 1033 693 //....oooOO0OOooo........oooOO0OOooo........oo 1034 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 694 1035 695 G4double G4VEmProcess::GetMeanFreePath(const G 1036 G4double G4VEmProcess::GetMeanFreePath(const G4Track& track, 696 G4doubl 1037 G4double, 697 G4Force 1038 G4ForceCondition* condition) 698 { 1039 { 699 *condition = NotForced; 1040 *condition = NotForced; 700 return G4VEmProcess::MeanFreePath(track); 1041 return G4VEmProcess::MeanFreePath(track); 701 } 1042 } 702 1043 703 //....oooOO0OOooo........oooOO0OOooo........oo 1044 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 704 1045 >> 1046 G4double G4VEmProcess::MeanFreePath(const G4Track& track) >> 1047 { >> 1048 const G4double kinEnergy = track.GetKineticEnergy(); >> 1049 CurrentSetup(track.GetMaterialCutsCouple(), kinEnergy); >> 1050 const G4double xs = GetCurrentLambda(kinEnergy, >> 1051 track.GetDynamicParticle()->GetLogKineticEnergy()); >> 1052 return (0.0 < xs) ? 1.0/xs : DBL_MAX; >> 1053 } >> 1054 >> 1055 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 1056 705 G4double 1057 G4double 706 G4VEmProcess::ComputeCrossSectionPerAtom(G4dou 1058 G4VEmProcess::ComputeCrossSectionPerAtom(G4double kinEnergy, 707 G4dou 1059 G4double Z, G4double A, G4double cut) 708 { 1060 { 709 SelectModel(kinEnergy, currentCoupleIndex); 1061 SelectModel(kinEnergy, currentCoupleIndex); 710 return (currentModel) ? 1062 return (currentModel) ? 711 currentModel->ComputeCrossSectionPerAtom(c 1063 currentModel->ComputeCrossSectionPerAtom(currentParticle, kinEnergy, 712 Z 1064 Z, A, cut) : 0.0; 713 } 1065 } 714 1066 715 //....oooOO0OOooo........oooOO0OOooo........oo 1067 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 716 1068 717 G4PhysicsVector* << 1069 void G4VEmProcess::FindLambdaMax() 718 G4VEmProcess::LambdaPhysicsVector(const G4Mate << 719 { 1070 { 720 DefineMaterial(couple); << 1071 if(1 < verboseLevel) { 721 G4PhysicsVector* newv = new G4PhysicsLogVect << 1072 G4cout << "### G4VEmProcess::FindLambdaMax: " 722 << 1073 << particle->GetParticleName() 723 return newv; << 1074 << " and process " << GetProcessName() << " " << G4endl; 724 } << 1075 } 725 << 1076 size_t n = theLambdaTable->length(); 726 //....oooOO0OOooo........oooOO0OOooo........oo << 1077 G4PhysicsVector* pv; 727 << 1078 G4double e, ss, emax, smax; 728 const G4Element* G4VEmProcess::GetCurrentEleme << 1079 729 { << 1080 size_t i; 730 return (nullptr != currentModel) ? << 1081 731 currentModel->GetCurrentElement(currentMat << 1082 // first loop on existing vectors >> 1083 for (i=0; i<n; ++i) { >> 1084 pv = (*theLambdaTable)[i]; >> 1085 if(pv) { >> 1086 size_t nb = pv->GetVectorLength(); >> 1087 emax = DBL_MAX; >> 1088 smax = 0.0; >> 1089 if(nb > 0) { >> 1090 for (size_t j=0; j<nb; ++j) { >> 1091 e = pv->Energy(j); >> 1092 ss = (*pv)(j); >> 1093 if(ss > smax) { >> 1094 smax = ss; >> 1095 emax = e; >> 1096 } >> 1097 } >> 1098 } >> 1099 theEnergyOfCrossSectionMax[i] = emax; >> 1100 theCrossSectionMax[i] = smax; >> 1101 if(1 < verboseLevel) { >> 1102 G4cout << "For " << particle->GetParticleName() >> 1103 << " Max CS at i= " << i << " emax(MeV)= " << emax/MeV >> 1104 << " lambda= " << smax << G4endl; >> 1105 } >> 1106 } >> 1107 } >> 1108 // second loop using base materials >> 1109 for (i=0; i<n; ++i) { >> 1110 pv = (*theLambdaTable)[i]; >> 1111 if(!pv){ >> 1112 G4int j = (*theDensityIdx)[i]; >> 1113 theEnergyOfCrossSectionMax[i] = theEnergyOfCrossSectionMax[j]; >> 1114 theCrossSectionMax[i] = (*theDensityFactor)[i]*theCrossSectionMax[j]; >> 1115 } >> 1116 } 732 } 1117 } 733 1118 734 //....oooOO0OOooo........oooOO0OOooo........oo 1119 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 735 1120 736 const G4Element* G4VEmProcess::GetTargetElemen << 1121 G4PhysicsVector* >> 1122 G4VEmProcess::LambdaPhysicsVector(const G4MaterialCutsCouple*) 737 { 1123 { 738 return (nullptr != currentModel) ? << 1124 G4PhysicsVector* v = 739 currentModel->GetCurrentElement(currentMat << 1125 new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nLambdaBins); >> 1126 v->SetSpline(theParameters->Spline()); >> 1127 return v; 740 } 1128 } 741 1129 742 //....oooOO0OOooo........oooOO0OOooo........oo 1130 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 743 1131 744 const G4Isotope* G4VEmProcess::GetTargetIsotop << 1132 const G4Element* G4VEmProcess::GetCurrentElement() const 745 { 1133 { 746 return (nullptr != currentModel) ? << 1134 const G4Element* elm = 747 currentModel->GetCurrentIsotope(GetCurrent << 1135 (currentModel) ? currentModel->GetCurrentElement() : nullptr; >> 1136 return elm; 748 } 1137 } 749 1138 750 //....oooOO0OOooo........oooOO0OOooo........oo 1139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 751 1140 752 void G4VEmProcess::SetCrossSectionBiasingFacto 1141 void G4VEmProcess::SetCrossSectionBiasingFactor(G4double f, G4bool flag) 753 { 1142 { 754 if(f > 0.0) { 1143 if(f > 0.0) { 755 biasFactor = f; 1144 biasFactor = f; 756 weightFlag = flag; 1145 weightFlag = flag; 757 if(1 < verboseLevel) { 1146 if(1 < verboseLevel) { 758 G4cout << "### SetCrossSectionBiasingFac 1147 G4cout << "### SetCrossSectionBiasingFactor: for " 759 << particle->GetParticleName() 1148 << particle->GetParticleName() 760 << " and process " << GetProcessN 1149 << " and process " << GetProcessName() 761 << " biasFactor= " << f << " weig 1150 << " biasFactor= " << f << " weightFlag= " << flag 762 << G4endl; 1151 << G4endl; 763 } 1152 } 764 } 1153 } 765 } 1154 } 766 1155 767 //....oooOO0OOooo........oooOO0OOooo........oo 1156 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 768 1157 769 void 1158 void 770 G4VEmProcess::ActivateForcedInteraction(G4doub 1159 G4VEmProcess::ActivateForcedInteraction(G4double length, const G4String& r, 771 G4bool 1160 G4bool flag) 772 { 1161 { 773 if(nullptr == biasManager) { biasManager = n << 1162 if(!biasManager) { biasManager = new G4EmBiasingManager(); } 774 if(1 < verboseLevel) { 1163 if(1 < verboseLevel) { 775 G4cout << "### ActivateForcedInteraction: 1164 G4cout << "### ActivateForcedInteraction: for " 776 << particle->GetParticleName() 1165 << particle->GetParticleName() 777 << " and process " << GetProcessNam 1166 << " and process " << GetProcessName() 778 << " length(mm)= " << length/mm 1167 << " length(mm)= " << length/mm 779 << " in G4Region <" << r 1168 << " in G4Region <" << r 780 << "> weightFlag= " << flag 1169 << "> weightFlag= " << flag 781 << G4endl; 1170 << G4endl; 782 } 1171 } 783 weightFlag = flag; 1172 weightFlag = flag; 784 biasManager->ActivateForcedInteraction(lengt 1173 biasManager->ActivateForcedInteraction(length, r); 785 } 1174 } 786 1175 787 //....oooOO0OOooo........oooOO0OOooo........oo 1176 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 788 1177 789 void 1178 void 790 G4VEmProcess::ActivateSecondaryBiasing(const G 1179 G4VEmProcess::ActivateSecondaryBiasing(const G4String& region, 791 G4double factor, 1180 G4double factor, 792 G4double energyLimit) 1181 G4double energyLimit) 793 { 1182 { 794 if (0.0 <= factor) { 1183 if (0.0 <= factor) { 795 1184 796 // Range cut can be applied only for e- 1185 // Range cut can be applied only for e- 797 if(0.0 == factor && secondaryParticle != G 1186 if(0.0 == factor && secondaryParticle != G4Electron::Electron()) 798 { return; } 1187 { return; } 799 1188 800 if(!biasManager) { biasManager = new G4EmB 1189 if(!biasManager) { biasManager = new G4EmBiasingManager(); } 801 biasManager->ActivateSecondaryBiasing(regi 1190 biasManager->ActivateSecondaryBiasing(region, factor, energyLimit); 802 if(1 < verboseLevel) { 1191 if(1 < verboseLevel) { 803 G4cout << "### ActivateSecondaryBiasing: 1192 G4cout << "### ActivateSecondaryBiasing: for " 804 << " process " << GetProcessName() 1193 << " process " << GetProcessName() 805 << " factor= " << factor 1194 << " factor= " << factor 806 << " in G4Region <" << region 1195 << " in G4Region <" << region 807 << "> energyLimit(MeV)= " << energyLimi 1196 << "> energyLimit(MeV)= " << energyLimit/MeV 808 << G4endl; 1197 << G4endl; 809 } 1198 } 810 } 1199 } 811 } 1200 } 812 1201 813 //....oooOO0OOooo........oooOO0OOooo........oo 1202 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 814 1203 815 void G4VEmProcess::SetLambdaBinning(G4int n) 1204 void G4VEmProcess::SetLambdaBinning(G4int n) 816 { 1205 { 817 if(5 < n && n < 10000000) { 1206 if(5 < n && n < 10000000) { 818 nLambdaBins = n; 1207 nLambdaBins = n; 819 actBinning = true; 1208 actBinning = true; 820 } else { 1209 } else { 821 G4double e = (G4double)n; 1210 G4double e = (G4double)n; 822 PrintWarning("SetLambdaBinning", e); 1211 PrintWarning("SetLambdaBinning", e); 823 } 1212 } 824 } 1213 } 825 1214 826 //....oooOO0OOooo........oooOO0OOooo........oo 1215 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 827 1216 828 void G4VEmProcess::SetMinKinEnergy(G4double e) 1217 void G4VEmProcess::SetMinKinEnergy(G4double e) 829 { 1218 { 830 if(1.e-3*eV < e && e < maxKinEnergy) { 1219 if(1.e-3*eV < e && e < maxKinEnergy) { 831 nLambdaBins = G4lrint(nLambdaBins*G4Log(ma 1220 nLambdaBins = G4lrint(nLambdaBins*G4Log(maxKinEnergy/e) 832 /G4Log(maxKinEnergy/ 1221 /G4Log(maxKinEnergy/minKinEnergy)); 833 minKinEnergy = e; 1222 minKinEnergy = e; 834 actMinKinEnergy = true; 1223 actMinKinEnergy = true; 835 } else { PrintWarning("SetMinKinEnergy", e); 1224 } else { PrintWarning("SetMinKinEnergy", e); } 836 } 1225 } 837 1226 838 //....oooOO0OOooo........oooOO0OOooo........oo 1227 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 839 1228 840 void G4VEmProcess::SetMaxKinEnergy(G4double e) 1229 void G4VEmProcess::SetMaxKinEnergy(G4double e) 841 { 1230 { 842 if(minKinEnergy < e && e < 1.e+6*TeV) { 1231 if(minKinEnergy < e && e < 1.e+6*TeV) { 843 nLambdaBins = G4lrint(nLambdaBins*G4Log(e/ 1232 nLambdaBins = G4lrint(nLambdaBins*G4Log(e/minKinEnergy) 844 /G4Log(maxKinEnergy/ 1233 /G4Log(maxKinEnergy/minKinEnergy)); 845 maxKinEnergy = e; 1234 maxKinEnergy = e; 846 actMaxKinEnergy = true; 1235 actMaxKinEnergy = true; 847 } else { PrintWarning("SetMaxKinEnergy", e); 1236 } else { PrintWarning("SetMaxKinEnergy", e); } 848 } 1237 } 849 1238 850 //....oooOO0OOooo........oooOO0OOooo........oo 1239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 851 1240 852 void G4VEmProcess::SetMinKinEnergyPrim(G4doubl 1241 void G4VEmProcess::SetMinKinEnergyPrim(G4double e) 853 { 1242 { 854 if(theParameters->MinKinEnergy() <= e && 1243 if(theParameters->MinKinEnergy() <= e && 855 e <= theParameters->MaxKinEnergy()) { min 1244 e <= theParameters->MaxKinEnergy()) { minKinEnergyPrim = e; } 856 else { PrintWarning("SetMinKinEnergyPrim", e 1245 else { PrintWarning("SetMinKinEnergyPrim", e); } 857 } 1246 } 858 1247 859 //....oooOO0OOooo........oooOO0OOooo........oo 1248 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 860 1249 861 G4VEmProcess* G4VEmProcess::GetEmProcess(const 1250 G4VEmProcess* G4VEmProcess::GetEmProcess(const G4String& nam) 862 { 1251 { 863 return (nam == GetProcessName()) ? this : nu 1252 return (nam == GetProcessName()) ? this : nullptr; 864 } 1253 } 865 1254 866 //....oooOO0OOooo........oooOO0OOooo........oo 1255 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 867 1256 868 G4double G4VEmProcess::PolarAngleLimit() const << 869 { << 870 return theParameters->MscThetaLimit(); << 871 } << 872 << 873 //....oooOO0OOooo........oooOO0OOooo........oo << 874 << 875 void G4VEmProcess::PrintWarning(G4String tit, 1257 void G4VEmProcess::PrintWarning(G4String tit, G4double val) 876 { 1258 { 877 G4String ss = "G4VEmProcess::" + tit; 1259 G4String ss = "G4VEmProcess::" + tit; 878 G4ExceptionDescription ed; 1260 G4ExceptionDescription ed; 879 ed << "Parameter is out of range: " << val 1261 ed << "Parameter is out of range: " << val 880 << " it will have no effect!\n" << " Pro 1262 << " it will have no effect!\n" << " Process " 881 << GetProcessName() << " nbins= " << the 1263 << GetProcessName() << " nbins= " << theParameters->NumberOfBins() 882 << " Emin(keV)= " << theParameters->MinKi 1264 << " Emin(keV)= " << theParameters->MinKinEnergy()/keV 883 << " Emax(GeV)= " << theParameters->MaxKi 1265 << " Emax(GeV)= " << theParameters->MaxKinEnergy()/GeV; 884 G4Exception(ss, "em0044", JustWarning, ed); 1266 G4Exception(ss, "em0044", JustWarning, ed); 885 } 1267 } 886 1268 887 //....oooOO0OOooo........oooOO0OOooo........oo 1269 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 888 1270 889 void G4VEmProcess::ProcessDescription(std::ost 1271 void G4VEmProcess::ProcessDescription(std::ostream& out) const 890 { 1272 { 891 if(nullptr != particle) { << 1273 if(particle) { 892 StreamInfo(out, *particle, true); 1274 StreamInfo(out, *particle, true); 893 } 1275 } 894 } 1276 } 895 1277 896 //....oooOO0OOooo........oooOO0OOooo........oo 1278 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 897 1279