Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4WentzelVIModel.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// -------------------------------------------------------------------
28//
29// GEANT4 Class file
30//
31//
32// File name: G4WentzelVIModel
33//
34// Author: V.Ivanchenko
35//
36// Creation date: 09.04.2008 from G4MuMscModel
37//
38// Modifications:
39// 27-05-2010 V.Ivanchenko added G4WentzelOKandVIxSection class to
40// compute cross sections and sample scattering angle
41//
42//
43// Class Description:
44//
45// Implementation of the model of multiple scattering based on
46// G.Wentzel, Z. Phys. 40 (1927) 590.
47// H.W.Lewis, Phys Rev 78 (1950) 526.
48// J.M. Fernandez-Varea et al., NIM B73 (1993) 447.
49// L.Urban, CERN-OPEN-2006-077.
50
51// -------------------------------------------------------------------
52//
53
54//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
55//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
56
57#include "G4WentzelVIModel.hh"
59#include "G4SystemOfUnits.hh"
60#include "Randomize.hh"
63#include "G4ElementVector.hh"
65#include "G4EmParameters.hh"
66#include "G4Log.hh"
67#include "G4Exp.hh"
68
69//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
70
71using namespace std;
72
73const G4double invsqrt12 = 1./std::sqrt(12.);
74const G4double numlimit = 0.1;
76
78 : G4VMscModel(nam),
79 singleScatteringMode(false),
80 isCombined(comb),
81 useSecondMoment(false)
82{
83 tlimitminfix = 1.e-6*CLHEP::mm;
84 lowEnergyLimit = 1.0*CLHEP::eV;
87}
88
89//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
90
92{
93 delete wokvi;
94 if(IsMaster()) {
95 delete fSecondMoments;
96 fSecondMoments = nullptr;
97 }
98}
99
100//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
101
103 const G4DataVector& cuts)
104{
105 // reset parameters
106 SetupParticle(p);
108 currentRange = 0.0;
109
110 if(isCombined) {
112 if(tet <= 0.0) { cosThetaMax = 1.0; }
113 else if(tet < CLHEP::pi) { cosThetaMax = cos(tet); }
114 }
115 //G4cout << "G4WentzelVIModel::Initialise " << p->GetParticleName()
116 // << " " << this << " " << wokvi << G4endl;
117
119 /*
120 G4cout << "G4WentzelVIModel: " << particle->GetParticleName()
121 << " 1-cos(ThetaLimit)= " << 1 - cosThetaMax
122 << " SingScatFactor= " << ssFactor
123 << G4endl;
124 */
125 currentCuts = &cuts;
126
127 // set values of some data members
129
130 // Access to materials
131 const G4ProductionCutsTable* theCoupleTable =
133 G4int numOfCouples = (G4int)theCoupleTable->GetTableSize();
134 nelments = 0;
135 for(G4int i=0; i<numOfCouples; ++i) {
136 G4int nelm = (G4int)theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial()->GetNumberOfElements();
137 nelments = std::max(nelments, nelm);
138 }
139 xsecn.resize(nelments);
140 prob.resize(nelments);
141
142 // build second moment table only if transport table is build
144 if(useSecondMoment && IsMaster() && nullptr != table) {
145
146 //G4cout << "### G4WentzelVIModel::Initialise: build 2nd moment table "
147 // << table << G4endl;
150
151 G4bool splineFlag = true;
152 G4PhysicsVector* aVector = nullptr;
153 G4PhysicsVector* bVector = nullptr;
156 if(emin < emax) {
158 *G4lrint(std::log10(emax/emin));
159 if(n < 3) { n = 3; }
160
161 for(G4int i=0; i<numOfCouples; ++i) {
162
163 //G4cout<< "i= " << i << " Flag= " << fSecondMoments->GetFlag(i)
164 // << G4endl;
165 if(fSecondMoments->GetFlag(i)) {
166 DefineMaterial(theCoupleTable->GetMaterialCutsCouple(i));
167
168 delete (*fSecondMoments)[i];
169 if(nullptr == aVector) {
170 aVector = new G4PhysicsLogVector(emin, emax, n, splineFlag);
171 bVector = aVector;
172 } else {
173 bVector = new G4PhysicsVector(*aVector);
174 }
175 for(std::size_t j=0; j<n; ++j) {
176 G4double e = bVector->Energy(j);
177 bVector->PutValue(j, ComputeSecondMoment(p, e)*e*e);
178 }
179 if(splineFlag) { bVector->FillSecondDerivatives(); }
180 (*fSecondMoments)[i] = bVector;
181 }
182 }
183 }
184 //G4cout << *fSecondMoments << G4endl;
185 }
186}
187
188//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
189
191 G4VEmModel* masterModel)
192{
193 fSecondMoments = static_cast<G4WentzelVIModel*>(masterModel)
195}
196
197//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
198
200{
201 if(cup != currentCouple) {
202 currentCouple = cup;
203 SetCurrentCouple(cup);
206 }
207}
208
209//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
210
212 const G4ParticleDefinition* p,
213 G4double kinEnergy,
215 G4double cutEnergy, G4double)
216{
217 G4double cross = 0.0;
218 SetupParticle(p);
219 if(kinEnergy < lowEnergyLimit) { return cross; }
220 if(nullptr == CurrentCouple()) {
221 G4Exception("G4WentzelVIModel::ComputeCrossSectionPerAtom", "em0011",
222 FatalException, " G4MaterialCutsCouple is not defined");
223 return 0.0;
224 }
227 if(cosTetMaxNuc < 1.0) {
228 G4double cut = (0.0 < fixedCut) ? fixedCut : cutEnergy;
229 G4double cost = wokvi->SetupTarget(G4lrint(Z), cut);
231 /*
232 if(p->GetParticleName() == "e-")
233 G4cout << "G4WentzelVIModel::CS: Z= " << G4int(Z) << " e(MeV)= "<<kinEnergy
234 << " 1-cosN= " << 1 - cosTetMaxNuc << " cross(bn)= " << cross/barn
235 << " " << particle->GetParticleName() << G4endl;
236 */
237 }
238 return cross;
239}
240
241//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
242
244{
245 /*
246 G4cout << "G4WentzelVIModel::StartTracking " << track << " " << this << " "
247 << track->GetParticleDefinition()->GetParticleName()
248 << " workvi: " << wokvi << G4endl;
249 */
251}
252
253//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
254
256 const G4Track& track,
257 G4double& currentMinimalStep)
258{
259 G4double tlimit = currentMinimalStep;
260 const G4DynamicParticle* dp = track.GetDynamicParticle();
261 const G4StepPoint* sp = track.GetStep()->GetPreStepPoint();
262 G4StepStatus stepStatus = sp->GetStepStatus();
263 singleScatteringMode = false;
264
265 //G4cout << "G4WentzelVIModel::ComputeTruePathLengthLimit stepStatus= "
266 // << stepStatus << " " << track.GetDefinition()->GetParticleName()
267 // << G4endl;
268
269 // initialisation for each step, lambda may be computed from scratch
273 const G4double logPreKinEnergy = dp->GetLogKineticEnergy();
277
278 //G4cout << "lambdaeff= " << lambdaeff << " Range= " << currentRange
279 // << " tlimit= " << tlimit << " 1-cost= " << 1 - cosTetMaxNuc << G4endl;
280
281 // extra check for abnormal situation
282 // this check needed to run MSC with eIoni and eBrem inactivated
283 if(tlimit > currentRange) { tlimit = currentRange; }
284
285 // stop here if small range particle
286 if(tlimit < tlimitminfix) {
287 return ConvertTrueToGeom(tlimit, currentMinimalStep);
288 }
289
290 // pre step
291 G4double presafety = sp->GetSafety();
292 // far from geometry boundary
293 if(currentRange < presafety) {
294 return ConvertTrueToGeom(tlimit, currentMinimalStep);
295 }
296
297 // compute presafety again if presafety <= 0 and no boundary
298 // i.e. when it is needed for optimization purposes
299 if(stepStatus != fGeomBoundary && presafety < tlimitminfix) {
300 presafety = ComputeSafety(sp->GetPosition(), tlimit);
301 if(currentRange < presafety) {
302 return ConvertTrueToGeom(tlimit, currentMinimalStep);
303 }
304 }
305 /*
306 G4cout << "e(MeV)= " << preKinEnergy/MeV
307 << " " << particle->GetParticleName()
308 << " CurLimit(mm)= " << tlimit/mm <<" safety(mm)= " << presafety/mm
309 << " R(mm)= " <<currentRange/mm
310 << " L0(mm^-1)= " << lambdaeff*mm
311 << G4endl;
312 */
313 // natural limit for high energy
314 G4double rlimit = std::max(facrange*currentRange,
316
317 // low-energy e-
319 rlimit = std::min(rlimit, facsafety*presafety);
320 }
321
322 // cut correction
324 //G4cout << "rcut= " << rcut << " rlimit= " << rlimit << " presafety= "
325 // << presafety << " 1-cosThetaMax= " <<1-cosThetaMax
326 //<< " 1-cosTetMaxNuc= " << 1-cosTetMaxNuc << G4endl;
327 if(rcut > rlimit) { rlimit = std::min(rlimit, rcut*sqrt(rlimit/rcut)); }
328
329 tlimit = std::min(tlimit, rlimit);
330 tlimit = std::max(tlimit, tlimitminfix);
331
332 // step limit in infinite media
333 tlimit = std::min(tlimit, 50*currentMaterial->GetRadlen()/facgeom);
334
335 //compute geomlimit and force few steps within a volume
337 && stepStatus == fGeomBoundary) {
338
339 G4double geomlimit = ComputeGeomLimit(track, presafety, currentRange);
340 tlimit = std::min(tlimit, geomlimit/facgeom);
341 }
342 /*
343 G4cout << particle->GetParticleName() << " e= " << preKinEnergy
344 << " L0= " << lambdaeff << " R= " << currentRange
345 << " tlimit= " << tlimit
346 << " currentMinimalStep= " << currentMinimalStep << G4endl;
347 */
348 return ConvertTrueToGeom(tlimit, currentMinimalStep);
349}
350
351//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
352
354{
355 zPathLength = tPathLength = truelength;
356
357 // small step use only single scattering
358 cosThetaMin = 1.0;
360 //G4cout << "xtsec= " << xtsec << " Nav= "
361 // << zPathLength*xtsec << G4endl;
365
366 } else {
367 //G4cout << "ComputeGeomPathLength: tLength= " << tPathLength
368 // << " Leff= " << lambdaeff << G4endl;
369 // small step
372 zPathLength *= (1.0 - 0.5*tau + tau*tau/6.0);
373
374 // medium step
375 } else {
376 G4double e1 = 0.0;
379 }
380 effKinEnergy = 0.5*(e1 + preKinEnergy);
383 //G4cout << " tLength= "<< tPathLength<< " Leff= " << lambdaeff << G4endl;
387 }
388 }
389 }
390 //G4cout << "Comp.geom: zLength= "<<zPathLength<<" tLength= "
391 // << tPathLength<< " Leff= " << lambdaeff << G4endl;
392 return zPathLength;
393}
394
395//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
396
398{
399 // initialisation of single scattering x-section
400 /*
401 G4cout << "ComputeTrueStepLength: Step= " << geomStepLength
402 << " geomL= " << zPathLength
403 << " Lambda= " << lambdaeff
404 << " 1-cosThetaMaxNuc= " << 1 - cosTetMaxNuc << G4endl;
405 */
407 zPathLength = tPathLength = geomStepLength;
408
409 } else {
410
411 // step defined by transportation
412 // change both geom and true step lengths
413 if(geomStepLength < zPathLength) {
414
415 // single scattering
416 if(G4int(geomStepLength*xtsec) < minNCollisions) {
417 zPathLength = tPathLength = geomStepLength;
420
421 // multiple scattering
422 } else {
423 // small step
424 if(geomStepLength < numlimit*lambdaeff) {
425 G4double tau = geomStepLength/lambdaeff;
426 tPathLength = geomStepLength*(1.0 + 0.5*tau + tau*tau/3.0);
427
428 // energy correction for a big step
429 } else {
430 tPathLength *= geomStepLength/zPathLength;
431 G4double e1 = 0.0;
434 }
435 effKinEnergy = 0.5*(e1 + preKinEnergy);
438 G4double tau = geomStepLength/lambdaeff;
439
440 if(tau < 0.999999) { tPathLength = -lambdaeff*G4Log(1.0 - tau); }
441 else { tPathLength = currentRange; }
442 }
443 zPathLength = geomStepLength;
444 }
445 }
446 }
447 // check of step length
448 // define threshold angle between single and multiple scattering
451 xtsec = 0.0;
452
453 // recompute transport cross section - do not change energy
454 // anymore - cannot be applied for big steps
456 // new computation
458 //G4cout << "%%%% cross= " << cross << " xtsec= " << xtsec
459 // << " 1-cosTMin= " << 1.0 - cosThetaMin << G4endl;
460 if(cross <= 0.0) {
464 cosThetaMin = 1.0;
465 } else if(xtsec > 0.0) {
466
467 lambdaeff = 1./cross;
468 G4double tau = zPathLength*cross;
469 if(tau < numlimit) {
470 tPathLength = zPathLength*(1.0 + 0.5*tau + tau*tau/3.0);
471 } else if(tau < 0.999999) {
472 tPathLength = -lambdaeff*G4Log(1.0 - tau);
473 } else {
475 }
476 }
477 }
478 }
480 /*
481 G4cout <<"Comp.true: zLength= "<<zPathLength<<" tLength= "<<tPathLength
482 <<" Leff(mm)= "<<lambdaeff/mm<<" sig0(1/mm)= " << xtsec <<G4endl;
483 G4cout << particle->GetParticleName() << " 1-cosThetaMin= " << 1-cosThetaMin
484 << " 1-cosTetMaxNuc= " << 1-cosTetMaxNuc
485 << " e(MeV)= " << preKinEnergy/MeV << " "
486 << " SSmode= " << singleScatteringMode << G4endl;
487 */
488 return tPathLength;
489}
490
491//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
492
495 G4double /*safety*/)
496{
497 fDisplacement.set(0.0,0.0,0.0);
498 //G4cout << "!##! G4WentzelVIModel::SampleScattering for "
499 // << particle->GetParticleName() << G4endl;
500
501 // ignore scattering for zero step length and energy below the limit
503 { return fDisplacement; }
504
505 G4double invlambda = 0.0;
506 if(lambdaeff < DBL_MAX) { invlambda = 0.5/lambdaeff; }
507
508 // use average kinetic energy over the step
509 G4double cut = (*currentCuts)[currentMaterialIndex];
510 if(fixedCut > 0.0) { cut = fixedCut; }
511 /*
512 G4cout <<"SampleScat: E0(MeV)= "<< preKinEnergy/MeV
513 << " Leff= " << lambdaeff <<" sig0(1/mm)= " << xtsec
514 << " xmsc= " << tPathLength*invlambda
515 << " safety= " << safety << G4endl;
516 */
517 // step limit due msc
518 G4int nMscSteps = 1;
520 G4double z0 = x0*invlambda;
521 //G4double zzz = 0.0;
522 G4double prob2 = 0.0;
523
524 CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
525
526 // large scattering angle case - two step approach
528 static const G4double zzmin = 0.05;
529 if(useSecondMoment) {
530 G4double z1 = invlambda*invlambda;
532 prob2 = (z2 - z1)/(1.5*z1 - z2);
533 }
534 // if(z0 > zzmin && safety > tlimitminfix) {
535 if(z0 > zzmin) {
536 x0 *= 0.5;
537 z0 *= 0.5;
538 nMscSteps = 2;
539 }
540 //if(z0 > zzmin) { zzz = G4Exp(-1.0/z0); }
541 G4double zzz = 0.0;
542 if(z0 > zzmin) {
543 zzz = G4Exp(-1.0/z0);
544 z0 += zzz;
545 prob2 *= (1 + zzz);
546 }
547 prob2 /= (1 + prob2);
548 }
549
550 // step limit due to single scattering
551 G4double x1 = 2*tPathLength;
552 if(0.0 < xtsec) { x1 = -G4Log(rndmEngine->flat())/xtsec; }
553
554 // no scattering case
556 { return fDisplacement; }
557
558 const G4ElementVector* theElementVector =
560 std::size_t nelm = currentMaterial->GetNumberOfElements();
561
562 // geometry
563 G4double sint, cost, phi;
564 G4ThreeVector temp(0.0,0.0,1.0);
565
566 // current position and direction relative to the end point
567 // because of magnetic field geometry is computed relatively to the
568 // end point of the step
569 G4ThreeVector dir(0.0,0.0,1.0);
570 fDisplacement.set(0.0,0.0,-zPathLength);
571
573
574 // start a loop
575 G4double x2 = x0;
576 G4double step, z;
577 G4bool singleScat;
578 /*
579 G4cout << "Start of the loop x1(mm)= " << x1 << " x2(mm)= " << x2
580 << " 1-cost1= " << 1 - cosThetaMin << " SSmode= " << singleScatteringMode
581 << " xtsec= " << xtsec << " Nst= " << nMscSteps << G4endl;
582 */
583 do {
584
585 //G4cout << "# x1(mm)= "<< x1<< " x2(mm)= "<< x2 << G4endl;
586 // single scattering case
587 if(singleScatteringMode && x1 > x2) {
588 fDisplacement += x2*mscfac*dir;
589 break;
590 }
591
592 // what is next single of multiple?
593 if(x1 <= x2) {
594 step = x1;
595 singleScat = true;
596 } else {
597 step = x2;
598 singleScat = false;
599 }
600
601 //G4cout << "# step(mm)= "<< step<< " singlScat= "<< singleScat << G4endl;
602
603 // new position
604 fDisplacement += step*mscfac*dir;
605
606 if(singleScat) {
607
608 // select element
609 std::size_t i = 0;
610 if(nelm > 1) {
611 G4double qsec = rndmEngine->flat()*xtsec;
612 for (; i<nelm; ++i) { if(xsecn[i] >= qsec) { break; } }
613 }
614 G4double cosTetM =
615 wokvi->SetupTarget((*theElementVector)[i]->GetZasInt(), cut);
616 //G4cout << "!!! " << cosThetaMin << " " << cosTetM << " "
617 // << prob[i] << G4endl;
618 temp = wokvi->SampleSingleScattering(cosThetaMin, cosTetM, prob[i]);
619
620 // direction is changed
621 temp.rotateUz(dir);
622 dir = temp;
623 //G4cout << dir << G4endl;
624
625 // new proposed step length
626 x2 -= step;
627 x1 = -G4Log(rndmEngine->flat())/xtsec;
628
629 // multiple scattering
630 } else {
631 --nMscSteps;
632 x1 -= step;
633 x2 = x0;
634
635 // sample z in interval 0 - 1
636 G4bool isFirst = true;
637 if(prob2 > 0.0 && rndmEngine->flat() < prob2) { isFirst = false; }
638 do {
639 //z = -z0*G4Log(1.0 - (1.0 - zzz)*rndmEngine->flat());
640 if(isFirst) { z = -G4Log(rndmEngine->flat()); }
641 else { z = G4RandGamma::shoot(rndmEngine, 2.0, 2.0); }
642 z *= z0;
643 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
644 } while(z > 1.0);
645
646 cost = 1.0 - 2.0*z/*factCM*/;
647 if(cost > 1.0) { cost = 1.0; }
648 else if(cost < -1.0) { cost =-1.0; }
649 sint = sqrt((1.0 - cost)*(1.0 + cost));
650 phi = twopi*rndmEngine->flat();
651 G4double vx1 = sint*cos(phi);
652 G4double vy1 = sint*sin(phi);
653
654 // lateral displacement
655 if (latDisplasment) {
656 G4double rms = invsqrt12*sqrt(2*z0);
657 G4double r = x0*mscfac;
658 G4double dx = r*(0.5*vx1 + rms*G4RandGauss::shoot(rndmEngine,0.0,1.0));
659 G4double dy = r*(0.5*vy1 + rms*G4RandGauss::shoot(rndmEngine,0.0,1.0));
660 G4double d = r*r - dx*dx - dy*dy;
661
662 // change position
663 if(d >= 0.0) {
664 temp.set(dx,dy,sqrt(d) - r);
665 temp.rotateUz(dir);
666 fDisplacement += temp;
667 }
668 }
669 // change direction
670 temp.set(vx1,vy1,cost);
671 temp.rotateUz(dir);
672 dir = temp;
673 }
674 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
675 } while (0 < nMscSteps);
676
677 dir.rotateUz(oldDirection);
678
679 //G4cout<<"G4WentzelVIModel sampling is done 1-cost= "<< 1.-dir.z()<<G4endl;
680 // end of sampling -------------------------------
681
683
684 // lateral displacement
685 fDisplacement.rotateUz(oldDirection);
686
687 /*
688 G4cout << " r(mm)= " << fDisplacement.mag()
689 << " safety= " << safety
690 << " trueStep(mm)= " << tPathLength
691 << " geomStep(mm)= " << zPathLength
692 << " x= " << fDisplacement.x()
693 << " y= " << fDisplacement.y()
694 << " z= " << fDisplacement.z()
695 << G4endl;
696 */
697
698 //G4cout<< "G4WentzelVIModel::SampleScattering end NewDir= " << dir<< G4endl;
699 return fDisplacement;
700}
701
702//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
703
705{
706 // prepare recomputation of x-sections
707 const G4ElementVector* theElementVector = currentMaterial->GetElementVector();
708 const G4double* theAtomNumDensityVector =
711 if(nelm > nelments) {
712 nelments = nelm;
713 xsecn.resize(nelm);
714 prob.resize(nelm);
715 }
716
717 // check consistency
718 xtsec = 0.0;
719 if(cosTetMaxNuc >= cosTheta) { return 0.0; }
720
721 G4double cut = (*currentCuts)[currentMaterialIndex];
722 if(fixedCut > 0.0) { cut = fixedCut; }
723
724 // loop over elements
725 G4double xs = 0.0;
726 for (G4int i=0; i<nelm; ++i) {
727 G4double costm =
728 wokvi->SetupTarget((*theElementVector)[i]->GetZasInt(), cut);
729 G4double density = theAtomNumDensityVector[i];
730
731 G4double esec = 0.0;
732 if(costm < cosTheta) {
733
734 // recompute the transport x-section
735 if(1.0 > cosTheta) {
736 xs += density*wokvi->ComputeTransportCrossSectionPerAtom(cosTheta);
737 }
738 // recompute the total x-section
739 G4double nucsec = wokvi->ComputeNuclearCrossSection(cosTheta, costm);
740 esec = wokvi->ComputeElectronCrossSection(cosTheta, costm);
741 nucsec += esec;
742 if(nucsec > 0.0) { esec /= nucsec; }
743 xtsec += nucsec*density;
744 }
745 xsecn[i] = xtsec;
746 prob[i] = esec;
747 //G4cout << i << " xs= " << xs << " xtsec= " << xtsec
748 // << " 1-cosTheta= " << 1-cosTheta
749 // << " 1-cosTetMaxNuc2= " <<1-cosTetMaxNuc2<< G4endl;
750 }
751
752 //G4cout << "ComputeXS result: xsec(1/mm)= " << xs
753 // << " txsec(1/mm)= " << xtsec <<G4endl;
754 return xs;
755}
756
757//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
758
759G4double G4WentzelVIModel::ComputeSecondMoment(const G4ParticleDefinition* p,
760 G4double kinEnergy)
761{
762 G4double xs = 0.0;
763
764 SetupParticle(p);
766
767 if(cosTetMaxNuc >= 1.0) { return xs; }
768
769 const G4ElementVector* theElementVector = currentMaterial->GetElementVector();
770 const G4double* theAtomNumDensityVector =
772 std::size_t nelm = currentMaterial->GetNumberOfElements();
773
774 G4double cut = (*currentCuts)[currentMaterialIndex];
775 if(fixedCut > 0.0) { cut = fixedCut; }
776
777 // loop over elements
778 for (std::size_t i=0; i<nelm; ++i) {
779 G4double costm =
780 wokvi->SetupTarget((*theElementVector)[i]->GetZasInt(), cut);
781 xs += theAtomNumDensityVector[i]
783 }
784 return xs;
785}
786
787//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
788
790{
791 if(val > 0.05) {
792 ssFactor = val;
793 invssFactor = 1.0/(val - 0.05);
794 }
795}
796
797//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
std::vector< const G4Element * > G4ElementVector
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
@ fUseDistanceToBoundary
G4StepStatus
Definition: G4StepStatus.hh:40
@ fGeomBoundary
Definition: G4StepStatus.hh:43
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
const G4double numlimit
const G4double invsqrt12
const G4double numlimit
const G4int minNCollisions
void set(double x, double y, double z)
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
virtual double flat()=0
G4double GetLogKineticEnergy() const
G4double GetKineticEnergy() const
static G4EmParameters * Instance()
G4int NumberOfBinsPerDecade() const
const G4Material * GetMaterial() const
G4ProductionCuts * GetProductionCuts() const
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:185
size_t GetNumberOfElements() const
Definition: G4Material.hh:181
G4double GetRadlen() const
Definition: G4Material.hh:215
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:201
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
static G4PhysicsTable * PreparePhysicsTable(G4PhysicsTable *physTable)
G4bool GetFlag(std::size_t i) const
void PutValue(const std::size_t index, const G4double value)
G4double Energy(const std::size_t index) const
void FillSecondDerivatives(const G4SplineType=G4SplineType::Base, const G4double dir1=0.0, const G4double dir2=0.0)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
G4double GetProductionCut(G4int index) const
G4StepPoint * GetPreStepPoint() const
const G4ParticleDefinition * GetParticleDefinition() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const G4Step * GetStep() const
G4double PolarAngleLimit() const
Definition: G4VEmModel.hh:662
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:641
G4bool IsMaster() const
Definition: G4VEmModel.hh:725
void SetCurrentCouple(const G4MaterialCutsCouple *)
Definition: G4VEmModel.hh:468
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:634
G4double HighEnergyActivationLimit() const
Definition: G4VEmModel.hh:648
const G4MaterialCutsCouple * CurrentCouple() const
Definition: G4VEmModel.hh:486
G4PhysicsTable * GetCrossSectionTable()
Definition: G4VEmModel.hh:849
G4double LowEnergyActivationLimit() const
Definition: G4VEmModel.hh:655
G4double facrange
Definition: G4VMscModel.hh:199
G4double ComputeGeomLimit(const G4Track &, G4double &presafety, G4double limit)
Definition: G4VMscModel.hh:296
G4double GetTransportMeanFreePath(const G4ParticleDefinition *part, G4double kinEnergy)
Definition: G4VMscModel.hh:325
G4ParticleChangeForMSC * GetParticleChangeForMSC(const G4ParticleDefinition *p=nullptr)
Definition: G4VMscModel.cc:77
G4double GetEnergy(const G4ParticleDefinition *part, G4double range, const G4MaterialCutsCouple *couple)
Definition: G4VMscModel.cc:223
G4double GetRange(const G4ParticleDefinition *part, G4double kineticEnergy, const G4MaterialCutsCouple *couple)
Definition: G4VMscModel.cc:188
G4MscStepLimitType steppingAlgorithm
Definition: G4VMscModel.hh:209
G4double ConvertTrueToGeom(G4double &tLength, G4double &gLength)
Definition: G4VMscModel.hh:286
G4bool latDisplasment
Definition: G4VMscModel.hh:212
G4double ComputeSafety(const G4ThreeVector &position, G4double limit=DBL_MAX)
Definition: G4VMscModel.hh:278
G4double facsafety
Definition: G4VMscModel.hh:201
G4ThreeVector fDisplacement
Definition: G4VMscModel.hh:208
void InitialiseParameters(const G4ParticleDefinition *)
Definition: G4VMscModel.cc:115
G4double facgeom
Definition: G4VMscModel.hh:200
G4double SetupTarget(G4int Z, G4double cut)
G4double ComputeElectronCrossSection(G4double CosThetaMin, G4double CosThetaMax)
G4double ComputeSecondTransportMoment(G4double CosThetaMax)
void Initialise(const G4ParticleDefinition *, G4double CosThetaLim)
G4double ComputeTransportCrossSectionPerAtom(G4double CosThetaMax)
virtual G4double SetupKinematic(G4double kinEnergy, const G4Material *mat)
G4double ComputeNuclearCrossSection(G4double CosThetaMin, G4double CosThetaMax)
G4ThreeVector & SampleSingleScattering(G4double CosThetaMin, G4double CosThetaMax, G4double elecRatio)
G4ThreeVector & SampleScattering(const G4ThreeVector &, G4double safety) override
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double KineticEnergy, G4double AtomicNumber, G4double AtomicWeight=0., G4double cut=DBL_MAX, G4double emax=DBL_MAX) override
G4double ComputeTransportXSectionPerVolume(G4double cosTheta)
const G4MaterialCutsCouple * currentCouple
G4double ComputeTruePathLengthLimit(const G4Track &track, G4double &currentMinimalStep) override
G4PhysicsTable * GetSecondMomentTable()
std::vector< G4double > prob
G4double SecondMoment(const G4ParticleDefinition *, const G4MaterialCutsCouple *, G4double kineticEnergy)
~G4WentzelVIModel() override
G4WentzelVIModel(G4bool comb=true, const G4String &nam="WentzelVIUni")
void DefineMaterial(const G4MaterialCutsCouple *)
G4double ComputeTrueStepLength(G4double geomStepLength) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
G4PhysicsTable * fSecondMoments
std::vector< G4double > xsecn
G4double ComputeGeomPathLength(G4double truePathLength) override
G4ParticleChangeForMSC * fParticleChange
const G4ParticleDefinition * particle
const G4DataVector * currentCuts
const G4Material * currentMaterial
void SetupParticle(const G4ParticleDefinition *)
void StartTracking(G4Track *) override
void SetSingleScatteringFactor(G4double)
G4WentzelOKandVIxSection * wokvi
int G4lrint(double ad)
Definition: templates.hh:134
#define DBL_MAX
Definition: templates.hh:62