64G4VEmModel(nam), isInitialised(false),statCode(false),fasterCode(true)
72 fAtomDeexcitation = 0;
74 fParticleDefinition = 0;
79 G4cout <<
"Relativistic Ionisation Model is constructed " <<
G4endl;
99 "Calling G4DNARelativisticIonisationModel::Initialise()"
104 if(fParticleDefinition != 0 && fParticleDefinition != particle)
106 G4Exception(
"G4DNARelativisticIonisationModel::Initialise",
"em0001",
107 FatalException,
"Model already initialized for another particle type.");
110 fParticleDefinition = particle;
112 if(particle == electronDef)
114 fLowEnergyLimit = 10 * eV;
115 fHighEnergyLimit = 1.0 * GeV;
117 std::ostringstream eFullFileNameZ;
122 G4Exception(
"G4DNARelativisticIonisationModel::Initialise",
"em0006",
130 G4int Ncouple = (
G4int)coupletable ->GetTableSize();
131 for(
G4int i=0; i<Ncouple; ++i)
146 iSubShell [
Z].clear();
147 Nelectrons[
Z].clear();
148 Ebinding [
Z].clear();
149 Ekinetic [
Z].clear();
155 eProbaShellMapZ.clear();
156 eDiffCrossSectionDataZ.clear();
158 eFullFileNameZ.str(
"");
159 eFullFileNameZ.clear(stringstream::goodbit);
163 <<
"/dna/sigmadiff_cumulated_ionisation_e_RBEBV_Z"
165 std::ifstream eDiffCrossSectionZ(eFullFileNameZ.str().c_str());
166 if (!eDiffCrossSectionZ)
167 G4Exception(
"G4DNARelativisticIonisationModel::Initialise",
"em0003",
169 "Missing data file for cumulated DCS");
171 eVecEZ[
Z].push_back(0.);
172 while(!eDiffCrossSectionZ.eof())
176 eDiffCrossSectionZ>>tDummy>>eDummy;
177 if (tDummy != eVecEZ[
Z].back())
179 eVecEZ[
Z].push_back(tDummy);
180 eVecEjeEZ[
Z][tDummy].push_back(0.);
183 for(
G4int istate=0;istate<(
G4int)iState[
Z].size();istate++)
186 eDiffCrossSectionDataZ[
Z][istate][tDummy][eDummy];
187 eEjectedEnergyDataZ[
Z][istate][tDummy]
188 [eDiffCrossSectionDataZ[
Z][istate][tDummy][eDummy]]
190 eProbaShellMapZ[
Z][istate][tDummy].push_back(
191 eDiffCrossSectionDataZ[
Z][istate][tDummy][eDummy]);
194 if (eDummy != eVecEjeEZ[
Z][tDummy].back()){
195 eVecEjeEZ[
Z][tDummy].push_back(eDummy);
204 "Error : No particle Definition is found in G4DNARelativisticIonisationModel"
211 G4cout <<
"Relativistic Ionisation model is initialized " <<
G4endl
226 if (isInitialised){
return;}
227 isInitialised =
true;
239 if (verboseLevel > 3)
242 "Calling CrossSectionPerVolume() of G4DNARelativisticIonisationModel"
246 if(particleDefinition != fParticleDefinition)
return 0;
255 if(atomicNDensity!= 0.0)
257 if (ekin >= fLowEnergyLimit && ekin < fHighEnergyLimit)
262 if (verboseLevel > 2)
264 G4cout <<
"__________________________________" <<
G4endl;
265 G4cout <<
"=== G4DNARelativisticIonisationModel - XS INFO START" <<
G4endl;
266 G4cout <<
"=== Kinetic energy (eV)=" << ekin/eV <<
" particle : "
268 G4cout <<
"=== Cross section per atom for Z="<<z<<
" is (cm^2)"
270 G4cout <<
"=== Cross section per atom for Z="<<z<<
" is (cm^-1)="
271 << sigma*atomicNDensity/(1./cm) <<
G4endl;
272 G4cout <<
"=== G4DNARelativisticIonisationModel - XS INFO END" <<
G4endl;
275 return sigma*atomicNDensity;
281 std::vector<G4DynamicParticle*>* fvect,
286 if (verboseLevel > 3)
289 "Calling SampleSecondaries() of G4DNARelativisticIonisationModel"
298 if(fLowEnergyLimit <= k && k<fHighEnergyLimit)
303 G4double totalEnergy = k+particleMass;
304 G4double pSquare = k*(totalEnergy+particleMass);
305 G4double totalMomentum = std::sqrt(pSquare);
309 G4int level = RandomSelect(material,particleDef,k);
311 if(k<Ebinding[z].at(level))
return;
313 G4int NumSecParticlesInit =0;
314 G4int NumSecParticlesFinal=0;
316 if(fAtomDeexcitation){
319 NumSecParticlesInit = (
G4int)fvect->size();
321 NumSecParticlesFinal = (
G4int)fvect->size();
325 = GetEjectedElectronEnergy (material,particleDef,k,level);
327 = GetEjectedElectronDirection(particleDef,k,ejectedE);
330 G4double scatteredE = k - Ebinding[z].at(level) - ejectedE;
334 = std::sqrt(ejectedE*(ejectedE+2*CLHEP::electron_mass_c2));
336 = totalMomentum*primaryDir.
x()- secondaryTotMomentum*ejectedDir.
x();
338 = totalMomentum*primaryDir.
y()- secondaryTotMomentum*ejectedDir.
y();
340 = totalMomentum*primaryDir.
z()- secondaryTotMomentum*ejectedDir.
z();
342 G4ThreeVector scatteredDir(finalMomentumX,finalMomentumY,finalMomentumZ);
352 G4double restEproduction = Ebinding[z].at(level);
353 for(
G4int iparticle=NumSecParticlesInit;
354 iparticle<NumSecParticlesFinal;iparticle++)
357 G4double Edeex = (*fvect)[iparticle]->GetKineticEnergy();
358 if(restEproduction>=Edeex){
359 restEproduction -= Edeex;
362 delete (*fvect)[iparticle];
363 (*fvect)[iparticle]=0;
366 if(restEproduction < 0.0){
367 G4Exception(
"G4DNARelativisticIonisationModel::SampleSecondaries()",
389 fvect->push_back(ejectedelectron);
395 G4int z,
const char* path)
398 if (verboseLevel > 3)
401 "Calling LoadAtomicStates() of G4DNARelativisticIonisationModel"
404 const char *datadir = path;
410 G4Exception(
"G4DNARelativisticIonisationModel::LoadAtomicStates()",
411 "em0002",
FatalException,
"Enviroment variable G4LEDATA not defined");
416 std::ostringstream targetfile;
417 targetfile << datadir <<
"/dna/atomicstate_Z"<< z <<
".dat";
418 std::ifstream fin(targetfile.str().c_str());
421 G4cout<<
" Error : "<< targetfile.str() <<
" is not found "<<
G4endl;
422 G4Exception(
"G4DNARelativisticIonisationModel::LoadAtomicStates()",
"em0002",
427 G4String buff0,buff1,buff2,buff3,buff4,buff5,buff6;
428 fin >> buff0 >>buff1>>buff2>>buff3>>buff4>>buff5>>buff6;
431 fin >> buff0 >>buff1>>buff2>>buff3>>buff4>>buff5>>buff6;
434 iState [z].push_back(stoi(buff0));
435 iShell [z].push_back(stoi(buff1));
436 iSubShell [z].push_back(stoi(buff2));
437 Nelectrons[z].push_back(stoi(buff3));
438 Ebinding [z].push_back(stod(buff4));
442 G4double radius = std::pow(iShell[z].at(iline),2)
443 *std::pow(CLHEP::hbar_Planck,2)*(4*CLHEP::pi*CLHEP::epsilon0)
444 /CLHEP::electron_mass_c2;
445 G4double momentum = iShell[z].at(iline)*CLHEP::hbar_Planck/radius;
446 Ekinetic[z].push_back(std::pow(momentum,2)/(2*CLHEP::electron_mass_c2));
450 Ekinetic [z].push_back(stod(buff5));
470 if(z!=79){
return 0.;}
472 std::size_t
N=iState[z].size();
493 if(particle==electronDef){
495 G4double t = kineticEnergy /Ebinding[z].at(level);
496 G4double tdash = kineticEnergy /CLHEP::electron_mass_c2;
497 G4double udash = Ekinetic[z].at(level)/CLHEP::electron_mass_c2;
498 G4double bdash = Ebinding[z].at(level)/CLHEP::electron_mass_c2;
499 G4double beta_t2 = 1.-1./std::pow(1.+tdash,2);
500 G4double beta_u2 = 1.-1./std::pow(1.+udash,2);
501 G4double beta_b2 = 1.-1./std::pow(1.+bdash,2);
502 G4double alpha = std::sqrt(2*constRy/CLHEP::electron_mass_c2);
503 G4double phi = std::cos(std::sqrt(std::pow(alpha,2)
504 /(beta_t2+beta_b2))*
G4Log(beta_t2/beta_b2));
505 G4double constS = 4*CLHEP::pi*std::pow(CLHEP::Bohr_radius,2)
506 *Nelectrons[z].at(level)*std::pow(alpha,4);
508 if(Ebinding[z].at(level)<=kineticEnergy)
510 value =constS/((beta_t2+(beta_u2+beta_b2)/iShell[z].at(level))*2.*bdash)
511 *(1./2.*(
G4Log(beta_t2/(1.-beta_t2))-beta_t2-
G4Log(2.*bdash))
512 *(1.-1./std::pow(t,2.))
513 +1.-1./t-
G4Log(t)/(t+1.)*(1.+2.*tdash)/(std::pow(1.+tdash/2.,2.))
514 *phi+std::pow(bdash,2)/(std::pow(1+tdash/2.,2))*(t-1)/2.);
536 if(particle==electronDef){
537 G4double w = secondaryEnergy /Ebinding[z].at(level);
538 G4double t = kineticEnergy /Ebinding[z].at(level);
539 G4double tdash = kineticEnergy /CLHEP::electron_mass_c2;
540 G4double udash = Ekinetic[z].at(level)/CLHEP::electron_mass_c2;
541 G4double bdash = Ebinding[z].at(level)/CLHEP::electron_mass_c2;
542 G4double beta_t2 = 1.-1./std::pow(1.+tdash,2);
543 G4double beta_u2 = 1.-1./std::pow(1.+udash,2);
544 G4double beta_b2 = 1.-1./std::pow(1.+bdash,2);
545 G4double alpha = std::sqrt(2*constRy/CLHEP::electron_mass_c2);
546 G4double phi = std::cos(std::sqrt(std::pow(alpha,2)/(beta_t2+beta_b2))
547 *
G4Log(beta_t2/beta_b2));
548 G4double constS = 4*CLHEP::pi*std::pow(CLHEP::Bohr_radius,2)
549 *Nelectrons[z].at(level)*std::pow(alpha,4);
551 if(secondaryEnergy<=((kineticEnergy-Ebinding[z].at(level))/2.))
553 value = constS/((beta_t2+(beta_u2+beta_b2)/iShell[z].at(level))*2.*bdash)
554 *(-phi/(t+1.)*(1./std::pow(w+1.,1.)+1./std::pow(t-w,1.))
555 *(1.+2*tdash)/std::pow(1.+tdash/2.,2.)
556 +1./std::pow(w+1.,2.)+1./std::pow(t-w,2.)
557 +std::pow(bdash,2)/std::pow(1+tdash/2.,2)
558 +(1./std::pow(w+1.,3.)+1./std::pow(t-w,3.))
559 *(
G4Log(beta_t2/(1.-beta_t2))-beta_t2-
G4Log(2*bdash)));
567G4int G4DNARelativisticIonisationModel::RandomSelect(
574 std::size_t numberOfShell = iShell[z].size();
575 auto valuesBuffer =
new G4double[numberOfShell];
582 if((fLowEnergyLimit<=kineticEnergy)&&(kineticEnergy<fHighEnergyLimit))
586 value += valuesBuffer[i];
596 if (valuesBuffer[i] > value)
598 delete[] valuesBuffer;
601 value -= valuesBuffer[i];
604 if (valuesBuffer)
delete[] valuesBuffer;
612G4double G4DNARelativisticIonisationModel::GetEjectedElectronEnergy(
622 if(particle==electronDef){
623 G4double maximumsecondaryEnergy = (
energy-Ebinding[z].at(ishell))/2.;
624 if(maximumsecondaryEnergy<0.)
return 0.;
633 material,particle,energy,secondaryEnergy,ishell));
652 if((eVecEZ[z].at(0)<=energy)&&(energy<eVecEZ[z].back()))
654 std::vector<G4double>::iterator k2
655 = std::upper_bound(eVecEZ[z].begin(),eVecEZ[z].end(), energy);
656 std::vector<G4double>::iterator k1 = k2-1;
658 if ( random < eProbaShellMapZ[z][ishell][(*k1)].back()
659 && random < eProbaShellMapZ[z][ishell][(*k2)].back() )
661 std::vector<G4double>::iterator xs12 =
662 std::upper_bound(eProbaShellMapZ[z][ishell][(*k1)].begin(),
663 eProbaShellMapZ[z][ishell][(*k1)].end(), random);
664 std::vector<G4double>::iterator xs11 = xs12-1;
666 std::vector<G4double>::iterator xs22 =
667 std::upper_bound(eProbaShellMapZ[z][ishell][(*k2)].begin(),
668 eProbaShellMapZ[z][ishell][(*k2)].end(), random);
669 std::vector<G4double>::iterator xs21 = xs22-1;
678 ejeE11 = eEjectedEnergyDataZ[z][ishell][valueE1][valueXS11];
679 ejeE12 = eEjectedEnergyDataZ[z][ishell][valueE1][valueXS12];
680 ejeE21 = eEjectedEnergyDataZ[z][ishell][valueE2][valueXS21];
681 ejeE22 = eEjectedEnergyDataZ[z][ishell][valueE2][valueXS22];
683 secondaryEnergy = QuadInterpolator( valueXS11, valueXS12,
684 valueXS21, valueXS22,
694 if(secondaryEnergy<0) secondaryEnergy=0;
695 return secondaryEnergy;
700G4ThreeVector G4DNARelativisticIonisationModel::GetEjectedElectronDirection(
705 G4double sintheta = std::sqrt((1.-secondaryenergy/energy)
706 / (1.+secondaryenergy/(2*CLHEP::electron_mass_c2)));
708 G4double dirX = sintheta*std::cos(phi);
709 G4double dirY = sintheta*std::sin(phi);
710 G4double dirZ = std::sqrt(1.-sintheta*sintheta);
727 if((xs1!=0)&&(e1!=0)){
729 G4double a = (std::log10(xs2)-std::log10(xs1))
730 / (std::log10(e2)-std::log10(e1));
731 G4double b = std::log10(xs2) - a*std::log10(e2);
732 G4double sigma = a*std::log10(e) + b;
733 value = (std::pow(10.,sigma));
739 value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
747G4double G4DNARelativisticIonisationModel::QuadInterpolator(
755 G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
756 G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
758 = 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 Initialise(const G4ParticleDefinition *, const G4DataVector &= *(new G4DataVector()))
virtual void LoadAtomicStates(G4int z, const char *path)
virtual ~G4DNARelativisticIonisationModel()
virtual G4double GetTotalCrossSection(const G4Material *material, const G4ParticleDefinition *, G4double kineticEnergy)
G4DNARelativisticIonisationModel(const G4ParticleDefinition *p=0, const G4String &nam="DNARelativisticIonisationModel")
virtual G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax)
virtual G4double GetPartialCrossSection(const G4Material *material, G4int level, const G4ParticleDefinition *, G4double kineticEnergy)
virtual G4double GetDifferentialCrossSection(const G4Material *material, const G4ParticleDefinition *particle, G4double kineticEnergy, G4double secondaryEnergy, G4int level)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
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
size_t GetNumberOfElements() const
const G4double * GetAtomicNumDensityVector() 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)