Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/dna/models/src/G4DNACPA100IonisationModel.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 ]

Diff markup

Differences between /processes/electromagnetic/dna/models/src/G4DNACPA100IonisationModel.cc (Version 11.3.0) and /processes/electromagnetic/dna/models/src/G4DNACPA100IonisationModel.cc (Version 4.1)


  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26 // CPA100 ionisation model class for electrons    
 27 //                                                
 28 // Based on the work of M. Terrissol and M. C.    
 29 //                                                
 30 // Users are requested to cite the following p    
 31 // - M. Terrissol, A. Baudre, Radiat. Prot. Do    
 32 // - M.C. Bordage, J. Bordes, S. Edel, M. Terr    
 33 //   M. Bardies, N. Lampe, S. Incerti, Phys. M    
 34 //                                                
 35 // Authors of this class:                         
 36 // M.C. Bordage, M. Terrissol, S. Edel, J. Bor    
 37 //                                                
 38 // 15.01.2014: creation                           
 39 //                                                
 40 // Based on the study by S. Zein et. al. Nucl.    
 41 // 1/2/2023 : Hoang added modification            
 42                                                   
 43 #include "G4DNACPA100IonisationModel.hh"          
 44                                                   
 45 #include "G4DNAChemistryManager.hh"               
 46 #include "G4DNAMaterialManager.hh"                
 47 #include "G4DNAMolecularMaterial.hh"              
 48 #include "G4EnvironmentUtils.hh"                  
 49 #include "G4LossTableManager.hh"                  
 50 #include "G4PhysicalConstants.hh"                 
 51 #include "G4SystemOfUnits.hh"                     
 52 #include "G4UAtomicDeexcitation.hh"               
 53                                                   
 54 #include <fstream>                                
 55                                                   
 56 //....oooOO0OOooo........oooOO0OOooo........oo    
 57                                                   
 58 using namespace std;                              
 59                                                   
 60 //....oooOO0OOooo........oooOO0OOooo........oo    
 61                                                   
 62 G4DNACPA100IonisationModel::G4DNACPA100Ionisat    
 63                                                   
 64   : G4VDNAModel(nam, "all")                       
 65 {                                                 
 66   fpGuanine = G4Material::GetMaterial("G4_GUAN    
 67   fpG4_WATER = G4Material::GetMaterial("G4_WAT    
 68   fpDeoxyribose = G4Material::GetMaterial("G4_    
 69   fpCytosine = G4Material::GetMaterial("G4_CYT    
 70   fpThymine = G4Material::GetMaterial("G4_THYM    
 71   fpAdenine = G4Material::GetMaterial("G4_ADEN    
 72   fpPhosphate = G4Material::GetMaterial("G4_PH    
 73   fpParticle = G4Electron::ElectronDefinition(    
 74 }                                                 
 75                                                   
 76 //....oooOO0OOooo........oooOO0OOooo........oo    
 77                                                   
 78 void G4DNACPA100IonisationModel::Initialise(co    
 79                                             co    
 80 {                                                 
 81   if (isInitialised) {                            
 82     return;                                       
 83   }                                               
 84   if (verboseLevel > 3) {                         
 85     G4cout << "Calling G4DNACPA100IonisationMo    
 86   }                                               
 87                                                   
 88   if (!G4DNAMaterialManager::Instance()->IsLoc    
 89     if (p != fpParticle) {                        
 90       std::ostringstream oss;                     
 91       oss << " Model is not applied for this p    
 92       G4Exception("G4DNACPA100IonisationModel:    
 93                   FatalException, oss.str().c_    
 94     }                                             
 95                                                   
 96     const char* path = G4FindDataDir("G4LEDATA    
 97                                                   
 98     if (path == nullptr) {                        
 99       G4Exception("G4DNACPA100IonisationModel:    
100                   "G4LEDATA environment variab    
101       return;                                     
102     }                                             
103                                                   
104     std::size_t index;                            
105     if (fpG4_WATER != nullptr) {                  
106       index = fpG4_WATER->GetIndex();             
107       G4String eFullFileName = "";                
108       fasterCode ? eFullFileName = "/dna/sigma    
109                  : eFullFileName = "/dna/sigma    
110       AddCrossSectionData(index, p, "dna/sigma    
111                           1.e-20 * m * m);        
112       SetLowELimit(index, p, 11 * eV);            
113       SetHighELimit(index, p, 255955 * eV);       
114     }                                             
115     if (fpGuanine != nullptr) {                   
116       index = fpGuanine->GetIndex();              
117       G4String eFullFileName = "";                
118       if(useDcs) {                                
119         fasterCode ? eFullFileName = "/dna/sig    
120                    : eFullFileName = "/dna/sig    
121       }                                           
122       AddCrossSectionData(index, p, "dna/sigma    
123                           1. * cm * cm);          
124       SetLowELimit(index, p, 11 * eV);            
125       SetHighELimit(index, p, 1 * MeV);           
126     }                                             
127     if (fpDeoxyribose != nullptr) {               
128       index = fpDeoxyribose->GetIndex();          
129       G4String eFullFileName = "";                
130       if(useDcs) {                                
131         eFullFileName = "/dna/sigmadiff_cumula    
132       }                                           
133       AddCrossSectionData(index, p, "dna/sigma    
134                           1. * cm * cm);          
135       SetLowELimit(index, p, 11 * eV);            
136       SetHighELimit(index, p, 1 * MeV);           
137     }                                             
138     if (fpCytosine != nullptr) {                  
139       index = fpCytosine->GetIndex();             
140       G4String eFullFileName = "";                
141       if(useDcs) {                                
142         fasterCode ? eFullFileName = "/dna/sig    
143                    : eFullFileName = "/dna/sig    
144       }                                           
145       AddCrossSectionData(index, p, "dna/sigma    
146                           1. * cm * cm);          
147       SetLowELimit(index, p, 11 * eV);            
148       SetHighELimit(index, p, 1 * MeV);           
149     }                                             
150     if (fpThymine != nullptr) {                   
151       index = fpThymine->GetIndex();              
152       G4String eFullFileName = "";                
153       if(useDcs) {                                
154         fasterCode ? eFullFileName = "/dna/sig    
155                    : eFullFileName = "/dna/sig    
156       }                                           
157       AddCrossSectionData(index, p, "dna/sigma    
158                           1. * cm * cm);          
159       SetLowELimit(index, p, 11 * eV);            
160       SetHighELimit(index, p, 1 * MeV);           
161     }                                             
162     if (fpAdenine != nullptr) {                   
163       index = fpAdenine->GetIndex();              
164       G4String eFullFileName = "";                
165       if(useDcs) {                                
166         fasterCode ? eFullFileName = "/dna/sig    
167                    : eFullFileName = "/dna/sig    
168       }                                           
169       AddCrossSectionData(index, p, "dna/sigma    
170                           1. * cm * cm);          
171       SetLowELimit(index, p, 11 * eV);            
172       SetHighELimit(index, p, 1 * MeV);           
173     }                                             
174     if (fpPhosphate != nullptr) {                 
175       index = fpPhosphate->GetIndex();            
176       G4String eFullFileName = "";                
177       if(useDcs) {                                
178         eFullFileName = "dna/sigmadiff_cumulat    
179       }                                           
180       AddCrossSectionData(index, p, "dna/sigma    
181                           1. * cm * cm);          
182       SetLowELimit(index, p, 11 * eV);            
183       SetHighELimit(index, p, 1 * MeV);           
184     }                                             
185     LoadCrossSectionData(p);                      
186     G4DNAMaterialManager::Instance()->SetMaste    
187     fpModelData = this;                           
188   }                                               
189   else {                                          
190     auto dataModel = dynamic_cast<G4DNACPA100I    
191       G4DNAMaterialManager::Instance()->GetMod    
192     if (dataModel == nullptr) {                   
193       G4cout << "G4DNACPA100IonisationModel::C    
194       throw;                                      
195     }                                             
196     fpModelData = dataModel;                      
197   }                                               
198                                                   
199   fAtomDeexcitation = G4LossTableManager::Inst    
200                                                   
201   fParticleChangeForGamma = GetParticleChangeF    
202   isInitialised = true;                           
203 }                                                 
204                                                   
205 G4double G4DNACPA100IonisationModel::CrossSect    
206                                                   
207                                                   
208 {                                                 
209   // initialise the cross section value (outpu    
210   G4double sigma(0);                              
211                                                   
212   // Get the current particle name                
213   const G4String& particleName = p->GetParticl    
214                                                   
215   if (p != fpParticle) {                          
216     G4Exception("G4DNACPA100IonisationModel::C    
217                 "No model is registered for th    
218   }                                               
219                                                   
220   auto matID = material->GetIndex();              
221                                                   
222   // Set the low and high energy limits           
223   G4double lowLim = fpModelData->GetLowELimit(    
224   G4double highLim = fpModelData->GetHighELimi    
225                                                   
226   // Check that we are in the correct energy r    
227   if (ekin >= lowLim && ekin < highLim) {         
228     // Get the map with all the model data tab    
229     auto tableData = fpModelData->GetData();      
230                                                   
231     if ((*tableData)[matID][p] == nullptr) {      
232       G4Exception("G4DNACPA100IonisationModel:    
233                   "No model is registered");      
234     }                                             
235     else {                                        
236       sigma = (*tableData)[matID][p]->FindValu    
237     }                                             
238                                                   
239     if (verboseLevel > 2) {                       
240       auto MolDensity =                           
241         (*G4DNAMolecularMaterial::Instance()->    
242       G4cout << "_____________________________    
243       G4cout << "°°° G4DNACPA100IonisationM    
244       G4cout << "°°° Kinetic energy(eV)=" <    
245       G4cout << "°°° lowLim (eV) = " << low    
246       G4cout << "°°° Materials = " << (*G4M    
247       G4cout << "°°° Cross section per " <<    
248              << G4endl;                           
249       G4cout << "°°° Cross section per Phos    
250              << sigma * MolDensity / (1. / cm)    
251       G4cout << "°°° G4DNACPA100IonisationM    
252     }                                             
253   }                                               
254                                                   
255   auto MolDensity = (*G4DNAMolecularMaterial::    
256   return sigma * MolDensity;                      
257 }                                                 
258                                                   
259 //....oooOO0OOooo........oooOO0OOooo........oo    
260                                                   
261 void G4DNACPA100IonisationModel::SampleSeconda    
262   std::vector<G4DynamicParticle*>* fvect,         
263   const G4MaterialCutsCouple* couple,  // must    
264   const G4DynamicParticle* particle, G4double,    
265 {                                                 
266   if (verboseLevel > 3) {                         
267     G4cout << "Calling SampleSecondaries() of     
268   }                                               
269   auto k = particle->GetKineticEnergy();          
270                                                   
271   const G4Material* material = couple->GetMate    
272                                                   
273   auto MatID = material->GetIndex();              
274                                                   
275   auto p = particle->GetDefinition();             
276                                                   
277   auto lowLim = fpModelData->GetLowELimit(MatI    
278   auto highLim = fpModelData->GetHighELimit(Ma    
279                                                   
280   // Check if we are in the correct energy ran    
281   if (k >= lowLim && k < highLim) {               
282     const auto& primaryDirection = particle->G    
283     auto particleMass = particle->GetDefinitio    
284     auto totalEnergy = k + particleMass;          
285     auto pSquare = k * (totalEnergy + particle    
286     auto totalMomentum = std::sqrt(pSquare);      
287     G4int shell = -1;                             
288     G4double bindingEnergy, secondaryKinetic;     
289     shell = fpModelData->RandomSelectShell(k,     
290     bindingEnergy = iStructure.IonisationEnerg    
291                                                   
292     if (k < bindingEnergy) {                      
293       return;                                     
294     }                                             
295                                                   
296     auto info = std::make_tuple(MatID, k, shel    
297                                                   
298     secondaryKinetic = -1000 * eV;                
299     if (fpG4_WATER->GetIndex() != MatID) {//fo    
300       secondaryKinetic = fpModelData->Randomiz    
301     }else if(fasterCode){                         
302         secondaryKinetic = fpModelData->Random    
303       }else{                                      
304         secondaryKinetic = fpModelData->Random    
305       }                                           
306                                                   
307     G4double cosTheta = 0.;                       
308     G4double phi = 0.;                            
309     RandomizeEjectedElectronDirection(particle    
310                                       phi);       
311                                                   
312     G4double sinTheta = std::sqrt(1. - cosThet    
313     G4double dirX = sinTheta * std::cos(phi);     
314     G4double dirY = sinTheta * std::sin(phi);     
315     G4double dirZ = cosTheta;                     
316     G4ThreeVector deltaDirection(dirX, dirY, d    
317     deltaDirection.rotateUz(primaryDirection);    
318                                                   
319     // SI - For atom. deexc. tagging - 23/05/2    
320     if (secondaryKinetic > 0) {                   
321       auto dp = new G4DynamicParticle(G4Electr    
322       fvect->push_back(dp);                       
323     }                                             
324                                                   
325     if (particle->GetDefinition() != fpParticl    
326       fParticleChangeForGamma->ProposeMomentum    
327     }                                             
328     else {                                        
329       G4double deltaTotalMomentum =               
330         std::sqrt(secondaryKinetic * (secondar    
331       G4double finalPx =                          
332         totalMomentum * primaryDirection.x() -    
333       G4double finalPy =                          
334         totalMomentum * primaryDirection.y() -    
335       G4double finalPz =                          
336         totalMomentum * primaryDirection.z() -    
337       G4double finalMomentum = std::sqrt(final    
338       finalPx /= finalMomentum;                   
339       finalPy /= finalMomentum;                   
340       finalPz /= finalMomentum;                   
341                                                   
342       G4ThreeVector direction;                    
343       direction.set(finalPx, finalPy, finalPz)    
344                                                   
345       fParticleChangeForGamma->ProposeMomentum    
346     }                                             
347                                                   
348     // SI - For atom. deexc. tagging - 23/05/2    
349                                                   
350     // AM: sample deexcitation                    
351     // here we assume that H_{2}O electronic l    
352     // this can be considered true with a roug    
353                                                   
354     G4double scatteredEnergy = k - bindingEner    
355                                                   
356     // SI: only atomic deexcitation from K she    
357     // Hoang: only for water                      
358     if (material == G4Material::GetMaterial("G    
359       std::size_t secNumberInit = 0;  // need     
360       std::size_t secNumberFinal = 0;  // So I    
361       if ((fAtomDeexcitation != nullptr) && sh    
362         G4int Z = 8;                              
363         auto Kshell = fAtomDeexcitation->GetAt    
364         secNumberInit = fvect->size();            
365         fAtomDeexcitation->GenerateParticles(f    
366         secNumberFinal = fvect->size();           
367         if (secNumberFinal > secNumberInit) {     
368           for (std::size_t i = secNumberInit;     
369             // Check if there is enough residu    
370             if (bindingEnergy >= ((*fvect)[i])    
371               // Ok, this is a valid secondary    
372               bindingEnergy -= ((*fvect)[i])->    
373             }                                     
374             else {                                
375               // Invalid secondary: not enough    
376               // Keep its energy in the local     
377               delete (*fvect)[i];                 
378               (*fvect)[i] = nullptr;              
379             }                                     
380           }                                       
381         }                                         
382       }                                           
383     }                                             
384                                                   
385     // This should never happen                   
386     if (bindingEnergy < 0.0) {                    
387       G4Exception("G4DNACPA100IonisatioModel1:    
388                   "Negative local energy depos    
389     }                                             
390     if (!statCode) {                              
391       fParticleChangeForGamma->SetProposedKine    
392       fParticleChangeForGamma->ProposeLocalEne    
393     }                                             
394     else {                                        
395       fParticleChangeForGamma->SetProposedKine    
396       fParticleChangeForGamma->ProposeLocalEne    
397     }                                             
398                                                   
399     // only water for chemistry                   
400     if (fpG4_WATER != nullptr && material == G    
401       const G4Track* theIncomingTrack = fParti    
402       G4DNAChemistryManager::Instance()->Creat    
403                                                   
404     }                                             
405   }                                               
406 }                                                 
407                                                   
408 //....oooOO0OOooo........oooOO0OOooo........oo    
409                                                   
410 G4double G4DNACPA100IonisationModel::Randomize    
411 {                                                 
412   auto MatID = std::get<0>(info);                 
413   auto k = std::get<1>(info);                     
414   auto shell = std::get<2>(info);                 
415   G4double maximumEnergyTransfer = 0.;            
416   auto IonLevel = iStructure.IonisationEnergy(    
417   (k + IonLevel) / 2. > k ? maximumEnergyTrans    
418                                                   
419   G4double crossSectionMaximum = 0.;              
420                                                   
421   G4double minEnergy = IonLevel;                  
422   G4double maxEnergy = maximumEnergyTransfer;     
423                                                   
424   // nEnergySteps can be optimized - 100 by de    
425   G4int nEnergySteps = 50;                        
426                                                   
427   G4double value(minEnergy);                      
428   G4double stpEnergy(std::pow(maxEnergy / valu    
429   G4int step(nEnergySteps);                       
430   G4double differentialCrossSection = 0.;         
431   while (step > 0) {                              
432     step--;                                       
433     differentialCrossSection = DifferentialCro    
434                                                   
435     if (differentialCrossSection > 0) {           
436       crossSectionMaximum = differentialCrossS    
437       break;                                      
438     }                                             
439     value *= stpEnergy;                           
440   }                                               
441                                                   
442   G4double secondaryElectronKineticEnergy = 0.    
443   do {                                            
444     secondaryElectronKineticEnergy = G4Uniform    
445   } while (G4UniformRand() * crossSectionMaxim    
446            > DifferentialCrossSection(info, (s    
447                                                   
448   return secondaryElectronKineticEnergy;          
449 }                                                 
450                                                   
451 //....oooOO0OOooo........oooOO0OOooo........oo    
452                                                   
453 void G4DNACPA100IonisationModel::RandomizeEjec    
454                                                   
455                                                   
456                                                   
457 {                                                 
458   phi = twopi * G4UniformRand();                  
459   G4double sin2O = (1. - secKinetic / k) / (1.    
460   cosTheta = std::sqrt(1. - sin2O);               
461 }                                                 
462                                                   
463 //....oooOO0OOooo........oooOO0OOooo........oo    
464                                                   
465 G4double G4DNACPA100IonisationModel::Different    
466                                                   
467 {                                                 
468   auto MatID = std::get<0>(info);                 
469   auto k = std::get<1>(info) / eV;  // in eV u    
470   auto shell = std::get<2>(info);                 
471   G4double sigma = 0.;                            
472   G4double shellEnergy = iStructure.Ionisation    
473   G4double kSE(energyTransfer - shellEnergy);     
474                                                   
475   if (energyTransfer >= shellEnergy) {            
476     G4double valueT1 = 0;                         
477     G4double valueT2 = 0;                         
478     G4double valueE21 = 0;                        
479     G4double valueE22 = 0;                        
480     G4double valueE12 = 0;                        
481     G4double valueE11 = 0;                        
482                                                   
483     G4double xs11 = 0;                            
484     G4double xs12 = 0;                            
485     G4double xs21 = 0;                            
486     G4double xs22 = 0;                            
487                                                   
488     auto t2 = std::upper_bound(fTMapWithVec[Ma    
489                                fTMapWithVec[Ma    
490     auto t1 = t2 - 1;                             
491                                                   
492     if (kSE <= fEMapWithVector[MatID][fpPartic    
493         && kSE <= fEMapWithVector[MatID][fpPar    
494     {                                             
495       auto e12 = std::upper_bound(fEMapWithVec    
496                                   fEMapWithVec    
497       auto e11 = e12 - 1;                         
498                                                   
499       auto e22 = std::upper_bound(fEMapWithVec    
500                                   fEMapWithVec    
501       auto e21 = e22 - 1;                         
502                                                   
503       valueT1 = *t1;                              
504       valueT2 = *t2;                              
505       valueE21 = *e21;                            
506       valueE22 = *e22;                            
507       valueE12 = *e12;                            
508       valueE11 = *e11;                            
509                                                   
510       xs11 = diffCrossSectionData[MatID][fpPar    
511       xs12 = diffCrossSectionData[MatID][fpPar    
512       xs21 = diffCrossSectionData[MatID][fpPar    
513       xs22 = diffCrossSectionData[MatID][fpPar    
514     }                                             
515                                                   
516     G4double xsProduct = xs11 * xs12 * xs21 *     
517                                                   
518     if (xsProduct != 0.) {                        
519       sigma = QuadInterpolator(valueE11, value    
520                                valueT1, valueT    
521     }                                             
522   }                                               
523                                                   
524   return sigma;                                   
525 }                                                 
526                                                   
527 //....oooOO0OOooo........oooOO0OOooo........oo    
528                                                   
529 G4double G4DNACPA100IonisationModel::Interpola    
530                                                   
531 {                                                 
532   G4double value = 0.;                            
533                                                   
534   // Log-log interpolation by default             
535                                                   
536   if (e1 != 0 && e2 != 0 && (std::log10(e2) -     
537     G4double a = (std::log10(xs2) - std::log10    
538     G4double b = std::log10(xs2) - a * std::lo    
539     G4double sigma = a * std::log10(e) + b;       
540     value = (std::pow(10., sigma));               
541   }                                               
542                                                   
543   // Switch to lin-lin interpolation              
544   /*                                              
545   if ((e2-e1)!=0)                                 
546   {                                               
547     G4double d1 = xs1;                            
548     G4double d2 = xs2;                            
549     value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1    
550   }                                               
551   */                                              
552                                                   
553   // Switch to log-lin interpolation for faste    
554                                                   
555   if ((e2 - e1) != 0 && xs1 != 0 && xs2 != 0 &    
556     G4double d1 = std::log10(xs1);                
557     G4double d2 = std::log10(xs2);                
558     value = std::pow(10., (d1 + (d2 - d1) * (e    
559   }                                               
560                                                   
561   // Switch to lin-lin interpolation for faste    
562   // in case one of xs1 or xs2 (=cum proba) va    
563                                                   
564   if ((e2 - e1) != 0 && (xs1 == 0 || xs2 == 0)    
565     G4double d1 = xs1;                            
566     G4double d2 = xs2;                            
567     value = (d1 + (d2 - d1) * (e - e1) / (e2 -    
568   }                                               
569   return value;                                   
570 }                                                 
571                                                   
572 //....oooOO0OOooo........oooOO0OOooo........oo    
573                                                   
574 G4double G4DNACPA100IonisationModel::QuadInter    
575                                                   
576                                                   
577                                                   
578 {                                                 
579   G4double interpolatedvalue1 = Interpolate(e1    
580   G4double interpolatedvalue2 = Interpolate(e2    
581   G4double value = Interpolate(t1, t2, t, inte    
582                                                   
583   return value;                                   
584 }                                                 
585                                                   
586 G4double                                          
587 G4DNACPA100IonisationModel::RandomizeEjectedEl    
588 {                                                 
589   auto MatID = std::get<0>(info);                 
590   auto shell = std::get<2>(info);                 
591   G4double secondaryElectronKineticEnergy =       
592     RandomTransferedEnergy(info) * eV - iStruc    
593   if (secondaryElectronKineticEnergy < 0.) {      
594     return 0.;                                    
595   }                                               
596   return secondaryElectronKineticEnergy;          
597 }                                                 
598                                                   
599 G4double G4DNACPA100IonisationModel::RandomTra    
600 {                                                 
601   auto materialID = std::get<0>(info);            
602   auto k = std::get<1>(info) / eV;  // data ta    
603   auto shell = std::get<2>(info);                 
604   G4double ejectedElectronEnergy = 0.;            
605   G4double valueK1 = 0;                           
606   G4double valueK2 = 0;                           
607   G4double valueCumulCS21 = 0;                    
608   G4double valueCumulCS22 = 0;                    
609   G4double valueCumulCS12 = 0;                    
610   G4double valueCumulCS11 = 0;                    
611   G4double secElecE11 = 0;                        
612   G4double secElecE12 = 0;                        
613   G4double secElecE21 = 0;                        
614   G4double secElecE22 = 0;                        
615                                                   
616   if (k == fTMapWithVec[materialID][fpParticle    
617     k = k * (1. - 1e-12);                         
618   }                                               
619                                                   
620   G4double random = G4UniformRand();              
621   auto k2 = std::upper_bound(fTMapWithVec[mate    
622                              fTMapWithVec[mate    
623   auto k1 = k2 - 1;                               
624                                                   
625   if (random <= fProbaShellMap[materialID][fpP    
626       && random <= fProbaShellMap[materialID][    
627   {                                               
628     auto cumulCS12 =                              
629       std::upper_bound(fProbaShellMap[material    
630                        fProbaShellMap[material    
631     auto cumulCS11 = cumulCS12 - 1;               
632     // Second one.                                
633     auto cumulCS22 =                              
634       std::upper_bound(fProbaShellMap[material    
635                        fProbaShellMap[material    
636     auto cumulCS21 = cumulCS22 - 1;               
637                                                   
638     valueK1 = *k1;                                
639     valueK2 = *k2;                                
640     valueCumulCS11 = *cumulCS11;                  
641     valueCumulCS12 = *cumulCS12;                  
642     valueCumulCS21 = *cumulCS21;                  
643     valueCumulCS22 = *cumulCS22;                  
644                                                   
645     secElecE11 = fEnergySecondaryData[material    
646     secElecE12 = fEnergySecondaryData[material    
647     secElecE21 = fEnergySecondaryData[material    
648     secElecE22 = fEnergySecondaryData[material    
649                                                   
650     if (valueCumulCS11 == 0. && valueCumulCS12    
651       auto interpolatedvalue2 =                   
652         Interpolate(valueCumulCS21, valueCumul    
653       G4double valueNrjTransf = Interpolate(va    
654       return valueNrjTransf;                      
655     }                                             
656   }                                               
657                                                   
658   if (random > fProbaShellMap[materialID][fpPa    
659     auto cumulCS22 =                              
660       std::upper_bound(fProbaShellMap[material    
661                        fProbaShellMap[material    
662     auto cumulCS21 = cumulCS22 - 1;               
663     valueK1 = *k1;                                
664     valueK2 = *k2;                                
665     valueCumulCS21 = *cumulCS21;                  
666     valueCumulCS22 = *cumulCS22;                  
667                                                   
668     secElecE21 = fEnergySecondaryData[material    
669     secElecE22 = fEnergySecondaryData[material    
670                                                   
671     G4double interpolatedvalue2 =                 
672       Interpolate(valueCumulCS21, valueCumulCS    
673                                                   
674     G4double value = Interpolate(valueK1, valu    
675     return value;                                 
676   }                                               
677   G4double nrjTransfProduct = secElecE11 * sec    
678                                                   
679   if (nrjTransfProduct != 0.) {                   
680     ejectedElectronEnergy =                       
681       QuadInterpolator(valueCumulCS11, valueCu    
682                        secElecE12, secElecE21,    
683   }                                               
684   return ejectedElectronEnergy;                   
685 }                                                 
686                                                   
687 //....oooOO0OOooo........oooOO0OOooo........oo    
688                                                   
689 G4double                                          
690 G4DNACPA100IonisationModel::RandomizeEjectedEl    
691 {                                                 
692   auto MatID = std::get<0>(info);                 
693   auto tt = std::get<1>(info);                    
694   auto shell = std::get<2>(info);                 
695   // ***** METHOD by M. C. Bordage ***** (opti    
696   //  Composition sampling method based on eq     
697                                                   
698   //// Defining constants                         
699   G4double alfa = 1. / 137;  // fine structure    
700   G4double e_charge = 1.6e-19;  // electron ch    
701   G4double e_mass = 9.1e-31;  // electron mass    
702   G4double c = 3e8;  // speed of light in vacu    
703   G4double mc2 = e_mass * c * c / e_charge;  /    
704                                                   
705   G4double BB = iStructure.IonisationEnergy(sh    
706                                                   
707   if (tt <= BB) return 0.;                        
708                                                   
709   G4double b_prime = BB / mc2;  // binding ene    
710   G4double beta_b2 = 1. - 1. / ((1 + b_prime)     
711                                                   
712   //// Indicent energy                            
713   //// tt is the incident electron energy         
714                                                   
715   G4double t_prime = tt / mc2;  // incident en    
716   G4double t = tt / BB;  // reduced incident e    
717                                                   
718   G4double D = (1 + 2 * t_prime) / ((1 + t_pri    
719   G4double F = b_prime * b_prime / ((1 + t_pri    
720                                                   
721   G4double beta_t2 = 1 - 1 / ((1 + t_prime) *     
722                                                   
723   G4double PHI_R = std::cos(std::sqrt(alfa * a    
724                             * std::log(beta_t2    
725   G4double G_R = std::log(beta_t2 / (1 - beta_    
726                                                   
727   G4double tplus1 = t + 1;                        
728   G4double tminus1 = t - 1;                       
729   G4double tplus12 = tplus1 * tplus1;             
730   G4double ZH1max = 1 + F - (PHI_R * D * (2 *     
731   G4double ZH2max = 1 - PHI_R * D / 4;            
732                                                   
733   G4double A1_p = ZH1max * tminus1 / tplus1;      
734   G4double A2_p = ZH2max * tminus1 / (t * tplu    
735   G4double A3_p = ((tplus12 - 4) / tplus12) *     
736                                                   
737   G4double AAA = A1_p + A2_p + A3_p;              
738                                                   
739   G4double AA1_R = A1_p / AAA;                    
740   G4double AA2_R = (A1_p + A2_p) / AAA;           
741                                                   
742   G4int FF = 0;                                   
743   G4double fx = 0;                                
744   G4double gx = 0;                                
745   G4double gg = 0;                                
746   G4double wx = 0;                                
747                                                   
748   G4double r1 = 0;                                
749   G4double r2 = 0;                                
750   G4double r3 = 0;                                
751                                                   
752   //                                              
753                                                   
754   do {                                            
755     r1 = G4UniformRand();                         
756     r2 = G4UniformRand();                         
757     r3 = G4UniformRand();                         
758                                                   
759     if (r1 > AA2_R)                               
760       FF = 3;                                     
761     else if ((r1 > AA1_R) && (r1 < AA2_R))        
762       FF = 2;                                     
763     else                                          
764       FF = 1;                                     
765                                                   
766     switch (FF) {                                 
767       case 1: {                                   
768         fx = r2 * tminus1 / tplus1;               
769         wx = 1 / (1 - fx) - 1;                    
770         gg = PHI_R * D * (wx + 1) / tplus1;       
771         gx = 1 - gg;                              
772         gx = gx - gg * (wx + 1) / (2 * (t - wx    
773         gx = gx + F * (wx + 1) * (wx + 1);        
774         gx = gx / ZH1max;                         
775         break;                                    
776       }                                           
777                                                   
778       case 2: {                                   
779         fx = tplus1 + r2 * tminus1;               
780         wx = t * tminus1 * r2 / fx;               
781         gx = 1 - (PHI_R * D * (t - wx) / (2 *     
782         gx = gx / ZH2max;                         
783         break;                                    
784       }                                           
785                                                   
786       case 3: {                                   
787         fx = 1 - r2 * (tplus12 - 4) / tplus12;    
788         wx = std::sqrt(1 / fx) - 1;               
789         gg = (wx + 1) / (t - wx);                 
790         gx = (1 + gg * gg * gg) / 2;              
791         break;                                    
792       }                                           
793     }  // switch                                  
794                                                   
795   } while (r3 > gx);                              
796                                                   
797   return wx * BB;                                 
798 }                                                 
799                                                   
800 //....oooOO0OOooo........oooOO0OOooo........oo    
801                                                   
802 void G4DNACPA100IonisationModel::ReadDiffCSFil    
803                                                   
804                                                   
805 {                                                 
806   const char* path = G4FindDataDir("G4LEDATA")    
807   if (path == nullptr) {                          
808     G4Exception("G4DNACPA100IonisationModel::R    
809                 "G4LEDATA environment variable    
810     return;                                       
811   }                                               
812                                                   
813   std::ostringstream fullFileName;                
814   fullFileName << path << "/" << file << ".dat    
815                                                   
816   std::ifstream diffCrossSection(fullFileName.    
817   std::stringstream endPath;                      
818   if (!diffCrossSection) {                        
819     endPath << "Missing data file: " << file;     
820     G4Exception("G4DNACPA100IonisationModel::I    
821                 endPath.str().c_str());           
822   }                                               
823                                                   
824   // load data from the file                      
825   fTMapWithVec[materialID][p].push_back(0.);      
826                                                   
827   G4String line;                                  
828                                                   
829   while (!diffCrossSection.eof()) {               
830     G4double T, E;                                
831     diffCrossSection >> T >> E;                   
832                                                   
833     if (T != fTMapWithVec[materialID][p].back(    
834       fTMapWithVec[materialID][p].push_back(T)    
835     }                                             
836                                                   
837     // T is incident energy, E is the energy t    
838     if (T != fTMapWithVec[materialID][p].back(    
839       fTMapWithVec[materialID][p].push_back(T)    
840     }                                             
841                                                   
842     auto eshell = (G4int)iStructure.NumberOfLe    
843     for (G4int shell = 0; shell < eshell; ++sh    
844       diffCrossSection >> diffCrossSectionData    
845       if (fasterCode) {                           
846         fEnergySecondaryData[materialID][p][sh    
847                             [diffCrossSectionD    
848                                                   
849         fProbaShellMap[materialID][p][shell][T    
850           diffCrossSectionData[materialID][p][    
851       }                                           
852       else {                                      
853         diffCrossSectionData[materialID][p][sh    
854         fEMapWithVector[materialID][p][T].push    
855       }                                           
856     }                                             
857   }                                               
858 }                                                 
859