71 fParticleChange(nullptr),fParticle(nullptr),isInitialised(false),logAtomicCrossSection(nullptr),
72 atomicFormFactor(nullptr),MolInterferenceData(nullptr),logFormFactorTable(nullptr),
73 pMaxTable(nullptr),samplingTable(nullptr),fLocalTable(false),fIsMIActive(true),
74 angularFunction(nullptr), fKnownMaterials(nullptr)
76 fIntrinsicLowEnergyLimit = 100.0*eV;
77 fIntrinsicHighEnergyLimit = 100.0*GeV;
81 if (part) SetParticle(part);
98 logEnergyGridPMax.push_back(logenergy);
100 if (logenergy < logtransitionenergy)
101 logenergy += logfactor1;
103 logenergy += logfactor2;
104 logEnergyGridPMax.push_back(logenergy);
105 }
while (logenergy < logmaxenergy);
114 if (logAtomicCrossSection) {
115 for (
auto& item : (*logAtomicCrossSection))
116 if (item.second)
delete item.second;
117 delete logAtomicCrossSection;
118 logAtomicCrossSection =
nullptr;
121 if (atomicFormFactor) {
122 for (
auto& item : (*atomicFormFactor))
123 if (item.second)
delete item.second;
124 delete atomicFormFactor;
125 atomicFormFactor =
nullptr;
128 if (MolInterferenceData) {
129 for (
auto& item : (*MolInterferenceData))
130 if (item.second)
delete item.second;
131 delete MolInterferenceData;
132 MolInterferenceData =
nullptr;
137 delete fKnownMaterials;
138 fKnownMaterials =
nullptr;
143 delete angularFunction;
144 angularFunction =
nullptr;
154void G4PenelopeRayleighModelMI::ClearTables()
163 if (logFormFactorTable) {
164 for (
auto& item : (*logFormFactorTable))
165 if (item.second)
delete item.second;
166 delete logFormFactorTable;
167 logFormFactorTable =
nullptr;
171 for (
auto& item : (*pMaxTable))
172 if (item.second)
delete item.second;
178 for (
auto& item : (*samplingTable))
179 if (item.second)
delete item.second;
180 delete samplingTable;
181 samplingTable =
nullptr;
192 if (verboseLevel > 3)
193 G4cout <<
"Calling G4PenelopeRayleighModelMI::Initialise()" <<
G4endl;
199 G4cout <<
"# Molecular Interference is " << (fIsMIActive ?
"ON" :
"OFF") <<
" #" <<
G4endl;
202 if (
IsMaster() && part == fParticle) {
208 if (globVerb > verboseLevel)
210 verboseLevel = globVerb;
212 G4cout <<
"Verbosity level of G4PenelopeRayleighModelMI set to " << verboseLevel <<
213 " from G4EmParameters()" <<
G4endl;
216 if (verboseLevel > 3)
217 G4cout <<
"Calling G4PenelopeRayleighModelMI::Initialise() [master]" <<
G4endl;
222 if (!fKnownMaterials)
223 fKnownMaterials =
new std::map<G4String,G4String>;
224 if (!fKnownMaterials->size())
225 LoadKnownMIFFMaterials();
226 if (!angularFunction)
230 CalculateThetaAndAngFun();
237 if (!logAtomicCrossSection)
238 logAtomicCrossSection =
new std::map<G4int,G4PhysicsFreeVector*>;
240 if (!atomicFormFactor)
241 atomicFormFactor =
new std::map<G4int,G4PhysicsFreeVector*>;
243 if (fIsMIActive && !MolInterferenceData)
244 MolInterferenceData =
new std::map<G4String,G4PhysicsFreeVector*>;
246 if (!logFormFactorTable)
247 logFormFactorTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
250 pMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
253 samplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
264 G4int iZ = theElementVector->at(j)->GetZasInt();
266 if (!logAtomicCrossSection->count(iZ))
271 if (fIsMIActive && !MolInterferenceData->count(material->
GetName()))
272 ReadMolInterferenceData(material->
GetName());
275 if (!logFormFactorTable->count(material))
276 BuildFormFactorTable(material);
279 if (!(samplingTable->count(material)))
280 InitializeSamplingAlgorithm(material);
283 if (!pMaxTable->count(material))
284 GetPMaxTable(material);
287 if (verboseLevel > 1) {
300 isInitialised =
true;
308 if (verboseLevel > 3)
309 G4cout <<
"Calling G4PenelopeRayleighModelMI::InitialiseLocal()" <<
G4endl;
313 if (part == fParticle) {
320 logAtomicCrossSection = theModel->logAtomicCrossSection;
321 atomicFormFactor = theModel->atomicFormFactor;
322 MolInterferenceData = theModel->MolInterferenceData;
323 logFormFactorTable = theModel->logFormFactorTable;
324 pMaxTable = theModel->pMaxTable;
325 samplingTable = theModel->samplingTable;
326 fKnownMaterials = theModel->fKnownMaterials;
327 angularFunction = theModel->angularFunction;
330 logQSquareGrid = theModel->logQSquareGrid;
333 verboseLevel = theModel->verboseLevel;
354 if (verboseLevel > 3)
355 G4cout <<
"Calling CrossSectionPerAtom() of G4PenelopeRayleighModelMI" <<
G4endl;
361 if (!logAtomicCrossSection) {
365 logAtomicCrossSection =
new std::map<G4int,G4PhysicsFreeVector*>;
369 if (!logAtomicCrossSection->count(iZ)) {
372 if (verboseLevel > 0) {
375 ed <<
"Unable to retrieve the cross section table for Z=" << iZ <<
G4endl;
376 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
377 G4Exception(
"G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom()",
393 ed <<
"Unable to find Z=" << iZ <<
" in the atomic cross section table" <<
G4endl;
394 G4Exception(
"G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom()",
401 cross =
G4Exp(logXS);
403 if (verboseLevel > 2) {
404 G4cout <<
"Rayleigh cross section at " << energy/keV <<
" keV for Z="
405 << Z <<
" = " << cross/barn <<
" barn" <<
G4endl;
413void G4PenelopeRayleighModelMI::CalculateThetaAndAngFun()
417 for(
G4int k=0; k<Ntheta; k++) {
419 G4double value = (1+std::cos(theta)*std::cos(theta))*std::sin(theta);
420 angularFunction->
PutValue(k,theta,value);
421 if (verboseLevel > 3)
422 G4cout <<
"theta[" << k <<
"]: " << angularFunction->
Energy(k)
423 <<
", angFun[" << k <<
"]: " << (*angularFunction)[k] <<
G4endl;
434 x = 1./
lambda*std::sin(angle/2.);
435 q = 2.*h_Planck*x/(electron_mass_c2/c_light);
437 if (verboseLevel > 3) {
439 <<
", x: " << x*nm <<
", q: " << q <<
G4endl;
457 static G4bool amInAUnitTest =
false;
460 amInAUnitTest =
true;
462 ed <<
"The ProductionCuts table is empty " <<
G4endl;
463 ed <<
"This should happen only in Unit Tests" <<
G4endl;
464 G4Exception(
"G4PenelopeRayleighModelMI::CrossSectionPerVolume()",
475 G4int iZ = theElementVector->at(j)->GetZasInt();
476 if (!logAtomicCrossSection->count(iZ)) {
481 ReadMolInterferenceData(matname);
482 if (!logFormFactorTable->count(material))
483 BuildFormFactorTable(material);
484 if (!(samplingTable->count(material)))
485 InitializeSamplingAlgorithm(material);
486 if (!pMaxTable->count(material))
487 GetPMaxTable(material);
490 G4bool useMIFF = fIsMIActive && (MolInterferenceData->count(matname) || matname.find(
"MedMat") != std::string::npos);
493 if (verboseLevel > 2)
494 G4cout <<
"Rayleigh CS of: " << matname <<
" calculated through CSperAtom!" <<
G4endl;
499 if (verboseLevel > 2)
500 G4cout <<
"Rayleigh CS of: " << matname
501 <<
" calculated through integration of the DCS" <<
G4endl;
516 if (crystalExtension != 0) {
517 G4cout <<
"The material has a crystalline structure, a dedicated diffraction model is used!" <<
G4endl;
532 std::vector<G4double> *StoichiometricFactors =
new std::vector<G4double>;
533 for (
G4int i=0;i<nElements;i++) {
534 G4double fraction = fractionVector[i];
535 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
536 StoichiometricFactors->push_back(fraction/atomicWeigth);
538 G4double MaxStoichiometricFactor = 0.;
539 for (
G4int i=0;i<nElements;i++) {
540 if ((*StoichiometricFactors)[i] > MaxStoichiometricFactor)
541 MaxStoichiometricFactor = (*StoichiometricFactors)[i];
543 for (
G4int i=0;i<nElements;i++) {
544 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
550 for (
G4int i=0;i<nElements;i++)
551 atPerMol += (*StoichiometricFactors)[i];
553 if (atPerMol) moleculeDensity = atomDensity/atPerMol;
555 if (verboseLevel > 2)
556 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
" atoms "
557 <<
"per molecule and " << moleculeDensity/(cm*cm*cm) <<
" molecule/cm3" <<
G4endl;
561 for (
G4int i=0;i<nElements;i++)
562 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
564 if (verboseLevel > 2)
565 G4cout <<
"Molecular weight of " << matname <<
": " << MolWeight <<
" g/mol" <<
G4endl;
568 for (
G4int k=0; k<Ntheta; k++) {
570 G4double F2 = GetFSquared(material,CalculateQSquared(theta,energy));
571 IntegrandFun[k] = (*angularFunction)[k]*F2;
574 G4double constant = pi*classic_electr_radius*classic_electr_radius;
575 cs = constant*IntegrateFun(IntegrandFun,Ntheta,fDTheta);
578 G4double csvolume = cs*moleculeDensity;
582 if (verboseLevel > 2)
583 G4cout <<
"Rayleigh CS of " << matname <<
" at " << energy/keV
584 <<
" keV: " << cs/barn <<
" barn"
585 <<
", mean free path: " << 1./csvolume/mm <<
" mm" <<
G4endl;
588 delete StoichiometricFactors;
596void G4PenelopeRayleighModelMI::BuildFormFactorTable(
const G4Material* material)
598 if (verboseLevel > 3)
599 G4cout <<
"Calling BuildFormFactorTable() of G4PenelopeRayleighModelMI" <<
G4endl;
608 std::vector<G4double> *StoichiometricFactors =
new std::vector<G4double>;
609 for (
G4int i=0;i<nElements;i++) {
610 G4double fraction = fractionVector[i];
611 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
612 StoichiometricFactors->push_back(fraction/atomicWeigth);
614 G4double MaxStoichiometricFactor = 0.;
615 for (
G4int i=0;i<nElements;i++) {
616 if ((*StoichiometricFactors)[i] > MaxStoichiometricFactor)
617 MaxStoichiometricFactor = (*StoichiometricFactors)[i];
619 if (MaxStoichiometricFactor<1e-16) {
621 ed <<
"Inconsistent data of atomic composition for " << material->
GetName() <<
G4endl;
622 G4Exception(
"G4PenelopeRayleighModelMI::BuildFormFactorTable()",
625 for (
G4int i=0;i<nElements;i++)
626 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
630 for (
G4int i=0;i<nElements;i++)
631 atomsPerMolecule += (*StoichiometricFactors)[i];
635 for (
G4int i=0;i<nElements;i++)
636 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
650 G4MIData* dataMI = GetMIData(material);
655 if (fIsMIActive && aFileNameFF !=
"") {
657 G4cout <<
"Read MIFF for " << matname <<
" from custom file: " << aFileNameFF <<
G4endl;
659 ReadMolInterferenceData(matname,aFileNameFF);
662 for (
size_t k=0;k<logQSquareGrid.size();k++) {
677 if (fIsMIActive && matname.find(
"MedMat") != std::string::npos) {
679 G4cout <<
"Build MIFF from components for " << matname <<
G4endl;
682 G4int ki, kf=6, ktot=19;
684 G4String compstring = matname.substr(kf+1, ktot);
685 for (
size_t j=0; j<4; j++) {
688 compstring = matname.substr(ki, 4);
689 comp[j] = atof(compstring.c_str());
690 if (verboseLevel > 2)
691 G4cout <<
" -- MedMat comp[" << j+1 <<
"]: " << comp[j] <<
G4endl;
694 char* path = std::getenv(
"G4LEDATA");
696 G4String excep =
"G4LEDATA environment variable not set!";
697 G4Exception(
"G4PenelopeRayleighModelMI::BuildFormFactorTable()",
701 if (!MolInterferenceData->count(
"Fat_MI"))
702 ReadMolInterferenceData(
"Fat_MI");
705 if (!MolInterferenceData->count(
"Water_MI"))
706 ReadMolInterferenceData(
"Water_MI");
709 if (!MolInterferenceData->count(
"BoneMatrix_MI"))
710 ReadMolInterferenceData(
"BoneMatrix_MI");
713 if (!MolInterferenceData->count(
"Mineral_MI"))
714 ReadMolInterferenceData(
"Mineral_MI");
718 for (
size_t k=0;k<logQSquareGrid.size();k++) {
725 ff2 = comp[0]*ffat*ffat+comp[1]*fwater*fwater+
726 comp[2]*fbonematrix*fbonematrix+comp[3]*fmineral*fmineral;
732 else if (fIsMIActive && MolInterferenceData->count(matname)) {
734 G4cout <<
"Read MIFF from database " << matname <<
G4endl;
736 for (
size_t k=0;k<logQSquareGrid.size();k++) {
749 G4cout <<
"FF of " << matname <<
" calculated according to the IAM" <<
G4endl;
750 for (
size_t k=0;k<logQSquareGrid.size();k++) {
752 for (
G4int i=0;i<nElements;i++) {
753 G4int iZ = (*elementVector)[i]->GetZasInt();
757 ff2 += f*f*(*StoichiometricFactors)[i];
763 logFormFactorTable->insert(std::make_pair(material,theFFVec));
765 if (verboseLevel > 3)
767 delete StoichiometricFactors;
794 if (verboseLevel > 3)
795 G4cout <<
"Calling SamplingSecondaries() of G4PenelopeRayleighModelMI" <<
G4endl;
799 if (photonEnergy0 <= fIntrinsicLowEnergyLimit) {
813 if (!pMaxTable || !samplingTable || !logAtomicCrossSection || !atomicFormFactor ||
814 !logFormFactorTable) {
818 if (!logAtomicCrossSection)
819 logAtomicCrossSection =
new std::map<G4int,G4PhysicsFreeVector*>;
820 if (!atomicFormFactor)
821 atomicFormFactor =
new std::map<G4int,G4PhysicsFreeVector*>;
822 if (!logFormFactorTable)
823 logFormFactorTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
825 pMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
827 samplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
828 if (fIsMIActive && !MolInterferenceData)
829 MolInterferenceData =
new std::map<G4String,G4PhysicsFreeVector*>;
832 if (!samplingTable->count(theMat)) {
835 if (verboseLevel > 0) {
838 ed <<
"Unable to find the samplingTable data for " <<
840 ed <<
"This can happen only in Unit Tests" <<
G4endl;
841 G4Exception(
"G4PenelopeRayleighModelMI::SampleSecondaries()",
848 G4int iZ = theElementVector->at(j)->GetZasInt();
849 if (!logAtomicCrossSection->count(iZ)) {
858 if (!logFormFactorTable->count(theMat))
859 BuildFormFactorTable(theMat);
862 if (!(samplingTable->count(theMat)))
863 InitializeSamplingAlgorithm(theMat);
866 if (!pMaxTable->count(theMat))
867 GetPMaxTable(theMat);
879 G4double qmax = 2.0*photonEnergy0/electron_mass_c2;
886 G4double G = 0.5*(1+cosTheta*cosTheta);
895 G4double LastQ2inTheTable = theDataTable->
GetX(nData-1);
896 G4double q2max = std::min(qmax*qmax,LastQ2inTheTable);
913 cosTheta = 1.0-2.0*xx/q2max;
914 G4double G = 0.5*(1+cosTheta*cosTheta);
920 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
924 G4double dirX = sinTheta*std::cos(phi);
925 G4double dirY = sinTheta*std::sin(phi);
931 photonDirection1.
rotateUz(photonDirection0);
940void G4PenelopeRayleighModelMI::ReadDataFile(
const G4int Z)
943 if (verboseLevel > 2) {
944 G4cout <<
"G4PenelopeRayleighModelMI::ReadDataFile()" <<
G4endl;
945 G4cout <<
"Going to read Rayleigh data files for Z=" << Z <<
G4endl;
948 char* path = std::getenv(
"G4LEDATA");
950 G4String excep =
"G4LEDATA environment variable not set!";
951 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
957 std::ostringstream ost;
959 ost << path <<
"/penelope/rayleigh/pdgra" << Z <<
".p08";
961 ost << path <<
"/penelope/rayleigh/pdgra0" << Z <<
".p08";
962 std::ifstream file(ost.str().c_str());
964 if (!file.is_open()) {
966 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
972 file >> readZ >> nPoints;
974 if (readZ != Z || nPoints <= 0 || nPoints >= 5000) {
976 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
977 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
984 for (
size_t i=0;i<nPoints;i++) {
985 file >> ene >> f1 >> f2 >> xs;
990 if (file.eof() && i != (nPoints-1)) {
992 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
993 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
994 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
999 if (!logAtomicCrossSection) {
1000 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
1001 "em2044",
FatalException,
"Unable to allocate the atomic cross section table");
1005 logAtomicCrossSection->insert(std::make_pair(Z,theVec));
1009 std::ostringstream ost2;
1010 ost2 << path <<
"/penelope/rayleigh/MIFF/qext.dat";
1011 file.open(ost2.str().c_str());
1013 if (!file.is_open()) {
1015 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
1019 G4bool fillQGrid =
false;
1020 if (!logQSquareGrid.size()) {
1027 for (
size_t i=0;i<nPoints;i++) {
1029 logQSquareGrid.push_back(2.0*
G4Log(qext));
1035 std::ostringstream ost3;
1037 ost3 << path <<
"/penelope/rayleigh/pdaff" << Z <<
".p08";
1039 ost3 << path <<
"/penelope/rayleigh/pdaff0" << Z <<
".p08";
1040 file.open(ost3.str().c_str());
1042 if (!file.is_open()) {
1044 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
1048 file >> readZ >> nPoints;
1050 if (readZ != Z || nPoints <= 0 || nPoints >= 5000) {
1052 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
1053 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
1060 for (
size_t i=0;i<nPoints;i++) {
1061 file >> q >> ff >> incoh;
1063 if (file.eof() && i != (nPoints-1)) {
1065 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
1066 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
1067 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
1072 if (!atomicFormFactor) {
1073 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
1075 "Unable to allocate the atomicFormFactor data table");
1080 atomicFormFactor->insert(std::make_pair(Z,theFFVec));
1087void G4PenelopeRayleighModelMI::ReadMolInterferenceData(
const G4String& matname,
1091 if (verboseLevel > 2) {
1092 G4cout <<
"G4PenelopeRayleighModelMI::ReadMolInterferenceData() for material " <<
1095 G4bool isLocalFile = (FFfilename !=
"NULL");
1097 char* path = std::getenv(
"G4LEDATA");
1099 G4String excep =
"G4LEDATA environment variable not set!";
1100 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1105 if (!(fKnownMaterials->count(matname)) && !isLocalFile)
1108 G4String aFileName = (isLocalFile) ? FFfilename : fKnownMaterials->find(matname)->second;
1111 if (aFileName !=
"") {
1112 if (verboseLevel > 2)
1113 G4cout <<
"ReadMolInterferenceData(). Read material: " << matname <<
", filename: " <<
1115 (isLocalFile ?
"(local)" :
"(database)") <<
G4endl;
1117 std::ostringstream ostIMFF;
1119 ostIMFF << aFileName;
1121 ostIMFF << path <<
"/penelope/rayleigh/MIFF/" << aFileName;
1122 file.open(ostIMFF.str().c_str());
1124 if (!file.is_open()) {
1126 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1134 while (file.good()) {
1140 if (verboseLevel > 3)
1144 file.open(ostIMFF.str().c_str());
1147 for (
size_t i=0; i<nPoints; i++) {
1154 if (file.eof() && i != (nPoints-1)) {
1156 ed <<
"Corrupted data file" <<
G4endl;
1157 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
1158 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1162 if (!MolInterferenceData) {
1163 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1165 "Unable to allocate the Molecular Interference data table");
1170 MolInterferenceData->insert(std::make_pair(matname,theFFVec));
1185 G4double logQSquared = (QSquared>1e-10) ?
G4Log(QSquared) : -23.;
1187 G4double maxlogQ2 = logQSquareGrid[logQSquareGrid.size()-1];
1194 ed <<
"Unable to retrieve F squared table for " << mat->
GetName() <<
G4endl;
1195 G4Exception(
"G4PenelopeRayleighModelMI::GetFSquared()",
1200 if (logQSquared < -20) {
1204 else if (logQSquared > maxlogQ2)
1212 if (verboseLevel > 3) {
1214 G4cout <<
"Q^2 = " << QSquared <<
" (units of 1/(m_e*c)); F^2 = " << f2 <<
G4endl;
1221void G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm(
const G4Material* mat)
1226 const size_t np = 150;
1228 for (
size_t i=1;i<logQSquareGrid.size();i++)
1231 if (GetFSquared(mat,Q2) > 1e-35)
1233 q2max =
G4Exp(logQSquareGrid[i-1]);
1238 size_t nReducedPoints = np/4;
1243 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1245 "Too few points to initialize the sampling algorithm");
1247 if (q2min > (q2max-1e-10))
1249 G4cout <<
"q2min= " << q2min <<
" q2max= " << q2max <<
G4endl;
1250 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1252 "Too narrow grid to initialize the sampling algorithm");
1264 size_t NUNIF = std::min(std::max(((
size_t)8),nReducedPoints),np/2);
1265 const G4int nip = 51;
1268 x->push_back(q2min);
1269 for (
size_t i=1;i<NUNIF-1;i++)
1274 x->push_back(q2max);
1276 if (verboseLevel> 3)
1277 G4cout <<
"Vector x has " << x->size() <<
" points, while NUNIF = " << NUNIF <<
G4endl;
1286 for (
size_t i=0;i<NUNIF-1;i++)
1295 for (
G4int k=0;k<nip;k++)
1298 G4double pdfk = std::max(GetFSquared(mat,xik),0.);
1299 pdfi->push_back(pdfk);
1300 pdfmax = std::max(pdfmax,pdfk);
1304 G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
1305 pdfih->push_back(pdfIK);
1306 pdfmax = std::max(pdfmax,pdfIK);
1312 sumi->push_back(0.);
1313 for (
G4int k=1;k<nip;k++)
1316 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
1317 sumi->push_back(next);
1320 G4double lastIntegral = (*sumi)[sumi->size()-1];
1321 area->push_back(lastIntegral);
1323 G4double factor = 1.0/lastIntegral;
1324 for (
size_t k=0;k<sumi->size();k++)
1325 (*sumi)[k] *= factor;
1328 if ((*pdfi)[0] < 1e-35)
1329 (*pdfi)[0] = 1e-5*pdfmax;
1330 if ((*pdfi)[pdfi->size()-1] < 1e-35)
1331 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
1334 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
1335 G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
1336 G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
1337 G4double C_temp = 1.0+A_temp+B_temp;
1346 a->push_back(A_temp);
1347 b->push_back(B_temp);
1348 c->push_back(C_temp);
1360 for (
G4int k=0;k<nip;k++)
1363 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
1364 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1365 if (k == 0 || k == nip-1)
1366 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1368 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1373 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1389 (*x)[x->size()-1] = q2max;
1394 area->push_back(0.);
1396 if (x->size() != NUNIF || a->size() != NUNIF ||
1397 err->size() != NUNIF || area->size() != NUNIF)
1400 ed <<
"Problem in building the Table for Sampling: array dimensions do not match" <<
G4endl;
1401 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1413 for (
size_t i=0;i<err->size()-2;i++)
1416 if ((*err)[i] > maxError)
1418 maxError = (*err)[i];
1424 G4double newx = 0.5*((*x)[iErrMax]+(*x)[iErrMax+1]);
1426 x->insert(x->begin()+iErrMax+1,newx);
1428 area->insert(area->begin()+iErrMax+1,0.);
1429 a->insert(a->begin()+iErrMax+1,0.);
1430 b->insert(b->begin()+iErrMax+1,0.);
1431 c->insert(c->begin()+iErrMax+1,0.);
1432 err->insert(err->begin()+iErrMax+1,0.);
1435 for (
size_t i=iErrMax;i<=iErrMax+1;i++)
1442 G4double dxLocal = (*x)[i+1]-(*x)[i];
1445 for (
G4int k=0;k<nip;k++)
1448 G4double pdfk = std::max(GetFSquared(mat,xik),0.);
1449 pdfi->push_back(pdfk);
1450 pdfmax = std::max(pdfmax,pdfk);
1454 G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
1455 pdfih->push_back(pdfIK);
1456 pdfmax = std::max(pdfmax,pdfIK);
1462 sumi->push_back(0.);
1463 for (
G4int k=1;k<nip;k++)
1466 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
1467 sumi->push_back(next);
1469 G4double lastIntegral = (*sumi)[sumi->size()-1];
1470 (*area)[i] = lastIntegral;
1473 G4double factor = 1.0/lastIntegral;
1474 for (
size_t k=0;k<sumi->size();k++)
1475 (*sumi)[k] *= factor;
1478 if ((*pdfi)[0] < 1e-35)
1479 (*pdfi)[0] = 1e-5*pdfmax;
1480 if ((*pdfi)[pdfi->size()-1] < 1e-35)
1481 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
1484 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
1485 G4double B_temp = 1.0-1.0/(pli*pui*dxLocal*dxLocal);
1486 G4double A_temp = (1.0/(pli*dxLocal))-1.0-B_temp;
1487 G4double C_temp = 1.0+A_temp+B_temp;
1508 for (
G4int k=0;k<nip;k++)
1511 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
1512 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1513 if (k == 0 || k == nip-1)
1514 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1516 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1521 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1534 }
while(x->size() < np);
1536 if (x->size() != np || a->size() != np ||
1537 err->size() != np || area->size() != np)
1539 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1541 "Problem in building the extended Table for Sampling: array dimensions do not match ");
1548 for (
size_t i=0;i<np-1;i++)
1552 for (
size_t i=0;i<np-1;i++)
1556 errMax = std::max(errMax,(*err)[i]);
1562 for (
size_t i=0;i<np-1;i++)
1565 PAC->push_back(previous+(*area)[i]);
1567 (*PAC)[PAC->size()-1] = 1.;
1574 std::vector<size_t> *ITTL =
new std::vector<size_t>;
1575 std::vector<size_t> *ITTU =
new std::vector<size_t>;
1578 for (
size_t i=0;i<np;i++)
1586 for (
size_t i=1;i<(np-1);i++)
1590 for (
size_t j=(*ITTL)[i-1];j<np && !found;j++)
1592 if ((*PAC)[j] > ptst)
1600 (*ITTU)[ITTU->size()-2] = ITTU->size()-1;
1601 (*ITTU)[ITTU->size()-1] = ITTU->size()-1;
1602 (*ITTL)[ITTL->size()-1] = ITTU->size()-2;
1604 if (ITTU->size() != np || ITTU->size() != np)
1606 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1608 "Problem in building the Limit Tables for Sampling: array dimensions do not match");
1616 for (
size_t i=0;i<np;i++)
1618 theTable->
AddPoint((*x)[i],(*PAC)[i],(*a)[i],(*b)[i],(*ITTL)[i],(*ITTU)[i]);
1621 if (verboseLevel > 2)
1623 G4cout <<
"*************************************************************************" <<
1625 G4cout <<
"Sampling table for Penelope Rayleigh scattering in " << mat->
GetName() <<
G4endl;
1628 samplingTable->insert(std::make_pair(mat,theTable));
1649void G4PenelopeRayleighModelMI::GetPMaxTable(
const G4Material* mat)
1654 G4cout <<
"G4PenelopeRayleighModelMI::BuildPMaxTable" <<
G4endl;
1655 G4cout <<
"Going to instanziate the pMaxTable !" <<
G4endl;
1657 pMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
1660 if (pMaxTable->count(mat))
1666 G4Exception(
"G4PenelopeRayleighModelMI::GetPMaxTable()",
1668 "SamplingTable is not properly instantiated");
1673 if (!samplingTable->count(mat))
1676 ed <<
"Sampling table for material " << mat->
GetName() <<
" not found";
1677 G4Exception(
"G4PenelopeRayleighModelMI::GetPMaxTable()",
1686 size_t nOfEnergyPoints = logEnergyGridPMax.size();
1689 const size_t nip = 51;
1691 for (
size_t ie=0;ie<logEnergyGridPMax.size();ie++)
1705 size_t lowerBound = 0;
1706 size_t upperBound = tablePoints-1;
1707 while (lowerBound <= upperBound)
1709 size_t midBin = (lowerBound + upperBound)/2;
1710 if( Qm2 < theTable->GetX(midBin))
1711 { upperBound = midBin-1; }
1713 { lowerBound = midBin+1; }
1723 for (
size_t k=0;k<nip;k++)
1727 (theTable->
GetX(upperBound+1)-Q1);
1732 if (std::fabs(con1) > 1.0e-16*std::fabs(con2))
1733 etap = con2*(1.0-std::sqrt(1.0-2.0*tau*con1/(con2*con2)))/con1;
1737 (1.0+(theA+theB*etap)*etap)*(1.0+(theA+theB*etap)*etap)/
1738 ((1.0-theB*etap*etap)*ci*(theTable->
GetX(upperBound+1)-Q1));
1739 fun->push_back(theFun);
1747 (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*CONS;
1748 sum->push_back(secondPoint);
1749 for (
size_t hh=2;hh<nip-1;hh++)
1752 G4double next = previous+(13.0*((*fun)[hh-1]+(*fun)[hh])-
1753 (*fun)[hh+1]-(*fun)[hh-2])*HCONS;
1754 sum->push_back(next);
1756 G4double last = (*sum)[nip-2]+(5.0*(*fun)[nip-1]+8.0*(*fun)[nip-2]-
1757 (*fun)[nip-3])*CONS;
1758 sum->push_back(last);
1759 thePMax = thePAC + (*sum)[sum->size()-1];
1770 thePMax = theTable->
GetPAC(0);
1774 theVec->
PutValue(ie,energy,thePMax);
1777 pMaxTable->insert(std::make_pair(mat,theVec));
1786 G4cout <<
"*****************************************************************" <<
G4endl;
1787 G4cout <<
"G4PenelopeRayleighModelMI: Form Factor Table for " << mat->
GetName() <<
G4endl;
1790 G4cout <<
"*****************************************************************" <<
G4endl;
1791 if (!logFormFactorTable->count(mat))
1792 BuildFormFactorTable(mat);
1817void G4PenelopeRayleighModelMI::LoadKnownMIFFMaterials()
1819 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Fat_MI",
"FF_fat_Tartari2002.dat"));
1820 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Water_MI",
"FF_water_Tartari2002.dat"));
1821 fKnownMaterials->insert(std::pair<G4String,G4String>(
"BoneMatrix_MI",
"FF_bonematrix_Tartari2002.dat"));
1822 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Mineral_MI",
"FF_mineral_Tartari2002.dat"));
1823 fKnownMaterials->insert(std::pair<G4String,G4String>(
"adipose_MI",
"FF_adipose_Poletti2002.dat"));
1824 fKnownMaterials->insert(std::pair<G4String,G4String>(
"glandular_MI",
"FF_glandular_Poletti2002.dat"));
1825 fKnownMaterials->insert(std::pair<G4String,G4String>(
"breast5050_MI",
"FF_human_breast_Peplow1998.dat"));
1826 fKnownMaterials->insert(std::pair<G4String,G4String>(
"carcinoma_MI",
"FF_carcinoma_Kidane1999.dat"));
1827 fKnownMaterials->insert(std::pair<G4String,G4String>(
"muscle_MI",
"FF_pork_muscle_Peplow1998.dat"));
1828 fKnownMaterials->insert(std::pair<G4String,G4String>(
"kidney_MI",
"FF_pork_kidney_Peplow1998.dat"));
1829 fKnownMaterials->insert(std::pair<G4String,G4String>(
"liver_MI",
"FF_pork_liver_Peplow1998.dat"));
1830 fKnownMaterials->insert(std::pair<G4String,G4String>(
"heart_MI",
"FF_pork_heart_Peplow1998.dat"));
1831 fKnownMaterials->insert(std::pair<G4String,G4String>(
"blood_MI",
"FF_beef_blood_Peplow1998.dat"));
1832 fKnownMaterials->insert(std::pair<G4String,G4String>(
"grayMatter_MI",
"FF_gbrain_DeFelici2008.dat"));
1833 fKnownMaterials->insert(std::pair<G4String,G4String>(
"whiteMatter_MI",
"FF_wbrain_DeFelici2008.dat"));
1834 fKnownMaterials->insert(std::pair<G4String,G4String>(
"bone_MI",
"FF_bone_King2011.dat"));
1835 fKnownMaterials->insert(std::pair<G4String,G4String>(
"FatLowX_MI",
"FF_fat_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1836 fKnownMaterials->insert(std::pair<G4String,G4String>(
"BoneMatrixLowX_MI",
"FF_bonematrix_Tartari2002_joint_lowXdata.dat"));
1837 fKnownMaterials->insert(std::pair<G4String,G4String>(
"PMMALowX_MI",
"FF_PMMA_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1838 fKnownMaterials->insert(std::pair<G4String,G4String>(
"dryBoneLowX_MI",
"FF_drybone_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1839 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS30-70_MI",
"FF_CIRS30-70_Poletti2002.dat"));
1840 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS50-50_MI",
"FF_CIRS50-50_Poletti2002.dat"));
1841 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS70-30_MI",
"FF_CIRS70-30_Poletti2002.dat"));
1842 fKnownMaterials->insert(std::pair<G4String,G4String>(
"RMI454_MI",
"FF_RMI454_Poletti2002.dat"));
1843 fKnownMaterials->insert(std::pair<G4String,G4String>(
"PMMA_MI",
"FF_PMMA_Tartari2002.dat"));
1844 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Lexan_MI",
"FF_lexan_Peplow1998.dat"));
1845 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Kapton_MI",
"FF_kapton_Peplow1998.dat"));
1846 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Nylon_MI",
"FF_nylon_Kosanetzky1987.dat"));
1847 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Polyethylene_MI",
"FF_polyethylene_Kosanetzky1987.dat"));
1848 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Polystyrene_MI",
"FF_polystyrene_Kosanetzky1987.dat"));
1849 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Formaline_MI",
"FF_formaline_Peplow1998.dat"));
1850 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Acetone_MI",
"FF_acetone_Cozzini2010.dat"));
1851 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Hperoxide_MI",
"FF_Hperoxide_Cozzini2010.dat"));
1860 for (
G4int k=0; k<
n-1; k++) {
1861 integral += (y[k]+y[k+1]);
1863 integral *= dTheta*0.5;
std::vector< 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)
#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
size_t GetNumberOfElements() const
const G4String & GetName() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
virtual void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0., G4double maxEnergy=DBL_MAX) override
virtual 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(std::size_t index, G4double energy, G4double dValue)
G4double Energy(std::size_t index) const
G4double Value(G4double theEnergy, std::size_t &lastidx) const
G4double GetLowEdgeEnergy(std::size_t binNumber) const
std::size_t GetVectorLength() const
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)