63 G4cout <<
"RPWBA ionisation model is constructed " <<
G4endl;
80 if(lowEnergyLimit == highEnergyLimit)
82 G4Exception(
"G4DNARPWBAIonisationModel::InEnergyLimit",
"em0102",
85 return k >= lowEnergyLimit && k <= highEnergyLimit;
89void G4DNARPWBAIonisationModel::InitialiseForProton(
92 if(part != fProtonDef)
94 G4Exception(
"G4DNARPWBAIonisationModel::InitialiseForProton",
"em0002",
98 G4String fileProton(
"dna/sigma_ionisation_p_RPWBA");
101 lowEnergyLimit = 100. * MeV;
102 highEnergyLimit = 300. * MeV;
107 ed <<
"Model is applicable from "<<lowEnergyLimit<<
" to "<<highEnergyLimit;
108 G4Exception(
"G4DNARPWBAIonisationModel::InitialiseForProton",
"em0004",
112 fpTotalCrossSection = make_unique<G4DNACrossSectionDataSet>(
114 fpTotalCrossSection->LoadData(fileProton);
118 std::ostringstream pFullFileName;
119 fasterCode ? pFullFileName
120 << path <<
"/dna/sigmadiff_cumulated_ionisation_p_RPWBA.dat"
121 : pFullFileName << path <<
"/dna/sigmadiff_ionisation_p_RPWBA.dat";
122 std::ifstream pDiffCrossSection(pFullFileName.str().c_str());
123 if(!pDiffCrossSection)
126 exceptionDescription <<
"Missing data file: " + pFullFileName.str();
127 G4Exception(
"G4DNARPWBAIonisationModel::InitialiseForProton",
"em0003",
131 pTdummyVec.push_back(0.);
132 while(!pDiffCrossSection.eof())
136 pDiffCrossSection >> tDummy >> eDummy;
137 if(tDummy != pTdummyVec.back())
139 pTdummyVec.push_back(tDummy);
142 for(
G4int j = 0; j < 5; j++)
144 pDiffCrossSection >> pDiffCrossSectionData[j][tDummy][eDummy];
148 pNrjTransfData[j][tDummy][pDiffCrossSectionData[j][tDummy][eDummy]] =
150 pProbaShellMap[j][tDummy].push_back(
151 pDiffCrossSectionData[j][tDummy][eDummy]);
155 if(!pDiffCrossSection.eof() && !fasterCode)
157 pDiffCrossSectionData[j][tDummy][eDummy] *= scaleFactor;
162 pVecm[tDummy].push_back(eDummy);
181 G4cout <<
"Calling G4DNARPWBAIonisationModel::Initialise()"
185 InitialiseForProton(particle);
189 G4cout <<
"RPWBA ionisation model is initialized " <<
G4endl
205 exceptionDescription <<
"G4_WATER does not exist :";
206 G4Exception(
"G4DNARPWBAIonisationModel::Initialise",
"em00020",
211 isInitialised =
true;
220 if(particleDefinition != fProtonDef)
222 G4Exception(
"G4DNARPWBAIonisationModel::CrossSectionPerVolume",
"em0402",
227 G4cout <<
"Calling CrossSectionPerVolume() of G4DNARPWBAIonisationModel"
233 if(InEnergyLimit(ekin))
235 sigma = fpTotalCrossSection->FindValue(ekin);
246 G4cout <<
"__________________________________" <<
G4endl;
247 G4cout <<
"G4DNARPWBAIonisationModel - XS INFO START" <<
G4endl;
248 G4cout <<
"Kinetic energy(eV)=" << ekin / eV
250 G4cout <<
"Cross section per water molecule (cm^2)=" << sigma / cm / cm
252 G4cout <<
"Cross section per water molecule (cm^-1)="
253 << sigma * waterDensity / (1. / cm) <<
G4endl;
254 G4cout <<
"G4DNARPWBAIonisationModel - XS INFO END" <<
G4endl;
257 return sigma * waterDensity;
268 G4cout <<
"Calling SampleSecondaries() of G4DNARPWBAIonisationModel"
276 G4double totalEnergy = k + particleMass;
277 G4double pSquare = k * (totalEnergy + particleMass);
278 G4double totalMomentum = std::sqrt(pSquare);
279 G4int ionizationShell;
283 ionizationShell = RandomSelect(k);
290 ionizationShell = RandomSelect(k);
291 }
while(k < 19 * eV && ionizationShell == 2 &&
298 if(k < bindingEnergy)
306 secondaryKinetic = RandomizeEjectedElectronEnergy(k, ionizationShell);
311 RandomizeEjectedElectronEnergyFromCumulatedDcs(k, ionizationShell);
317 particle, secondaryKinetic, Z, ionizationShell, couple->
GetMaterial());
319 if(secondaryKinetic > 0){
322 fvect->push_back(dp);
326 G4double deltaTotalMomentum = std::sqrt(
327 secondaryKinetic * (secondaryKinetic + 2. * electron_mass_c2));
329 G4double finalPx = totalMomentum * primaryDirection.
x() -
330 deltaTotalMomentum * deltaDirection.
x();
331 G4double finalPy = totalMomentum * primaryDirection.
y() -
332 deltaTotalMomentum * deltaDirection.
y();
333 G4double finalPz = totalMomentum * primaryDirection.
z() -
334 deltaTotalMomentum * deltaDirection.
z();
336 std::sqrt(finalPx * finalPx + finalPy * finalPy + finalPz * finalPz);
337 finalPx /= finalMomentum;
338 finalPy /= finalMomentum;
339 finalPz /= finalMomentum;
341 direction.
set(finalPx, finalPy, finalPz);
353 size_t secNumberInit;
358 G4double scatteredEnergy = k - bindingEnergy - secondaryKinetic;
361 if((fAtomDeexcitation !=
nullptr) && ionizationShell == 4)
365 secNumberInit = fvect->size();
367 secNumberFinal = fvect->size();
369 if(secNumberFinal > secNumberInit){
370 for(
size_t i = secNumberInit; i < secNumberFinal; ++i){
371 if(bindingEnergy >= ((*fvect)[i])->GetKineticEnergy())
373 bindingEnergy -= ((*fvect)[i])->GetKineticEnergy();
376 (*fvect)[i] =
nullptr;
383 if(bindingEnergy < 0.0)
385 G4Exception(
"G4DNARPWBAIonisatioModel::SampleSecondaries()",
"em2050",
398 const G4Track* theIncomingTrack =
407G4double G4DNARPWBAIonisationModel::RandomizeEjectedElectronEnergy(
410 G4double maximumKineticEnergyTransfer =
411 4. * (electron_mass_c2 / proton_mass_c2) * k;
416 for(
G4double value = IonisationEnergyInShell;
417 value <= 4. * IonisationEnergyInShell; value += 0.1 * eV)
421 if(differentialCrossSection >= crossSectionMaximum)
423 crossSectionMaximum = differentialCrossSection;
427 G4double secondaryElectronKineticEnergy;
430 secondaryElectronKineticEnergy =
434 (secondaryElectronKineticEnergy +
435 IonisationEnergyInShell) / eV, shell));
437 return secondaryElectronKineticEnergy;
443 const G4int& ionizationLevelIndex)
464 if(k == pTdummyVec.back())
466 k = k * (1. - 1e-12);
469 auto t2 = std::upper_bound(pTdummyVec.begin(), pTdummyVec.end(), k);
472 auto e12 = std::upper_bound(pVecm[(*t1)].begin(), pVecm[(*t1)].end(),
476 auto e22 = std::upper_bound(pVecm[(*t2)].begin(), pVecm[(*t2)].end(),
487 xs11 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
488 xs12 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
489 xs21 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
490 xs22 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
492 G4double xsProduct = xs11 * xs12 * xs21 * xs22;
496 QuadInterpolator(valueE11, valueE12, valueE21, valueE22, xs11, xs12,
497 xs21, xs22, valueT1, valueT2, k, energyTransfer);
515 if(e1 != 0 && e2 != 0 && (std::log10(e2) - std::log10(e1)) != 0 &&
519 (std::log10(xs2) - std::log10(xs1)) / (std::log10(e2) - std::log10(e1));
520 G4double b = std::log10(xs2) - a * std::log10(e2);
521 G4double sigma = a * std::log10(e) + b;
522 value = (std::pow(10., sigma));
535 if((e2 - e1) != 0 && xs1 != 0 && xs2 != 0 && fasterCode)
539 value = std::pow(10., (d1 + (d2 - d1) * (e - e1) / (e2 - e1)));
545 if((e2 - e1) != 0 && (xs1 == 0 || xs2 == 0) && fasterCode)
549 value = (d1 + (d2 - d1) * (e - e1) / (e2 - e1));
556G4double G4DNARPWBAIonisationModel::QuadInterpolator(
562 G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
563 G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
565 Interpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
574 if(fpTotalCrossSection !=
nullptr && particle != fProtonDef)
576 G4Exception(
"G4DNARPWBAIonisationModel::GetPartialCrossSection",
"em0010",
579 return fpTotalCrossSection->GetComponent(level)->FindValue(kineticEnergy);
586 if(fpTotalCrossSection ==
nullptr)
588 G4Exception(
"G4DNARPWBAIonisationModel::RandomSelect",
"em0010",
593 auto valuesBuffer =
new G4double[fpTotalCrossSection->NumberOfComponents()];
594 const auto n = (
G4int)fpTotalCrossSection->NumberOfComponents();
600 valuesBuffer[i] = fpTotalCrossSection->GetComponent(i)->FindValue(k);
601 value += valuesBuffer[i];
609 if(valuesBuffer[i] > value)
611 delete[] valuesBuffer;
614 value -= valuesBuffer[i];
616 delete[] valuesBuffer;
624G4DNARPWBAIonisationModel::RandomizeEjectedElectronEnergyFromCumulatedDcs(
631 if(secondaryKineticEnergy < 0.)
635 return secondaryKineticEnergy;
641 G4int ionizationLevelIndex,
656 if(k == pTdummyVec.back())
658 k = k * (1. - 1e-12);
662 auto k2 = std::upper_bound(pTdummyVec.begin(), pTdummyVec.end(), k);
668 if(random <= pProbaShellMap[ionizationLevelIndex][(*k1)].back() &&
669 random <= pProbaShellMap[ionizationLevelIndex][(*k2)].back())
671 auto prob12 = std::upper_bound(
672 pProbaShellMap[ionizationLevelIndex][(*k1)].begin(),
673 pProbaShellMap[ionizationLevelIndex][(*k1)].end(), random);
674 auto prob11 = prob12 - 1;
675 auto prob22 = std::upper_bound(
676 pProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
677 pProbaShellMap[ionizationLevelIndex][(*k2)].end(), random);
679 auto prob21 = prob22 - 1;
683 valuePROB21 = *prob21;
684 valuePROB22 = *prob22;
685 valuePROB12 = *prob12;
686 valuePROB11 = *prob11;
688 nrjTransf11 = pNrjTransfData[ionizationLevelIndex][valueK1][valuePROB11];
689 nrjTransf12 = pNrjTransfData[ionizationLevelIndex][valueK1][valuePROB12];
690 nrjTransf21 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
691 nrjTransf22 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
697 if(random > pProbaShellMap[ionizationLevelIndex][(*k1)].back())
699 auto prob22 = std::upper_bound(
700 pProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
701 pProbaShellMap[ionizationLevelIndex][(*k2)].end(), random);
702 auto prob21 = prob22 - 1;
706 valuePROB21 = *prob21;
707 valuePROB22 = *prob22;
708 nrjTransf21 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
709 nrjTransf22 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
712 Interpolate(valuePROB21, valuePROB22, random, nrjTransf21, nrjTransf22);
714 G4double value = Interpolate(valueK1, valueK2, k, 0., interpolatedvalue2);
718 nrjTransf11 * nrjTransf12 * nrjTransf21 * nrjTransf22;
720 if(nrjTransfProduct != 0.)
722 nrj = QuadInterpolator(valuePROB11, valuePROB12, valuePROB21, valuePROB22,
723 nrjTransf11, nrjTransf12, nrjTransf21, nrjTransf22,
724 valueK1, valueK2, k, random);
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 G4cout
void set(double x, double y, double z)
static G4DNAChemistryManager * Instance()
void CreateWaterMolecule(ElectronicModification, G4int, const G4Track *)
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()
G4DNARPWBAIonisationModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="DNARPWBAIonisationModel")
~G4DNARPWBAIonisationModel() override
G4ParticleChangeForGamma * fParticleChangeForGamma
void Initialise(const G4ParticleDefinition *, const G4DataVector &= *(new G4DataVector())) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
G4double TransferedEnergy(G4double incomingParticleEnergy, G4int shell, const G4double &random)
G4double DifferentialCrossSection(const G4double &k, const G4double &energyTransfer, const G4int &shell)
G4double GetPartialCrossSection(const G4Material *, G4int, const G4ParticleDefinition *, G4double) override
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax) override
G4double IonisationEnergy(G4int level)
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * ElectronDefinition()
static G4Electron * Electron()
static G4LossTableManager * Instance()
G4VAtomDeexcitation * AtomDeexcitation()
const G4Material * GetMaterial() const
std::size_t GetIndex() 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
virtual const G4AtomicShell * GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)=0
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
virtual G4ThreeVector & SampleDirectionForShell(const G4DynamicParticle *dp, G4double finalTotalEnergy, G4int Z, G4int shellID, const G4Material *)
G4VEmAngularDistribution * GetAngularDistribution()
G4ParticleChangeForGamma * GetParticleChangeForGamma()
G4double LowEnergyLimit() const
G4double HighEnergyLimit() const
void SetDeexcitationFlag(G4bool val)
void SetAngularDistribution(G4VEmAngularDistribution *)
const G4Track * GetCurrentTrack() const
void ProposeLocalEnergyDeposit(G4double anEnergyPart)