88 theIonEffChargeModel(0),
89 theNuclearStoppingModel(0),
90 theIonChuFluctuationModel(0),
91 theIonYangFluctuationModel(0),
92 protonTable(
"ICRU_R49p"),
93 antiprotonTable(
"ICRU_R49p"),
94 theNuclearTable(
"ICRU_R49"),
97 theMeanFreePathTable(0),
98 paramStepLimit (0.005),
99 pixeCrossSectionHandler(0)
106 void G4hImpactIonisation::InitializeMe()
112 protonLowEnergy = 1.*
keV ;
113 protonHighEnergy = 100.*
MeV ;
114 antiprotonLowEnergy = 25.*
keV ;
115 antiprotonHighEnergy = 2.*
MeV ;
116 minGammaEnergy = 100 *
eV;
117 minElectronEnergy = 250.*
eV;
123 eMaxPixe = 200. *
MeV;
125 G4String defaultPixeModel(
"ecpssr");
126 modelK = defaultPixeModel;
127 modelL = defaultPixeModel;
128 modelM = defaultPixeModel;
134 if (theMeanFreePathTable)
137 delete theMeanFreePathTable;
140 if (betheBlochModel)
delete betheBlochModel;
141 if (protonModel)
delete protonModel;
142 if (antiprotonModel)
delete antiprotonModel;
143 if (theNuclearStoppingModel)
delete theNuclearStoppingModel;
144 if (theIonEffChargeModel)
delete theIonEffChargeModel;
145 if (theIonChuFluctuationModel)
delete theIonChuFluctuationModel;
146 if (theIonYangFluctuationModel)
delete theIonYangFluctuationModel;
148 delete pixeCrossSectionHandler;
164 SetProtonElectronicStoppingPowerModel(dedxTable) ;
169 SetAntiProtonElectronicStoppingPowerModel(dedxTable) ;
175 void G4hImpactIonisation::InitializeParametrisation()
181 protonHighEnergy = std::min(protonHighEnergy,protonModel->
HighEnergyLimit(0, 0));
199 G4cout <<
"G4hImpactIonisation::BuildPhysicsTable for "
210 G4cout <<
" 0: " << (*pv)[0]->GetProcessName() <<
" " << (*pv)[0]
211 <<
" 1: " << (*pv)[1]->GetProcessName() <<
" " << (*pv)[1]
214 G4cout <<
"ionModel= " << theIonEffChargeModel
215 <<
" MFPtable= " << theMeanFreePathTable
216 <<
" iniMass= " << initialMass
242 InitializeParametrisation() ;
247 chargeSquare = charge*charge ;
256 for (
size_t j=0; j<numOfCouples; j++) {
268 tCut = std::max(tCut,excEnergy);
269 cutForDelta.push_back(tCut);
274 tCut = std::max(tCut,minGammaEnergy);
275 cutForGamma.push_back(tCut);
285 BuildLossTable(*proton) ;
296 BuildLossTable(*antiproton) ;
308 G4cout <<
"G4hImpactIonisation::BuildPhysicsTable: "
309 <<
"Loss table is built "
314 BuildLambdaTable(particleDef) ;
322 G4cout <<
"G4hImpactIonisation::BuildPhysicsTable: "
323 <<
"DEDX table will be built "
338 G4cout <<
"G4hImpactIonisation::BuildPhysicsTable: end for "
351 G4double lowEdgeEnergy , ionloss, ionlossBB, paramB ;
356 if (particleDef == *proton)
359 highEnergy = protonHighEnergy ;
365 highEnergy = antiprotonHighEnergy ;
383 for (
size_t j=0; j<numOfCouples; j++) {
394 if ( charge > 0.0 ) {
395 ionloss = ProtonParametrisedDEDX(couple,highEnergy) ;
397 ionloss = AntiProtonParametrisedDEDX(couple,highEnergy) ;
400 ionlossBB = betheBlochModel->
TheValue(&particleDef,material,highEnergy) ;
404 paramB = ionloss/ionlossBB - 1.0 ;
411 if ( lowEdgeEnergy < highEnergy ) {
413 if ( charge > 0.0 ) {
414 ionloss = ProtonParametrisedDEDX(couple,lowEdgeEnergy) ;
416 ionloss = AntiProtonParametrisedDEDX(couple,lowEdgeEnergy) ;
422 ionloss = betheBlochModel->
TheValue(proton,material,
427 ionloss *= (1.0 + paramB*highEnergy/lowEdgeEnergy) ;
432 G4cout <<
"E(MeV)= " << lowEdgeEnergy/
MeV
433 <<
" dE/dx(MeV/mm)= " << ionloss*
mm/
MeV
453 G4cout <<
"G4hImpactIonisation::BuildLambdaTable for "
460 chargeSquare = charge*charge ;
468 if (theMeanFreePathTable) {
470 delete theMeanFreePathTable;
477 for (
size_t j=0 ; j < numOfCouples; j++) {
504 for (
G4int iel=0; iel<numberOfElements; iel++ )
506 Z = (
G4int) (*theElementVector)[iel]->GetZ();
509 G4double microCross = MicroscopicCrossSection( particleDef,
514 sigma += theAtomicNumDensityVector[iel] * microCross ;
519 value = sigma<=0 ?
DBL_MAX : 1./sigma ;
524 theMeanFreePathTable->
insert(aVector);
547 G4double particleMass = initialMass;
551 G4double gamma = energy / particleMass;
552 G4double beta2 = 1. - 1. / (gamma * gamma);
558 if ( tMax > deltaCutInEnergy )
560 var = deltaCutInEnergy / tMax;
561 totalCrossSection = (1. -
var * (1. - beta2 * std::log(
var))) / deltaCutInEnergy ;
568 totalCrossSection += 0.5 * (tMax - deltaCutInEnergy) / (
energy*
energy);
571 else if (spin > 0.9 )
573 totalCrossSection += -std::log(
var) /
574 (3. * deltaCutInEnergy) + (tMax - deltaCutInEnergy) * ( (5. + 1. /
var)*0.25 / (
energy*
energy) -
575 beta2 / (tMax * deltaCutInEnergy) ) / 3. ;
583 return totalCrossSection ;
599 G4bool isOutRange =
false;
605 chargeSquare = theIonEffChargeModel->
TheValue(dynamicParticle, material);
614 meanFreePath = (((*theMeanFreePathTable)(couple->
GetIndex()))->
615 GetValue(kineticEnergy,isOutRange))/chargeSquare;
618 return meanFreePath ;
642 G4double tScaled = kineticEnergy*massRatio ;
647 highEnergy = protonHighEnergy ;
654 if (theBarkas && tScaled > highEnergy)
656 fBarkas = BarkasTerm(material,tScaled)*std::sqrt(chargeSquare)*chargeSquare
657 + BlochTerm(material,tScaled,chargeSquare);
663 highEnergy = antiprotonHighEnergy ;
668 if (theBarkas && tScaled > highEnergy)
670 fBarkas = -BarkasTerm(material,tScaled)*std::sqrt(chargeSquare)*chargeSquare
671 + BlochTerm(material,tScaled,chargeSquare);
686 fRangeNow /= (chargeSquare*massRatio) ;
687 dx /= (chargeSquare*massRatio) ;
689 stepLimit = fRangeNow ;
696 if (stepLimit > fRangeNow) stepLimit = fRangeNow;
699 if(tScaled > highEnergy )
704 if(stepLimit > fRangeNow - dx*0.9) stepLimit = fRangeNow - dx*0.9 ;
711 if (stepLimit > x) stepLimit =
x;
738 G4double tScaled = kineticEnergy * massRatio ;
746 eLoss = kineticEnergy ;
752 eLoss = stepLength * fdEdx ;
755 else if (stepLength >= fRangeNow )
757 eLoss = kineticEnergy ;
766 G4double rScaled = fRangeNow * massRatio * chargeSquare ;
767 G4double sScaled = stepLength * massRatio * chargeSquare ;
784 eLoss += fBarkas * stepLength;
790 eLoss = stepLength *fdEdx ;
792 if (nStopping && tScaled < protonHighEnergy)
794 nLoss = (theNuclearStoppingModel->
TheValue(particle, material)) * stepLength;
798 if (eLoss < 0.0) eLoss = 0.0;
800 finalT = kineticEnergy - eLoss - nLoss;
806 eLoss = ElectronicLossFluctuation(particle, couple, eLoss, stepLength) ;
807 if (eLoss < 0.0) eLoss = 0.0;
808 finalT = kineticEnergy - eLoss - nLoss;
823 eLoss = kineticEnergy-finalT;
840 if(kineticEnergy < protonLowEnergy) {
841 eLoss = (protonModel->
TheValue(proton, material, protonLowEnergy))
842 * std::sqrt(kineticEnergy/protonLowEnergy) ;
846 eLoss = protonModel->
TheValue(proton, material, kineticEnergy) ;
853 G4cout <<
"p E(MeV)= " << kineticEnergy/
MeV
854 <<
" dE/dx(MeV/mm)= " << eLoss*
mm/
MeV
855 <<
" for " << material->
GetName()
856 <<
" model: " << protonModel <<
G4endl;
859 if(eLoss < 0.0) eLoss = 0.0 ;
875 if(antiprotonModel->
IsInCharge(antiproton,material)) {
876 if(kineticEnergy < antiprotonLowEnergy) {
877 eLoss = antiprotonModel->
TheValue(antiproton,material,antiprotonLowEnergy)
878 * std::sqrt(kineticEnergy/antiprotonLowEnergy) ;
882 eLoss = antiprotonModel->
TheValue(antiproton,material,
888 if(kineticEnergy < protonLowEnergy) {
890 * std::sqrt(kineticEnergy/protonLowEnergy) ;
904 G4cout <<
"pbar E(MeV)= " << kineticEnergy/
MeV
905 <<
" dE/dx(MeV/mm)= " << eLoss*
mm/
MeV
906 <<
" for " << material->
GetName()
907 <<
" model: " << protonModel <<
G4endl;
910 if(eLoss < 0.0) eLoss = 0.0 ;
926 G4double excitationEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
928 G4double tau = kineticEnergy / particleMass ;
935 G4double beta2 = bg2/(gamma*gamma) ;
939 G4double deltaCut = std::max(deltaCutNow, excitationEnergy);
941 if ( deltaCut < tMax)
944 dLoss = ( beta2 * (x-1.) - std::log(
x) ) *
twopi_mc2_rcl2 * electronDensity / beta2 ;
968 G4double totalEnergy = kineticEnergy + mass ;
969 G4double pSquare = kineticEnergy *( totalEnergy + mass) ;
970 G4double eSquare = totalEnergy * totalEnergy;
971 G4double betaSquare = pSquare / eSquare;
974 G4double gamma = kineticEnergy / mass + 1.;
982 if (deltaCut >= tMax)
999 gRej = 1.0 - betaSquare *
x ;
1001 else if (0.5 == spin)
1003 gRej = (1. - betaSquare * x + 0.5 * x*x * rate) / (1. + 0.5 * rate) ;
1007 gRej = (1. - betaSquare *
x ) * (1. + x/(3.*xc)) +
1008 x*x * rate * (1. + 0.5*x/xc) / 3.0 /
1009 (1. + 1./(3.*xc) + rate *(1.+ 0.5/xc) / 3.);
1014 G4double deltaKineticEnergy = x * tMax;
1015 G4double deltaTotalMomentum = std::sqrt(deltaKineticEnergy *
1017 G4double totalMomentum = std::sqrt(pSquare) ;
1021 if ( cosTheta < -1. ) cosTheta = -1.;
1022 if ( cosTheta > 1. ) cosTheta = 1.;
1026 G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
1027 G4double dirX = sinTheta * std::cos(phi);
1028 G4double dirY = sinTheta * std::sin(phi);
1032 deltaDirection.
rotateUz(particleDirection);
1039 deltaDirection.
z());
1043 G4double finalKineticEnergy = kineticEnergy - deltaKineticEnergy;
1044 size_t totalNumber = 1;
1050 size_t nSecondaries = 0;
1051 std::vector<G4DynamicParticle*>* secondaryVector = 0;
1058 if (pixeCrossSectionHandler == 0)
1063 pixeCrossSectionHandler =
1112 if (finalKineticEnergy >= bindingEnergy)
1128 if (secondaryVector != 0)
1130 nSecondaries = secondaryVector->size();
1131 for (
size_t i = 0; i<nSecondaries; i++)
1149 if (e < finalKineticEnergy &&
1154 finalKineticEnergy -=
e;
1181 (*secondaryVector)[i] = 0;
1196 G4double finalPx = totalMomentum*particleDirection.
x() - deltaTotalMomentum*deltaDirection.
x();
1197 G4double finalPy = totalMomentum*particleDirection.
y() - deltaTotalMomentum*deltaDirection.
y();
1198 G4double finalPz = totalMomentum*particleDirection.
z() - deltaTotalMomentum*deltaDirection.
z();
1199 G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz) ;
1200 finalPx /= finalMomentum;
1201 finalPy /= finalMomentum;
1202 finalPz /= finalMomentum;
1208 eDeposit = finalKineticEnergy;
1209 finalKineticEnergy = 0.;
1211 particleDirection.
y(),
1212 particleDirection.
z());
1214 GetAtRestProcessVector()->size())
1237 if (secondaryVector != 0)
1239 for (
size_t l = 0; l < nSecondaries; l++)
1258 delete secondaryVector;
1280 if (tScaled > protonHighEnergy)
1286 dedx = ProtonParametrisedDEDX(couple,tScaled) ;
1291 if (tScaled > antiprotonHighEnergy)
1297 dedx = AntiProtonParametrisedDEDX(couple,tScaled) ;
1300 dedx *= theIonEffChargeModel->
TheValue(aParticle, material, kineticEnergy) ;
1315 static double FTable[47][2] = {
1366 if(0.5*
MeV > kinE) kinE = 0.5*
MeV ;
1368 G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;
1369 if(0.0 >= beta2)
return 0.0;
1374 const G4ElementVector* theElementVector = material->GetElementVector();
1375 G4int numberOfElements = material->GetNumberOfElements();
1377 for (
G4int i = 0; i<numberOfElements; i++) {
1380 ZMaterial = (*theElementVector)[i]->GetZ();
1382 G4double X = 137.0 * 137.0 * beta2 / ZMaterial;
1386 G4double EtaChi = Eta0Chi * ( 1.0 + 6.02*std::pow( ZMaterial,-1.19 ) );
1387 G4double W = ( EtaChi * std::pow( ZMaterial,1.0/6.0 ) ) / std::sqrt(X);
1388 G4double FunctionOfW = FTable[46][1]*FTable[46][0]/W ;
1390 for(
G4int j=0; j<47; j++) {
1392 if( W < FTable[j][0] ) {
1395 FunctionOfW = FTable[0][1] ;
1398 FunctionOfW = (FTable[j][1] - FTable[j-1][1]) * (W - FTable[j-1][0])
1399 / (FTable[j][0] - FTable[j-1][0])
1408 BTerm += FunctionOfW /( std::sqrt(ZMaterial * X) *
X);
1411 BTerm *=
twopi_mc2_rcl2 * (material->GetElectronDensity()) / beta2 ;
1430 G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;
1431 G4double y = cSquare / (137.0*137.0*beta2) ;
1437 eLoss = 1.0 / (1.0 +
y) ;
1440 for(
G4int i=2; de>eLoss*0.01; i++) {
1441 de = 1.0/( i * (i*i +
y)) ;
1446 (material->GetElectronDensity()) / beta2 ;
1453 G4double G4hImpactIonisation::ElectronicLossFluctuation(
1468 static const G4double kappa = 10. ;
1480 G4double deltaCutInKineticEnergyNow = cutForDelta[imaterial];
1483 if(meanLoss < minLoss)
return meanLoss ;
1486 G4double threshold = std::max(deltaCutInKineticEnergyNow,ipotFluct);
1496 if(tMax > threshold) tMax = threshold;
1500 if(meanLoss > kappa*tMax || tMax < kappa*ipotFluct )
1503 * electronDensity / beta2 ;
1506 if( beta2 > 3.0*theBohrBeta2*zeff || charge < 0.0) {
1507 siga = std::sqrt( siga * chargeSquare ) ;
1512 G4double chu = theIonChuFluctuationModel->TheValue(particle, material);
1513 G4double yang = theIonYangFluctuationModel->TheValue(particle, material);
1514 siga = std::sqrt( siga * (chargeSquare * chu + yang)) ;
1518 loss = G4RandGauss::shoot(meanLoss,siga);
1519 }
while (loss < 0. || loss > 2.0*meanLoss);
1524 static const G4double probLim = 0.01 ;
1525 static const G4double sumaLim = -std::log(probLim) ;
1532 G4double corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
1544 w1 = tMax/ipotFluct;
1547 C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
1549 a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
1550 a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
1551 a3 = rateFluct*meanLoss*(tMax-ipotFluct)/(ipotFluct*tMax*std::log(w1));
1552 if(a1 < 0.0) a1 = 0.0;
1553 if(a2 < 0.0) a2 = 0.0;
1554 if(a3 < 0.0) a3 = 0.0;
1565 if(tMax == ipotFluct)
1571 siga=std::sqrt(a3) ;
1572 p3 = std::max(0,
G4int(G4RandGauss::shoot(a3,siga)+0.5));
1585 tMax = tMax-ipotFluct+e0 ;
1586 a3 = meanLoss*(tMax-e0)/(tMax*e0*std::log(tMax/e0));
1590 siga=std::sqrt(a3) ;
1591 p3 = std::max(0,
int(G4RandGauss::shoot(a3,siga)+0.5));
1598 w = (tMax-e0)/tMax ;
1602 corrfac = dp3/
G4float(nmaxCont2) ;
1609 loss *= e0*corrfac ;
1619 siga=std::sqrt(a1) ;
1620 p1 = std::max(0,
G4int(G4RandGauss::shoot(a1,siga)+0.5));
1628 siga=std::sqrt(a2) ;
1629 p2 = std::max(0,
G4int(G4RandGauss::shoot(a2,siga)+0.5));
1634 loss = p1*e1Fluct+p2*e2Fluct;
1647 siga=std::sqrt(a3) ;
1648 p3 = std::max(0,
G4int(G4RandGauss::shoot(a3,siga)+0.5));
1661 rfac = dp3/(
G4float(nmaxCont2)+dp3);
1664 na = G4RandGauss::shoot(namean,sa);
1667 alfa = w1*
G4float(nmaxCont2+p3)/
1669 alfa1 = alfa*std::log(alfa)/(alfa-1.);
1670 ea = na*ipotFluct*alfa1;
1671 sea = ipotFluct*std::sqrt(na*(alfa-alfa1*alfa1));
1672 lossc += G4RandGauss::shoot(ea,sea);
1679 w2 = alfa*ipotFluct;
1695 minGammaEnergy = cut;
1702 minElectronEnergy = cut;
1716 G4String comments =
" Knock-on electron cross sections . ";
1717 comments +=
"\n Good description above the mean excitation energy.\n";
1718 comments +=
" Delta ray energy sampled from differential Xsection.";
1723 <<
" in " << TotBin <<
" bins."
1724 <<
"\n Electronic stopping power model is "
1726 <<
"\n from " << protonLowEnergy /
keV <<
" keV "
1727 <<
" to " << protonHighEnergy /
MeV <<
" MeV " <<
"." <<
G4endl ;
1728 G4cout <<
"\n Parametrisation model for antiprotons is "
1730 <<
"\n from " << antiprotonLowEnergy /
keV <<
" keV "
1731 <<
" to " << antiprotonHighEnergy /
MeV <<
" MeV " <<
"." <<
G4endl ;
1733 G4cout <<
" Parametrization of the Barkas effect is switched on."
1737 G4cout <<
" Nuclear stopping power model is " << theNuclearTable
1749 for (
size_t j=0 ; j < numOfCouples; j++) {
1756 if(excitationEnergy > deltaCutNow) {
1760 G4cout <<
" material min.delta energy(keV) " <<
G4endl;
1765 << std::setw(15) << excitationEnergy/
keV <<
G4endl;