103G4bool G4GoudsmitSaundersonTable::gIsInitialised =
false;
105std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions1;
106std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions2;
108std::vector<double> G4GoudsmitSaundersonTable::gMoliereBc;
109std::vector<double> G4GoudsmitSaundersonTable::gMoliereXc2;
113 fIsElectron = iselectron;
116 fLogDeltaLambda = 0.;
117 fInvLogDeltaLambda = 0.;
122 fLowEnergyLimit = 0.1*CLHEP::keV;
123 fHighEnergyLimit = 100.0*CLHEP::MeV;
125 fIsMottCorrection =
false;
126 fIsPWACorrection =
false;
127 fMottCorrection =
nullptr;
129 fNumSPCEbinPerDec = 3;
133 for (std::size_t i=0; i<gGSMSCAngularDistributions1.size(); ++i) {
134 if (gGSMSCAngularDistributions1[i]) {
135 delete [] gGSMSCAngularDistributions1[i]->fUValues;
136 delete [] gGSMSCAngularDistributions1[i]->fParamA;
137 delete [] gGSMSCAngularDistributions1[i]->fParamB;
138 delete gGSMSCAngularDistributions1[i];
141 gGSMSCAngularDistributions1.clear();
142 for (std::size_t i=0; i<gGSMSCAngularDistributions2.size(); ++i) {
143 if (gGSMSCAngularDistributions2[i]) {
144 delete [] gGSMSCAngularDistributions2[i]->fUValues;
145 delete [] gGSMSCAngularDistributions2[i]->fParamA;
146 delete [] gGSMSCAngularDistributions2[i]->fParamB;
147 delete gGSMSCAngularDistributions2[i];
150 gGSMSCAngularDistributions2.clear();
151 if (fMottCorrection) {
152 delete fMottCorrection;
153 fMottCorrection =
nullptr;
156 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
157 if (fSCPCPerMatCuts[imc]) {
158 fSCPCPerMatCuts[imc]->fVSCPC.clear();
159 delete fSCPCPerMatCuts[imc];
162 fSCPCPerMatCuts.clear();
164 gIsInitialised =
false;
168 fLowEnergyLimit = lownergylimit;
169 fHighEnergyLimit = highenergylimit;
172 fLogLambda0 = lLambdaMin;
173 fLogDeltaLambda = (lLambdaMax-lLambdaMin)/(gLAMBNUM-1.);
174 fInvLogDeltaLambda = 1./fLogDeltaLambda;
175 fInvDeltaQ1 = 1./((gQMAX1-gQMIN1)/(gQNUM1-1.));
176 fDeltaQ2 = (gQMAX2-gQMIN2)/(gQNUM2-1.);
177 fInvDeltaQ2 = 1./fDeltaQ2;
180 if (!gIsInitialised) {
183 gIsInitialised =
true;
185 InitMoliereMSCParams();
187 if (fIsMottCorrection) {
188 if (!fMottCorrection) {
191 fMottCorrection->Initialise();
195 if (fMottCorrection) {
229 if (rand0<(1.+lambdaval)*expn) {
233 if (cost<-1.0) cost = -1.0;
234 if (cost>1.0) cost = 1.0;
237 sint = std::sqrt(dum0*(2.0-dum0));
256 prob = cumprob = expn;
261 for (
G4int iel=1; iel<10; ++iel) {
270 cursint = dum0*(2.0-dum0);
274 if (cursint>1.0e-20) {
275 cursint = std::sqrt(cursint);
277 cost = cost*curcost-sint*cursint*std::cos(curphi);
278 sint = std::sqrt(std::max(0.0, (1.0-cost)*(1.0+cost)));
294 cost =
SampleCosTheta(lambdaval, qval, scra, lekin, beta2, matindx, gsDtr, mcekini, mcdelti, transfPar, isfirst);
296 if (cost<-1.0) cost = -1.0;
297 if (cost> 1.0) cost = 1.0;
300 sint = std::sqrt(dum0*(2.0-dum0));
318 if (fIsMottCorrection && *gsDtr) {
319 static const G4int nlooplim = 1000;
323 G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
327 val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
346 G4int indxl = rndm*ndatm1;
355 return 1.-(2.0*transfpar*sample)/(1.0-sample+transfpar);
369 G4int numQVal = gQNUM2;
385 invDelQ = fInvDeltaQ1;
389 if (lambdaval>=gLAMBMAX) {
390 lambdaval = gLAMBMAX-1.e-8;
391 lamIndx = gLAMBNUM-1;
397 pIndxH = (lLambda-fLogLambda0)*fInvLogDeltaLambda;
398 lamIndx = (
G4int)(pIndxH);
399 pIndxH = pIndxH-lamIndx;
407 pIndxH = (qval-minQVal)*invDelQ;
408 qIndx = (
G4int)(pIndxH);
409 pIndxH = pIndxH-qIndx;
415 G4int indx = lamIndx*numQVal+qIndx;
417 dtr = gGSMSCAngularDistributions1[indx];
419 dtr = gGSMSCAngularDistributions2[indx];
426 if (lambdaval>10.0) {
427 transfpar = 0.5*(-2.77164+lLambda*( 2.94874-lLambda*(0.1535754-lLambda*0.00552888) ));
429 transfpar = 0.5*(1.347+lLambda*(0.209364-lLambda*(0.45525-lLambda*(0.50142-lLambda*0.081234))));
431 transfpar *= (lambdaval+4.0)*scra;
439 gGSMSCAngularDistributions1.resize(gLAMBNUM*gQNUM1,
nullptr);
441 for (
G4int il=0; il<gLAMBNUM; ++il) {
442 G4String fname = str1 + std::to_string(il);
443 std::ifstream infile(fname,std::ios::in);
444 if (!infile.is_open()) {
445 G4String msgc =
"Cannot open file: " + fname;
446 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
450 for (
G4int iq=0; iq<gQNUM1; ++iq) {
452 infile >> gsd->fNumData;
453 gsd->fUValues =
new G4double[gsd->fNumData]();
454 gsd->fParamA =
new G4double[gsd->fNumData]();
455 gsd->fParamB =
new G4double[gsd->fNumData]();
457 infile >> ddummy; infile >> ddummy;
458 for (
G4int i=0; i<gsd->fNumData; ++i) {
459 infile >> gsd->fUValues[i];
460 infile >> gsd->fParamA[i];
461 infile >> gsd->fParamB[i];
463 gGSMSCAngularDistributions1[il*gQNUM1+iq] = gsd;
469 gGSMSCAngularDistributions2.resize(gLAMBNUM*gQNUM2,
nullptr);
471 for (
G4int il=0; il<gLAMBNUM; ++il) {
472 G4String fname = str2 + std::to_string(il);
473 std::ifstream infile(fname,std::ios::in);
474 if (!infile.is_open()) {
475 G4String msgc =
"Cannot open file: " + fname;
476 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
480 for (
G4int iq=0; iq<gQNUM2; ++iq) {
485 gsd->fNumData = numData;
486 gsd->fUValues =
new G4double[gsd->fNumData]();
487 gsd->fParamA =
new G4double[gsd->fNumData]();
488 gsd->fParamB =
new G4double[gsd->fNumData]();
490 infile >> ddummy; infile >> ddummy;
491 for (
G4int i=0; i<gsd->fNumData; ++i) {
492 infile >> gsd->fUValues[i];
493 infile >> gsd->fParamA[i];
494 infile >> gsd->fParamB[i];
496 gGSMSCAngularDistributions2[il*gQNUM2+iq] = gsd;
498 gGSMSCAngularDistributions2[il*gQNUM2+iq] =
nullptr;
512 G4double cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
514 if (fIsMottCorrection) {
515 static const G4int nlooplim = 1000;
521 G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost,
522 matindx, ekindx, deltindx);
526 cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
528 val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost, matindx,
539 if (fIsMottCorrection) {
540 fMottCorrection->GetMottCorrectionFactors(logekin, beta2, matindx, mcToScr, mcToQ1, mcToG2PerG1);
546void G4GoudsmitSaundersonTable::InitMoliereMSCParams() {
549 const G4double finstrc2 = 5.325135453E-5;
553 std::size_t numMaterials = theMaterialTable->size();
555 if(gMoliereBc.size()<numMaterials) {
556 gMoliereBc.resize(numMaterials);
557 gMoliereXc2.resize(numMaterials);
561 if (fIsMottCorrection || fIsPWACorrection) {
566 for (std::size_t imat=0; imat<numMaterials; ++imat) {
567 const G4Material* theMaterial = (*theMaterialTable)[imat];
579 for(
G4int ielem = 0; ielem < numelems; ielem++) {
580 G4double zet = (*theElemVect)[ielem]->GetZ();
584 G4double iwa = (*theElemVect)[ielem]->GetN();
585 G4double ipz = theNbAtomsPerVolVect[ielem]/theTotNbAtomsPerVol;
588 ze += dum*(-2.0/3.0)*
G4Log(zet);
589 zx += dum*
G4Log(1.0+3.34*finstrc2*zet*zet);
595 gMoliereXc2[theMaterial->
GetIndex()] = const2*density*zs/sa;
597 gMoliereBc[theMaterial->
GetIndex()] *= 1.0/CLHEP::cm;
598 gMoliereXc2[theMaterial->
GetIndex()] *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
607 if (!(fSCPCPerMatCuts[imc]->fIsUse) || ekin<=fSCPCPerMatCuts[imc]->fPrCut) {
612 G4double remaining = (lekin-fSCPCPerMatCuts[imc]->fLEmin)*fSCPCPerMatCuts[imc]->fILDel;
613 std::size_t lindx = (std::size_t)remaining;
615 std::size_t imax = fSCPCPerMatCuts[imc]->fVSCPC.size()-1;
617 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[imax];
619 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[lindx] + remaining*(fSCPCPerMatCuts[imc]->fVSCPC[lindx+1]-fSCPCPerMatCuts[imc]->fVSCPC[lindx]);
630 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
631 if (fSCPCPerMatCuts[imc]) {
632 fSCPCPerMatCuts[imc]->fVSCPC.clear();
633 delete fSCPCPerMatCuts[imc];
634 fSCPCPerMatCuts[imc] =
nullptr;
639 fSCPCPerMatCuts.resize(numMatCuts,
nullptr);
641 for (
G4int imc=0; imc<(
G4int)numMatCuts; ++imc) {
653 G4double min = std::max(limit,fLowEnergyLimit);
656 fSCPCPerMatCuts[imc] =
new SCPCorrection();
657 fSCPCPerMatCuts[imc]->fIsUse =
false;
658 fSCPCPerMatCuts[imc]->fPrCut = min;
661 G4int numEbins = fNumSPCEbinPerDec*
G4lrint(std::log10(max/min));
662 numEbins = std::max(numEbins,3);
665 fSCPCPerMatCuts[imc] =
new SCPCorrection();
666 fSCPCPerMatCuts[imc]->fVSCPC.resize(numEbins,1.0);
667 fSCPCPerMatCuts[imc]->fIsUse =
true;
668 fSCPCPerMatCuts[imc]->fPrCut = min;
669 fSCPCPerMatCuts[imc]->fLEmin = lmin;
670 fSCPCPerMatCuts[imc]->fILDel = 1./ldel;
671 for (
G4int ie=0; ie<numEbins; ++ie) {
676 G4double tau = ekin/CLHEP::electron_mass_c2;
677 G4double tauCut = ecut/CLHEP::electron_mass_c2;
684 G4double gm =
G4Log(0.5*tau/tauCut) + (1.+dum0*dum0)*
G4Log(2.*(tau-tauCut+2.)/(tau+4.))
685 - 0.25*(tau+2.)*( tau+2.+2.*(2.*tau+1.)/(dum1*dum1))*
686 G4Log((tau+4.)*(tau-tauCut)/tau/(tau-tauCut+2.))
687 + 0.5*(tau-2*tauCut)*(tau+2.)*(1./(tau-tauCut)-1./(dum1*dum1));
694 scpCorr = 1.-gm*z0/(z0*(z0+1.));
696 fSCPCPerMatCuts[imc]->fVSCPC[ie] = scpCorr;
std::vector< const G4Element * > G4ElementVector
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
static G4EmParameters * Instance()
const G4String & GetDirLEDATA() const
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
const G4double * GetVecNbOfAtomsPerVolume() const
std::size_t GetIndex() const
static G4MaterialTable * GetMaterialTable()
std::size_t GetNumberOfElements() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
const std::vector< G4double > * GetEnergyCutsVector(std::size_t pcIdx) const
static G4ProductionCutsTable * GetProductionCutsTable()