Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/dna/models/src/G4DNARelativisticIonisationModel.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 // $Id: G4DNARelativisticIonisationModel.cc $
 27 //
 28 // Created on 2016/05/12
 29 //
 30 // Authors: D Sakata, S. Incerti
 31 //
 32 // This class perform ionisation for electron transportation in gold,
 33 // based on Relativistic Binary Encounter Bethe-Vriens(RBEBV) model.
 34 // See following reference paper, 
 35 // M. Guerra et al, J. Phys. B: At. Mol. Opt. Phys. 48, 185202 (2015)
 36 // =======================================================================
 37 // Limitation of secondaries by GEANT4 atomic de-excitation:
 38 // The cross section and energy of secondary production is based on 
 39 // EADL database. If there are no tabele for several orbitals, this class
 40 // will not provide secondaries for the orbitals.
 41 // For gold(Au), this class provide secondaries for inner 18 orbitals
 42 // but don't provide for outer 3 orbitals due to EADL databese limitation. 
 43 // =======================================================================
 44 
 45 #include "G4DNARelativisticIonisationModel.hh"
 46 #include "G4SystemOfUnits.hh"
 47 #include "G4AtomicShell.hh"
 48 #include "G4UAtomicDeexcitation.hh"
 49 #include "G4LossTableManager.hh"
 50 #include "G4Gamma.hh"
 51 #include "G4RandomDirection.hh"
 52 
 53 #include "G4DNAMolecularMaterial.hh"
 54 
 55 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 56 
 57 using namespace std;
 58 
 59 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 60 
 61 G4DNARelativisticIonisationModel::G4DNARelativisticIonisationModel(
 62                 const G4ParticleDefinition*,
 63                 const G4String& nam) :
 64 G4VEmModel(nam), fasterCode(true)
 65 {
 66   fHighEnergyLimit        = 0;
 67   fLowEnergyLimit         = 0;
 68 
 69   verboseLevel = 0;
 70 
 71   SetDeexcitationFlag(true);
 72   fAtomDeexcitation       = nullptr;
 73   fMaterialDensity        = nullptr;
 74   fParticleDefinition     = nullptr;
 75   fParticleChangeForGamma = nullptr;
 76 
 77   if (verboseLevel > 0)
 78   {
 79     G4cout << "Relativistic Ionisation Model is constructed " << G4endl;
 80   }
 81 }
 82 
 83 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 84 
 85 G4DNARelativisticIonisationModel::~G4DNARelativisticIonisationModel()
 86 = default;
 87 
 88 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 89 
 90 void G4DNARelativisticIonisationModel::Initialise(const G4ParticleDefinition* particle,
 91                                            const G4DataVector& /*cuts*/)
 92 {
 93 
 94   if (verboseLevel > 3)
 95   {
 96     G4cout << 
 97     "Calling G4DNARelativisticIonisationModel::Initialise()"
 98     << G4endl;
 99   }
100 
101 
102   if(fParticleDefinition != nullptr && fParticleDefinition != particle)
103   {
104     G4Exception("G4DNARelativisticIonisationModel::Initialise","em0001",
105         FatalException,"Model already initialized for another particle type.");
106   }
107 
108   fParticleDefinition = particle;
109   G4ParticleDefinition *electronDef = G4Electron::ElectronDefinition();
110   if(particle == electronDef)
111   {
112     fLowEnergyLimit           =  10  *  eV;
113     fHighEnergyLimit          =  1.0 * GeV;
114 
115     std::ostringstream eFullFileNameZ;
116 
117     const char *path = G4FindDataDir("G4LEDATA");
118     if (path == nullptr)
119     {
120       G4Exception("G4DNARelativisticIonisationModel::Initialise","em0006",
121         FatalException,"G4LEDATA environment variable not set.");
122       return;
123     }
124 
125 
126     G4ProductionCutsTable *coupletable 
127                   = G4ProductionCutsTable::GetProductionCutsTable();
128     auto  Ncouple = (G4int)coupletable ->GetTableSize();
129     for(G4int i=0; i<Ncouple; ++i)
130     {
131       const G4MaterialCutsCouple* couple   
132                            = coupletable->GetMaterialCutsCouple(i);
133       const G4Material          * material = couple     ->GetMaterial();
134       {
135         // Protection: only for single element
136         if(material->GetNumberOfElements()>1) continue; 
137 
138         G4int Z = material->GetZ();
139         // Protection: only for GOLD
140         if(Z!=79) continue;
141 
142         iState    [Z].clear();
143         iShell    [Z].clear();
144         iSubShell [Z].clear();
145         Nelectrons[Z].clear();
146         Ebinding  [Z].clear();
147         Ekinetic  [Z].clear();
148         LoadAtomicStates(Z,path);
149 
150         /////////////Load cumulated DCS////////////////
151         eVecEZ.clear();
152         eVecEjeEZ.clear();
153         eProbaShellMapZ.clear();
154         eDiffCrossSectionDataZ.clear();
155 
156         eFullFileNameZ.str("");
157         eFullFileNameZ.clear(stringstream::goodbit);
158               
159         eFullFileNameZ
160           << path
161           << "/dna/sigmadiff_cumulated_ionisation_e_RBEBV_Z"
162           << Z << ".dat";
163         std::ifstream eDiffCrossSectionZ(eFullFileNameZ.str().c_str());
164         if (!eDiffCrossSectionZ)
165           G4Exception("G4DNARelativisticIonisationModel::Initialise","em0003",
166           FatalException,
167           "Missing data file for cumulated DCS");
168 
169         eVecEZ[Z].push_back(0.);
170         while(!eDiffCrossSectionZ.eof())
171         {
172           G4double tDummy;
173           G4double eDummy;
174           eDiffCrossSectionZ>>tDummy>>eDummy;
175           if (tDummy != eVecEZ[Z].back())
176           {
177            eVecEZ[Z].push_back(tDummy);
178            eVecEjeEZ[Z][tDummy].push_back(0.);
179           }
180 
181           for(G4int istate=0;istate<(G4int)iState[Z].size();istate++)
182           {
183             eDiffCrossSectionZ>>
184             eDiffCrossSectionDataZ[Z][istate][tDummy][eDummy];
185             eEjectedEnergyDataZ[Z][istate][tDummy]
186             [eDiffCrossSectionDataZ[Z][istate][tDummy][eDummy]] 
187             = eDummy;
188             eProbaShellMapZ[Z][istate][tDummy].push_back(
189             eDiffCrossSectionDataZ[Z][istate][tDummy][eDummy]);
190           }
191 
192           if (eDummy != eVecEjeEZ[Z][tDummy].back()){
193                              eVecEjeEZ[Z][tDummy].push_back(eDummy);
194           }
195         }
196       }
197     }
198   }
199   else
200   { 
201     G4cout<< 
202     "Error : No particle Definition is found in G4DNARelativisticIonisationModel"
203     <<G4endl;
204     return;
205   }
206 
207   if( verboseLevel>0 )
208   {
209     G4cout << "Relativistic Ionisation model is initialized " << G4endl
210     << "Energy range: "
211     << LowEnergyLimit() / eV << " eV - "
212     << HighEnergyLimit() / keV << " keV for "
213     << particle->GetParticleName()
214     << G4endl;
215   }
216 
217   // Initialise gold density pointer
218   fMaterialDensity = G4DNAMolecularMaterial::Instance()
219                     ->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_Au"));
220 
221   fAtomDeexcitation       = G4LossTableManager::Instance()->AtomDeexcitation();
222   fParticleChangeForGamma = GetParticleChangeForGamma();
223 
224   if (isInitialised){return;}
225   isInitialised = true;
226 }
227 
228 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
229 
230 G4double G4DNARelativisticIonisationModel::CrossSectionPerVolume(
231                 const G4Material* material,
232                 const G4ParticleDefinition* particleDefinition,
233                 G4double ekin,
234                 G4double,
235                 G4double)
236 {
237   if (verboseLevel > 3)
238   {
239     G4cout << 
240        "Calling CrossSectionPerVolume() of G4DNARelativisticIonisationModel"
241     << G4endl;
242   }
243 
244   if(particleDefinition != fParticleDefinition) return 0;
245 
246   // Calculate total cross section for model
247   G4double sigma=0;
248 
249   if(material->GetNumberOfElements()>1) return 0.; // Protection for Molecules
250   G4double atomicNDensity = material->GetAtomicNumDensityVector()[0];
251   G4double z              = material->GetZ();
252 
253   if(atomicNDensity!= 0.0)
254   {
255     if (ekin >= fLowEnergyLimit && ekin < fHighEnergyLimit)
256     {    
257       sigma = GetTotalCrossSection(material,particleDefinition,ekin);
258     }
259 
260     if (verboseLevel > 2)
261     {
262       G4cout << "__________________________________" << G4endl;
263       G4cout << "=== G4DNARelativisticIonisationModel - XS INFO START" <<G4endl;
264       G4cout << "=== Kinetic energy (eV)=" << ekin/eV << " particle : " 
265              << particleDefinition->GetParticleName() << G4endl;
266       G4cout << "=== Cross section per atom for Z="<<z<<" is (cm^2)" 
267              << sigma/cm/cm << G4endl;
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;
271     }
272   } 
273   return sigma*atomicNDensity;
274 }
275 
276 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
277 
278 void G4DNARelativisticIonisationModel::SampleSecondaries(
279                 std::vector<G4DynamicParticle*>* fvect,
280                 const G4MaterialCutsCouple* couple,
281                 const G4DynamicParticle* particle,
282                 G4double,G4double)
283 {
284   if (verboseLevel > 3)
285   {
286     G4cout << 
287       "Calling SampleSecondaries() of G4DNARelativisticIonisationModel"
288     << G4endl;
289   }
290 
291 
292   G4ParticleDefinition* particleDef = particle->GetDefinition();
293   G4double k                        = particle->GetKineticEnergy();
294   G4double ejectedE                 = 0.*eV;
295 
296   if(fLowEnergyLimit <= k && k<fHighEnergyLimit)
297   {
298     G4ThreeVector primaryDir        = particle   ->GetMomentumDirection(); 
299 
300     G4double      particleMass      = particleDef->GetPDGMass();
301     G4double      totalEnergy       = k+particleMass;
302     G4double      pSquare           = k*(totalEnergy+particleMass);
303     G4double      totalMomentum     = std::sqrt(pSquare);
304 
305     const G4Material *material = couple->GetMaterial();
306     G4int             z        = material->GetZ();
307     G4int             level    = RandomSelect(material,particleDef,k);
308 
309     if(k<Ebinding[z].at(level)) return;
310 
311     G4int NumSecParticlesInit =0;
312     G4int NumSecParticlesFinal=0;
313 
314     if(fAtomDeexcitation != nullptr){
315       auto  as = G4AtomicShellEnumerator(level);
316       const G4AtomicShell *shell = fAtomDeexcitation->GetAtomicShell(z,as);
317       NumSecParticlesInit  = (G4int)fvect->size();
318       fAtomDeexcitation->GenerateParticles(fvect,shell,z,0,0);
319       NumSecParticlesFinal = (G4int)fvect->size();
320     }
321 
322     ejectedE                
323             = GetEjectedElectronEnergy   (material,particleDef,k,level);
324     G4ThreeVector ejectedDir
325             = GetEjectedElectronDirection(particleDef,k,ejectedE);
326     ejectedDir.rotateUz(primaryDir);
327 
328     G4double scatteredE = k - Ebinding[z].at(level) - ejectedE;
329 
330     if(particleDef == G4Electron::ElectronDefinition()){
331       G4double secondaryTotMomentum  
332             = std::sqrt(ejectedE*(ejectedE+2*CLHEP::electron_mass_c2));
333       G4double finalMomentumX    
334             = totalMomentum*primaryDir.x()- secondaryTotMomentum*ejectedDir.x();
335       G4double finalMomentumY    
336             = totalMomentum*primaryDir.y()- secondaryTotMomentum*ejectedDir.y();
337       G4double finalMomentumZ    
338             = totalMomentum*primaryDir.z()- secondaryTotMomentum*ejectedDir.z();
339       
340       G4ThreeVector scatteredDir(finalMomentumX,finalMomentumY,finalMomentumZ);
341       fParticleChangeForGamma->ProposeMomentumDirection(scatteredDir.unit());
342 
343     }
344     else 
345     {
346       fParticleChangeForGamma->ProposeMomentumDirection(primaryDir);
347     }
348 
349     //G4double deexSecEnergy=0.;
350     G4double restEproduction = Ebinding[z].at(level);
351     for(G4int iparticle=NumSecParticlesInit;
352                    iparticle<NumSecParticlesFinal;iparticle++)
353     {
354       //deexSecEnergy = deexSecEnergy + (*fvect)[iparticle]->GetKineticEnergy();
355       G4double Edeex = (*fvect)[iparticle]->GetKineticEnergy();
356       if(restEproduction>=Edeex){
357         restEproduction -= Edeex;
358       }
359       else{
360         delete (*fvect)[iparticle];
361         (*fvect)[iparticle]=nullptr;
362       }
363     }
364     if(restEproduction < 0.0){
365       G4Exception("G4DNARelativisticIonisationModel::SampleSecondaries()",
366                   "em0008",FatalException,"Negative local energy deposit");
367     }
368 
369     if(!statCode)
370     {
371       if(scatteredE>0){
372         fParticleChangeForGamma->SetProposedKineticEnergy (scatteredE);
373         fParticleChangeForGamma->ProposeLocalEnergyDeposit(restEproduction);
374         //fParticleChangeForGamma
375         //->ProposeLocalEnergyDeposit(k-scatteredE-ejectedE-deexSecEnergy);
376       }
377     }
378     else
379     {
380       fParticleChangeForGamma->SetProposedKineticEnergy (k);
381       fParticleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredE);
382     }
383     
384     if(ejectedE>0){
385       auto  ejectedelectron 
386              = new G4DynamicParticle(G4Electron::Electron(),ejectedDir,ejectedE);
387       fvect->push_back(ejectedelectron);
388     }
389   }
390 }
391 
392 void G4DNARelativisticIonisationModel::LoadAtomicStates(
393                                           G4int z,const char* path)
394 {
395 
396   if (verboseLevel > 3)
397   {
398     G4cout << 
399       "Calling LoadAtomicStates() of G4DNARelativisticIonisationModel"
400     << G4endl;
401   }
402   const char *datadir =  path;
403   if(datadir == nullptr)
404   {
405      datadir = G4FindDataDir("G4LEDATA");
406      if(datadir == nullptr)
407      {
408        G4Exception("G4DNARelativisticIonisationModel::LoadAtomicStates()",
409             "em0002",FatalException,"Enviroment variable G4LEDATA not defined");
410                    
411        return;
412      }
413   }
414   std::ostringstream targetfile;
415   targetfile << datadir <<"/dna/atomicstate_Z"<< z <<".dat";
416   std::ifstream fin(targetfile.str().c_str());
417   if(!fin)
418   {
419     G4cout<< " Error : "<< targetfile.str() <<" is not found "<<G4endl;
420     G4Exception("G4DNARelativisticIonisationModel::LoadAtomicStates()","em0002",
421                 FatalException,"There is no target file");
422     return;
423   }
424 
425   G4String buff0,buff1,buff2,buff3,buff4,buff5,buff6;
426   fin >> buff0 >>buff1>>buff2>>buff3>>buff4>>buff5>>buff6;
427   G4int iline=0;
428   while(true){
429     fin >> buff0 >>buff1>>buff2>>buff3>>buff4>>buff5>>buff6;
430     if(!fin.eof())
431     {
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));
437       if(stod(buff5)==0.)
438       {// if there is no kinetic energy in the file, kinetic energy 
439        // for Bhor atomic model will be calculated: !!! I's not realistic!!!
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));
445       }
446       else
447       {
448         Ekinetic  [z].push_back(stod(buff5));
449       }
450       iline++;
451     }
452     else
453     {
454       break;
455     }
456   }
457 }
458 
459 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
460 
461 G4double G4DNARelativisticIonisationModel::GetTotalCrossSection(
462                 const G4Material* material,
463                 const G4ParticleDefinition* particle,
464                 G4double kineticEnergy)
465 {
466   G4double value=0;
467   G4int  z = material->GetZ();
468   if(z!=79){ return 0.;}
469   
470   std::size_t N=iState[z].size();
471   for(G4int i=0; i<(G4int)N; ++i){
472     value = value+GetPartialCrossSection(material,i,particle,kineticEnergy);
473   }
474   return value;
475 }
476 
477 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
478 
479 G4double G4DNARelativisticIonisationModel::GetPartialCrossSection(
480                 const G4Material* material,
481                 G4int level,
482                 const G4ParticleDefinition* particle,
483                 G4double kineticEnergy)
484 {
485   G4double value   = 0; 
486   G4double constRy =13.6057E-6;//MeV
487 
488   G4ParticleDefinition *electronDef = G4Electron::ElectronDefinition();
489   G4int z = material->GetZ();
490   if(particle==electronDef){
491 
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);
504 
505     if(Ebinding[z].at(level)<=kineticEnergy)
506     {
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.);
512     }
513     
514   }
515   return value;
516 }
517 
518 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
519 
520 G4double G4DNARelativisticIonisationModel::GetDifferentialCrossSection(
521                 const G4Material* material,
522                 const G4ParticleDefinition* particle,
523                 G4double kineticEnergy,
524                 G4double secondaryEnergy,
525                 G4int  level)
526 {
527   G4double value=0.; 
528   G4double constRy =13.6057E-6;//MeV
529 
530   G4int z = material->GetZ();
531 
532   G4ParticleDefinition *electronDef = G4Electron::ElectronDefinition();
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);
547 
548     if(secondaryEnergy<=((kineticEnergy-Ebinding[z].at(level))/2.))
549     {
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)));
557     }
558   }
559   return value;
560 }
561 
562 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
563 
564 G4int G4DNARelativisticIonisationModel::RandomSelect(
565                 const G4Material* material,
566                 const G4ParticleDefinition* particle,
567                 G4double kineticEnergy)
568 {
569   G4double value = 0.;
570   G4int z = material->GetZ();
571   std::size_t numberOfShell = iShell[z].size();
572   std::vector<G4double> valuesBuffer(numberOfShell, 0.0);
573   const auto  n = (G4int)iShell[z].size();
574   G4int i(n);
575 
576   while (i > 0)
577   {
578     i--;
579     if((fLowEnergyLimit<=kineticEnergy)&&(kineticEnergy<fHighEnergyLimit))
580     {
581       valuesBuffer[i]=GetPartialCrossSection(material,i,particle,kineticEnergy);
582     }
583     value += valuesBuffer[i];
584   }
585 
586   value *= G4UniformRand();
587   i = n;
588 
589   while (i > 0)
590   {
591     i--;
592 
593     if (valuesBuffer[i] > value)
594     {
595       return i;
596     }
597     value -= valuesBuffer[i];
598   }
599 
600   return 9999;
601 }
602 
603 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
604 
605 
606 G4double  G4DNARelativisticIonisationModel::GetEjectedElectronEnergy(
607                        const G4Material* material,
608                        const G4ParticleDefinition* particle,
609                        G4double energy, G4int ishell)
610 {
611   G4double secondaryEnergy=0;
612 
613   G4ParticleDefinition *electronDef = G4Electron::ElectronDefinition();
614   G4int z = material->GetZ();
615   if(!fasterCode){ // for 2D rejection method
616     if(particle==electronDef){
617       G4double maximumsecondaryEnergy = (energy-Ebinding[z].at(ishell))/2.;
618       if(maximumsecondaryEnergy<0.) return 0.;
619       G4double maximumCrossSection=-999.;
620 
621       maximumCrossSection 
622             = GetDifferentialCrossSection(material,particle,energy,0.,ishell);
623       do{
624         secondaryEnergy = G4UniformRand()* maximumsecondaryEnergy;
625       }while(G4UniformRand()*maximumCrossSection > 
626            GetDifferentialCrossSection(
627                         material,particle,energy,secondaryEnergy,ishell));
628     }
629   }
630   else { // for cumulative method using cumulated DCS file
631 
632     G4double valueE1  =0.;
633     G4double valueE2  =0.;
634     G4double valueXS21=0.;
635     G4double valueXS22=0.;
636     G4double valueXS11=0.;
637     G4double valueXS12=0.;
638     G4double ejeE21   =0.;
639     G4double ejeE22   =0.;
640     G4double ejeE11   =0.;
641     G4double ejeE12   =0.;
642     G4double random = G4UniformRand();
643 
644     if (particle == G4Electron::ElectronDefinition())
645     {
646       if((eVecEZ[z].at(0)<=energy)&&(energy<eVecEZ[z].back()))
647       {
648         auto k2 
649                 = std::upper_bound(eVecEZ[z].begin(),eVecEZ[z].end(), energy);
650         auto k1 = k2-1;
651 
652         if (     random < eProbaShellMapZ[z][ishell][(*k1)].back()
653               && random < eProbaShellMapZ[z][ishell][(*k2)].back() )
654         {
655           auto xs12 =
656              std::upper_bound(eProbaShellMapZ[z][ishell][(*k1)].begin(),
657                               eProbaShellMapZ[z][ishell][(*k1)].end(), random);
658           auto xs11 = xs12-1;
659 
660           auto xs22 =
661              std::upper_bound(eProbaShellMapZ[z][ishell][(*k2)].begin(),
662                               eProbaShellMapZ[z][ishell][(*k2)].end(), random);
663           auto xs21 = xs22-1;
664 
665           valueE1  =*k1;
666           valueE2  =*k2;
667           valueXS21 =*xs21;
668           valueXS22 =*xs22;
669           valueXS12 =*xs12;
670           valueXS11 =*xs11;
671 
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];
676 
677           secondaryEnergy  = QuadInterpolator(  valueXS11, valueXS12,
678                                                 valueXS21, valueXS22,
679                                                 ejeE11 , ejeE12 ,
680                                                 ejeE21 , ejeE22 ,
681                                                 valueE1, valueE2,
682                                                 energy, random );
683         }
684       }
685     }
686   }
687 
688   if(secondaryEnergy<0) secondaryEnergy=0;
689   return secondaryEnergy;
690 }
691 
692 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
693 
694 G4ThreeVector  G4DNARelativisticIonisationModel::GetEjectedElectronDirection(
695                              const G4ParticleDefinition* ,
696                              G4double energy,G4double secondaryenergy)
697 {
698   G4double phi       = 2*CLHEP::pi*G4UniformRand();
699   G4double sintheta  = std::sqrt((1.-secondaryenergy/energy) 
700                        / (1.+secondaryenergy/(2*CLHEP::electron_mass_c2)));
701 
702   G4double dirX = sintheta*std::cos(phi);
703   G4double dirY = sintheta*std::sin(phi);
704   G4double dirZ = std::sqrt(1.-sintheta*sintheta);
705 
706   G4ThreeVector vec(dirX,dirY,dirZ);
707   return vec;
708 }
709 
710 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
711 
712 G4double G4DNARelativisticIonisationModel::Interpolate(    G4double e1,
713                                                            G4double e2,
714                                                            G4double e,
715                                                            G4double xs1,
716                                                            G4double xs2)
717 {
718 
719     G4double value = 0.;
720 
721     if((xs1!=0)&&(e1!=0)){
722       // Log-log interpolation by default
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));
728     }
729     else{
730       // Lin-Lin interpolation 
731       G4double d1 = xs1;
732       G4double d2 = xs2;
733       value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
734     }
735 
736     return value;
737 }
738 
739 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
740 
741 G4double G4DNARelativisticIonisationModel::QuadInterpolator(
742                 G4double e11, G4double e12,
743                 G4double e21, G4double e22,
744                 G4double xs11, G4double xs12,
745                 G4double xs21, G4double xs22,
746                 G4double t1, G4double t2,
747                 G4double t, G4double e)
748 {
749     G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
750     G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
751     G4double value 
752              = Interpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
753     return value;
754 }
755 
756