61 :
G4VEmModel(nam),fParticleChange(nullptr),fParticle(nullptr),
62 fLogFormFactorTable(nullptr),fPMaxTable(nullptr),fSamplingTable(nullptr),
63 fIsInitialised(false),fLocalTable(false)
91 if (logenergy < logtransitionenergy)
92 logenergy += logfactor1;
94 logenergy += logfactor2;
96 }
while (logenergy < logmaxenergy);
129 if (item.second)
delete item.second;
136 if (item.second)
delete item.second;
143 if (item.second)
delete item.second;
156 G4cout <<
"Calling G4PenelopeRayleighModel::Initialise()" <<
G4endl;
167 G4cout <<
"Calling G4PenelopeRayleighModel::Initialise() [master]" <<
G4endl;
173 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
175 fSamplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
186 for (
size_t j=0;j<
material->GetNumberOfElements();j++)
188 G4int iZ = theElementVector->at(j)->GetZasInt();
208 G4cout <<
"Penelope Rayleigh model v2008 is initialized " <<
G4endl
227 G4cout <<
"Calling G4PenelopeRayleighModel::InitialiseLocal()" <<
G4endl;
273 G4cout <<
"Calling CrossSectionPerAtom() of G4PenelopeRayleighModel" <<
G4endl;
285 ed <<
"Unable to retrieve the cross section table for Z=" << iZ <<
G4endl;
286 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
287 G4Exception(
"G4PenelopeRayleighModel::ComputeCrossSectionPerAtom()",
301 ed <<
"Unable to find Z=" << iZ <<
" in the atomic cross section table" <<
G4endl;
302 G4Exception(
"G4PenelopeRayleighModel::ComputeCrossSectionPerAtom()",
308 cross =
G4Exp(logXS);
312 G4cout <<
"Rayleigh cross section at " <<
energy/
keV <<
" keV for Z=" <<
Z <<
329 std::vector<G4double> *StechiometricFactors =
new std::vector<G4double>;
330 for (
G4int i=0;i<nElements;i++)
332 G4double fraction = fractionVector[i];
333 G4double atomicWeigth = (*elementVector)[i]->GetA()/(
g/
mole);
334 StechiometricFactors->push_back(fraction/atomicWeigth);
337 G4double MaxStechiometricFactor = 0.;
338 for (
G4int i=0;i<nElements;i++)
340 if ((*StechiometricFactors)[i] > MaxStechiometricFactor)
341 MaxStechiometricFactor = (*StechiometricFactors)[i];
343 if (MaxStechiometricFactor<1e-16)
346 ed <<
"Inconsistent data of atomic composition for " <<
348 G4Exception(
"G4PenelopeRayleighModel::BuildFormFactorTable()",
352 for (
G4int i=0;i<nElements;i++)
353 (*StechiometricFactors)[i] /= MaxStechiometricFactor;
363 for (
G4int i=0;i<nElements;i++)
365 G4int iZ = (*elementVector)[i]->GetZasInt();
368 ff2 += f*f*(*StechiometricFactors)[i];
376 delete StechiometricFactors;
402 G4cout <<
"Calling SamplingSecondaries() of G4PenelopeRayleighModel" <<
G4endl;
429 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
431 fSamplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
442 ed <<
"Unable to find the fSamplingTable data for " <<
444 ed <<
"This can happen only in Unit Tests" <<
G4endl;
445 G4Exception(
"G4PenelopeRayleighModel::SampleSecondaries()",
453 G4int iZ = theElementVector->at(j)->GetZasInt();
492 G4double G = 0.5*(1+cosTheta*cosTheta);
500 G4double LastQ2inTheTable = theDataTable->
GetX(nData-1);
518 cosTheta = 1.0-2.0*xx/q2max;
519 G4double G = 0.5*(1+cosTheta*cosTheta);
525 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
529 G4double dirX = sinTheta*std::cos(phi);
530 G4double dirY = sinTheta*std::sin(phi);
536 photonDirection1.
rotateUz(photonDirection0);
550 G4cout <<
"G4PenelopeRayleighModel::ReadDataFile()" <<
G4endl;
551 G4cout <<
"Going to read Rayleigh data files for Z=" <<
Z <<
G4endl;
553 char* path = std::getenv(
"G4LEDATA");
556 G4String excep =
"G4LEDATA environment variable not set!";
557 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
565 std::ostringstream ost;
567 ost << path <<
"/penelope/rayleigh/pdgra" <<
Z <<
".p08";
569 ost << path <<
"/penelope/rayleigh/pdgra0" <<
Z <<
".p08";
570 std::ifstream
file(ost.str().c_str());
574 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
579 file >> readZ >> nPoints;
581 if (readZ !=
Z || nPoints <= 0 || nPoints >= 5000)
584 ed <<
"Corrupted data file for Z=" <<
Z <<
G4endl;
585 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
592 for (
size_t i=0;i<nPoints;i++)
594 file >> ene >> f1 >> f2 >> xs;
599 if (
file.eof() && i != (nPoints-1))
602 ed <<
"Corrupted data file for Z=" <<
Z <<
G4endl;
603 ed <<
"Found less than " << nPoints <<
"entries " <<
G4endl;
604 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
613 std::ostringstream ost2;
615 ost2 << path <<
"/penelope/rayleigh/pdaff" <<
Z <<
".p08";
617 ost2 << path <<
"/penelope/rayleigh/pdaff0" <<
Z <<
".p08";
618 file.open(ost2.str().c_str());
622 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
625 file >> readZ >> nPoints;
627 if (readZ !=
Z || nPoints <= 0 || nPoints >= 5000)
630 ed <<
"Corrupted data file for Z=" <<
Z <<
G4endl;
631 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
641 for (
size_t i=0;i<nPoints;i++)
643 file >> q >> ff >> incoh;
650 if (
file.eof() && i != (nPoints-1))
653 ed <<
"Corrupted data file for Z=" <<
Z <<
G4endl;
654 ed <<
"Found less than " << nPoints <<
"entries " <<
G4endl;
655 G4Exception(
"G4PenelopeRayleighModel::ReadDataFile()",
671 G4double logQSquared = (QSquared>1e-10) ?
G4Log(QSquared) : -23.;
681 ed <<
"Unable to retrieve F squared table for " << mat->
GetName() <<
G4endl;
682 G4Exception(
"G4PenelopeRayleighModel::GetFSquared()",
686 if (logQSquared < -20)
691 else if (logQSquared > maxlogQ2)
703 G4cout <<
"Q^2 = " << QSquared <<
" (units of 1/(m_e*c); F^2 = " << f2 <<
G4endl;
714 const size_t np = 150;
726 size_t nReducedPoints = np/4;
731 G4Exception(
"G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
733 "Too few points to initialize the sampling algorithm");
735 if (q2min > (q2max-1e-10))
737 G4cout <<
"q2min= " << q2min <<
" q2max= " << q2max <<
G4endl;
738 G4Exception(
"G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
740 "Too narrow grid to initialize the sampling algorithm");
753 const G4int nip = 51;
757 for (
size_t i=1;i<NUNIF-1;i++)
765 G4cout <<
"Vector x has " << x->size() <<
" points, while NUNIF = " << NUNIF <<
G4endl;
774 for (
size_t i=0;i<NUNIF-1;i++)
783 for (
G4int k=0;k<nip;k++)
787 pdfi->push_back(pdfk);
793 pdfih->push_back(pdfIK);
801 for (
G4int k=1;k<nip;k++)
804 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
805 sumi->push_back(next);
808 G4double lastIntegral = (*sumi)[sumi->size()-1];
809 area->push_back(lastIntegral);
812 for (
size_t k=0;k<sumi->size();k++)
813 (*sumi)[k] *= factor;
816 if ((*pdfi)[0] < 1e-35)
817 (*pdfi)[0] = 1e-5*pdfmax;
818 if ((*pdfi)[pdfi->size()-1] < 1e-35)
819 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
822 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
823 G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
824 G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
825 G4double C_temp = 1.0+A_temp+B_temp;
834 a->push_back(A_temp);
835 b->push_back(B_temp);
836 c->push_back(C_temp);
848 for (
G4int k=0;k<nip;k++)
851 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
852 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
853 if (k == 0 || k == nip-1)
854 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
856 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
861 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
876 (*x)[x->size()-1] = q2max;
883 if (x->size() != NUNIF || a->size() != NUNIF ||
884 err->size() != NUNIF || area->size() != NUNIF)
887 ed <<
"Problem in building the Table for Sampling: array dimensions do not match" <<
G4endl;
888 G4Exception(
"G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
900 for (
size_t i=0;i<err->size()-2;i++)
903 if ((*err)[i] > maxError)
905 maxError = (*err)[i];
911 G4double newx = 0.5*((*x)[iErrMax]+(*x)[iErrMax+1]);
913 x->insert(x->begin()+iErrMax+1,newx);
915 area->insert(area->begin()+iErrMax+1,0.);
916 a->insert(a->begin()+iErrMax+1,0.);
917 b->insert(b->begin()+iErrMax+1,0.);
918 c->insert(c->begin()+iErrMax+1,0.);
919 err->insert(err->begin()+iErrMax+1,0.);
922 for (
size_t i=iErrMax;i<=iErrMax+1;i++)
929 G4double dxLocal = (*x)[i+1]-(*x)[i];
932 for (
G4int k=0;k<nip;k++)
936 pdfi->push_back(pdfk);
942 pdfih->push_back(pdfIK);
950 for (
G4int k=1;k<nip;k++)
953 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
954 sumi->push_back(next);
956 G4double lastIntegral = (*sumi)[sumi->size()-1];
957 (*area)[i] = lastIntegral;
961 for (
size_t k=0;k<sumi->size();k++)
962 (*sumi)[k] *= factor;
965 if ((*pdfi)[0] < 1e-35)
966 (*pdfi)[0] = 1e-5*pdfmax;
967 if ((*pdfi)[pdfi->size()-1] < 1e-35)
968 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
971 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
972 G4double B_temp = 1.0-1.0/(pli*pui*dxLocal*dxLocal);
973 G4double A_temp = (1.0/(pli*dxLocal))-1.0-B_temp;
974 G4double C_temp = 1.0+A_temp+B_temp;
995 for (
G4int k=0;k<nip;k++)
998 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
999 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1000 if (k == 0 || k == nip-1)
1001 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1003 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1008 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1021 }
while(x->size() < np);
1023 if (x->size() != np || a->size() != np ||
1024 err->size() != np || area->size() != np)
1026 G4Exception(
"G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
1028 "Problem in building the extended Table for Sampling: array dimensions do not match ");
1035 for (
size_t i=0;i<np-1;i++)
1039 for (
size_t i=0;i<np-1;i++)
1043 errMax =
std::max(errMax,(*err)[i]);
1049 for (
size_t i=0;i<np-1;i++)
1052 PAC->push_back(previous+(*area)[i]);
1054 (*PAC)[PAC->size()-1] = 1.;
1059 std::vector<size_t> *ITTL =
new std::vector<size_t>;
1060 std::vector<size_t> *ITTU =
new std::vector<size_t>;
1063 for (
size_t i=0;i<np;i++)
1071 for (
size_t i=1;i<(np-1);i++)
1075 for (
size_t j=(*ITTL)[i-1];j<np && !found;j++)
1077 if ((*PAC)[j] > ptst)
1085 (*ITTU)[ITTU->size()-2] = ITTU->size()-1;
1086 (*ITTU)[ITTU->size()-1] = ITTU->size()-1;
1087 (*ITTL)[ITTL->size()-1] = ITTU->size()-2;
1089 if (ITTU->size() != np || ITTU->size() != np)
1091 G4Exception(
"G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
1093 "Problem in building the Limit Tables for Sampling: array dimensions do not match");
1100 for (
size_t i=0;i<np;i++)
1102 theTable->
AddPoint((*x)[i],(*PAC)[i],(*a)[i],(*b)[i],(*ITTL)[i],(*ITTU)[i]);
1107 G4cout <<
"*************************************************************************" <<
1109 G4cout <<
"Sampling table for Penelope Rayleigh scattering in " << mat->
GetName() <<
G4endl;
1135 G4cout <<
"G4PenelopeRayleighModel::BuildPMaxTable" <<
G4endl;
1136 G4cout <<
"Going to instanziate the fPMaxTable !" <<
G4endl;
1138 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
1147 G4Exception(
"G4PenelopeRayleighModel::GetPMaxTable()",
1149 "SamplingTable is not properly instantiated");
1157 ed <<
"Sampling table for material " << mat->
GetName() <<
" not found";
1158 G4Exception(
"G4PenelopeRayleighModel::GetPMaxTable()",
1170 const size_t nip = 51;
1186 size_t lowerBound = 0;
1187 size_t upperBound = tablePoints-1;
1188 while (lowerBound <= upperBound)
1190 size_t midBin = (lowerBound + upperBound)/2;
1191 if( Qm2 < theTable->GetX(midBin))
1192 { upperBound = midBin-1; }
1194 { lowerBound = midBin+1; }
1204 for (
size_t k=0;k<nip;k++)
1208 (theTable->
GetX(upperBound+1)-Q1);
1213 if (std::fabs(con1) > 1.0e-16*std::fabs(con2))
1214 etap = con2*(1.0-std::sqrt(1.0-2.0*tau*con1/(con2*con2)))/con1;
1218 (1.0+(theA+theB*etap)*etap)*(1.0+(theA+theB*etap)*etap)/
1219 ((1.0-theB*etap*etap)*ci*(theTable->
GetX(upperBound+1)-Q1));
1220 fun->push_back(theFun);
1228 (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*CONS;
1229 sum->push_back(secondPoint);
1230 for (
size_t hh=2;hh<nip-1;hh++)
1233 G4double next = previous+(13.0*((*fun)[hh-1]+(*fun)[hh])-
1234 (*fun)[hh+1]-(*fun)[hh-2])*HCONS;
1235 sum->push_back(next);
1237 G4double last = (*sum)[nip-2]+(5.0*(*fun)[nip-1]+8.0*(*fun)[nip-2]-
1238 (*fun)[nip-3])*CONS;
1239 sum->push_back(last);
1240 thePMax = thePAC + (*sum)[sum->size()-1];
1251 thePMax = theTable->
GetPAC(0);
1258 fPMaxTable->insert(std::make_pair(mat,theVec));
1266 G4cout <<
"*****************************************************************" <<
G4endl;
1270 G4cout <<
"*****************************************************************" <<
G4endl;
std::vector< const G4Element * > G4ElementVector
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
static constexpr double mole
static constexpr double twopi
static constexpr double barn
static constexpr double cm2
static constexpr double keV
static constexpr double eV
static constexpr double g
static constexpr double GeV
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
const G4Material * GetMaterial() const
const G4ElementVector * GetElementVector() const
size_t GetNumberOfElements() const
const G4String & GetName() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4DataVector fLogQSquareGrid
G4double fIntrinsicLowEnergyLimit
std::map< const G4Material *, G4PenelopeSamplingData * > * fSamplingTable
G4PenelopeRayleighModel(const G4ParticleDefinition *p=nullptr, const G4String &processName="PenRayleigh")
G4DataVector fLogEnergyGridPMax
void GetPMaxTable(const G4Material *)
void DumpFormFactorTable(const G4Material *)
void BuildFormFactorTable(const G4Material *)
const G4ParticleDefinition * fParticle
G4ParticleChangeForGamma * fParticleChange
virtual ~G4PenelopeRayleighModel()
std::map< const G4Material *, G4PhysicsFreeVector * > * fLogFormFactorTable
void InitializeSamplingAlgorithm(const G4Material *)
G4double GetFSquared(const G4Material *, const G4double)
void SetParticle(const G4ParticleDefinition *)
G4double fIntrinsicHighEnergyLimit
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
static G4PhysicsFreeVector * fLogAtomicCrossSection[fMaxZ+1]
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
std::map< const G4Material *, G4PhysicsFreeVector * > * fPMaxTable
static G4PhysicsFreeVector * fAtomicFormFactor[fMaxZ+1]
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
G4double GetA(size_t index)
G4double GetPAC(size_t index)
size_t GetNumberOfStoredPoints()
void AddPoint(G4double x0, G4double pac0, G4double a0, G4double b0, size_t ITTL0, size_t ITTU0)
G4double GetX(size_t index)
G4double SampleValue(G4double rndm)
G4double GetB(size_t index)
void PutValue(const std::size_t index, const G4double e, const G4double value)
G4double GetLowEdgeEnergy(const std::size_t index) const
G4double Value(const G4double energy, std::size_t &lastidx) const
std::size_t GetVectorLength() const
void FillSecondDerivatives(const G4SplineType=G4SplineType::Base, const G4double dir1=0.0, const G4double dir2=0.0)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
void SetHighEnergyLimit(G4double)
G4ParticleChangeForGamma * GetParticleChangeForGamma()
G4double LowEnergyLimit() const
G4double HighEnergyLimit() const
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double energy(const ThreeVector &p, const G4double m)
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4Mutex PenelopeRayleighModelMutex