72 fAtomDeexcitation =
nullptr;
73 fMaterialDensity =
nullptr;
74 fParticleDefinition =
nullptr;
79 G4cout <<
"Relativistic Ionisation Model is constructed " <<
G4endl;
97 "Calling G4DNARelativisticIonisationModel::Initialise()"
102 if(fParticleDefinition !=
nullptr && fParticleDefinition != particle)
104 G4Exception(
"G4DNARelativisticIonisationModel::Initialise",
"em0001",
105 FatalException,
"Model already initialized for another particle type.");
108 fParticleDefinition = particle;
110 if(particle == electronDef)
112 fLowEnergyLimit = 10 * eV;
113 fHighEnergyLimit = 1.0 * GeV;
115 std::ostringstream eFullFileNameZ;
120 G4Exception(
"G4DNARelativisticIonisationModel::Initialise",
"em0006",
128 auto Ncouple = (
G4int)coupletable ->GetTableSize();
129 for(
G4int i=0; i<Ncouple; ++i)
144 iSubShell [Z].clear();
145 Nelectrons[Z].clear();
146 Ebinding [Z].clear();
147 Ekinetic [Z].clear();
153 eProbaShellMapZ.clear();
154 eDiffCrossSectionDataZ.clear();
156 eFullFileNameZ.str(
"");
157 eFullFileNameZ.clear(stringstream::goodbit);
161 <<
"/dna/sigmadiff_cumulated_ionisation_e_RBEBV_Z"
163 std::ifstream eDiffCrossSectionZ(eFullFileNameZ.str().c_str());
164 if (!eDiffCrossSectionZ)
165 G4Exception(
"G4DNARelativisticIonisationModel::Initialise",
"em0003",
167 "Missing data file for cumulated DCS");
169 eVecEZ[Z].push_back(0.);
170 while(!eDiffCrossSectionZ.eof())
174 eDiffCrossSectionZ>>tDummy>>eDummy;
175 if (tDummy != eVecEZ[Z].back())
177 eVecEZ[Z].push_back(tDummy);
178 eVecEjeEZ[Z][tDummy].push_back(0.);
181 for(
G4int istate=0;istate<(
G4int)iState[Z].size();istate++)
184 eDiffCrossSectionDataZ[Z][istate][tDummy][eDummy];
185 eEjectedEnergyDataZ[Z][istate][tDummy]
186 [eDiffCrossSectionDataZ[Z][istate][tDummy][eDummy]]
188 eProbaShellMapZ[Z][istate][tDummy].push_back(
189 eDiffCrossSectionDataZ[Z][istate][tDummy][eDummy]);
192 if (eDummy != eVecEjeEZ[Z][tDummy].back()){
193 eVecEjeEZ[Z][tDummy].push_back(eDummy);
202 "Error : No particle Definition is found in G4DNARelativisticIonisationModel"
209 G4cout <<
"Relativistic Ionisation model is initialized " <<
G4endl
224 if (isInitialised){
return;}
225 isInitialised =
true;
237 if (verboseLevel > 3)
240 "Calling CrossSectionPerVolume() of G4DNARelativisticIonisationModel"
244 if(particleDefinition != fParticleDefinition)
return 0;
253 if(atomicNDensity!= 0.0)
255 if (ekin >= fLowEnergyLimit && ekin < fHighEnergyLimit)
260 if (verboseLevel > 2)
262 G4cout <<
"__________________________________" <<
G4endl;
263 G4cout <<
"=== G4DNARelativisticIonisationModel - XS INFO START" <<
G4endl;
264 G4cout <<
"=== Kinetic energy (eV)=" << ekin/eV <<
" particle : "
266 G4cout <<
"=== Cross section per atom for Z="<<z<<
" is (cm^2)"
268 G4cout <<
"=== Cross section per atom for Z="<<z<<
" is (cm^-1)="
269 << sigma*atomicNDensity/(1./cm) <<
G4endl;
270 G4cout <<
"=== G4DNARelativisticIonisationModel - XS INFO END" <<
G4endl;
273 return sigma*atomicNDensity;
279 std::vector<G4DynamicParticle*>* fvect,
284 if (verboseLevel > 3)
287 "Calling SampleSecondaries() of G4DNARelativisticIonisationModel"
296 if(fLowEnergyLimit <= k && k<fHighEnergyLimit)
301 G4double totalEnergy = k+particleMass;
302 G4double pSquare = k*(totalEnergy+particleMass);
303 G4double totalMomentum = std::sqrt(pSquare);
307 G4int level = RandomSelect(material,particleDef,k);
309 if(k<Ebinding[z].at(level))
return;
311 G4int NumSecParticlesInit =0;
312 G4int NumSecParticlesFinal=0;
314 if(fAtomDeexcitation !=
nullptr){
317 NumSecParticlesInit = (
G4int)fvect->size();
319 NumSecParticlesFinal = (
G4int)fvect->size();
323 = GetEjectedElectronEnergy (material,particleDef,k,level);
325 = GetEjectedElectronDirection(particleDef,k,ejectedE);
328 G4double scatteredE = k - Ebinding[z].at(level) - ejectedE;
332 = std::sqrt(ejectedE*(ejectedE+2*CLHEP::electron_mass_c2));
334 = totalMomentum*primaryDir.
x()- secondaryTotMomentum*ejectedDir.
x();
336 = totalMomentum*primaryDir.
y()- secondaryTotMomentum*ejectedDir.
y();
338 = totalMomentum*primaryDir.
z()- secondaryTotMomentum*ejectedDir.
z();
340 G4ThreeVector scatteredDir(finalMomentumX,finalMomentumY,finalMomentumZ);
350 G4double restEproduction = Ebinding[z].at(level);
351 for(
G4int iparticle=NumSecParticlesInit;
352 iparticle<NumSecParticlesFinal;iparticle++)
355 G4double Edeex = (*fvect)[iparticle]->GetKineticEnergy();
356 if(restEproduction>=Edeex){
357 restEproduction -= Edeex;
360 delete (*fvect)[iparticle];
361 (*fvect)[iparticle]=
nullptr;
364 if(restEproduction < 0.0){
365 G4Exception(
"G4DNARelativisticIonisationModel::SampleSecondaries()",
387 fvect->push_back(ejectedelectron);
393 G4int z,
const char* path)
396 if (verboseLevel > 3)
399 "Calling LoadAtomicStates() of G4DNARelativisticIonisationModel"
402 const char *datadir = path;
403 if(datadir ==
nullptr)
406 if(datadir ==
nullptr)
408 G4Exception(
"G4DNARelativisticIonisationModel::LoadAtomicStates()",
409 "em0002",
FatalException,
"Enviroment variable G4LEDATA not defined");
414 std::ostringstream targetfile;
415 targetfile << datadir <<
"/dna/atomicstate_Z"<< z <<
".dat";
416 std::ifstream fin(targetfile.str().c_str());
419 G4cout<<
" Error : "<< targetfile.str() <<
" is not found "<<
G4endl;
420 G4Exception(
"G4DNARelativisticIonisationModel::LoadAtomicStates()",
"em0002",
425 G4String buff0,buff1,buff2,buff3,buff4,buff5,buff6;
426 fin >> buff0 >>buff1>>buff2>>buff3>>buff4>>buff5>>buff6;
429 fin >> buff0 >>buff1>>buff2>>buff3>>buff4>>buff5>>buff6;
432 iState [z].push_back(stoi(buff0));
433 iShell [z].push_back(stoi(buff1));
434 iSubShell [z].push_back(stoi(buff2));
435 Nelectrons[z].push_back(stoi(buff3));
436 Ebinding [z].push_back(stod(buff4));
440 G4double radius = std::pow(iShell[z].at(iline),2)
441 *std::pow(CLHEP::hbar_Planck,2)*(4*CLHEP::pi*CLHEP::epsilon0)
442 /CLHEP::electron_mass_c2;
443 G4double momentum = iShell[z].at(iline)*CLHEP::hbar_Planck/radius;
444 Ekinetic[z].push_back(std::pow(momentum,2)/(2*CLHEP::electron_mass_c2));
448 Ekinetic [z].push_back(stod(buff5));
468 if(z!=79){
return 0.;}
470 std::size_t
N=iState[z].size();
490 if(particle==electronDef){
492 G4double t = kineticEnergy /Ebinding[z].at(level);
493 G4double tdash = kineticEnergy /CLHEP::electron_mass_c2;
494 G4double udash = Ekinetic[z].at(level)/CLHEP::electron_mass_c2;
495 G4double bdash = Ebinding[z].at(level)/CLHEP::electron_mass_c2;
496 G4double beta_t2 = 1.-1./std::pow(1.+tdash,2);
497 G4double beta_u2 = 1.-1./std::pow(1.+udash,2);
498 G4double beta_b2 = 1.-1./std::pow(1.+bdash,2);
499 G4double alpha = std::sqrt(2*constRy/CLHEP::electron_mass_c2);
500 G4double phi = std::cos(std::sqrt(std::pow(alpha,2)
501 /(beta_t2+beta_b2))*
G4Log(beta_t2/beta_b2));
502 G4double constS = 4*CLHEP::pi*std::pow(CLHEP::Bohr_radius,2)
503 *Nelectrons[z].at(level)*std::pow(alpha,4);
505 if(Ebinding[z].at(level)<=kineticEnergy)
507 value =constS/((beta_t2+(beta_u2+beta_b2)/iShell[z].at(level))*2.*bdash)
508 *(1./2.*(
G4Log(beta_t2/(1.-beta_t2))-beta_t2-
G4Log(2.*bdash))
509 *(1.-1./std::pow(t,2.))
510 +1.-1./t-
G4Log(t)/(t+1.)*(1.+2.*tdash)/(std::pow(1.+tdash/2.,2.))
511 *phi+std::pow(bdash,2)/(std::pow(1+tdash/2.,2))*(t-1)/2.);
533 if(particle==electronDef){
534 G4double w = secondaryEnergy /Ebinding[z].at(level);
535 G4double t = kineticEnergy /Ebinding[z].at(level);
536 G4double tdash = kineticEnergy /CLHEP::electron_mass_c2;
537 G4double udash = Ekinetic[z].at(level)/CLHEP::electron_mass_c2;
538 G4double bdash = Ebinding[z].at(level)/CLHEP::electron_mass_c2;
539 G4double beta_t2 = 1.-1./std::pow(1.+tdash,2);
540 G4double beta_u2 = 1.-1./std::pow(1.+udash,2);
541 G4double beta_b2 = 1.-1./std::pow(1.+bdash,2);
542 G4double alpha = std::sqrt(2*constRy/CLHEP::electron_mass_c2);
543 G4double phi = std::cos(std::sqrt(std::pow(alpha,2)/(beta_t2+beta_b2))
544 *
G4Log(beta_t2/beta_b2));
545 G4double constS = 4*CLHEP::pi*std::pow(CLHEP::Bohr_radius,2)
546 *Nelectrons[z].at(level)*std::pow(alpha,4);
548 if(secondaryEnergy<=((kineticEnergy-Ebinding[z].at(level))/2.))
550 value = constS/((beta_t2+(beta_u2+beta_b2)/iShell[z].at(level))*2.*bdash)
551 *(-phi/(t+1.)*(1./std::pow(w+1.,1.)+1./std::pow(t-w,1.))
552 *(1.+2*tdash)/std::pow(1.+tdash/2.,2.)
553 +1./std::pow(w+1.,2.)+1./std::pow(t-w,2.)
554 +std::pow(bdash,2)/std::pow(1+tdash/2.,2)
555 +(1./std::pow(w+1.,3.)+1./std::pow(t-w,3.))
556 *(
G4Log(beta_t2/(1.-beta_t2))-beta_t2-
G4Log(2*bdash)));
564G4int G4DNARelativisticIonisationModel::RandomSelect(
571 std::size_t numberOfShell = iShell[z].size();
572 std::vector<G4double> valuesBuffer(numberOfShell, 0.0);
573 const auto n = (
G4int)iShell[z].size();
579 if((fLowEnergyLimit<=kineticEnergy)&&(kineticEnergy<fHighEnergyLimit))
583 value += valuesBuffer[i];
593 if (valuesBuffer[i] > value)
597 value -= valuesBuffer[i];
606G4double G4DNARelativisticIonisationModel::GetEjectedElectronEnergy(
616 if(particle==electronDef){
617 G4double maximumsecondaryEnergy = (
energy-Ebinding[z].at(ishell))/2.;
618 if(maximumsecondaryEnergy<0.)
return 0.;
627 material,particle,energy,secondaryEnergy,ishell));
646 if((eVecEZ[z].at(0)<=energy)&&(energy<eVecEZ[z].back()))
649 = std::upper_bound(eVecEZ[z].begin(),eVecEZ[z].end(), energy);
652 if ( random < eProbaShellMapZ[z][ishell][(*k1)].back()
653 && random < eProbaShellMapZ[z][ishell][(*k2)].back() )
656 std::upper_bound(eProbaShellMapZ[z][ishell][(*k1)].begin(),
657 eProbaShellMapZ[z][ishell][(*k1)].end(), random);
661 std::upper_bound(eProbaShellMapZ[z][ishell][(*k2)].begin(),
662 eProbaShellMapZ[z][ishell][(*k2)].end(), random);
672 ejeE11 = eEjectedEnergyDataZ[z][ishell][valueE1][valueXS11];
673 ejeE12 = eEjectedEnergyDataZ[z][ishell][valueE1][valueXS12];
674 ejeE21 = eEjectedEnergyDataZ[z][ishell][valueE2][valueXS21];
675 ejeE22 = eEjectedEnergyDataZ[z][ishell][valueE2][valueXS22];
677 secondaryEnergy = QuadInterpolator( valueXS11, valueXS12,
678 valueXS21, valueXS22,
688 if(secondaryEnergy<0) secondaryEnergy=0;
689 return secondaryEnergy;
694G4ThreeVector G4DNARelativisticIonisationModel::GetEjectedElectronDirection(
699 G4double sintheta = std::sqrt((1.-secondaryenergy/energy)
700 / (1.+secondaryenergy/(2*CLHEP::electron_mass_c2)));
702 G4double dirX = sintheta*std::cos(phi);
703 G4double dirY = sintheta*std::sin(phi);
704 G4double dirZ = std::sqrt(1.-sintheta*sintheta);
721 if((xs1!=0)&&(e1!=0)){
723 G4double a = (std::log10(xs2)-std::log10(xs1))
724 / (std::log10(e2)-std::log10(e1));
725 G4double b = std::log10(xs2) - a*std::log10(e2);
726 G4double sigma = a*std::log10(e) + b;
727 value = (std::pow(10.,sigma));
733 value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
741G4double G4DNARelativisticIonisationModel::QuadInterpolator(
749 G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
750 G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
752 = Interpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
const char * G4FindDataDir(const char *)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4Log(G4double x)
G4GLOB_DLL std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
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()
virtual void LoadAtomicStates(G4int z, const char *path)
virtual G4double GetTotalCrossSection(const G4Material *material, const G4ParticleDefinition *, G4double kineticEnergy)
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &= *(new G4DataVector())) override
G4double GetPartialCrossSection(const G4Material *material, G4int level, const G4ParticleDefinition *, G4double kineticEnergy) override
~G4DNARelativisticIonisationModel() override
G4DNARelativisticIonisationModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="DNARelativisticIonisationModel")
virtual G4double GetDifferentialCrossSection(const G4Material *material, const G4ParticleDefinition *particle, G4double kineticEnergy, G4double secondaryEnergy, G4int level)
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax) override
G4ParticleChangeForGamma * fParticleChangeForGamma
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
const G4double * GetAtomicNumDensityVector() const
std::size_t GetNumberOfElements() 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
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4ProductionCutsTable * GetProductionCutsTable()
virtual const G4AtomicShell * GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)=0
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
G4ParticleChangeForGamma * GetParticleChangeForGamma()
G4double LowEnergyLimit() const
G4double HighEnergyLimit() const
void SetDeexcitationFlag(G4bool val)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double energy(const ThreeVector &p, const G4double m)