Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4MicroElecInelasticModel.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/lowenergy/src/G4MicroElecInelasticModel.cc (Version 11.3.0) and /processes/electromagnetic/lowenergy/src/G4MicroElecInelasticModel.cc (Version 9.2.p1)


  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 //                                                
 27 // G4MicroElecInelasticModel.cc, 2011/08/29 A.    
 28 //                                                
 29 // Based on the following publications            
 30 //                                                
 31 //          - Inelastic cross-sections of low     
 32 //      for the simulation of heavy ion tracks    
 33 //      NSS Conf. Record 2010, pp. 80-85.         
 34 //      - Geant4 physics processes for microdo    
 35 //      very low energy electromagnetic models    
 36 //      NIM B, vol. 288, pp. 66 - 73, 2012.       
 37 //      - Geant4 physics processes for microdo    
 38 //      very low energy electromagnetic models    
 39 //      heavy ions in Si, NIM B, vol. 287, pp.    
 40 //                                                
 41 //....oooOO0OOooo........oooOO0OOooo........oo    
 42                                                   
 43 #include "G4MicroElecInelasticModel.hh"           
 44                                                   
 45 #include "globals.hh"                             
 46 #include "G4PhysicalConstants.hh"                 
 47 #include "G4SystemOfUnits.hh"                     
 48 #include "G4ios.hh"                               
 49 #include "G4UnitsTable.hh"                        
 50 #include "G4UAtomicDeexcitation.hh"               
 51 #include "G4MicroElecSiStructure.hh"              
 52 #include "G4LossTableManager.hh"                  
 53 #include "G4ionEffectiveCharge.hh"                
 54 #include "G4MicroElecCrossSectionDataSet.hh"      
 55 #include "G4Electron.hh"                          
 56 #include "G4Proton.hh"                            
 57 #include "G4GenericIon.hh"                        
 58 #include "G4ParticleDefinition.hh"                
 59 #include "G4NistManager.hh"                       
 60 #include "G4LogLogInterpolation.hh"               
 61 #include "G4DeltaAngle.hh"                        
 62                                                   
 63 //....oooOO0OOooo........oooOO0OOooo........oo    
 64                                                   
 65 using namespace std;                              
 66                                                   
 67 //....oooOO0OOooo........oooOO0OOooo........oo    
 68                                                   
 69 G4MicroElecInelasticModel::G4MicroElecInelasti    
 70                                                   
 71 :G4VEmModel(nam),isInitialised(false)             
 72 {                                                 
 73   nistSi = G4NistManager::Instance()->FindOrBu    
 74                                                   
 75   verboseLevel= 0;                                
 76   // Verbosity scale:                             
 77   // 0 = nothing                                  
 78   // 1 = warning for energy non-conservation      
 79   // 2 = details of energy budget                 
 80   // 3 = calculation of cross sections, file o    
 81   // 4 = entering in methods                      
 82                                                   
 83   if( verboseLevel>0 )                            
 84   {                                               
 85     G4cout << "MicroElec inelastic model is co    
 86   }                                               
 87                                                   
 88   //Mark this model as "applicable" for atomic    
 89   SetDeexcitationFlag(true);                      
 90   fAtomDeexcitation = nullptr;                    
 91   fParticleChangeForGamma = nullptr;              
 92                                                   
 93   // default generator                            
 94   SetAngularDistribution(new G4DeltaAngle());     
 95                                                   
 96   // Selection of computation method              
 97   fasterCode = true; //false;                     
 98 }                                                 
 99                                                   
100 //....oooOO0OOooo........oooOO0OOooo........oo    
101                                                   
102 G4MicroElecInelasticModel::~G4MicroElecInelast    
103 {                                                 
104   // Cross section                                
105   for (auto & pos : tableData)                    
106   {                                               
107     G4MicroElecCrossSectionDataSet* table = po    
108     delete table;                                 
109   }                                               
110                                                   
111   // Final state                                  
112   eVecm.clear();                                  
113   pVecm.clear();                                  
114                                                   
115 }                                                 
116                                                   
117 //....oooOO0OOooo........oooOO0OOooo........oo    
118                                                   
119 void G4MicroElecInelasticModel::Initialise(con    
120                                            con    
121 {                                                 
122                                                   
123   if (verboseLevel > 3)                           
124     G4cout << "Calling G4MicroElecInelasticMod    
125                                                   
126   // Energy limits                                
127                                                   
128   G4String fileElectron("microelec/sigma_inela    
129   G4String fileProton("microelec/sigma_inelast    
130                                                   
131   G4ParticleDefinition* electronDef = G4Electr    
132   G4ParticleDefinition* protonDef = G4Proton::    
133   G4String electron = electronDef->GetParticle    
134   G4String proton = protonDef->GetParticleName    
135                                                   
136   G4double scaleFactor = 1e-18 * cm *cm;          
137                                                   
138   const char* path = G4FindDataDir("G4LEDATA")    
139                                                   
140   // *** ELECTRON                                 
141   tableFile[electron] = fileElectron;             
142   lowEnergyLimit[electron] = 16.7 * eV;           
143   highEnergyLimit[electron] = 100.0 * MeV;        
144                                                   
145   // Cross section                                
146   G4MicroElecCrossSectionDataSet* tableE = new    
147   tableE->LoadData(fileElectron);                 
148                                                   
149   tableData[electron] = tableE;                   
150                                                   
151   // Final state                                  
152                                                   
153   std::ostringstream eFullFileName;               
154                                                   
155   if (fasterCode) eFullFileName << path << "/m    
156   else eFullFileName << path << "/microelec/si    
157                                                   
158   std::ifstream eDiffCrossSection(eFullFileNam    
159                                                   
160   if (!eDiffCrossSection)                         
161   {                                               
162      if (fasterCode) G4Exception("G4MicroElecI    
163      FatalException,"Missing data file:/microe    
164                                                   
165      else G4Exception("G4MicroElecInelasticMod    
166      FatalException,"Missing data file:/microe    
167   }                                               
168                                                   
169   // Clear the arrays for re-initialization ca    
170   // Octobre 22nd, 2014 - Melanie Raine           
171   eTdummyVec.clear();                             
172   pTdummyVec.clear();                             
173                                                   
174   eVecm.clear();                                  
175   pVecm.clear();                                  
176                                                   
177   for (int j=0; j<6; j++)                         
178   {                                               
179     eProbaShellMap[j].clear();                    
180     pProbaShellMap[j].clear();                    
181                                                   
182     eDiffCrossSectionData[j].clear();             
183     pDiffCrossSectionData[j].clear();             
184                                                   
185     eNrjTransfData[j].clear();                    
186     pNrjTransfData[j].clear();                    
187   }                                               
188                                                   
189   //                                              
190   eTdummyVec.push_back(0.);                       
191   while(!eDiffCrossSection.eof())                 
192   {                                               
193     G4double tDummy;                              
194     G4double eDummy;                              
195     eDiffCrossSection>>tDummy>>eDummy;            
196     if (tDummy != eTdummyVec.back()) eTdummyVe    
197                                                   
198     G4double tmp;                                 
199     for (int j=0; j<6; j++)                       
200     {                                             
201       eDiffCrossSection>> tmp;                    
202                                                   
203       eDiffCrossSectionData[j][tDummy][eDummy]    
204                                                   
205       if (fasterCode)                             
206       {                                           
207         eNrjTransfData[j][tDummy][eDiffCrossSe    
208         eProbaShellMap[j][tDummy].push_back(eD    
209       }                                           
210       else                                        
211       {                                           
212       // SI - only if eof is not reached !        
213   if (!eDiffCrossSection.eof()) eDiffCrossSect    
214   eVecm[tDummy].push_back(eDummy);                
215       }                                           
216                                                   
217     }                                             
218   }                                               
219   //                                              
220                                                   
221   // *** PROTON                                   
222   tableFile[proton] = fileProton;                 
223   lowEnergyLimit[proton] = 50. * keV;             
224   highEnergyLimit[proton] = 10. * GeV;            
225                                                   
226   // Cross section                                
227   G4MicroElecCrossSectionDataSet* tableP = new    
228   tableP->LoadData(fileProton);                   
229   tableData[proton] = tableP;                     
230                                                   
231   // Final state                                  
232   std::ostringstream pFullFileName;               
233                                                   
234   if (fasterCode) pFullFileName << path << "/m    
235   else pFullFileName << path << "/microelec/si    
236                                                   
237   std::ifstream pDiffCrossSection(pFullFileNam    
238                                                   
239   if (!pDiffCrossSection)                         
240   {                                               
241     if (fasterCode) G4Exception("G4MicroElecIn    
242       FatalException,"Missing data file:/micro    
243                                                   
244     else G4Exception("G4MicroElecInelasticMode    
245       FatalException,"Missing data file:/micro    
246   }                                               
247                                                   
248   pTdummyVec.push_back(0.);                       
249   while(!pDiffCrossSection.eof())                 
250   {                                               
251     G4double tDummy;                              
252     G4double eDummy;                              
253     pDiffCrossSection>>tDummy>>eDummy;            
254     if (tDummy != pTdummyVec.back()) pTdummyVe    
255     for (int j=0; j<6; j++)                       
256     {                                             
257       pDiffCrossSection>>pDiffCrossSectionData    
258                                                   
259       if (fasterCode)                             
260       {                                           
261         pNrjTransfData[j][tDummy][pDiffCrossSe    
262         pProbaShellMap[j][tDummy].push_back(pD    
263       }                                           
264       else                                        
265       {                                           
266   // SI - only if eof is not reached !            
267   if (!pDiffCrossSection.eof()) pDiffCrossSect    
268   pVecm[tDummy].push_back(eDummy);                
269       }                                           
270     }                                             
271   }                                               
272                                                   
273   if (particle==electronDef)                      
274   {                                               
275     SetLowEnergyLimit(lowEnergyLimit[electron]    
276     SetHighEnergyLimit(highEnergyLimit[electro    
277   }                                               
278                                                   
279   if (particle==protonDef)                        
280   {                                               
281     SetLowEnergyLimit(lowEnergyLimit[proton]);    
282     SetHighEnergyLimit(highEnergyLimit[proton]    
283   }                                               
284                                                   
285   if( verboseLevel>0 )                            
286   {                                               
287     G4cout << "MicroElec Inelastic model is in    
288     << "Energy range: "                           
289     << LowEnergyLimit() / keV << " keV - "        
290     << HighEnergyLimit() / MeV << " MeV for "     
291     << particle->GetParticleName()                
292      << " with mass (amu) " << particle->GetPD    
293      << " and charge " << particle->GetPDGChar    
294     << G4endl << G4endl ;                         
295   }                                               
296                                                   
297   //                                              
298   fAtomDeexcitation  = G4LossTableManager::Ins    
299                                                   
300   if (isInitialised) { return; }                  
301   fParticleChangeForGamma = GetParticleChangeF    
302   isInitialised = true;                           
303 }                                                 
304                                                   
305 //....oooOO0OOooo........oooOO0OOooo........oo    
306                                                   
307 G4double G4MicroElecInelasticModel::CrossSecti    
308                                                   
309                                                   
310                                                   
311                                                   
312 {                                                 
313   if (verboseLevel > 3)                           
314     G4cout << "Calling CrossSectionPerVolume()    
315                                                   
316   G4double density = material->GetTotNbOfAtoms    
317                                                   
318   // Calculate total cross section for model      
319   G4double lowLim = 0;                            
320   G4double highLim = 0;                           
321   G4double sigma=0;                               
322                                                   
323   const G4String& particleName = particleDefin    
324   G4String nameLocal = particleName ;             
325                                                   
326   G4double Zeff2 = 1.0;                           
327   G4double Mion_c2 = particleDefinition->GetPD    
328                                                   
329   if (Mion_c2 > proton_mass_c2)                   
330   {                                               
331     G4ionEffectiveCharge EffCharge ;              
332     G4double Zeff = EffCharge.EffectiveCharge(    
333     Zeff2 = Zeff*Zeff;                            
334                                                   
335     if (verboseLevel > 3)                         
336       G4cout << "Before scaling : " << G4endl     
337       << "Particle : " << nameLocal << ", mass    
338       << ", Ekin (eV) = " << ekin/eV << G4endl    
339                                                   
340     ekin *= proton_mass_c2/Mion_c2 ;              
341     nameLocal = "proton" ;                        
342                                                   
343     if (verboseLevel > 3)                         
344       G4cout << "After scaling : " << G4endl      
345       << "Particle : " << nameLocal  << ", Eki    
346   }                                               
347                                                   
348   if (material == nistSi || material->GetBaseM    
349   {                                               
350     auto pos1 = lowEnergyLimit.find(nameLocal)    
351     if (pos1 != lowEnergyLimit.end())             
352     {                                             
353       lowLim = pos1->second;                      
354     }                                             
355                                                   
356     auto pos2 = highEnergyLimit.find(nameLocal    
357     if (pos2 != highEnergyLimit.end())            
358     {                                             
359       highLim = pos2->second;                     
360     }                                             
361                                                   
362     if (ekin >= lowLim && ekin < highLim)         
363     {                                             
364       auto pos = tableData.find(nameLocal);       
365       if (pos != tableData.end())                 
366       {                                           
367         G4MicroElecCrossSectionDataSet* table     
368         if (table != nullptr)                     
369         {                                         
370           sigma = table->FindValue(ekin);         
371         }                                         
372       }                                           
373       else                                        
374       {                                           
375         G4Exception("G4MicroElecInelasticModel    
376         FatalException,"Model not applicable t    
377       }                                           
378     }                                             
379     else                                          
380     {                                             
381       if (nameLocal!="e-")                        
382       {                                           
383         // G4cout << "Particle : " << nameLoca    
384         // G4cout << "### Warning: particle en    
385       }                                           
386     }                                             
387                                                   
388     if (verboseLevel > 3)                         
389     {                                             
390       G4cout << "---> Kinetic energy (eV)=" <<    
391       G4cout << " - Cross section per Si atom     
392       G4cout << " - Cross section per Si atom     
393     }                                             
394                                                   
395   } // if (SiMaterial)                            
396   return sigma*density*Zeff2;                     
397 }                                                 
398                                                   
399 //....oooOO0OOooo........oooOO0OOooo........oo    
400                                                   
401 void G4MicroElecInelasticModel::SampleSecondar    
402                                                   
403                                                   
404                                                   
405                                                   
406 {                                                 
407                                                   
408   if (verboseLevel > 3)                           
409     G4cout << "Calling SampleSecondaries() of     
410                                                   
411   G4double lowLim = 0;                            
412   G4double highLim = 0;                           
413                                                   
414   G4double ekin = particle->GetKineticEnergy()    
415   G4double k = ekin ;                             
416                                                   
417   G4ParticleDefinition* PartDef = particle->Ge    
418   const G4String& particleName = PartDef->GetP    
419   G4String nameLocal2 = particleName ;            
420   G4double particleMass = particle->GetDefinit    
421                                                   
422   if (particleMass > proton_mass_c2)              
423   {                                               
424     k *= proton_mass_c2/particleMass ;            
425     PartDef = G4Proton::ProtonDefinition();       
426     nameLocal2 = "proton" ;                       
427   }                                               
428                                                   
429   auto pos1 = lowEnergyLimit.find(nameLocal2);    
430   if (pos1 != lowEnergyLimit.end())               
431   {                                               
432     lowLim = pos1->second;                        
433   }                                               
434                                                   
435   auto pos2 = highEnergyLimit.find(nameLocal2)    
436   if (pos2 != highEnergyLimit.end())              
437   {                                               
438     highLim = pos2->second;                       
439   }                                               
440                                                   
441   if (k >= lowLim && k < highLim)                 
442   {                                               
443     G4ParticleMomentum primaryDirection = part    
444     G4double totalEnergy = ekin + particleMass    
445     G4double pSquare = ekin * (totalEnergy + p    
446     G4double totalMomentum = std::sqrt(pSquare    
447                                                   
448     G4int Shell = 0;                              
449                                                   
450     /* if (!fasterCode)*/ Shell = RandomSelect    
451                                                   
452     // SI: The following protection is necessa    
453     //  sigmadiff_ionisation_e_born.dat has no    
454     //  sigmadiff_cumulated_ionisation_e_born.    
455     //  this is due to the fact that the max a    
456     //  strictly above this value have non zer    
457                                                   
458     G4double bindingEnergy = SiStructure.Energ    
459                                                   
460     if (verboseLevel > 3)                         
461     {                                             
462       G4cout << "---> Kinetic energy (eV)=" <<    
463       G4cout << "Shell: " << Shell << ", energ    
464     }                                             
465                                                   
466     // sample deexcitation                        
467     std::size_t secNumberInit = 0;  // need to    
468     std::size_t secNumberFinal = 0; // So I'll    
469                                                   
470     //SI: additional protection if tcs interpo    
471     if (k<bindingEnergy) return;                  
472                                                   
473     G4int Z = 14;                                 
474                                                   
475     if(fAtomDeexcitation && Shell > 2) {          
476                                                   
477       G4AtomicShellEnumerator as = fKShell;       
478                                                   
479       if (Shell == 4)                             
480       {                                           
481         as = G4AtomicShellEnumerator(1);          
482       }                                           
483       else if (Shell == 3)                        
484       {                                           
485         as = G4AtomicShellEnumerator(3);          
486       }                                           
487                                                   
488       const G4AtomicShell* shell = fAtomDeexci    
489       secNumberInit = fvect->size();              
490       fAtomDeexcitation->GenerateParticles(fve    
491       secNumberFinal = fvect->size();             
492     }                                             
493                                                   
494     G4double secondaryKinetic=-1000*eV;           
495                                                   
496     if (!fasterCode)                              
497     {                                             
498       secondaryKinetic = RandomizeEjectedElect    
499     }                                             
500     else                                          
501     {                                             
502       secondaryKinetic = RandomizeEjectedElect    
503     }                                             
504                                                   
505     if (verboseLevel > 3)                         
506     {                                             
507       G4cout << "Ionisation process" << G4endl    
508       G4cout << "Shell: " << Shell << " Kin. e    
509       << " Sec. energy (eV)=" << secondaryKine    
510     }                                             
511                                                   
512     G4ThreeVector deltaDirection =                
513     GetAngularDistribution()->SampleDirectionF    
514                                                   
515                                                   
516                                                   
517     if (particle->GetDefinition() == G4Electro    
518     {                                             
519       G4double deltaTotalMomentum = std::sqrt(    
520       G4double finalPx = totalMomentum*primary    
521       G4double finalPy = totalMomentum*primary    
522       G4double finalPz = totalMomentum*primary    
523       G4double finalMomentum = std::sqrt(final    
524       finalPx /= finalMomentum;                   
525       finalPy /= finalMomentum;                   
526       finalPz /= finalMomentum;                   
527                                                   
528       G4ThreeVector direction;                    
529       direction.set(finalPx,finalPy,finalPz);     
530                                                   
531       fParticleChangeForGamma->ProposeMomentum    
532     }                                             
533     else                                          
534       fParticleChangeForGamma->ProposeMomentum    
535                                                   
536     // note that secondaryKinetic is the energ    
537     G4double deexSecEnergy = 0;                   
538     for (std::size_t j=secNumberInit; j < secN    
539       deexSecEnergy = deexSecEnergy + (*fvect)    
540                                                   
541     fParticleChangeForGamma->SetProposedKineti    
542     fParticleChangeForGamma->ProposeLocalEnerg    
543                                                   
544     if (secondaryKinetic>0)                       
545     {                                             
546       G4DynamicParticle* dp = new G4DynamicPar    
547       fvect->push_back(dp);                       
548     }                                             
549   }                                               
550 }                                                 
551                                                   
552 //....oooOO0OOooo........oooOO0OOooo........oo    
553                                                   
554 G4double G4MicroElecInelasticModel::RandomizeE    
555                                                   
556 {                                                 
557   if (particleDefinition == G4Electron::Electr    
558   {                                               
559     G4double maximumEnergyTransfer=0.;            
560     if ((k+SiStructure.Energy(shell))/2. > k)     
561     else maximumEnergyTransfer = (k+SiStructur    
562                                                   
563     G4double crossSectionMaximum = 0.;            
564                                                   
565     G4double minEnergy = SiStructure.Energy(sh    
566     G4double maxEnergy = maximumEnergyTransfer    
567     G4int nEnergySteps = 100;                     
568                                                   
569     G4double value(minEnergy);                    
570     G4double stpEnergy(std::pow(maxEnergy/valu    
571     G4int step(nEnergySteps);                     
572     while (step>0)                                
573     {                                             
574       step--;                                     
575       G4double differentialCrossSection = Diff    
576       if(differentialCrossSection >= crossSect    
577       value*=stpEnergy;                           
578     }                                             
579                                                   
580     G4double secondaryElectronKineticEnergy=0.    
581     do                                            
582     {                                             
583       secondaryElectronKineticEnergy = G4Unifo    
584     } while(G4UniformRand()*crossSectionMaximu    
585             DifferentialCrossSection(particleD    
586                                                   
587     return secondaryElectronKineticEnergy;        
588   }                                               
589                                                   
590   if (particleDefinition == G4Proton::ProtonDe    
591   {                                               
592     G4double maximumEnergyTransfer = 4.* (elec    
593     G4double crossSectionMaximum = 0.;            
594                                                   
595     G4double minEnergy = SiStructure.Energy(sh    
596     G4double maxEnergy = maximumEnergyTransfer    
597     G4int nEnergySteps = 100;                     
598                                                   
599     G4double value(minEnergy);                    
600     G4double stpEnergy(std::pow(maxEnergy/valu    
601     G4int step(nEnergySteps);                     
602     while (step>0)                                
603     {                                             
604       step--;                                     
605       G4double differentialCrossSection = Diff    
606       if(differentialCrossSection >= crossSect    
607       value*=stpEnergy;                           
608     }                                             
609                                                   
610     G4double secondaryElectronKineticEnergy =     
611     do                                            
612     {                                             
613       secondaryElectronKineticEnergy = G4Unifo    
614                                                   
615     } while(G4UniformRand()*crossSectionMaximu    
616             DifferentialCrossSection(particleD    
617     return secondaryElectronKineticEnergy;        
618   }                                               
619                                                   
620   return 0;                                       
621 }                                                 
622                                                   
623 //....oooOO0OOooo........oooOO0OOooo........oo    
624                                                   
625 // The following section is not used anymore b    
626 // GetAngularDistribution()->SampleDirectionFo    
627                                                   
628 /*void G4MicroElecInelasticModel::RandomizeEje    
629  G4double k,                                      
630  G4double secKinetic,                             
631  G4double & cosTheta,                             
632  G4double & phi )                                 
633  {                                                
634  if (particleDefinition == G4Electron::Electro    
635  {                                                
636  phi = twopi * G4UniformRand();                   
637  G4double sin2O = (1.-secKinetic/k) / (1.+secK    
638  cosTheta = std::sqrt(1.-sin2O);                  
639  }                                                
640                                                   
641  if (particleDefinition == G4Proton::ProtonDef    
642  {                                                
643  G4double maxSecKinetic = 4.* (electron_mass_c    
644  phi = twopi * G4UniformRand();                   
645  cosTheta = std::sqrt(secKinetic / maxSecKinet    
646  }                                                
647                                                   
648  else                                             
649  {                                                
650  G4double maxSecKinetic = 4.* (electron_mass_c    
651  phi = twopi * G4UniformRand();                   
652  cosTheta = std::sqrt(secKinetic / maxSecKinet    
653  }                                                
654  }                                                
655  */                                               
656                                                   
657 //....oooOO0OOooo........oooOO0OOooo........oo    
658                                                   
659 G4double G4MicroElecInelasticModel::Differenti    
660                                                   
661                                                   
662                                                   
663 {                                                 
664   G4double sigma = 0.;                            
665                                                   
666   if (energyTransfer >= SiStructure.Energy(Lev    
667   {                                               
668     G4double valueT1 = 0;                         
669     G4double valueT2 = 0;                         
670     G4double valueE21 = 0;                        
671     G4double valueE22 = 0;                        
672     G4double valueE12 = 0;                        
673     G4double valueE11 = 0;                        
674                                                   
675     G4double xs11 = 0;                            
676     G4double xs12 = 0;                            
677     G4double xs21 = 0;                            
678     G4double xs22 = 0;                            
679                                                   
680     if (particleDefinition == G4Electron::Elec    
681     {                                             
682       // k should be in eV and energy transfer    
683       auto t2 = std::upper_bound(eTdummyVec.be    
684       auto t1 = t2-1;                             
685       // The following condition avoids situat    
686       if (energyTransfer <= eVecm[(*t1)].back(    
687       {                                           
688         auto e12 = std::upper_bound(eVecm[(*t1    
689         auto e11 = e12-1;                         
690         auto e22 = std::upper_bound(eVecm[(*t2    
691         auto e21 = e22-1;                         
692                                                   
693         valueT1  =*t1;                            
694         valueT2  =*t2;                            
695         valueE21 =*e21;                           
696         valueE22 =*e22;                           
697         valueE12 =*e12;                           
698         valueE11 =*e11;                           
699                                                   
700         xs11 = eDiffCrossSectionData[LevelInde    
701         xs12 = eDiffCrossSectionData[LevelInde    
702         xs21 = eDiffCrossSectionData[LevelInde    
703         xs22 = eDiffCrossSectionData[LevelInde    
704       }                                           
705     }                                             
706                                                   
707     if (particleDefinition == G4Proton::Proton    
708     {                                             
709       // k should be in eV and energy transfer    
710       auto t2 = std::upper_bound(pTdummyVec.be    
711       auto t1 = t2-1;                             
712       if (energyTransfer <= pVecm[(*t1)].back(    
713       {                                           
714         auto e12 = std::upper_bound(pVecm[(*t1    
715         auto e11 = e12-1;                         
716                                                   
717         auto e22 = std::upper_bound(pVecm[(*t2    
718         auto e21 = e22-1;                         
719                                                   
720         valueT1  =*t1;                            
721         valueT2  =*t2;                            
722         valueE21 =*e21;                           
723         valueE22 =*e22;                           
724         valueE12 =*e12;                           
725         valueE11 =*e11;                           
726                                                   
727         xs11 = pDiffCrossSectionData[LevelInde    
728         xs12 = pDiffCrossSectionData[LevelInde    
729         xs21 = pDiffCrossSectionData[LevelInde    
730         xs22 = pDiffCrossSectionData[LevelInde    
731       }                                           
732     }                                             
733                                                   
734     sigma = QuadInterpolator(     valueE11, va    
735           valueE21, valueE22,                     
736           xs11, xs12,                             
737           xs21, xs22,                             
738           valueT1, valueT2,                       
739           k, energyTransfer);                     
740   }                                               
741   return sigma;                                   
742 }                                                 
743                                                   
744 //....oooOO0OOooo........oooOO0OOooo........oo    
745                                                   
746 G4double G4MicroElecInelasticModel::Interpolat    
747                                                   
748                                                   
749                                                   
750                                                   
751 {                                                 
752   G4double value = 0.;                            
753                                                   
754   // Log-log interpolation by default             
755   if (e1 != 0 && e2 != 0 && (std::log10(e2) -     
756       && !fasterCode)                             
757   {                                               
758     G4double a = (std::log10(xs2)-std::log10(x    
759     G4double b = std::log10(xs2) - a*std::log1    
760     G4double sigma = a*std::log10(e) + b;         
761     value = (std::pow(10.,sigma));                
762                                                   
763   }                                               
764                                                   
765   // Switch to log-lin interpolation for faste    
766   if ((e2 - e1) != 0 && xs1 != 0 && xs2 != 0 &    
767   {                                               
768     G4double d1 = std::log10(xs1);                
769     G4double d2 = std::log10(xs2);                
770     value = std::pow(10., (d1 + (d2 - d1) * (e    
771   }                                               
772                                                   
773   // Switch to lin-lin interpolation for faste    
774   // in case one of xs1 or xs2 (=cum proba) va    
775   if ((e2 - e1) != 0 && (xs1 == 0 || xs2 == 0)    
776   {                                               
777     G4double d1 = xs1;                            
778     G4double d2 = xs2;                            
779     value = (d1 + (d2 - d1) * (e - e1) / (e2 -    
780   }                                               
781                                                   
782   return value;                                   
783 }                                                 
784                                                   
785 //....oooOO0OOooo........oooOO0OOooo........oo    
786                                                   
787 G4double G4MicroElecInelasticModel::QuadInterp    
788                                                   
789                                                   
790                                                   
791                                                   
792                                                   
793 {                                                 
794   G4double interpolatedvalue1 = Interpolate(e1    
795   G4double interpolatedvalue2 = Interpolate(e2    
796   G4double value = Interpolate(t1, t2, t, inte    
797   return value;                                   
798 }                                                 
799                                                   
800 //....oooOO0OOooo........oooOO0OOooo........oo    
801                                                   
802 G4int G4MicroElecInelasticModel::RandomSelect(    
803 {                                                 
804   G4int level = 0;                                
805                                                   
806   auto pos = tableData.find(particle);            
807   if (pos != tableData.cend())                    
808   {                                               
809     G4MicroElecCrossSectionDataSet* table = po    
810                                                   
811     if (table != nullptr)                         
812     {                                             
813       G4double* valuesBuffer = new G4double[ta    
814       const G4int n = (G4int)table->NumberOfCo    
815       G4int i(n);                                 
816       G4double value = 0.;                        
817                                                   
818       while (i>0)                                 
819       {                                           
820         --i;                                      
821         valuesBuffer[i] = table->GetComponent(    
822         value += valuesBuffer[i];                 
823       }                                           
824                                                   
825       value *= G4UniformRand();                   
826                                                   
827       i = n;                                      
828                                                   
829       while (i > 0)                               
830       {                                           
831         --i;                                      
832                                                   
833         if (valuesBuffer[i] > value)              
834         {                                         
835           delete[] valuesBuffer;                  
836           return i;                               
837         }                                         
838         value -= valuesBuffer[i];                 
839       }                                           
840                                                   
841       if (valuesBuffer) delete[] valuesBuffer;    
842                                                   
843     }                                             
844   }                                               
845   else                                            
846   {                                               
847     G4Exception("G4MicroElecInelasticModel::Ra    
848   }                                               
849                                                   
850   return level;                                   
851 }                                                 
852                                                   
853 //....oooOO0OOooo........oooOO0OOooo........oo    
854                                                   
855 G4double G4MicroElecInelasticModel::RandomizeE    
856                                                   
857                                                   
858 {                                                 
859                                                   
860   G4double secondaryElectronKineticEnergy = 0.    
861   G4double random = G4UniformRand();              
862   secondaryElectronKineticEnergy = TransferedE    
863                                                   
864                                                   
865                                                   
866       - SiStructure.Energy(shell);                
867                                                   
868   if (secondaryElectronKineticEnergy < 0.)        
869     return 0.;                                    
870   //                                              
871   return secondaryElectronKineticEnergy;          
872 }                                                 
873                                                   
874 //....oooOO0OOooo........oooOO0OOooo........oo    
875                                                   
876 G4double G4MicroElecInelasticModel::Transfered    
877                                                   
878                                                   
879                                                   
880 {                                                 
881   G4double nrj = 0.;                              
882                                                   
883   G4double valueK1 = 0;                           
884   G4double valueK2 = 0;                           
885   G4double valuePROB21 = 0;                       
886   G4double valuePROB22 = 0;                       
887   G4double valuePROB12 = 0;                       
888   G4double valuePROB11 = 0;                       
889                                                   
890   G4double nrjTransf11 = 0;                       
891   G4double nrjTransf12 = 0;                       
892   G4double nrjTransf21 = 0;                       
893   G4double nrjTransf22 = 0;                       
894                                                   
895   G4double maximumEnergyTransfer1 = 0;            
896   G4double maximumEnergyTransfer2 = 0;            
897   G4double maximumEnergyTransferP = 4.* (elect    
898   G4double bindingEnergy = SiStructure.Energy(    
899                                                   
900   if (particleDefinition == G4Electron::Electr    
901   {                                               
902     // k should be in eV                          
903     auto k2 = std::upper_bound(eTdummyVec.begi    
904              eTdummyVec.end(),                    
905              k);                                  
906     auto k1 = k2 - 1;                             
907                                                   
908     /*                                            
909      G4cout << "----> k=" << k                    
910      << " " << *k1                                
911      << " " << *k2                                
912      << " " << random                             
913      << " " << ionizationLevelIndex               
914      << " " << eProbaShellMap[ionizationLevelI    
915      << " " << eProbaShellMap[ionizationLevelI    
916      << G4endl;                                   
917      */                                           
918                                                   
919     // SI : the following condition avoids sit    
920     if (random <= eProbaShellMap[ionizationLev    
921         && random <= eProbaShellMap[ionization    
922     {                                             
923       auto prob12 =                               
924           std::upper_bound(eProbaShellMap[ioni    
925                            eProbaShellMap[ioni    
926                            random);               
927       auto prob11 = prob12 - 1;                   
928       auto prob22 =                               
929           std::upper_bound(eProbaShellMap[ioni    
930                            eProbaShellMap[ioni    
931                            random);               
932       auto prob21 = prob22 - 1;                   
933                                                   
934       valueK1 = *k1;                              
935       valueK2 = *k2;                              
936       valuePROB21 = *prob21;                      
937       valuePROB22 = *prob22;                      
938       valuePROB12 = *prob12;                      
939       valuePROB11 = *prob11;                      
940                                                   
941       // The following condition avoid getting    
942       if(valuePROB11 == 0) nrjTransf11 = bindi    
943       else nrjTransf11 = eNrjTransfData[ioniza    
944       if(valuePROB12 == 1)                        
945       {                                           
946   if ((valueK1+bindingEnergy)/2. > valueK1) ma    
947       else maximumEnergyTransfer1 = (valueK1+b    
948                                                   
949   nrjTransf12 = maximumEnergyTransfer1;           
950       }                                           
951       else nrjTransf12 = eNrjTransfData[ioniza    
952                                                   
953       if(valuePROB21 == 0) nrjTransf21 = bindi    
954       else nrjTransf21 = eNrjTransfData[ioniza    
955       if(valuePROB22 == 1)                        
956       {                                           
957   if ((valueK2+bindingEnergy)/2. > valueK2) ma    
958       else maximumEnergyTransfer2 = (valueK2+b    
959                                                   
960   nrjTransf22 = maximumEnergyTransfer2;           
961       }                                           
962       else                                        
963   nrjTransf22 = eNrjTransfData[ionizationLevel    
964     }                                             
965     // Avoids cases where cum xs is zero for k    
966     if (random > eProbaShellMap[ionizationLeve    
967     {                                             
968       auto prob22 =                               
969           std::upper_bound(eProbaShellMap[ioni    
970                            eProbaShellMap[ioni    
971                            random);               
972                                                   
973       auto prob21 = prob22 - 1;                   
974                                                   
975       valueK1 = *k1;                              
976       valueK2 = *k2;                              
977       valuePROB21 = *prob21;                      
978       valuePROB22 = *prob22;                      
979                                                   
980       nrjTransf21 = eNrjTransfData[ionizationL    
981       nrjTransf22 = eNrjTransfData[ionizationL    
982                                                   
983       G4double interpolatedvalue2 = Interpolat    
984                                                   
985                                                   
986                                                   
987                                                   
988                                                   
989       // zeros are explicitly set                 
990       G4double value = Interpolate(valueK1, va    
991       return value;                               
992     }                                             
993   }                                               
994   //                                              
995   else if (particleDefinition == G4Proton::Pro    
996   {                                               
997     // k should be in eV                          
998     auto k2 = std::upper_bound(pTdummyVec.begi    
999              pTdummyVec.end(),                    
1000              k);                                 
1001                                                  
1002     auto k1 = k2 - 1;                            
1003                                                  
1004     /*                                           
1005      G4cout << "----> k=" << k                   
1006      << " " << *k1                               
1007      << " " << *k2                               
1008      << " " << random                            
1009      << " " << ionizationLevelIndex              
1010      << " " << pProbaShellMap[ionizationLevel    
1011      << " " << pProbaShellMap[ionizationLevel    
1012      << G4endl;                                  
1013      */                                          
1014                                                  
1015     // SI : the following condition avoids si    
1016     //      for eg. when the last element is     
1017     if (random <= pProbaShellMap[ionizationLe    
1018         && random <= pProbaShellMap[ionizatio    
1019     {                                            
1020       auto prob12 =                              
1021           std::upper_bound(pProbaShellMap[ion    
1022                            pProbaShellMap[ion    
1023                            random);              
1024                                                  
1025       auto prob11 = prob12 - 1;                  
1026                                                  
1027       auto prob22 =                              
1028   std::upper_bound(pProbaShellMap[ionizationL    
1029        pProbaShellMap[ionizationLevelIndex][(    
1030        random);                                  
1031                                                  
1032       auto prob21 = prob22 - 1;                  
1033                                                  
1034       valueK1 = *k1;                             
1035       valueK2 = *k2;                             
1036       valuePROB21 = *prob21;                     
1037       valuePROB22 = *prob22;                     
1038       valuePROB12 = *prob12;                     
1039       valuePROB11 = *prob11;                     
1040                                                  
1041       // The following condition avoid gettin    
1042       if(valuePROB11 == 0) nrjTransf11 = bind    
1043       else nrjTransf11 = pNrjTransfData[ioniz    
1044       if(valuePROB12 == 1) nrjTransf12 = maxi    
1045       else nrjTransf12 = pNrjTransfData[ioniz    
1046       if(valuePROB21 == 0) nrjTransf21 = bind    
1047       else nrjTransf21 = pNrjTransfData[ioniz    
1048       if(valuePROB22 == 1) nrjTransf22 = maxi    
1049       else nrjTransf22 = pNrjTransfData[ioniz    
1050                                                  
1051     }                                            
1052                                                  
1053     // Avoids cases where cum xs is zero for     
1054     if (random > pProbaShellMap[ionizationLev    
1055     {                                            
1056       auto prob22 =                              
1057           std::upper_bound(pProbaShellMap[ion    
1058                            pProbaShellMap[ion    
1059                            random);              
1060                                                  
1061       auto prob21 = prob22 - 1;                  
1062                                                  
1063       valueK1 = *k1;                             
1064       valueK2 = *k2;                             
1065       valuePROB21 = *prob21;                     
1066       valuePROB22 = *prob22;                     
1067                                                  
1068       nrjTransf21 = pNrjTransfData[ionization    
1069       nrjTransf22 = pNrjTransfData[ionization    
1070                                                  
1071       G4double interpolatedvalue2 = Interpola    
1072                                                  
1073                                                  
1074                                                  
1075                                                  
1076                                                  
1077       // zeros are explicitly set                
1078       G4double value = Interpolate(valueK1, v    
1079                                                  
1080       return value;                              
1081     }                                            
1082   }                                              
1083   // End electron and proton cases               
1084                                                  
1085   G4double nrjTransfProduct = nrjTransf11 * n    
1086       * nrjTransf22;                             
1087                                                  
1088   if (nrjTransfProduct != 0.)                    
1089   {                                              
1090     nrj = QuadInterpolator(valuePROB11,          
1091                            valuePROB12,          
1092                            valuePROB21,          
1093                            valuePROB22,          
1094                            nrjTransf11,          
1095                            nrjTransf12,          
1096                            nrjTransf21,          
1097                            nrjTransf22,          
1098                            valueK1,              
1099                            valueK2,              
1100                            k,                    
1101                            random);              
1102   }                                              
1103                                                  
1104   return nrj;                                    
1105 }                                                
1106                                                  
1107                                                  
1108