46 fpDNAPTBAugerModel = std::make_unique<G4DNAPTBAugerModel>(
"e-_G4DNAPTBAugerModel");
70 if (verboseLevel > 3) {
71 G4cout <<
"Calling G4DNAPTBIonisationModel::Initialise()" <<
G4endl;
74 G4double scaleFactor = 1e-16 * cm * cm;
75 G4double scaleFactorBorn = (1.e-22 / 3.343) * m * m;
84 if (particle == electronDef) {
88 if (fpN2 !=
nullptr) {
91 "dna/sigmadiff_cumulated_ionisation_e-_PTB_N2", scaleFactor);
98 if (fpTHF !=
nullptr) {
101 "dna/sigmadiff_cumulated_ionisation_e-_PTB_THF", scaleFactor);
106 if (fpPY !=
nullptr) {
109 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PY", scaleFactor);
114 if (fpPU !=
nullptr) {
117 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU", scaleFactor);
121 if (fpTMP !=
nullptr) {
124 "dna/sigmadiff_cumulated_ionisation_e-_PTB_TMP", scaleFactor);
129 if (fpG4_WATER !=
nullptr) {
132 "dna/sigmadiff_ionisation_e_born", scaleFactorBorn);
138 if (fpBackbone_THF !=
nullptr) {
141 "dna/sigmadiff_cumulated_ionisation_e-_PTB_THF", scaleFactor * 33. / 30);
146 if (fpCytosine_PY !=
nullptr) {
149 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PY", scaleFactor * 42. / 30);
154 if (fpThymine_PY !=
nullptr) {
157 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PY", scaleFactor * 48. / 30);
162 if (fpAdenine_PU !=
nullptr) {
165 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU", scaleFactor * 50. / 44);
170 if (fpGuanine_PU !=
nullptr) {
173 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU", scaleFactor * 56. / 44);
178 if (fpBackbone_TMP !=
nullptr) {
181 "dna/sigmadiff_cumulated_ionisation_e-_PTB_TMP", scaleFactor * 33. / 50);
187 else if (particle == protonDef) {
192 if (fpTHF !=
nullptr) {
195 "dna/sigmadiff_cumulated_ionisation_p_PTB_THF", scaleFactor);
200 if (fpPY !=
nullptr) {
203 "dna/sigmadiff_cumulated_ionisation_p_PTB_PY", scaleFactor);
217 if (fpTMP !=
nullptr) {
220 "dna/sigmadiff_cumulated_ionisation_p_PTB_TMP", scaleFactor);
236 if (dataModel ==
nullptr) {
237 G4cout <<
"G4DNAPTBIonisationModel::Initialise:: not good modelData" <<
G4endl;
239 "not good modelData");
242 fpModelData = dataModel;
246 if (fpDNAPTBAugerModel) {
247 fpDNAPTBAugerModel->Initialise();
265 const std::size_t& matID = material->
GetIndex();
272 if (ekin >= lowLim && ekin < highLim) {
274 auto tableData = fpModelData->
GetData();
275 if ((*tableData)[matID][p] ==
nullptr) {
277 "No model is registered");
280 sigma = (*tableData)[matID][p]->FindValue(ekin);
282 if (verboseLevel > 2) {
283 G4cout <<
"__________________________________" <<
G4endl;
284 G4cout <<
"°°° G4DNAPTBIonisationModel - XS INFO START" <<
G4endl;
285 G4cout <<
"°°° Kinetic energy(eV)=" << ekin / eV <<
" particle : " << particleName <<
G4endl;
286 G4cout <<
"°°° Cross section per " << matID <<
" index molecule (cm^2)=" << sigma / cm / cm
288 G4cout <<
"°°° G4DNAPTBIonisationModel - XS INFO END" <<
G4endl;
295 return sigma * MolDensity;
317 if (k >= lowLim && k < highLim) {
320 G4double totalEnergy = k + particleMass;
321 G4double pSquare = k * (totalEnergy + particleMass);
322 G4double totalMomentum = std::sqrt(pSquare);
331 G4double secondaryKinetic(-1000 * eV);
333 if (fpG4_WATER ==
nullptr || materialID != fpG4_WATER->
GetIndex()) {
335 secondaryKinetic = fpModelData->RandomizeEjectedElectronEnergyFromCumulated(
336 aDynamicParticle->
GetDefinition(), k / eV, ionizationShell, materialID);
339 secondaryKinetic = fpModelData->RandomizeEjectedElectronEnergy(
340 aDynamicParticle->
GetDefinition(), k, ionizationShell, materialID);
343 if (secondaryKinetic <= 0) {
344 G4cout <<
"Fatal error *************************************** " << secondaryKinetic / eV
346 G4cout <<
"secondaryKinetic: " << secondaryKinetic / eV <<
G4endl;
351 "Fatal error:: scatteredEnergy <= 0");
356 RandomizeEjectedElectronDirection(aDynamicParticle->
GetDefinition(), k, secondaryKinetic,
359 G4double sinTheta = std::sqrt(1. - cosTheta * cosTheta);
360 G4double dirX = sinTheta * std::cos(phi);
361 G4double dirY = sinTheta * std::sin(phi);
364 deltaDirection.
rotateUz(primaryDirection);
375 std::sqrt(secondaryKinetic * (secondaryKinetic + 2. * electron_mass_c2));
377 totalMomentum * primaryDirection.
x() - deltaTotalMomentum * deltaDirection.
x();
379 totalMomentum * primaryDirection.
y() - deltaTotalMomentum * deltaDirection.
y();
381 totalMomentum * primaryDirection.
z() - deltaTotalMomentum * deltaDirection.
z();
382 G4double finalMomentum = std::sqrt(finalPx * finalPx + finalPy * finalPy + finalPz * finalPz);
383 finalPx /= finalMomentum;
384 finalPy /= finalMomentum;
385 finalPz /= finalMomentum;
390 G4cout <<
"Fatal error ****************************" <<
G4endl;
393 "Fatal error:: direction problem");
405 G4double scatteredEnergy = k - bindingEnergy - secondaryKinetic;
407 if (scatteredEnergy <= 0) {
408 G4cout <<
"Fatal error ****************************" <<
G4endl;
410 G4cout <<
"secondaryKinetic: " << secondaryKinetic / eV <<
G4endl;
412 G4cout <<
"bindingEnergy: " << bindingEnergy / eV <<
G4endl;
413 G4cout <<
"scatteredEnergy: " << scatteredEnergy / eV <<
G4endl;
416 "Fatal error:: scatteredEnergy <= 0");
427 fvect->push_back(dp);
430 if (fpDNAPTBAugerModel) {
432 if (materialName !=
"G4_WATER") {
433 fpDNAPTBAugerModel->ComputeAugerEffect(fvect, materialName, bindingEnergy);
441void G4DNAPTBIonisationModel::ReadDiffCSFile(
const std::size_t& materialID,
450 if (path ==
nullptr) {
452 "G4LEDATA environment variable was not set.");
457 std::ostringstream fullFileName;
458 fullFileName << path <<
"/" << file <<
".dat";
461 std::ifstream diffCrossSection(fullFileName.str().c_str());
463 std::stringstream endPath;
464 if (!diffCrossSection) {
465 endPath <<
"Missing data file: " << file;
467 endPath.str().c_str());
471 fTMapWithVec[materialID][p].push_back(0.);
478 while (std::getline(diffCrossSection, line)) {
481 std::istringstream testIss(line);
498 std::istringstream iss(line);
509 if (T != fTMapWithVec[materialID][p].back()) fTMapWithVec[materialID][p].push_back(T);
512 for (
int shell = 0, eshell = ptbStructure.
NumberOfLevels(materialID); shell < eshell; ++shell) {
515 iss >> diffCrossSectionData[materialID][p][shell][T][E];
517 if (fpG4_WATER !=
nullptr && fpG4_WATER->
GetIndex() != materialID) {
520 fEnergySecondaryData[materialID][p][shell][T]
521 [diffCrossSectionData[materialID][p][shell][T][E]] = E;
525 fProbaShellMap[materialID][p][shell][T].push_back(
526 diffCrossSectionData[materialID][p][shell][T][E]);
529 diffCrossSectionData[materialID][p][shell][T][E] *= scaleFactor;
530 fEMapWithVector[materialID][p][T].push_back(E);
538G4double G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergy(
545 ? maximumEnergyTransfer = k
546 : maximumEnergyTransfer = (k + ptbStructure.
IonisationEnergy(shell, materialID)) / 2.;
567 G4double maxEnergy = maximumEnergyTransfer;
568 G4int nEnergySteps = 50;
570 G4double stpEnergy(std::pow(maxEnergy / value, 1. /
static_cast<G4double>(nEnergySteps - 1)));
571 G4int step(nEnergySteps);
575 DifferentialCrossSection(particleDefinition, k / eV, value / eV, shell, materialID);
576 if (differentialCrossSection >= crossSectionMaximum)
577 crossSectionMaximum = differentialCrossSection;
582 G4double secondaryElectronKineticEnergy = 0.;
585 secondaryElectronKineticEnergy =
587 * (maximumEnergyTransfer - ptbStructure.
IonisationEnergy(shell, materialID));
590 G4UniformRand() * crossSectionMaximum > DifferentialCrossSection(
591 particleDefinition, k / eV,
592 (secondaryElectronKineticEnergy + ptbStructure.
IonisationEnergy(shell, materialID)) / eV,
595 return secondaryElectronKineticEnergy;
599 G4double maximumKineticEnergyTransfer = 4. * (electron_mass_c2 / proton_mass_c2) * k;
603 value <= 4. * ptbStructure.
IonisationEnergy(shell, materialID); value += 0.1 * eV)
606 DifferentialCrossSection(particleDefinition, k / eV, value / eV, shell, materialID);
607 if (differentialCrossSection >= crossSectionMaximum)
608 crossSectionMaximum = differentialCrossSection;
611 G4double secondaryElectronKineticEnergy = 0.;
613 secondaryElectronKineticEnergy =
G4UniformRand() * maximumKineticEnergyTransfer;
615 G4UniformRand() * crossSectionMaximum >= DifferentialCrossSection(
616 particleDefinition, k / eV,
617 (secondaryElectronKineticEnergy + ptbStructure.
IonisationEnergy(shell, materialID)) / eV,
620 return secondaryElectronKineticEnergy;
634 if (secKinetic < 50. * eV)
636 else if (secKinetic <= 200. * eV) {
643 G4double sin2O = (1. - secKinetic / k) / (1. + secKinetic / (2. * electron_mass_c2));
644 cosTheta = std::sqrt(1. - sin2O);
648 G4double maxSecKinetic = 4. * (electron_mass_c2 / proton_mass_c2) * k;
655 (secKinetic > 100 * eV) ? cosTheta = std::sqrt(secKinetic / maxSecKinetic)
664 G4int ionizationLevelIndex,
665 const std::size_t& materialID)
669 G4double kSE(energyTransfer - shellEnergy);
671 if (energyTransfer >= shellEnergy) {
687 std::upper_bound(fTMapWithVec[materialID][p].begin(), fTMapWithVec[materialID][p].end(), k);
691 if (kSE <= fEMapWithVector[materialID][p][(*t1)].back()
692 && kSE <= fEMapWithVector[materialID][p][(*t2)].back())
694 auto e12 = std::upper_bound(fEMapWithVector[materialID][p][(*t1)].begin(),
695 fEMapWithVector[materialID][p][(*t1)].end(), kSE);
698 auto e22 = std::upper_bound(fEMapWithVector[materialID][p][(*t2)].begin(),
699 fEMapWithVector[materialID][p][(*t2)].end(), kSE);
709 xs11 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT1][valueE11];
710 xs12 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT1][valueE12];
711 xs21 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT2][valueE21];
712 xs22 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT2][valueE22];
719 std::upper_bound(fTMapWithVec[materialID][p].begin(), fTMapWithVec[materialID][p].end(), k);
722 auto e12 = std::upper_bound(fEMapWithVector[materialID][p][(*t1)].begin(),
723 fEMapWithVector[materialID][p][(*t1)].end(), kSE);
726 auto e22 = std::upper_bound(fEMapWithVector[materialID][p][(*t2)].begin(),
727 fEMapWithVector[materialID][p][(*t2)].end(), kSE);
737 xs11 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT1][valueE11];
738 xs12 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT1][valueE12];
739 xs21 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT2][valueE21];
740 xs22 = diffCrossSectionData[materialID][p][ionizationLevelIndex][valueT2][valueE22];
743 G4double xsProduct = xs11 * xs12 * xs21 * xs22;
745 if (xsProduct != 0.) {
746 sigma = QuadInterpolator(valueE11, valueE12, valueE21, valueE22, xs11, xs12, xs21, xs22,
747 valueT1, valueT2, k, kSE);
756G4double G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated(
784 G4double ejectedElectronEnergy = 0.;
816 std::upper_bound(fTMapWithVec[materialID][p].begin(), fTMapWithVec[materialID][p].end(), k);
826 G4cerr <<
"**************** Fatal error ******************" <<
G4endl;
827 G4cerr <<
"G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated" <<
G4endl;
828 G4cerr <<
"You have *k1 > *k2 with k1 " << *k1 <<
" and k2 " << *k2 <<
G4endl;
830 <<
"This may be because the energy of the incident particle is to high for the data table."
841 std::upper_bound(fProbaShellMap[materialID][p][ionizationLevelIndex][(*k1)].begin(),
842 fProbaShellMap[materialID][p][ionizationLevelIndex][(*k1)].end(), random);
843 auto cumulCS11 = cumulCS12 - 1;
846 std::upper_bound(fProbaShellMap[materialID][p][ionizationLevelIndex][(*k2)].begin(),
847 fProbaShellMap[materialID][p][ionizationLevelIndex][(*k2)].end(), random);
848 auto cumulCS21 = cumulCS22 - 1;
853 valueCumulCS11 = *cumulCS11;
854 valueCumulCS12 = *cumulCS12;
855 valueCumulCS21 = *cumulCS21;
856 valueCumulCS22 = *cumulCS22;
876 if (cumulCS12 == fProbaShellMap[materialID][p][ionizationLevelIndex][(*k1)].end()) {
881 secElecE21 = fEnergySecondaryData[materialID][p][ionizationLevelIndex][valueK2][valueCumulCS21];
882 secElecE22 = fEnergySecondaryData[materialID][p][ionizationLevelIndex][valueK2][valueCumulCS22];
889 secElecE11 = fEnergySecondaryData[materialID][p][ionizationLevelIndex][valueK1][valueCumulCS11];
890 secElecE12 = fEnergySecondaryData[materialID][p][ionizationLevelIndex][valueK1][valueCumulCS12];
891 secElecE21 = fEnergySecondaryData[materialID][p][ionizationLevelIndex][valueK2][valueCumulCS21];
892 secElecE22 = fEnergySecondaryData[materialID][p][ionizationLevelIndex][valueK2][valueCumulCS22];
895 ejectedElectronEnergy =
896 QuadInterpolator(valueCumulCS11, valueCumulCS12, valueCumulCS21, valueCumulCS22, secElecE11,
897 secElecE12, secElecE21, secElecE22, valueK1, valueK2, k, random);
904 if (k - ejectedElectronEnergy - bindingEnergy <= 0 || ejectedElectronEnergy <= 0) {
907 G4cout <<
"secondaryKin " << ejectedElectronEnergy <<
G4endl;
912 G4cout <<
"surrounding k values: valueK1 valueK2\n" << valueK1 <<
" " << valueK2 <<
G4endl;
913 G4cout <<
"surrounding E values: secElecE11 secElecE12 secElecE21 secElecE22\n"
914 << secElecE11 <<
" " << secElecE12 <<
" " << secElecE21 <<
" " << secElecE22 <<
" "
917 <<
"surrounding cumulCS values: valueCumulCS11 valueCumulCS12 valueCumulCS21 valueCumulCS22\n"
918 << valueCumulCS11 <<
" " << valueCumulCS12 <<
" " << valueCumulCS21 <<
" " << valueCumulCS22
921 errmsg <<
"*****************************" <<
G4endl;
922 errmsg <<
"Fatal error, EXIT." <<
G4endl;
923 G4Exception(
"G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated",
"",
928 return ejectedElectronEnergy * eV;
940 if ((e2 - e1) != 0 && xs1 != 0 && xs2 != 0) {
943 value = std::pow(10., (d1 + (d2 - d1) * (e - e1) / (e2 - e1)));
949 if ((e2 - e1) != 0 && (xs1 == 0 || xs2 == 0)) {
952 value = (d1 + (d2 - d1) * (e - e1) / (e2 - e1));
965 G4double interpolatedvalue1, interpolatedvalue2, value;
966 (xs11 != xs12) ? interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12)
967 : interpolatedvalue1 = xs11;
969 (xs21 != xs22) ? interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22)
970 : interpolatedvalue2 = xs21;
972 (interpolatedvalue1 != interpolatedvalue2)
973 ? value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2)
974 : value = interpolatedvalue1;
const char * G4FindDataDir(const char *)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
static G4DNAMaterialManager * Instance()
void SetMasterDataModel(const DNAModelType &t, G4VEmModel *m)
G4VEmModel * GetModel(const DNAModelType &t)
const std::vector< G4double > * GetNumMolPerVolTableFor(const G4Material *) const
Retrieve a table of molecular densities (number of molecules per unit volume) in the G4 unit system f...
static G4DNAMolecularMaterial * Instance()
The G4DNAPTBIonisationModel class Implements the PTB ionisation model.
G4ParticleChangeForGamma * fParticleChangeForGamma
void Initialise(const G4ParticleDefinition *particle, const G4DataVector &data) override
Initialise Method called once at the beginning of the simulation. It is used to setup the list of the...
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double tmax) override
SampleSecondaries If the model is selected for the ModelInterface then SampleSecondaries will be call...
G4DNAPTBIonisationModel(const G4String &applyToMaterial="all", const G4ParticleDefinition *p=nullptr, const G4String &nam="DNAPTBIonisationModel", const G4bool isAuger=true)
G4DNAPTBIonisationModel Constructor.
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax) override
CrossSectionPerVolume Mandatory for every model the CrossSectionPerVolume method is in charge of retu...
G4double IonisationEnergy(G4int level, const size_t &materialName)
G4int NumberOfLevels(const size_t &materialName)
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * ElectronDefinition()
static G4Electron * Electron()
const G4Material * GetMaterial() const
std::size_t GetIndex() const
const G4String & GetName() const
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
G4double GetPDGMass() const
const G4String & GetParticleName() const
static G4Proton * ProtonDefinition()
void LoadCrossSectionData(const G4ParticleDefinition *particleName)
LoadCrossSectionData Method to loop on all the registered materials in the model and load the corresp...
void SetLowELimit(const size_t &materialID, const G4ParticleDefinition *particle, G4double lim)
SetLowEnergyLimit.
void SetHighELimit(const size_t &materialID, const G4ParticleDefinition *particle, G4double lim)
SetHighEnergyLimit.
G4double GetHighELimit(const size_t &materialID, const G4ParticleDefinition *particle)
GetHighEnergyLimit.
G4int RandomSelectShell(const G4double &k, const G4ParticleDefinition *particle, const size_t &materialName)
RandomSelectShell Method to randomely select a shell from the data table uploaded....
void AddCrossSectionData(const size_t &materialName, const G4ParticleDefinition *particleName, const G4String &fileCS, const G4String &fileDiffCS, const G4double &scaleFactor)
AddCrossSectionData Method used during the initialization of the model class to add a new material....
G4double GetLowELimit(const size_t &materialID, const G4ParticleDefinition *particle)
GetLowEnergyLimit.
MaterialParticleMapData * GetData()
GetTableData.
G4ParticleChangeForGamma * GetParticleChangeForGamma()
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double bindingEnergy(G4int A, G4int Z)