52G4bool G4eDPWAElasticDCS::gIsGridLoaded =
false;
53G4String G4eDPWAElasticDCS::gDataDirectory =
"";
55std::size_t G4eDPWAElasticDCS::gNumEnergies = 106;
56std::size_t G4eDPWAElasticDCS::gIndxEnergyLim = 35;
57std::size_t G4eDPWAElasticDCS::gNumThetas1 = 247;
58std::size_t G4eDPWAElasticDCS::gNumThetas2 = 128;
59G4double G4eDPWAElasticDCS::gLogMinEkin = 1.0;
60G4double G4eDPWAElasticDCS::gInvDelLogEkin = 1.0;
62std::vector<G4double> G4eDPWAElasticDCS::gTheEnergies(G4eDPWAElasticDCS::gNumEnergies);
63std::vector<G4double> G4eDPWAElasticDCS::gTheMus1(G4eDPWAElasticDCS::gNumThetas1);
64std::vector<G4double> G4eDPWAElasticDCS::gTheMus2(G4eDPWAElasticDCS::gNumThetas2);
65std::vector<G4double> G4eDPWAElasticDCS::gTheU1(G4eDPWAElasticDCS::gNumThetas1);
66std::vector<G4double> G4eDPWAElasticDCS::gTheU2(G4eDPWAElasticDCS::gNumThetas2);
69const G4double G4eDPWAElasticDCS::gXGL[] = {
70 1.98550718E-02, 1.01666761E-01, 2.37233795E-01, 4.08282679E-01,
71 5.91717321E-01, 7.62766205E-01, 8.98333239E-01, 9.80144928E-01
73const G4double G4eDPWAElasticDCS::gWGL[] = {
74 5.06142681E-02, 1.11190517E-01, 1.56853323E-01, 1.81341892E-01,
75 1.81341892E-01, 1.56853323E-01, 1.11190517E-01, 5.06142681E-02
83: fIsRestrictedSamplingRequired(isrestricted), fIsElectron(iselectron) {
84 fDCS.resize(gMaxZ+1,
nullptr);
85 fDCSLow.resize(gMaxZ+1,
nullptr);
86 fSamplingTables.resize(gMaxZ+1,
nullptr);
92 for (std::size_t i=0; i<fDCS.size(); ++i) {
93 if (fDCS[i])
delete fDCS[i];
95 for (std::size_t i=0; i<fDCSLow.size(); ++i) {
96 if (fDCSLow[i])
delete fDCSLow[i];
98 for (std::size_t i=0; i<fSamplingTables.size(); ++i) {
99 if (fSamplingTables[i])
delete fSamplingTables[i];
102 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
103 if (fSCPCPerMatCuts[imc]) {
104 fSCPCPerMatCuts[imc]->fVSCPC.clear();
105 delete fSCPCPerMatCuts[imc];
108 fSCPCPerMatCuts.clear();
115 if (!gIsGridLoaded) {
118 LoadDCSForZ((
G4int)iz);
119 BuildSmplingTableForZ((
G4int)iz);
125void G4eDPWAElasticDCS::LoadGrid() {
126 G4String fname = FindDirectoryPath() +
"grid.dat";
127 std::ifstream infile(fname.c_str());
128 if (!infile.is_open()) {
130 " Problem while trying to read " + fname +
" file.\n"+
131 " G4LEDATA version should be G4EMLOW7.12 or later.\n";
132 G4Exception(
"G4eDPWAElasticDCS::ReadCompressedFile",
"em0006",
137 infile >> gNumEnergies;
138 infile >> gNumThetas1;
139 infile >> gNumThetas2;
143 gTheEnergies.resize(gNumEnergies);
144 for (std::size_t ie=0; ie<gNumEnergies; ++ie) {
146 gTheEnergies[ie] =
G4Log(dum*CLHEP::MeV);
147 if (gTheEnergies[ie]<
G4Log(2.0*CLHEP::keV)) gIndxEnergyLim = ie;
151 gLogMinEkin = gTheEnergies[0];
152 gInvDelLogEkin = (gNumEnergies-1)/(gTheEnergies[gNumEnergies-1]-gTheEnergies[0]);
154 gTheMus1.resize(gNumThetas1);
155 gTheU1.resize(gNumThetas1);
156 const double theA = 0.01;
157 for (std::size_t it=0; it<gNumThetas1; ++it) {
159 gTheMus1[it] = 0.5*(1.0-std::cos(dum*CLHEP::degree));
160 gTheU1[it] = (theA+1.0)*gTheMus1[it]/(theA+gTheMus1[it]);
163 gTheMus2.resize(gNumThetas2);
164 gTheU2.resize(gNumThetas2);
165 for (std::size_t it=0; it<gNumThetas2; ++it) {
167 gTheMus2[it] = 0.5*(1.0-std::cos(dum*CLHEP::degree));
168 gTheU2[it] = (theA+1.0)*gTheMus2[it]/(theA+gTheMus2[it]);
172 gIsGridLoaded =
true;
177void G4eDPWAElasticDCS::LoadDCSForZ(
G4int iz) {
179 if (fDCS[iz])
return;
185 const std::size_t hNumEnergries = gNumEnergies-gIndxEnergyLim;
187 v2DHigh->SetBicubicInterpolation(
true);
188 for (std::size_t it=0; it<gNumThetas2; ++it) {
189 v2DHigh->PutX(it, gTheMus2[it]);
191 for (std::size_t ie=0; ie<hNumEnergries; ++ie) {
192 v2DHigh->PutY(ie, gTheEnergies[gIndxEnergyLim+ie]);
194 std::ostringstream ossh;
195 ossh << FindDirectoryPath() <<
"dcss/el/dcs_"<< iz<<
"_h";
196 std::istringstream finh(std::ios::in);
197 ReadCompressedFile(ossh.str(), finh);
199 for (std::size_t it=0; it<gNumThetas2; ++it) {
201 for (std::size_t ie=0; ie<hNumEnergries; ++ie) {
203 v2DHigh->PutValue(it, ie,
G4Log(dum*CLHEP::cm2/CLHEP::sr));
211 v2DLow->SetBicubicInterpolation(
true);
212 for (std::size_t it=0; it<gNumThetas1; ++it) {
213 v2DLow->PutX(it, gTheMus1[it]);
215 for (std::size_t ie=0; ie<gIndxEnergyLim+1; ++ie) {
216 v2DLow->PutY(ie, gTheEnergies[ie]);
218 std::ostringstream ossl;
219 ossl << FindDirectoryPath() <<
"dcss/el/dcs_"<< iz<<
"_l";
220 std::istringstream finl(std::ios::in);
221 ReadCompressedFile(ossl.str(), finl);
222 for (std::size_t it=0; it<gNumThetas1; ++it) {
224 for (std::size_t ie=0; ie<gIndxEnergyLim; ++ie) {
226 v2DLow->PutValue(it, ie,
G4Log(dum*CLHEP::cm2/CLHEP::sr));
232 for (std::size_t it=0; it<gNumThetas1; ++it) {
233 const G4double val = v2DHigh->Value(gTheMus1[it], gTheEnergies[gIndxEnergyLim], ix, iy);
234 v2DLow->PutValue(it, gIndxEnergyLim, val);
237 fDCSLow[iz] = v2DLow;
242 v2D->SetBicubicInterpolation(
true);
243 for (std::size_t it=0; it<gNumThetas2; ++it) {
244 v2D->PutX(it, gTheMus2[it]);
246 for (std::size_t ie=0; ie<gNumEnergies; ++ie) {
247 v2D->PutY(ie, gTheEnergies[ie]);
249 std::ostringstream oss;
250 oss << FindDirectoryPath() <<
"dcss/pos/dcs_"<< iz;
251 std::istringstream fin(std::ios::in);
252 ReadCompressedFile(oss.str(), fin);
254 for (std::size_t it=0; it<gNumThetas2; ++it) {
256 for (std::size_t ie=0; ie<gNumEnergies; ++ie) {
258 v2D->PutValue(it, ie,
G4Log(dum*CLHEP::cm2/CLHEP::sr));
278 mumin = std::max(0.0, std::min(1.0, mumin));
279 mumax = std::max(0.0, std::min(1.0, mumax));
280 if (mumin>=mumax)
return;
282 const G4double lekin = std::max(gTheEnergies[0], std::min(gTheEnergies[gNumEnergies-1],
G4Log(ekin)));
284 const G4bool isLowerGrid = (fIsElectron && lekin<gTheEnergies[gIndxEnergyLim]);
285 const std::vector<G4double>& theMuVector = (isLowerGrid) ? gTheMus1 : gTheMus2;
289 const std::size_t iMuStart = (mumin == 0.0) ? 0 : std::distance( theMuVector.begin(), std::upper_bound(theMuVector.begin(), theMuVector.end(), mumin) )-1 ;
291 const std::size_t iMuEnd = (mumax == 1.0) ? theMuVector.size()-2 : std::distance( theMuVector.begin(), std::upper_bound(theMuVector.begin(), theMuVector.end(), mumax) )-1 ;
296 for (std::size_t imu=iMuStart; imu<=iMuEnd; ++imu) {
300 const G4double low = (imu==iMuStart) ? mumin : theMuVector[imu];
301 const G4double del = (imu==iMuEnd) ? mumax-low : theMuVector[imu+1]-low;
303 for (std::size_t igl=0; igl<8; ++igl) {
304 const double mu = low + del*gXGL[igl];
305 const double dcs =
G4Exp(the2DDCS->
Value(mu, lekin, ix, iy));
306 elcsPar += gWGL[igl]*dcs;
307 tr1csPar += gWGL[igl]*dcs*mu;
308 tr2csPar += gWGL[igl]*dcs*mu*(1.0-mu);
311 tr1cs += del*tr1csPar;
312 tr2cs += del*tr2csPar;
314 elcs *= 2.0*CLHEP::twopi;
315 tr1cs *= 4.0*CLHEP::twopi;
316 tr2cs *= 12.0*CLHEP::twopi;
344 std::vector<G4double>
fW;
346 std::vector<G4double>
fA;
347 std::vector<G4double>
fB;
348 std::vector<G4int>
fI;
353void G4eDPWAElasticDCS::BuildSmplingTableForZ(
G4int iz) {
355 if (fSamplingTables[iz])
return;
358 auto sTables =
new std::vector<OneSamplingTable>(gNumEnergies);
360 std::ostringstream oss;
361 const G4String fname = fIsElectron ?
"stables/el/" :
"stables/pos/";
362 oss << FindDirectoryPath() << fname <<
"stable_" << iz;
363 std::istringstream fin(std::ios::in);
364 ReadCompressedFile(oss.str(), fin);
365 std::size_t ndata = 0;
366 for (std::size_t ie=0; ie<gNumEnergies; ++ie) {
370 aTable.
SetSize(ndata, !fIsRestrictedSamplingRequired);
374 if (!fIsRestrictedSamplingRequired) {
375 for (std::size_t
id=0;
id<ndata; ++id) {
376 fin >> aTable.
fW[id];
378 for (std::size_t
id=0;
id<ndata; ++id) {
379 fin >> aTable.
fI[id];
382 for (std::size_t
id=0;
id<ndata; ++id) {
383 fin >> aTable.
fCum[id];
385 for (std::size_t
id=0;
id<ndata; ++id) {
386 fin >> aTable.
fA[id];
388 for (std::size_t
id=0;
id<ndata; ++id) {
389 fin >> aTable.
fB[id];
392 fSamplingTables[iz] = sTables;
407 lekin = std::max(gTheEnergies[0], std::min(gTheEnergies[gNumEnergies-1], lekin));
410 const G4double rem = (lekin-gLogMinEkin)*gInvDelLogEkin;
411 const auto k = (std::size_t)rem;
412 const std::size_t iekin = (r1 < rem-k) ? k+1 : k;
414 const double mu = SampleMu(iz, iekin, r2, r3);
415 return std::max(-1.0, std::min(1.0, 1.0-2.0*mu));
432 lekin = std::max(gTheEnergies[0], std::min(gTheEnergies[gNumEnergies-1], lekin));
435 const G4double rem = (lekin-gLogMinEkin)*gInvDelLogEkin;
436 const auto k = (size_t)rem;
437 const std::size_t iekin = (r1 < rem-k) ? k : k+1;
439 const G4double mu = SampleMu(iz, iekin, r2, 0.5*(1.0-costMax), 0.5*(1.0-costMin));
440 return std::max(-1.0, std::min(1.0, 1.0-2.0*mu));
446G4eDPWAElasticDCS::SampleMu(std::size_t izet, std::size_t ie,
G4double r1,
G4double r2) {
450 auto indxl = (std::size_t)rest;
452 if (rtn.
fW[indxl] < dum0) indxl = rtn.
fI[indxl];
457 const G4double dum1 = (1.0 + rtn.
fA[indxl] + rtn.
fB[indxl]) * delta * aval;
458 const G4double dum2 = delta * delta + rtn.
fA[indxl] * delta * aval + rtn.
fB[indxl] * aval * aval;
459 const std::vector<G4double>& theUVect = (fIsElectron && ie<gIndxEnergyLim) ? gTheU1 : gTheU2;
460 const G4double u = theUVect[indxl] + dum1 / dum2 * (theUVect[indxl + 1] - theUVect[indxl]);
469 const std::vector<G4double>& uvect) {
470 const std::size_t iLow = std::distance( uvect.begin(), std::upper_bound(uvect.begin(), uvect.end(), u) )-1;
471 const G4double tau = (u-uvect[iLow])/(uvect[iLow+1]-uvect[iLow]);
472 const G4double dum0 = (1.0+stable.
fA[iLow]*(1.0-tau)+stable.
fB[iLow]);
473 const G4double dum1 = 2.0*stable.
fB[iLow]*tau;
474 const G4double dum2 = 1.0 - std::sqrt(std::max(0.0, 1.0-2.0*dum1*tau/(dum0*dum0)));
475 return std::min(stable.
fCum[iLow+1], std::max(stable.
fCum[iLow], stable.
fCum[iLow]+dum0*dum2*(stable.
fCum[iLow+1]-stable.
fCum[iLow])/dum1 ));
479G4double G4eDPWAElasticDCS::SampleMu(std::size_t izet, std::size_t ie,
G4double r1,
484 const std::vector<G4double>& theUVect = (fIsElectron && ie<gIndxEnergyLim) ? gTheU1 : gTheU2;
485 const G4double xiMin = (muMin > 0.0) ? FindCumValue((theA+1.0)*muMin/(theA+muMin), rtn, theUVect) : 0.0;
486 const G4double xiMax = (muMax < 1.0) ? FindCumValue((theA+1.0)*muMax/(theA+muMax), rtn, theUVect) : 1.0;
488 const G4double xi = xiMin+r1*(xiMax-xiMin);
489 const std::size_t iLow = std::distance( rtn.
fCum.begin(), std::upper_bound(rtn.
fCum.begin(), rtn.
fCum.end(), xi) )-1;
493 const G4double dum1 = (1.0 + rtn.
fA[iLow] + rtn.
fB[iLow]) * delta * aval;
494 const G4double dum2 = delta * delta + rtn.
fA[iLow] * delta * aval + rtn.
fB[iLow] * aval * aval;
495 const G4double u = theUVect[iLow] + dum1 / dum2 * (theUVect[iLow + 1] - theUVect[iLow]);
496 return theA*u/(theA+1.0-u);
502const G4String& G4eDPWAElasticDCS::FindDirectoryPath() {
504 if (gDataDirectory.empty()) {
507 std::ostringstream ost;
508 ost << path <<
"/dpwa/";
509 gDataDirectory = ost.str();
511 G4Exception(
"G4eDPWAElasticDCS::FindDirectoryPath()",
"em0006",
513 "Environment variable G4LEDATA not defined");
516 return gDataDirectory;
523G4eDPWAElasticDCS::ReadCompressedFile(
G4String fname, std::istringstream &iss) {
527 std::ifstream in(compfilename, std::ios::binary | std::ios::ate);
530 std::size_t fileSize = in.tellg();
532 in.seekg(0,std::ios::beg);
534 Bytef *compdata =
new Bytef[fileSize];
536 in.read((
char*)compdata, fileSize);
539 uLongf complen = (uLongf)(fileSize*4);
540 Bytef *uncompdata =
new Bytef[complen];
541 while (
Z_OK!=
uncompress(uncompdata, &complen, compdata, fileSize)) {
545 uncompdata =
new Bytef[complen];
550 dataString =
new G4String((
char*)uncompdata, (
long)complen);
552 delete [] uncompdata;
555 " Problem while trying to read " + fname +
" data file.\n"+
556 " G4LEDATA version should be G4EMLOW7.12 or later.\n";
557 G4Exception(
"G4eDPWAElasticDCS::ReadCompressedFile",
"em0006",
563 iss.str(*dataString);
577 if (!(fSCPCPerMatCuts[imc]->fIsUse) || ekin<=fSCPCPerMatCuts[imc]->fPrCut) {
582 G4double remaining = (lekin-fSCPCPerMatCuts[imc]->fLEmin)*fSCPCPerMatCuts[imc]->fILDel;
583 std::size_t lindx = (
G4int)remaining;
585 std::size_t imax = fSCPCPerMatCuts[imc]->fVSCPC.size()-1;
587 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[imax];
589 corFactor = fSCPCPerMatCuts[imc]->fVSCPC[lindx] + remaining*(fSCPCPerMatCuts[imc]->fVSCPC[lindx+1]-fSCPCPerMatCuts[imc]->fVSCPC[lindx]);
601 for (std::size_t imc=0; imc<fSCPCPerMatCuts.size(); ++imc) {
602 if (fSCPCPerMatCuts[imc]) {
603 fSCPCPerMatCuts[imc]->fVSCPC.clear();
604 delete fSCPCPerMatCuts[imc];
605 fSCPCPerMatCuts[imc] =
nullptr;
610 fSCPCPerMatCuts.resize(numMatCuts,
nullptr);
612 for (
G4int imc=0; imc<(
G4int)numMatCuts; ++imc) {
617 const G4double limit = fIsElectron ? 2.0*ecut : ecut;
618 const G4double min = std::max(limit,lowEnergyLimit);
619 const G4double max = highEnergyLimit;
621 fSCPCPerMatCuts[imc] =
new SCPCorrection();
622 fSCPCPerMatCuts[imc]->fIsUse =
false;
623 fSCPCPerMatCuts[imc]->fPrCut = min;
626 G4int numEbins = fNumSPCEbinPerDec*
G4lrint(std::log10(max/min));
627 numEbins = std::max(numEbins,3);
630 fSCPCPerMatCuts[imc] =
new SCPCorrection();
631 fSCPCPerMatCuts[imc]->fVSCPC.resize(numEbins,1.0);
632 fSCPCPerMatCuts[imc]->fIsUse =
true;
633 fSCPCPerMatCuts[imc]->fPrCut = min;
634 fSCPCPerMatCuts[imc]->fLEmin = lmin;
635 fSCPCPerMatCuts[imc]->fILDel = 1./ldel;
639 ComputeMParams(mat, moliereBc, moliereXc2);
641 for (
G4int ie=0; ie<numEbins; ++ie) {
646 const G4double tau = ekin/CLHEP::electron_mass_c2;
647 const G4double tauCut = ecut/CLHEP::electron_mass_c2;
649 const G4double A = moliereXc2/(4.0*tau*(tau+2.)*moliereBc);
651 const G4double dum0 = (tau+2.)/(tau+1.);
653 G4double gm =
G4Log(0.5*tau/tauCut) + (1.+dum0*dum0)*
G4Log(2.*(tau-tauCut+2.)/(tau+4.))
654 - 0.25*(tau+2.)*( tau+2.+2.*(2.*tau+1.)/(dum1*dum1))*
655 G4Log((tau+4.)*(tau-tauCut)/tau/(tau-tauCut+2.))
656 + 0.5*(tau-2*tauCut)*(tau+2.)*(1./(tau-tauCut)-1./(dum1*dum1));
663 scpCorr = 1.-gm*z0/(z0*(z0+1.));
665 fSCPCPerMatCuts[imc]->fVSCPC[ie] = scpCorr;
676 const G4double finstrc2 = 5.325135453E-5;
689 for(std::size_t ielem = 0; ielem < numelems; ++ielem) {
690 const G4double zet = (*theElemVect)[ielem]->GetZ();
691 const G4double iwa = (*theElemVect)[ielem]->GetN();
692 const G4double ipz = theNbAtomsPerVolVect[ielem]/theTotNbAtomsPerVol;
693 const G4double dum = ipz*zet*(zet+1.0);
695 ze += dum*(-2.0/3.0)*
G4Log(zet);
696 zx += dum*
G4Log(1.0+3.34*finstrc2*zet*zet);
701 theBc = const1*density*zs/sa*
G4Exp(ze/zs)/
G4Exp(zx/zs);
702 theXc2 = const2*density*zs/sa;
704 theBc *= 1.0/CLHEP::cm;
705 theXc2 *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
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)
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
G4double Value(G4double x, G4double y, std::size_t &lastidx, std::size_t &lastidy) 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()
void ComputeCSPerAtom(G4int iz, G4double ekin, G4double &elcs, G4double &tr1cs, G4double &tr2cs, G4double mumin=0.0, G4double mumax=1.0)
void InitialiseForZ(std::size_t iz)
void InitSCPCorrection(G4double lowEnergyLimit, G4double highEnergyLimit)
G4double ComputeScatteringPowerCorrection(const G4MaterialCutsCouple *matcut, G4double ekin)
G4double SampleCosineTheta(std::size_t iz, G4double lekin, G4double r1, G4double r2, G4double r3)
G4double SampleCosineThetaRestricted(std::size_t iz, G4double lekin, G4double r1, G4double r2, G4double costMax, G4double costMin)
G4eDPWAElasticDCS(G4bool iselectron=true, G4bool isrestricted=false)
std::vector< G4double > fB
std::vector< G4double > fA
void SetSize(std::size_t nx, G4bool useAlias)
OneSamplingTable()=default
std::vector< G4double > fW
std::vector< G4double > fCum
int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)