Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // >> 26 // $Id: G4VMultipleScattering.cc 94120 2015-11-06 09:18:03Z gcosmo $ 26 // 27 // 27 // ------------------------------------------- 28 // ------------------------------------------------------------------- 28 // 29 // 29 // GEANT4 Class file 30 // GEANT4 Class file 30 // 31 // 31 // 32 // 32 // File name: G4VMultipleScattering 33 // File name: G4VMultipleScattering 33 // 34 // 34 // Author: Vladimir Ivanchenko on base 35 // Author: Vladimir Ivanchenko on base of Laszlo Urban code 35 // 36 // 36 // Creation date: 25.03.2003 37 // Creation date: 25.03.2003 37 // 38 // 38 // Modifications: 39 // Modifications: 39 // 40 // >> 41 // 13.04.03 Change printout (V.Ivanchenko) >> 42 // 04-06-03 Fix compilation warnings (V.Ivanchenko) 40 // 16-07-03 Use G4VMscModel interface (V.Ivanc 43 // 16-07-03 Use G4VMscModel interface (V.Ivanchenko) 41 // 03-11-03 Fix initialisation problem in Retr 44 // 03-11-03 Fix initialisation problem in RetrievePhysicsTable (V.Ivanchenko) 42 // 04-11-03 Update PrintInfoDefinition (V.Ivan 45 // 04-11-03 Update PrintInfoDefinition (V.Ivanchenko) 43 // 01-03-04 SampleCosineTheta signature change 46 // 01-03-04 SampleCosineTheta signature changed 44 // 22-04-04 SampleCosineTheta signature change 47 // 22-04-04 SampleCosineTheta signature changed back to original 45 // 27-08-04 Add InitialiseForRun method (V.Iva 48 // 27-08-04 Add InitialiseForRun method (V.Ivanchneko) 46 // 08-11-04 Migration to new interface of Stor 49 // 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivantchenko) 47 // 11-03-05 Shift verbose level by 1 (V.Ivantc 50 // 11-03-05 Shift verbose level by 1 (V.Ivantchenko) 48 // 15-04-05 optimize internal interface (V.Iva 51 // 15-04-05 optimize internal interface (V.Ivanchenko) 49 // 15-04-05 remove boundary flag (V.Ivanchenko 52 // 15-04-05 remove boundary flag (V.Ivanchenko) 50 // 27-10-05 introduce virtual function MscStep 53 // 27-10-05 introduce virtual function MscStepLimitation() (V.Ivanchenko) 51 // 12-04-07 Add verbosity at destruction (V.Iv 54 // 12-04-07 Add verbosity at destruction (V.Ivanchenko) 52 // 27-10-07 Virtual functions moved to source 55 // 27-10-07 Virtual functions moved to source (V.Ivanchenko) 53 // 11-03-08 Set skin value does not effect ste 56 // 11-03-08 Set skin value does not effect step limit type (V.Ivanchenko) 54 // 24-06-09 Removed hidden bin in G4PhysicsVec 57 // 24-06-09 Removed hidden bin in G4PhysicsVector (V.Ivanchenko) 55 // 04-06-13 Adoptation to MT mode (V.Ivanchenk 58 // 04-06-13 Adoptation to MT mode (V.Ivanchenko) 56 // 59 // >> 60 // Class Description: >> 61 // >> 62 // It is the generic process of multiple scattering it includes common >> 63 // part of calculations for all charged particles 57 64 58 // ------------------------------------------- 65 // ------------------------------------------------------------------- 59 // 66 // 60 //....oooOO0OOooo........oooOO0OOooo........oo 67 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 61 //....oooOO0OOooo........oooOO0OOooo........oo 68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 62 69 63 #include "G4VMultipleScattering.hh" 70 #include "G4VMultipleScattering.hh" 64 #include "G4PhysicalConstants.hh" 71 #include "G4PhysicalConstants.hh" 65 #include "G4SystemOfUnits.hh" 72 #include "G4SystemOfUnits.hh" 66 #include "G4LossTableManager.hh" 73 #include "G4LossTableManager.hh" 67 #include "G4MaterialCutsCouple.hh" 74 #include "G4MaterialCutsCouple.hh" 68 #include "G4Step.hh" 75 #include "G4Step.hh" 69 #include "G4ParticleDefinition.hh" 76 #include "G4ParticleDefinition.hh" 70 #include "G4VEmFluctuationModel.hh" 77 #include "G4VEmFluctuationModel.hh" 71 #include "G4UnitsTable.hh" 78 #include "G4UnitsTable.hh" 72 #include "G4ProductionCutsTable.hh" 79 #include "G4ProductionCutsTable.hh" 73 #include "G4Electron.hh" 80 #include "G4Electron.hh" 74 #include "G4GenericIon.hh" 81 #include "G4GenericIon.hh" 75 #include "G4TransportationManager.hh" 82 #include "G4TransportationManager.hh" 76 #include "G4SafetyHelper.hh" 83 #include "G4SafetyHelper.hh" 77 #include "G4ParticleTable.hh" 84 #include "G4ParticleTable.hh" 78 #include "G4ProcessVector.hh" 85 #include "G4ProcessVector.hh" 79 #include "G4ProcessManager.hh" 86 #include "G4ProcessManager.hh" 80 #include "G4LossTableBuilder.hh" << 81 #include "G4EmTableUtil.hh" << 82 #include <iostream> 87 #include <iostream> 83 88 84 //....oooOO0OOooo........oooOO0OOooo........oo 89 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 85 90 86 G4VMultipleScattering::G4VMultipleScattering(c << 91 static const G4double minSafety = 1.20*CLHEP::nm; 87 : G4VContinuousDiscreteProcess("msc", fElect << 92 static const G4double geomMin = 0.05*CLHEP::nm; >> 93 static const G4double minDisplacement2 = geomMin*geomMin; >> 94 >> 95 G4VMultipleScattering::G4VMultipleScattering(const G4String& name, >> 96 G4ProcessType): >> 97 G4VContinuousDiscreteProcess("msc", fElectromagnetic), >> 98 numberOfModels(0), >> 99 firstParticle(nullptr), >> 100 currParticle(nullptr), >> 101 stepLimit(fUseSafety), >> 102 facrange(0.04), >> 103 latDisplacement(true), >> 104 isIon(false), >> 105 fDispBeyondSafety(false), 88 fNewPosition(0.,0.,0.), 106 fNewPosition(0.,0.,0.), 89 fNewDirection(0.,0.,1.) 107 fNewDirection(0.,0.,1.) 90 { 108 { 91 theParameters = G4EmParameters::Instance(); 109 theParameters = G4EmParameters::Instance(); 92 SetVerboseLevel(1); 110 SetVerboseLevel(1); 93 SetProcessSubType(fMultipleScattering); 111 SetProcessSubType(fMultipleScattering); >> 112 if("ionmsc" == name) { firstParticle = G4GenericIon::GenericIon(); } 94 113 95 lowestKinEnergy = 10*CLHEP::eV; 114 lowestKinEnergy = 10*CLHEP::eV; 96 115 97 geomMin = 0.05*CLHEP::nm; << 116 physStepLimit = gPathLength = tPathLength = 0.0; 98 minDisplacement2 = geomMin*geomMin; << 117 fIonisation = nullptr; 99 118 100 pParticleChange = &fParticleChange; 119 pParticleChange = &fParticleChange; >> 120 safetyHelper = nullptr; >> 121 fPositionChanged = false; >> 122 isActive = false; 101 123 >> 124 currentModel = nullptr; 102 modelManager = new G4EmModelManager(); 125 modelManager = new G4EmModelManager(); 103 emManager = G4LossTableManager::Instance(); 126 emManager = G4LossTableManager::Instance(); 104 mscModels.reserve(2); << 105 emManager->Register(this); 127 emManager->Register(this); 106 } 128 } 107 129 108 //....oooOO0OOooo........oooOO0OOooo........oo 130 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 109 131 110 G4VMultipleScattering::~G4VMultipleScattering( 132 G4VMultipleScattering::~G4VMultipleScattering() 111 { 133 { >> 134 /* >> 135 if(1 < verboseLevel) { >> 136 G4cout << "G4VMultipleScattering destruct " << GetProcessName() >> 137 << G4endl; >> 138 } >> 139 */ 112 delete modelManager; 140 delete modelManager; 113 emManager->DeRegister(this); 141 emManager->DeRegister(this); 114 } 142 } 115 143 116 //....oooOO0OOooo........oooOO0OOooo........oo 144 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 117 145 118 void G4VMultipleScattering::AddEmModel(G4int o << 146 void G4VMultipleScattering::AddEmModel(G4int order, G4VEmModel* p, 119 const G 147 const G4Region* region) 120 { 148 { 121 if(nullptr == ptr) { return; } << 122 G4VEmFluctuationModel* fm = nullptr; 149 G4VEmFluctuationModel* fm = nullptr; 123 modelManager->AddEmModel(order, ptr, fm, reg << 150 modelManager->AddEmModel(order, p, fm, region); 124 ptr->SetParticleChange(pParticleChange); << 151 if(p) { p->SetParticleChange(pParticleChange); } 125 } 152 } 126 153 127 //....oooOO0OOooo........oooOO0OOooo........oo 154 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 128 155 129 void G4VMultipleScattering::SetEmModel(G4VMscM << 156 void G4VMultipleScattering::SetEmModel(G4VMscModel* p, G4int index) 130 { 157 { 131 if(nullptr == ptr) { return; } << 158 G4int n = mscModels.size(); 132 if(!mscModels.empty()) { << 159 if(index >= n) { for(G4int i=n; i<=index; ++i) { mscModels.push_back(0); } } 133 for(auto & msc : mscModels) { if(msc == pt << 160 mscModels[index] = p; 134 } << 161 } 135 mscModels.push_back(ptr); << 162 >> 163 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 164 >> 165 G4VMscModel* G4VMultipleScattering::EmModel(G4int index) const >> 166 { >> 167 G4VMscModel* p = nullptr; >> 168 if(index >= 0 && index < G4int(mscModels.size())) { p = mscModels[index]; } >> 169 return p; >> 170 } >> 171 >> 172 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 173 >> 174 G4VEmModel* >> 175 G4VMultipleScattering::GetModelByIndex(G4int idx, G4bool ver) const >> 176 { >> 177 return modelManager->GetModel(idx, ver); 136 } 178 } 137 179 138 //....oooOO0OOooo........oooOO0OOooo........oo 180 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 139 181 140 void 182 void 141 G4VMultipleScattering::PreparePhysicsTable(con 183 G4VMultipleScattering::PreparePhysicsTable(const G4ParticleDefinition& part) 142 { 184 { 143 G4bool master = emManager->IsMaster(); << 185 G4bool master = true; 144 if (nullptr == firstParticle) { firstParticl << 186 const G4VMultipleScattering* masterProc = >> 187 static_cast<const G4VMultipleScattering*>(GetMasterProcess()); >> 188 if(masterProc && masterProc != this) { master = false; } >> 189 >> 190 if(!firstParticle) { firstParticle = ∂ } >> 191 if(part.GetParticleType() == "nucleus") { >> 192 stepLimit = fMinimal; >> 193 latDisplacement = false; >> 194 facrange = 0.2; >> 195 G4String pname = part.GetParticleName(); >> 196 if(pname != "deuteron" && pname != "triton" && >> 197 pname != "alpha+" && pname != "helium" && >> 198 pname != "alpha" && pname != "He3" && >> 199 pname != "hydrogen") { >> 200 >> 201 const G4ParticleDefinition* theGenericIon = >> 202 G4ParticleTable::GetParticleTable()->FindParticle("GenericIon"); >> 203 if(&part == theGenericIon) { isIon = true; } >> 204 >> 205 if(theGenericIon && firstParticle != theGenericIon) { >> 206 G4ProcessManager* pm = theGenericIon->GetProcessManager(); >> 207 G4ProcessVector* v = pm->GetAlongStepProcessVector(); >> 208 size_t n = v->size(); >> 209 for(size_t j=0; j<n; ++j) { >> 210 if((*v)[j] == this) { >> 211 firstParticle = theGenericIon; >> 212 isIon = true; >> 213 break; >> 214 } >> 215 } >> 216 } >> 217 } >> 218 } >> 219 >> 220 emManager->PreparePhysicsTable(&part, this, master); >> 221 currParticle = 0; 145 222 146 emManager->PreparePhysicsTable(&part, this); << 223 if(1 < verboseLevel) { 147 currParticle = nullptr; << 224 G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for " >> 225 << GetProcessName() >> 226 << " and particle " << part.GetParticleName() >> 227 << " local particle " << firstParticle->GetParticleName() >> 228 << " isIon= " << isIon >> 229 << G4endl; >> 230 } 148 231 149 if(firstParticle == &part) { 232 if(firstParticle == &part) { 150 baseMat = emManager->GetTableBuilder()->Ge << 151 G4EmTableUtil::PrepareMscProcess(this, par << 152 stepLimit, facrange, << 153 latDisplacement, master, << 154 isIon, baseMat); << 155 233 >> 234 // initialise process >> 235 InitialiseProcess(firstParticle); >> 236 >> 237 // heavy particles and not ions >> 238 if(!isIon) { >> 239 if(part.GetPDGMass() > MeV) { >> 240 stepLimit = theParameters->MscMuHadStepLimitType(); >> 241 facrange = theParameters->MscMuHadRangeFactor(); >> 242 latDisplacement = theParameters->MuHadLateralDisplacement(); >> 243 } else { >> 244 stepLimit = theParameters->MscStepLimitType(); >> 245 facrange = theParameters->MscRangeFactor(); >> 246 latDisplacement = theParameters->LateralDisplacement(); >> 247 } >> 248 if(latDisplacement) { >> 249 fDispBeyondSafety = theParameters->LatDisplacementBeyondSafety(); >> 250 } >> 251 } >> 252 if(master) { SetVerboseLevel(theParameters->Verbose()); } >> 253 else { SetVerboseLevel(theParameters->WorkerVerbose()); } >> 254 >> 255 // initialisation of models 156 numberOfModels = modelManager->NumberOfMod 256 numberOfModels = modelManager->NumberOfModels(); 157 currentModel = GetModelByIndex(0); << 257 for(G4int i=0; i<numberOfModels; ++i) { >> 258 G4VMscModel* msc = static_cast<G4VMscModel*>(modelManager->GetModel(i)); >> 259 msc->SetIonisation(0, firstParticle); >> 260 msc->SetMasterThread(master); >> 261 if(0 == i) { currentModel = msc; } >> 262 msc->SetStepLimitType(stepLimit); >> 263 msc->SetLateralDisplasmentFlag(latDisplacement); >> 264 msc->SetSkin(theParameters->MscSkin()); >> 265 msc->SetRangeFactor(facrange); >> 266 msc->SetGeomFactor(theParameters->MscGeomFactor()); >> 267 msc->SetPolarAngleLimit(theParameters->MscThetaLimit()); >> 268 G4double emax = >> 269 std::min(msc->HighEnergyLimit(),theParameters->MaxKinEnergy()); >> 270 msc->SetHighEnergyLimit(emax); >> 271 } >> 272 >> 273 modelManager->Initialise(firstParticle, G4Electron::Electron(), >> 274 10.0, verboseLevel); 158 275 159 if (nullptr == safetyHelper) { << 276 if(!safetyHelper) { 160 safetyHelper = G4TransportationManager:: 277 safetyHelper = G4TransportationManager::GetTransportationManager() 161 ->GetSafetyHelper(); << 278 ->GetSafetyHelper(); 162 safetyHelper->InitialiseHelper(); 279 safetyHelper->InitialiseHelper(); 163 } 280 } 164 } 281 } 165 } 282 } 166 283 167 //....oooOO0OOooo........oooOO0OOooo........oo 284 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 168 285 169 void G4VMultipleScattering::BuildPhysicsTable( 286 void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part) 170 { 287 { 171 G4bool master = emManager->IsMaster(); << 288 G4String num = part.GetParticleName(); >> 289 if(1 < verboseLevel) { >> 290 G4cout << "### G4VMultipleScattering::BuildPhysicsTable() for " >> 291 << GetProcessName() >> 292 << " and particle " << num >> 293 << " IsMaster= " << G4LossTableManager::Instance()->IsMaster() >> 294 << G4endl; >> 295 } >> 296 G4bool master = true; >> 297 const G4VMultipleScattering* masterProcess = >> 298 static_cast<const G4VMultipleScattering*>(GetMasterProcess()); >> 299 if(masterProcess && masterProcess != this) { master = false; } 172 300 173 if(firstParticle == &part) { << 301 if(firstParticle == &part) { 174 emManager->BuildPhysicsTable(&part); << 302 /* 175 } << 303 G4cout << "### G4VMultipleScattering::BuildPhysicsTable() for " 176 const G4VMultipleScattering* ptr = this; << 304 << GetProcessName() 177 if(!master) { << 305 << " and particle " << num 178 ptr = static_cast<const G4VMultipleScatter << 306 << " IsMaster= " << G4LossTableManager::Instance()->IsMaster() >> 307 << " " << this >> 308 << G4endl; >> 309 */ >> 310 emManager->BuildPhysicsTable(firstParticle); >> 311 >> 312 if(!master) { >> 313 // initialisation of models >> 314 G4bool printing = true; >> 315 numberOfModels = modelManager->NumberOfModels(); >> 316 /* >> 317 G4cout << "### G4VMultipleScattering::SlaveBuildPhysicsTable() for " >> 318 << GetProcessName() >> 319 << " and particle " << num >> 320 << " Nmod= " << numberOfModels << " " << this >> 321 << G4endl; >> 322 */ >> 323 for(G4int i=0; i<numberOfModels; ++i) { >> 324 G4VMscModel* msc = >> 325 static_cast<G4VMscModel*>(GetModelByIndex(i, printing)); >> 326 G4VMscModel* msc0= >> 327 static_cast<G4VMscModel*>(masterProcess->GetModelByIndex(i,printing)); >> 328 msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false); >> 329 msc->InitialiseLocal(firstParticle, msc0); >> 330 } >> 331 } 179 } 332 } 180 333 181 G4EmTableUtil::BuildMscProcess(this, ptr, pa << 334 // explicitly defined printout by particle name 182 numberOfModels, master); << 335 if(1 < verboseLevel || >> 336 (0 < verboseLevel && (num == "e-" || >> 337 num == "e+" || num == "mu+" || >> 338 num == "mu-" || num == "proton"|| >> 339 num == "pi+" || num == "pi-" || >> 340 num == "kaon+" || num == "kaon-" || >> 341 num == "alpha" || num == "anti_proton" || >> 342 num == "GenericIon"))) >> 343 { >> 344 G4cout << G4endl << GetProcessName() >> 345 << ": for " << num >> 346 << " SubType= " << GetProcessSubType() >> 347 << G4endl; >> 348 PrintInfo(); >> 349 modelManager->DumpModelList(verboseLevel); >> 350 } >> 351 >> 352 if(1 < verboseLevel) { >> 353 G4cout << "### G4VMultipleScattering::BuildPhysicsTable() done for " >> 354 << GetProcessName() >> 355 << " and particle " << num >> 356 << G4endl; >> 357 } 183 } 358 } 184 359 185 //....oooOO0OOooo........oooOO0OOooo........oo 360 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 186 361 187 void G4VMultipleScattering::StreamInfo(std::os << 362 void G4VMultipleScattering::PrintInfoDefinition() 188 const G4ParticleDefinition& << 189 { 363 { 190 G4String indent = (rst ? " " : ""); << 364 if (0 < verboseLevel) { 191 outFile << G4endl << indent << GetProcessNam << 365 G4cout << G4endl << GetProcessName() 192 if (!rst) outFile << " for " << part.GetPart << 366 << ": for " << firstParticle->GetParticleName() 193 outFile << " SubType= " << GetProcessSubTy << 367 << " SubType= " << GetProcessSubType() 194 modelManager->DumpModelList(outFile, verbose << 368 << G4endl; >> 369 PrintInfo(); >> 370 modelManager->DumpModelList(verboseLevel); >> 371 } 195 } 372 } 196 373 197 //....oooOO0OOooo........oooOO0OOooo........oo 374 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 198 375 199 void G4VMultipleScattering::StartTracking(G4Tr 376 void G4VMultipleScattering::StartTracking(G4Track* track) 200 { 377 { 201 G4VEnergyLossProcess* eloss = nullptr; 378 G4VEnergyLossProcess* eloss = nullptr; 202 if(track->GetParticleDefinition() != currPar 379 if(track->GetParticleDefinition() != currParticle) { 203 currParticle = track->GetParticleDefinitio 380 currParticle = track->GetParticleDefinition(); 204 fIonisation = emManager->GetEnergyLossProc 381 fIonisation = emManager->GetEnergyLossProcess(currParticle); 205 eloss = fIonisation; 382 eloss = fIonisation; 206 } 383 } 207 for(G4int i=0; i<numberOfModels; ++i) { << 384 /* 208 G4VMscModel* msc = GetModelByIndex(i); << 385 G4cout << "G4VMultipleScattering::StartTracking Nmod= " << numberOfModels 209 msc->StartTracking(track); << 386 << " " << currParticle->GetParticleName() 210 if(nullptr != eloss) { << 387 << " E(MeV)= " << track->GetKineticEnergy() 211 msc->SetIonisation(eloss, currParticle); << 388 << " Ion= " << eloss << " " << fIonisation << " IsMaster= " >> 389 << G4LossTableManager::Instance()->IsMaster() >> 390 << G4endl; >> 391 */ >> 392 // one model >> 393 if(1 == numberOfModels) { >> 394 currentModel->StartTracking(track); >> 395 if(eloss) { currentModel->SetIonisation(fIonisation, currParticle); } >> 396 >> 397 // many models >> 398 } else { >> 399 for(G4int i=0; i<numberOfModels; ++i) { >> 400 G4VMscModel* msc = static_cast<G4VMscModel*>(GetModelByIndex(i,true)); >> 401 msc->StartTracking(track); >> 402 if(eloss) { msc->SetIonisation(fIonisation, currParticle); } 212 } 403 } 213 } 404 } 214 } << 405 } 215 406 216 //....oooOO0OOooo........oooOO0OOooo........oo 407 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 217 408 218 G4double G4VMultipleScattering::AlongStepGetPh 409 G4double G4VMultipleScattering::AlongStepGetPhysicalInteractionLength( 219 const G4Track& tr 410 const G4Track& track, 220 G4double, 411 G4double, 221 G4double currentM 412 G4double currentMinimalStep, 222 G4double&, 413 G4double&, 223 G4GPILSelection* 414 G4GPILSelection* selection) 224 { 415 { 225 // get Step limit proposed by the process 416 // get Step limit proposed by the process 226 *selection = NotCandidateForSelection; 417 *selection = NotCandidateForSelection; 227 physStepLimit = gPathLength = tPathLength = 418 physStepLimit = gPathLength = tPathLength = currentMinimalStep; 228 419 229 G4double ekin = track.GetKineticEnergy(); 420 G4double ekin = track.GetKineticEnergy(); 230 /* 421 /* 231 G4cout << "MSC::AlongStepGPIL: Ekin= " << ek 422 G4cout << "MSC::AlongStepGPIL: Ekin= " << ekin 232 << " " << currParticle->GetParticleN 423 << " " << currParticle->GetParticleName() 233 << " currMod " << currentModel 424 << " currMod " << currentModel 234 << G4endl; 425 << G4endl; 235 */ 426 */ 236 // isIon flag is used only to select a model 427 // isIon flag is used only to select a model 237 if(isIon) { 428 if(isIon) { 238 ekin *= proton_mass_c2/track.GetParticleDe 429 ekin *= proton_mass_c2/track.GetParticleDefinition()->GetPDGMass(); 239 } 430 } 240 const G4MaterialCutsCouple* couple = track.G << 241 431 242 // select new model, static cast is possible << 432 // select new model 243 if(1 < numberOfModels) { 433 if(1 < numberOfModels) { 244 currentModel = << 434 currentModel = static_cast<G4VMscModel*>( 245 static_cast<G4VMscModel*>(SelectModel(ek << 435 SelectModel(ekin,track.GetMaterialCutsCouple()->GetIndex())); 246 } 436 } 247 currentModel->SetCurrentCouple(couple); << 248 // msc is active is model is active, energy 437 // msc is active is model is active, energy above the limit, 249 // and step size is above the limit; 438 // and step size is above the limit; 250 // if it is active msc may limit the step 439 // if it is active msc may limit the step 251 if(currentModel->IsActive(ekin) && tPathLeng 440 if(currentModel->IsActive(ekin) && tPathLength > geomMin 252 && ekin >= lowestKinEnergy) { 441 && ekin >= lowestKinEnergy) { 253 isActive = true; 442 isActive = true; 254 tPathLength = 443 tPathLength = 255 currentModel->ComputeTruePathLengthLimit 444 currentModel->ComputeTruePathLengthLimit(track, gPathLength); 256 if (tPathLength < physStepLimit) { 445 if (tPathLength < physStepLimit) { 257 *selection = CandidateForSelection; 446 *selection = CandidateForSelection; 258 } 447 } 259 } else { << 448 } else { isActive = false; } 260 isActive = false; << 261 gPathLength = DBL_MAX; << 262 } << 263 449 264 //if(currParticle->GetPDGMass() > GeV) 450 //if(currParticle->GetPDGMass() > GeV) 265 /* 451 /* 266 G4cout << "MSC::AlongStepGPIL: Ekin= " << ek 452 G4cout << "MSC::AlongStepGPIL: Ekin= " << ekin 267 << " " << currParticle->GetParticleN 453 << " " << currParticle->GetParticleName() 268 << " gPathLength= " << gPathLength 454 << " gPathLength= " << gPathLength 269 << " tPathLength= " << tPathLength 455 << " tPathLength= " << tPathLength 270 << " currentMinimalStep= " << current 456 << " currentMinimalStep= " << currentMinimalStep 271 << " isActive " << isActive << G4endl 457 << " isActive " << isActive << G4endl; 272 */ 458 */ 273 return gPathLength; 459 return gPathLength; 274 } 460 } 275 461 276 //....oooOO0OOooo........oooOO0OOooo........oo 462 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 277 463 278 G4double 464 G4double 279 G4VMultipleScattering::PostStepGetPhysicalInte 465 G4VMultipleScattering::PostStepGetPhysicalInteractionLength( 280 const G4Track&, G4double, G4Forc 466 const G4Track&, G4double, G4ForceCondition* condition) 281 { 467 { 282 *condition = NotForced; << 468 *condition = Forced; >> 469 //*condition = NotForced; 283 return DBL_MAX; 470 return DBL_MAX; 284 } 471 } 285 472 286 //....oooOO0OOooo........oooOO0OOooo........oo 473 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 287 474 288 G4VParticleChange* 475 G4VParticleChange* 289 G4VMultipleScattering::AlongStepDoIt(const G4T 476 G4VMultipleScattering::AlongStepDoIt(const G4Track& track, const G4Step& step) 290 { 477 { 291 fParticleChange.InitialiseMSC(track, step); << 478 fParticleChange.ProposeMomentumDirection( 292 fNewPosition = fParticleChange.GetProposedPo << 479 step.GetPostStepPoint()->GetMomentumDirection()); >> 480 fNewPosition = step.GetPostStepPoint()->GetPosition(); >> 481 fParticleChange.ProposePosition(fNewPosition); 293 fPositionChanged = false; 482 fPositionChanged = false; 294 483 295 G4double geomLength = step.GetStepLength(); 484 G4double geomLength = step.GetStepLength(); 296 485 297 // very small step - no msc 486 // very small step - no msc 298 if(!isActive) { 487 if(!isActive) { 299 tPathLength = geomLength; 488 tPathLength = geomLength; 300 489 301 // sample msc 490 // sample msc 302 } else { 491 } else { 303 G4double range = 492 G4double range = 304 currentModel->GetRange(currParticle,trac 493 currentModel->GetRange(currParticle,track.GetKineticEnergy(), 305 track.GetMaterial 494 track.GetMaterialCutsCouple()); 306 495 307 tPathLength = currentModel->ComputeTrueSte 496 tPathLength = currentModel->ComputeTrueStepLength(geomLength); 308 497 >> 498 // protection against wrong t->g->t conversion 309 /* 499 /* 310 if(currParticle->GetPDGMass() > 0.9*GeV) 500 if(currParticle->GetPDGMass() > 0.9*GeV) 311 G4cout << "G4VMsc::AlongStepDoIt: GeomLeng 501 G4cout << "G4VMsc::AlongStepDoIt: GeomLength= " 312 << geomLength 502 << geomLength 313 << " tPathLength= " << tPathLength 503 << " tPathLength= " << tPathLength 314 << " physStepLimit= " << physStepLi 504 << " physStepLimit= " << physStepLimit 315 << " dr= " << range - tPathLength 505 << " dr= " << range - tPathLength 316 << " ekin= " << track.GetKineticEne 506 << " ekin= " << track.GetKineticEnergy() << G4endl; 317 */ 507 */ 318 // protection against wrong t->g->t conver << 319 tPathLength = std::min(tPathLength, physSt 508 tPathLength = std::min(tPathLength, physStepLimit); 320 509 321 // do not sample scattering at the last or 510 // do not sample scattering at the last or at a small step 322 if(tPathLength < range && tPathLength > ge 511 if(tPathLength < range && tPathLength > geomMin) { 323 512 324 static const G4double minSafety = 1.20*C << 325 static const G4double sFact = 0.99; << 326 << 327 G4ThreeVector displacement = currentMode 513 G4ThreeVector displacement = currentModel->SampleScattering( 328 step.GetPostStepPoint()->GetMomentumDi 514 step.GetPostStepPoint()->GetMomentumDirection(),minSafety); 329 515 330 G4double r2 = displacement.mag2(); 516 G4double r2 = displacement.mag2(); 331 //G4cout << " R= " << sqrt(r2) << " R 517 //G4cout << " R= " << sqrt(r2) << " Rmin= " << sqrt(minDisplacement2) 332 // << " flag= " << fDispBeyondSafety 518 // << " flag= " << fDispBeyondSafety << G4endl; 333 if(r2 > minDisplacement2) { 519 if(r2 > minDisplacement2) { 334 520 335 fPositionChanged = true; 521 fPositionChanged = true; 336 G4double dispR = std::sqrt(r2); << 522 const G4double sFact = 0.99; 337 G4double postSafety = 523 G4double postSafety = 338 sFact*safetyHelper->ComputeSafety(fN << 524 sFact*(step.GetPreStepPoint()->GetSafety() - geomLength); 339 //G4cout<<" R= "<< dispR<<" postSaf << 525 //G4cout<<" R= "<<sqrt(r2)<<" postSafety= "<<postSafety<<G4endl; 340 526 341 // far away from geometry boundary 527 // far away from geometry boundary 342 if(postSafety > 0.0 && dispR <= postSa << 528 if(postSafety > 0.0 && r2 <= postSafety*postSafety) { 343 fNewPosition += displacement; 529 fNewPosition += displacement; 344 530 345 //near the boundary << 531 //near the boundary 346 } else { 532 } else { >> 533 G4double dispR = std::sqrt(r2); >> 534 postSafety = >> 535 sFact*safetyHelper->ComputeSafety(fNewPosition, dispR); >> 536 347 // displaced point is definitely wit 537 // displaced point is definitely within the volume 348 //G4cout<<" R= "<<dispR<<" postSa 538 //G4cout<<" R= "<<dispR<<" postSafety= "<<postSafety<<G4endl; 349 if(dispR < postSafety) { 539 if(dispR < postSafety) { 350 fNewPosition += displacement; 540 fNewPosition += displacement; 351 541 352 // reduced displacement << 542 // optional extra mechanism is applied only if a particle 353 } else if(postSafety > geomMin) { << 543 // is stopped by the boundary 354 fNewPosition += displacement*(post << 544 } else if(fDispBeyondSafety && 0.0 == postSafety) { >> 545 fNewPosition += displacement; >> 546 G4double maxshift = >> 547 std::min(2.0*dispR, geomLength*(physStepLimit/tPathLength - 1.0)); >> 548 G4double dist = 0.0; >> 549 G4double safety = postSafety + dispR; >> 550 fNewDirection = *(fParticleChange.GetMomentumDirection()); >> 551 /* >> 552 G4cout << "##MSC before Recheck maxshift= " << maxshift >> 553 << " postsafety= " << postSafety >> 554 << " Ekin= " << track.GetKineticEnergy() >> 555 << " " << track.GetDefinition()->GetParticleName() >> 556 << G4endl; >> 557 */ >> 558 // check if it is possible to shift to the boundary >> 559 // and the shift is not large >> 560 if(safetyHelper->RecheckDistanceToCurrentBoundary(fNewPosition, >> 561 fNewDirection, maxshift, &dist, &safety) >> 562 && std::abs(dist) < maxshift) { >> 563 /* >> 564 G4cout << "##MSC after Recheck dist= " << dist >> 565 << " postsafety= " << postSafety >> 566 << " t= " << tPathLength >> 567 << " g= " << geomLength >> 568 << " p= " << physStepLimit >> 569 << G4endl; >> 570 */ >> 571 // shift is positive >> 572 if(dist >= 0.0) { >> 573 tPathLength *= (1.0 + dist/geomLength); >> 574 fNewPosition += dist*fNewDirection; >> 575 >> 576 // shift is negative cannot be larger than geomLength >> 577 } else { >> 578 maxshift = std::min(maxshift, geomLength); >> 579 if(0.0 < maxshift + dist) { >> 580 G4ThreeVector postpoint = step.GetPostStepPoint()->GetPosition(); >> 581 G4ThreeVector point = fNewPosition + dist*fNewDirection; >> 582 G4double R2 = (postpoint - point).mag2(); >> 583 G4double newdist = dist; >> 584 // check not more than 10 extra boundaries >> 585 for(G4int i=0; i<10; ++i) { >> 586 dist = 0.0; >> 587 if(safetyHelper->RecheckDistanceToCurrentBoundary( >> 588 point, fNewDirection, maxshift, &dist, &safety) >> 589 && std::abs(newdist + dist) < maxshift) { >> 590 point += dist*fNewDirection; >> 591 G4double R2new = (postpoint - point).mag2(); >> 592 //G4cout << "Backward i= " << i << " dist= " << dist >> 593 // << " R2= " << R2new << G4endl; >> 594 if(dist >= 0.0 || R2new > R2) { break; } >> 595 R2 = R2new; >> 596 fNewPosition = point; >> 597 newdist += dist; >> 598 } else { >> 599 break; >> 600 } >> 601 } >> 602 tPathLength *= (1.0 + newdist/geomLength); >> 603 // shift on boundary is not possible for negative disp >> 604 } else { >> 605 fNewPosition += displacement*(postSafety/dispR - 1.0); >> 606 } >> 607 } >> 608 // shift on boundary is not possible for any disp >> 609 } else { >> 610 fNewPosition += displacement*(postSafety/dispR - 1.0); >> 611 } >> 612 // reduced displacement >> 613 } else if(postSafety > geomMin) { >> 614 fNewPosition += displacement*(postSafety/dispR); 355 615 356 // very small postSafety 616 // very small postSafety 357 } else { 617 } else { 358 fPositionChanged = false; 618 fPositionChanged = false; 359 } 619 } 360 } 620 } 361 if(fPositionChanged) { << 621 //safetyHelper->ReLocateWithinVolume(fNewPosition); 362 safetyHelper->ReLocateWithinVolume(f << 363 fParticleChange.ProposePosition(fNew << 364 } << 365 } 622 } 366 } 623 } 367 } 624 } 368 fParticleChange.ProposeTrueStepLength(tPathL 625 fParticleChange.ProposeTrueStepLength(tPathLength); >> 626 //fParticleChange.ProposePosition(fNewPosition); >> 627 return &fParticleChange; >> 628 } >> 629 >> 630 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 631 >> 632 G4VParticleChange* >> 633 G4VMultipleScattering::PostStepDoIt(const G4Track& track, const G4Step&) >> 634 { >> 635 fParticleChange.Initialize(track); >> 636 >> 637 if(fPositionChanged) { >> 638 safetyHelper->ReLocateWithinVolume(fNewPosition); >> 639 fParticleChange.ProposePosition(fNewPosition); >> 640 } >> 641 369 return &fParticleChange; 642 return &fParticleChange; 370 } 643 } 371 644 372 //....oooOO0OOooo........oooOO0OOooo........oo 645 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 373 646 374 G4double G4VMultipleScattering::GetContinuousS 647 G4double G4VMultipleScattering::GetContinuousStepLimit( 375 const G 648 const G4Track& track, 376 G4doubl 649 G4double previousStepSize, 377 G4doubl 650 G4double currentMinimalStep, 378 G4doubl 651 G4double& currentSafety) 379 { 652 { 380 G4GPILSelection selection = NotCandidateForS 653 G4GPILSelection selection = NotCandidateForSelection; 381 G4double x = AlongStepGetPhysicalInteraction 654 G4double x = AlongStepGetPhysicalInteractionLength(track,previousStepSize, 382 655 currentMinimalStep, 383 656 currentSafety, 384 657 &selection); 385 return x; 658 return x; 386 } 659 } 387 660 388 //....oooOO0OOooo........oooOO0OOooo........oo 661 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 389 662 390 G4double G4VMultipleScattering::ContinuousStep 663 G4double G4VMultipleScattering::ContinuousStepLimit( 391 const G 664 const G4Track& track, 392 G4doubl 665 G4double previousStepSize, 393 G4doubl 666 G4double currentMinimalStep, 394 G4doubl 667 G4double& currentSafety) 395 { 668 { 396 return GetContinuousStepLimit(track,previous 669 return GetContinuousStepLimit(track,previousStepSize,currentMinimalStep, 397 currentSafety) 670 currentSafety); 398 } 671 } 399 672 400 //....oooOO0OOooo........oooOO0OOooo........oo 673 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 401 674 402 G4double G4VMultipleScattering::GetMeanFreePat 675 G4double G4VMultipleScattering::GetMeanFreePath( 403 const G4Track&, G4double, G4Forc 676 const G4Track&, G4double, G4ForceCondition* condition) 404 { 677 { 405 *condition = Forced; 678 *condition = Forced; 406 return DBL_MAX; 679 return DBL_MAX; 407 } 680 } 408 681 409 //....oooOO0OOooo........oooOO0OOooo........oo 682 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 410 683 411 G4bool 684 G4bool 412 G4VMultipleScattering::StorePhysicsTable(const 685 G4VMultipleScattering::StorePhysicsTable(const G4ParticleDefinition* part, 413 const 686 const G4String& directory, 414 G4boo 687 G4bool ascii) 415 { 688 { 416 G4bool yes = true; 689 G4bool yes = true; 417 if(part != firstParticle || !emManager->IsMa << 690 if(part != firstParticle) { return yes; } 418 << 691 const G4VMultipleScattering* masterProcess = 419 return G4EmTableUtil::StoreMscTable(this, pa << 692 static_cast<const G4VMultipleScattering*>(GetMasterProcess()); 420 numberOfModels, verboseLevel, << 693 if(masterProcess && masterProcess != this) { return yes; } 421 ascii); << 694 >> 695 G4int nmod = modelManager->NumberOfModels(); >> 696 static const G4String ss[4] = {"1","2","3","4"}; >> 697 for(G4int i=0; i<nmod; ++i) { >> 698 G4VEmModel* msc = modelManager->GetModel(i); >> 699 yes = true; >> 700 G4PhysicsTable* table = msc->GetCrossSectionTable(); >> 701 if (table) { >> 702 G4int j = std::min(i,3); >> 703 G4String name = >> 704 GetPhysicsTableFileName(part,directory,"LambdaMod"+ss[j],ascii); >> 705 yes = table->StorePhysicsTable(name,ascii); >> 706 >> 707 if ( yes ) { >> 708 if ( verboseLevel>0 ) { >> 709 G4cout << "Physics table are stored for " >> 710 << part->GetParticleName() >> 711 << " and process " << GetProcessName() >> 712 << " with a name <" << name << "> " << G4endl; >> 713 } >> 714 } else { >> 715 G4cout << "Fail to store Physics Table for " >> 716 << part->GetParticleName() >> 717 << " and process " << GetProcessName() >> 718 << " in the directory <" << directory >> 719 << "> " << G4endl; >> 720 } >> 721 } >> 722 } >> 723 return yes; 422 } 724 } 423 725 424 //....oooOO0OOooo........oooOO0OOooo........oo 726 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 425 727 426 G4bool 728 G4bool 427 G4VMultipleScattering::RetrievePhysicsTable(co 729 G4VMultipleScattering::RetrievePhysicsTable(const G4ParticleDefinition*, 428 co 730 const G4String&, 429 G4 731 G4bool) 430 { 732 { 431 return true; 733 return true; 432 } 734 } 433 735 434 //....oooOO0OOooo........oooOO0OOooo........oo 736 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 435 737 436 void G4VMultipleScattering::ProcessDescription << 738 void G4VMultipleScattering::SetIonisation(G4VEnergyLossProcess* p) 437 { 739 { 438 if(nullptr != firstParticle) { << 740 for(G4int i=0; i<numberOfModels; ++i) { 439 StreamInfo(outFile, *firstParticle, true); << 741 G4VMscModel* msc = static_cast<G4VMscModel*>(GetModelByIndex(i, true)); >> 742 msc->SetIonisation(p, firstParticle); 440 } 743 } >> 744 } >> 745 >> 746 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 747 >> 748 void G4VMultipleScattering::ProcessDescription(std::ostream& outFile) const >> 749 { >> 750 outFile << "Multiple scattering process <" << GetProcessName() >> 751 << ">" << G4endl; 441 } 752 } 442 753 443 //....oooOO0OOooo........oooOO0OOooo........oo 754 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 444 755 445 756