104G4bool G4GoudsmitSaundersonTable::gIsInitialised =
false;
106std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions1;
107std::vector<G4GoudsmitSaundersonTable::GSMSCAngularDtr*> G4GoudsmitSaundersonTable::gGSMSCAngularDistributions2;
109std::vector<double> G4GoudsmitSaundersonTable::gMoliereBc;
110std::vector<double> G4GoudsmitSaundersonTable::gMoliereXc2;
114 fIsElectron = iselectron;
117 fLogDeltaLambda = 0.;
118 fInvLogDeltaLambda = 0.;
123 fLowEnergyLimit = 0.1*CLHEP::keV;
124 fHighEnergyLimit = 100.0*CLHEP::MeV;
126 fIsMottCorrection =
false;
127 fIsPWACorrection =
false;
128 fMottCorrection =
nullptr;
130 fNumSPCEbinPerDec = 3;
134 for (std::size_t i=0; i<gGSMSCAngularDistributions1.size(); ++i) {
135 if (gGSMSCAngularDistributions1[i]) {
136 delete [] gGSMSCAngularDistributions1[i]->fUValues;
137 delete [] gGSMSCAngularDistributions1[i]->fParamA;
138 delete [] gGSMSCAngularDistributions1[i]->fParamB;
139 delete gGSMSCAngularDistributions1[i];
142 gGSMSCAngularDistributions1.clear();
143 for (std::size_t i=0; i<gGSMSCAngularDistributions2.size(); ++i) {
144 if (gGSMSCAngularDistributions2[i]) {
145 delete [] gGSMSCAngularDistributions2[i]->fUValues;
146 delete [] gGSMSCAngularDistributions2[i]->fParamA;
147 delete [] gGSMSCAngularDistributions2[i]->fParamB;
148 delete gGSMSCAngularDistributions2[i];
151 gGSMSCAngularDistributions2.clear();
152 if (fMottCorrection) {
153 delete fMottCorrection;
154 fMottCorrection =
nullptr;
157 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
158 if (fSCPCPerMatCuts[imc]) {
159 fSCPCPerMatCuts[imc]->fVSCPC.clear();
160 delete fSCPCPerMatCuts[imc];
163 fSCPCPerMatCuts.clear();
165 gIsInitialised =
false;
169 fLowEnergyLimit = lownergylimit;
170 fHighEnergyLimit = highenergylimit;
173 fLogLambda0 = lLambdaMin;
174 fLogDeltaLambda = (lLambdaMax-lLambdaMin)/(gLAMBNUM-1.);
175 fInvLogDeltaLambda = 1./fLogDeltaLambda;
176 fInvDeltaQ1 = 1./((gQMAX1-gQMIN1)/(gQNUM1-1.));
177 fDeltaQ2 = (gQMAX2-gQMIN2)/(gQNUM2-1.);
178 fInvDeltaQ2 = 1./fDeltaQ2;
181 if (!gIsInitialised) {
184 gIsInitialised =
true;
186 InitMoliereMSCParams();
188 if (fIsMottCorrection) {
189 if (!fMottCorrection) {
192 fMottCorrection->Initialise();
196 if (fMottCorrection) {
230 if (rand0<(1.+lambdaval)*expn) {
234 if (cost<-1.0) cost = -1.0;
235 if (cost>1.0) cost = 1.0;
238 sint = std::sqrt(dum0*(2.0-dum0));
257 prob = cumprob = expn;
262 for (
G4int iel=1; iel<10; ++iel) {
271 cursint = dum0*(2.0-dum0);
275 if (cursint>1.0e-20) {
276 cursint = std::sqrt(cursint);
278 cost = cost*curcost-sint*cursint*std::cos(curphi);
279 sint = std::sqrt(std::max(0.0, (1.0-cost)*(1.0+cost)));
295 cost =
SampleCosTheta(lambdaval, qval, scra, lekin, beta2, matindx, gsDtr, mcekini, mcdelti, transfPar, isfirst);
297 if (cost<-1.0) cost = -1.0;
298 if (cost> 1.0) cost = 1.0;
301 sint = std::sqrt(dum0*(2.0-dum0));
319 if (fIsMottCorrection && *gsDtr) {
320 static const G4int nlooplim = 1000;
324 G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
328 val = fMottCorrection->GetMottRejectionValue(lekin, beta2, qval, cost, matindx, mcekini, mcdelti);
347 G4int indxl = rndm*ndatm1;
356 return 1.-(2.0*transfpar*sample)/(1.0-sample+transfpar);
370 G4int numQVal = gQNUM2;
386 invDelQ = fInvDeltaQ1;
390 if (lambdaval>=gLAMBMAX) {
391 lambdaval = gLAMBMAX-1.e-8;
392 lamIndx = gLAMBNUM-1;
398 pIndxH = (lLambda-fLogLambda0)*fInvLogDeltaLambda;
399 lamIndx = (
G4int)(pIndxH);
400 pIndxH = pIndxH-lamIndx;
408 pIndxH = (qval-minQVal)*invDelQ;
409 qIndx = (
G4int)(pIndxH);
410 pIndxH = pIndxH-qIndx;
416 G4int indx = lamIndx*numQVal+qIndx;
418 dtr = gGSMSCAngularDistributions1[indx];
420 dtr = gGSMSCAngularDistributions2[indx];
427 if (lambdaval>10.0) {
428 transfpar = 0.5*(-2.77164+lLambda*( 2.94874-lLambda*(0.1535754-lLambda*0.00552888) ));
430 transfpar = 0.5*(1.347+lLambda*(0.209364-lLambda*(0.45525-lLambda*(0.50142-lLambda*0.081234))));
432 transfpar *= (lambdaval+4.0)*scra;
440 gGSMSCAngularDistributions1.resize(gLAMBNUM*gQNUM1,
nullptr);
442 for (
G4int il=0; il<gLAMBNUM; ++il) {
444 std::ifstream infile(fname,std::ios::in);
445 if (!infile.is_open()) {
446 G4String msgc =
"Cannot open file: " + fname;
447 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
451 for (
G4int iq=0; iq<gQNUM1; ++iq) {
453 infile >> gsd->fNumData;
454 gsd->fUValues =
new G4double[gsd->fNumData]();
455 gsd->fParamA =
new G4double[gsd->fNumData]();
456 gsd->fParamB =
new G4double[gsd->fNumData]();
458 infile >> ddummy; infile >> ddummy;
459 for (
G4int i=0; i<gsd->fNumData; ++i) {
460 infile >> gsd->fUValues[i];
461 infile >> gsd->fParamA[i];
462 infile >> gsd->fParamB[i];
464 gGSMSCAngularDistributions1[il*gQNUM1+iq] = gsd;
470 gGSMSCAngularDistributions2.resize(gLAMBNUM*gQNUM2,
nullptr);
472 for (
G4int il=0; il<gLAMBNUM; ++il) {
474 std::ifstream infile(fname,std::ios::in);
475 if (!infile.is_open()) {
476 G4String msgc =
"Cannot open file: " + fname;
477 G4Exception(
"G4GoudsmitSaundersonTable::LoadMSCData()",
"em0006",
481 for (
G4int iq=0; iq<gQNUM2; ++iq) {
486 gsd->fNumData = numData;
487 gsd->fUValues =
new G4double[gsd->fNumData]();
488 gsd->fParamA =
new G4double[gsd->fNumData]();
489 gsd->fParamB =
new G4double[gsd->fNumData]();
491 infile >> ddummy; infile >> ddummy;
492 for (
G4int i=0; i<gsd->fNumData; ++i) {
493 infile >> gsd->fUValues[i];
494 infile >> gsd->fParamA[i];
495 infile >> gsd->fParamB[i];
497 gGSMSCAngularDistributions2[il*gQNUM2+iq] = gsd;
499 gGSMSCAngularDistributions2[il*gQNUM2+iq] =
nullptr;
513 G4double cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
515 if (fIsMottCorrection) {
516 static const G4int nlooplim = 1000;
522 G4double val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost,
523 matindx, ekindx, deltindx);
527 cost = 1.-2.0*scra*rand1/(1.0-rand1+scra);
529 val = fMottCorrection->GetMottRejectionValue(lekin, beta2, q1, cost, matindx,
540 if (fIsMottCorrection) {
541 fMottCorrection->GetMottCorrectionFactors(logekin, beta2, matindx, mcToScr, mcToQ1, mcToG2PerG1);
547void G4GoudsmitSaundersonTable::InitMoliereMSCParams() {
550 const G4double finstrc2 = 5.325135453E-5;
554 std::size_t numMaterials = theMaterialTable->size();
556 if(gMoliereBc.size()<numMaterials) {
557 gMoliereBc.resize(numMaterials);
558 gMoliereXc2.resize(numMaterials);
562 if (fIsMottCorrection || fIsPWACorrection) {
567 for (std::size_t imat=0; imat<numMaterials; ++imat) {
568 const G4Material* theMaterial = (*theMaterialTable)[imat];
580 for(
G4int ielem = 0; ielem < numelems; ielem++) {
581 G4double zet = (*theElemVect)[ielem]->GetZ();
585 G4double iwa = (*theElemVect)[ielem]->GetN();
586 G4double ipz = theNbAtomsPerVolVect[ielem]/theTotNbAtomsPerVol;
589 ze += dum*(-2.0/3.0)*
G4Log(zet);
590 zx += dum*
G4Log(1.0+3.34*finstrc2*zet*zet);
596 gMoliereXc2[theMaterial->
GetIndex()] = const2*density*zs/sa;
598 gMoliereBc[theMaterial->
GetIndex()] *= 1.0/CLHEP::cm;
599 gMoliereXc2[theMaterial->
GetIndex()] *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
608 if (!(fSCPCPerMatCuts[imc]->fIsUse) || ekin<=fSCPCPerMatCuts[imc]->fPrCut) {
613 G4double remaining = (lekin-fSCPCPerMatCuts[imc]->fLEmin)*fSCPCPerMatCuts[imc]->fILDel;
614 std::size_t lindx = (std::size_t)remaining;
616 std::size_t imax = fSCPCPerMatCuts[imc]->fVSCPC.size()-1;
618 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[imax];
620 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[lindx] + remaining*(fSCPCPerMatCuts[imc]->fVSCPC[lindx+1]-fSCPCPerMatCuts[imc]->fVSCPC[lindx]);
631 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
632 if (fSCPCPerMatCuts[imc]) {
633 fSCPCPerMatCuts[imc]->fVSCPC.clear();
634 delete fSCPCPerMatCuts[imc];
635 fSCPCPerMatCuts[imc] =
nullptr;
640 fSCPCPerMatCuts.resize(numMatCuts,
nullptr);
642 for (
G4int imc=0; imc<(
G4int)numMatCuts; ++imc) {
652 for(
G4int ielem = 0; ielem < numelems; ielem++) {
653 G4double zet = (*theElemVect)[ielem]->GetZ();
654 G4double ipz = theNbAtomsPerVolVect[ielem]/theTotNbAtomsPerVol;
655 zs = zs + ipz*zet*(zet + 1.0);
669 G4double min = std::max(limit,fLowEnergyLimit);
672 fSCPCPerMatCuts[imc] =
new SCPCorrection();
673 fSCPCPerMatCuts[imc]->fIsUse =
false;
674 fSCPCPerMatCuts[imc]->fPrCut = min;
677 G4int numEbins = fNumSPCEbinPerDec*
G4lrint(std::log10(max/min));
678 numEbins = std::max(numEbins,3);
681 fSCPCPerMatCuts[imc] =
new SCPCorrection();
682 fSCPCPerMatCuts[imc]->fVSCPC.resize(numEbins,1.0);
683 fSCPCPerMatCuts[imc]->fIsUse =
true;
684 fSCPCPerMatCuts[imc]->fPrCut = min;
685 fSCPCPerMatCuts[imc]->fLEmin = lmin;
686 fSCPCPerMatCuts[imc]->fILDel = 1./ldel;
687 for (
G4int ie=0; ie<numEbins; ++ie) {
692 G4double tau = ekin/CLHEP::electron_mass_c2;
693 G4double tauCut = ecut/CLHEP::electron_mass_c2;
700 G4double gm =
G4Log(0.5*tau/tauCut) + (1.+dum0*dum0)*
G4Log(2.*(tau-tauCut+2.)/(tau+4.))
701 - 0.25*(tau+2.)*( tau+2.+2.*(2.*tau+1.)/(dum1*dum1))*
702 G4Log((tau+4.)*(tau-tauCut)/tau/(tau-tauCut+2.))
703 + 0.5*(tau-2*tauCut)*(tau+2.)*(1./(tau-tauCut)-1./(dum1*dum1));
709 scpCorr = 1.0 - gm*sm/zs;
711 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)
const G4Material * GetMaterial() const
G4double GetDensity() const
const G4ElementVector * GetElementVector() const
G4double GetTotNbOfAtomsPerVolume() 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()
std::string to_string(G4FermiAtomicMass mass)