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: G4VEnergyLossProcess 31 // File name: G4VEnergyLossProcess 32 // 32 // 33 // Author: Vladimir Ivanchenko 33 // Author: Vladimir Ivanchenko 34 // 34 // 35 // Creation date: 03.01.2002 35 // Creation date: 03.01.2002 36 // 36 // 37 // Modifications: Vladimir Ivanchenko 37 // Modifications: Vladimir Ivanchenko 38 // 38 // 39 // 39 // 40 // Class Description: 40 // Class Description: 41 // 41 // 42 // It is the unified energy loss process it ca 42 // It is the unified energy loss process it calculates the continuous 43 // energy loss for charged particles using a s 43 // energy loss for charged particles using a set of Energy Loss 44 // models valid for different energy regions. 44 // models valid for different energy regions. There are a possibility 45 // to create and access to dE/dx and range tab 45 // to create and access to dE/dx and range tables, or to calculate 46 // that information on fly. 46 // that information on fly. 47 // ------------------------------------------- 47 // ------------------------------------------------------------------- 48 // 48 // 49 //....oooOO0OOooo........oooOO0OOooo........oo 49 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 50 //....oooOO0OOooo........oooOO0OOooo........oo 50 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 51 51 52 #include "G4VEnergyLossProcess.hh" 52 #include "G4VEnergyLossProcess.hh" 53 #include "G4PhysicalConstants.hh" 53 #include "G4PhysicalConstants.hh" 54 #include "G4SystemOfUnits.hh" 54 #include "G4SystemOfUnits.hh" 55 #include "G4ProcessManager.hh" 55 #include "G4ProcessManager.hh" 56 #include "G4LossTableManager.hh" 56 #include "G4LossTableManager.hh" 57 #include "G4LossTableBuilder.hh" 57 #include "G4LossTableBuilder.hh" 58 #include "G4Step.hh" 58 #include "G4Step.hh" 59 #include "G4ParticleDefinition.hh" 59 #include "G4ParticleDefinition.hh" 60 #include "G4ParticleTable.hh" 60 #include "G4ParticleTable.hh" 61 #include "G4EmParameters.hh" << 62 #include "G4EmUtility.hh" << 63 #include "G4EmTableUtil.hh" << 64 #include "G4VEmModel.hh" 61 #include "G4VEmModel.hh" 65 #include "G4VEmFluctuationModel.hh" 62 #include "G4VEmFluctuationModel.hh" 66 #include "G4DataVector.hh" 63 #include "G4DataVector.hh" 67 #include "G4PhysicsLogVector.hh" 64 #include "G4PhysicsLogVector.hh" 68 #include "G4VParticleChange.hh" 65 #include "G4VParticleChange.hh" >> 66 #include "G4Gamma.hh" 69 #include "G4Electron.hh" 67 #include "G4Electron.hh" >> 68 #include "G4Positron.hh" 70 #include "G4ProcessManager.hh" 69 #include "G4ProcessManager.hh" 71 #include "G4UnitsTable.hh" 70 #include "G4UnitsTable.hh" >> 71 #include "G4ProductionCutsTable.hh" 72 #include "G4Region.hh" 72 #include "G4Region.hh" 73 #include "G4RegionStore.hh" 73 #include "G4RegionStore.hh" 74 #include "G4PhysicsTableHelper.hh" 74 #include "G4PhysicsTableHelper.hh" 75 #include "G4SafetyHelper.hh" 75 #include "G4SafetyHelper.hh" 76 #include "G4EmDataHandler.hh" << 77 #include "G4TransportationManager.hh" 76 #include "G4TransportationManager.hh" >> 77 #include "G4EmConfigurator.hh" 78 #include "G4VAtomDeexcitation.hh" 78 #include "G4VAtomDeexcitation.hh" 79 #include "G4VSubCutProducer.hh" 79 #include "G4VSubCutProducer.hh" 80 #include "G4EmBiasingManager.hh" 80 #include "G4EmBiasingManager.hh" 81 #include "G4Log.hh" 81 #include "G4Log.hh" 82 #include <iostream> 82 #include <iostream> 83 83 84 //....oooOO0OOooo........oooOO0OOooo........oo 84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 85 85 86 namespace << 87 { << 88 G4String tnames[7] = << 89 {"DEDX","Ionisation","DEDXnr","CSDARange", << 90 } << 91 << 92 << 93 G4VEnergyLossProcess::G4VEnergyLossProcess(con 86 G4VEnergyLossProcess::G4VEnergyLossProcess(const G4String& name, 94 G4P 87 G4ProcessType type): 95 G4VContinuousDiscreteProcess(name, type) << 88 G4VContinuousDiscreteProcess(name, type), >> 89 secondaryParticle(nullptr), >> 90 nSCoffRegions(0), >> 91 idxSCoffRegions(nullptr), >> 92 nProcesses(0), >> 93 theDEDXTable(nullptr), >> 94 theDEDXSubTable(nullptr), >> 95 theDEDXunRestrictedTable(nullptr), >> 96 theIonisationTable(nullptr), >> 97 theIonisationSubTable(nullptr), >> 98 theRangeTableForLoss(nullptr), >> 99 theCSDARangeTable(nullptr), >> 100 theSecondaryRangeTable(nullptr), >> 101 theInverseRangeTable(nullptr), >> 102 theLambdaTable(nullptr), >> 103 theSubLambdaTable(nullptr), >> 104 baseParticle(nullptr), >> 105 lossFluctuationFlag(true), >> 106 rndmStepFlag(false), >> 107 tablesAreBuilt(false), >> 108 integral(true), >> 109 isIon(false), >> 110 isIonisation(true), >> 111 useSubCutoff(false), >> 112 useDeexcitation(false), >> 113 currentCouple(nullptr), >> 114 mfpKinEnergy(0.0), >> 115 particle(nullptr) 96 { 116 { 97 theParameters = G4EmParameters::Instance(); 117 theParameters = G4EmParameters::Instance(); 98 SetVerboseLevel(1); 118 SetVerboseLevel(1); 99 119 100 // low energy limit 120 // low energy limit 101 lowestKinEnergy = theParameters->LowestElect << 121 lowestKinEnergy = theParameters->LowestElectronEnergy(); 102 << 122 preStepKinEnergy = 0.0; 103 // Size of tables << 123 preStepLogKinEnergy = LOG_EKIN_MIN; 104 minKinEnergy = 0.1*CLHEP::keV; << 124 preStepRangeEnergy = 0.0; 105 maxKinEnergy = 100.0*CLHEP::TeV; << 125 computedRange = DBL_MAX; 106 maxKinEnergyCSDA = 1.0*CLHEP::GeV; << 126 >> 127 // Size of tables assuming spline >> 128 minKinEnergy = 0.1*keV; >> 129 maxKinEnergy = 100.0*TeV; 107 nBins = 84; 130 nBins = 84; >> 131 maxKinEnergyCSDA = 1.0*GeV; 108 nBinsCSDA = 35; 132 nBinsCSDA = 35; >> 133 actMinKinEnergy = actMaxKinEnergy = actBinning = actLinLossLimit >> 134 = actLossFluc = actIntegral = false; 109 135 110 invLambdaFactor = 1.0/lambdaFactor; << 136 // default linear loss limit for spline 111 << 137 linLossLimit = 0.01; 112 // default linear loss limit << 138 dRoverRange = 0.2; 113 finalRange = 1.*CLHEP::mm; << 139 finalRange = CLHEP::mm; >> 140 >> 141 // default lambda factor >> 142 lambdaFactor = 0.8; >> 143 logLambdafactor = G4Log(lambdaFactor); >> 144 >> 145 // cross section biasing >> 146 biasFactor = 1.0; >> 147 >> 148 // particle types >> 149 theElectron = G4Electron::Electron(); >> 150 thePositron = G4Positron::Positron(); >> 151 theGamma = G4Gamma::Gamma(); >> 152 theGenericIon = nullptr; 114 153 115 // run time objects 154 // run time objects 116 pParticleChange = &fParticleChange; 155 pParticleChange = &fParticleChange; 117 fParticleChange.SetSecondaryWeightByProcess( 156 fParticleChange.SetSecondaryWeightByProcess(true); 118 modelManager = new G4EmModelManager(); 157 modelManager = new G4EmModelManager(); 119 safetyHelper = G4TransportationManager::GetT 158 safetyHelper = G4TransportationManager::GetTransportationManager() 120 ->GetSafetyHelper(); 159 ->GetSafetyHelper(); 121 aGPILSelection = CandidateForSelection; 160 aGPILSelection = CandidateForSelection; 122 161 123 // initialise model 162 // initialise model 124 lManager = G4LossTableManager::Instance(); 163 lManager = G4LossTableManager::Instance(); 125 lManager->Register(this); 164 lManager->Register(this); 126 isMaster = lManager->IsMaster(); << 127 << 128 G4LossTableBuilder* bld = lManager->GetTable 165 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 129 theDensityFactor = bld->GetDensityFactors(); 166 theDensityFactor = bld->GetDensityFactors(); 130 theDensityIdx = bld->GetCoupleIndexes(); 167 theDensityIdx = bld->GetCoupleIndexes(); 131 168 132 scTracks.reserve(10); << 169 fluctModel = nullptr; 133 secParticles.reserve(12); << 170 currentModel = nullptr; 134 emModels = new std::vector<G4VEmModel*>; << 171 atomDeexcitation = nullptr; >> 172 subcutProducer = nullptr; >> 173 >> 174 biasManager = nullptr; >> 175 biasFlag = false; >> 176 weightFlag = false; >> 177 isMaster = true; >> 178 lastIdx = 0; >> 179 >> 180 scTracks.reserve(5); >> 181 secParticles.reserve(5); >> 182 >> 183 theCuts = theSubCuts = nullptr; >> 184 currentMaterial = nullptr; >> 185 currentCoupleIndex = basedCoupleIndex = 0; >> 186 massRatio = fFactor = reduceFactor = chargeSqRatio = 1.0; >> 187 preStepLambda = preStepScaledEnergy = fRange = logMassRatio = 0.0; >> 188 preStepLogScaledEnergy = LOG_EKIN_MIN; >> 189 >> 190 secID = biasID = subsecID = -1; 135 } 191 } 136 192 137 //....oooOO0OOooo........oooOO0OOooo........oo 193 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 138 194 139 G4VEnergyLossProcess::~G4VEnergyLossProcess() 195 G4VEnergyLossProcess::~G4VEnergyLossProcess() 140 { 196 { 141 if (isMaster) { << 197 /* 142 if(nullptr == baseParticle) { delete theDa << 198 G4cout << "** G4VEnergyLossProcess::~G4VEnergyLossProcess() for " 143 delete theEnergyOfCrossSectionMax; << 199 << GetProcessName() << " isMaster: " << isMaster 144 if(nullptr != fXSpeaks) { << 200 << " basePart: " << baseParticle 145 for(auto const & v : *fXSpeaks) { delete << 201 << G4endl; 146 delete fXSpeaks; << 202 */ >> 203 Clean(); >> 204 >> 205 // G4cout << " isIonisation " << isIonisation << " " >> 206 // << theDEDXTable << " " << theIonisationTable << G4endl; >> 207 >> 208 if (isMaster && !baseParticle) { >> 209 if(theDEDXTable) { >> 210 >> 211 //G4cout << " theIonisationTable " << theIonisationTable << G4endl; >> 212 if(theIonisationTable == theDEDXTable) { theIonisationTable = nullptr; } >> 213 //G4cout << " delete theDEDXTable " << theDEDXTable << G4endl; >> 214 theDEDXTable->clearAndDestroy(); >> 215 delete theDEDXTable; >> 216 theDEDXTable = nullptr; >> 217 if(theDEDXSubTable) { >> 218 if(theIonisationSubTable == theDEDXSubTable) >> 219 { theIonisationSubTable = nullptr; } >> 220 theDEDXSubTable->clearAndDestroy(); >> 221 delete theDEDXSubTable; >> 222 theDEDXSubTable = nullptr; >> 223 } >> 224 } >> 225 //G4cout << " theIonisationTable " << theIonisationTable << G4endl; >> 226 if(theIonisationTable) { >> 227 //G4cout << " delete theIonisationTable " << theIonisationTable << G4endl; >> 228 theIonisationTable->clearAndDestroy(); >> 229 delete theIonisationTable; >> 230 theIonisationTable = nullptr; >> 231 } >> 232 if(theIonisationSubTable) { >> 233 theIonisationSubTable->clearAndDestroy(); >> 234 delete theIonisationSubTable; >> 235 theIonisationSubTable = nullptr; >> 236 } >> 237 if(theDEDXunRestrictedTable && isIonisation) { >> 238 theDEDXunRestrictedTable->clearAndDestroy(); >> 239 delete theDEDXunRestrictedTable; >> 240 theDEDXunRestrictedTable = nullptr; >> 241 } >> 242 if(theCSDARangeTable && isIonisation) { >> 243 theCSDARangeTable->clearAndDestroy(); >> 244 delete theCSDARangeTable; >> 245 theCSDARangeTable = nullptr; >> 246 } >> 247 //G4cout << "delete RangeTable: " << theRangeTableForLoss << G4endl; >> 248 if(theRangeTableForLoss && isIonisation) { >> 249 theRangeTableForLoss->clearAndDestroy(); >> 250 delete theRangeTableForLoss; >> 251 theRangeTableForLoss = nullptr; >> 252 } >> 253 //G4cout << "delete InvRangeTable: " << theInverseRangeTable << G4endl; >> 254 if(theInverseRangeTable && isIonisation /*&& !isIon*/) { >> 255 theInverseRangeTable->clearAndDestroy(); >> 256 delete theInverseRangeTable; >> 257 theInverseRangeTable = nullptr; >> 258 } >> 259 //G4cout << "delete LambdaTable: " << theLambdaTable << G4endl; >> 260 if(theLambdaTable) { >> 261 theLambdaTable->clearAndDestroy(); >> 262 delete theLambdaTable; >> 263 theLambdaTable = nullptr; >> 264 } >> 265 if(theSubLambdaTable) { >> 266 theSubLambdaTable->clearAndDestroy(); >> 267 delete theSubLambdaTable; >> 268 theSubLambdaTable = nullptr; 147 } 269 } 148 } 270 } >> 271 149 delete modelManager; 272 delete modelManager; 150 delete biasManager; 273 delete biasManager; 151 delete scoffRegions; << 152 delete emModels; << 153 lManager->DeRegister(this); 274 lManager->DeRegister(this); >> 275 //G4cout << "** all removed" << G4endl; >> 276 } >> 277 >> 278 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 279 >> 280 void G4VEnergyLossProcess::Clean() >> 281 { >> 282 /* >> 283 if(1 < verboseLevel) { >> 284 G4cout << "G4VEnergyLossProcess::Clear() for " << GetProcessName() >> 285 << G4endl; >> 286 } >> 287 */ >> 288 delete [] idxSCoffRegions; >> 289 >> 290 tablesAreBuilt = false; >> 291 >> 292 scProcesses.clear(); >> 293 nProcesses = 0; >> 294 /* >> 295 idxDEDX = idxDEDXSub = idxDEDXunRestricted = idxIonisation = >> 296 idxIonisationSub = idxRange = idxCSDA = idxSecRange = >> 297 idxInverseRange = idxLambda = idxSubLambda = 0; >> 298 */ 154 } 299 } 155 300 156 //....oooOO0OOooo........oooOO0OOooo........oo 301 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 157 302 158 G4double G4VEnergyLossProcess::MinPrimaryEnerg 303 G4double G4VEnergyLossProcess::MinPrimaryEnergy(const G4ParticleDefinition*, 159 304 const G4Material*, 160 305 G4double cut) 161 { 306 { 162 return cut; 307 return cut; 163 } 308 } 164 309 165 //....oooOO0OOooo........oooOO0OOooo........oo 310 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 166 311 167 void G4VEnergyLossProcess::AddEmModel(G4int or << 312 void G4VEnergyLossProcess::AddEmModel(G4int order, G4VEmModel* p, 168 G4VEmFlu 313 G4VEmFluctuationModel* fluc, 169 const G4 314 const G4Region* region) 170 { 315 { 171 if(nullptr == ptr) { return; } << 316 modelManager->AddEmModel(order, p, fluc, region); 172 G4VEmFluctuationModel* afluc = (nullptr == f << 317 if(p) { p->SetParticleChange(pParticleChange, fluc); } 173 modelManager->AddEmModel(order, ptr, afluc, << 318 } 174 ptr->SetParticleChange(pParticleChange, aflu << 319 >> 320 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 321 >> 322 void G4VEnergyLossProcess::UpdateEmModel(const G4String& nam, >> 323 G4double emin, G4double emax) >> 324 { >> 325 modelManager->UpdateEmModel(nam, emin, emax); 175 } 326 } 176 327 177 //....oooOO0OOooo........oooOO0OOooo........oo 328 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 178 329 179 void G4VEnergyLossProcess::SetEmModel(G4VEmMod 330 void G4VEnergyLossProcess::SetEmModel(G4VEmModel* ptr, G4int) 180 { 331 { 181 if(nullptr == ptr) { return; } << 332 for(auto & em : emModels) { if(em == ptr) { return; } } 182 if(!emModels->empty()) { << 333 emModels.push_back(ptr); 183 for(auto & em : *emModels) { if(em == ptr) << 184 } << 185 emModels->push_back(ptr); << 186 } 334 } 187 335 188 //....oooOO0OOooo........oooOO0OOooo........oo 336 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 189 337 190 void G4VEnergyLossProcess::SetDynamicMassCharg << 338 G4VEmModel* G4VEnergyLossProcess::EmModel(size_t index) const 191 << 192 { 339 { 193 massRatio = massratio; << 340 return (index < emModels.size()) ? emModels[index] : nullptr; 194 logMassRatio = G4Log(massRatio); << 341 } 195 fFactor = charge2ratio*biasFactor; << 342 196 if(baseMat) { fFactor *= (*theDensityFactor) << 343 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 197 chargeSqRatio = charge2ratio; << 344 198 reduceFactor = 1.0/(fFactor*massRatio); << 345 G4VEmModel* G4VEnergyLossProcess::GetModelByIndex(G4int idx, G4bool ver) const >> 346 { >> 347 return modelManager->GetModel(idx, ver); >> 348 } >> 349 >> 350 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 351 >> 352 G4int G4VEnergyLossProcess::NumberOfModels() const >> 353 { >> 354 return modelManager->NumberOfModels(); 199 } 355 } 200 356 201 //....oooOO0OOooo........oooOO0OOooo........oo 357 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 202 358 203 void 359 void 204 G4VEnergyLossProcess::PreparePhysicsTable(cons 360 G4VEnergyLossProcess::PreparePhysicsTable(const G4ParticleDefinition& part) 205 { 361 { 206 particle = G4EmTableUtil::CheckIon(this, &pa << 362 if(1 < verboseLevel) { 207 verboseLe << 363 G4cout << "G4VEnergyLossProcess::PreparePhysicsTable for " >> 364 << GetProcessName() << " for " << part.GetParticleName() >> 365 << " " << this << G4endl; >> 366 } >> 367 isMaster = lManager->IsMaster(); >> 368 >> 369 currentCouple = nullptr; >> 370 preStepLambda = 0.0; >> 371 mfpKinEnergy = DBL_MAX; >> 372 fRange = DBL_MAX; >> 373 preStepKinEnergy = 0.0; >> 374 preStepLogKinEnergy = LOG_EKIN_MIN; >> 375 preStepRangeEnergy = 0.0; >> 376 chargeSqRatio = 1.0; >> 377 massRatio = 1.0; >> 378 logMassRatio = 0.; >> 379 reduceFactor = 1.0; >> 380 fFactor = 1.0; >> 381 lastIdx = 0; >> 382 >> 383 // Are particle defined? >> 384 if( !particle ) { particle = ∂ } >> 385 >> 386 if(part.GetParticleType() == "nucleus") { >> 387 >> 388 G4String pname = part.GetParticleName(); >> 389 if(pname != "deuteron" && pname != "triton" && >> 390 pname != "alpha+" && pname != "helium" && >> 391 pname != "hydrogen") { >> 392 >> 393 if(!theGenericIon) { >> 394 theGenericIon = >> 395 G4ParticleTable::GetParticleTable()->FindParticle("GenericIon"); >> 396 } >> 397 isIon = true; >> 398 if(theGenericIon && particle != theGenericIon) { >> 399 G4ProcessManager* pm = theGenericIon->GetProcessManager(); >> 400 G4ProcessVector* v = pm->GetAlongStepProcessVector(); >> 401 size_t n = v->size(); >> 402 for(size_t j=0; j<n; ++j) { >> 403 if((*v)[j] == this) { >> 404 particle = theGenericIon; >> 405 break; >> 406 } >> 407 } >> 408 } >> 409 } >> 410 } 208 411 209 if( particle != &part ) { 412 if( particle != &part ) { 210 if(!isIon) { lManager->RegisterExtraPartic << 413 if(!isIon) { >> 414 lManager->RegisterExtraParticle(&part, this); >> 415 } 211 if(1 < verboseLevel) { 416 if(1 < verboseLevel) { 212 G4cout << "### G4VEnergyLossProcess::Pre 417 G4cout << "### G4VEnergyLossProcess::PreparePhysicsTable()" 213 << " interrupted for " << GetProc << 418 << " interrupted for " 214 << part.GetParticleName() << " is << 419 << part.GetParticleName() << " isIon= " << isIon 215 << " spline=" << spline << G4endl << 420 << " particle " << particle << " GenericIon " << theGenericIon >> 421 << G4endl; 216 } 422 } 217 return; 423 return; 218 } 424 } 219 425 220 tablesAreBuilt = false; << 426 Clean(); 221 if (GetProcessSubType() == fIonisation) { Se << 427 lManager->PreparePhysicsTable(&part, this, isMaster); 222 << 223 G4LossTableBuilder* bld = lManager->GetTable 428 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 224 lManager->PreparePhysicsTable(&part, this); << 225 429 226 // Base particle and set of models can be de 430 // Base particle and set of models can be defined here 227 InitialiseEnergyLossProcess(particle, basePa 431 InitialiseEnergyLossProcess(particle, baseParticle); 228 432 >> 433 const G4ProductionCutsTable* theCoupleTable= >> 434 G4ProductionCutsTable::GetProductionCutsTable(); >> 435 size_t n = theCoupleTable->GetTableSize(); >> 436 >> 437 theDEDXAtMaxEnergy.resize(n, 0.0); >> 438 theRangeAtMaxEnergy.resize(n, 0.0); >> 439 theEnergyOfCrossSectionMax.resize(n, 0.0); >> 440 theCrossSectionMax.resize(n, DBL_MAX); >> 441 229 // parameters of the process 442 // parameters of the process >> 443 if(!actIntegral) { integral = theParameters->Integral(); } 230 if(!actLossFluc) { lossFluctuationFlag = the 444 if(!actLossFluc) { lossFluctuationFlag = theParameters->LossFluctuation(); } 231 useCutAsFinalRange = theParameters->UseCutAs << 445 rndmStepFlag = theParameters->UseCutAsFinalRange(); 232 if(!actMinKinEnergy) { minKinEnergy = thePar 446 if(!actMinKinEnergy) { minKinEnergy = theParameters->MinKinEnergy(); } 233 if(!actMaxKinEnergy) { maxKinEnergy = thePar 447 if(!actMaxKinEnergy) { maxKinEnergy = theParameters->MaxKinEnergy(); } 234 if(!actBinning) { nBins = theParameters->Num << 448 if(!actBinning) { >> 449 nBins = theParameters->NumberOfBinsPerDecade() >> 450 *G4lrint(std::log10(maxKinEnergy/minKinEnergy)); >> 451 } 235 maxKinEnergyCSDA = theParameters->MaxEnergyF 452 maxKinEnergyCSDA = theParameters->MaxEnergyForCSDARange(); 236 nBinsCSDA = theParameters->NumberOfBinsPerDe 453 nBinsCSDA = theParameters->NumberOfBinsPerDecade() 237 *G4lrint(std::log10(maxKinEnergyCSDA/minKi 454 *G4lrint(std::log10(maxKinEnergyCSDA/minKinEnergy)); 238 if(!actLinLossLimit) { linLossLimit = thePar 455 if(!actLinLossLimit) { linLossLimit = theParameters->LinearLossLimit(); } 239 lambdaFactor = theParameters->LambdaFactor() << 456 lambdaFactor = theParameters->LambdaFactor(); 240 invLambdaFactor = 1.0/lambdaFactor; << 457 logLambdafactor = G4Log(lambdaFactor); 241 if(isMaster) { SetVerboseLevel(theParameters 458 if(isMaster) { SetVerboseLevel(theParameters->Verbose()); } 242 else { SetVerboseLevel(theParameters->Worker << 459 else { SetVerboseLevel(theParameters->WorkerVerbose()); } 243 // integral option may be disabled << 244 if(!theParameters->Integral()) { fXSType = f << 245 460 246 theParameters->DefineRegParamForLoss(this); 461 theParameters->DefineRegParamForLoss(this); 247 462 248 fRangeEnergy = 0.0; << 249 << 250 G4double initialCharge = particle->GetPDGCha 463 G4double initialCharge = particle->GetPDGCharge(); 251 G4double initialMass = particle->GetPDGMas 464 G4double initialMass = particle->GetPDGMass(); 252 465 253 theParameters->FillStepFunction(particle, th 466 theParameters->FillStepFunction(particle, this); 254 467 255 // parameters for scaling from the base part << 468 if (baseParticle) { 256 if (nullptr != baseParticle) { << 257 massRatio = (baseParticle->GetPDGMass() 469 massRatio = (baseParticle->GetPDGMass())/initialMass; 258 logMassRatio = G4Log(massRatio); 470 logMassRatio = G4Log(massRatio); 259 G4double q = initialCharge/baseParticle->G 471 G4double q = initialCharge/baseParticle->GetPDGCharge(); 260 chargeSqRatio = q*q; 472 chargeSqRatio = q*q; 261 if(chargeSqRatio > 0.0) { reduceFactor = 1 473 if(chargeSqRatio > 0.0) { reduceFactor = 1.0/(chargeSqRatio*massRatio); } 262 } 474 } 263 lowestKinEnergy = (initialMass < CLHEP::MeV) << 475 lowestKinEnergy = (initialMass < MeV) ? theParameters->LowestElectronEnergy() 264 ? theParameters->LowestElectronEnergy() << 265 : theParameters->LowestMuHadEnergy(); 476 : theParameters->LowestMuHadEnergy(); 266 477 267 // Tables preparation 478 // Tables preparation 268 if (isMaster && nullptr == baseParticle) { << 479 if (isMaster && !baseParticle) { 269 if(nullptr == theData) { theData = new G4E << 270 480 271 if(nullptr != theDEDXTable && isIonisation << 481 if(theDEDXTable && isIonisation) { 272 if(nullptr != theIonisationTable && theD << 482 if(theIonisationTable && theDEDXTable != theIonisationTable) { 273 theData->CleanTable(0); << 483 theDEDXTable->clearAndDestroy(); 274 theDEDXTable = theIonisationTable; << 484 delete theDEDXTable; 275 theIonisationTable = nullptr; << 485 theDEDXTable = theIonisationTable; 276 } << 486 } >> 487 if(theDEDXSubTable && theIonisationSubTable && >> 488 theDEDXSubTable != theIonisationSubTable) { >> 489 theDEDXSubTable->clearAndDestroy(); >> 490 delete theDEDXSubTable; >> 491 theDEDXSubTable = theIonisationSubTable; >> 492 } 277 } 493 } 278 494 279 theDEDXTable = theData->MakeTable(theDEDXT << 495 theDEDXTable = G4PhysicsTableHelper::PreparePhysicsTable(theDEDXTable); 280 bld->InitialiseBaseMaterials(theDEDXTable) 496 bld->InitialiseBaseMaterials(theDEDXTable); 281 theData->UpdateTable(theIonisationTable, 1 << 497 >> 498 if(theDEDXSubTable) { >> 499 theDEDXSubTable = >> 500 G4PhysicsTableHelper::PreparePhysicsTable(theDEDXSubTable); >> 501 } 282 502 283 if (theParameters->BuildCSDARange()) { 503 if (theParameters->BuildCSDARange()) { 284 theDEDXunRestrictedTable = theData->Make << 504 theDEDXunRestrictedTable = 285 if(isIonisation) { theCSDARangeTable = t << 505 G4PhysicsTableHelper::PreparePhysicsTable(theDEDXunRestrictedTable); >> 506 theCSDARangeTable = >> 507 G4PhysicsTableHelper::PreparePhysicsTable(theCSDARangeTable); 286 } 508 } 287 509 288 theLambdaTable = theData->MakeTable(4); << 510 theLambdaTable = G4PhysicsTableHelper::PreparePhysicsTable(theLambdaTable); >> 511 289 if(isIonisation) { 512 if(isIonisation) { 290 theRangeTableForLoss = theData->MakeTabl << 513 theRangeTableForLoss = 291 theInverseRangeTable = theData->MakeTabl << 514 G4PhysicsTableHelper::PreparePhysicsTable(theRangeTableForLoss); >> 515 theInverseRangeTable = >> 516 G4PhysicsTableHelper::PreparePhysicsTable(theInverseRangeTable); 292 } 517 } 293 } << 294 518 >> 519 if (nSCoffRegions && !lManager->SubCutProducer()) { >> 520 theDEDXSubTable = >> 521 G4PhysicsTableHelper::PreparePhysicsTable(theDEDXSubTable); >> 522 theSubLambdaTable = >> 523 G4PhysicsTableHelper::PreparePhysicsTable(theSubLambdaTable); >> 524 } >> 525 } >> 526 /* >> 527 G4cout << "** G4VEnergyLossProcess::PreparePhysicsTable() for " >> 528 << GetProcessName() << " and " << particle->GetParticleName() >> 529 << " isMaster: " << isMaster << " isIonisation: " >> 530 << isIonisation << G4endl; >> 531 G4cout << " theDEDX: " << theDEDXTable >> 532 << " theRange: " << theRangeTableForLoss >> 533 << " theInverse: " << theInverseRangeTable >> 534 << " theLambda: " << theLambdaTable << G4endl; >> 535 */ 295 // forced biasing 536 // forced biasing 296 if(nullptr != biasManager) { << 537 if(biasManager) { 297 biasManager->Initialise(part,GetProcessNam 538 biasManager->Initialise(part,GetProcessName(),verboseLevel); 298 biasFlag = false; 539 biasFlag = false; 299 } 540 } 300 baseMat = bld->GetBaseMaterialFlag(); << 541 301 numberOfModels = modelManager->NumberOfModel << 542 // defined ID of secondary particles 302 currentModel = modelManager->GetModel(0); << 543 if(isMaster) { 303 G4EmTableUtil::UpdateModels(this, modelManag << 544 G4String nam1 = GetProcessName(); 304 numberOfModels, << 545 G4String nam4 = nam1 + "_split"; 305 mainSecondaries, << 546 G4String nam5 = nam1 + "_subcut"; 306 theParameters->U << 547 secID = G4PhysicsModelCatalog::Register(nam1); 307 theCuts = modelManager->Initialise(particle, << 548 biasID = G4PhysicsModelCatalog::Register(nam4); 308 verboseLe << 549 subsecID= G4PhysicsModelCatalog::Register(nam5); 309 // subcut processor << 550 } 310 if(isIonisation) { << 551 311 subcutProducer = lManager->SubCutProducer( << 552 // initialisation of models >> 553 G4int nmod = modelManager->NumberOfModels(); >> 554 for(G4int i=0; i<nmod; ++i) { >> 555 G4VEmModel* mod = modelManager->GetModel(i); >> 556 mod->SetMasterThread(isMaster); >> 557 mod->SetAngularGeneratorFlag( >> 558 theParameters->UseAngularGeneratorForIonisation()); >> 559 if(mod->HighEnergyLimit() > maxKinEnergy) { >> 560 mod->SetHighEnergyLimit(maxKinEnergy); >> 561 } 312 } 562 } 313 if(1 == nSCoffRegions) { << 563 theCuts = modelManager->Initialise(particle, secondaryParticle, 314 if((*scoffRegions)[0]->GetName() == "Defau << 564 theParameters->MinSubRange(), 315 delete scoffRegions; << 565 verboseLevel); 316 scoffRegions = nullptr; << 566 317 nSCoffRegions = 0; << 567 // Sub Cutoff >> 568 if(nSCoffRegions > 0) { >> 569 if(theParameters->MinSubRange() < 1.0) { useSubCutoff = true; } >> 570 >> 571 theSubCuts = modelManager->SubCutoff(); >> 572 >> 573 idxSCoffRegions = new G4bool[n]; >> 574 for (size_t j=0; j<n; ++j) { >> 575 >> 576 const G4MaterialCutsCouple* couple = >> 577 theCoupleTable->GetMaterialCutsCouple(j); >> 578 const G4ProductionCuts* pcuts = couple->GetProductionCuts(); >> 579 >> 580 G4bool reg = false; >> 581 for(G4int i=0; i<nSCoffRegions; ++i) { >> 582 if( pcuts == scoffRegions[i]->GetProductionCuts()) { >> 583 reg = true; >> 584 break; >> 585 } >> 586 } >> 587 idxSCoffRegions[j] = reg; 318 } 588 } 319 } 589 } 320 590 321 if(1 < verboseLevel) { 591 if(1 < verboseLevel) { 322 G4cout << "G4VEnergyLossProcess::PrepearPh 592 G4cout << "G4VEnergyLossProcess::PrepearPhysicsTable() is done " 323 << " for " << GetProcessName() << " << 593 << " for local " << particle->GetParticleName() 324 << " isIon= " << isIon << " spline= << 594 << " isIon= " << isIon; 325 if(baseParticle) { 595 if(baseParticle) { 326 G4cout << "; base: " << baseParticle->Ge 596 G4cout << "; base: " << baseParticle->GetParticleName(); 327 } 597 } 328 G4cout << G4endl; << 329 G4cout << " chargeSqRatio= " << chargeSqRa 598 G4cout << " chargeSqRatio= " << chargeSqRatio 330 << " massRatio= " << massRatio 599 << " massRatio= " << massRatio 331 << " reduceFactor= " << reduceFacto 600 << " reduceFactor= " << reduceFactor << G4endl; 332 if (nSCoffRegions > 0) { << 601 if (nSCoffRegions) { 333 G4cout << " SubCut secondary production << 602 G4cout << " SubCutoff Regime is ON for regions: " << G4endl; 334 for (G4int i=0; i<nSCoffRegions; ++i) { 603 for (G4int i=0; i<nSCoffRegions; ++i) { 335 const G4Region* r = (*scoffRegions)[i] << 604 const G4Region* r = scoffRegions[i]; 336 G4cout << " " << r->GetName( 605 G4cout << " " << r->GetName() << G4endl; 337 } 606 } 338 } else if(nullptr != subcutProducer) { << 339 G4cout << " SubCut secondary production << 340 } 607 } 341 } 608 } 342 } 609 } 343 610 344 //....oooOO0OOooo........oooOO0OOooo........oo 611 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 345 612 346 void G4VEnergyLossProcess::BuildPhysicsTable(c 613 void G4VEnergyLossProcess::BuildPhysicsTable(const G4ParticleDefinition& part) 347 { 614 { 348 if(1 < verboseLevel) { 615 if(1 < verboseLevel) { 349 G4cout << "### G4VEnergyLossProcess::Build 616 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() for " 350 << GetProcessName() 617 << GetProcessName() 351 << " and particle " << part.GetPart 618 << " and particle " << part.GetParticleName() 352 << "; the first particle " << parti << 619 << "; local: " << particle->GetParticleName(); 353 if(baseParticle) { 620 if(baseParticle) { 354 G4cout << "; base: " << baseParticle->Ge 621 G4cout << "; base: " << baseParticle->GetParticleName(); 355 } 622 } 356 G4cout << G4endl; << 623 G4cout << " TablesAreBuilt= " << tablesAreBuilt 357 G4cout << " TablesAreBuilt= " << tables << 624 << " isIon= " << isIon << " " << this << G4endl; 358 << " spline=" << spline << " ptr: " << 359 } 625 } 360 626 361 if(&part == particle) { 627 if(&part == particle) { >> 628 362 if(isMaster) { 629 if(isMaster) { 363 lManager->BuildPhysicsTable(particle, th 630 lManager->BuildPhysicsTable(particle, this); 364 631 365 } else { 632 } else { 366 const auto masterProcess = << 633 >> 634 const G4VEnergyLossProcess* masterProcess = 367 static_cast<const G4VEnergyLossProcess 635 static_cast<const G4VEnergyLossProcess*>(GetMasterProcess()); 368 636 369 numberOfModels = modelManager->NumberOfM << 637 // copy table pointers from master thread 370 G4EmTableUtil::BuildLocalElossProcess(th << 638 SetDEDXTable(masterProcess->DEDXTable(),fRestricted); 371 pa << 639 SetDEDXTable(masterProcess->DEDXTableForSubsec(),fSubRestricted); >> 640 SetDEDXTable(masterProcess->DEDXunRestrictedTable(),fTotal); >> 641 SetDEDXTable(masterProcess->IonisationTable(),fIsIonisation); >> 642 SetDEDXTable(masterProcess->IonisationTableForSubsec(),fIsSubIonisation); >> 643 SetRangeTableForLoss(masterProcess->RangeTableForLoss()); >> 644 SetCSDARangeTable(masterProcess->CSDARangeTable()); >> 645 SetSecondaryRangeTable(masterProcess->SecondaryRangeTable()); >> 646 SetInverseRangeTable(masterProcess->InverseRangeTable()); >> 647 SetLambdaTable(masterProcess->LambdaTable()); >> 648 SetSubLambdaTable(masterProcess->SubLambdaTable()); >> 649 isIonisation = masterProcess->IsIonisationProcess(); >> 650 372 tablesAreBuilt = true; 651 tablesAreBuilt = true; 373 baseMat = masterProcess->UseBaseMaterial << 652 // local initialisation of models >> 653 G4bool printing = true; >> 654 G4int numberOfModels = modelManager->NumberOfModels(); >> 655 for(G4int i=0; i<numberOfModels; ++i) { >> 656 G4VEmModel* mod = GetModelByIndex(i, printing); >> 657 G4VEmModel* mod0= masterProcess->GetModelByIndex(i,printing); >> 658 mod->InitialiseLocal(particle, mod0); >> 659 } >> 660 374 lManager->LocalPhysicsTables(particle, t 661 lManager->LocalPhysicsTables(particle, this); 375 } 662 } 376 663 377 // needs to be done only once 664 // needs to be done only once 378 safetyHelper->InitialiseHelper(); 665 safetyHelper->InitialiseHelper(); 379 } 666 } 380 // Added tracking cut to avoid tracking arti << 381 // and identified deexcitation flag << 382 if(isIonisation) { << 383 atomDeexcitation = lManager->AtomDeexcitat << 384 if(nullptr != atomDeexcitation) { << 385 if(atomDeexcitation->IsPIXEActive()) { u << 386 } << 387 } << 388 << 389 // protection against double printout << 390 if(theParameters->IsPrintLocked()) { return; << 391 << 392 // explicitly defined printout by particle n 667 // explicitly defined printout by particle name 393 G4String num = part.GetParticleName(); 668 G4String num = part.GetParticleName(); 394 if(1 < verboseLevel || 669 if(1 < verboseLevel || 395 (0 < verboseLevel && (num == "e-" || 670 (0 < verboseLevel && (num == "e-" || 396 num == "e+" || n 671 num == "e+" || num == "mu+" || 397 num == "mu-" || n 672 num == "mu-" || num == "proton"|| 398 num == "pi+" || n 673 num == "pi+" || num == "pi-" || 399 num == "kaon+" || n 674 num == "kaon+" || num == "kaon-" || 400 num == "alpha" || n 675 num == "alpha" || num == "anti_proton" || 401 num == "GenericIon" << 676 num == "GenericIon"|| num == "alpha++" || 402 StreamInfo(G4cout, part); << 677 num == "alpha+" ))) >> 678 { >> 679 StreamInfo(G4cout, part); >> 680 } >> 681 >> 682 // Added tracking cut to avoid tracking artifacts >> 683 // identify deexcitation flag >> 684 if(isIonisation) { >> 685 atomDeexcitation = lManager->AtomDeexcitation(); >> 686 if(nSCoffRegions > 0) { subcutProducer = lManager->SubCutProducer(); } >> 687 if(atomDeexcitation) { >> 688 if(atomDeexcitation->IsPIXEActive()) { useDeexcitation = true; } >> 689 } 403 } 690 } >> 691 /* >> 692 G4cout << "** G4VEnergyLossProcess::BuildPhysicsTable() for " >> 693 << GetProcessName() << " and " << particle->GetParticleName() >> 694 << " isMaster: " << isMaster << " isIonisation: " >> 695 << isIonisation << G4endl; >> 696 G4cout << " theDEDX: " << theDEDXTable >> 697 << " theRange: " << theRangeTableForLoss >> 698 << " theInverse: " << theInverseRangeTable >> 699 << " theLambda: " << theLambdaTable << G4endl; >> 700 */ >> 701 //if(1 < verboseLevel || verb) { 404 if(1 < verboseLevel) { 702 if(1 < verboseLevel) { 405 G4cout << "### G4VEnergyLossProcess::Build 703 G4cout << "### G4VEnergyLossProcess::BuildPhysicsTable() done for " 406 << GetProcessName() 704 << GetProcessName() 407 << " and particle " << part.GetPart 705 << " and particle " << part.GetParticleName(); 408 if(isIonisation) { G4cout << " isIonisati << 706 if(isIonisation) { G4cout << " isIonisation flag = 1"; } 409 G4cout << " baseMat=" << baseMat << G4endl << 707 G4cout << G4endl; 410 } 708 } 411 } 709 } 412 710 413 //....oooOO0OOooo........oooOO0OOooo........oo 711 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 414 712 415 G4PhysicsTable* G4VEnergyLossProcess::BuildDED 713 G4PhysicsTable* G4VEnergyLossProcess::BuildDEDXTable(G4EmTableType tType) 416 { 714 { >> 715 if(1 < verboseLevel ) { >> 716 G4cout << "G4VEnergyLossProcess::BuildDEDXTable() of type " << tType >> 717 << " for " << GetProcessName() >> 718 << " and particle " << particle->GetParticleName() >> 719 << G4endl; >> 720 } 417 G4PhysicsTable* table = nullptr; 721 G4PhysicsTable* table = nullptr; 418 G4double emax = maxKinEnergy; 722 G4double emax = maxKinEnergy; 419 G4int bin = nBins; 723 G4int bin = nBins; 420 724 421 if(fTotal == tType) { 725 if(fTotal == tType) { 422 emax = maxKinEnergyCSDA; 726 emax = maxKinEnergyCSDA; 423 bin = nBinsCSDA; 727 bin = nBinsCSDA; 424 table = theDEDXunRestrictedTable; 728 table = theDEDXunRestrictedTable; 425 } else if(fRestricted == tType) { 729 } else if(fRestricted == tType) { 426 table = theDEDXTable; 730 table = theDEDXTable; >> 731 } else if(fSubRestricted == tType) { >> 732 table = theDEDXSubTable; 427 } else { 733 } else { 428 G4cout << "G4VEnergyLossProcess::BuildDEDX 734 G4cout << "G4VEnergyLossProcess::BuildDEDXTable WARNING: wrong type " 429 << tType << G4endl; 735 << tType << G4endl; 430 } 736 } >> 737 >> 738 // Access to materials >> 739 const G4ProductionCutsTable* theCoupleTable= >> 740 G4ProductionCutsTable::GetProductionCutsTable(); >> 741 size_t numOfCouples = theCoupleTable->GetTableSize(); >> 742 431 if(1 < verboseLevel) { 743 if(1 < verboseLevel) { 432 G4cout << "G4VEnergyLossProcess::BuildDEDX << 744 G4cout << numOfCouples << " materials" 433 << " for " << GetProcessName() << 745 << " minKinEnergy= " << minKinEnergy 434 << " and " << particle->GetParticle << 746 << " maxKinEnergy= " << emax 435 << "spline=" << spline << G4endl; << 747 << " nbin= " << bin >> 748 << " EmTableType= " << tType >> 749 << " table= " << table << " " << this >> 750 << G4endl; 436 } 751 } 437 if(nullptr == table) { return table; } << 752 if(!table) { return table; } 438 753 439 G4LossTableBuilder* bld = lManager->GetTable 754 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 440 G4EmTableUtil::BuildDEDXTable(this, particle << 755 G4bool splineFlag = theParameters->Spline(); 441 table, minKinE << 756 G4PhysicsLogVector* aVector = nullptr; 442 verboseLevel, << 757 G4PhysicsLogVector* bVector = nullptr; >> 758 >> 759 for(size_t i=0; i<numOfCouples; ++i) { >> 760 >> 761 if(1 < verboseLevel) { >> 762 G4cout << "G4VEnergyLossProcess::BuildDEDXVector Idx= " << i >> 763 << " flagTable= " << table->GetFlag(i) >> 764 << " Flag= " << bld->GetFlag(i) << G4endl; >> 765 } >> 766 if(bld->GetFlag(i)) { >> 767 >> 768 // create physics vector and fill it >> 769 const G4MaterialCutsCouple* couple = >> 770 theCoupleTable->GetMaterialCutsCouple(i); >> 771 if((*table)[i]) { delete (*table)[i]; } >> 772 if(bVector) { >> 773 aVector = new G4PhysicsLogVector(*bVector); >> 774 } else { >> 775 bVector = new G4PhysicsLogVector(minKinEnergy, emax, bin); >> 776 aVector = bVector; >> 777 } >> 778 aVector->SetSpline(splineFlag); >> 779 >> 780 modelManager->FillDEDXVector(aVector, couple, tType); >> 781 if(splineFlag) { aVector->FillSecondDerivatives(); } >> 782 >> 783 // Insert vector for this material into the table >> 784 G4PhysicsTableHelper::SetPhysicsVector(table, i, aVector); >> 785 } >> 786 } >> 787 >> 788 if(1 < verboseLevel) { >> 789 G4cout << "G4VEnergyLossProcess::BuildDEDXTable(): table is built for " >> 790 << particle->GetParticleName() >> 791 << " and process " << GetProcessName() >> 792 << G4endl; >> 793 if(2 < verboseLevel) G4cout << (*table) << G4endl; >> 794 } >> 795 443 return table; 796 return table; 444 } 797 } 445 798 446 //....oooOO0OOooo........oooOO0OOooo........oo 799 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 447 800 448 G4PhysicsTable* G4VEnergyLossProcess::BuildLam << 801 G4PhysicsTable* G4VEnergyLossProcess::BuildLambdaTable(G4EmTableType tType) 449 { 802 { 450 if(nullptr == theLambdaTable) { return theLa << 803 G4PhysicsTable* table = nullptr; >> 804 >> 805 if(fRestricted == tType) { >> 806 table = theLambdaTable; >> 807 } else if(fSubRestricted == tType) { >> 808 table = theSubLambdaTable; >> 809 } else { >> 810 G4cout << "G4VEnergyLossProcess::BuildLambdaTable WARNING: wrong type " >> 811 << tType << G4endl; >> 812 } >> 813 >> 814 if(1 < verboseLevel) { >> 815 G4cout << "G4VEnergyLossProcess::BuildLambdaTable() of type " >> 816 << tType << " for process " >> 817 << GetProcessName() << " and particle " >> 818 << particle->GetParticleName() >> 819 << " EmTableType= " << tType >> 820 << " table= " << table >> 821 << G4endl; >> 822 } >> 823 if(!table) {return table;} >> 824 >> 825 // Access to materials >> 826 const G4ProductionCutsTable* theCoupleTable= >> 827 G4ProductionCutsTable::GetProductionCutsTable(); >> 828 size_t numOfCouples = theCoupleTable->GetTableSize(); 451 829 452 G4double scale = theParameters->MaxKinEnergy << 453 G4int nbin = << 454 theParameters->NumberOfBinsPerDecade()*G4l << 455 scale = nbin/G4Log(scale); << 456 << 457 G4LossTableBuilder* bld = lManager->GetTable 830 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 458 G4EmTableUtil::BuildLambdaTable(this, partic << 831 theDensityFactor = bld->GetDensityFactors(); 459 bld, theLamb << 832 theDensityIdx = bld->GetCoupleIndexes(); 460 minKinEnergy << 833 461 verboseLevel << 834 G4bool splineFlag = theParameters->Spline(); 462 return theLambdaTable; << 835 G4PhysicsLogVector* aVector = nullptr; >> 836 G4double scale = G4Log(maxKinEnergy/minKinEnergy); >> 837 >> 838 for(size_t i=0; i<numOfCouples; ++i) { >> 839 >> 840 if (bld->GetFlag(i)) { >> 841 >> 842 // create physics vector and fill it >> 843 const G4MaterialCutsCouple* couple = >> 844 theCoupleTable->GetMaterialCutsCouple(i); >> 845 delete (*table)[i]; >> 846 >> 847 G4bool startNull = true; >> 848 G4double emin = >> 849 MinPrimaryEnergy(particle,couple->GetMaterial(),(*theCuts)[i]); >> 850 if(minKinEnergy > emin) { >> 851 emin = minKinEnergy; >> 852 startNull = false; >> 853 } >> 854 >> 855 G4double emax = maxKinEnergy; >> 856 if(emax <= emin) { emax = 2*emin; } >> 857 G4int bin = G4lrint(nBins*G4Log(emax/emin)/scale); >> 858 bin = std::max(bin, 3); >> 859 aVector = new G4PhysicsLogVector(emin, emax, bin); >> 860 aVector->SetSpline(splineFlag); >> 861 >> 862 modelManager->FillLambdaVector(aVector, couple, startNull, tType); >> 863 if(splineFlag) { aVector->FillSecondDerivatives(); } >> 864 >> 865 // Insert vector for this material into the table >> 866 G4PhysicsTableHelper::SetPhysicsVector(table, i, aVector); >> 867 } >> 868 } >> 869 >> 870 if(1 < verboseLevel) { >> 871 G4cout << "Lambda table is built for " >> 872 << particle->GetParticleName() >> 873 << G4endl; >> 874 } >> 875 >> 876 return table; 463 } 877 } 464 878 465 //....oooOO0OOooo........oooOO0OOooo........oo 879 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 466 880 467 void G4VEnergyLossProcess::StreamInfo(std::ost 881 void G4VEnergyLossProcess::StreamInfo(std::ostream& out, 468 const G4ParticleDefinition& pa 882 const G4ParticleDefinition& part, G4bool rst) const 469 { 883 { 470 G4String indent = (rst ? " " : ""); 884 G4String indent = (rst ? " " : ""); 471 out << std::setprecision(6); 885 out << std::setprecision(6); 472 out << G4endl << indent << GetProcessName() 886 out << G4endl << indent << GetProcessName() << ": "; 473 if (!rst) out << " for " << part.GetParticle 887 if (!rst) out << " for " << part.GetParticleName(); 474 out << " XStype:" << fXSType << 888 out << " SubType=" << GetProcessSubType() << G4endl 475 << " SubType=" << GetProcessSubType() < << 476 << " dE/dx and range tables from " 889 << " dE/dx and range tables from " 477 << G4BestUnit(minKinEnergy,"Energy") 890 << G4BestUnit(minKinEnergy,"Energy") 478 << " to " << G4BestUnit(maxKinEnergy,"En 891 << " to " << G4BestUnit(maxKinEnergy,"Energy") 479 << " in " << nBins << " bins" << G4endl 892 << " in " << nBins << " bins" << G4endl 480 << " Lambda tables from threshold t 893 << " Lambda tables from threshold to " 481 << G4BestUnit(maxKinEnergy,"Energy") 894 << G4BestUnit(maxKinEnergy,"Energy") 482 << ", " << theParameters->NumberOfBinsPe 895 << ", " << theParameters->NumberOfBinsPerDecade() 483 << " bins/decade, spline: " << spline << 896 << " bins/decade, spline: " >> 897 << theParameters->Spline() 484 << G4endl; 898 << G4endl; 485 if(nullptr != theRangeTableForLoss && isIoni << 899 if(theRangeTableForLoss && isIonisation) { 486 out << " StepFunction=(" << dRoverRan 900 out << " StepFunction=(" << dRoverRange << ", " 487 << finalRange/mm << " mm)" 901 << finalRange/mm << " mm)" 488 << ", integ: " << fXSType << 902 << ", integ: " << integral 489 << ", fluct: " << lossFluctuationFlag 903 << ", fluct: " << lossFluctuationFlag 490 << ", linLossLim= " << linLossLimit 904 << ", linLossLim= " << linLossLimit 491 << G4endl; 905 << G4endl; 492 } 906 } 493 StreamProcessInfo(out); 907 StreamProcessInfo(out); 494 modelManager->DumpModelList(out, verboseLeve 908 modelManager->DumpModelList(out, verboseLevel); 495 if(nullptr != theCSDARangeTable && isIonisat << 909 if(theCSDARangeTable && isIonisation) { 496 out << " CSDA range table up" 910 out << " CSDA range table up" 497 << " to " << G4BestUnit(maxKinEnergyCS 911 << " to " << G4BestUnit(maxKinEnergyCSDA,"Energy") 498 << " in " << nBinsCSDA << " bins" << G 912 << " in " << nBinsCSDA << " bins" << G4endl; 499 } 913 } 500 if(nSCoffRegions>0 && isIonisation) { 914 if(nSCoffRegions>0 && isIonisation) { 501 out << " Subcutoff sampling in " << n 915 out << " Subcutoff sampling in " << nSCoffRegions 502 << " regions" << G4endl; 916 << " regions" << G4endl; 503 } 917 } 504 if(2 < verboseLevel) { 918 if(2 < verboseLevel) { 505 for(std::size_t i=0; i<7; ++i) { << 919 out << " DEDXTable address= " << theDEDXTable << G4endl; 506 auto ta = theData->Table(i); << 920 if(theDEDXTable && isIonisation) out << (*theDEDXTable) << G4endl; 507 out << " " << tnames[i] << " addres << 921 out << "non restricted DEDXTable address= " 508 if(nullptr != ta) { out << *ta << G4endl << 922 << theDEDXunRestrictedTable << G4endl; >> 923 if(theDEDXunRestrictedTable && isIonisation) { >> 924 out << (*theDEDXunRestrictedTable) << G4endl; >> 925 } >> 926 if(theDEDXSubTable && isIonisation) { >> 927 out << (*theDEDXSubTable) << G4endl; >> 928 } >> 929 out << " CSDARangeTable address= " << theCSDARangeTable << G4endl; >> 930 if(theCSDARangeTable && isIonisation) { >> 931 out << (*theCSDARangeTable) << G4endl; >> 932 } >> 933 out << " RangeTableForLoss address= " << theRangeTableForLoss >> 934 << G4endl; >> 935 if(theRangeTableForLoss && isIonisation) { >> 936 out << (*theRangeTableForLoss) << G4endl; >> 937 } >> 938 out << " InverseRangeTable address= " << theInverseRangeTable >> 939 << G4endl; >> 940 if(theInverseRangeTable && isIonisation) { >> 941 out << (*theInverseRangeTable) << G4endl; >> 942 } >> 943 out << " LambdaTable address= " << theLambdaTable << G4endl; >> 944 if(theLambdaTable && isIonisation) { >> 945 out << (*theLambdaTable) << G4endl; >> 946 } >> 947 out << " SubLambdaTable address= " << theSubLambdaTable << G4endl; >> 948 if(theSubLambdaTable && isIonisation) { >> 949 out << (*theSubLambdaTable) << G4endl; 509 } 950 } 510 } 951 } 511 } 952 } 512 953 513 //....oooOO0OOooo........oooOO0OOooo........oo 954 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 514 955 515 void G4VEnergyLossProcess::ActivateSubCutoff(c << 956 void G4VEnergyLossProcess::ActivateSubCutoff(G4bool val, const G4Region* r) 516 { 957 { 517 if(nullptr == scoffRegions) { << 958 G4RegionStore* regionStore = G4RegionStore::GetInstance(); 518 scoffRegions = new std::vector<const G4Reg << 959 const G4Region* reg = r; >> 960 if (!reg) { >> 961 reg = regionStore->GetRegion("DefaultRegionForTheWorld", false); 519 } 962 } >> 963 520 // the region is in the list 964 // the region is in the list 521 if(!scoffRegions->empty()) { << 965 if (nSCoffRegions > 0) { 522 for (auto & reg : *scoffRegions) { << 966 for (G4int i=0; i<nSCoffRegions; ++i) { 523 if (reg == r) { return; } << 967 if (reg == scoffRegions[i]) { >> 968 return; >> 969 } 524 } 970 } 525 } 971 } 526 // new region 972 // new region 527 scoffRegions->push_back(r); << 973 if(val) { 528 ++nSCoffRegions; << 974 scoffRegions.push_back(reg); 529 } << 975 ++nSCoffRegions; 530 << 531 //....oooOO0OOooo........oooOO0OOooo........oo << 532 << 533 G4bool G4VEnergyLossProcess::IsRegionForCubcut << 534 { << 535 if(0 == nSCoffRegions) { return true; } << 536 const G4Region* r = aTrack.GetVolume()->GetL << 537 for(auto & reg : *scoffRegions) { << 538 if(r == reg) { return true; } << 539 } 976 } 540 return false; << 541 } 977 } 542 978 543 //....oooOO0OOooo........oooOO0OOooo........oo 979 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 544 980 545 void G4VEnergyLossProcess::StartTracking(G4Tra 981 void G4VEnergyLossProcess::StartTracking(G4Track* track) 546 { 982 { >> 983 /* >> 984 G4cout << track->GetDefinition()->GetParticleName() >> 985 << " e(MeV)= " << track->GetKineticEnergy() >> 986 << " baseParticle " << baseParticle << " proc " << this; >> 987 if(particle) G4cout << " " << particle->GetParticleName(); >> 988 G4cout << " isIon= " << isIon << " dedx " << theDEDXTable <<G4endl; >> 989 */ 547 // reset parameters for the new track 990 // reset parameters for the new track 548 theNumberOfInteractionLengthLeft = -1.0; 991 theNumberOfInteractionLengthLeft = -1.0; 549 mfpKinEnergy = DBL_MAX; << 992 currentInteractionLength = mfpKinEnergy = DBL_MAX; 550 preStepLambda = 0.0; << 993 preStepRangeEnergy = 0.0; 551 currentCouple = nullptr; << 552 994 553 // reset ion 995 // reset ion 554 if(isIon) { 996 if(isIon) { 555 const G4double newmass = track->GetDefinit << 997 chargeSqRatio = 0.5; 556 massRatio = (nullptr == baseParticle) ? CL << 998 557 : baseParticle->GetPDGMass()/newmass; << 999 G4double newmass = track->GetDefinition()->GetPDGMass(); 558 logMassRatio = G4Log(massRatio); << 1000 if(baseParticle) { >> 1001 massRatio = baseParticle->GetPDGMass()/newmass; >> 1002 logMassRatio = G4Log(massRatio); >> 1003 } else if(theGenericIon) { >> 1004 massRatio = proton_mass_c2/newmass; >> 1005 logMassRatio = G4Log(massRatio); >> 1006 } else { >> 1007 massRatio = 1.0; >> 1008 logMassRatio = 0.0; >> 1009 } 559 } 1010 } 560 // forced biasing only for primary particles 1011 // forced biasing only for primary particles 561 if(nullptr != biasManager) { << 1012 if(biasManager) { 562 if(0 == track->GetParentID()) { 1013 if(0 == track->GetParentID()) { >> 1014 // primary particle 563 biasFlag = true; 1015 biasFlag = true; 564 biasManager->ResetForcedInteraction(); 1016 biasManager->ResetForcedInteraction(); 565 } 1017 } 566 } 1018 } 567 } 1019 } 568 1020 569 //....oooOO0OOooo........oooOO0OOooo........oo 1021 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 570 1022 571 G4double G4VEnergyLossProcess::AlongStepGetPhy 1023 G4double G4VEnergyLossProcess::AlongStepGetPhysicalInteractionLength( 572 const G4Track& tr << 1024 const G4Track&,G4double,G4double,G4double&, 573 G4GPILSelection* 1025 G4GPILSelection* selection) 574 { 1026 { 575 G4double x = DBL_MAX; 1027 G4double x = DBL_MAX; 576 *selection = aGPILSelection; 1028 *selection = aGPILSelection; 577 if(isIonisation && currentModel->IsActive(pr 1029 if(isIonisation && currentModel->IsActive(preStepScaledEnergy)) { 578 GetScaledRangeForScaledEnergy(preStepScale << 1030 fRange = reduceFactor*GetScaledRangeForScaledEnergy(preStepScaledEnergy, 579 x = (useCutAsFinalRange) ? std::min(finalR << 1031 preStepLogScaledEnergy); >> 1032 G4double finR = (rndmStepFlag) ? std::min(finalRange, 580 currentCouple->GetProductionCuts()->GetP 1033 currentCouple->GetProductionCuts()->GetProductionCut(1)) : finalRange; 581 x = (fRange > x) ? fRange*dRoverRange + x* << 1034 x = (fRange > finR) ? 582 : fRange; << 1035 fRange*dRoverRange + finR*(1.0-dRoverRange)*(2.0-finR/fRange) : fRange; 583 /* << 1036 // if(particle->GetPDGMass() > 0.9*GeV) 584 G4cout<<"AlongStepGPIL: " << GetProcessN << 1037 /* 585 << " fRange=" << fRange << " finR=" << finR << 1038 G4cout<<GetProcessName()<<": e= "<<preStepKinEnergy >> 1039 <<" range= "<<fRange << " idx= " << basedCoupleIndex >> 1040 << " finR= " << finR >> 1041 << " limit= " << x <<G4endl; >> 1042 G4cout << "massRatio= " << massRatio << " Q^2= " << chargeSqRatio >> 1043 << " finR= " << finR << " dRoverRange= " << dRoverRange >> 1044 << " finalRange= " << finalRange << G4endl; 586 */ 1045 */ 587 } 1046 } >> 1047 //G4cout<<GetProcessName()<<": e= "<<preStepKinEnergy >> 1048 //<<" stepLimit= "<<x<<G4endl; 588 return x; 1049 return x; 589 } 1050 } 590 1051 591 //....oooOO0OOooo........oooOO0OOooo........oo 1052 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 592 1053 593 G4double G4VEnergyLossProcess::PostStepGetPhys 1054 G4double G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength( 594 const G4Track& tr 1055 const G4Track& track, 595 G4double previo 1056 G4double previousStepSize, 596 G4ForceCondition* 1057 G4ForceCondition* condition) 597 { 1058 { 598 // condition is set to "Not Forced" 1059 // condition is set to "Not Forced" 599 *condition = NotForced; 1060 *condition = NotForced; 600 G4double x = DBL_MAX; 1061 G4double x = DBL_MAX; 601 1062 602 // initialisation of material, mass, charge, 1063 // initialisation of material, mass, charge, model 603 // at the beginning of the step 1064 // at the beginning of the step 604 DefineMaterial(track.GetMaterialCutsCouple() 1065 DefineMaterial(track.GetMaterialCutsCouple()); 605 preStepKinEnergy = track.GetKineticEne 1066 preStepKinEnergy = track.GetKineticEnergy(); >> 1067 preStepLogKinEnergy = track.GetDynamicParticle()->GetLogKineticEnergy(); 606 preStepScaledEnergy = preStepKinEnergy*ma 1068 preStepScaledEnergy = preStepKinEnergy*massRatio; >> 1069 preStepLogScaledEnergy = preStepLogKinEnergy + logMassRatio; 607 SelectModel(preStepScaledEnergy); 1070 SelectModel(preStepScaledEnergy); 608 1071 609 if(!currentModel->IsActive(preStepScaledEner 1072 if(!currentModel->IsActive(preStepScaledEnergy)) { 610 theNumberOfInteractionLengthLeft = -1.0; 1073 theNumberOfInteractionLengthLeft = -1.0; 611 mfpKinEnergy = DBL_MAX; << 612 preStepLambda = 0.0; << 613 currentInteractionLength = DBL_MAX; 1074 currentInteractionLength = DBL_MAX; 614 return x; << 1075 return x; 615 } 1076 } 616 1077 617 // change effective charge of a charged part << 1078 // change effective charge of an ion on fly 618 if(isIon) { 1079 if(isIon) { 619 const G4double q2 = currentModel->ChargeSq << 1080 G4double q2 = currentModel->ChargeSquareRatio(track); 620 fFactor = q2*biasFactor; << 1081 if(q2 != chargeSqRatio && q2 > 0.0) { 621 if(baseMat) { fFactor *= (*theDensityFacto << 1082 chargeSqRatio = q2; 622 reduceFactor = 1.0/(fFactor*massRatio); << 1083 fFactor = q2*biasFactor*(*theDensityFactor)[currentCoupleIndex]; 623 if (lossFluctuationFlag) { << 1084 reduceFactor = 1.0/(fFactor*massRatio); 624 auto fluc = currentModel->GetModelOfFluc << 625 fluc->SetParticleAndCharge(track.GetDefi << 626 } 1085 } 627 } 1086 } >> 1087 // if(particle->GetPDGMass() > 0.9*GeV) >> 1088 //G4cout << "q2= "<<chargeSqRatio << " massRatio= " << massRatio << G4endl; 628 1089 629 // forced biasing only for primary particles 1090 // forced biasing only for primary particles 630 if(biasManager) { 1091 if(biasManager) { 631 if(0 == track.GetParentID() && biasFlag && 1092 if(0 == track.GetParentID() && biasFlag && 632 biasManager->ForcedInteractionRegion((G << 1093 biasManager->ForcedInteractionRegion(currentCoupleIndex)) { 633 return biasManager->GetStepLimit((G4int) << 1094 return biasManager->GetStepLimit(currentCoupleIndex, previousStepSize); 634 } 1095 } 635 } 1096 } 636 1097 637 ComputeLambdaForScaledEnergy(preStepScaledEn << 1098 // compute mean free path 638 << 1099 if(preStepScaledEnergy < mfpKinEnergy) { 639 // zero cross section << 1100 if (integral) { 640 if(preStepLambda <= 0.0) { << 1101 ComputeLambdaForScaledEnergy(preStepScaledEnergy, preStepLogScaledEnergy); 641 theNumberOfInteractionLengthLeft = -1.0; << 1102 } else { 642 currentInteractionLength = DBL_MAX; << 1103 preStepLambda = 643 } else { << 1104 GetLambdaForScaledEnergy(preStepScaledEnergy, preStepLogScaledEnergy); >> 1105 } >> 1106 >> 1107 // zero cross section >> 1108 if(preStepLambda <= 0.0) { >> 1109 theNumberOfInteractionLengthLeft = -1.0; >> 1110 currentInteractionLength = DBL_MAX; >> 1111 } >> 1112 } 644 1113 645 // non-zero cross section << 1114 // non-zero cross section >> 1115 if(preStepLambda > 0.0) { 646 if (theNumberOfInteractionLengthLeft < 0.0 1116 if (theNumberOfInteractionLengthLeft < 0.0) { 647 1117 648 // beggining of tracking (or just after 1118 // beggining of tracking (or just after DoIt of this process) 649 theNumberOfInteractionLengthLeft = -G4Lo << 1119 theNumberOfInteractionLengthLeft = -G4Log( G4UniformRand() ); 650 theInitialNumberOfInteractionLength = th 1120 theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft; 651 1121 652 } else if(currentInteractionLength < DBL_M 1122 } else if(currentInteractionLength < DBL_MAX) { 653 1123 654 // subtract NumberOfInteractionLengthLef 1124 // subtract NumberOfInteractionLengthLeft using previous step 655 theNumberOfInteractionLengthLeft -= 1125 theNumberOfInteractionLengthLeft -= 656 previousStepSize/currentInteractionLen 1126 previousStepSize/currentInteractionLength; 657 1127 658 theNumberOfInteractionLengthLeft = 1128 theNumberOfInteractionLengthLeft = 659 std::max(theNumberOfInteractionLengthL 1129 std::max(theNumberOfInteractionLengthLeft, 0.0); 660 } 1130 } 661 1131 662 // new mean free path and step limit 1132 // new mean free path and step limit 663 currentInteractionLength = 1.0/preStepLamb 1133 currentInteractionLength = 1.0/preStepLambda; 664 x = theNumberOfInteractionLengthLeft * cur 1134 x = theNumberOfInteractionLengthLeft * currentInteractionLength; 665 } 1135 } 666 #ifdef G4VERBOSE 1136 #ifdef G4VERBOSE 667 if (verboseLevel>2) { << 1137 if (verboseLevel>2){ >> 1138 // if(particle->GetPDGMass() > 0.9*GeV){ 668 G4cout << "G4VEnergyLossProcess::PostStepG 1139 G4cout << "G4VEnergyLossProcess::PostStepGetPhysicalInteractionLength "; 669 G4cout << "[ " << GetProcessName() << "]" 1140 G4cout << "[ " << GetProcessName() << "]" << G4endl; 670 G4cout << " for " << track.GetDefinition() 1141 G4cout << " for " << track.GetDefinition()->GetParticleName() 671 << " in Material " << currentMate 1142 << " in Material " << currentMaterial->GetName() 672 << " Ekin(MeV)= " << preStepKinEner 1143 << " Ekin(MeV)= " << preStepKinEnergy/MeV 673 << " track material: " << track.Get << 1144 << " " << track.GetMaterial()->GetName() 674 <<G4endl; 1145 <<G4endl; 675 G4cout << "MeanFreePath = " << currentInte 1146 G4cout << "MeanFreePath = " << currentInteractionLength/cm << "[cm]" 676 << "InteractionLength= " << x/cm << 1147 << "InteractionLength= " << x/cm <<"[cm] " <<G4endl; 677 } 1148 } 678 #endif 1149 #endif 679 return x; 1150 return x; 680 } 1151 } 681 1152 682 //....oooOO0OOooo........oooOO0OOooo........oo 1153 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 683 1154 684 void 1155 void 685 G4VEnergyLossProcess::ComputeLambdaForScaledEn << 1156 G4VEnergyLossProcess::ComputeLambdaForScaledEnergy(G4double e, G4double loge) 686 { 1157 { 687 // cross section increased with energy << 1158 // condition to skip recomputation of cross section 688 if(fXSType == fEmIncreasing) { << 1159 const G4double epeak = theEnergyOfCrossSectionMax[currentCoupleIndex]; 689 if(e*invLambdaFactor < mfpKinEnergy) { << 1160 if(e <= epeak && e/lambdaFactor >= mfpKinEnergy) { return; } 690 preStepLambda = GetLambdaForScaledEnergy << 1161 691 mfpKinEnergy = (preStepLambda > 0.0) ? e << 1162 // recomputation is needed 692 } << 1163 if (e <= epeak) { 693 << 1164 preStepLambda = GetLambdaForScaledEnergy(e, loge); 694 // cross section has one peak << 1165 mfpKinEnergy = e; 695 } else if(fXSType == fEmOnePeak) { << 1166 } else { 696 const G4double epeak = (*theEnergyOfCrossS << 1167 const G4double e1 = e*lambdaFactor; 697 if(e <= epeak) { << 1168 if (e1 > epeak) { 698 if(e*invLambdaFactor < mfpKinEnergy) { << 1169 preStepLambda = GetLambdaForScaledEnergy(e, loge); 699 preStepLambda = GetLambdaForScaledEner << 1170 mfpKinEnergy = e; 700 mfpKinEnergy = (preStepLambda > 0.0) ? << 1171 const G4double preStepLambda1 = 701 } << 1172 GetLambdaForScaledEnergy(e1, loge+logLambdafactor); 702 } else if(e < mfpKinEnergy) { << 1173 if (preStepLambda1 > preStepLambda) { 703 const G4double e1 = std::max(epeak, e*la << 1174 mfpKinEnergy = e1; 704 mfpKinEnergy = e1; << 1175 preStepLambda = preStepLambda1; 705 preStepLambda = GetLambdaForScaledEnergy << 706 } << 707 << 708 // cross section has more than one peaks << 709 } else if(fXSType == fEmTwoPeaks) { << 710 G4TwoPeaksXS* xs = (*fXSpeaks)[basedCouple << 711 const G4double e1peak = xs->e1peak; << 712 << 713 // below the 1st peak << 714 if(e <= e1peak) { << 715 if(e*invLambdaFactor < mfpKinEnergy) { << 716 preStepLambda = GetLambdaForScaledEner << 717 mfpKinEnergy = (preStepLambda > 0.0) ? << 718 } << 719 return; << 720 } << 721 const G4double e1deep = xs->e1deep; << 722 // above the 1st peak, below the deep << 723 if(e <= e1deep) { << 724 if(mfpKinEnergy >= e1deep || e <= mfpKin << 725 const G4double e1 = std::max(e1peak, e << 726 mfpKinEnergy = e1; << 727 preStepLambda = GetLambdaForScaledEner << 728 } << 729 return; << 730 } << 731 const G4double e2peak = xs->e2peak; << 732 // above the deep, below 2nd peak << 733 if(e <= e2peak) { << 734 if(e*invLambdaFactor < mfpKinEnergy) { << 735 mfpKinEnergy = e; << 736 preStepLambda = GetLambdaForScaledEner << 737 } << 738 return; << 739 } << 740 const G4double e2deep = xs->e2deep; << 741 // above the 2nd peak, below the deep << 742 if(e <= e2deep) { << 743 if(mfpKinEnergy >= e2deep || e <= mfpKin << 744 const G4double e1 = std::max(e2peak, e << 745 mfpKinEnergy = e1; << 746 preStepLambda = GetLambdaForScaledEner << 747 } << 748 return; << 749 } << 750 const G4double e3peak = xs->e3peak; << 751 // above the deep, below 3d peak << 752 if(e <= e3peak) { << 753 if(e*invLambdaFactor < mfpKinEnergy) { << 754 mfpKinEnergy = e; << 755 preStepLambda = GetLambdaForScaledEner << 756 } 1176 } 757 return; << 1177 } else { 758 } << 1178 preStepLambda = fFactor*theCrossSectionMax[currentCoupleIndex]; 759 // above 3d peak << 1179 mfpKinEnergy = epeak; 760 if(e <= mfpKinEnergy) { << 761 const G4double e1 = std::max(e3peak, e*l << 762 mfpKinEnergy = e1; << 763 preStepLambda = GetLambdaForScaledEnergy << 764 } 1180 } 765 // integral method is not used << 766 } else { << 767 preStepLambda = GetLambdaForScaledEnergy(e << 768 } 1181 } 769 } 1182 } 770 1183 771 //....oooOO0OOooo........oooOO0OOooo........oo 1184 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 772 1185 773 G4VParticleChange* G4VEnergyLossProcess::Along 1186 G4VParticleChange* G4VEnergyLossProcess::AlongStepDoIt(const G4Track& track, 774 1187 const G4Step& step) 775 { 1188 { 776 fParticleChange.InitializeForAlongStep(track 1189 fParticleChange.InitializeForAlongStep(track); 777 // The process has range table - calculate e 1190 // The process has range table - calculate energy loss 778 if(!isIonisation || !currentModel->IsActive( 1191 if(!isIonisation || !currentModel->IsActive(preStepScaledEnergy)) { 779 return &fParticleChange; 1192 return &fParticleChange; 780 } 1193 } 781 1194 >> 1195 // Get the actual (true) Step length 782 G4double length = step.GetStepLength(); 1196 G4double length = step.GetStepLength(); >> 1197 if(length <= 0.0) { return &fParticleChange; } 783 G4double eloss = 0.0; 1198 G4double eloss = 0.0; 784 1199 785 /* << 1200 /* 786 if(-1 < verboseLevel) { 1201 if(-1 < verboseLevel) { 787 const G4ParticleDefinition* d = track.GetP 1202 const G4ParticleDefinition* d = track.GetParticleDefinition(); 788 G4cout << "AlongStepDoIt for " 1203 G4cout << "AlongStepDoIt for " 789 << GetProcessName() << " and partic << 1204 << GetProcessName() << " and particle " 790 << " eScaled(MeV)=" << preStepScal << 1205 << d->GetParticleName() 791 << " range(mm)=" << fRange/mm << " << 1206 << " eScaled(MeV)= " << preStepScaledEnergy/MeV 792 << " rf=" << reduceFactor << " q^ << 1207 << " range(mm)= " << fRange/mm 793 << " md=" << d->GetPDGMass() << " << 1208 << " s(mm)= " << length/mm 794 << " " << track.GetMaterial()->Get << 1209 << " rf= " << reduceFactor >> 1210 << " q^2= " << chargeSqRatio >> 1211 << " md= " << d->GetPDGMass() >> 1212 << " status= " << track.GetTrackStatus() >> 1213 << " " << track.GetMaterial()->GetName() >> 1214 << G4endl; 795 } 1215 } 796 */ 1216 */ >> 1217 797 const G4DynamicParticle* dynParticle = track 1218 const G4DynamicParticle* dynParticle = track.GetDynamicParticle(); 798 1219 799 // define new weight for primary and seconda 1220 // define new weight for primary and secondaries 800 G4double weight = fParticleChange.GetParentW 1221 G4double weight = fParticleChange.GetParentWeight(); 801 if(weightFlag) { 1222 if(weightFlag) { 802 weight /= biasFactor; 1223 weight /= biasFactor; 803 fParticleChange.ProposeWeight(weight); 1224 fParticleChange.ProposeWeight(weight); 804 } 1225 } 805 1226 806 // stopping, check actual range and kinetic << 1227 // stopping 807 if (length >= fRange || preStepKinEnergy <= 1228 if (length >= fRange || preStepKinEnergy <= lowestKinEnergy) { 808 eloss = preStepKinEnergy; 1229 eloss = preStepKinEnergy; 809 if (useDeexcitation) { 1230 if (useDeexcitation) { 810 atomDeexcitation->AlongStepDeexcitation( 1231 atomDeexcitation->AlongStepDeexcitation(scTracks, step, 811 << 1232 eloss, currentCoupleIndex); 812 if(scTracks.size() > 0) { FillSecondarie << 1233 if(scTracks.size() > 0) { FillSecondariesAlongStep(eloss, weight); } 813 eloss = std::max(eloss, 0.0); 1234 eloss = std::max(eloss, 0.0); 814 } 1235 } 815 fParticleChange.SetProposedKineticEnergy(0 1236 fParticleChange.SetProposedKineticEnergy(0.0); 816 fParticleChange.ProposeLocalEnergyDeposit( 1237 fParticleChange.ProposeLocalEnergyDeposit(eloss); 817 return &fParticleChange; 1238 return &fParticleChange; 818 } 1239 } 819 // zero step length with non-zero range << 1240 //G4cout << theDEDXTable << " idx= " << basedCoupleIndex 820 if(length <= 0.0) { return &fParticleChange; << 1241 // << " " << GetProcessName() << " "<< currentMaterial->GetName()<<G4endl; 821 << 1242 //if(particle->GetParticleName() == "e-")G4cout << (*theDEDXTable) <<G4endl; 822 // Short step 1243 // Short step 823 eloss = length*GetDEDXForScaledEnergy(preSte << 1244 eloss = GetDEDXForScaledEnergy(preStepScaledEnergy, preStepLogScaledEnergy); 824 LogSca << 1245 eloss *= length; 825 /* << 1246 826 G4cout << "##### Short STEP: eloss= " << elo << 1247 //G4cout << "eloss= " << eloss << G4endl; 827 << " Escaled=" << preStepScaledEnergy << 1248 828 << " R=" << fRange << 829 << " L=" << length << 830 << " fFactor=" << fFactor << " minE=" << mi << 831 << " idxBase=" << basedCoupleIndex << G4end << 832 */ << 833 // Long step 1249 // Long step 834 if(eloss > preStepKinEnergy*linLossLimit) { 1250 if(eloss > preStepKinEnergy*linLossLimit) { 835 1251 836 const G4double x = (fRange - length)/reduc << 1252 G4double x = (fRange - length)/reduceFactor; 837 const G4double de = preStepKinEnergy - Sca << 1253 //G4cout << "x= " << x << " " << theInverseRangeTable << G4endl; 838 if(de > 0.0) { eloss = de; } << 1254 eloss = preStepKinEnergy - ScaledKinEnergyForLoss(x)/massRatio; >> 1255 839 /* 1256 /* 840 if(-1 < verboseLevel) 1257 if(-1 < verboseLevel) 841 G4cout << " Long STEP: rPre(mm)=" << 1258 G4cout << "Long STEP: rPre(mm)= " 842 << GetScaledRangeForScaledEnergy( 1259 << GetScaledRangeForScaledEnergy(preStepScaledEnergy)/mm 843 << " x(mm)=" << x/mm << 1260 << " rPost(mm)= " << x/mm 844 << " eloss(MeV)=" << eloss/MeV << 1261 << " ePre(MeV)= " << preStepScaledEnergy/MeV 845 << " rFactor=" << reduceFactor << 1262 << " eloss(MeV)= " << eloss/MeV 846 << " massRatio=" << massRatio << 1263 << " eloss0(MeV)= " >> 1264 << GetDEDXForScaledEnergy(preStepScaledEnergy)*length/MeV >> 1265 << " lim(MeV)= " << preStepKinEnergy*linLossLimit/MeV 847 << G4endl; 1266 << G4endl; 848 */ 1267 */ 849 } 1268 } 850 1269 851 /* << 1270 /* >> 1271 G4double eloss0 = eloss; 852 if(-1 < verboseLevel ) { 1272 if(-1 < verboseLevel ) { 853 G4cout << "Before fluct: eloss(MeV)= " << 1273 G4cout << "Before fluct: eloss(MeV)= " << eloss/MeV 854 << " e-eloss= " << preStepKinEnergy 1274 << " e-eloss= " << preStepKinEnergy-eloss 855 << " step(mm)= " << length/mm << " << 1275 << " step(mm)= " << length/mm 856 << " fluct= " << lossFluctuationFla << 1276 << " range(mm)= " << fRange/mm >> 1277 << " fluct= " << lossFluctuationFlag >> 1278 << G4endl; 857 } 1279 } 858 */ 1280 */ 859 1281 860 const G4double cut = (*theCuts)[currentCoupl << 1282 G4double cut = (*theCuts)[currentCoupleIndex]; 861 G4double esec = 0.0; 1283 G4double esec = 0.0; 862 1284 >> 1285 //G4cout << "cut= " << cut << " useSubCut= " << useSubCutoff << G4endl; >> 1286 >> 1287 // SubCutOff >> 1288 if(useSubCutoff && !subcutProducer) { >> 1289 if(idxSCoffRegions[currentCoupleIndex]) { >> 1290 >> 1291 G4bool yes = false; >> 1292 const G4StepPoint* prePoint = step.GetPreStepPoint(); >> 1293 >> 1294 // Check boundary >> 1295 if(prePoint->GetStepStatus() == fGeomBoundary) { yes = true; } >> 1296 >> 1297 // Check PrePoint >> 1298 else { >> 1299 G4double preSafety = prePoint->GetSafety(); >> 1300 G4double rcut = >> 1301 currentCouple->GetProductionCuts()->GetProductionCut(1); >> 1302 >> 1303 // recompute presafety >> 1304 if(preSafety < rcut) { >> 1305 preSafety = safetyHelper->ComputeSafety(prePoint->GetPosition(), >> 1306 rcut); >> 1307 } >> 1308 >> 1309 if(preSafety < rcut) { yes = true; } >> 1310 >> 1311 // Check PostPoint >> 1312 else { >> 1313 G4double postSafety = preSafety - length; >> 1314 if(postSafety < rcut) { >> 1315 postSafety = safetyHelper->ComputeSafety( >> 1316 step.GetPostStepPoint()->GetPosition(), rcut); >> 1317 if(postSafety < rcut) { yes = true; } >> 1318 } >> 1319 } >> 1320 } >> 1321 >> 1322 // Decided to start subcut sampling >> 1323 if(yes) { >> 1324 >> 1325 cut = (*theSubCuts)[currentCoupleIndex]; >> 1326 eloss -= GetSubDEDXForScaledEnergy(preStepScaledEnergy)*length; >> 1327 esec = SampleSubCutSecondaries(scTracks, step, >> 1328 currentModel,currentCoupleIndex); >> 1329 // add bremsstrahlung sampling >> 1330 /* >> 1331 if(nProcesses > 0) { >> 1332 for(G4int i=0; i<nProcesses; ++i) { >> 1333 (scProcesses[i])->SampleSubCutSecondaries( >> 1334 scTracks, step, (scProcesses[i])-> >> 1335 SelectModelForMaterial(preStepKinEnergy, currentCoupleIndex), >> 1336 currentCoupleIndex); >> 1337 } >> 1338 } >> 1339 */ >> 1340 } >> 1341 } >> 1342 } >> 1343 863 // Corrections, which cannot be tabulated 1344 // Corrections, which cannot be tabulated 864 if(isIon) { 1345 if(isIon) { >> 1346 G4double eadd = 0.0; >> 1347 G4double eloss_before = eloss; 865 currentModel->CorrectionsAlongStep(current 1348 currentModel->CorrectionsAlongStep(currentCouple, dynParticle, 866 length, << 1349 eloss, eadd, length); 867 eloss = std::max(eloss, 0.0); << 1350 if(eloss < 0.0) { eloss = 0.5*eloss_before; } 868 } 1351 } 869 1352 870 // Sample fluctuations if not full energy lo << 1353 // Sample fluctuations 871 if(eloss >= preStepKinEnergy) { << 1354 if (lossFluctuationFlag) { 872 eloss = preStepKinEnergy; << 873 << 874 } else if (lossFluctuationFlag) { << 875 const G4double tmax = currentModel->MaxSec << 876 const G4double tcut = std::min(cut, tmax); << 877 G4VEmFluctuationModel* fluc = currentModel 1355 G4VEmFluctuationModel* fluc = currentModel->GetModelOfFluctuations(); 878 eloss = fluc->SampleFluctuations(currentCo << 1356 if(eloss + esec < preStepKinEnergy) { 879 tcut, tma << 1357 880 /* << 1358 G4double tmax = 881 if(-1 < verboseLevel) << 1359 std::min(currentModel->MaxSecondaryKinEnergy(dynParticle),cut); >> 1360 eloss = fluc->SampleFluctuations(currentCouple,dynParticle, >> 1361 tmax,length,eloss); >> 1362 /* >> 1363 if(-1 < verboseLevel) 882 G4cout << "After fluct: eloss(MeV)= " << 1364 G4cout << "After fluct: eloss(MeV)= " << eloss/MeV 883 << " fluc= " << (eloss-eloss0)/Me 1365 << " fluc= " << (eloss-eloss0)/MeV 884 << " ChargeSqRatio= " << chargeSq 1366 << " ChargeSqRatio= " << chargeSqRatio 885 << " massRatio= " << massRatio << << 1367 << " massRatio= " << massRatio 886 */ << 1368 << " tmax= " << tmax >> 1369 << G4endl; >> 1370 */ >> 1371 } 887 } 1372 } 888 1373 889 // deexcitation 1374 // deexcitation 890 if (useDeexcitation) { 1375 if (useDeexcitation) { 891 G4double esecfluo = preStepKinEnergy; << 1376 G4double esecfluo = preStepKinEnergy - esec; 892 G4double de = esecfluo; 1377 G4double de = esecfluo; >> 1378 //G4double eloss0 = eloss; >> 1379 /* >> 1380 G4cout << "### 1: E(keV)= " << preStepKinEnergy/keV >> 1381 << " Efluomax(keV)= " << de/keV >> 1382 << " Eloss(keV)= " << eloss/keV << G4endl; >> 1383 */ 893 atomDeexcitation->AlongStepDeexcitation(sc 1384 atomDeexcitation->AlongStepDeexcitation(scTracks, step, 894 de << 1385 de, currentCoupleIndex); 895 1386 896 // sum of de-excitation energies 1387 // sum of de-excitation energies 897 esecfluo -= de; 1388 esecfluo -= de; 898 1389 899 // subtracted from energy loss 1390 // subtracted from energy loss 900 if(eloss >= esecfluo) { 1391 if(eloss >= esecfluo) { 901 esec += esecfluo; 1392 esec += esecfluo; 902 eloss -= esecfluo; 1393 eloss -= esecfluo; 903 } else { 1394 } else { 904 esec += esecfluo; 1395 esec += esecfluo; 905 eloss = 0.0; 1396 eloss = 0.0; 906 } 1397 } >> 1398 /* >> 1399 if(esecfluo > 0.0) { >> 1400 G4cout << "### 2: E(keV)= " << preStepKinEnergy/keV >> 1401 << " Esec(keV)= " << esec/keV >> 1402 << " Esecf(kV)= " << esecfluo/keV >> 1403 << " Eloss0(kV)= " << eloss0/keV >> 1404 << " Eloss(keV)= " << eloss/keV >> 1405 << G4endl; >> 1406 } >> 1407 */ 907 } 1408 } 908 if(nullptr != subcutProducer && IsRegionForC << 1409 if(subcutProducer && idxSCoffRegions[currentCoupleIndex]) { 909 subcutProducer->SampleSecondaries(step, sc 1410 subcutProducer->SampleSecondaries(step, scTracks, eloss, cut); 910 } 1411 } 911 // secondaries from atomic de-excitation and << 1412 if(scTracks.size() > 0) { FillSecondariesAlongStep(eloss, weight); } 912 if(!scTracks.empty()) { FillSecondariesAlong << 913 1413 914 // Energy balance 1414 // Energy balance 915 G4double finalT = preStepKinEnergy - eloss - 1415 G4double finalT = preStepKinEnergy - eloss - esec; 916 if (finalT <= lowestKinEnergy) { 1416 if (finalT <= lowestKinEnergy) { 917 eloss += finalT; 1417 eloss += finalT; 918 finalT = 0.0; 1418 finalT = 0.0; 919 } else if(isIon) { 1419 } else if(isIon) { 920 fParticleChange.SetProposedCharge( 1420 fParticleChange.SetProposedCharge( 921 currentModel->GetParticleCharge(track.Ge 1421 currentModel->GetParticleCharge(track.GetParticleDefinition(), 922 currentM 1422 currentMaterial,finalT)); 923 } 1423 } >> 1424 924 eloss = std::max(eloss, 0.0); 1425 eloss = std::max(eloss, 0.0); 925 1426 926 fParticleChange.SetProposedKineticEnergy(fin 1427 fParticleChange.SetProposedKineticEnergy(finalT); 927 fParticleChange.ProposeLocalEnergyDeposit(el 1428 fParticleChange.ProposeLocalEnergyDeposit(eloss); 928 /* 1429 /* 929 if(-1 < verboseLevel) { 1430 if(-1 < verboseLevel) { 930 G4double del = finalT + eloss + esec - pre 1431 G4double del = finalT + eloss + esec - preStepKinEnergy; 931 G4cout << "Final value eloss(MeV)= " << el 1432 G4cout << "Final value eloss(MeV)= " << eloss/MeV 932 << " preStepKinEnergy= " << preStep 1433 << " preStepKinEnergy= " << preStepKinEnergy 933 << " postStepKinEnergy= " << finalT 1434 << " postStepKinEnergy= " << finalT 934 << " de(keV)= " << del/keV 1435 << " de(keV)= " << del/keV 935 << " lossFlag= " << lossFluctuation 1436 << " lossFlag= " << lossFluctuationFlag 936 << " status= " << track.GetTrackSt 1437 << " status= " << track.GetTrackStatus() 937 << G4endl; 1438 << G4endl; 938 } 1439 } 939 */ 1440 */ 940 return &fParticleChange; 1441 return &fParticleChange; 941 } 1442 } 942 1443 943 //....oooOO0OOooo........oooOO0OOooo........oo 1444 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 944 1445 945 void G4VEnergyLossProcess::FillSecondariesAlon << 1446 void >> 1447 G4VEnergyLossProcess::FillSecondariesAlongStep(G4double&, G4double& weight) 946 { 1448 { 947 const std::size_t n0 = scTracks.size(); << 1449 G4int n0 = scTracks.size(); 948 G4double weight = wt; << 1450 949 // weight may be changed by biasing manager 1451 // weight may be changed by biasing manager 950 if(biasManager) { 1452 if(biasManager) { 951 if(biasManager->SecondaryBiasingRegion((G4 << 1453 if(biasManager->SecondaryBiasingRegion(currentCoupleIndex)) { 952 weight *= 1454 weight *= 953 biasManager->ApplySecondaryBiasing(scT << 1455 biasManager->ApplySecondaryBiasing(scTracks, currentCoupleIndex); 954 } 1456 } 955 } 1457 } 956 1458 957 // fill secondaries 1459 // fill secondaries 958 const std::size_t n = scTracks.size(); << 1460 G4int n = scTracks.size(); 959 fParticleChange.SetNumberOfSecondaries((G4in << 1461 fParticleChange.SetNumberOfSecondaries(n); 960 1462 961 for(std::size_t i=0; i<n; ++i) { << 1463 for(G4int i=0; i<n; ++i) { 962 G4Track* t = scTracks[i]; 1464 G4Track* t = scTracks[i]; 963 if(nullptr != t) { << 1465 if(t) { 964 t->SetWeight(weight); 1466 t->SetWeight(weight); 965 pParticleChange->AddSecondary(t); 1467 pParticleChange->AddSecondary(t); 966 G4int pdg = t->GetDefinition()->GetPDGEn << 1468 if(i >= n0) { t->SetCreatorModelIndex(biasID); } 967 if (i < n0) { << 1469 //G4cout << "Secondary(along step) has weight " << t->GetWeight() 968 if (pdg == 22) { << 1470 //<< ", kenergy " << t->GetKineticEnergy()/MeV << " MeV" <<G4endl; 969 t->SetCreatorModelID(gpixeID); << 970 } else if (pdg == 11) { << 971 t->SetCreatorModelID(epixeID); << 972 } else { << 973 t->SetCreatorModelID(biasID); << 974 } << 975 } else { << 976 t->SetCreatorModelID(biasID); << 977 } << 978 } 1471 } 979 } 1472 } 980 scTracks.clear(); 1473 scTracks.clear(); 981 } 1474 } 982 1475 983 //....oooOO0OOooo........oooOO0OOooo........oo 1476 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 984 1477 >> 1478 G4double >> 1479 G4VEnergyLossProcess::SampleSubCutSecondaries(std::vector<G4Track*>& tracks, >> 1480 const G4Step& step, >> 1481 G4VEmModel* model, >> 1482 G4int idx) >> 1483 { >> 1484 // Fast check weather subcutoff can work >> 1485 G4double esec = 0.0; >> 1486 G4double subcut = (*theSubCuts)[idx]; >> 1487 G4double cut = (*theCuts)[idx]; >> 1488 if(cut <= subcut) { return esec; } >> 1489 >> 1490 const G4Track* track = step.GetTrack(); >> 1491 const G4DynamicParticle* dp = track->GetDynamicParticle(); >> 1492 G4double e = dp->GetKineticEnergy()*massRatio; >> 1493 G4double cross = (*theDensityFactor)[idx]*chargeSqRatio >> 1494 *(((*theSubLambdaTable)[(*theDensityIdx)[idx]])->Value(e, idxSubLambda)); >> 1495 G4double length = step.GetStepLength(); >> 1496 >> 1497 // negligible probability to get any interaction >> 1498 if(length*cross < perMillion) { return esec; } >> 1499 /* >> 1500 if(-1 < verboseLevel) >> 1501 G4cout << "<<< Subcutoff for " << GetProcessName() >> 1502 << " cross(1/mm)= " << cross*mm << ">>>" >> 1503 << " e(MeV)= " << preStepScaledEnergy >> 1504 << " matIdx= " << currentCoupleIndex >> 1505 << G4endl; >> 1506 */ >> 1507 >> 1508 // Sample subcutoff secondaries >> 1509 G4StepPoint* preStepPoint = step.GetPreStepPoint(); >> 1510 G4StepPoint* postStepPoint = step.GetPostStepPoint(); >> 1511 G4ThreeVector prepoint = preStepPoint->GetPosition(); >> 1512 G4ThreeVector dr = postStepPoint->GetPosition() - prepoint; >> 1513 G4double pretime = preStepPoint->GetGlobalTime(); >> 1514 G4double dt = postStepPoint->GetGlobalTime() - pretime; >> 1515 G4double fragment = 0.0; >> 1516 >> 1517 do { >> 1518 G4double del = -G4Log(G4UniformRand())/cross; >> 1519 fragment += del/length; >> 1520 if (fragment > 1.0) { break; } >> 1521 >> 1522 // sample secondaries >> 1523 secParticles.clear(); >> 1524 model->SampleSecondaries(&secParticles,track->GetMaterialCutsCouple(), >> 1525 dp,subcut,cut); >> 1526 >> 1527 // position of subcutoff particles >> 1528 G4ThreeVector r = prepoint + fragment*dr; >> 1529 std::vector<G4DynamicParticle*>::iterator it; >> 1530 for(it=secParticles.begin(); it!=secParticles.end(); ++it) { >> 1531 >> 1532 G4Track* t = new G4Track((*it), pretime + fragment*dt, r); >> 1533 t->SetTouchableHandle(track->GetTouchableHandle()); >> 1534 t->SetCreatorModelIndex(subsecID); >> 1535 tracks.push_back(t); >> 1536 esec += t->GetKineticEnergy(); >> 1537 if (t->GetParticleDefinition() == thePositron) { >> 1538 esec += 2.0*electron_mass_c2; >> 1539 } >> 1540 >> 1541 /* >> 1542 if(-1 < verboseLevel) >> 1543 G4cout << "New track " >> 1544 << t->GetParticleDefinition()->GetParticleName() >> 1545 << " e(keV)= " << t->GetKineticEnergy()/keV >> 1546 << " fragment= " << fragment >> 1547 << G4endl; >> 1548 */ >> 1549 } >> 1550 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko >> 1551 } while (fragment <= 1.0); >> 1552 return esec; >> 1553 } >> 1554 >> 1555 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 1556 985 G4VParticleChange* G4VEnergyLossProcess::PostS 1557 G4VParticleChange* G4VEnergyLossProcess::PostStepDoIt(const G4Track& track, 986 1558 const G4Step& step) 987 { 1559 { 988 // clear number of interaction lengths in an << 1560 // In all cases clear number of interaction lengths 989 theNumberOfInteractionLengthLeft = -1.0; 1561 theNumberOfInteractionLengthLeft = -1.0; 990 mfpKinEnergy = DBL_MAX; << 1562 mfpKinEnergy = currentInteractionLength = DBL_MAX; 991 1563 992 fParticleChange.InitializeForPostStep(track) 1564 fParticleChange.InitializeForPostStep(track); 993 const G4double finalT = track.GetKineticEner << 1565 G4double finalT = track.GetKineticEnergy(); >> 1566 if(finalT <= lowestKinEnergy) { return &fParticleChange; } 994 1567 995 const G4double postStepScaledEnergy = finalT << 1568 G4double postStepScaledEnergy = finalT*massRatio; 996 SelectModel(postStepScaledEnergy); 1569 SelectModel(postStepScaledEnergy); 997 1570 998 if(!currentModel->IsActive(postStepScaledEne 1571 if(!currentModel->IsActive(postStepScaledEnergy)) { 999 return &fParticleChange; 1572 return &fParticleChange; 1000 } 1573 } 1001 /* 1574 /* 1002 if(1 < verboseLevel) { << 1575 if(-1 < verboseLevel) { 1003 G4cout<<GetProcessName()<<" PostStepDoIt: << 1576 G4cout << GetProcessName() >> 1577 << "::PostStepDoIt: E(MeV)= " << finalT/MeV >> 1578 << G4endl; 1004 } 1579 } 1005 */ 1580 */ >> 1581 1006 // forced process - should happen only once 1582 // forced process - should happen only once per track 1007 if(biasFlag) { 1583 if(biasFlag) { 1008 if(biasManager->ForcedInteractionRegion(( << 1584 if(biasManager->ForcedInteractionRegion(currentCoupleIndex)) { 1009 biasFlag = false; 1585 biasFlag = false; 1010 } 1586 } 1011 } 1587 } >> 1588 1012 const G4DynamicParticle* dp = track.GetDyna 1589 const G4DynamicParticle* dp = track.GetDynamicParticle(); >> 1590 const G4double logFinalT = dp->GetLogKineticEnergy(); >> 1591 // postStepLogScaledEnergy = logFinalT + logMassRatio; 1013 1592 1014 // Integral approach 1593 // Integral approach 1015 if (fXSType != fEmNoIntegral) { << 1594 if (integral) { 1016 const G4double logFinalT = dp->GetLogKine << 1595 const G4double lx = GetLambdaForScaledEnergy(postStepScaledEnergy, 1017 G4double lx = GetLambdaForScaledEnergy(po << 1596 logFinalT + logMassRatio); 1018 lo << 1597 /* 1019 lx = std::max(lx, 0.0); << 1598 if(preStepLambda<lx && 1 < verboseLevel) { 1020 << 1599 G4cout << "WARNING: for " << particle->GetParticleName() 1021 // if both lg and lx are zero then no int << 1600 << " and " << GetProcessName() 1022 if(preStepLambda*G4UniformRand() >= lx) { << 1601 << " E(MeV)= " << finalT/MeV >> 1602 << " preLambda= " << preStepLambda >> 1603 << " < " << lx << " (postLambda) " >> 1604 << G4endl; >> 1605 } >> 1606 */ >> 1607 if(lx <= 0.0 || preStepLambda*G4UniformRand() > lx) { 1023 return &fParticleChange; 1608 return &fParticleChange; 1024 } 1609 } 1025 } 1610 } 1026 1611 >> 1612 SelectModel(postStepScaledEnergy); >> 1613 1027 // define new weight for primary and second 1614 // define new weight for primary and secondaries 1028 G4double weight = fParticleChange.GetParent 1615 G4double weight = fParticleChange.GetParentWeight(); 1029 if(weightFlag) { 1616 if(weightFlag) { 1030 weight /= biasFactor; 1617 weight /= biasFactor; 1031 fParticleChange.ProposeWeight(weight); 1618 fParticleChange.ProposeWeight(weight); 1032 } 1619 } 1033 1620 1034 const G4double tcut = (*theCuts)[currentCou << 1621 G4double tcut = (*theCuts)[currentCoupleIndex]; 1035 1622 1036 // sample secondaries 1623 // sample secondaries 1037 secParticles.clear(); 1624 secParticles.clear(); >> 1625 //G4cout<< "@@@ Eprimary= "<<dynParticle->GetKineticEnergy()/MeV >> 1626 // << " cut= " << tcut/MeV << G4endl; 1038 currentModel->SampleSecondaries(&secParticl 1627 currentModel->SampleSecondaries(&secParticles, currentCouple, dp, tcut); 1039 1628 1040 const G4int num0 = (G4int)secParticles.size << 1629 G4int num0 = secParticles.size(); 1041 1630 1042 // bremsstrahlung splitting or Russian roul 1631 // bremsstrahlung splitting or Russian roulette 1043 if(biasManager) { 1632 if(biasManager) { 1044 if(biasManager->SecondaryBiasingRegion((G << 1633 if(biasManager->SecondaryBiasingRegion(currentCoupleIndex)) { 1045 G4double eloss = 0.0; 1634 G4double eloss = 0.0; 1046 weight *= biasManager->ApplySecondaryBi 1635 weight *= biasManager->ApplySecondaryBiasing( 1047 secPart 1636 secParticles, 1048 track, 1637 track, currentModel, 1049 &fParti 1638 &fParticleChange, eloss, 1050 (G4int) << 1639 currentCoupleIndex, tcut, 1051 step.Ge 1640 step.GetPostStepPoint()->GetSafety()); 1052 if(eloss > 0.0) { 1641 if(eloss > 0.0) { 1053 eloss += fParticleChange.GetLocalEner 1642 eloss += fParticleChange.GetLocalEnergyDeposit(); 1054 fParticleChange.ProposeLocalEnergyDep 1643 fParticleChange.ProposeLocalEnergyDeposit(eloss); 1055 } 1644 } 1056 } 1645 } 1057 } 1646 } 1058 1647 1059 // save secondaries 1648 // save secondaries 1060 const G4int num = (G4int)secParticles.size( << 1649 G4int num = secParticles.size(); 1061 if(num > 0) { 1650 if(num > 0) { 1062 1651 1063 fParticleChange.SetNumberOfSecondaries(nu 1652 fParticleChange.SetNumberOfSecondaries(num); 1064 G4double time = track.GetGlobalTime(); 1653 G4double time = track.GetGlobalTime(); 1065 1654 1066 G4int n1(0), n2(0); << 1067 if(num0 > mainSecondaries) { << 1068 currentModel->FillNumberOfSecondaries(n << 1069 } << 1070 << 1071 for (G4int i=0; i<num; ++i) { 1655 for (G4int i=0; i<num; ++i) { 1072 if(nullptr != secParticles[i]) { << 1656 if(secParticles[i]) { 1073 G4Track* t = new G4Track(secParticles 1657 G4Track* t = new G4Track(secParticles[i], time, track.GetPosition()); 1074 t->SetTouchableHandle(track.GetToucha 1658 t->SetTouchableHandle(track.GetTouchableHandle()); 1075 if (biasManager) { 1659 if (biasManager) { 1076 t->SetWeight(weight * biasManager-> 1660 t->SetWeight(weight * biasManager->GetWeight(i)); 1077 } else { 1661 } else { 1078 t->SetWeight(weight); 1662 t->SetWeight(weight); 1079 } 1663 } 1080 if(i < num0) { << 1664 if(i < num0) { t->SetCreatorModelIndex(secID); } 1081 t->SetCreatorModelID(secID); << 1665 else { t->SetCreatorModelIndex(biasID); } 1082 } else if(i < num0 + n1) { << 1083 t->SetCreatorModelID(tripletID); << 1084 } else { << 1085 t->SetCreatorModelID(biasID); << 1086 } << 1087 1666 1088 //G4cout << "Secondary(post step) has 1667 //G4cout << "Secondary(post step) has weight " << t->GetWeight() 1089 // << ", kenergy " << t->GetKin 1668 // << ", kenergy " << t->GetKineticEnergy()/MeV << " MeV" 1090 // << " time= " << time/ns << " 1669 // << " time= " << time/ns << " ns " << G4endl; 1091 pParticleChange->AddSecondary(t); 1670 pParticleChange->AddSecondary(t); 1092 } 1671 } 1093 } 1672 } 1094 } 1673 } 1095 1674 1096 if(0.0 == fParticleChange.GetProposedKineti 1675 if(0.0 == fParticleChange.GetProposedKineticEnergy() && 1097 fAlive == fParticleChange.GetTrackStatus 1676 fAlive == fParticleChange.GetTrackStatus()) { 1098 if(particle->GetProcessManager()->GetAtRe 1677 if(particle->GetProcessManager()->GetAtRestProcessVector()->size() > 0) 1099 { fParticleChange.ProposeTrackStatus 1678 { fParticleChange.ProposeTrackStatus(fStopButAlive); } 1100 else { fParticleChange.ProposeTrackStatus 1679 else { fParticleChange.ProposeTrackStatus(fStopAndKill); } 1101 } 1680 } 1102 1681 1103 /* 1682 /* 1104 if(-1 < verboseLevel) { 1683 if(-1 < verboseLevel) { 1105 G4cout << "::PostStepDoIt: Sample seconda 1684 G4cout << "::PostStepDoIt: Sample secondary; Efin= " 1106 << fParticleChange.GetProposedKineticEner 1685 << fParticleChange.GetProposedKineticEnergy()/MeV 1107 << " MeV; model= (" << currentMode 1686 << " MeV; model= (" << currentModel->LowEnergyLimit() 1108 << ", " << currentModel->HighEner 1687 << ", " << currentModel->HighEnergyLimit() << ")" 1109 << " preStepLambda= " << preStepL 1688 << " preStepLambda= " << preStepLambda 1110 << " dir= " << track.GetMomentumD 1689 << " dir= " << track.GetMomentumDirection() 1111 << " status= " << track.GetTrackS 1690 << " status= " << track.GetTrackStatus() 1112 << G4endl; 1691 << G4endl; 1113 } 1692 } 1114 */ 1693 */ 1115 return &fParticleChange; 1694 return &fParticleChange; 1116 } 1695 } 1117 1696 1118 //....oooOO0OOooo........oooOO0OOooo........o 1697 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1119 1698 1120 G4bool G4VEnergyLossProcess::StorePhysicsTabl 1699 G4bool G4VEnergyLossProcess::StorePhysicsTable( 1121 const G4ParticleDefinition* part, cons << 1700 const G4ParticleDefinition* part, const G4String& directory, >> 1701 G4bool ascii) 1122 { 1702 { 1123 if (!isMaster || nullptr != baseParticle || << 1703 G4bool res = true; 1124 for(std::size_t i=0; i<7; ++i) { << 1704 //G4cout << "G4VEnergyLossProcess::StorePhysicsTable: " << part->GetParticleName() 1125 // ionisation table only for ionisation p << 1705 // << " " << directory << " " << ascii << G4endl; 1126 if (nullptr == theData->Table(i) || (!isI << 1706 if (!isMaster || baseParticle || part != particle ) return res; 1127 continue; << 1707 1128 } << 1708 if(!StoreTable(part,theDEDXTable,ascii,directory,"DEDX")) 1129 if (-1 < verboseLevel) { << 1709 {res = false;} 1130 G4cout << "G4VEnergyLossProcess::StoreP << 1710 1131 << " " << particle->GetParticleName() << 1711 if(!StoreTable(part,theDEDXunRestrictedTable,ascii,directory,"DEDXnr")) 1132 << " " << GetProcessName() << 1712 {res = false;} 1133 << " " << tnames[i] << " " << theDat << 1713 1134 } << 1714 if(!StoreTable(part,theDEDXSubTable,ascii,directory,"SubDEDX")) 1135 if (!G4EmTableUtil::StoreTable(this, part << 1715 {res = false;} 1136 dir, tnames[i], verboseLevel, asci << 1716 1137 return false; << 1717 if(!StoreTable(part,theIonisationTable,ascii,directory,"Ionisation")) 1138 } << 1718 {res = false;} 1139 } << 1719 1140 return true; << 1720 if(!StoreTable(part,theIonisationSubTable,ascii,directory,"SubIonisation")) >> 1721 {res = false;} >> 1722 >> 1723 if(isIonisation && >> 1724 !StoreTable(part,theCSDARangeTable,ascii,directory,"CSDARange")) >> 1725 {res = false;} >> 1726 >> 1727 if(isIonisation && >> 1728 !StoreTable(part,theRangeTableForLoss,ascii,directory,"Range")) >> 1729 {res = false;} >> 1730 >> 1731 if(isIonisation && >> 1732 !StoreTable(part,theInverseRangeTable,ascii,directory,"InverseRange")) >> 1733 {res = false;} >> 1734 >> 1735 if(!StoreTable(part,theLambdaTable,ascii,directory,"Lambda")) >> 1736 {res = false;} >> 1737 >> 1738 if(!StoreTable(part,theSubLambdaTable,ascii,directory,"SubLambda")) >> 1739 {res = false;} >> 1740 >> 1741 return res; 1141 } 1742 } 1142 1743 1143 //....oooOO0OOooo........oooOO0OOooo........o 1744 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 1144 1745 1145 G4bool 1746 G4bool 1146 G4VEnergyLossProcess::RetrievePhysicsTable(co 1747 G4VEnergyLossProcess::RetrievePhysicsTable(const G4ParticleDefinition* part, 1147 co << 1748 const G4String& directory, >> 1749 G4bool ascii) 1148 { 1750 { 1149 if (!isMaster || nullptr != baseParticle || << 1751 G4bool res = true; 1150 for(std::size_t i=0; i<7; ++i) { << 1752 if (!isMaster) return res; 1151 // ionisation table only for ionisation p << 1753 const G4String& particleName = part->GetParticleName(); 1152 if (!isIonisation && 1 == i) { continue; << 1754 1153 if(!G4EmTableUtil::RetrieveTable(this, pa << 1755 if(1 < verboseLevel) { 1154 verboseL << 1756 G4cout << "G4VEnergyLossProcess::RetrievePhysicsTable() for " 1155 return false; << 1757 << particleName << " and process " << GetProcessName() >> 1758 << "; tables_are_built= " << tablesAreBuilt >> 1759 << G4endl; >> 1760 } >> 1761 if(particle == part) { >> 1762 >> 1763 if ( !baseParticle ) { >> 1764 >> 1765 G4bool fpi = true; >> 1766 if(!RetrieveTable(part,theDEDXTable,ascii,directory,"DEDX",fpi)) >> 1767 {fpi = false;} >> 1768 >> 1769 // ionisation table keeps individual dEdx and not sum of sub-processes >> 1770 if(!RetrieveTable(part,theDEDXTable,ascii,directory,"Ionisation",false)) >> 1771 {fpi = false;} >> 1772 >> 1773 if(!RetrieveTable(part,theRangeTableForLoss,ascii,directory,"Range",fpi)) >> 1774 {res = false;} >> 1775 >> 1776 if(!RetrieveTable(part,theDEDXunRestrictedTable,ascii,directory, >> 1777 "DEDXnr",false)) >> 1778 {res = false;} >> 1779 >> 1780 if(!RetrieveTable(part,theCSDARangeTable,ascii,directory, >> 1781 "CSDARange",false)) >> 1782 {res = false;} >> 1783 >> 1784 if(!RetrieveTable(part,theInverseRangeTable,ascii,directory, >> 1785 "InverseRange",fpi)) >> 1786 {res = false;} >> 1787 >> 1788 if(!RetrieveTable(part,theLambdaTable,ascii,directory,"Lambda",true)) >> 1789 {res = false;} >> 1790 >> 1791 G4bool yes = false; >> 1792 if(nSCoffRegions > 0) {yes = true;} >> 1793 >> 1794 if(!RetrieveTable(part,theDEDXSubTable,ascii,directory,"SubDEDX",yes)) >> 1795 {res = false;} >> 1796 >> 1797 if(!RetrieveTable(part,theSubLambdaTable,ascii,directory, >> 1798 "SubLambda",yes)) >> 1799 {res = false;} >> 1800 >> 1801 if(!fpi) yes = false; >> 1802 if(!RetrieveTable(part,theIonisationSubTable,ascii,directory, >> 1803 "SubIonisation",yes)) >> 1804 {res = false;} 1156 } 1805 } 1157 } 1806 } >> 1807 >> 1808 return res; >> 1809 } >> 1810 >> 1811 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... >> 1812 >> 1813 G4bool G4VEnergyLossProcess::StoreTable(const G4ParticleDefinition* part, >> 1814 G4PhysicsTable* aTable, G4bool ascii, >> 1815 const G4String& directory, >> 1816 const G4String& tname) >> 1817 { >> 1818 G4bool res = true; >> 1819 if ( aTable ) { >> 1820 const G4String& name = GetPhysicsTableFileName(part, directory, tname, ascii); >> 1821 if ( aTable->StorePhysicsTable(name,ascii) ) { >> 1822 if (0 < verboseLevel) G4cout << "Stored: " << name << G4endl; >> 1823 } else { >> 1824 res = false; >> 1825 G4cout << "Fail to store: " << name << G4endl; >> 1826 } >> 1827 } >> 1828 return res; >> 1829 } >> 1830 >> 1831 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... >> 1832 >> 1833 G4bool >> 1834 G4VEnergyLossProcess::RetrieveTable(const G4ParticleDefinition* part, >> 1835 G4PhysicsTable* aTable, >> 1836 G4bool ascii, >> 1837 const G4String& directory, >> 1838 const G4String& tname, >> 1839 G4bool mandatory) >> 1840 { >> 1841 G4bool isRetrieved = false; >> 1842 G4String filename = GetPhysicsTableFileName(part,directory,tname,ascii); >> 1843 if(aTable) { >> 1844 if(aTable->ExistPhysicsTable(filename)) { >> 1845 if(G4PhysicsTableHelper::RetrievePhysicsTable(aTable,filename,ascii)) { >> 1846 isRetrieved = true; >> 1847 if(theParameters->Spline()) { >> 1848 size_t n = aTable->length(); >> 1849 for(size_t i=0; i<n; ++i) { >> 1850 if((*aTable)[i]) { (*aTable)[i]->SetSpline(true); } >> 1851 } >> 1852 } >> 1853 if (0 < verboseLevel) { >> 1854 G4cout << tname << " table for " << part->GetParticleName() >> 1855 << " is Retrieved from <" << filename << ">" >> 1856 << G4endl; >> 1857 } >> 1858 } >> 1859 } >> 1860 } >> 1861 if(mandatory && !isRetrieved) { >> 1862 if(0 < verboseLevel) { >> 1863 G4cout << tname << " table for " << part->GetParticleName() >> 1864 << " from file <" >> 1865 << filename << "> is not Retrieved" >> 1866 << G4endl; >> 1867 } >> 1868 return false; >> 1869 } 1158 return true; 1870 return true; 1159 } 1871 } 1160 1872 1161 //....oooOO0OOooo........oooOO0OOooo........o 1873 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1162 1874 1163 G4double G4VEnergyLossProcess::GetDEDXDispers 1875 G4double G4VEnergyLossProcess::GetDEDXDispersion( 1164 const G4Mat 1876 const G4MaterialCutsCouple *couple, 1165 const G4Dyn 1877 const G4DynamicParticle* dp, 1166 G4dou 1878 G4double length) 1167 { 1879 { 1168 DefineMaterial(couple); 1880 DefineMaterial(couple); 1169 G4double ekin = dp->GetKineticEnergy(); 1881 G4double ekin = dp->GetKineticEnergy(); 1170 SelectModel(ekin*massRatio); 1882 SelectModel(ekin*massRatio); 1171 G4double tmax = currentModel->MaxSecondaryK 1883 G4double tmax = currentModel->MaxSecondaryKinEnergy(dp); 1172 G4double tcut = std::min(tmax,(*theCuts)[cu << 1884 tmax = std::min(tmax,(*theCuts)[currentCoupleIndex]); 1173 G4double d = 0.0; 1885 G4double d = 0.0; 1174 G4VEmFluctuationModel* fm = currentModel->G 1886 G4VEmFluctuationModel* fm = currentModel->GetModelOfFluctuations(); 1175 if(nullptr != fm) { d = fm->Dispersion(curr << 1887 if(fm) { d = fm->Dispersion(currentMaterial,dp,tmax,length); } 1176 return d; 1888 return d; 1177 } 1889 } 1178 1890 1179 //....oooOO0OOooo........oooOO0OOooo........o 1891 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1180 1892 1181 G4double 1893 G4double 1182 G4VEnergyLossProcess::CrossSectionPerVolume(G 1894 G4VEnergyLossProcess::CrossSectionPerVolume(G4double kineticEnergy, 1183 c 1895 const G4MaterialCutsCouple* couple, 1184 G 1896 G4double logKineticEnergy) 1185 { 1897 { 1186 // Cross section per volume is calculated 1898 // Cross section per volume is calculated 1187 DefineMaterial(couple); 1899 DefineMaterial(couple); 1188 G4double cross = 0.0; 1900 G4double cross = 0.0; 1189 if (nullptr != theLambdaTable) { << 1901 if (theLambdaTable) { 1190 cross = GetLambdaForScaledEnergy(kineticE 1902 cross = GetLambdaForScaledEnergy(kineticEnergy * massRatio, 1191 logKinet 1903 logKineticEnergy + logMassRatio); 1192 } else { 1904 } else { 1193 SelectModel(kineticEnergy*massRatio); 1905 SelectModel(kineticEnergy*massRatio); 1194 cross = (!baseMat) ? biasFactor : biasFac << 1906 cross = biasFactor*(*theDensityFactor)[currentCoupleIndex] 1195 cross *= (currentModel->CrossSectionPerVo << 1907 *(currentModel->CrossSectionPerVolume(currentMaterial, 1196 << 1908 particle, kineticEnergy, >> 1909 (*theCuts)[currentCoupleIndex])); 1197 } 1910 } 1198 return std::max(cross, 0.0); 1911 return std::max(cross, 0.0); 1199 } 1912 } 1200 1913 1201 //....oooOO0OOooo........oooOO0OOooo........o 1914 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1202 1915 1203 G4double G4VEnergyLossProcess::MeanFreePath(c 1916 G4double G4VEnergyLossProcess::MeanFreePath(const G4Track& track) 1204 { 1917 { 1205 DefineMaterial(track.GetMaterialCutsCouple( 1918 DefineMaterial(track.GetMaterialCutsCouple()); 1206 const G4double kinEnergy = track.GetKine 1919 const G4double kinEnergy = track.GetKineticEnergy(); 1207 const G4double logKinEnergy = track.GetDyna 1920 const G4double logKinEnergy = track.GetDynamicParticle()->GetLogKineticEnergy(); 1208 const G4double cs = GetLambdaForScaledEnerg 1921 const G4double cs = GetLambdaForScaledEnergy(kinEnergy * massRatio, 1209 1922 logKinEnergy + logMassRatio); 1210 return (0.0 < cs) ? 1.0/cs : DBL_MAX; 1923 return (0.0 < cs) ? 1.0/cs : DBL_MAX; 1211 } 1924 } 1212 1925 1213 //....oooOO0OOooo........oooOO0OOooo........o 1926 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1214 1927 1215 G4double G4VEnergyLossProcess::ContinuousStep 1928 G4double G4VEnergyLossProcess::ContinuousStepLimit(const G4Track& track, 1216 1929 G4double x, G4double y, 1217 1930 G4double& z) 1218 { 1931 { 1219 return AlongStepGetPhysicalInteractionLengt << 1932 G4GPILSelection sel; >> 1933 return AlongStepGetPhysicalInteractionLength(track, x, y, z, &sel); 1220 } 1934 } 1221 1935 1222 //....oooOO0OOooo........oooOO0OOooo........o 1936 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1223 1937 1224 G4double G4VEnergyLossProcess::GetMeanFreePat 1938 G4double G4VEnergyLossProcess::GetMeanFreePath( 1225 const G4Track& t 1939 const G4Track& track, 1226 G4double, 1940 G4double, 1227 G4ForceCondition 1941 G4ForceCondition* condition) 1228 1942 1229 { 1943 { 1230 *condition = NotForced; 1944 *condition = NotForced; 1231 return MeanFreePath(track); 1945 return MeanFreePath(track); 1232 } 1946 } 1233 1947 1234 //....oooOO0OOooo........oooOO0OOooo........o 1948 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1235 1949 1236 G4double G4VEnergyLossProcess::GetContinuousS 1950 G4double G4VEnergyLossProcess::GetContinuousStepLimit( 1237 const G4Track&, 1951 const G4Track&, 1238 G4double, G4double, G4double& 1952 G4double, G4double, G4double&) 1239 { 1953 { 1240 return DBL_MAX; 1954 return DBL_MAX; 1241 } 1955 } 1242 1956 1243 //....oooOO0OOooo........oooOO0OOooo........o 1957 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1244 1958 1245 G4PhysicsVector* 1959 G4PhysicsVector* 1246 G4VEnergyLossProcess::LambdaPhysicsVector(con << 1960 G4VEnergyLossProcess::LambdaPhysicsVector(const G4MaterialCutsCouple*, 1247 G4d 1961 G4double) 1248 { 1962 { 1249 DefineMaterial(couple); << 1963 G4PhysicsVector* v = 1250 G4PhysicsVector* v = (*theLambdaTable)[base << 1964 new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nBins); 1251 return new G4PhysicsVector(*v); << 1965 v->SetSpline(theParameters->Spline()); >> 1966 return v; >> 1967 } >> 1968 >> 1969 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 1970 >> 1971 void G4VEnergyLossProcess::AddCollaborativeProcess( >> 1972 G4VEnergyLossProcess* p) >> 1973 { >> 1974 G4bool add = true; >> 1975 if(p->GetProcessName() != "eBrem") { add = false; } >> 1976 if(add && nProcesses > 0) { >> 1977 for(G4int i=0; i<nProcesses; ++i) { >> 1978 if(p == scProcesses[i]) { >> 1979 add = false; >> 1980 break; >> 1981 } >> 1982 } >> 1983 } >> 1984 if(add) { >> 1985 scProcesses.push_back(p); >> 1986 ++nProcesses; >> 1987 if (1 < verboseLevel) { >> 1988 G4cout << "### The process " << p->GetProcessName() >> 1989 << " is added to the list of collaborative processes of " >> 1990 << GetProcessName() << G4endl; >> 1991 } >> 1992 } 1252 } 1993 } 1253 1994 1254 //....oooOO0OOooo........oooOO0OOooo........o 1995 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1255 1996 1256 void 1997 void 1257 G4VEnergyLossProcess::SetDEDXTable(G4PhysicsT 1998 G4VEnergyLossProcess::SetDEDXTable(G4PhysicsTable* p, G4EmTableType tType) 1258 { 1999 { 1259 if(1 < verboseLevel) { << 1260 G4cout << "### Set DEDX table " << p << " << 1261 << " " << theDEDXunRestrictedTable << << 1262 << " for " << particle->GetParticl << 1263 << " and process " << GetProcessNa << 1264 << " type=" << tType << " isIonisation:" << 1265 } << 1266 if(fTotal == tType) { 2000 if(fTotal == tType) { 1267 theDEDXunRestrictedTable = p; 2001 theDEDXunRestrictedTable = p; >> 2002 if(p) { >> 2003 size_t n = p->length(); >> 2004 G4PhysicsVector* pv = (*p)[0]; >> 2005 G4double emax = maxKinEnergyCSDA; >> 2006 >> 2007 G4LossTableBuilder* bld = lManager->GetTableBuilder(); >> 2008 theDensityFactor = bld->GetDensityFactors(); >> 2009 theDensityIdx = bld->GetCoupleIndexes(); >> 2010 >> 2011 for (size_t i=0; i<n; ++i) { >> 2012 G4double dedx = 0.0; >> 2013 pv = (*p)[i]; >> 2014 if(pv) { >> 2015 dedx = pv->Value(emax, idxDEDXunRestricted); >> 2016 } else { >> 2017 pv = (*p)[(*theDensityIdx)[i]]; >> 2018 if(pv) { >> 2019 dedx = >> 2020 pv->Value(emax, idxDEDXunRestricted)*(*theDensityFactor)[i]; >> 2021 } >> 2022 } >> 2023 theDEDXAtMaxEnergy[i] = dedx; >> 2024 //G4cout << "i= " << i << " emax(MeV)= " << emax/MeV<< " dedx= " >> 2025 // << dedx << G4endl; >> 2026 } >> 2027 } >> 2028 1268 } else if(fRestricted == tType) { 2029 } else if(fRestricted == tType) { >> 2030 /* >> 2031 G4cout<< "G4VEnergyLossProcess::SetDEDXTable " >> 2032 << particle->GetParticleName() >> 2033 << " oldTable " << theDEDXTable << " newTable " << p >> 2034 << " ion " << theIonisationTable >> 2035 << " IsMaster " << isMaster >> 2036 << " " << GetProcessName() << G4endl; >> 2037 G4cout << (*p) << G4endl; >> 2038 */ 1269 theDEDXTable = p; 2039 theDEDXTable = p; 1270 if(isMaster && nullptr == baseParticle) { << 2040 } else if(fSubRestricted == tType) { 1271 theData->UpdateTable(theDEDXTable, 0); << 2041 theDEDXSubTable = p; 1272 } << 1273 } else if(fIsIonisation == tType) { 2042 } else if(fIsIonisation == tType) { >> 2043 /* >> 2044 G4cout<< "G4VEnergyLossProcess::SetIonisationTable " >> 2045 << particle->GetParticleName() >> 2046 << " oldTable " << theDEDXTable << " newTable " << p >> 2047 << " ion " << theIonisationTable >> 2048 << " IsMaster " << isMaster >> 2049 << " " << GetProcessName() << G4endl; >> 2050 */ 1274 theIonisationTable = p; 2051 theIonisationTable = p; 1275 if(isMaster && nullptr == baseParticle) { << 2052 } else if(fIsSubIonisation == tType) { 1276 theData->UpdateTable(theIonisationTable << 2053 theIonisationSubTable = p; 1277 } << 1278 } 2054 } 1279 } 2055 } 1280 2056 1281 //....oooOO0OOooo........oooOO0OOooo........o 2057 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1282 2058 1283 void G4VEnergyLossProcess::SetCSDARangeTable( 2059 void G4VEnergyLossProcess::SetCSDARangeTable(G4PhysicsTable* p) 1284 { 2060 { 1285 theCSDARangeTable = p; << 2061 theCSDARangeTable = p; >> 2062 >> 2063 if(p) { >> 2064 size_t n = p->length(); >> 2065 G4PhysicsVector* pv; >> 2066 G4double emax = maxKinEnergyCSDA; >> 2067 >> 2068 for (size_t i=0; i<n; ++i) { >> 2069 pv = (*p)[i]; >> 2070 G4double rmax = 0.0; >> 2071 if(pv) { rmax = pv->Value(emax, idxCSDA); } >> 2072 else { >> 2073 pv = (*p)[(*theDensityIdx)[i]]; >> 2074 if(pv) { rmax = pv->Value(emax, idxCSDA)/(*theDensityFactor)[i]; } >> 2075 } >> 2076 theRangeAtMaxEnergy[i] = rmax; >> 2077 //G4cout << "i= " << i << " Emax(MeV)= " << emax/MeV << " Rmax= " >> 2078 //<< rmax<< G4endl; >> 2079 } >> 2080 } 1286 } 2081 } 1287 2082 1288 //....oooOO0OOooo........oooOO0OOooo........o 2083 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1289 2084 1290 void G4VEnergyLossProcess::SetRangeTableForLo 2085 void G4VEnergyLossProcess::SetRangeTableForLoss(G4PhysicsTable* p) 1291 { 2086 { 1292 theRangeTableForLoss = p; 2087 theRangeTableForLoss = p; >> 2088 if(1 < verboseLevel) { >> 2089 G4cout << "### Set Range table " << p >> 2090 << " for " << particle->GetParticleName() >> 2091 << " and process " << GetProcessName() << G4endl; >> 2092 } >> 2093 } >> 2094 >> 2095 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 2096 >> 2097 void G4VEnergyLossProcess::SetSecondaryRangeTable(G4PhysicsTable* p) >> 2098 { >> 2099 theSecondaryRangeTable = p; >> 2100 if(1 < verboseLevel) { >> 2101 G4cout << "### Set SecondaryRange table " << p >> 2102 << " for " << particle->GetParticleName() >> 2103 << " and process " << GetProcessName() << G4endl; >> 2104 } 1293 } 2105 } 1294 2106 1295 //....oooOO0OOooo........oooOO0OOooo........o 2107 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1296 2108 1297 void G4VEnergyLossProcess::SetInverseRangeTab 2109 void G4VEnergyLossProcess::SetInverseRangeTable(G4PhysicsTable* p) 1298 { 2110 { 1299 theInverseRangeTable = p; 2111 theInverseRangeTable = p; >> 2112 if(1 < verboseLevel) { >> 2113 G4cout << "### Set InverseRange table " << p >> 2114 << " for " << particle->GetParticleName() >> 2115 << " and process " << GetProcessName() << G4endl; >> 2116 } 1300 } 2117 } 1301 2118 1302 //....oooOO0OOooo........oooOO0OOooo........o 2119 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1303 2120 1304 void G4VEnergyLossProcess::SetLambdaTable(G4P 2121 void G4VEnergyLossProcess::SetLambdaTable(G4PhysicsTable* p) 1305 { 2122 { 1306 if(1 < verboseLevel) { 2123 if(1 < verboseLevel) { 1307 G4cout << "### Set Lambda table " << p << << 2124 G4cout << "### Set Lambda table " << p 1308 << " for " << particle->GetParticl 2125 << " for " << particle->GetParticleName() 1309 << " and process " << GetProcessNa 2126 << " and process " << GetProcessName() << G4endl; >> 2127 //G4cout << *p << G4endl; 1310 } 2128 } 1311 theLambdaTable = p; << 2129 theLambdaTable = p; 1312 tablesAreBuilt = true; 2130 tablesAreBuilt = true; 1313 2131 1314 if(isMaster && nullptr != p) { << 2132 G4LossTableBuilder* bld = lManager->GetTableBuilder(); 1315 delete theEnergyOfCrossSectionMax; << 2133 theDensityFactor = bld->GetDensityFactors(); 1316 theEnergyOfCrossSectionMax = nullptr; << 2134 theDensityIdx = bld->GetCoupleIndexes(); 1317 if(fEmTwoPeaks == fXSType) { << 2135 1318 if(nullptr != fXSpeaks) { << 2136 if(theLambdaTable) { 1319 for(auto & ptr : *fXSpeaks) { delete ptr; } << 2137 size_t n = theLambdaTable->length(); 1320 delete fXSpeaks; << 2138 G4PhysicsVector* pv = (*theLambdaTable)[0]; >> 2139 G4double e, ss, smax, emax; >> 2140 >> 2141 size_t i; >> 2142 >> 2143 // first loop on existing vectors >> 2144 for (i=0; i<n; ++i) { >> 2145 pv = (*theLambdaTable)[i]; >> 2146 if(pv) { >> 2147 size_t nb = pv->GetVectorLength(); >> 2148 emax = DBL_MAX; >> 2149 smax = 0.0; >> 2150 if(nb > 0) { >> 2151 for (size_t j=0; j<nb; ++j) { >> 2152 e = pv->Energy(j); >> 2153 ss = (*pv)(j); >> 2154 if(ss > smax) { >> 2155 smax = ss; >> 2156 emax = e; >> 2157 } >> 2158 } >> 2159 } >> 2160 theEnergyOfCrossSectionMax[i] = emax; >> 2161 theCrossSectionMax[i] = smax; >> 2162 if(1 < verboseLevel) { >> 2163 G4cout << "For " << particle->GetParticleName() >> 2164 << " Max CS at i= " << i << " emax(MeV)= " << emax/MeV >> 2165 << " lambda= " << smax << G4endl; >> 2166 } 1321 } 2167 } 1322 G4LossTableBuilder* bld = lManager->Get << 1323 fXSpeaks = G4EmUtility::FillPeaksStruct << 1324 if(nullptr == fXSpeaks) { fXSType = fEm << 1325 } 2168 } 1326 if(fXSType == fEmOnePeak) { << 2169 // second loop using base materials 1327 theEnergyOfCrossSectionMax = G4EmUtilit << 2170 for (i=0; i<n; ++i) { 1328 if(nullptr == theEnergyOfCrossSectionMa << 2171 pv = (*theLambdaTable)[i]; >> 2172 if(!pv){ >> 2173 G4int j = (*theDensityIdx)[i]; >> 2174 theEnergyOfCrossSectionMax[i] = theEnergyOfCrossSectionMax[j]; >> 2175 theCrossSectionMax[i] = (*theDensityFactor)[i]*theCrossSectionMax[j]; >> 2176 } 1329 } 2177 } 1330 } 2178 } 1331 } 2179 } 1332 2180 1333 //....oooOO0OOooo........oooOO0OOooo........o 2181 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1334 2182 1335 void G4VEnergyLossProcess::SetEnergyOfCrossSe << 2183 void G4VEnergyLossProcess::SetSubLambdaTable(G4PhysicsTable* p) 1336 { << 1337 theEnergyOfCrossSectionMax = p; << 1338 } << 1339 << 1340 //....oooOO0OOooo........oooOO0OOooo........o << 1341 << 1342 void G4VEnergyLossProcess::SetTwoPeaksXS(std: << 1343 { 2184 { 1344 fXSpeaks = ptr; << 2185 theSubLambdaTable = p; >> 2186 if(1 < verboseLevel) { >> 2187 G4cout << "### Set SebLambda table " << p >> 2188 << " for " << particle->GetParticleName() >> 2189 << " and process " << GetProcessName() << G4endl; >> 2190 } 1345 } 2191 } 1346 2192 1347 //....oooOO0OOooo........oooOO0OOooo........o 2193 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1348 2194 1349 const G4Element* G4VEnergyLossProcess::GetCur 2195 const G4Element* G4VEnergyLossProcess::GetCurrentElement() const 1350 { 2196 { 1351 return (nullptr != currentModel) << 2197 const G4Element* elm = nullptr; 1352 ? currentModel->GetCurrentElement(current << 2198 if(currentModel) { elm = currentModel->GetCurrentElement(); } >> 2199 return elm; 1353 } 2200 } 1354 2201 1355 //....oooOO0OOooo........oooOO0OOooo........o 2202 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1356 2203 1357 void G4VEnergyLossProcess::SetCrossSectionBia 2204 void G4VEnergyLossProcess::SetCrossSectionBiasingFactor(G4double f, 1358 2205 G4bool flag) 1359 { 2206 { 1360 if(f > 0.0) { 2207 if(f > 0.0) { 1361 biasFactor = f; 2208 biasFactor = f; 1362 weightFlag = flag; 2209 weightFlag = flag; 1363 if(1 < verboseLevel) { 2210 if(1 < verboseLevel) { 1364 G4cout << "### SetCrossSectionBiasingFa 2211 G4cout << "### SetCrossSectionBiasingFactor: for " 1365 << " process " << GetProcessName 2212 << " process " << GetProcessName() 1366 << " biasFactor= " << f << " wei 2213 << " biasFactor= " << f << " weightFlag= " << flag 1367 << G4endl; 2214 << G4endl; 1368 } 2215 } 1369 } 2216 } 1370 } 2217 } 1371 2218 1372 //....oooOO0OOooo........oooOO0OOooo........o 2219 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1373 2220 1374 void G4VEnergyLossProcess::ActivateForcedInte << 2221 void 1375 << 2222 G4VEnergyLossProcess::ActivateForcedInteraction(G4double length, 1376 << 2223 const G4String& region, >> 2224 G4bool flag) 1377 { 2225 { 1378 if(nullptr == biasManager) { biasManager = << 2226 if(!biasManager) { biasManager = new G4EmBiasingManager(); } 1379 if(1 < verboseLevel) { 2227 if(1 < verboseLevel) { 1380 G4cout << "### ActivateForcedInteraction: 2228 G4cout << "### ActivateForcedInteraction: for " 1381 << " process " << GetProcessName() 2229 << " process " << GetProcessName() 1382 << " length(mm)= " << length/mm 2230 << " length(mm)= " << length/mm 1383 << " in G4Region <" << region 2231 << " in G4Region <" << region 1384 << "> weightFlag= " << flag 2232 << "> weightFlag= " << flag 1385 << G4endl; 2233 << G4endl; 1386 } 2234 } 1387 weightFlag = flag; 2235 weightFlag = flag; 1388 biasManager->ActivateForcedInteraction(leng 2236 biasManager->ActivateForcedInteraction(length, region); 1389 } 2237 } 1390 2238 1391 //....oooOO0OOooo........oooOO0OOooo........o 2239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1392 2240 1393 void 2241 void 1394 G4VEnergyLossProcess::ActivateSecondaryBiasin 2242 G4VEnergyLossProcess::ActivateSecondaryBiasing(const G4String& region, 1395 2243 G4double factor, 1396 2244 G4double energyLimit) 1397 { 2245 { 1398 if (0.0 <= factor) { 2246 if (0.0 <= factor) { >> 2247 1399 // Range cut can be applied only for e- 2248 // Range cut can be applied only for e- 1400 if(0.0 == factor && secondaryParticle != 2249 if(0.0 == factor && secondaryParticle != G4Electron::Electron()) 1401 { return; } 2250 { return; } 1402 2251 1403 if(nullptr == biasManager) { biasManager << 2252 if(!biasManager) { biasManager = new G4EmBiasingManager(); } 1404 biasManager->ActivateSecondaryBiasing(reg 2253 biasManager->ActivateSecondaryBiasing(region, factor, energyLimit); 1405 if(1 < verboseLevel) { 2254 if(1 < verboseLevel) { 1406 G4cout << "### ActivateSecondaryBiasing 2255 G4cout << "### ActivateSecondaryBiasing: for " 1407 << " process " << GetProcessName 2256 << " process " << GetProcessName() 1408 << " factor= " << factor 2257 << " factor= " << factor 1409 << " in G4Region <" << region 2258 << " in G4Region <" << region 1410 << "> energyLimit(MeV)= " << ene 2259 << "> energyLimit(MeV)= " << energyLimit/MeV 1411 << G4endl; 2260 << G4endl; 1412 } 2261 } 1413 } 2262 } 1414 } 2263 } 1415 2264 1416 //....oooOO0OOooo........oooOO0OOooo........o 2265 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1417 2266 1418 void G4VEnergyLossProcess::SetIonisation(G4bo 2267 void G4VEnergyLossProcess::SetIonisation(G4bool val) 1419 { 2268 { 1420 isIonisation = val; 2269 isIonisation = val; 1421 aGPILSelection = (val) ? CandidateForSelect 2270 aGPILSelection = (val) ? CandidateForSelection : NotCandidateForSelection; 1422 } 2271 } 1423 2272 1424 //....oooOO0OOooo........oooOO0OOooo........o 2273 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1425 2274 1426 void G4VEnergyLossProcess::SetLinearLossLimi 2275 void G4VEnergyLossProcess::SetLinearLossLimit(G4double val) 1427 { 2276 { 1428 if(0.0 < val && val < 1.0) { 2277 if(0.0 < val && val < 1.0) { 1429 linLossLimit = val; 2278 linLossLimit = val; 1430 actLinLossLimit = true; 2279 actLinLossLimit = true; 1431 } else { PrintWarning("SetLinearLossLimit", 2280 } else { PrintWarning("SetLinearLossLimit", val); } 1432 } 2281 } 1433 2282 1434 //....oooOO0OOooo........oooOO0OOooo........o 2283 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1435 2284 1436 void G4VEnergyLossProcess::SetStepFunction(G4 2285 void G4VEnergyLossProcess::SetStepFunction(G4double v1, G4double v2) 1437 { 2286 { 1438 if(0.0 < v1 && 0.0 < v2) { 2287 if(0.0 < v1 && 0.0 < v2) { 1439 dRoverRange = std::min(1.0, v1); 2288 dRoverRange = std::min(1.0, v1); 1440 finalRange = std::min(v2, 1.e+50); 2289 finalRange = std::min(v2, 1.e+50); 1441 } else { 2290 } else { 1442 PrintWarning("SetStepFunctionV1", v1); 2291 PrintWarning("SetStepFunctionV1", v1); 1443 PrintWarning("SetStepFunctionV2", v2); 2292 PrintWarning("SetStepFunctionV2", v2); 1444 } 2293 } 1445 } 2294 } 1446 2295 1447 //....oooOO0OOooo........oooOO0OOooo........o 2296 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1448 2297 1449 void G4VEnergyLossProcess::SetLowestEnergyLim 2298 void G4VEnergyLossProcess::SetLowestEnergyLimit(G4double val) 1450 { 2299 { 1451 if(1.e-18 < val && val < 1.e+50) { lowestKi 2300 if(1.e-18 < val && val < 1.e+50) { lowestKinEnergy = val; } 1452 else { PrintWarning("SetLowestEnergyLimit", 2301 else { PrintWarning("SetLowestEnergyLimit", val); } 1453 } 2302 } 1454 2303 1455 //....oooOO0OOooo........oooOO0OOooo........o 2304 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1456 2305 1457 void G4VEnergyLossProcess::SetDEDXBinning(G4i 2306 void G4VEnergyLossProcess::SetDEDXBinning(G4int n) 1458 { 2307 { 1459 if(2 < n && n < 1000000000) { 2308 if(2 < n && n < 1000000000) { 1460 nBins = n; 2309 nBins = n; 1461 actBinning = true; 2310 actBinning = true; 1462 } else { 2311 } else { 1463 G4double e = (G4double)n; 2312 G4double e = (G4double)n; 1464 PrintWarning("SetDEDXBinning", e); 2313 PrintWarning("SetDEDXBinning", e); 1465 } 2314 } 1466 } 2315 } 1467 2316 1468 //....oooOO0OOooo........oooOO0OOooo........o 2317 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1469 2318 1470 void G4VEnergyLossProcess::SetMinKinEnergy(G4 2319 void G4VEnergyLossProcess::SetMinKinEnergy(G4double e) 1471 { 2320 { 1472 if(1.e-18 < e && e < maxKinEnergy) { 2321 if(1.e-18 < e && e < maxKinEnergy) { 1473 minKinEnergy = e; 2322 minKinEnergy = e; 1474 actMinKinEnergy = true; 2323 actMinKinEnergy = true; 1475 } else { PrintWarning("SetMinKinEnergy", e) 2324 } else { PrintWarning("SetMinKinEnergy", e); } 1476 } 2325 } 1477 2326 1478 //....oooOO0OOooo........oooOO0OOooo........o 2327 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1479 2328 1480 void G4VEnergyLossProcess::SetMaxKinEnergy(G4 2329 void G4VEnergyLossProcess::SetMaxKinEnergy(G4double e) 1481 { 2330 { 1482 if(minKinEnergy < e && e < 1.e+50) { 2331 if(minKinEnergy < e && e < 1.e+50) { 1483 maxKinEnergy = e; 2332 maxKinEnergy = e; 1484 actMaxKinEnergy = true; 2333 actMaxKinEnergy = true; 1485 if(e < maxKinEnergyCSDA) { maxKinEnergyCS 2334 if(e < maxKinEnergyCSDA) { maxKinEnergyCSDA = e; } 1486 } else { PrintWarning("SetMaxKinEnergy", e) 2335 } else { PrintWarning("SetMaxKinEnergy", e); } 1487 } 2336 } 1488 2337 1489 //....oooOO0OOooo........oooOO0OOooo........o 2338 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1490 2339 1491 void G4VEnergyLossProcess::PrintWarning(const << 2340 void G4VEnergyLossProcess::PrintWarning(G4String tit, G4double val) 1492 { 2341 { 1493 G4String ss = "G4VEnergyLossProcess::" + ti 2342 G4String ss = "G4VEnergyLossProcess::" + tit; 1494 G4ExceptionDescription ed; 2343 G4ExceptionDescription ed; 1495 ed << "Parameter is out of range: " << val 2344 ed << "Parameter is out of range: " << val 1496 << " it will have no effect!\n" << " Pr 2345 << " it will have no effect!\n" << " Process " 1497 << GetProcessName() << " nbins= " << nB 2346 << GetProcessName() << " nbins= " << nBins 1498 << " Emin(keV)= " << minKinEnergy/keV 2347 << " Emin(keV)= " << minKinEnergy/keV 1499 << " Emax(GeV)= " << maxKinEnergy/GeV; 2348 << " Emax(GeV)= " << maxKinEnergy/GeV; 1500 G4Exception(ss, "em0044", JustWarning, ed); 2349 G4Exception(ss, "em0044", JustWarning, ed); 1501 } 2350 } 1502 2351 1503 //....oooOO0OOooo........oooOO0OOooo........o 2352 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1504 2353 1505 void G4VEnergyLossProcess::ProcessDescription 2354 void G4VEnergyLossProcess::ProcessDescription(std::ostream& out) const 1506 { 2355 { 1507 if(nullptr != particle) { StreamInfo(out, * << 2356 if(particle) { StreamInfo(out, *particle, true); } 1508 } 2357 } 1509 2358 1510 //....oooOO0OOooo........oooOO0OOooo........o 2359 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1511 2360