102G4bool G4GoudsmitSaundersonTable::gIsInitialised =
false;
104std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions1;
105std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions2;
107std::vector<double> G4GoudsmitSaundersonTable::gMoliereBc;
108std::vector<double> G4GoudsmitSaundersonTable::gMoliereXc2;
112 fIsElectron = iselectron;
115 fLogDeltaLambda = 0.;
116 fInvLogDeltaLambda = 0.;
121 fLowEnergyLimit = 0.1*CLHEP::keV;
122 fHighEnergyLimit = 100.0*CLHEP::MeV;
124 fIsMottCorrection =
false;
125 fIsPWACorrection =
false;
126 fMottCorrection =
nullptr;
128 fNumSPCEbinPerDec = 3;
132 for (std::size_t i=0; i<gGSMSCAngularDistributions1.size(); ++i) {
133 if (gGSMSCAngularDistributions1[i]) {
134 delete [] gGSMSCAngularDistributions1[i]->fUValues;
135 delete [] gGSMSCAngularDistributions1[i]->fParamA;
136 delete [] gGSMSCAngularDistributions1[i]->fParamB;
137 delete gGSMSCAngularDistributions1[i];
140 gGSMSCAngularDistributions1.clear();
141 for (std::size_t i=0; i<gGSMSCAngularDistributions2.size(); ++i) {
142 if (gGSMSCAngularDistributions2[i]) {
143 delete [] gGSMSCAngularDistributions2[i]->fUValues;
144 delete [] gGSMSCAngularDistributions2[i]->fParamA;
145 delete [] gGSMSCAngularDistributions2[i]->fParamB;
146 delete gGSMSCAngularDistributions2[i];
149 gGSMSCAngularDistributions2.clear();
150 if (fMottCorrection) {
151 delete fMottCorrection;
152 fMottCorrection =
nullptr;
155 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
156 if (fSCPCPerMatCuts[imc]) {
157 fSCPCPerMatCuts[imc]->fVSCPC.clear();
158 delete fSCPCPerMatCuts[imc];
161 fSCPCPerMatCuts.clear();
163 gIsInitialised =
false;
167 fLowEnergyLimit = lownergylimit;
168 fHighEnergyLimit = highenergylimit;
171 fLogLambda0 = lLambdaMin;
172 fLogDeltaLambda = (lLambdaMax-lLambdaMin)/(gLAMBNUM-1.);
173 fInvLogDeltaLambda = 1./fLogDeltaLambda;
174 fInvDeltaQ1 = 1./((gQMAX1-gQMIN1)/(gQNUM1-1.));
175 fDeltaQ2 = (gQMAX2-gQMIN2)/(gQNUM2-1.);
176 fInvDeltaQ2 = 1./fDeltaQ2;
179 if (!gIsInitialised) {
182 gIsInitialised =
true;
184 InitMoliereMSCParams();
186 if (fIsMottCorrection) {
187 if (!fMottCorrection) {
190 fMottCorrection->Initialise();
194 if (fMottCorrection) {
228 if (rand0<(1.+lambdaval)*expn) {
232 if (cost<-1.0) cost = -1.0;
233 if (cost>1.0) cost = 1.0;
236 sint = std::sqrt(dum0*(2.0-dum0));
255 prob = cumprob = expn;
260 for (
G4int iel=1; iel<10; ++iel) {
269 cursint = dum0*(2.0-dum0);
273 if (cursint>1.0e-20) {
274 cursint = std::sqrt(cursint);
276 cost = cost*curcost-sint*cursint*std::cos(curphi);
277 sint = std::sqrt(std::max(0.0, (1.0-cost)*(1.0+cost)));
293 cost =
SampleCosTheta(lambdaval, qval, scra, lekin, beta2, matindx, gsDtr, mcekini, mcdelti, transfPar, isfirst);
295 if (cost<-1.0) cost = -1.0;
296 if (cost> 1.0) cost = 1.0;
299 sint = std::sqrt(dum0*(2.0-dum0));
317 if (fIsMottCorrection && *gsDtr) {
318 static const G4int nlooplim = 1000;
322 G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
326 val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
345 G4int indxl = rndm*ndatm1;
354 return 1.-(2.0*transfpar*sample)/(1.0-sample+transfpar);
368 G4int numQVal = gQNUM2;
384 invDelQ = fInvDeltaQ1;
388 if (lambdaval>=gLAMBMAX) {
389 lambdaval = gLAMBMAX-1.e-8;
390 lamIndx = gLAMBNUM-1;
396 pIndxH = (lLambda-fLogLambda0)*fInvLogDeltaLambda;
397 lamIndx = (
G4int)(pIndxH);
398 pIndxH = pIndxH-lamIndx;
406 pIndxH = (qval-minQVal)*invDelQ;
407 qIndx = (
G4int)(pIndxH);
408 pIndxH = pIndxH-qIndx;
414 G4int indx = lamIndx*numQVal+qIndx;
416 dtr = gGSMSCAngularDistributions1[indx];
418 dtr = gGSMSCAngularDistributions2[indx];
425 if (lambdaval>10.0) {
426 transfpar = 0.5*(-2.77164+lLambda*( 2.94874-lLambda*(0.1535754-lLambda*0.00552888) ));
428 transfpar = 0.5*(1.347+lLambda*(0.209364-lLambda*(0.45525-lLambda*(0.50142-lLambda*0.081234))));
430 transfpar *= (lambdaval+4.0)*scra;
440 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
442 "Environment variable G4LEDATA not defined");
446 gGSMSCAngularDistributions1.resize(gLAMBNUM*gQNUM1,
nullptr);
448 for (
G4int il=0; il<gLAMBNUM; ++il) {
449 G4String fname = str1 + std::to_string(il);
450 std::ifstream infile(fname,std::ios::in);
451 if (!infile.is_open()) {
452 G4String msgc =
"Cannot open file: " + fname;
453 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
457 for (
G4int iq=0; iq<gQNUM1; ++iq) {
459 infile >> gsd->fNumData;
460 gsd->fUValues =
new G4double[gsd->fNumData]();
461 gsd->fParamA =
new G4double[gsd->fNumData]();
462 gsd->fParamB =
new G4double[gsd->fNumData]();
464 infile >> ddummy; infile >> ddummy;
465 for (
G4int i=0; i<gsd->fNumData; ++i) {
466 infile >> gsd->fUValues[i];
467 infile >> gsd->fParamA[i];
468 infile >> gsd->fParamB[i];
470 gGSMSCAngularDistributions1[il*gQNUM1+iq] = gsd;
476 gGSMSCAngularDistributions2.resize(gLAMBNUM*gQNUM2,
nullptr);
478 for (
G4int il=0; il<gLAMBNUM; ++il) {
479 G4String fname = str2 + std::to_string(il);
480 std::ifstream infile(fname,std::ios::in);
481 if (!infile.is_open()) {
482 G4String msgc =
"Cannot open file: " + fname;
483 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
487 for (
G4int iq=0; iq<gQNUM2; ++iq) {
492 gsd->fNumData = numData;
493 gsd->fUValues =
new G4double[gsd->fNumData]();
494 gsd->fParamA =
new G4double[gsd->fNumData]();
495 gsd->fParamB =
new G4double[gsd->fNumData]();
497 infile >> ddummy; infile >> ddummy;
498 for (
G4int i=0; i<gsd->fNumData; ++i) {
499 infile >> gsd->fUValues[i];
500 infile >> gsd->fParamA[i];
501 infile >> gsd->fParamB[i];
503 gGSMSCAngularDistributions2[il*gQNUM2+iq] = gsd;
505 gGSMSCAngularDistributions2[il*gQNUM2+iq] =
nullptr;
519 G4double cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
521 if (fIsMottCorrection) {
522 static const G4int nlooplim = 1000;
528 G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost,
529 matindx, ekindx, deltindx);
533 cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
535 val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost, matindx,
546 if (fIsMottCorrection) {
547 fMottCorrection->GetMottCorrectionFactors(logekin, beta2, matindx, mcToScr, mcToQ1, mcToG2PerG1);
553void G4GoudsmitSaundersonTable::InitMoliereMSCParams() {
556 const G4double finstrc2 = 5.325135453E-5;
560 std::size_t numMaterials = theMaterialTable->size();
562 if(gMoliereBc.size()<numMaterials) {
563 gMoliereBc.resize(numMaterials);
564 gMoliereXc2.resize(numMaterials);
568 if (fIsMottCorrection || fIsPWACorrection) {
573 for (std::size_t imat=0; imat<numMaterials; ++imat) {
574 const G4Material* theMaterial = (*theMaterialTable)[imat];
586 for(
G4int ielem = 0; ielem < numelems; ielem++) {
587 G4double zet = (*theElemVect)[ielem]->GetZ();
591 G4double iwa = (*theElemVect)[ielem]->GetN();
592 G4double ipz = theNbAtomsPerVolVect[ielem]/theTotNbAtomsPerVol;
595 ze += dum*(-2.0/3.0)*
G4Log(zet);
596 zx += dum*
G4Log(1.0+3.34*finstrc2*zet*zet);
602 gMoliereXc2[theMaterial->
GetIndex()] = const2*density*zs/sa;
604 gMoliereBc[theMaterial->
GetIndex()] *= 1.0/CLHEP::cm;
605 gMoliereXc2[theMaterial->
GetIndex()] *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
614 if (!(fSCPCPerMatCuts[imc]->fIsUse) || ekin<=fSCPCPerMatCuts[imc]->fPrCut) {
619 G4double remaining = (lekin-fSCPCPerMatCuts[imc]->fLEmin)*fSCPCPerMatCuts[imc]->fILDel;
620 std::size_t lindx = (std::size_t)remaining;
622 std::size_t imax = fSCPCPerMatCuts[imc]->fVSCPC.size()-1;
624 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[imax];
626 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[lindx] + remaining*(fSCPCPerMatCuts[imc]->fVSCPC[lindx+1]-fSCPCPerMatCuts[imc]->fVSCPC[lindx]);
637 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
638 if (fSCPCPerMatCuts[imc]) {
639 fSCPCPerMatCuts[imc]->fVSCPC.clear();
640 delete fSCPCPerMatCuts[imc];
641 fSCPCPerMatCuts[imc] =
nullptr;
646 fSCPCPerMatCuts.resize(numMatCuts,
nullptr);
648 for (
G4int imc=0; imc<(
G4int)numMatCuts; ++imc) {
660 G4double min = std::max(limit,fLowEnergyLimit);
663 fSCPCPerMatCuts[imc] =
new SCPCorrection();
664 fSCPCPerMatCuts[imc]->fIsUse =
false;
665 fSCPCPerMatCuts[imc]->fPrCut = min;
668 G4int numEbins = fNumSPCEbinPerDec*
G4lrint(std::log10(max/min));
669 numEbins = std::max(numEbins,3);
672 fSCPCPerMatCuts[imc] =
new SCPCorrection();
673 fSCPCPerMatCuts[imc]->fVSCPC.resize(numEbins,1.0);
674 fSCPCPerMatCuts[imc]->fIsUse =
true;
675 fSCPCPerMatCuts[imc]->fPrCut = min;
676 fSCPCPerMatCuts[imc]->fLEmin = lmin;
677 fSCPCPerMatCuts[imc]->fILDel = 1./ldel;
678 for (
G4int ie=0; ie<numEbins; ++ie) {
683 G4double tau = ekin/CLHEP::electron_mass_c2;
684 G4double tauCut = ecut/CLHEP::electron_mass_c2;
691 G4double gm =
G4Log(0.5*tau/tauCut) + (1.+dum0*dum0)*
G4Log(2.*(tau-tauCut+2.)/(tau+4.))
692 - 0.25*(tau+2.)*( tau+2.+2.*(2.*tau+1.)/(dum1*dum1))*
693 G4Log((tau+4.)*(tau-tauCut)/tau/(tau-tauCut+2.))
694 + 0.5*(tau-2*tauCut)*(tau+2.)*(1./(tau-tauCut)-1./(dum1*dum1));
701 scpCorr = 1.-gm*z0/(z0*(z0+1.));
703 fSCPCPerMatCuts[imc]->fVSCPC[ie] = scpCorr;
std::vector< const G4Element * > G4ElementVector
const char * G4FindDataDir(const char *)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
std::vector< G4Material * > G4MaterialTable
G4double SampleGSSRCosTheta(const GSMSCAngularDtr *gsDrt, G4double transfpar)
G4double SampleCosTheta(G4double lambdaval, G4double qval, G4double scra, G4double lekin, G4double beta2, G4int matindx, GSMSCAngularDtr **gsDtr, G4int &mcekini, G4int &mcdelti, G4double &transfPar, G4bool isfirst)
G4double ComputeScatteringPowerCorrection(const G4MaterialCutsCouple *matcut, G4double ekin)
void GetMottCorrectionFactors(G4double logekin, G4double beta2, G4int matindx, G4double &mcToScr, G4double &mcToQ1, G4double &mcToG2PerG1)
G4double SingleScattering(G4double lambdaval, G4double scra, G4double lekin, G4double beta2, G4int matindx)
~G4GoudsmitSaundersonTable()
G4bool Sampling(G4double lambdaval, G4double qval, G4double scra, G4double &cost, G4double &sint, G4double lekin, G4double beta2, G4int matindx, GSMSCAngularDtr **gsDtr, G4int &mcekini, G4int &mcdelti, G4double &transfPar, G4bool isfirst)
G4GoudsmitSaundersonTable(G4bool iselectron)
GSMSCAngularDtr * GetGSAngularDtr(G4double scra, G4double &lambdaval, G4double &qval, G4double &transfpar)
G4double GetMoliereBc(G4int matindx)
void Initialise(G4double lownergylimit, G4double highenergylimit)
G4double GetMoliereXc2(G4int matindx)
G4double GetZeffective() const
const G4Material * GetMaterial() const
G4double GetDensity() const
const G4ElementVector * GetElementVector() const
G4double GetTotNbOfAtomsPerVolume() const
G4IonisParamMat * GetIonisation() const
size_t GetNumberOfElements() const
const G4double * GetVecNbOfAtomsPerVolume() const
static G4MaterialTable * GetMaterialTable()
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
const std::vector< G4double > * GetEnergyCutsVector(std::size_t pcIdx) const
static G4ProductionCutsTable * GetProductionCutsTable()