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 if (MaxStoichiometricFactor > 0.)
497 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
502 for (std::size_t i=0;i<nElements;++i)
503 atPerMol += (*StoichiometricFactors)[i];
505 if (atPerMol != 0.) moleculeDensity = atomDensity/atPerMol;
507 if (fVerboseLevel > 2)
508 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
" atoms "
509 <<
"per molecule and " << moleculeDensity/(cm*cm*cm) <<
" molecule/cm3" <<
G4endl;
513 for (std::size_t i=0;i<nElements;++i)
514 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
516 if (fVerboseLevel > 2)
517 G4cout <<
"Molecular weight of " << matname <<
": " << MolWeight <<
" g/mol" <<
G4endl;
520 for (
G4int k=0; k<fNtheta; k++) {
521 G4double theta = fAngularFunction->Energy(k);
522 G4double F2 = GetFSquared(material,CalculateQSquared(theta,energy));
523 IntegrandFun[k] = (*fAngularFunction)[k]*F2;
526 G4double constant = pi*classic_electr_radius*classic_electr_radius;
527 cs = constant*IntegrateFun(IntegrandFun,fNtheta,fDTheta);
530 G4double csvolume = cs*moleculeDensity;
533 if (fVerboseLevel > 2)
534 G4cout <<
"Rayleigh CS of " << matname <<
" at " << energy/keV
535 <<
" keV: " << cs/barn <<
" barn"
536 <<
", mean free path: " << 1./csvolume/mm <<
" mm" <<
G4endl;
538 delete StoichiometricFactors;
545void G4PenelopeRayleighModelMI::BuildFormFactorTable(
const G4Material* material)
547 if (fVerboseLevel > 3)
548 G4cout <<
"Calling BuildFormFactorTable() of G4PenelopeRayleighModelMI" <<
G4endl;
556 std::vector<G4double> *StoichiometricFactors =
new std::vector<G4double>;
557 for (std::size_t i=0;i<nElements;++i) {
558 G4double fraction = fractionVector[i];
559 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
560 StoichiometricFactors->push_back(fraction/atomicWeigth);
562 G4double MaxStoichiometricFactor = 0.;
563 for (std::size_t i=0;i<nElements;++i) {
564 if ((*StoichiometricFactors)[i] > MaxStoichiometricFactor)
565 MaxStoichiometricFactor = (*StoichiometricFactors)[i];
567 if (MaxStoichiometricFactor<1e-16) {
569 ed <<
"Inconsistent data of atomic composition for " << material->
GetName() <<
G4endl;
570 G4Exception(
"G4PenelopeRayleighModelMI::BuildFormFactorTable()",
573 for (std::size_t i=0;i<nElements;++i)
574 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
578 for (std::size_t i=0;i<nElements;++i)
579 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
585 G4PhysicsFreeVector* theFFVec =
new G4PhysicsFreeVector(fLogQSquareGrid.size(),
588 G4String matname = material->
GetName();
589 G4String aFileNameFF =
"";
592 G4MIData* dataMI = GetMIData(material);
597 if (fIsMIActive && aFileNameFF !=
"") {
599 G4cout <<
"Read MIFF for " << matname <<
" from custom file: " << aFileNameFF <<
G4endl;
601 ReadMolInterferenceData(matname,aFileNameFF);
602 G4PhysicsFreeVector* Fvector = fMolInterferenceData->find(matname)->second;
604 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
615 if (fIsMIActive && matname.find(
"MedMat") != std::string::npos) {
617 G4cout <<
"Build MIFF from components for " << matname <<
G4endl;
620 G4int ki, kf=6, ktot=19;
622 G4String compstring = matname.substr(kf+1, ktot);
623 for (std::size_t j=0; j<4; ++j) {
626 compstring = matname.substr(ki, 4);
627 comp[j] = atof(compstring.c_str());
628 if (fVerboseLevel > 2)
629 G4cout <<
" -- MedMat comp[" << j+1 <<
"]: " << comp[j] <<
G4endl;
634 G4String excep =
"G4LEDATA environment variable not set!";
635 G4Exception(
"G4PenelopeRayleighModelMI::BuildFormFactorTable()",
639 if (!fMolInterferenceData->count(
"Fat_MI"))
640 ReadMolInterferenceData(
"Fat_MI");
641 G4PhysicsFreeVector* fatFF = fMolInterferenceData->find(
"Fat_MI")->second;
643 if (!fMolInterferenceData->count(
"Water_MI"))
644 ReadMolInterferenceData(
"Water_MI");
645 G4PhysicsFreeVector* waterFF = fMolInterferenceData->find(
"Water_MI")->second;
647 if (!fMolInterferenceData->count(
"BoneMatrix_MI"))
648 ReadMolInterferenceData(
"BoneMatrix_MI");
649 G4PhysicsFreeVector* bonematrixFF = fMolInterferenceData->find(
"BoneMatrix_MI")->second;
651 if (!fMolInterferenceData->count(
"Mineral_MI"))
652 ReadMolInterferenceData(
"Mineral_MI");
653 G4PhysicsFreeVector* mineralFF = fMolInterferenceData->find(
"Mineral_MI")->second;
656 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
663 ff2 = comp[0]*ffat*ffat+comp[1]*fwater*fwater+
664 comp[2]*fbonematrix*fbonematrix+comp[3]*fmineral*fmineral;
666 if (ff2) theFFVec->
PutValue(k,fLogQSquareGrid[k],
G4Log(ff2));
670 else if (fIsMIActive && fMolInterferenceData->count(matname)) {
672 G4cout <<
"Read MIFF from database " << matname <<
G4endl;
673 G4PhysicsFreeVector* FF = fMolInterferenceData->find(matname)->second;
674 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
679 if (ff2) theFFVec->
PutValue(k,fLogQSquareGrid[k],
G4Log(ff2));
685 G4cout <<
"FF of " << matname <<
" calculated according to the IAM" <<
G4endl;
686 for (std::size_t k=0;k<fLogQSquareGrid.size();++k) {
688 for (std::size_t i=0;i<nElements;++i) {
689 G4int iZ = (*elementVector)[i]->GetZasInt();
690 G4PhysicsFreeVector* theAtomVec = fAtomicFormFactor[iZ];
693 ff2 += f*f*(*StoichiometricFactors)[i];
695 if (ff2) theFFVec->
PutValue(k,fLogQSquareGrid[k],
G4Log(ff2));
700 fLogFormFactorTable->insert(std::make_pair(material,theFFVec));
702 if (fVerboseLevel > 3)
704 delete StoichiometricFactors;
730 if (fVerboseLevel > 3)
731 G4cout <<
"Calling SamplingSecondaries() of G4PenelopeRayleighModelMI" <<
G4endl;
735 if (photonEnergy0 <= fIntrinsicLowEnergyLimit) {
737 fParticleChange->SetProposedKineticEnergy(0.);
738 fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
748 if (!fPMaxTable || !fSamplingTable || !fLogFormFactorTable) {
752 if (!fLogFormFactorTable)
753 fLogFormFactorTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
755 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
757 fSamplingTable =
new std::map<const G4Material*,G4PenelopeSamplingData*>;
758 if (fIsMIActive && !fMolInterferenceData)
759 fMolInterferenceData =
new std::map<G4String,G4PhysicsFreeVector*>;
762 if (!fSamplingTable->count(theMat)) {
765 if (fVerboseLevel > 0) {
768 ed <<
"Unable to find the fSamplingTable data for " <<
770 ed <<
"This can happen only in Unit Tests" <<
G4endl;
771 G4Exception(
"G4PenelopeRayleighModelMI::SampleSecondaries()",
778 G4int iZ = theElementVector->at(j)->GetZasInt();
779 if (!fLogAtomicCrossSection[iZ]) {
788 if (!fLogFormFactorTable->count(theMat))
789 BuildFormFactorTable(theMat);
792 if (!(fSamplingTable->count(theMat)))
793 InitializeSamplingAlgorithm(theMat);
796 if (!fPMaxTable->count(theMat))
797 GetPMaxTable(theMat);
808 G4double qmax = 2.0*photonEnergy0/electron_mass_c2;
815 G4double G = 0.5*(1+cosTheta*cosTheta);
822 G4double LastQ2inTheTable = theDataTable->
GetX(nData-1);
823 G4double q2max = std::min(qmax*qmax,LastQ2inTheTable);
840 cosTheta = 1.0-2.0*xx/q2max;
841 G4double G = 0.5*(1+cosTheta*cosTheta);
847 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
851 G4double dirX = sinTheta*std::cos(phi);
852 G4double dirY = sinTheta*std::sin(phi);
858 photonDirection1.
rotateUz(photonDirection0);
859 fParticleChange->ProposeMomentumDirection(photonDirection1) ;
860 fParticleChange->SetProposedKineticEnergy(photonEnergy0) ;
867void G4PenelopeRayleighModelMI::ReadDataFile(
const G4int Z)
869 if (fVerboseLevel > 2) {
870 G4cout <<
"G4PenelopeRayleighModelMI::ReadDataFile()" <<
G4endl;
871 G4cout <<
"Going to read Rayleigh data files for Z=" << Z <<
G4endl;
876 G4String excep =
"G4LEDATA environment variable not set!";
877 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
883 std::ostringstream ost;
885 ost << path <<
"/penelope/rayleigh/pdgra" << Z <<
".p08";
887 ost << path <<
"/penelope/rayleigh/pdgra0" << Z <<
".p08";
888 std::ifstream file(ost.str().c_str());
890 if (!file.is_open()) {
891 G4String excep =
"Data file " + G4String(ost.str()) +
" not found!";
892 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
897 std::size_t nPoints = 0;
898 file >> readZ >> nPoints;
900 if (readZ != Z || nPoints <= 0 || nPoints >= 5000) {
902 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
903 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
908 fLogAtomicCrossSection[Z] =
new G4PhysicsFreeVector((std::size_t)nPoints);
910 for (std::size_t i=0;i<nPoints;++i) {
911 file >> ene >> f1 >> f2 >> xs;
915 fLogAtomicCrossSection[Z]->PutValue(i,
G4Log(ene),
G4Log(xs));
916 if (file.eof() && i != (nPoints-1)) {
918 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
919 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
920 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
927 std::ostringstream ost2;
928 ost2 << path <<
"/penelope/rayleigh/MIFF/qext.dat";
929 file.open(ost2.str().c_str());
931 if (!file.is_open()) {
932 G4String excep =
"Data file " + G4String(ost2.str()) +
" not found!";
933 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
937 if (!fLogQSquareGrid.size()) {
943 for (std::size_t i=0;i<nPoints;++i) {
945 fLogQSquareGrid.push_back(2.0*
G4Log(qext));
951 std::ostringstream ost3;
953 ost3 << path <<
"/penelope/rayleigh/pdaff" << Z <<
".p08";
955 ost3 << path <<
"/penelope/rayleigh/pdaff0" << Z <<
".p08";
956 file.open(ost3.str().c_str());
958 if (!file.is_open()) {
959 G4String excep =
"Data file " + G4String(ost3.str()) +
" not found!";
960 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
964 file >> readZ >> nPoints;
966 if (readZ != Z || nPoints <= 0 || nPoints >= 5000) {
968 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
969 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
974 fAtomicFormFactor[Z] =
new G4PhysicsFreeVector((std::size_t)nPoints);
976 for (std::size_t i=0;i<nPoints;++i) {
977 file >> q >> ff >> incoh;
978 fAtomicFormFactor[Z]->PutValue(i,q,ff);
979 if (file.eof() && i != (nPoints-1)) {
981 ed <<
"Corrupted data file for Z=" << Z <<
G4endl;
982 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
983 G4Exception(
"G4PenelopeRayleighModelMI::ReadDataFile()",
993void G4PenelopeRayleighModelMI::ReadMolInterferenceData(
const G4String& matname,
996 if (fVerboseLevel > 2) {
997 G4cout <<
"G4PenelopeRayleighModelMI::ReadMolInterferenceData() for material " <<
1000 G4bool isLocalFile = (FFfilename !=
"NULL");
1004 G4String excep =
"G4LEDATA environment variable not set!";
1005 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1010 if (!(fKnownMaterials->count(matname)) && !isLocalFile)
1013 G4String aFileName = (isLocalFile) ? FFfilename : fKnownMaterials->find(matname)->second;
1016 if (aFileName !=
"") {
1017 if (fVerboseLevel > 2)
1018 G4cout <<
"ReadMolInterferenceData(). Read material: " << matname <<
", filename: " <<
1020 (isLocalFile ?
"(local)" :
"(database)") <<
G4endl;
1022 std::ostringstream ostIMFF;
1024 ostIMFF << aFileName;
1026 ostIMFF << path <<
"/penelope/rayleigh/MIFF/" << aFileName;
1027 file.open(ostIMFF.str().c_str());
1029 if (!file.is_open()) {
1030 G4String excep =
"Data file " + G4String(ostIMFF.str()) +
" not found!";
1031 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1037 std::size_t nPoints = 0;
1039 while (file.good()) {
1045 if (fVerboseLevel > 3)
1049 file.open(ostIMFF.str().c_str());
1050 G4PhysicsFreeVector* theFFVec =
new G4PhysicsFreeVector((std::size_t)nPoints);
1052 for (std::size_t i=0; i<nPoints; ++i) {
1059 if (file.eof() && i != (nPoints-1)) {
1061 ed <<
"Corrupted data file" <<
G4endl;
1062 ed <<
"Found less than " << nPoints <<
" entries" <<
G4endl;
1063 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1067 if (!fMolInterferenceData) {
1068 G4Exception(
"G4PenelopeRayleighModelMI::ReadMolInterferenceData()",
1070 "Unable to allocate the Molecular Interference data table");
1075 fMolInterferenceData->insert(std::make_pair(matname,theFFVec));
1089 G4double logQSquared = (QSquared>1e-10) ?
G4Log(QSquared) : -23.;
1091 G4double maxlogQ2 = fLogQSquareGrid[fLogQSquareGrid.size()-1];
1094 G4PhysicsFreeVector* theVec = fLogFormFactorTable->find(mat)->second;
1098 ed <<
"Unable to retrieve F squared table for " << mat->
GetName() <<
G4endl;
1099 G4Exception(
"G4PenelopeRayleighModelMI::GetFSquared()",
1104 if (logQSquared < -20) {
1108 else if (logQSquared > maxlogQ2)
1116 if (fVerboseLevel > 3) {
1118 G4cout <<
"Q^2 = " << QSquared <<
" (units of 1/(m_e*c)); F^2 = " << f2 <<
G4endl;
1125void G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm(
const G4Material* mat)
1129 const std::size_t np = 150;
1130 for (std::size_t i=1;i<fLogQSquareGrid.size();++i)
1133 if (GetFSquared(mat,Q2) > 1e-35)
1135 q2max =
G4Exp(fLogQSquareGrid[i-1]);
1138 std::size_t nReducedPoints = np/4;
1143 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1145 "Too few points to initialize the sampling algorithm");
1147 if (q2min > (q2max-1e-10))
1149 G4cout <<
"q2min= " << q2min <<
" q2max= " << q2max <<
G4endl;
1150 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1152 "Too narrow grid to initialize the sampling algorithm");
1159 G4DataVector* x =
new G4DataVector();
1164 std::size_t NUNIF = std::min(std::max(((std::size_t)8),nReducedPoints),np/2);
1165 const G4int nip = 51;
1168 x->push_back(q2min);
1169 for (std::size_t i=1;i<NUNIF-1;++i)
1174 x->push_back(q2max);
1176 if (fVerboseLevel> 3)
1177 G4cout <<
"Vector x has " << x->size() <<
" points, while NUNIF = " << NUNIF <<
G4endl;
1180 G4DataVector* area =
new G4DataVector();
1181 G4DataVector* a =
new G4DataVector();
1182 G4DataVector* b =
new G4DataVector();
1183 G4DataVector* c =
new G4DataVector();
1184 G4DataVector* err =
new G4DataVector();
1186 for (std::size_t i=0;i<NUNIF-1;++i)
1189 G4DataVector* pdfi =
new G4DataVector();
1190 G4DataVector* pdfih =
new G4DataVector();
1191 G4DataVector* sumi =
new G4DataVector();
1195 for (
G4int k=0;k<nip;k++)
1198 G4double pdfk = std::max(GetFSquared(mat,xik),0.);
1199 pdfi->push_back(pdfk);
1200 pdfmax = std::max(pdfmax,pdfk);
1204 G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
1205 pdfih->push_back(pdfIK);
1206 pdfmax = std::max(pdfmax,pdfIK);
1212 sumi->push_back(0.);
1213 for (
G4int k=1;k<nip;k++)
1216 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
1217 sumi->push_back(next);
1220 G4double lastIntegral = (*sumi)[sumi->size()-1];
1221 area->push_back(lastIntegral);
1223 G4double factor = 1.0/lastIntegral;
1224 for (std::size_t k=0;k<sumi->size();++k)
1225 (*sumi)[k] *= factor;
1228 if ((*pdfi)[0] < 1e-35)
1229 (*pdfi)[0] = 1e-5*pdfmax;
1230 if ((*pdfi)[pdfi->size()-1] < 1e-35)
1231 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
1234 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
1235 G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
1236 G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
1237 G4double C_temp = 1.0+A_temp+B_temp;
1246 a->push_back(A_temp);
1247 b->push_back(B_temp);
1248 c->push_back(C_temp);
1260 for (
G4int k=0;k<nip;k++)
1263 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
1264 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1265 if (k == 0 || k == nip-1)
1266 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1268 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1273 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1289 (*x)[x->size()-1] = q2max;
1294 area->push_back(0.);
1296 if (x->size() != NUNIF || a->size() != NUNIF ||
1297 err->size() != NUNIF || area->size() != NUNIF)
1300 ed <<
"Problem in building the Table for Sampling: array dimensions do not match" <<
G4endl;
1301 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1312 std::size_t iErrMax = 0;
1313 for (std::size_t i=0;i<err->size()-2;++i)
1316 if ((*err)[i] > maxError)
1318 maxError = (*err)[i];
1324 G4double newx = 0.5*((*x)[iErrMax]+(*x)[iErrMax+1]);
1326 x->insert(x->begin()+iErrMax+1,newx);
1328 area->insert(area->begin()+iErrMax+1,0.);
1329 a->insert(a->begin()+iErrMax+1,0.);
1330 b->insert(b->begin()+iErrMax+1,0.);
1331 c->insert(c->begin()+iErrMax+1,0.);
1332 err->insert(err->begin()+iErrMax+1,0.);
1335 for (std::size_t i=iErrMax;i<=iErrMax+1;++i)
1338 G4DataVector* pdfi =
new G4DataVector();
1339 G4DataVector* pdfih =
new G4DataVector();
1340 G4DataVector* sumi =
new G4DataVector();
1342 G4double dxLocal = (*x)[i+1]-(*x)[i];
1345 for (
G4int k=0;k<nip;k++)
1348 G4double pdfk = std::max(GetFSquared(mat,xik),0.);
1349 pdfi->push_back(pdfk);
1350 pdfmax = std::max(pdfmax,pdfk);
1354 G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
1355 pdfih->push_back(pdfIK);
1356 pdfmax = std::max(pdfmax,pdfIK);
1362 sumi->push_back(0.);
1363 for (
G4int k=1;k<nip;k++)
1366 G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
1367 sumi->push_back(next);
1369 G4double lastIntegral = (*sumi)[sumi->size()-1];
1370 (*area)[i] = lastIntegral;
1373 G4double factor = 1.0/lastIntegral;
1374 for (std::size_t k=0;k<sumi->size();++k)
1375 (*sumi)[k] *= factor;
1378 if ((*pdfi)[0] < 1e-35)
1379 (*pdfi)[0] = 1e-5*pdfmax;
1380 if ((*pdfi)[pdfi->size()-1] < 1e-35)
1381 (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
1384 G4double pui = (*pdfi)[pdfi->size()-1]*factor;
1385 G4double B_temp = 1.0-1.0/(pli*pui*dxLocal*dxLocal);
1386 G4double A_temp = (1.0/(pli*dxLocal))-1.0-B_temp;
1387 G4double C_temp = 1.0+A_temp+B_temp;
1408 for (
G4int k=0;k<nip;k++)
1411 G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
1412 ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1413 if (k == 0 || k == nip-1)
1414 (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1416 (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1421 if ((*err)[i] > 0.1*(*area)[i] && icase == 1)
1434 }
while(x->size() < np);
1436 if (x->size() != np || a->size() != np ||
1437 err->size() != np || area->size() != np)
1439 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1441 "Problem in building the extended Table for Sampling: array dimensions do not match ");
1448 for (std::size_t i=0;i<np-1;++i)
1452 for (std::size_t i=0;i<np-1;++i)
1456 errMax = std::max(errMax,(*err)[i]);
1460 G4DataVector* PAC =
new G4DataVector();
1462 for (std::size_t i=0;i<np-1;++i)
1465 PAC->push_back(previous+(*area)[i]);
1467 (*PAC)[PAC->size()-1] = 1.;
1472 std::vector<std::size_t> *ITTL =
new std::vector<std::size_t>;
1473 std::vector<std::size_t> *ITTU =
new std::vector<std::size_t>;
1476 for (std::size_t i=0;i<np;++i)
1484 for (std::size_t i=1;i<(np-1);++i)
1488 for (std::size_t j=(*ITTL)[i-1];j<np && !found;++j)
1490 if ((*PAC)[j] > ptst)
1498 (*ITTU)[ITTU->size()-2] = ITTU->size()-1;
1499 (*ITTU)[ITTU->size()-1] = ITTU->size()-1;
1500 (*ITTL)[ITTL->size()-1] = ITTU->size()-2;
1502 if (ITTU->size() != np || ITTU->size() != np)
1504 G4Exception(
"G4PenelopeRayleighModelMI::InitializeSamplingAlgorithm()",
1506 "Problem in building the Limit Tables for Sampling: array dimensions do not match");
1512 G4PenelopeSamplingData* theTable =
new G4PenelopeSamplingData(np);
1513 for (std::size_t i=0;i<np;++i)
1515 theTable->
AddPoint((*x)[i],(*PAC)[i],(*a)[i],(*b)[i],(*ITTL)[i],(*ITTU)[i]);
1517 if (fVerboseLevel > 2)
1519 G4cout <<
"*************************************************************************" <<
1521 G4cout <<
"Sampling table for Penelope Rayleigh scattering in " << mat->
GetName() <<
G4endl;
1524 fSamplingTable->insert(std::make_pair(mat,theTable));
1543void G4PenelopeRayleighModelMI::GetPMaxTable(
const G4Material* mat)
1547 G4cout <<
"G4PenelopeRayleighModelMI::BuildPMaxTable" <<
G4endl;
1548 G4cout <<
"Going to instanziate the fPMaxTable !" <<
G4endl;
1550 fPMaxTable =
new std::map<const G4Material*,G4PhysicsFreeVector*>;
1553 if (fPMaxTable->count(mat))
1557 if (!fSamplingTable)
1559 G4Exception(
"G4PenelopeRayleighModelMI::GetPMaxTable()",
1561 "SamplingTable is not properly instantiated");
1566 if (!fSamplingTable->count(mat))
1569 ed <<
"Sampling table for material " << mat->
GetName() <<
" not found";
1570 G4Exception(
"G4PenelopeRayleighModelMI::GetPMaxTable()",
1576 G4PenelopeSamplingData *theTable = fSamplingTable->find(mat)->second;
1578 std::size_t nOfEnergyPoints = fLogEnergyGridPMax.size();
1579 G4PhysicsFreeVector* theVec =
new G4PhysicsFreeVector(nOfEnergyPoints);
1581 const std::size_t nip = 51;
1583 for (std::size_t ie=0;ie<fLogEnergyGridPMax.size();++ie)
1597 std::size_t lowerBound = 0;
1598 std::size_t upperBound = tablePoints-1;
1599 while (lowerBound <= upperBound)
1601 std::size_t midBin = (lowerBound + upperBound)/2;
1602 if( Qm2 < theTable->GetX(midBin))
1603 { upperBound = midBin-1; }
1605 { lowerBound = midBin+1; }
1614 G4DataVector* fun =
new G4DataVector();
1615 for (std::size_t k=0;k<nip;++k)
1619 (theTable->
GetX(upperBound+1)-Q1);
1624 if (std::fabs(con1) > 1.0e-16*std::fabs(con2))
1625 etap = con2*(1.0-std::sqrt(1.0-2.0*tau*con1/(con2*con2)))/con1;
1629 (1.0+(theA+theB*etap)*etap)*(1.0+(theA+theB*etap)*etap)/
1630 ((1.0-theB*etap*etap)*ci*(theTable->
GetX(upperBound+1)-Q1));
1631 fun->push_back(theFun);
1634 G4DataVector* sum =
new G4DataVector;
1639 (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*CONS;
1640 sum->push_back(secondPoint);
1641 for (std::size_t hh=2;hh<nip-1;++hh)
1644 G4double next = previous+(13.0*((*fun)[hh-1]+(*fun)[hh])-
1645 (*fun)[hh+1]-(*fun)[hh-2])*HCONS;
1646 sum->push_back(next);
1648 G4double last = (*sum)[nip-2]+(5.0*(*fun)[nip-1]+8.0*(*fun)[nip-2]-
1649 (*fun)[nip-3])*CONS;
1650 sum->push_back(last);
1651 thePMax = thePAC + (*sum)[sum->size()-1];
1662 thePMax = theTable->
GetPAC(0);
1666 theVec->
PutValue(ie,energy,thePMax);
1669 fPMaxTable->insert(std::make_pair(mat,theVec));
1677 G4cout <<
"*****************************************************************" <<
G4endl;
1678 G4cout <<
"G4PenelopeRayleighModelMI: Form Factor Table for " << mat->
GetName() <<
G4endl;
1681 G4cout <<
"*****************************************************************" <<
G4endl;
1682 if (!fLogFormFactorTable->count(mat))
1683 BuildFormFactorTable(mat);
1708void G4PenelopeRayleighModelMI::LoadKnownMIFFMaterials()
1710 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Fat_MI",
"FF_fat_Tartari2002.dat"));
1711 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Water_MI",
"FF_water_Tartari2002.dat"));
1712 fKnownMaterials->insert(std::pair<G4String,G4String>(
"BoneMatrix_MI",
"FF_bonematrix_Tartari2002.dat"));
1713 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Mineral_MI",
"FF_mineral_Tartari2002.dat"));
1714 fKnownMaterials->insert(std::pair<G4String,G4String>(
"adipose_MI",
"FF_adipose_Poletti2002.dat"));
1715 fKnownMaterials->insert(std::pair<G4String,G4String>(
"glandular_MI",
"FF_glandular_Poletti2002.dat"));
1716 fKnownMaterials->insert(std::pair<G4String,G4String>(
"breast5050_MI",
"FF_human_breast_Peplow1998.dat"));
1717 fKnownMaterials->insert(std::pair<G4String,G4String>(
"carcinoma_MI",
"FF_carcinoma_Kidane1999.dat"));
1718 fKnownMaterials->insert(std::pair<G4String,G4String>(
"muscle_MI",
"FF_pork_muscle_Peplow1998.dat"));
1719 fKnownMaterials->insert(std::pair<G4String,G4String>(
"kidney_MI",
"FF_pork_kidney_Peplow1998.dat"));
1720 fKnownMaterials->insert(std::pair<G4String,G4String>(
"liver_MI",
"FF_pork_liver_Peplow1998.dat"));
1721 fKnownMaterials->insert(std::pair<G4String,G4String>(
"heart_MI",
"FF_pork_heart_Peplow1998.dat"));
1722 fKnownMaterials->insert(std::pair<G4String,G4String>(
"blood_MI",
"FF_beef_blood_Peplow1998.dat"));
1723 fKnownMaterials->insert(std::pair<G4String,G4String>(
"grayMatter_MI",
"FF_gbrain_DeFelici2008.dat"));
1724 fKnownMaterials->insert(std::pair<G4String,G4String>(
"whiteMatter_MI",
"FF_wbrain_DeFelici2008.dat"));
1725 fKnownMaterials->insert(std::pair<G4String,G4String>(
"bone_MI",
"FF_bone_King2011.dat"));
1726 fKnownMaterials->insert(std::pair<G4String,G4String>(
"FatLowX_MI",
"FF_fat_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1727 fKnownMaterials->insert(std::pair<G4String,G4String>(
"BoneMatrixLowX_MI",
"FF_bonematrix_Tartari2002_joint_lowXdata.dat"));
1728 fKnownMaterials->insert(std::pair<G4String,G4String>(
"PMMALowX_MI",
"FF_PMMA_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1729 fKnownMaterials->insert(std::pair<G4String,G4String>(
"dryBoneLowX_MI",
"FF_drybone_Tartari2002_joint_lowXdata_ESRF2003.dat"));
1730 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS30-70_MI",
"FF_CIRS30-70_Poletti2002.dat"));
1731 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS50-50_MI",
"FF_CIRS50-50_Poletti2002.dat"));
1732 fKnownMaterials->insert(std::pair<G4String,G4String>(
"CIRS70-30_MI",
"FF_CIRS70-30_Poletti2002.dat"));
1733 fKnownMaterials->insert(std::pair<G4String,G4String>(
"RMI454_MI",
"FF_RMI454_Poletti2002.dat"));
1734 fKnownMaterials->insert(std::pair<G4String,G4String>(
"PMMA_MI",
"FF_PMMA_Tartari2002.dat"));
1735 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Lexan_MI",
"FF_lexan_Peplow1998.dat"));
1736 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Kapton_MI",
"FF_kapton_Peplow1998.dat"));
1737 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Nylon_MI",
"FF_nylon_Kosanetzky1987.dat"));
1738 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Polyethylene_MI",
"FF_polyethylene_Kosanetzky1987.dat"));
1739 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Polystyrene_MI",
"FF_polystyrene_Kosanetzky1987.dat"));
1740 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Formaline_MI",
"FF_formaline_Peplow1998.dat"));
1741 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Acetone_MI",
"FF_acetone_Cozzini2010.dat"));
1742 fKnownMaterials->insert(std::pair<G4String,G4String>(
"Hperoxide_MI",
"FF_Hperoxide_Cozzini2010.dat"));
1750 for (
G4int k=0; k<
n-1; k++) {
1751 integral += (y[k]+y[k+1]);
1753 integral *= dTheta*0.5;
1761 G4ExtendedMaterial* aEM = (G4ExtendedMaterial*)material;
G4TemplateAutoLock< G4Mutex > G4AutoLock
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)
G4ThreeVector G4ParticleMomentum
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
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
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
G4VEmModel(const G4String &nam)
G4double energy(const ThreeVector &p, const G4double m)