66const G4int G4PenelopeRayleighModelMI::fMaxZ;
75 fParticleChange(nullptr),fParticle(nullptr),fLogFormFactorTable(nullptr),fPMaxTable(nullptr),
76 fSamplingTable(nullptr),fMolInterferenceData(nullptr),fAngularFunction(nullptr), fKnownMaterials(nullptr),
77 fIsInitialised(false),fLocalTable(false),fIsMIActive(true)
79 fIntrinsicLowEnergyLimit = 100.0*eV;
80 fIntrinsicHighEnergyLimit = 100.0*GeV;
84 if (part) SetParticle(part);
100 G4double logfactor2 = logfactor1*10;
101 fLogEnergyGridPMax.push_back(logenergy);
103 if (logenergy < logtransitionenergy)
104 logenergy += logfactor1;
106 logenergy += logfactor2;
107 fLogEnergyGridPMax.push_back(logenergy);
108 }
while (logenergy < logmaxenergy);
117 for(
G4int i=0; i<=fMaxZ; ++i)
119 if(fLogAtomicCrossSection[i])
121 delete fLogAtomicCrossSection[i];
122 fLogAtomicCrossSection[i] =
nullptr;
124 if(fAtomicFormFactor[i])
126 delete fAtomicFormFactor[i];
127 fAtomicFormFactor[i] =
nullptr;
130 if (fMolInterferenceData) {
131 for (
auto& item : (*fMolInterferenceData))
132 if (item.second)
delete item.second;
133 delete fMolInterferenceData;
134 fMolInterferenceData =
nullptr;
138 delete fKnownMaterials;
139 fKnownMaterials =
nullptr;
141 if (fAngularFunction)
143 delete fAngularFunction;
144 fAngularFunction =
nullptr;
152void G4PenelopeRayleighModelMI::ClearTables()
154 if (fLogFormFactorTable) {
155 for (
auto& item : (*fLogFormFactorTable))
156 if (item.second)
delete item.second;
157 delete fLogFormFactorTable;
158 fLogFormFactorTable =
nullptr;
162 for (
auto& item : (*fPMaxTable))
163 if (item.second)
delete item.second;
165 fPMaxTable =
nullptr;
168 if (fSamplingTable) {
169 for (
auto& item : (*fSamplingTable))
170 if (item.second)
delete item.second;
171 delete fSamplingTable;
172 fSamplingTable =
nullptr;
183 if (fVerboseLevel > 3)
184 G4cout <<
"Calling G4PenelopeRayleighModelMI::Initialise()" <<
G4endl;
189 G4cout <<
"# Molecular Interference is " << (fIsMIActive ?
"ON" :
"OFF") <<
" #" <<
G4endl;
192 if (
IsMaster() && part == fParticle) {
198 if (globVerb > fVerboseLevel)
200 fVerboseLevel = globVerb;
202 G4cout <<
"Verbosity level of G4PenelopeRayleighModelMI set to " << fVerboseLevel <<
203 " from G4EmParameters()" <<
G4endl;
205 if (fVerboseLevel > 3)
206 G4cout <<
"Calling G4PenelopeRayleighModelMI::Initialise() [master]" <<
G4endl;
211 if (!fKnownMaterials)
212 fKnownMaterials =
new std::map<G4String,G4String>;
213 if (!fKnownMaterials->size())
214 LoadKnownMIFFMaterials();
215 if (!fAngularFunction)
219 CalculateThetaAndAngFun();
222 if (fIsMIActive && !fMolInterferenceData)
223 fMolInterferenceData =
new std::map<G4String,G4PhysicsFreeVector*>;
224 if (!fLogFormFactorTable)
225 fLogFormFactorTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
227 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
229 fSamplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
240 G4int iZ = theElementVector->at(j)->GetZasInt();
242 if (!fLogAtomicCrossSection[iZ])
247 if (fIsMIActive && !fMolInterferenceData->count(material->
GetName()))
248 ReadMolInterferenceData(material->
GetName());
251 if (!fLogFormFactorTable->count(material))
252 BuildFormFactorTable(material);
255 if (!(fSamplingTable->count(material)))
256 InitializeSamplingAlgorithm(material);
259 if (!fPMaxTable->count(material))
260 GetPMaxTable(material);
263 if (fVerboseLevel > 1) {
275 fIsInitialised =
true;
283 if (fVerboseLevel > 3)
284 G4cout <<
"Calling G4PenelopeRayleighModelMI::InitialiseLocal()" <<
G4endl;
288 if (part == fParticle) {
295 for(
G4int i=0; i<=fMaxZ; ++i)
297 fLogAtomicCrossSection[i] = theModel->fLogAtomicCrossSection[i];
298 fAtomicFormFactor[i] = theModel->fAtomicFormFactor[i];
300 fMolInterferenceData = theModel->fMolInterferenceData;
301 fLogFormFactorTable = theModel->fLogFormFactorTable;
302 fPMaxTable = theModel->fPMaxTable;
303 fSamplingTable = theModel->fSamplingTable;
304 fKnownMaterials = theModel->fKnownMaterials;
305 fAngularFunction = theModel->fAngularFunction;
308 fLogQSquareGrid = theModel->fLogQSquareGrid;
311 fVerboseLevel = theModel->fVerboseLevel;
330 if (fVerboseLevel > 3)
331 G4cout <<
"Calling CrossSectionPerAtom() of G4PenelopeRayleighModelMI" <<
G4endl;
334 if (!fLogAtomicCrossSection[iZ]) {
337 if (fVerboseLevel > 0) {
340 ed <<
"Unable to retrieve the cross section table for Z=" << iZ <<
G4endl;
341 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
342 G4Exception(
"G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom()",
356 ed <<
"Unable to find Z=" << iZ <<
" in the atomic cross section table" <<
G4endl;
357 G4Exception(
"G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom()",
364 cross =
G4Exp(logXS);
366 if (fVerboseLevel > 2) {
367 G4cout <<
"Rayleigh cross section at " << energy/keV <<
" keV for Z="
368 << Z <<
" = " << cross/barn <<
" barn" <<
G4endl;
375void G4PenelopeRayleighModelMI::CalculateThetaAndAngFun()
378 for(
G4int k=0; k<fNtheta; k++) {
380 G4double value = (1+std::cos(theta)*std::cos(theta))*std::sin(theta);
381 fAngularFunction->
PutValue(k,theta,value);
382 if (fVerboseLevel > 3)
383 G4cout <<
"theta[" << k <<
"]: " << fAngularFunction->
Energy(k)
384 <<
", angFun[" << k <<
"]: " << (*fAngularFunction)[k] <<
G4endl;
395 x = 1./
lambda*std::sin(angle/2.);
396 q = 2.*h_Planck*x/(electron_mass_c2/c_light);
398 if (fVerboseLevel > 3) {
400 <<
", x: " << x*nm <<
", q: " << q <<
G4endl;
416 static G4bool amInAUnitTest =
false;
419 amInAUnitTest =
true;
421 ed <<
"The ProductionCuts table is empty " <<
G4endl;
422 ed <<
"This should happen only in Unit Tests" <<
G4endl;
423 G4Exception(
"G4PenelopeRayleighModelMI::CrossSectionPerVolume()",
434 G4int iZ = theElementVector->at(j)->GetZasInt();
435 if (!fLogAtomicCrossSection[iZ]) {
440 ReadMolInterferenceData(matname);
441 if (!fLogFormFactorTable->count(material))
442 BuildFormFactorTable(material);
443 if (!(fSamplingTable->count(material)))
444 InitializeSamplingAlgorithm(material);
445 if (!fPMaxTable->count(material))
446 GetPMaxTable(material);
448 G4bool useMIFF = fIsMIActive && (fMolInterferenceData->count(matname) || matname.find(
"MedMat") != std::string::npos);
451 if (fVerboseLevel > 2)
452 G4cout <<
"Rayleigh CS of: " << matname <<
" calculated through CSperAtom!" <<
G4endl;
457 if (fVerboseLevel > 2)
458 G4cout <<
"Rayleigh CS of: " << matname
459 <<
" calculated through integration of the DCS" <<
G4endl;
471 if (crystalExtension != 0) {
472 G4cout <<
"The material has a crystalline structure, a dedicated diffraction model is used!" <<
G4endl;
484 std::vector<G4double> *StoichiometricFactors =
new std::vector<G4double>;
485 for (std::size_t i=0;i<nElements;++i) {
486 G4double fraction = fractionVector[i];
487 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
488 StoichiometricFactors->push_back(fraction/atomicWeigth);
490 G4double MaxStoichiometricFactor = 0.;
491 for (std::size_t i=0;i<nElements;++i) {
492 if ((*StoichiometricFactors)[i] > MaxStoichiometricFactor)
493 MaxStoichiometricFactor = (*StoichiometricFactors)[i];
495 for (std::size_t i=0;i<nElements;++i) {
496 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
501 for (std::size_t i=0;i<nElements;++i)
502 atPerMol += (*StoichiometricFactors)[i];
504 if (atPerMol) moleculeDensity = atomDensity/atPerMol;
506 if (fVerboseLevel > 2)
507 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
" atoms "
508 <<
"per molecule and " << moleculeDensity/(cm*cm*cm) <<
" molecule/cm3" <<
G4endl;
512 for (std::size_t i=0;i<nElements;++i)
513 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
515 if (fVerboseLevel > 2)
516 G4cout <<
"Molecular weight of " << matname <<
": " << MolWeight <<
" g/mol" <<
G4endl;
519 for (
G4int k=0; k<fNtheta; k++) {
521 G4double F2 = GetFSquared(material,CalculateQSquared(theta,energy));
522 IntegrandFun[k] = (*fAngularFunction)[k]*F2;
525 G4double constant = pi*classic_electr_radius*classic_electr_radius;
526 cs = constant*IntegrateFun(IntegrandFun,fNtheta,fDTheta);
529 G4double csvolume = cs*moleculeDensity;
532 if (fVerboseLevel > 2)
533 G4cout <<
"Rayleigh CS of " << matname <<
" at " << energy/keV
534 <<
" keV: " << cs/barn <<
" barn"
535 <<
", mean free path: " << 1./csvolume/mm <<
" mm" <<
G4endl;
537 delete StoichiometricFactors;
544void G4PenelopeRayleighModelMI::BuildFormFactorTable(
const G4Material* material)
546 if (fVerboseLevel > 3)
547 G4cout <<
"Calling BuildFormFactorTable() of G4PenelopeRayleighModelMI" <<
G4endl;
555 std::vector<G4double> *StoichiometricFactors =
new std::vector<G4double>;
556 for (std::size_t i=0;i<nElements;++i) {
557 G4double fraction = fractionVector[i];
558 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
559 StoichiometricFactors->push_back(fraction/atomicWeigth);
561 G4double MaxStoichiometricFactor = 0.;
562 for (std::size_t i=0;i<nElements;++i) {
563 if ((*StoichiometricFactors)[i] > MaxStoichiometricFactor)
564 MaxStoichiometricFactor = (*StoichiometricFactors)[i];
566 if (MaxStoichiometricFactor<1e-16) {
568 ed <<
"Inconsistent data of atomic composition for " << material->
GetName() <<
G4endl;
569 G4Exception(
"G4PenelopeRayleighModelMI::BuildFormFactorTable()",
572 for (std::size_t i=0;i<nElements;++i)
573 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
577 for (std::size_t i=0;i<nElements;++i)
578 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
591 G4MIData* dataMI = GetMIData(material);
596 if (fIsMIActive && aFileNameFF !=
"") {
598 G4cout <<
"Read MIFF for " << matname <<
" from custom file: " << aFileNameFF <<
G4endl;
600 ReadMolInterferenceData(matname,aFileNameFF);
603 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
614 if (fIsMIActive && matname.find(
"MedMat") != std::string::npos) {
616 G4cout <<
"Build MIFF from components for " << matname <<
G4endl;
619 G4int ki, kf=6, ktot=19;
621 G4String compstring = matname.substr(kf+1, ktot);
622 for (std::size_t j=0; j<4; ++j) {
625 compstring = matname.substr(ki, 4);
626 comp[j] = atof(compstring.c_str());
627 if (fVerboseLevel > 2)
628 G4cout <<
" -- MedMat comp[" << j+1 <<
"]: " << comp[j] <<
G4endl;
633 G4String excep =
"G4LEDATA environment variable not set!";
634 G4Exception(
"G4PenelopeRayleighModelMI::BuildFormFactorTable()",
638 if (!fMolInterferenceData->count(
"Fat_MI"))
639 ReadMolInterferenceData(
"Fat_MI");
642 if (!fMolInterferenceData->count(
"Water_MI"))
643 ReadMolInterferenceData(
"Water_MI");
646 if (!fMolInterferenceData->count(
"BoneMatrix_MI"))
647 ReadMolInterferenceData(
"BoneMatrix_MI");
650 if (!fMolInterferenceData->count(
"Mineral_MI"))
651 ReadMolInterferenceData(
"Mineral_MI");
655 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
662 ff2 = comp[0]*ffat*ffat+comp[1]*fwater*fwater+
663 comp[2]*fbonematrix*fbonematrix+comp[3]*fmineral*fmineral;
665 if (ff2) theFFVec->
PutValue(k,fLogQSquareGrid[k],
G4Log(ff2));
669 else if (fIsMIActive && fMolInterferenceData->count(matname)) {
671 G4cout <<
"Read MIFF from database " << matname <<
G4endl;
673 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
678 if (ff2) theFFVec->
PutValue(k,fLogQSquareGrid[k],
G4Log(ff2));
684 G4cout <<
"FF of " << matname <<
" calculated according to the IAM" <<
G4endl;
685 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
687 for (std::size_t i=0;i<nElements;++i) {
688 G4int iZ = (*elementVector)[i]->GetZasInt();
692 ff2 += f*f*(*StoichiometricFactors)[i];
694 if (ff2) theFFVec->
PutValue(k,fLogQSquareGrid[k],
G4Log(ff2));
699 fLogFormFactorTable->insert(std::make_pair(material,theFFVec));
701 if (fVerboseLevel > 3)
703 delete StoichiometricFactors;
729 if (fVerboseLevel > 3)
730 G4cout <<
"Calling SamplingSecondaries() of G4PenelopeRayleighModelMI" <<
G4endl;
734 if (photonEnergy0 <= fIntrinsicLowEnergyLimit) {
747 if (!fPMaxTable || !fSamplingTable || !fLogFormFactorTable) {
751 if (!fLogFormFactorTable)
752 fLogFormFactorTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
754 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
756 fSamplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
757 if (fIsMIActive && !fMolInterferenceData)
758 fMolInterferenceData =
new std::map<G4String,G4PhysicsFreeVector*>;
761 if (!fSamplingTable->count(theMat)) {
764 if (fVerboseLevel > 0) {
767 ed <<
"Unable to find the fSamplingTable data for " <<
769 ed <<
"This can happen only in Unit Tests" <<
G4endl;
770 G4Exception(
"G4PenelopeRayleighModelMI::SampleSecondaries()",
777 G4int iZ = theElementVector->at(j)->GetZasInt();
778 if (!fLogAtomicCrossSection[iZ]) {
787 if (!fLogFormFactorTable->count(theMat))
788 BuildFormFactorTable(theMat);
791 if (!(fSamplingTable->count(theMat)))
792 InitializeSamplingAlgorithm(theMat);
795 if (!fPMaxTable->count(theMat))
796 GetPMaxTable(theMat);
807 G4double qmax = 2.0*photonEnergy0/electron_mass_c2;
814 G4double G = 0.5*(1+cosTheta*cosTheta);
821 G4double LastQ2inTheTable = theDataTable->
GetX(nData-1);
822 G4double q2max = std::min(qmax*qmax,LastQ2inTheTable);
839 cosTheta = 1.0-2.0*xx/q2max;
840 G4double G = 0.5*(1+cosTheta*cosTheta);
846 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
850 G4double dirX = sinTheta*std::cos(phi);
851 G4double dirY = sinTheta*std::sin(phi);
857 photonDirection1.
rotateUz(photonDirection0);
866void G4PenelopeRayleighModelMI::ReadDataFile(
const G4int Z)
868 if (fVerboseLevel > 2) {
869 G4cout <<
"G4PenelopeRayleighModelMI::ReadDataFile()" <<
G4endl;
870 G4cout <<
"Going to read Rayleigh data files for Z=" << Z <<
G4endl;
875 G4String excep =
"G4LEDATA environment variable not set!";
876 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
882 std::ostringstream ost;
884 ost << path <<
"/penelope/rayleigh/pdgra" << Z <<
".p08";
886 ost << path <<
"/penelope/rayleigh/pdgra0" << Z <<
".p08";
887 std::ifstream file(ost.str().c_str());
889 if (!file.is_open()) {
891 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
896 std::size_t nPoints = 0;
897 file >> readZ >> nPoints;
899 if (readZ != Z || nPoints <= 0 || nPoints >= 5000) {
901 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
902 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
909 for (std::size_t i=0;i<nPoints;++i) {
910 file >> ene >> f1 >> f2 >> xs;
915 if (file.eof() && i != (nPoints-1)) {
917 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
918 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
919 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
926 std::ostringstream ost2;
927 ost2 << path <<
"/penelope/rayleigh/MIFF/qext.dat";
928 file.open(ost2.str().c_str());
930 if (!file.is_open()) {
932 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
936 if (!fLogQSquareGrid.size()) {
942 for (std::size_t i=0;i<nPoints;++i) {
944 fLogQSquareGrid.push_back(2.0*
G4Log(qext));
950 std::ostringstream ost3;
952 ost3 << path <<
"/penelope/rayleigh/pdaff" << Z <<
".p08";
954 ost3 << path <<
"/penelope/rayleigh/pdaff0" << Z <<
".p08";
955 file.open(ost3.str().c_str());
957 if (!file.is_open()) {
959 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
963 file >> readZ >> nPoints;
965 if (readZ != Z || nPoints <= 0 || nPoints >= 5000) {
967 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
968 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
975 for (std::size_t i=0;i<nPoints;++i) {
976 file >> q >> ff >> incoh;
977 fAtomicFormFactor[Z]->
PutValue(i,q,ff);
978 if (file.eof() && i != (nPoints-1)) {
980 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
981 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
982 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
992void G4PenelopeRayleighModelMI::ReadMolInterferenceData(
const G4String& matname,
995 if (fVerboseLevel > 2) {
996 G4cout <<
"G4PenelopeRayleighModelMI::ReadMolInterferenceData() for material " <<
999 G4bool isLocalFile = (FFfilename !=
"NULL");
1003 G4String excep =
"G4LEDATA environment variable not set!";
1004 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1009 if (!(fKnownMaterials->count(matname)) && !isLocalFile)
1012 G4String aFileName = (isLocalFile) ? FFfilename : fKnownMaterials->find(matname)->second;
1015 if (aFileName !=
"") {
1016 if (fVerboseLevel > 2)
1017 G4cout <<
"ReadMolInterferenceData(). Read material: " << matname <<
", filename: " <<
1019 (isLocalFile ?
"(local)" :
"(database)") <<
G4endl;
1021 std::ostringstream ostIMFF;
1023 ostIMFF << aFileName;
1025 ostIMFF << path <<
"/penelope/rayleigh/MIFF/" << aFileName;
1026 file.open(ostIMFF.str().c_str());
1028 if (!file.is_open()) {
1030 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1036 std::size_t nPoints = 0;
1038 while (file.good()) {
1044 if (fVerboseLevel > 3)
1048 file.open(ostIMFF.str().c_str());
1051 for (std::size_t i=0; i<nPoints; ++i) {
1058 if (file.eof() && i != (nPoints-1)) {
1060 ed <<
"Corrupted data file" <<
G4endl;
1061 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
1062 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1066 if (!fMolInterferenceData) {
1067 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1069 "Unable to allocate the Molecular Interference data table");
1074 fMolInterferenceData->insert(std::make_pair(matname,theFFVec));
1088 G4double logQSquared = (QSquared>1e-10) ?
G4Log(QSquared) : -23.;
1090 G4double maxlogQ2 = fLogQSquareGrid[fLogQSquareGrid.size()-1];
1097 ed <<
"Unable to retrieve F squared table for " << mat->
GetName() <<
G4endl;
1098 G4Exception(
"G4PenelopeRayleighModelMI::GetFSquared()",
1103 if (logQSquared < -20) {
1107 else if (logQSquared > maxlogQ2)
1115 if (fVerboseLevel > 3) {
1117 G4cout <<
"Q^2 = " << QSquared <<
" (units of 1/(m_e*c)); F^2 = " << f2 <<
G4endl;
1124void G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm(
const G4Material* mat)
1128 const std::size_t np = 150;
1129 for (std::size_t i=1;i<fLogQSquareGrid.size();++i)
1132 if (GetFSquared(mat,Q2) > 1e-35)
1134 q2max =
G4Exp(fLogQSquareGrid[i-1]);
1137 std::size_t nReducedPoints = np/4;
1142 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1144 "Too few points to initialize the sampling algorithm");
1146 if (q2min > (q2max-1e-10))
1148 G4cout <<
"q2min= " << q2min <<
" q2max= " << q2max <<
G4endl;
1149 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1151 "Too narrow grid to initialize the sampling algorithm");
1163 std::size_t NUNIF = std::min(std::max(((std::size_t)8),nReducedPoints),np/2);
1164 const G4int nip = 51;
1167 x->push_back(q2min);
1168 for (std::size_t i=1;i<NUNIF-1;++i)
1173 x->push_back(q2max);
1175 if (fVerboseLevel> 3)
1176 G4cout <<
"Vector x has " << x->size() <<
" points, while NUNIF = " << NUNIF <<
G4endl;
1185 for (std::size_t i=0;i<NUNIF-1;++i)
1194 for (
G4int k=0;k<nip;k++)
1197 G4double pdfk = std::max(GetFSquared(mat,xik),0.);
1198 pdfi->push_back(pdfk);
1199 pdfmax = std::max(pdfmax,pdfk);
1203 G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
1204 pdfih->push_back(pdfIK);
1205 pdfmax = std::max(pdfmax,pdfIK);
1211 sumi->push_back(0.);
1212 for (
G4int k=1;k<nip;k++)
1215 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
1216 sumi->push_back(next);
1219 G4double lastIntegral = (*sumi)[sumi->size()-1];
1220 area->push_back(lastIntegral);
1222 G4double factor = 1.0/lastIntegral;
1223 for (std::size_t k=0;k<sumi->size();++k)
1224 (*sumi)[k] *= factor;
1227 if ((*pdfi)[0] < 1e-35)
1228 (*pdfi)[0] = 1e-5*pdfmax;
1229 if ((*pdfi)[pdfi->size()-1] < 1e-35)
1230 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
1233 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
1234 G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
1235 G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
1236 G4double C_temp = 1.0+A_temp+B_temp;
1245 a->push_back(A_temp);
1246 b->push_back(B_temp);
1247 c->push_back(C_temp);
1259 for (
G4int k=0;k<nip;k++)
1262 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
1263 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1264 if (k == 0 || k == nip-1)
1265 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1267 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1272 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1288 (*x)[x->size()-1] = q2max;
1293 area->push_back(0.);
1295 if (x->size() != NUNIF || a->size() != NUNIF ||
1296 err->size() != NUNIF || area->size() != NUNIF)
1299 ed <<
"Problem in building the Table for Sampling: array dimensions do not match" <<
G4endl;
1300 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1311 std::size_t iErrMax = 0;
1312 for (std::size_t i=0;i<err->size()-2;++i)
1315 if ((*err)[i] > maxError)
1317 maxError = (*err)[i];
1323 G4double newx = 0.5*((*x)[iErrMax]+(*x)[iErrMax+1]);
1325 x->insert(x->begin()+iErrMax+1,newx);
1327 area->insert(area->begin()+iErrMax+1,0.);
1328 a->insert(a->begin()+iErrMax+1,0.);
1329 b->insert(b->begin()+iErrMax+1,0.);
1330 c->insert(c->begin()+iErrMax+1,0.);
1331 err->insert(err->begin()+iErrMax+1,0.);
1334 for (std::size_t i=iErrMax;i<=iErrMax+1;++i)
1341 G4double dxLocal = (*x)[i+1]-(*x)[i];
1344 for (
G4int k=0;k<nip;k++)
1347 G4double pdfk = std::max(GetFSquared(mat,xik),0.);
1348 pdfi->push_back(pdfk);
1349 pdfmax = std::max(pdfmax,pdfk);
1353 G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
1354 pdfih->push_back(pdfIK);
1355 pdfmax = std::max(pdfmax,pdfIK);
1361 sumi->push_back(0.);
1362 for (
G4int k=1;k<nip;k++)
1365 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
1366 sumi->push_back(next);
1368 G4double lastIntegral = (*sumi)[sumi->size()-1];
1369 (*area)[i] = lastIntegral;
1372 G4double factor = 1.0/lastIntegral;
1373 for (std::size_t k=0;k<sumi->size();++k)
1374 (*sumi)[k] *= factor;
1377 if ((*pdfi)[0] < 1e-35)
1378 (*pdfi)[0] = 1e-5*pdfmax;
1379 if ((*pdfi)[pdfi->size()-1] < 1e-35)
1380 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
1383 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
1384 G4double B_temp = 1.0-1.0/(pli*pui*dxLocal*dxLocal);
1385 G4double A_temp = (1.0/(pli*dxLocal))-1.0-B_temp;
1386 G4double C_temp = 1.0+A_temp+B_temp;
1407 for (
G4int k=0;k<nip;k++)
1410 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
1411 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1412 if (k == 0 || k == nip-1)
1413 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1415 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1420 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1433 }
while(x->size() < np);
1435 if (x->size() != np || a->size() != np ||
1436 err->size() != np || area->size() != np)
1438 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1440 "Problem in building the extended Table for Sampling: array dimensions do not match ");
1447 for (std::size_t i=0;i<np-1;++i)
1451 for (std::size_t i=0;i<np-1;++i)
1455 errMax = std::max(errMax,(*err)[i]);
1461 for (std::size_t i=0;i<np-1;++i)
1464 PAC->push_back(previous+(*area)[i]);
1466 (*PAC)[PAC->size()-1] = 1.;
1471 std::vector<std::size_t> *ITTL =
new std::vector<std::size_t>;
1472 std::vector<std::size_t> *ITTU =
new std::vector<std::size_t>;
1475 for (std::size_t i=0;i<np;++i)
1483 for (std::size_t i=1;i<(np-1);++i)
1487 for (std::size_t j=(*ITTL)[i-1];j<np && !found;++j)
1489 if ((*PAC)[j] > ptst)
1497 (*ITTU)[ITTU->size()-2] = ITTU->size()-1;
1498 (*ITTU)[ITTU->size()-1] = ITTU->size()-1;
1499 (*ITTL)[ITTL->size()-1] = ITTU->size()-2;
1501 if (ITTU->size() != np || ITTU->size() != np)
1503 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1505 "Problem in building the Limit Tables for Sampling: array dimensions do not match");
1512 for (std::size_t i=0;i<np;++i)
1514 theTable->
AddPoint((*x)[i],(*PAC)[i],(*a)[i],(*b)[i],(*ITTL)[i],(*ITTU)[i]);
1516 if (fVerboseLevel > 2)
1518 G4cout <<
"*************************************************************************" <<
1520 G4cout <<
"Sampling table for Penelope Rayleigh scattering in " << mat->
GetName() <<
G4endl;
1523 fSamplingTable->insert(std::make_pair(mat,theTable));
1542void G4PenelopeRayleighModelMI::GetPMaxTable(
const G4Material* mat)
1546 G4cout <<
"G4PenelopeRayleighModelMI::BuildPMaxTable" <<
G4endl;
1547 G4cout <<
"Going to instanziate the fPMaxTable !" <<
G4endl;
1549 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
1552 if (fPMaxTable->count(mat))
1556 if (!fSamplingTable)
1558 G4Exception(
"G4PenelopeRayleighModelMI::GetPMaxTable()",
1560 "SamplingTable is not properly instantiated");
1565 if (!fSamplingTable->count(mat))
1568 ed <<
"Sampling table for material " << mat->
GetName() <<
" not found";
1569 G4Exception(
"G4PenelopeRayleighModelMI::GetPMaxTable()",
1577 std::size_t nOfEnergyPoints = fLogEnergyGridPMax.size();
1580 const std::size_t nip = 51;
1582 for (std::size_t ie=0;ie<fLogEnergyGridPMax.size();++ie)
1596 std::size_t lowerBound = 0;
1597 std::size_t upperBound = tablePoints-1;
1598 while (lowerBound <= upperBound)
1600 std::size_t midBin = (lowerBound + upperBound)/2;
1601 if( Qm2 < theTable->GetX(midBin))
1602 { upperBound = midBin-1; }
1604 { lowerBound = midBin+1; }
1614 for (std::size_t k=0;k<nip;++k)
1618 (theTable->
GetX(upperBound+1)-Q1);
1623 if (std::fabs(con1) > 1.0e-16*std::fabs(con2))
1624 etap = con2*(1.0-std::sqrt(1.0-2.0*tau*con1/(con2*con2)))/con1;
1628 (1.0+(theA+theB*etap)*etap)*(1.0+(theA+theB*etap)*etap)/
1629 ((1.0-theB*etap*etap)*ci*(theTable->
GetX(upperBound+1)-Q1));
1630 fun->push_back(theFun);
1638 (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*CONS;
1639 sum->push_back(secondPoint);
1640 for (std::size_t hh=2;hh<nip-1;++hh)
1643 G4double next = previous+(13.0*((*fun)[hh-1]+(*fun)[hh])-
1644 (*fun)[hh+1]-(*fun)[hh-2])*HCONS;
1645 sum->push_back(next);
1647 G4double last = (*sum)[nip-2]+(5.0*(*fun)[nip-1]+8.0*(*fun)[nip-2]-
1648 (*fun)[nip-3])*CONS;
1649 sum->push_back(last);
1650 thePMax = thePAC + (*sum)[sum->size()-1];
1661 thePMax = theTable->
GetPAC(0);
1665 theVec->
PutValue(ie,energy,thePMax);
1668 fPMaxTable->insert(std::make_pair(mat,theVec));
1676 G4cout <<
"*****************************************************************" <<
G4endl;
1677 G4cout <<
"G4PenelopeRayleighModelMI: Form Factor Table for " << mat->
GetName() <<
G4endl;
1680 G4cout <<
"*****************************************************************" <<
G4endl;
1681 if (!fLogFormFactorTable->count(mat))
1682 BuildFormFactorTable(mat);
1707void G4PenelopeRayleighModelMI::LoadKnownMIFFMaterials()
1709 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Fat_MI",
"FF_fat_Tartari2002.dat"));
1710 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Water_MI",
"FF_water_Tartari2002.dat"));
1711 fKnownMaterials->insert(std::pair<G4String,G4String>(
"BoneMatrix_MI",
"FF_bonematrix_Tartari2002.dat"));
1712 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Mineral_MI",
"FF_mineral_Tartari2002.dat"));
1713 fKnownMaterials->insert(std::pair<G4String,G4String>(
"adipose_MI",
"FF_adipose_Poletti2002.dat"));
1714 fKnownMaterials->insert(std::pair<G4String,G4String>(
"glandular_MI",
"FF_glandular_Poletti2002.dat"));
1715 fKnownMaterials->insert(std::pair<G4String,G4String>(
"breast5050_MI",
"FF_human_breast_Peplow1998.dat"));
1716 fKnownMaterials->insert(std::pair<G4String,G4String>(
"carcinoma_MI",
"FF_carcinoma_Kidane1999.dat"));
1717 fKnownMaterials->insert(std::pair<G4String,G4String>(
"muscle_MI",
"FF_pork_muscle_Peplow1998.dat"));
1718 fKnownMaterials->insert(std::pair<G4String,G4String>(
"kidney_MI",
"FF_pork_kidney_Peplow1998.dat"));
1719 fKnownMaterials->insert(std::pair<G4String,G4String>(
"liver_MI",
"FF_pork_liver_Peplow1998.dat"));
1720 fKnownMaterials->insert(std::pair<G4String,G4String>(
"heart_MI",
"FF_pork_heart_Peplow1998.dat"));
1721 fKnownMaterials->insert(std::pair<G4String,G4String>(
"blood_MI",
"FF_beef_blood_Peplow1998.dat"));
1722 fKnownMaterials->insert(std::pair<G4String,G4String>(
"grayMatter_MI",
"FF_gbrain_DeFelici2008.dat"));
1723 fKnownMaterials->insert(std::pair<G4String,G4String>(
"whiteMatter_MI",
"FF_wbrain_DeFelici2008.dat"));
1724 fKnownMaterials->insert(std::pair<G4String,G4String>(
"bone_MI",
"FF_bone_King2011.dat"));
1725 fKnownMaterials->insert(std::pair<G4String,G4String>(
"FatLowX_MI",
"FF_fat_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1726 fKnownMaterials->insert(std::pair<G4String,G4String>(
"BoneMatrixLowX_MI",
"FF_bonematrix_Tartari2002_joint_lowXdata.dat"));
1727 fKnownMaterials->insert(std::pair<G4String,G4String>(
"PMMALowX_MI",
"FF_PMMA_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1728 fKnownMaterials->insert(std::pair<G4String,G4String>(
"dryBoneLowX_MI",
"FF_drybone_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1729 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS30-70_MI",
"FF_CIRS30-70_Poletti2002.dat"));
1730 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS50-50_MI",
"FF_CIRS50-50_Poletti2002.dat"));
1731 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS70-30_MI",
"FF_CIRS70-30_Poletti2002.dat"));
1732 fKnownMaterials->insert(std::pair<G4String,G4String>(
"RMI454_MI",
"FF_RMI454_Poletti2002.dat"));
1733 fKnownMaterials->insert(std::pair<G4String,G4String>(
"PMMA_MI",
"FF_PMMA_Tartari2002.dat"));
1734 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Lexan_MI",
"FF_lexan_Peplow1998.dat"));
1735 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Kapton_MI",
"FF_kapton_Peplow1998.dat"));
1736 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Nylon_MI",
"FF_nylon_Kosanetzky1987.dat"));
1737 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Polyethylene_MI",
"FF_polyethylene_Kosanetzky1987.dat"));
1738 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Polystyrene_MI",
"FF_polystyrene_Kosanetzky1987.dat"));
1739 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Formaline_MI",
"FF_formaline_Peplow1998.dat"));
1740 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Acetone_MI",
"FF_acetone_Cozzini2010.dat"));
1741 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Hperoxide_MI",
"FF_Hperoxide_Cozzini2010.dat"));
1749 for (
G4int k=0; k<
n-1; k++) {
1750 integral += (y[k]+y[k+1]);
1752 integral *= dTheta*0.5;
std::vector< const G4Element * > G4ElementVector
const char * G4FindDataDir(const char *)
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)
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
static G4EmParameters * Instance()
G4VMaterialExtension * RetrieveExtension(const G4String &name)
const G4String & GetFilenameFF()
const G4Material * GetMaterial() const
const G4ElementVector * GetElementVector() const
G4double GetTotNbOfAtomsPerVolume() const
virtual G4bool IsExtended() const
const G4double * GetFractionVector() const
std::size_t GetNumberOfElements() const
const G4String & GetName() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0., G4double maxEnergy=DBL_MAX) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
void DumpFormFactorTable(const G4Material *)
G4PenelopeRayleighModelMI(const G4ParticleDefinition *p=nullptr, const G4String &processName="PenRayleighMI")
virtual ~G4PenelopeRayleighModelMI()
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 Energy(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
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
G4double HighEnergyLimit() const
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double energy(const ThreeVector &p, const G4double m)