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: G4WentzelVIModel.cc 96934 2016-05-18 09:10:41Z gcosmo $ 26 // 27 // 27 // ------------------------------------------- 28 // ------------------------------------------------------------------- 28 // 29 // 29 // GEANT4 Class file 30 // GEANT4 Class file 30 // 31 // 31 // 32 // 32 // File name: G4WentzelVIModel 33 // File name: G4WentzelVIModel 33 // 34 // 34 // Author: V.Ivanchenko 35 // Author: V.Ivanchenko 35 // 36 // 36 // Creation date: 09.04.2008 from G4MuMscModel 37 // Creation date: 09.04.2008 from G4MuMscModel 37 // 38 // 38 // Modifications: 39 // Modifications: 39 // 27-05-2010 V.Ivanchenko added G4WentzelOKan 40 // 27-05-2010 V.Ivanchenko added G4WentzelOKandVIxSection class to 40 // compute cross sections and sam 41 // compute cross sections and sample scattering angle 41 // 42 // 42 // 43 // 43 // Class Description: 44 // Class Description: 44 // 45 // 45 // Implementation of the model of multiple sca 46 // Implementation of the model of multiple scattering based on 46 // G.Wentzel, Z. Phys. 40 (1927) 590. 47 // G.Wentzel, Z. Phys. 40 (1927) 590. 47 // H.W.Lewis, Phys Rev 78 (1950) 526. 48 // H.W.Lewis, Phys Rev 78 (1950) 526. 48 // J.M. Fernandez-Varea et al., NIM B73 (1993) 49 // J.M. Fernandez-Varea et al., NIM B73 (1993) 447. 49 // L.Urban, CERN-OPEN-2006-077. 50 // L.Urban, CERN-OPEN-2006-077. 50 51 51 // ------------------------------------------- 52 // ------------------------------------------------------------------- 52 // 53 // 53 54 54 //....oooOO0OOooo........oooOO0OOooo........oo 55 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 55 //....oooOO0OOooo........oooOO0OOooo........oo 56 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 56 57 57 #include "G4WentzelVIModel.hh" 58 #include "G4WentzelVIModel.hh" 58 #include "G4PhysicalConstants.hh" 59 #include "G4PhysicalConstants.hh" 59 #include "G4SystemOfUnits.hh" 60 #include "G4SystemOfUnits.hh" 60 #include "Randomize.hh" 61 #include "Randomize.hh" 61 #include "G4ParticleChangeForMSC.hh" 62 #include "G4ParticleChangeForMSC.hh" 62 #include "G4PhysicsTableHelper.hh" 63 #include "G4PhysicsTableHelper.hh" 63 #include "G4ElementVector.hh" 64 #include "G4ElementVector.hh" 64 #include "G4ProductionCutsTable.hh" 65 #include "G4ProductionCutsTable.hh" 65 #include "G4EmParameters.hh" 66 #include "G4EmParameters.hh" 66 #include "G4Log.hh" 67 #include "G4Log.hh" 67 #include "G4Exp.hh" 68 #include "G4Exp.hh" 68 69 69 //....oooOO0OOooo........oooOO0OOooo........oo 70 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 70 71 71 using namespace std; 72 using namespace std; 72 73 73 const G4double invsqrt12 = 1./std::sqrt(12.); << 74 G4WentzelVIModel::G4WentzelVIModel(G4bool combined, const G4String& nam) : 74 const G4double numlimit = 0.1; << 75 G4VMscModel(nam), 75 const G4int minNCollisions = 10; << 76 ssFactor(1.05), 76 << 77 invssFactor(1.0), 77 G4WentzelVIModel::G4WentzelVIModel(G4bool comb << 78 currentCouple(nullptr), 78 : G4VMscModel(nam), << 79 singleScatteringMode(false), 79 singleScatteringMode(false), << 80 cosThetaMin(1.0), 80 isCombined(comb), << 81 cosThetaMax(-1.0), 81 useSecondMoment(false) << 82 fSecondMoments(nullptr), >> 83 idx2(0), >> 84 numlimit(0.1), >> 85 isCombined(combined), >> 86 useSecondMoment(false) 82 { 87 { 83 tlimitminfix = 1.e-6*CLHEP::mm; << 84 lowEnergyLimit = 1.0*CLHEP::eV; << 85 SetSingleScatteringFactor(1.25); 88 SetSingleScatteringFactor(1.25); 86 wokvi = new G4WentzelOKandVIxSection(isCombi << 89 invsqrt12 = 1./sqrt(12.); >> 90 tlimitminfix = 1.e-6*mm; >> 91 lowEnergyLimit = 1.0*eV; >> 92 particle = 0; >> 93 nelments = 5; >> 94 xsecn.resize(nelments); >> 95 prob.resize(nelments); >> 96 wokvi = new G4WentzelOKandVIxSection(combined); >> 97 fixedCut = -1.0; >> 98 >> 99 minNCollisions = 10; >> 100 >> 101 preKinEnergy = effKinEnergy = tPathLength = zPathLength = lambdaeff >> 102 = currentRange = xtsec = cosTetMaxNuc = 0.0; >> 103 currentMaterialIndex = 0; >> 104 >> 105 fParticleChange = nullptr; >> 106 currentCuts = nullptr; >> 107 currentMaterial = nullptr; 87 } 108 } 88 109 89 //....oooOO0OOooo........oooOO0OOooo........oo 110 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 90 111 91 G4WentzelVIModel::~G4WentzelVIModel() 112 G4WentzelVIModel::~G4WentzelVIModel() 92 { 113 { 93 delete wokvi; 114 delete wokvi; 94 if(IsMaster()) { << 115 if(fSecondMoments && IsMaster()) { 95 delete fSecondMoments; 116 delete fSecondMoments; 96 fSecondMoments = nullptr; << 117 fSecondMoments = 0; 97 } 118 } 98 } 119 } 99 120 100 //....oooOO0OOooo........oooOO0OOooo........oo 121 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 101 122 102 void G4WentzelVIModel::Initialise(const G4Part 123 void G4WentzelVIModel::Initialise(const G4ParticleDefinition* p, 103 const G4Data 124 const G4DataVector& cuts) 104 { 125 { 105 // reset parameters 126 // reset parameters 106 SetupParticle(p); 127 SetupParticle(p); 107 InitialiseParameters(p); << 108 currentRange = 0.0; 128 currentRange = 0.0; 109 129 110 if(isCombined) { 130 if(isCombined) { 111 G4double tet = PolarAngleLimit(); 131 G4double tet = PolarAngleLimit(); 112 if(tet <= 0.0) { cosThetaMax = 1 132 if(tet <= 0.0) { cosThetaMax = 1.0; } 113 else if(tet < CLHEP::pi) { cosThetaMax = c 133 else if(tet < CLHEP::pi) { cosThetaMax = cos(tet); } 114 } 134 } 115 //G4cout << "G4WentzelVIModel::Initialise " << 116 // << " " << this << " " << wokvi << G4end << 117 135 >> 136 //G4cout << "G4WentzelVIModel::Initialise " << p->GetParticleName() << G4endl; 118 wokvi->Initialise(p, cosThetaMax); 137 wokvi->Initialise(p, cosThetaMax); 119 /* << 138 /* 120 G4cout << "G4WentzelVIModel: " << particle-> 139 G4cout << "G4WentzelVIModel: " << particle->GetParticleName() 121 << " 1-cos(ThetaLimit)= " << 1 - cos 140 << " 1-cos(ThetaLimit)= " << 1 - cosThetaMax 122 << " SingScatFactor= " << ssFactor 141 << " SingScatFactor= " << ssFactor 123 << G4endl; 142 << G4endl; 124 */ 143 */ 125 currentCuts = &cuts; 144 currentCuts = &cuts; 126 145 127 // set values of some data members 146 // set values of some data members 128 fParticleChange = GetParticleChangeForMSC(p) 147 fParticleChange = GetParticleChangeForMSC(p); 129 148 130 // Access to materials << 131 const G4ProductionCutsTable* theCoupleTable << 132 G4ProductionCutsTable::GetProductionCutsTa << 133 G4int numOfCouples = (G4int)theCoupleTable-> << 134 nelments = 0; << 135 for(G4int i=0; i<numOfCouples; ++i) { << 136 G4int nelm = (G4int)theCoupleTable->GetMat << 137 nelments = std::max(nelments, nelm); << 138 } << 139 xsecn.resize(nelments); << 140 prob.resize(nelments); << 141 << 142 // build second moment table only if transpo 149 // build second moment table only if transport table is build 143 G4PhysicsTable* table = GetCrossSectionTable 150 G4PhysicsTable* table = GetCrossSectionTable(); 144 if(useSecondMoment && IsMaster() && nullptr << 151 if(useSecondMoment && IsMaster() && table) { 145 152 146 //G4cout << "### G4WentzelVIModel::Initial 153 //G4cout << "### G4WentzelVIModel::Initialise: build 2nd moment table " 147 // << table << G4endl; 154 // << table << G4endl; 148 fSecondMoments = 155 fSecondMoments = 149 G4PhysicsTableHelper::PreparePhysicsTabl 156 G4PhysicsTableHelper::PreparePhysicsTable(fSecondMoments); >> 157 // Access to materials >> 158 const G4ProductionCutsTable* theCoupleTable = >> 159 G4ProductionCutsTable::GetProductionCutsTable(); >> 160 size_t numOfCouples = theCoupleTable->GetTableSize(); 150 161 151 G4bool splineFlag = true; 162 G4bool splineFlag = true; 152 G4PhysicsVector* aVector = nullptr; 163 G4PhysicsVector* aVector = nullptr; 153 G4PhysicsVector* bVector = nullptr; 164 G4PhysicsVector* bVector = nullptr; 154 G4double emin = std::max(LowEnergyLimit(), 165 G4double emin = std::max(LowEnergyLimit(), LowEnergyActivationLimit()); 155 G4double emax = std::min(HighEnergyLimit() 166 G4double emax = std::min(HighEnergyLimit(), HighEnergyActivationLimit()); 156 if(emin < emax) { 167 if(emin < emax) { 157 std::size_t n = G4EmParameters::Instance << 168 size_t n = G4EmParameters::Instance()->NumberOfBinsPerDecade() 158 *G4lrint(std::log10(emax/emin)); 169 *G4lrint(std::log10(emax/emin)); 159 if(n < 3) { n = 3; } 170 if(n < 3) { n = 3; } 160 171 161 for(G4int i=0; i<numOfCouples; ++i) { << 172 for(size_t i=0; i<numOfCouples; ++i) { 162 173 163 //G4cout<< "i= " << i << " Flag= " << 174 //G4cout<< "i= " << i << " Flag= " << fSecondMoments->GetFlag(i) 164 // << G4endl; 175 // << G4endl; 165 if(fSecondMoments->GetFlag(i)) { 176 if(fSecondMoments->GetFlag(i)) { 166 DefineMaterial(theCoupleTable->GetMa 177 DefineMaterial(theCoupleTable->GetMaterialCutsCouple(i)); 167 178 168 delete (*fSecondMoments)[i]; 179 delete (*fSecondMoments)[i]; 169 if(nullptr == aVector) { << 180 if(!aVector) { 170 aVector = new G4PhysicsLogVector(e << 181 aVector = new G4PhysicsLogVector(emin, emax, n); 171 bVector = aVector; 182 bVector = aVector; 172 } else { 183 } else { 173 bVector = new G4PhysicsVector(*aVe 184 bVector = new G4PhysicsVector(*aVector); 174 } 185 } 175 for(std::size_t j=0; j<n; ++j) { << 186 for(size_t j=0; j<n; ++j) { 176 G4double e = bVector->Energy(j); 187 G4double e = bVector->Energy(j); 177 bVector->PutValue(j, ComputeSecond 188 bVector->PutValue(j, ComputeSecondMoment(p, e)*e*e); 178 } 189 } 179 if(splineFlag) { bVector->FillSecond 190 if(splineFlag) { bVector->FillSecondDerivatives(); } 180 (*fSecondMoments)[i] = bVector; 191 (*fSecondMoments)[i] = bVector; 181 } 192 } 182 } 193 } 183 } 194 } 184 //G4cout << *fSecondMoments << G4endl; 195 //G4cout << *fSecondMoments << G4endl; 185 } 196 } 186 } 197 } 187 198 188 //....oooOO0OOooo........oooOO0OOooo........oo 199 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 189 200 190 void G4WentzelVIModel::InitialiseLocal(const G 201 void G4WentzelVIModel::InitialiseLocal(const G4ParticleDefinition*, 191 G4VEmMo 202 G4VEmModel* masterModel) 192 { 203 { 193 fSecondMoments = static_cast<G4WentzelVIMode 204 fSecondMoments = static_cast<G4WentzelVIModel*>(masterModel) 194 ->GetSecondMomentTable(); 205 ->GetSecondMomentTable(); 195 } 206 } 196 207 197 //....oooOO0OOooo........oooOO0OOooo........oo << 198 << 199 void G4WentzelVIModel::DefineMaterial(const G4 << 200 { << 201 if(cup != currentCouple) { << 202 currentCouple = cup; << 203 SetCurrentCouple(cup); << 204 currentMaterial = cup->GetMaterial(); << 205 currentMaterialIndex = currentCouple->GetI << 206 } << 207 } << 208 << 209 //....oooOO0OOooo........oooOO0OOooo........oo 208 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 210 209 211 G4double G4WentzelVIModel::ComputeCrossSection 210 G4double G4WentzelVIModel::ComputeCrossSectionPerAtom( 212 const G4ParticleD 211 const G4ParticleDefinition* p, 213 G4double kinEnerg 212 G4double kinEnergy, 214 G4double Z, G4dou 213 G4double Z, G4double, 215 G4double cutEnerg 214 G4double cutEnergy, G4double) 216 { 215 { 217 G4double cross = 0.0; 216 G4double cross = 0.0; 218 SetupParticle(p); << 217 if(p != particle) { SetupParticle(p); } 219 if(kinEnergy < lowEnergyLimit) { return cros 218 if(kinEnergy < lowEnergyLimit) { return cross; } 220 if(nullptr == CurrentCouple()) { << 219 if(!CurrentCouple()) { 221 G4Exception("G4WentzelVIModel::ComputeCros 220 G4Exception("G4WentzelVIModel::ComputeCrossSectionPerAtom", "em0011", 222 FatalException, " G4MaterialCu 221 FatalException, " G4MaterialCutsCouple is not defined"); 223 return 0.0; 222 return 0.0; 224 } 223 } 225 DefineMaterial(CurrentCouple()); 224 DefineMaterial(CurrentCouple()); 226 cosTetMaxNuc = wokvi->SetupKinematic(kinEner 225 cosTetMaxNuc = wokvi->SetupKinematic(kinEnergy, currentMaterial); 227 if(cosTetMaxNuc < 1.0) { 226 if(cosTetMaxNuc < 1.0) { 228 G4double cut = (0.0 < fixedCut) ? fixedCu << 227 G4double cut = cutEnergy; >> 228 if(fixedCut > 0.0) { cut = fixedCut; } 229 G4double cost = wokvi->SetupTarget(G4lrint 229 G4double cost = wokvi->SetupTarget(G4lrint(Z), cut); 230 cross = wokvi->ComputeTransportCrossSectio 230 cross = wokvi->ComputeTransportCrossSectionPerAtom(cost); 231 /* 231 /* 232 if(p->GetParticleName() == "e-") 232 if(p->GetParticleName() == "e-") 233 G4cout << "G4WentzelVIModel::CS: Z= " << G 233 G4cout << "G4WentzelVIModel::CS: Z= " << G4int(Z) << " e(MeV)= "<<kinEnergy 234 << " 1-cosN= " << 1 - cosTetMaxNuc 234 << " 1-cosN= " << 1 - cosTetMaxNuc << " cross(bn)= " << cross/barn 235 << " " << particle->GetParticleName 235 << " " << particle->GetParticleName() << G4endl; 236 */ 236 */ 237 } 237 } 238 return cross; 238 return cross; 239 } 239 } 240 240 241 //....oooOO0OOooo........oooOO0OOooo........oo 241 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 242 242 243 void G4WentzelVIModel::StartTracking(G4Track* 243 void G4WentzelVIModel::StartTracking(G4Track* track) 244 { 244 { 245 /* << 245 SetupParticle(track->GetDynamicParticle()->GetDefinition()); 246 G4cout << "G4WentzelVIModel::StartTracking " << 247 << track->GetParticleDefinition()->GetParti << 248 << " workvi: " << wokvi << G4endl; << 249 */ << 250 SetupParticle(track->GetParticleDefinition() << 251 } 246 } 252 247 253 //....oooOO0OOooo........oooOO0OOooo........oo 248 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 254 249 255 G4double G4WentzelVIModel::ComputeTruePathLeng 250 G4double G4WentzelVIModel::ComputeTruePathLengthLimit( 256 const G4Track& tr 251 const G4Track& track, 257 G4double& current 252 G4double& currentMinimalStep) 258 { 253 { 259 G4double tlimit = currentMinimalStep; 254 G4double tlimit = currentMinimalStep; 260 const G4DynamicParticle* dp = track.GetDynam 255 const G4DynamicParticle* dp = track.GetDynamicParticle(); 261 const G4StepPoint* sp = track.GetStep()->Get << 256 G4StepPoint* sp = track.GetStep()->GetPreStepPoint(); 262 G4StepStatus stepStatus = sp->GetStepStatus( 257 G4StepStatus stepStatus = sp->GetStepStatus(); 263 singleScatteringMode = false; 258 singleScatteringMode = false; 264 259 265 //G4cout << "G4WentzelVIModel::ComputeTruePa 260 //G4cout << "G4WentzelVIModel::ComputeTruePathLengthLimit stepStatus= " 266 // << stepStatus << " " << track.Ge 261 // << stepStatus << " " << track.GetDefinition()->GetParticleName() 267 // << G4endl; 262 // << G4endl; 268 263 269 // initialisation for each step, lambda may 264 // initialisation for each step, lambda may be computed from scratch 270 preKinEnergy = dp->GetKineticEnergy(); 265 preKinEnergy = dp->GetKineticEnergy(); 271 effKinEnergy = preKinEnergy; 266 effKinEnergy = preKinEnergy; 272 DefineMaterial(track.GetMaterialCutsCouple() 267 DefineMaterial(track.GetMaterialCutsCouple()); 273 const G4double logPreKinEnergy = dp->GetLogK << 268 lambdaeff = GetTransportMeanFreePath(particle,preKinEnergy); 274 lambdaeff = GetTransportMeanFreePath(particl << 269 currentRange = GetRange(particle,preKinEnergy,currentCouple); 275 currentRange = GetRange(particle,preKinEnerg << 276 cosTetMaxNuc = wokvi->SetupKinematic(preKinE 270 cosTetMaxNuc = wokvi->SetupKinematic(preKinEnergy, currentMaterial); 277 271 278 //G4cout << "lambdaeff= " << lambdaeff << " 272 //G4cout << "lambdaeff= " << lambdaeff << " Range= " << currentRange 279 // << " tlimit= " << tlimit << " 1-cost= " < 273 // << " tlimit= " << tlimit << " 1-cost= " << 1 - cosTetMaxNuc << G4endl; 280 274 281 // extra check for abnormal situation 275 // extra check for abnormal situation 282 // this check needed to run MSC with eIoni a 276 // this check needed to run MSC with eIoni and eBrem inactivated 283 if(tlimit > currentRange) { tlimit = current 277 if(tlimit > currentRange) { tlimit = currentRange; } 284 278 285 // stop here if small range particle 279 // stop here if small range particle 286 if(tlimit < tlimitminfix) { 280 if(tlimit < tlimitminfix) { 287 return ConvertTrueToGeom(tlimit, currentMi 281 return ConvertTrueToGeom(tlimit, currentMinimalStep); 288 } 282 } 289 283 290 // pre step 284 // pre step 291 G4double presafety = sp->GetSafety(); 285 G4double presafety = sp->GetSafety(); 292 // far from geometry boundary 286 // far from geometry boundary 293 if(currentRange < presafety) { 287 if(currentRange < presafety) { 294 return ConvertTrueToGeom(tlimit, currentMi 288 return ConvertTrueToGeom(tlimit, currentMinimalStep); 295 } 289 } 296 290 297 // compute presafety again if presafety <= 0 291 // compute presafety again if presafety <= 0 and no boundary 298 // i.e. when it is needed for optimization p 292 // i.e. when it is needed for optimization purposes 299 if(stepStatus != fGeomBoundary && presafety 293 if(stepStatus != fGeomBoundary && presafety < tlimitminfix) { 300 presafety = ComputeSafety(sp->GetPosition( 294 presafety = ComputeSafety(sp->GetPosition(), tlimit); 301 if(currentRange < presafety) { 295 if(currentRange < presafety) { 302 return ConvertTrueToGeom(tlimit, current 296 return ConvertTrueToGeom(tlimit, currentMinimalStep); 303 } 297 } 304 } 298 } 305 /* 299 /* 306 G4cout << "e(MeV)= " << preKinEnergy/MeV 300 G4cout << "e(MeV)= " << preKinEnergy/MeV 307 << " " << particle->GetParticleName( 301 << " " << particle->GetParticleName() 308 << " CurLimit(mm)= " << tlimit/mm <<" 302 << " CurLimit(mm)= " << tlimit/mm <<" safety(mm)= " << presafety/mm 309 << " R(mm)= " <<currentRange/mm 303 << " R(mm)= " <<currentRange/mm 310 << " L0(mm^-1)= " << lambdaeff*mm 304 << " L0(mm^-1)= " << lambdaeff*mm 311 << G4endl; 305 << G4endl; 312 */ 306 */ 313 // natural limit for high energy 307 // natural limit for high energy 314 G4double rlimit = std::max(facrange*currentR 308 G4double rlimit = std::max(facrange*currentRange, 315 (1.0 - cosTetMaxN 309 (1.0 - cosTetMaxNuc)*lambdaeff*invssFactor); 316 310 317 // low-energy e- 311 // low-energy e- 318 if(cosThetaMax > cosTetMaxNuc) { 312 if(cosThetaMax > cosTetMaxNuc) { 319 rlimit = std::min(rlimit, facsafety*presaf 313 rlimit = std::min(rlimit, facsafety*presafety); 320 } 314 } 321 315 322 // cut correction 316 // cut correction 323 G4double rcut = currentCouple->GetProduction 317 G4double rcut = currentCouple->GetProductionCuts()->GetProductionCut(1); 324 //G4cout << "rcut= " << rcut << " rlimit= " 318 //G4cout << "rcut= " << rcut << " rlimit= " << rlimit << " presafety= " 325 // << presafety << " 1-cosThetaMax= " <<1-co 319 // << presafety << " 1-cosThetaMax= " <<1-cosThetaMax 326 //<< " 1-cosTetMaxNuc= " << 1-cosTetMaxNuc < 320 //<< " 1-cosTetMaxNuc= " << 1-cosTetMaxNuc << G4endl; 327 if(rcut > rlimit) { rlimit = std::min(rlimit << 321 if(rcut > rlimit) { rlimit = std::min(rlimit, rcut*sqrt(rlimit/rcut)); } 328 322 329 tlimit = std::min(tlimit, rlimit); 323 tlimit = std::min(tlimit, rlimit); 330 tlimit = std::max(tlimit, tlimitminfix); 324 tlimit = std::max(tlimit, tlimitminfix); 331 325 332 // step limit in infinite media 326 // step limit in infinite media 333 tlimit = std::min(tlimit, 50*currentMaterial 327 tlimit = std::min(tlimit, 50*currentMaterial->GetRadlen()/facgeom); 334 328 335 //compute geomlimit and force few steps with 329 //compute geomlimit and force few steps within a volume 336 if (steppingAlgorithm == fUseDistanceToBound 330 if (steppingAlgorithm == fUseDistanceToBoundary 337 && stepStatus == fGeomBoundary) { 331 && stepStatus == fGeomBoundary) { 338 332 339 G4double geomlimit = ComputeGeomLimit(trac 333 G4double geomlimit = ComputeGeomLimit(track, presafety, currentRange); 340 tlimit = std::min(tlimit, geomlimit/facgeo 334 tlimit = std::min(tlimit, geomlimit/facgeom); 341 } 335 } 342 /* 336 /* 343 G4cout << particle->GetParticleName() << " e 337 G4cout << particle->GetParticleName() << " e= " << preKinEnergy 344 << " L0= " << lambdaeff << " R= " << 338 << " L0= " << lambdaeff << " R= " << currentRange 345 << " tlimit= " << tlimit 339 << " tlimit= " << tlimit 346 << " currentMinimalStep= " << curre 340 << " currentMinimalStep= " << currentMinimalStep << G4endl; 347 */ 341 */ 348 return ConvertTrueToGeom(tlimit, currentMini 342 return ConvertTrueToGeom(tlimit, currentMinimalStep); 349 } 343 } 350 344 351 //....oooOO0OOooo........oooOO0OOooo........oo 345 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 352 346 353 G4double G4WentzelVIModel::ComputeGeomPathLeng 347 G4double G4WentzelVIModel::ComputeGeomPathLength(G4double truelength) 354 { 348 { 355 zPathLength = tPathLength = truelength; 349 zPathLength = tPathLength = truelength; 356 350 357 // small step use only single scattering 351 // small step use only single scattering 358 cosThetaMin = 1.0; 352 cosThetaMin = 1.0; 359 ComputeTransportXSectionPerVolume(cosThetaMi 353 ComputeTransportXSectionPerVolume(cosThetaMin); 360 //G4cout << "xtsec= " << xtsec << " Nav= " 354 //G4cout << "xtsec= " << xtsec << " Nav= " 361 // << zPathLength*xtsec << G4endl; 355 // << zPathLength*xtsec << G4endl; 362 if(0.0 >= lambdaeff || G4int(zPathLength*xts 356 if(0.0 >= lambdaeff || G4int(zPathLength*xtsec) < minNCollisions) { 363 singleScatteringMode = true; 357 singleScatteringMode = true; 364 lambdaeff = DBL_MAX; 358 lambdaeff = DBL_MAX; 365 359 366 } else { 360 } else { 367 //G4cout << "ComputeGeomPathLength: tLengt 361 //G4cout << "ComputeGeomPathLength: tLength= " << tPathLength 368 // << " Leff= " << lambdaeff << 362 // << " Leff= " << lambdaeff << G4endl; 369 // small step 363 // small step 370 if(tPathLength < numlimit*lambdaeff) { 364 if(tPathLength < numlimit*lambdaeff) { 371 G4double tau = tPathLength/lambdaeff; 365 G4double tau = tPathLength/lambdaeff; 372 zPathLength *= (1.0 - 0.5*tau + tau*tau/ 366 zPathLength *= (1.0 - 0.5*tau + tau*tau/6.0); 373 367 374 // medium step 368 // medium step 375 } else { 369 } else { 376 G4double e1 = 0.0; 370 G4double e1 = 0.0; 377 if(currentRange > tPathLength) { 371 if(currentRange > tPathLength) { 378 e1 = GetEnergy(particle,currentRange-t 372 e1 = GetEnergy(particle,currentRange-tPathLength,currentCouple); 379 } 373 } 380 effKinEnergy = 0.5*(e1 + preKinEnergy); 374 effKinEnergy = 0.5*(e1 + preKinEnergy); 381 cosTetMaxNuc = wokvi->SetupKinematic(eff 375 cosTetMaxNuc = wokvi->SetupKinematic(effKinEnergy, currentMaterial); 382 lambdaeff = GetTransportMeanFreePath(par 376 lambdaeff = GetTransportMeanFreePath(particle, effKinEnergy); 383 //G4cout << " tLength= "<< tPathLength<< 377 //G4cout << " tLength= "<< tPathLength<< " Leff= " << lambdaeff << G4endl; 384 zPathLength = lambdaeff; 378 zPathLength = lambdaeff; 385 if(tPathLength*numlimit < lambdaeff) { 379 if(tPathLength*numlimit < lambdaeff) { 386 zPathLength *= (1.0 - G4Exp(-tPathLeng 380 zPathLength *= (1.0 - G4Exp(-tPathLength/lambdaeff)); 387 } 381 } 388 } 382 } 389 } 383 } 390 //G4cout << "Comp.geom: zLength= "<<zPathLen 384 //G4cout << "Comp.geom: zLength= "<<zPathLength<<" tLength= " 391 // << tPathLength<< " Leff= " << lam 385 // << tPathLength<< " Leff= " << lambdaeff << G4endl; 392 return zPathLength; 386 return zPathLength; 393 } 387 } 394 388 395 //....oooOO0OOooo........oooOO0OOooo........oo 389 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 396 390 397 G4double G4WentzelVIModel::ComputeTrueStepLeng 391 G4double G4WentzelVIModel::ComputeTrueStepLength(G4double geomStepLength) 398 { 392 { 399 // initialisation of single scattering x-sec 393 // initialisation of single scattering x-section 400 /* 394 /* 401 G4cout << "ComputeTrueStepLength: Step= " << 395 G4cout << "ComputeTrueStepLength: Step= " << geomStepLength 402 << " geomL= " << zPathLength 396 << " geomL= " << zPathLength 403 << " Lambda= " << lambdaeff 397 << " Lambda= " << lambdaeff 404 << " 1-cosThetaMaxNuc= " << 1 - cos 398 << " 1-cosThetaMaxNuc= " << 1 - cosTetMaxNuc << G4endl; 405 */ 399 */ 406 if(singleScatteringMode) { 400 if(singleScatteringMode) { 407 zPathLength = tPathLength = geomStepLength 401 zPathLength = tPathLength = geomStepLength; 408 402 409 } else { 403 } else { 410 404 411 // step defined by transportation 405 // step defined by transportation 412 // change both geom and true step lengths 406 // change both geom and true step lengths 413 if(geomStepLength < zPathLength) { 407 if(geomStepLength < zPathLength) { 414 408 415 // single scattering 409 // single scattering 416 if(G4int(geomStepLength*xtsec) < minNCol 410 if(G4int(geomStepLength*xtsec) < minNCollisions) { 417 zPathLength = tPathLength = geomStepLe 411 zPathLength = tPathLength = geomStepLength; 418 lambdaeff = DBL_MAX; 412 lambdaeff = DBL_MAX; 419 singleScatteringMode = true; 413 singleScatteringMode = true; 420 414 421 // multiple scattering 415 // multiple scattering 422 } else { 416 } else { 423 // small step 417 // small step 424 if(geomStepLength < numlimit*lambdaeff 418 if(geomStepLength < numlimit*lambdaeff) { 425 G4double tau = geomStepLength/lambda 419 G4double tau = geomStepLength/lambdaeff; 426 tPathLength = geomStepLength*(1.0 + 420 tPathLength = geomStepLength*(1.0 + 0.5*tau + tau*tau/3.0); 427 421 428 // energy correction for a big step 422 // energy correction for a big step 429 } else { 423 } else { 430 tPathLength *= geomStepLength/zPathL 424 tPathLength *= geomStepLength/zPathLength; 431 G4double e1 = 0.0; 425 G4double e1 = 0.0; 432 if(currentRange > tPathLength) { 426 if(currentRange > tPathLength) { 433 e1 = GetEnergy(particle,currentRan 427 e1 = GetEnergy(particle,currentRange-tPathLength,currentCouple); 434 } 428 } 435 effKinEnergy = 0.5*(e1 + preKinEnerg 429 effKinEnergy = 0.5*(e1 + preKinEnergy); 436 cosTetMaxNuc = wokvi->SetupKinematic 430 cosTetMaxNuc = wokvi->SetupKinematic(effKinEnergy, currentMaterial); 437 lambdaeff = GetTransportMeanFreePath 431 lambdaeff = GetTransportMeanFreePath(particle, effKinEnergy); 438 G4double tau = geomStepLength/lambda 432 G4double tau = geomStepLength/lambdaeff; 439 433 440 if(tau < 0.999999) { tPathLength = - 434 if(tau < 0.999999) { tPathLength = -lambdaeff*G4Log(1.0 - tau); } 441 else { tPathLength = c 435 else { tPathLength = currentRange; } 442 } 436 } 443 zPathLength = geomStepLength; 437 zPathLength = geomStepLength; 444 } 438 } 445 } 439 } 446 } 440 } 447 // check of step length 441 // check of step length 448 // define threshold angle between single and 442 // define threshold angle between single and multiple scattering 449 if(!singleScatteringMode) { 443 if(!singleScatteringMode) { 450 cosThetaMin -= ssFactor*tPathLength/lambda 444 cosThetaMin -= ssFactor*tPathLength/lambdaeff; 451 xtsec = 0.0; 445 xtsec = 0.0; 452 446 453 // recompute transport cross section - do 447 // recompute transport cross section - do not change energy 454 // anymore - cannot be applied for big ste 448 // anymore - cannot be applied for big steps 455 if(cosThetaMin > cosTetMaxNuc) { 449 if(cosThetaMin > cosTetMaxNuc) { 456 // new computation 450 // new computation 457 G4double cross = ComputeTransportXSectio 451 G4double cross = ComputeTransportXSectionPerVolume(cosThetaMin); 458 //G4cout << "%%%% cross= " << cross << " 452 //G4cout << "%%%% cross= " << cross << " xtsec= " << xtsec 459 // << " 1-cosTMin= " << 1.0 - 453 // << " 1-cosTMin= " << 1.0 - cosThetaMin << G4endl; 460 if(cross <= 0.0) { 454 if(cross <= 0.0) { 461 singleScatteringMode = true; 455 singleScatteringMode = true; 462 tPathLength = zPathLength; 456 tPathLength = zPathLength; 463 lambdaeff = DBL_MAX; 457 lambdaeff = DBL_MAX; 464 cosThetaMin = 1.0; 458 cosThetaMin = 1.0; 465 } else if(xtsec > 0.0) { 459 } else if(xtsec > 0.0) { 466 460 467 lambdaeff = 1./cross; 461 lambdaeff = 1./cross; 468 G4double tau = zPathLength*cross; 462 G4double tau = zPathLength*cross; 469 if(tau < numlimit) { 463 if(tau < numlimit) { 470 tPathLength = zPathLength*(1.0 + 0.5 464 tPathLength = zPathLength*(1.0 + 0.5*tau + tau*tau/3.0); 471 } else if(tau < 0.999999) { 465 } else if(tau < 0.999999) { 472 tPathLength = -lambdaeff*G4Log(1.0 - 466 tPathLength = -lambdaeff*G4Log(1.0 - tau); 473 } else { 467 } else { 474 tPathLength = currentRange; 468 tPathLength = currentRange; 475 } 469 } 476 } 470 } 477 } 471 } 478 } 472 } 479 tPathLength = std::min(tPathLength, currentR 473 tPathLength = std::min(tPathLength, currentRange); 480 /* 474 /* 481 G4cout <<"Comp.true: zLength= "<<zPathLength 475 G4cout <<"Comp.true: zLength= "<<zPathLength<<" tLength= "<<tPathLength 482 <<" Leff(mm)= "<<lambdaeff/mm<<" sig0 476 <<" Leff(mm)= "<<lambdaeff/mm<<" sig0(1/mm)= " << xtsec <<G4endl; 483 G4cout << particle->GetParticleName() << " 1 477 G4cout << particle->GetParticleName() << " 1-cosThetaMin= " << 1-cosThetaMin 484 << " 1-cosTetMaxNuc= " << 1-cosTetMax 478 << " 1-cosTetMaxNuc= " << 1-cosTetMaxNuc 485 << " e(MeV)= " << preKinEnergy/MeV << 479 << " e(MeV)= " << preKinEnergy/MeV << " " 486 << " SSmode= " << singleScatteringMod 480 << " SSmode= " << singleScatteringMode << G4endl; 487 */ 481 */ 488 return tPathLength; 482 return tPathLength; 489 } 483 } 490 484 491 //....oooOO0OOooo........oooOO0OOooo........oo 485 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 492 486 493 G4ThreeVector& 487 G4ThreeVector& 494 G4WentzelVIModel::SampleScattering(const G4Thr 488 G4WentzelVIModel::SampleScattering(const G4ThreeVector& oldDirection, 495 G4double /* 489 G4double /*safety*/) 496 { 490 { 497 fDisplacement.set(0.0,0.0,0.0); 491 fDisplacement.set(0.0,0.0,0.0); 498 //G4cout << "!##! G4WentzelVIModel::SampleSc 492 //G4cout << "!##! G4WentzelVIModel::SampleScattering for " 499 // << particle->GetParticleName() << 493 // << particle->GetParticleName() << G4endl; 500 494 501 // ignore scattering for zero step length an 495 // ignore scattering for zero step length and energy below the limit 502 if(preKinEnergy < lowEnergyLimit || tPathLen 496 if(preKinEnergy < lowEnergyLimit || tPathLength <= 0.0) 503 { return fDisplacement; } 497 { return fDisplacement; } 504 498 505 G4double invlambda = 0.0; 499 G4double invlambda = 0.0; 506 if(lambdaeff < DBL_MAX) { invlambda = 0.5/la 500 if(lambdaeff < DBL_MAX) { invlambda = 0.5/lambdaeff; } 507 501 508 // use average kinetic energy over the step 502 // use average kinetic energy over the step 509 G4double cut = (*currentCuts)[currentMateria 503 G4double cut = (*currentCuts)[currentMaterialIndex]; 510 if(fixedCut > 0.0) { cut = fixedCut; } 504 if(fixedCut > 0.0) { cut = fixedCut; } 511 /* 505 /* 512 G4cout <<"SampleScat: E0(MeV)= "<< preKinEne 506 G4cout <<"SampleScat: E0(MeV)= "<< preKinEnergy/MeV 513 << " Leff= " << lambdaeff <<" sig0( 507 << " Leff= " << lambdaeff <<" sig0(1/mm)= " << xtsec 514 << " xmsc= " << tPathLength*invlamb 508 << " xmsc= " << tPathLength*invlambda 515 << " safety= " << safety << G4endl; 509 << " safety= " << safety << G4endl; 516 */ 510 */ 517 // step limit due msc 511 // step limit due msc 518 G4int nMscSteps = 1; 512 G4int nMscSteps = 1; 519 G4double x0 = tPathLength; 513 G4double x0 = tPathLength; 520 G4double z0 = x0*invlambda; 514 G4double z0 = x0*invlambda; >> 515 //G4double zzz = 0.0; 521 G4double prob2 = 0.0; 516 G4double prob2 = 0.0; 522 517 523 CLHEP::HepRandomEngine* rndmEngine = G4Rando 518 CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine(); 524 519 525 // large scattering angle case - two step ap 520 // large scattering angle case - two step approach 526 if(!singleScatteringMode) { 521 if(!singleScatteringMode) { >> 522 static const G4double zzmin = 0.05; 527 if(useSecondMoment) { 523 if(useSecondMoment) { 528 G4double z1 = invlambda*invlambda; 524 G4double z1 = invlambda*invlambda; 529 G4double z2 = SecondMoment(particle, cur 525 G4double z2 = SecondMoment(particle, currentCouple, effKinEnergy); 530 prob2 = (z2 - z1)/(1.5*z1 - z2); 526 prob2 = (z2 - z1)/(1.5*z1 - z2); 531 } 527 } 532 // numerical limitation on step length for << 528 // if(z0 > zzmin && safety > tlimitminfix) { 533 if (z0 > 0.05 && z0 < 30.) { << 529 if(z0 > zzmin) { 534 x0 *= 0.5; 530 x0 *= 0.5; 535 z0 *= 0.5; 531 z0 *= 0.5; 536 nMscSteps = 2; 532 nMscSteps = 2; 537 G4double zzz = G4Exp(-1.0/z0); << 533 } >> 534 //if(z0 > zzmin) { zzz = G4Exp(-1.0/z0); } >> 535 G4double zzz = 0.0; >> 536 if(z0 > zzmin) { >> 537 zzz = G4Exp(-1.0/z0); 538 z0 += zzz; 538 z0 += zzz; 539 prob2 *= (1.0 + zzz); << 539 prob2 *= (1 + zzz); 540 } 540 } 541 prob2 /= (1.0 + prob2); << 541 prob2 /= (1 + prob2); 542 } 542 } 543 543 544 // step limit due to single scattering 544 // step limit due to single scattering 545 G4double x1 = 2*tPathLength; 545 G4double x1 = 2*tPathLength; 546 if(0.0 < xtsec) { x1 = -G4Log(rndmEngine->fl 546 if(0.0 < xtsec) { x1 = -G4Log(rndmEngine->flat())/xtsec; } 547 547 548 // no scattering case 548 // no scattering case 549 if(singleScatteringMode && x1 > tPathLength) 549 if(singleScatteringMode && x1 > tPathLength) 550 { return fDisplacement; } 550 { return fDisplacement; } 551 551 552 const G4ElementVector* theElementVector = 552 const G4ElementVector* theElementVector = 553 currentMaterial->GetElementVector(); 553 currentMaterial->GetElementVector(); 554 std::size_t nelm = currentMaterial->GetNumbe << 554 G4int nelm = currentMaterial->GetNumberOfElements(); 555 555 556 // geometry 556 // geometry 557 G4double sint, cost, phi; 557 G4double sint, cost, phi; 558 G4ThreeVector temp(0.0,0.0,1.0); 558 G4ThreeVector temp(0.0,0.0,1.0); 559 559 560 // current position and direction relative t 560 // current position and direction relative to the end point 561 // because of magnetic field geometry is com 561 // because of magnetic field geometry is computed relatively to the 562 // end point of the step 562 // end point of the step 563 G4ThreeVector dir(0.0,0.0,1.0); 563 G4ThreeVector dir(0.0,0.0,1.0); 564 fDisplacement.set(0.0,0.0,-zPathLength); 564 fDisplacement.set(0.0,0.0,-zPathLength); 565 565 566 G4double mscfac = zPathLength/tPathLength; 566 G4double mscfac = zPathLength/tPathLength; 567 567 568 // start a loop 568 // start a loop 569 G4double x2 = x0; 569 G4double x2 = x0; 570 G4double step, z; 570 G4double step, z; 571 G4bool singleScat; 571 G4bool singleScat; 572 /* 572 /* 573 G4cout << "Start of the loop x1(mm)= " << 573 G4cout << "Start of the loop x1(mm)= " << x1 << " x2(mm)= " << x2 574 << " 1-cost1= " << 1 - cosThetaMin << " SS 574 << " 1-cost1= " << 1 - cosThetaMin << " SSmode= " << singleScatteringMode 575 << " xtsec= " << xtsec << " Nst= " 575 << " xtsec= " << xtsec << " Nst= " << nMscSteps << G4endl; 576 */ 576 */ 577 do { 577 do { 578 578 579 //G4cout << "# x1(mm)= "<< x1<< " x2(mm)= 579 //G4cout << "# x1(mm)= "<< x1<< " x2(mm)= "<< x2 << G4endl; 580 // single scattering case 580 // single scattering case 581 if(singleScatteringMode && x1 > x2) { 581 if(singleScatteringMode && x1 > x2) { 582 fDisplacement += x2*mscfac*dir; 582 fDisplacement += x2*mscfac*dir; 583 break; 583 break; 584 } 584 } 585 585 586 // what is next single of multiple? 586 // what is next single of multiple? 587 if(x1 <= x2) { 587 if(x1 <= x2) { 588 step = x1; 588 step = x1; 589 singleScat = true; 589 singleScat = true; 590 } else { 590 } else { 591 step = x2; 591 step = x2; 592 singleScat = false; 592 singleScat = false; 593 } 593 } 594 594 595 //G4cout << "# step(mm)= "<< step<< " sin 595 //G4cout << "# step(mm)= "<< step<< " singlScat= "<< singleScat << G4endl; 596 596 597 // new position 597 // new position 598 fDisplacement += step*mscfac*dir; 598 fDisplacement += step*mscfac*dir; 599 599 600 if(singleScat) { 600 if(singleScat) { 601 601 602 // select element 602 // select element 603 std::size_t i = 0; << 603 G4int i = 0; 604 if(nelm > 1) { 604 if(nelm > 1) { 605 G4double qsec = rndmEngine->flat()*xts 605 G4double qsec = rndmEngine->flat()*xtsec; 606 for (; i<nelm; ++i) { if(xsecn[i] >= q 606 for (; i<nelm; ++i) { if(xsecn[i] >= qsec) { break; } } 607 } 607 } 608 G4double cosTetM = 608 G4double cosTetM = 609 wokvi->SetupTarget((*theElementVector) 609 wokvi->SetupTarget((*theElementVector)[i]->GetZasInt(), cut); 610 //G4cout << "!!! " << cosThetaMin << " 610 //G4cout << "!!! " << cosThetaMin << " " << cosTetM << " " 611 // << prob[i] << G4endl; 611 // << prob[i] << G4endl; 612 temp = wokvi->SampleSingleScattering(cos 612 temp = wokvi->SampleSingleScattering(cosThetaMin, cosTetM, prob[i]); 613 613 614 // direction is changed 614 // direction is changed 615 temp.rotateUz(dir); 615 temp.rotateUz(dir); 616 dir = temp; 616 dir = temp; 617 //G4cout << dir << G4endl; 617 //G4cout << dir << G4endl; 618 618 619 // new proposed step length 619 // new proposed step length 620 x2 -= step; 620 x2 -= step; 621 x1 = -G4Log(rndmEngine->flat())/xtsec; 621 x1 = -G4Log(rndmEngine->flat())/xtsec; 622 622 623 // multiple scattering 623 // multiple scattering 624 } else { 624 } else { 625 --nMscSteps; 625 --nMscSteps; 626 x1 -= step; 626 x1 -= step; 627 x2 = x0; 627 x2 = x0; 628 628 629 // sample z in interval 0 - 1 629 // sample z in interval 0 - 1 630 G4bool isFirst = true; 630 G4bool isFirst = true; 631 if(prob2 > 0.0 && rndmEngine->flat() < p 631 if(prob2 > 0.0 && rndmEngine->flat() < prob2) { isFirst = false; } 632 do { 632 do { >> 633 //z = -z0*G4Log(1.0 - (1.0 - zzz)*rndmEngine->flat()); 633 if(isFirst) { z = -G4Log(rndmEngine->f 634 if(isFirst) { z = -G4Log(rndmEngine->flat()); } 634 else { z = G4RandGamma::shoot(r 635 else { z = G4RandGamma::shoot(rndmEngine, 2.0, 2.0); } 635 z *= z0; 636 z *= z0; 636 // Loop checking, 03-Aug-2015, Vladimi 637 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko 637 } while(z > 1.0); 638 } while(z > 1.0); 638 639 639 cost = 1.0 - 2.0*z/*factCM*/; 640 cost = 1.0 - 2.0*z/*factCM*/; 640 if(cost > 1.0) { cost = 1.0; } 641 if(cost > 1.0) { cost = 1.0; } 641 else if(cost < -1.0) { cost =-1.0; } 642 else if(cost < -1.0) { cost =-1.0; } 642 sint = sqrt((1.0 - cost)*(1.0 + cost)); 643 sint = sqrt((1.0 - cost)*(1.0 + cost)); 643 phi = twopi*rndmEngine->flat(); 644 phi = twopi*rndmEngine->flat(); 644 G4double vx1 = sint*std::cos(phi); << 645 G4double vx1 = sint*cos(phi); 645 G4double vy1 = sint*std::sin(phi); << 646 G4double vy1 = sint*sin(phi); 646 647 647 // lateral displacement 648 // lateral displacement 648 if (latDisplasment) { 649 if (latDisplasment) { 649 G4double rms = z0 > 0.0 ? invsqrt12*st << 650 G4double rms = invsqrt12*sqrt(2*z0); 650 G4double r = x0*mscfac; 651 G4double r = x0*mscfac; 651 G4double dx = r*(0.5*vx1 + rms*G4RandG 652 G4double dx = r*(0.5*vx1 + rms*G4RandGauss::shoot(rndmEngine,0.0,1.0)); 652 G4double dy = r*(0.5*vy1 + rms*G4RandG 653 G4double dy = r*(0.5*vy1 + rms*G4RandGauss::shoot(rndmEngine,0.0,1.0)); 653 G4double d = r*r - dx*dx - dy*dy; 654 G4double d = r*r - dx*dx - dy*dy; 654 655 655 // change position 656 // change position 656 if(d >= 0.0) { 657 if(d >= 0.0) { 657 temp.set(dx, dy, std::sqrt(d) - r); << 658 temp.set(dx,dy,sqrt(d) - r); 658 temp.rotateUz(dir); 659 temp.rotateUz(dir); 659 fDisplacement += temp; 660 fDisplacement += temp; 660 } 661 } 661 } 662 } 662 // change direction 663 // change direction 663 temp.set(vx1,vy1,cost); 664 temp.set(vx1,vy1,cost); 664 temp.rotateUz(dir); 665 temp.rotateUz(dir); 665 dir = temp; 666 dir = temp; 666 } 667 } 667 // Loop checking, 03-Aug-2015, Vladimir Iv 668 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko 668 } while (0 < nMscSteps); 669 } while (0 < nMscSteps); 669 670 670 dir.rotateUz(oldDirection); 671 dir.rotateUz(oldDirection); 671 672 672 //G4cout<<"G4WentzelVIModel sampling is done 673 //G4cout<<"G4WentzelVIModel sampling is done 1-cost= "<< 1.-dir.z()<<G4endl; 673 // end of sampling ------------------------- 674 // end of sampling ------------------------------- 674 675 675 fParticleChange->ProposeMomentumDirection(di 676 fParticleChange->ProposeMomentumDirection(dir); 676 677 677 // lateral displacement 678 // lateral displacement 678 fDisplacement.rotateUz(oldDirection); 679 fDisplacement.rotateUz(oldDirection); 679 680 680 /* 681 /* 681 G4cout << " r(mm)= " << fDisplacement 682 G4cout << " r(mm)= " << fDisplacement.mag() 682 << " safety= " << safety 683 << " safety= " << safety 683 << " trueStep(mm)= " << tPathL 684 << " trueStep(mm)= " << tPathLength 684 << " geomStep(mm)= " << zPathL 685 << " geomStep(mm)= " << zPathLength 685 << " x= " << fDisplacement.x() 686 << " x= " << fDisplacement.x() 686 << " y= " << fDisplacement.y() 687 << " y= " << fDisplacement.y() 687 << " z= " << fDisplacement.z() 688 << " z= " << fDisplacement.z() 688 << G4endl; 689 << G4endl; 689 */ 690 */ 690 691 691 //G4cout<< "G4WentzelVIModel::SampleScatteri 692 //G4cout<< "G4WentzelVIModel::SampleScattering end NewDir= " << dir<< G4endl; 692 return fDisplacement; 693 return fDisplacement; 693 } 694 } 694 695 695 //....oooOO0OOooo........oooOO0OOooo........oo 696 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 696 697 697 G4double G4WentzelVIModel::ComputeTransportXSe 698 G4double G4WentzelVIModel::ComputeTransportXSectionPerVolume(G4double cosTheta) 698 { 699 { 699 // prepare recomputation of x-sections 700 // prepare recomputation of x-sections 700 const G4ElementVector* theElementVector = cu 701 const G4ElementVector* theElementVector = currentMaterial->GetElementVector(); 701 const G4double* theAtomNumDensityVector = 702 const G4double* theAtomNumDensityVector = 702 currentMaterial->GetVecNbOfAtomsPerVolume( 703 currentMaterial->GetVecNbOfAtomsPerVolume(); 703 G4int nelm = (G4int)currentMaterial->GetNumb << 704 G4int nelm = currentMaterial->GetNumberOfElements(); 704 if(nelm > nelments) { 705 if(nelm > nelments) { 705 nelments = nelm; 706 nelments = nelm; 706 xsecn.resize(nelm); 707 xsecn.resize(nelm); 707 prob.resize(nelm); 708 prob.resize(nelm); 708 } 709 } 709 710 710 // check consistency 711 // check consistency 711 xtsec = 0.0; 712 xtsec = 0.0; 712 if(cosTetMaxNuc >= cosTheta) { return 0.0; } 713 if(cosTetMaxNuc >= cosTheta) { return 0.0; } 713 714 714 G4double cut = (*currentCuts)[currentMateria 715 G4double cut = (*currentCuts)[currentMaterialIndex]; 715 if(fixedCut > 0.0) { cut = fixedCut; } 716 if(fixedCut > 0.0) { cut = fixedCut; } 716 717 717 // loop over elements 718 // loop over elements 718 G4double xs = 0.0; 719 G4double xs = 0.0; 719 for (G4int i=0; i<nelm; ++i) { 720 for (G4int i=0; i<nelm; ++i) { 720 G4double costm = 721 G4double costm = 721 wokvi->SetupTarget((*theElementVector)[i 722 wokvi->SetupTarget((*theElementVector)[i]->GetZasInt(), cut); 722 G4double density = theAtomNumDensityVector 723 G4double density = theAtomNumDensityVector[i]; 723 724 724 G4double esec = 0.0; 725 G4double esec = 0.0; 725 if(costm < cosTheta) { 726 if(costm < cosTheta) { 726 727 727 // recompute the transport x-section 728 // recompute the transport x-section 728 if(1.0 > cosTheta) { 729 if(1.0 > cosTheta) { 729 xs += density*wokvi->ComputeTransportC 730 xs += density*wokvi->ComputeTransportCrossSectionPerAtom(cosTheta); 730 } 731 } 731 // recompute the total x-section 732 // recompute the total x-section 732 G4double nucsec = wokvi->ComputeNuclearC 733 G4double nucsec = wokvi->ComputeNuclearCrossSection(cosTheta, costm); 733 esec = wokvi->ComputeElectronCrossSectio 734 esec = wokvi->ComputeElectronCrossSection(cosTheta, costm); 734 nucsec += esec; 735 nucsec += esec; 735 if(nucsec > 0.0) { esec /= nucsec; } 736 if(nucsec > 0.0) { esec /= nucsec; } 736 xtsec += nucsec*density; 737 xtsec += nucsec*density; 737 } 738 } 738 xsecn[i] = xtsec; 739 xsecn[i] = xtsec; 739 prob[i] = esec; 740 prob[i] = esec; 740 //G4cout << i << " xs= " << xs << " xtsec 741 //G4cout << i << " xs= " << xs << " xtsec= " << xtsec 741 // << " 1-cosTheta= " << 1-cosTheta 742 // << " 1-cosTheta= " << 1-cosTheta 742 // << " 1-cosTetMaxNuc2= " <<1-c 743 // << " 1-cosTetMaxNuc2= " <<1-cosTetMaxNuc2<< G4endl; 743 } 744 } 744 745 745 //G4cout << "ComputeXS result: xsec(1/mm)= 746 //G4cout << "ComputeXS result: xsec(1/mm)= " << xs 746 // << " txsec(1/mm)= " << xtsec <<G4 747 // << " txsec(1/mm)= " << xtsec <<G4endl; 747 return xs; 748 return xs; 748 } 749 } 749 750 750 //....oooOO0OOooo........oooOO0OOooo........oo 751 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 751 752 752 G4double G4WentzelVIModel::ComputeSecondMoment << 753 G4double G4WentzelVIModel:: ComputeSecondMoment(const G4ParticleDefinition* p, 753 G4double kinEnergy) << 754 G4double kinEnergy) 754 { 755 { 755 G4double xs = 0.0; 756 G4double xs = 0.0; 756 757 757 SetupParticle(p); 758 SetupParticle(p); 758 cosTetMaxNuc = wokvi->SetupKinematic(kinEner 759 cosTetMaxNuc = wokvi->SetupKinematic(kinEnergy, currentMaterial); 759 760 760 if(cosTetMaxNuc >= 1.0) { return xs; } 761 if(cosTetMaxNuc >= 1.0) { return xs; } 761 762 762 const G4ElementVector* theElementVector = cu 763 const G4ElementVector* theElementVector = currentMaterial->GetElementVector(); 763 const G4double* theAtomNumDensityVector = 764 const G4double* theAtomNumDensityVector = 764 currentMaterial->GetVecNbOfAtomsPerVolume( 765 currentMaterial->GetVecNbOfAtomsPerVolume(); 765 std::size_t nelm = currentMaterial->GetNumbe << 766 G4int nelm = currentMaterial->GetNumberOfElements(); 766 767 767 G4double cut = (*currentCuts)[currentMateria 768 G4double cut = (*currentCuts)[currentMaterialIndex]; 768 if(fixedCut > 0.0) { cut = fixedCut; } 769 if(fixedCut > 0.0) { cut = fixedCut; } 769 770 770 // loop over elements 771 // loop over elements 771 for (std::size_t i=0; i<nelm; ++i) { << 772 for (G4int i=0; i<nelm; ++i) { 772 G4double costm = 773 G4double costm = 773 wokvi->SetupTarget((*theElementVector)[i 774 wokvi->SetupTarget((*theElementVector)[i]->GetZasInt(), cut); 774 xs += theAtomNumDensityVector[i] 775 xs += theAtomNumDensityVector[i] 775 *wokvi->ComputeSecondTransportMoment(cos 776 *wokvi->ComputeSecondTransportMoment(costm); 776 } 777 } 777 return xs; 778 return xs; 778 } 779 } 779 780 780 //....oooOO0OOooo........oooOO0OOooo........oo 781 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 781 782 782 void G4WentzelVIModel::SetSingleScatteringFact 783 void G4WentzelVIModel::SetSingleScatteringFactor(G4double val) 783 { 784 { 784 if(val > 0.05) { 785 if(val > 0.05) { 785 ssFactor = val; 786 ssFactor = val; 786 invssFactor = 1.0/(val - 0.05); 787 invssFactor = 1.0/(val - 0.05); 787 } 788 } 788 } 789 } 789 790 790 //....oooOO0OOooo........oooOO0OOooo........oo 791 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 791 792