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 66594 2012-12-23 10:17:42Z vnivanch $ 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 << 56 // 58 // >> 59 // Class Description: >> 60 // >> 61 // It is the generic process of multiple scattering it includes common >> 62 // part of calculations for all charged particles 57 63 58 // ------------------------------------------- 64 // ------------------------------------------------------------------- 59 // 65 // 60 //....oooOO0OOooo........oooOO0OOooo........oo 66 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 61 //....oooOO0OOooo........oooOO0OOooo........oo 67 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 62 68 63 #include "G4VMultipleScattering.hh" 69 #include "G4VMultipleScattering.hh" 64 #include "G4PhysicalConstants.hh" 70 #include "G4PhysicalConstants.hh" 65 #include "G4SystemOfUnits.hh" 71 #include "G4SystemOfUnits.hh" 66 #include "G4LossTableManager.hh" 72 #include "G4LossTableManager.hh" 67 #include "G4MaterialCutsCouple.hh" 73 #include "G4MaterialCutsCouple.hh" 68 #include "G4Step.hh" 74 #include "G4Step.hh" 69 #include "G4ParticleDefinition.hh" 75 #include "G4ParticleDefinition.hh" 70 #include "G4VEmFluctuationModel.hh" 76 #include "G4VEmFluctuationModel.hh" 71 #include "G4UnitsTable.hh" 77 #include "G4UnitsTable.hh" 72 #include "G4ProductionCutsTable.hh" 78 #include "G4ProductionCutsTable.hh" 73 #include "G4Electron.hh" 79 #include "G4Electron.hh" 74 #include "G4GenericIon.hh" 80 #include "G4GenericIon.hh" 75 #include "G4TransportationManager.hh" 81 #include "G4TransportationManager.hh" 76 #include "G4SafetyHelper.hh" 82 #include "G4SafetyHelper.hh" 77 #include "G4ParticleTable.hh" << 78 #include "G4ProcessVector.hh" << 79 #include "G4ProcessManager.hh" << 80 #include "G4LossTableBuilder.hh" << 81 #include "G4EmTableUtil.hh" << 82 #include <iostream> << 83 83 84 //....oooOO0OOooo........oooOO0OOooo........oo 84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 85 85 86 G4VMultipleScattering::G4VMultipleScattering(c << 86 G4VMultipleScattering::G4VMultipleScattering(const G4String& name, G4ProcessType): 87 : G4VContinuousDiscreteProcess("msc", fElect << 87 G4VContinuousDiscreteProcess("msc", fElectromagnetic), 88 fNewPosition(0.,0.,0.), << 88 numberOfModels(0), 89 fNewDirection(0.,0.,1.) << 89 firstParticle(0), >> 90 currParticle(0), >> 91 stepLimit(fUseSafety), >> 92 skin(1.0), >> 93 facrange(0.04), >> 94 facgeom(2.5), >> 95 latDisplasment(true), >> 96 isIon(false) 90 { 97 { 91 theParameters = G4EmParameters::Instance(); << 92 SetVerboseLevel(1); 98 SetVerboseLevel(1); 93 SetProcessSubType(fMultipleScattering); 99 SetProcessSubType(fMultipleScattering); >> 100 if("ionmsc" == name) { firstParticle = G4GenericIon::GenericIon(); } >> 101 >> 102 geomMin = 1.e-6*CLHEP::mm; >> 103 lowestKinEnergy = 10*eV; 94 104 95 lowestKinEnergy = 10*CLHEP::eV; << 105 // default limit on polar angle >> 106 polarAngleLimit = 0.0; 96 107 97 geomMin = 0.05*CLHEP::nm; << 108 physStepLimit = gPathLength = tPathLength = 0.0; 98 minDisplacement2 = geomMin*geomMin; << 109 fIonisation = 0; 99 110 100 pParticleChange = &fParticleChange; 111 pParticleChange = &fParticleChange; >> 112 safetyHelper = 0; >> 113 fPositionChanged = false; >> 114 isActive = false; 101 115 102 modelManager = new G4EmModelManager(); 116 modelManager = new G4EmModelManager(); 103 emManager = G4LossTableManager::Instance(); 117 emManager = G4LossTableManager::Instance(); 104 mscModels.reserve(2); << 105 emManager->Register(this); 118 emManager->Register(this); >> 119 >> 120 warn = 0; 106 } 121 } 107 122 108 //....oooOO0OOooo........oooOO0OOooo........oo 123 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 109 124 110 G4VMultipleScattering::~G4VMultipleScattering( 125 G4VMultipleScattering::~G4VMultipleScattering() 111 { 126 { >> 127 if(1 < verboseLevel) { >> 128 G4cout << "G4VMultipleScattering destruct " << GetProcessName() >> 129 << G4endl; >> 130 } 112 delete modelManager; 131 delete modelManager; 113 emManager->DeRegister(this); 132 emManager->DeRegister(this); 114 } 133 } 115 134 116 //....oooOO0OOooo........oooOO0OOooo........oo 135 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 117 136 118 void G4VMultipleScattering::AddEmModel(G4int o << 137 void G4VMultipleScattering::AddEmModel(G4int order, G4VEmModel* p, 119 const G << 138 const G4Region* region) 120 { 139 { 121 if(nullptr == ptr) { return; } << 140 G4VEmFluctuationModel* fm = 0; 122 G4VEmFluctuationModel* fm = nullptr; << 141 modelManager->AddEmModel(order, p, fm, region); 123 modelManager->AddEmModel(order, ptr, fm, reg << 142 if(p) { p->SetParticleChange(pParticleChange); } 124 ptr->SetParticleChange(pParticleChange); << 125 } 143 } 126 144 127 //....oooOO0OOooo........oooOO0OOooo........oo 145 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 128 146 129 void G4VMultipleScattering::SetEmModel(G4VMscM << 147 void G4VMultipleScattering::SetModel(G4VMscModel* p, G4int index) 130 { 148 { 131 if(nullptr == ptr) { return; } << 149 ++warn; 132 if(!mscModels.empty()) { << 150 if(warn < 10) { 133 for(auto & msc : mscModels) { if(msc == pt << 151 G4cout << "### G4VMultipleScattering::SetModel is obsolete method " 134 } << 152 << "and will be removed for the next release." << G4endl; 135 mscModels.push_back(ptr); << 153 G4cout << " Please, use SetEmModel" << G4endl; >> 154 } >> 155 G4int n = mscModels.size(); >> 156 if(index >= n) { for(G4int i=n; i<=index; ++i) {mscModels.push_back(0);} } >> 157 mscModels[index] = p; >> 158 } >> 159 >> 160 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 161 >> 162 G4VMscModel* G4VMultipleScattering::Model(G4int index) >> 163 { >> 164 ++warn; >> 165 if(warn < 10) { >> 166 G4cout << "### G4VMultipleScattering::Model is obsolete method " >> 167 << "and will be removed for the next release." << G4endl; >> 168 G4cout << " Please, use EmModel" << G4endl; >> 169 } >> 170 G4VMscModel* p = 0; >> 171 if(index >= 0 && index < G4int(mscModels.size())) { p = mscModels[index]; } >> 172 return p; >> 173 } >> 174 >> 175 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 176 >> 177 void G4VMultipleScattering::SetEmModel(G4VMscModel* p, G4int index) >> 178 { >> 179 G4int n = mscModels.size(); >> 180 if(index >= n) { for(G4int i=n; i<=index; ++i) { mscModels.push_back(0); } } >> 181 mscModels[index] = p; >> 182 } >> 183 >> 184 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 185 >> 186 G4VMscModel* G4VMultipleScattering::EmModel(G4int index) >> 187 { >> 188 G4VMscModel* p = 0; >> 189 if(index >= 0 && index < G4int(mscModels.size())) { p = mscModels[index]; } >> 190 return p; >> 191 } >> 192 >> 193 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 194 >> 195 G4VEmModel* >> 196 G4VMultipleScattering::GetModelByIndex(G4int idx, G4bool ver) const >> 197 { >> 198 return modelManager->GetModel(idx, ver); 136 } 199 } 137 200 138 //....oooOO0OOooo........oooOO0OOooo........oo 201 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 139 202 140 void 203 void 141 G4VMultipleScattering::PreparePhysicsTable(con 204 G4VMultipleScattering::PreparePhysicsTable(const G4ParticleDefinition& part) 142 { 205 { 143 G4bool master = emManager->IsMaster(); << 206 if(!firstParticle) { firstParticle = ∂ } 144 if (nullptr == firstParticle) { firstParticl << 207 if(part.GetParticleType() == "nucleus") { >> 208 SetStepLimitType(fMinimal); >> 209 SetLateralDisplasmentFlag(false); >> 210 SetRangeFactor(0.2); >> 211 if(&part == G4GenericIon::GenericIon()) { firstParticle = ∂ } >> 212 isIon = true; >> 213 } 145 214 146 emManager->PreparePhysicsTable(&part, this); 215 emManager->PreparePhysicsTable(&part, this); 147 currParticle = nullptr; << 216 currParticle = 0; >> 217 >> 218 if(1 < verboseLevel) { >> 219 G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for " >> 220 << GetProcessName() >> 221 << " and particle " << part.GetParticleName() >> 222 << " local particle " << firstParticle->GetParticleName() >> 223 << " isIon= " << isIon >> 224 << G4endl; >> 225 } 148 226 149 if(firstParticle == &part) { 227 if(firstParticle == &part) { 150 baseMat = emManager->GetTableBuilder()->Ge << 151 G4EmTableUtil::PrepareMscProcess(this, par << 152 stepLimit, facrange, << 153 latDisplacement, master, << 154 isIon, baseMat); << 155 228 >> 229 InitialiseProcess(firstParticle); >> 230 >> 231 // initialisation of models 156 numberOfModels = modelManager->NumberOfMod 232 numberOfModels = modelManager->NumberOfModels(); 157 currentModel = GetModelByIndex(0); << 233 for(G4int i=0; i<numberOfModels; ++i) { >> 234 G4VMscModel* msc = static_cast<G4VMscModel*>(modelManager->GetModel(i)); >> 235 msc->SetIonisation(0, firstParticle); >> 236 if(0 == i) { currentModel = msc; } >> 237 if(isIon) { >> 238 msc->SetStepLimitType(fMinimal); >> 239 msc->SetLateralDisplasmentFlag(false); >> 240 msc->SetRangeFactor(0.2); >> 241 } else { >> 242 msc->SetStepLimitType(StepLimitType()); >> 243 msc->SetLateralDisplasmentFlag(LateralDisplasmentFlag()); >> 244 msc->SetSkin(Skin()); >> 245 msc->SetRangeFactor(RangeFactor()); >> 246 msc->SetGeomFactor(GeomFactor()); >> 247 } >> 248 msc->SetPolarAngleLimit(polarAngleLimit); >> 249 G4double emax = >> 250 std::min(msc->HighEnergyLimit(),emManager->MaxKinEnergy()); >> 251 msc->SetHighEnergyLimit(emax); >> 252 } 158 253 159 if (nullptr == safetyHelper) { << 254 modelManager->Initialise(firstParticle, G4Electron::Electron(), >> 255 10.0, verboseLevel); >> 256 >> 257 if(!safetyHelper) { 160 safetyHelper = G4TransportationManager:: 258 safetyHelper = G4TransportationManager::GetTransportationManager() 161 ->GetSafetyHelper(); 259 ->GetSafetyHelper(); 162 safetyHelper->InitialiseHelper(); 260 safetyHelper->InitialiseHelper(); 163 } 261 } 164 } 262 } 165 } 263 } 166 264 167 //....oooOO0OOooo........oooOO0OOooo........oo 265 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 168 266 169 void G4VMultipleScattering::BuildPhysicsTable( 267 void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part) 170 { 268 { 171 G4bool master = emManager->IsMaster(); << 269 G4String num = part.GetParticleName(); 172 << 270 if(1 < verboseLevel) { 173 if(firstParticle == &part) { << 271 G4cout << "### G4VMultipleScattering::BuildPhysicsTable() for " 174 emManager->BuildPhysicsTable(&part); << 272 << GetProcessName() 175 } << 273 << " and particle " << num 176 const G4VMultipleScattering* ptr = this; << 274 << G4endl; 177 if(!master) { << 178 ptr = static_cast<const G4VMultipleScatter << 179 } 275 } 180 276 181 G4EmTableUtil::BuildMscProcess(this, ptr, pa << 277 emManager->BuildPhysicsTable(firstParticle); 182 numberOfModels, master); << 278 >> 279 // explicitly defined printout by particle name >> 280 if(1 < verboseLevel || >> 281 (0 < verboseLevel && (num == "e-" || >> 282 num == "e+" || num == "mu+" || >> 283 num == "mu-" || num == "proton"|| >> 284 num == "pi+" || num == "pi-" || >> 285 num == "kaon+" || num == "kaon-" || >> 286 num == "alpha" || num == "anti_proton" || >> 287 num == "GenericIon"))) >> 288 { >> 289 G4cout << G4endl << GetProcessName() >> 290 << ": for " << num >> 291 << " SubType= " << GetProcessSubType() >> 292 << G4endl; >> 293 PrintInfo(); >> 294 modelManager->DumpModelList(verboseLevel); >> 295 } >> 296 >> 297 if(1 < verboseLevel) { >> 298 G4cout << "### G4VMultipleScattering::BuildPhysicsTable() done for " >> 299 << GetProcessName() >> 300 << " and particle " << num >> 301 << G4endl; >> 302 } 183 } 303 } 184 304 185 //....oooOO0OOooo........oooOO0OOooo........oo 305 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 186 306 187 void G4VMultipleScattering::StreamInfo(std::os << 307 void G4VMultipleScattering::PrintInfoDefinition() 188 const G4ParticleDefinition& << 189 { 308 { 190 G4String indent = (rst ? " " : ""); << 309 if (0 < verboseLevel) { 191 outFile << G4endl << indent << GetProcessNam << 310 G4cout << G4endl << GetProcessName() 192 if (!rst) outFile << " for " << part.GetPart << 311 << ": for " << firstParticle->GetParticleName() 193 outFile << " SubType= " << GetProcessSubTy << 312 << " SubType= " << GetProcessSubType() 194 modelManager->DumpModelList(outFile, verbose << 313 << G4endl; >> 314 PrintInfo(); >> 315 modelManager->DumpModelList(verboseLevel); >> 316 } 195 } 317 } 196 318 197 //....oooOO0OOooo........oooOO0OOooo........oo 319 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 198 320 199 void G4VMultipleScattering::StartTracking(G4Tr 321 void G4VMultipleScattering::StartTracking(G4Track* track) 200 { 322 { 201 G4VEnergyLossProcess* eloss = nullptr; << 323 G4VEnergyLossProcess* eloss = 0; 202 if(track->GetParticleDefinition() != currPar 324 if(track->GetParticleDefinition() != currParticle) { 203 currParticle = track->GetParticleDefinitio 325 currParticle = track->GetParticleDefinition(); 204 fIonisation = emManager->GetEnergyLossProc 326 fIonisation = emManager->GetEnergyLossProcess(currParticle); 205 eloss = fIonisation; 327 eloss = fIonisation; 206 } 328 } 207 for(G4int i=0; i<numberOfModels; ++i) { << 329 // one model 208 G4VMscModel* msc = GetModelByIndex(i); << 330 if(1 == numberOfModels) { 209 msc->StartTracking(track); << 331 currentModel->StartTracking(track); 210 if(nullptr != eloss) { << 332 if(eloss) { currentModel->SetIonisation(fIonisation, currParticle); } 211 msc->SetIonisation(eloss, currParticle); << 333 >> 334 // many models >> 335 } else { >> 336 for(G4int i=0; i<numberOfModels; ++i) { >> 337 G4VMscModel* msc = static_cast<G4VMscModel*>(modelManager->GetModel(i)); >> 338 msc->StartTracking(track); >> 339 if(eloss) { msc->SetIonisation(fIonisation, currParticle); } 212 } 340 } 213 } 341 } 214 } 342 } 215 343 216 //....oooOO0OOooo........oooOO0OOooo........oo 344 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 217 345 218 G4double G4VMultipleScattering::AlongStepGetPh 346 G4double G4VMultipleScattering::AlongStepGetPhysicalInteractionLength( 219 const G4Track& tr 347 const G4Track& track, 220 G4double, 348 G4double, 221 G4double currentM 349 G4double currentMinimalStep, 222 G4double&, 350 G4double&, 223 G4GPILSelection* 351 G4GPILSelection* selection) 224 { 352 { 225 // get Step limit proposed by the process 353 // get Step limit proposed by the process 226 *selection = NotCandidateForSelection; 354 *selection = NotCandidateForSelection; 227 physStepLimit = gPathLength = tPathLength = 355 physStepLimit = gPathLength = tPathLength = currentMinimalStep; 228 356 229 G4double ekin = track.GetKineticEnergy(); 357 G4double ekin = track.GetKineticEnergy(); 230 /* << 231 G4cout << "MSC::AlongStepGPIL: Ekin= " << ek << 232 << " " << currParticle->GetParticleN << 233 << " currMod " << currentModel << 234 << G4endl; << 235 */ << 236 // isIon flag is used only to select a model 358 // isIon flag is used only to select a model 237 if(isIon) { 359 if(isIon) { 238 ekin *= proton_mass_c2/track.GetParticleDe 360 ekin *= proton_mass_c2/track.GetParticleDefinition()->GetPDGMass(); 239 } 361 } 240 const G4MaterialCutsCouple* couple = track.G << 241 362 242 // select new model, static cast is possible << 363 // select new model 243 if(1 < numberOfModels) { 364 if(1 < numberOfModels) { 244 currentModel = << 365 currentModel = static_cast<G4VMscModel*>( 245 static_cast<G4VMscModel*>(SelectModel(ek << 366 SelectModel(ekin,track.GetMaterialCutsCouple()->GetIndex())); 246 } 367 } 247 currentModel->SetCurrentCouple(couple); << 368 248 // msc is active is model is active, energy << 369 // step limit 249 // and step size is above the limit; << 370 if(currentModel->IsActive(ekin) && gPathLength >= geomMin 250 // if it is active msc may limit the step << 251 if(currentModel->IsActive(ekin) && tPathLeng << 252 && ekin >= lowestKinEnergy) { 371 && ekin >= lowestKinEnergy) { 253 isActive = true; 372 isActive = true; 254 tPathLength = << 373 tPathLength = currentModel->ComputeTruePathLengthLimit(track, gPathLength); 255 currentModel->ComputeTruePathLengthLimit << 256 if (tPathLength < physStepLimit) { 374 if (tPathLength < physStepLimit) { 257 *selection = CandidateForSelection; 375 *selection = CandidateForSelection; 258 } 376 } 259 } else { << 377 } else { isActive = false; } 260 isActive = false; << 378 /* 261 gPathLength = DBL_MAX; << 379 if(currParticle->GetPDGMass() > GeV) 262 } << 263 << 264 //if(currParticle->GetPDGMass() > GeV) << 265 /* << 266 G4cout << "MSC::AlongStepGPIL: Ekin= " << ek 380 G4cout << "MSC::AlongStepGPIL: Ekin= " << ekin 267 << " " << currParticle->GetParticleN << 381 << " gPathLength= " << gPathLength 268 << " gPathLength= " << gPathLength << 382 << " tPathLength= " << tPathLength 269 << " tPathLength= " << tPathLength << 383 << " currentMinimalStep= " << currentMinimalStep 270 << " currentMinimalStep= " << current << 384 << " isActive " << isActive << G4endl; 271 << " isActive " << isActive << G4endl << 272 */ 385 */ 273 return gPathLength; 386 return gPathLength; 274 } 387 } 275 388 276 //....oooOO0OOooo........oooOO0OOooo........oo 389 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 277 390 278 G4double 391 G4double 279 G4VMultipleScattering::PostStepGetPhysicalInte 392 G4VMultipleScattering::PostStepGetPhysicalInteractionLength( 280 const G4Track&, G4double, G4Forc 393 const G4Track&, G4double, G4ForceCondition* condition) 281 { 394 { 282 *condition = NotForced; << 395 *condition = Forced; >> 396 //*condition = NotForced; 283 return DBL_MAX; 397 return DBL_MAX; 284 } 398 } 285 399 286 //....oooOO0OOooo........oooOO0OOooo........oo 400 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 287 401 288 G4VParticleChange* 402 G4VParticleChange* 289 G4VMultipleScattering::AlongStepDoIt(const G4T 403 G4VMultipleScattering::AlongStepDoIt(const G4Track& track, const G4Step& step) 290 { 404 { 291 fParticleChange.InitialiseMSC(track, step); << 405 fParticleChange.ProposeMomentumDirection(step.GetPostStepPoint()->GetMomentumDirection()); 292 fNewPosition = fParticleChange.GetProposedPo << 406 fNewPosition = step.GetPostStepPoint()->GetPosition(); >> 407 fParticleChange.ProposePosition(fNewPosition); 293 fPositionChanged = false; 408 fPositionChanged = false; 294 409 295 G4double geomLength = step.GetStepLength(); 410 G4double geomLength = step.GetStepLength(); 296 411 297 // very small step - no msc 412 // very small step - no msc 298 if(!isActive) { 413 if(!isActive) { 299 tPathLength = geomLength; 414 tPathLength = geomLength; 300 415 301 // sample msc 416 // sample msc 302 } else { 417 } else { 303 G4double range = 418 G4double range = 304 currentModel->GetRange(currParticle,trac 419 currentModel->GetRange(currParticle,track.GetKineticEnergy(), 305 track.GetMaterial << 420 track.GetMaterialCutsCouple()); 306 421 307 tPathLength = currentModel->ComputeTrueSte << 422 G4double trueLength = currentModel->ComputeTrueStepLength(geomLength); 308 << 423 309 /* << 424 310 if(currParticle->GetPDGMass() > 0.9*GeV) << 425 // protection against wrong t->g->t conversion >> 426 // if(trueLength > tPathLength) >> 427 /* >> 428 if(currParticle->GetPDGMass() > GeV) 311 G4cout << "G4VMsc::AlongStepDoIt: GeomLeng 429 G4cout << "G4VMsc::AlongStepDoIt: GeomLength= " 312 << geomLength << 430 << geomLength 313 << " tPathLength= " << tPathLength << 431 << " trueLenght= " << trueLength 314 << " physStepLimit= " << physStepLi << 432 << " tPathLength= " << tPathLength 315 << " dr= " << range - tPathLength << 433 << " dr= " << range - trueLength 316 << " ekin= " << track.GetKineticEne << 434 << " ekin= " << track.GetKineticEnergy() << G4endl; 317 */ 435 */ 318 // protection against wrong t->g->t conver << 436 if (trueLength <= physStepLimit) { 319 tPathLength = std::min(tPathLength, physSt << 437 tPathLength = trueLength; >> 438 } else { >> 439 tPathLength = physStepLimit - 0.5*geomMin; >> 440 } 320 441 321 // do not sample scattering at the last or 442 // do not sample scattering at the last or at a small step 322 if(tPathLength < range && tPathLength > ge << 443 if(tPathLength + geomMin < range && tPathLength > geomMin) { 323 << 324 static const G4double minSafety = 1.20*C << 325 static const G4double sFact = 0.99; << 326 444 327 G4ThreeVector displacement = currentMode << 445 G4double preSafety = step.GetPreStepPoint()->GetSafety(); 328 step.GetPostStepPoint()->GetMomentumDi << 446 G4double postSafety= preSafety - geomLength; >> 447 G4bool safetyRecomputed = false; >> 448 if( postSafety < geomMin ) { >> 449 safetyRecomputed = true; >> 450 postSafety = currentModel->ComputeSafety(fNewPosition,0.0); >> 451 } >> 452 G4ThreeVector displacement = >> 453 currentModel->SampleScattering(step.GetPostStepPoint()->GetMomentumDirection(),postSafety); 329 454 330 G4double r2 = displacement.mag2(); 455 G4double r2 = displacement.mag2(); 331 //G4cout << " R= " << sqrt(r2) << " R << 456 332 // << " flag= " << fDispBeyondSafety << 457 //G4cout << "R= " << sqrt(r2) << " postSafety= " << postSafety << G4endl; 333 if(r2 > minDisplacement2) { << 458 334 << 459 // make correction for displacement 335 fPositionChanged = true; << 460 if(r2 > 0.0) { 336 G4double dispR = std::sqrt(r2); << 461 337 G4double postSafety = << 462 fPositionChanged = true; 338 sFact*safetyHelper->ComputeSafety(fN << 463 G4double fac = 1.0; 339 //G4cout<<" R= "<< dispR<<" postSaf << 464 340 << 465 // displaced point is definitely within the volume 341 // far away from geometry boundary << 466 if(r2 > postSafety*postSafety) { 342 if(postSafety > 0.0 && dispR <= postSa << 467 343 fNewPosition += displacement; << 468 G4double dispR = std::sqrt(r2); 344 << 469 if(!safetyRecomputed) { 345 //near the boundary << 470 postSafety = currentModel->ComputeSafety(fNewPosition, dispR); 346 } else { << 471 } 347 // displaced point is definitely wit << 472 // add a factor which ensure numerical stability 348 //G4cout<<" R= "<<dispR<<" postSa << 473 if(dispR > postSafety) { fac = 0.99*postSafety/dispR; } 349 if(dispR < postSafety) { << 474 } 350 fNewPosition += displacement; << 475 // compute new endpoint of the Step 351 << 476 fNewPosition += fac*displacement; 352 // reduced displacement << 477 //safetyHelper->ReLocateWithinVolume(fNewPosition); 353 } else if(postSafety > geomMin) { << 354 fNewPosition += displacement*(post << 355 << 356 // very small postSafety << 357 } else { << 358 fPositionChanged = false; << 359 } << 360 } << 361 if(fPositionChanged) { << 362 safetyHelper->ReLocateWithinVolume(f << 363 fParticleChange.ProposePosition(fNew << 364 } << 365 } 478 } 366 } 479 } 367 } 480 } 368 fParticleChange.ProposeTrueStepLength(tPathL 481 fParticleChange.ProposeTrueStepLength(tPathLength); >> 482 //fParticleChange.ProposePosition(fNewPosition); >> 483 return &fParticleChange; >> 484 } >> 485 >> 486 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... >> 487 >> 488 G4VParticleChange* >> 489 G4VMultipleScattering::PostStepDoIt(const G4Track& track, const G4Step&) >> 490 { >> 491 fParticleChange.Initialize(track); >> 492 >> 493 if(fPositionChanged) { >> 494 safetyHelper->ReLocateWithinVolume(fNewPosition); >> 495 fParticleChange.ProposePosition(fNewPosition); >> 496 } >> 497 369 return &fParticleChange; 498 return &fParticleChange; 370 } 499 } 371 500 372 //....oooOO0OOooo........oooOO0OOooo........oo 501 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 373 502 374 G4double G4VMultipleScattering::GetContinuousS 503 G4double G4VMultipleScattering::GetContinuousStepLimit( 375 const G 504 const G4Track& track, 376 G4doubl 505 G4double previousStepSize, 377 G4doubl 506 G4double currentMinimalStep, 378 G4doubl 507 G4double& currentSafety) 379 { 508 { 380 G4GPILSelection selection = NotCandidateForS 509 G4GPILSelection selection = NotCandidateForSelection; 381 G4double x = AlongStepGetPhysicalInteraction 510 G4double x = AlongStepGetPhysicalInteractionLength(track,previousStepSize, 382 << 511 currentMinimalStep, 383 << 512 currentSafety, &selection); 384 << 385 return x; 513 return x; 386 } 514 } 387 515 388 //....oooOO0OOooo........oooOO0OOooo........oo 516 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 389 517 390 G4double G4VMultipleScattering::ContinuousStep 518 G4double G4VMultipleScattering::ContinuousStepLimit( 391 const G 519 const G4Track& track, 392 G4doubl 520 G4double previousStepSize, 393 G4doubl 521 G4double currentMinimalStep, 394 G4doubl 522 G4double& currentSafety) 395 { 523 { 396 return GetContinuousStepLimit(track,previous 524 return GetContinuousStepLimit(track,previousStepSize,currentMinimalStep, 397 currentSafety) << 525 currentSafety); 398 } 526 } 399 527 400 //....oooOO0OOooo........oooOO0OOooo........oo 528 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 401 529 402 G4double G4VMultipleScattering::GetMeanFreePat 530 G4double G4VMultipleScattering::GetMeanFreePath( 403 const G4Track&, G4double, G4Forc 531 const G4Track&, G4double, G4ForceCondition* condition) 404 { 532 { 405 *condition = Forced; 533 *condition = Forced; 406 return DBL_MAX; 534 return DBL_MAX; 407 } 535 } 408 536 409 //....oooOO0OOooo........oooOO0OOooo........oo 537 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 410 538 411 G4bool 539 G4bool 412 G4VMultipleScattering::StorePhysicsTable(const 540 G4VMultipleScattering::StorePhysicsTable(const G4ParticleDefinition* part, 413 const << 541 const G4String& directory, 414 G4boo << 542 G4bool ascii) 415 { 543 { 416 G4bool yes = true; 544 G4bool yes = true; 417 if(part != firstParticle || !emManager->IsMa << 545 if(part != firstParticle) { return yes; } 418 << 546 G4int nmod = modelManager->NumberOfModels(); 419 return G4EmTableUtil::StoreMscTable(this, pa << 547 const G4String ss[4] = {"1","2","3","4"}; 420 numberOfModels, verboseLevel, << 548 for(G4int i=0; i<nmod; ++i) { 421 ascii); << 549 G4VEmModel* msc = modelManager->GetModel(i); >> 550 yes = true; >> 551 G4PhysicsTable* table = msc->GetCrossSectionTable(); >> 552 if (table) { >> 553 G4int j = std::min(i,3); >> 554 G4String name = >> 555 GetPhysicsTableFileName(part,directory,"LambdaMod"+ss[j],ascii); >> 556 yes = table->StorePhysicsTable(name,ascii); >> 557 >> 558 if ( yes ) { >> 559 if ( verboseLevel>0 ) { >> 560 G4cout << "Physics table are stored for " << part->GetParticleName() >> 561 << " and process " << GetProcessName() >> 562 << " with a name <" << name << "> " << G4endl; >> 563 } >> 564 } else { >> 565 G4cout << "Fail to store Physics Table for " << part->GetParticleName() >> 566 << " and process " << GetProcessName() >> 567 << " in the directory <" << directory >> 568 << "> " << G4endl; >> 569 } >> 570 } >> 571 } >> 572 return yes; 422 } 573 } 423 574 424 //....oooOO0OOooo........oooOO0OOooo........oo 575 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 425 576 426 G4bool 577 G4bool 427 G4VMultipleScattering::RetrievePhysicsTable(co 578 G4VMultipleScattering::RetrievePhysicsTable(const G4ParticleDefinition*, 428 co << 579 const G4String&, 429 G4 << 580 G4bool) 430 { 581 { 431 return true; 582 return true; 432 } 583 } 433 584 434 //....oooOO0OOooo........oooOO0OOooo........oo 585 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 435 586 436 void G4VMultipleScattering::ProcessDescription << 587 void G4VMultipleScattering::SetIonisation(G4VEnergyLossProcess* p) 437 { 588 { 438 if(nullptr != firstParticle) { << 589 for(G4int i=0; i<numberOfModels; ++i) { 439 StreamInfo(outFile, *firstParticle, true); << 590 G4VMscModel* msc = static_cast<G4VMscModel*>(modelManager->GetModel(i)); >> 591 msc->SetIonisation(p, firstParticle); 440 } 592 } 441 } 593 } 442 594 443 //....oooOO0OOooo........oooOO0OOooo........oo 595 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 444 596 445 597