Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/advanced/eRosita/physics/src/G4eLowEnergyLoss.cc

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

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 //
 27 //  
 28 // -----------------------------------------------------------
 29 //      GEANT 4 class implementation file 
 30 //
 31 //      History: based on object model of
 32 //      2nd December 1995, G.Cosmo
 33 //      ---------- G4eLowEnergyLoss physics process -----------
 34 //                by Laszlo Urban, 20 March 1997 
 35 // **************************************************************
 36 // It calculates the energy loss of e+/e-.
 37 // --------------------------------------------------------------
 38 //
 39 // 08-05-97: small changes by L.Urban
 40 // 27-05-98: several bugs and inconsistencies are corrected,
 41 //           new table (the inverse of the range table) added ,
 42 //           AlongStepDoit uses now this new table. L.Urban
 43 // 08-09-98: cleanup
 44 // 24-09-98: rndmStepFlag false by default (no randomization of the step)
 45 // 14-10-98: messenger file added.
 46 // 16-10-98: public method SetStepFunction()
 47 // 20-01-99: important correction in AlongStepDoIt , L.Urban
 48 // 10/02/00  modifications , new e.m. structure, L.Urban
 49 // 11/04/00: Bug fix in dE/dx fluctuation simulation, Veronique Lefebure
 50 // 19-09-00  change of fluctuation sampling V.Ivanchenko
 51 // 20/09/00  update fluctuations V.Ivanchenko
 52 // 18/10/01  add fluorescence AlongStepDoIt V.Ivanchenko
 53 // 18/10/01  Revision to improve code quality and consistency with design, MGP
 54 // 19/10/01  update according to new design, V.Ivanchenko
 55 // 24/10/01  MGP - Protection against negative energy loss in AlongStepDoIt
 56 // 26/10/01  VI Clean up access to deexcitation
 57 // 23/11/01  VI Move static member-functions from header to source
 58 // 28/05/02  VI Remove flag fStopAndKill
 59 // 03/06/02  MGP - Restore fStopAndKill
 60 // 28/10/02  VI Optimal binning for dE/dx
 61 // 21/01/03  VI cut per region
 62 // 01/06/04  VI check if stopped particle has AtRest processes
 63 //
 64 // --------------------------------------------------------------
 65 
 66 #include "G4eLowEnergyLoss.hh"
 67 #include "G4SystemOfUnits.hh"
 68 #include ""
 69 #include "G4Poisson.hh"
 70 #include "G4ProductionCutsTable.hh"
 71 
 72 //
 73 
 74 // Initialisation of static data members
 75 // -------------------------------------
 76 // Contributing processes : ion.loss + soft brems->NbOfProcesses is initialized
 77 // to 2 . YOU DO NOT HAVE TO CHANGE this variable for a 'normal' run.
 78 //
 79 // You have to change NbOfProcesses if you invent a new process contributing
 80 // to the continuous energy loss.
 81 // The NbOfProcesses data member can be changed using the (public static)
 82 // functions Get/Set/Plus/MinusNbOfProcesses (see G4eLowEnergyLoss.hh)
 83 
 84 G4int            G4eLowEnergyLoss::NbOfProcesses = 2;
 85 
 86 G4int            G4eLowEnergyLoss::CounterOfElectronProcess = 0;
 87 G4int            G4eLowEnergyLoss::CounterOfPositronProcess = 0;
 88 G4PhysicsTable** G4eLowEnergyLoss::RecorderOfElectronProcess =
 89                                            new G4PhysicsTable*[10];
 90 G4PhysicsTable** G4eLowEnergyLoss::RecorderOfPositronProcess =
 91                                            new G4PhysicsTable*[10];
 92 
 93 
 94 G4PhysicsTable*  G4eLowEnergyLoss::theDEDXElectronTable         = 0;
 95 G4PhysicsTable*  G4eLowEnergyLoss::theDEDXPositronTable         = 0;
 96 G4PhysicsTable*  G4eLowEnergyLoss::theRangeElectronTable        = 0;
 97 G4PhysicsTable*  G4eLowEnergyLoss::theRangePositronTable        = 0;
 98 G4PhysicsTable*  G4eLowEnergyLoss::theInverseRangeElectronTable = 0;
 99 G4PhysicsTable*  G4eLowEnergyLoss::theInverseRangePositronTable = 0;
100 G4PhysicsTable*  G4eLowEnergyLoss::theLabTimeElectronTable      = 0;
101 G4PhysicsTable*  G4eLowEnergyLoss::theLabTimePositronTable      = 0;
102 G4PhysicsTable*  G4eLowEnergyLoss::theProperTimeElectronTable   = 0;
103 G4PhysicsTable*  G4eLowEnergyLoss::theProperTimePositronTable   = 0;
104 
105 G4PhysicsTable*  G4eLowEnergyLoss::theeRangeCoeffATable         = 0;
106 G4PhysicsTable*  G4eLowEnergyLoss::theeRangeCoeffBTable         = 0;
107 G4PhysicsTable*  G4eLowEnergyLoss::theeRangeCoeffCTable         = 0;
108 G4PhysicsTable*  G4eLowEnergyLoss::thepRangeCoeffATable         = 0;
109 G4PhysicsTable*  G4eLowEnergyLoss::thepRangeCoeffBTable         = 0;
110 G4PhysicsTable*  G4eLowEnergyLoss::thepRangeCoeffCTable         = 0;
111 
112 G4double         G4eLowEnergyLoss::LowerBoundEloss = 10.*eV ;
113 G4double         G4eLowEnergyLoss::UpperBoundEloss = 100.*GeV ;
114 G4int            G4eLowEnergyLoss::NbinEloss = 360 ;
115 G4double         G4eLowEnergyLoss::RTable ;
116 G4double         G4eLowEnergyLoss::LOGRTable ;
117 
118 
119 G4EnergyLossMessenger* G4eLowEnergyLoss::eLossMessenger         = 0;
120 
121 //    
122  
123 // constructor and destructor
124  
125 G4eLowEnergyLoss::G4eLowEnergyLoss(const G4String& processName)
126    : G4RDVeLowEnergyLoss (processName),
127      theLossTable(0),
128      MinKineticEnergy(1.*eV),
129      Charge(-1.),
130      lastCharge(0.),
131      theDEDXTable(0),
132      CounterOfProcess(0),
133      RecorderOfProcess(0),
134      fdEdx(0),
135      fRangeNow(0),
136      linLossLimit(0.05),
137      theFluo(false)
138 {
139  
140  //create (only once) EnergyLoss messenger 
141  if(!eLossMessenger) eLossMessenger = new G4EnergyLossMessenger();
142 }
143 
144 //
145 
146 G4eLowEnergyLoss::~G4eLowEnergyLoss() 
147 {
148      if (theLossTable) 
149        {
150          theLossTable->clearAndDestroy();
151          delete theLossTable;
152        }
153 }
154 
155 void G4eLowEnergyLoss::SetNbOfProcesses(G4int nb) 
156 {
157     NbOfProcesses=nb;
158 }
159 
160 void G4eLowEnergyLoss::PlusNbOfProcesses()        
161 {
162     NbOfProcesses++;
163 }
164 
165 void G4eLowEnergyLoss::MinusNbOfProcesses() 
166 {
167     NbOfProcesses--;
168 }                                      
169 
170 G4int G4eLowEnergyLoss::GetNbOfProcesses() 
171 {
172     return NbOfProcesses;
173 }
174     
175 void G4eLowEnergyLoss::SetLowerBoundEloss(G4double val) 
176 {
177     LowerBoundEloss=val;
178 }
179     
180 void G4eLowEnergyLoss::SetUpperBoundEloss(G4double val) 
181 {
182     UpperBoundEloss=val;
183 } 
184 
185 void G4eLowEnergyLoss::SetNbinEloss(G4int nb)
186 {
187     NbinEloss=nb;
188 }
189  
190 G4double G4eLowEnergyLoss::GetLowerBoundEloss()
191 {
192     return LowerBoundEloss;
193 } 
194     
195 G4double G4eLowEnergyLoss::GetUpperBoundEloss() 
196 {
197     return UpperBoundEloss;
198 } 
199 
200 G4int G4eLowEnergyLoss::GetNbinEloss() 
201 {
202     return NbinEloss;
203 } 
204 //     
205 
206 void G4eLowEnergyLoss::BuildDEDXTable(
207                          const G4ParticleDefinition& aParticleType)
208 {
209   ParticleMass = aParticleType.GetPDGMass(); 
210   Charge = aParticleType.GetPDGCharge()/eplus;
211 
212   //  calculate data members LOGRTable,RTable first
213 
214   G4double lrate = std::log(UpperBoundEloss/LowerBoundEloss);
215   LOGRTable=lrate/NbinEloss;
216   RTable   =std::exp(LOGRTable);
217   // Build energy loss table as a sum of the energy loss due to the
218   // different processes.
219   //
220 
221   const G4ProductionCutsTable* theCoupleTable=
222         G4ProductionCutsTable::GetProductionCutsTable();
223   size_t numOfCouples = theCoupleTable->GetTableSize();
224 
225   // create table for the total energy loss
226 
227   if (&aParticleType==G4Electron::Electron())
228     {
229       RecorderOfProcess=RecorderOfElectronProcess;
230       CounterOfProcess=CounterOfElectronProcess;
231       if (CounterOfProcess == NbOfProcesses)
232         {
233          if (theDEDXElectronTable)
234            {
235              theDEDXElectronTable->clearAndDestroy();
236              delete theDEDXElectronTable;
237            }
238          theDEDXElectronTable = new G4PhysicsTable(numOfCouples);
239          theDEDXTable = theDEDXElectronTable;
240         }
241     }
242   if (&aParticleType==G4Positron::Positron())
243     {
244      RecorderOfProcess=RecorderOfPositronProcess;
245      CounterOfProcess=CounterOfPositronProcess;
246      if (CounterOfProcess == NbOfProcesses)
247        {
248         if (theDEDXPositronTable)
249           {
250             theDEDXPositronTable->clearAndDestroy();
251             delete theDEDXPositronTable;
252           }
253         theDEDXPositronTable = new G4PhysicsTable(numOfCouples);
254         theDEDXTable = theDEDXPositronTable;
255        }
256     }
257 
258   if (CounterOfProcess == NbOfProcesses)
259     {
260      // fill the tables
261      // loop for materials
262      G4double LowEdgeEnergy , Value;
263      G4bool isOutRange;
264      G4PhysicsTable* pointer;
265 
266      for (size_t J=0; J<numOfCouples; J++)
267         {
268          // create physics vector and fill it
269 
270          G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
271                     LowerBoundEloss, UpperBoundEloss, NbinEloss);
272 
273          // loop for the kinetic energy
274          for (G4int i=0; i<NbinEloss; i++)
275             {
276               LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
277               //here comes the sum of the different tables created by the
278               //processes (ionisation,bremsstrahlung,etc...)
279               Value = 0.;
280               for (G4int process=0; process < NbOfProcesses; process++)
281                  {
282                    pointer= RecorderOfProcess[process];
283                    Value += (*pointer)[J]->GetValue(LowEdgeEnergy,isOutRange);
284                  }
285 
286               aVector->PutValue(i,Value) ;
287             }
288 
289          theDEDXTable->insert(aVector) ;
290 
291         }
292 
293 
294      //reset counter to zero
295      if (&aParticleType==G4Electron::Electron()) CounterOfElectronProcess=0;
296      if (&aParticleType==G4Positron::Positron()) CounterOfPositronProcess=0;
297 
298      ParticleMass = aParticleType.GetPDGMass();
299 
300      if (&aParticleType==G4Electron::Electron())
301      {
302        // Build range table
303        theRangeElectronTable = BuildRangeTable(theDEDXElectronTable,
304                                                theRangeElectronTable,
305                               LowerBoundEloss,UpperBoundEloss,NbinEloss);
306 
307        // Build lab/proper time tables
308        theLabTimeElectronTable = BuildLabTimeTable(theDEDXElectronTable,
309                          theLabTimeElectronTable,
310                          LowerBoundEloss,UpperBoundEloss,NbinEloss);
311        theProperTimeElectronTable = BuildProperTimeTable(theDEDXElectronTable,
312                             theProperTimeElectronTable,
313                             LowerBoundEloss,UpperBoundEloss,NbinEloss);
314 
315        // Build coeff tables for the energy loss calculation
316        theeRangeCoeffATable = BuildRangeCoeffATable(theRangeElectronTable,
317                              theeRangeCoeffATable,
318                              LowerBoundEloss,UpperBoundEloss,NbinEloss);
319 
320        theeRangeCoeffBTable = BuildRangeCoeffBTable(theRangeElectronTable,
321                              theeRangeCoeffBTable,
322                              LowerBoundEloss,UpperBoundEloss,NbinEloss);
323 
324        theeRangeCoeffCTable = BuildRangeCoeffCTable(theRangeElectronTable,
325                              theeRangeCoeffCTable,
326                              LowerBoundEloss,UpperBoundEloss,NbinEloss);
327 
328        // invert the range table
329        theInverseRangeElectronTable = BuildInverseRangeTable(theRangeElectronTable,
330                               theeRangeCoeffATable,
331                               theeRangeCoeffBTable,
332                               theeRangeCoeffCTable,
333                               theInverseRangeElectronTable,
334                               LowerBoundEloss,UpperBoundEloss,NbinEloss);
335      }
336      if (&aParticleType==G4Positron::Positron())
337      {
338        // Build range table
339        theRangePositronTable = BuildRangeTable(theDEDXPositronTable,
340                                                theRangePositronTable,
341                               LowerBoundEloss,UpperBoundEloss,NbinEloss);
342 
343 
344        // Build lab/proper time tables
345        theLabTimePositronTable = BuildLabTimeTable(theDEDXPositronTable,
346                          theLabTimePositronTable,
347                          LowerBoundEloss,UpperBoundEloss,NbinEloss);
348        theProperTimePositronTable = BuildProperTimeTable(theDEDXPositronTable,
349                             theProperTimePositronTable,
350                             LowerBoundEloss,UpperBoundEloss,NbinEloss);
351 
352        // Build coeff tables for the energy loss calculation
353        thepRangeCoeffATable = BuildRangeCoeffATable(theRangePositronTable,
354                              thepRangeCoeffATable,
355                              LowerBoundEloss,UpperBoundEloss,NbinEloss);
356 
357        thepRangeCoeffBTable = BuildRangeCoeffBTable(theRangePositronTable,
358                              thepRangeCoeffBTable,
359                              LowerBoundEloss,UpperBoundEloss,NbinEloss);
360 
361        thepRangeCoeffCTable = BuildRangeCoeffCTable(theRangePositronTable,
362                              thepRangeCoeffCTable,
363                              LowerBoundEloss,UpperBoundEloss,NbinEloss);
364 
365        // invert the range table
366        theInverseRangePositronTable = BuildInverseRangeTable(theRangePositronTable,
367                               thepRangeCoeffATable,
368                               thepRangeCoeffBTable,
369                               thepRangeCoeffCTable,
370                               theInverseRangePositronTable,
371                               LowerBoundEloss,UpperBoundEloss,NbinEloss);
372      }
373 
374      if(verboseLevel > 1) {
375        G4cout << (*theDEDXElectronTable) << G4endl;
376      }
377 
378 
379      // make the energy loss and the range table available
380      G4EnergyLossTables::Register(&aParticleType,
381        (&aParticleType==G4Electron::Electron())?
382        theDEDXElectronTable: theDEDXPositronTable,
383        (&aParticleType==G4Electron::Electron())?
384        theRangeElectronTable: theRangePositronTable,
385        (&aParticleType==G4Electron::Electron())?
386        theInverseRangeElectronTable: theInverseRangePositronTable,
387        (&aParticleType==G4Electron::Electron())?
388        theLabTimeElectronTable: theLabTimePositronTable,
389        (&aParticleType==G4Electron::Electron())?
390        theProperTimeElectronTable: theProperTimePositronTable,
391        LowerBoundEloss, UpperBoundEloss, 1.,NbinEloss);
392     }
393 }
394 
395 //
396 
397 G4VParticleChange* G4eLowEnergyLoss::AlongStepDoIt( const G4Track& trackData,
398                                                  const G4Step&  stepData)
399 {
400  // compute the energy loss after a Step
401 
402   static const G4double faclow = 1.5 ;
403 
404   // get particle and material pointers from trackData
405   const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
406   G4double E      = aParticle->GetKineticEnergy();
407 
408   const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
409 
410   G4double Step = stepData.GetStepLength();
411 
412   aParticleChange.Initialize(trackData);
413   //fParticleChange.Initialize(trackData);
414 
415   G4double MeanLoss, finalT;
416 
417   if (E < MinKineticEnergy)   finalT = 0.;
418 
419   else if ( E< faclow*LowerBoundEloss)
420   {
421     if (Step >= fRangeNow)  finalT = 0.;
422    //  else finalT = E*(1.-Step/fRangeNow) ;
423     else finalT = E*(1.-std::sqrt(Step/fRangeNow)) ;
424   }
425 
426   else if (E>=UpperBoundEloss) finalT = E - Step*fdEdx;
427 
428   else if (Step >= fRangeNow)  finalT = 0.;
429 
430   else
431   {
432     if(Step/fRangeNow < linLossLimit) finalT = E-Step*fdEdx ;
433     else
434     {
435       if (Charge<0.) finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
436                              (G4Electron::Electron(),fRangeNow-Step,couple);
437       else           finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
438                              (G4Positron::Positron(),fRangeNow-Step,couple);
439      }
440   }
441 
442   if(finalT < MinKineticEnergy) finalT = 0. ;
443 
444   MeanLoss = E-finalT ;
445 
446   //now the loss with fluctuation
447   if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
448   {
449     finalT = E-GetLossWithFluct(aParticle,couple,MeanLoss,Step);
450     if (finalT < 0.) finalT = 0.;
451   }
452 
453   // kill the particle if the kinetic energy <= 0
454   if (finalT <= 0. )
455   {
456     finalT = 0.;
457     if(Charge > 0.0) aParticleChange.ProposeTrackStatus(fStopButAlive);
458     else             aParticleChange.ProposeTrackStatus(fStopAndKill);
459   }
460 
461   G4double edep = E - finalT;
462 
463   aParticleChange.ProposeEnergy(finalT);
464 
465   // Deexcitation of ionised atoms
466   std::vector<G4DynamicParticle*>* deexcitationProducts = 0;
467   if (theFluo) deexcitationProducts = DeexciteAtom(couple,E,edep);
468 
469   size_t nSecondaries = 0;
470   if (deexcitationProducts != 0) nSecondaries = deexcitationProducts->size();
471   aParticleChange.SetNumberOfSecondaries(nSecondaries);
472 
473   if (nSecondaries > 0) {
474 
475     const G4StepPoint* preStep = stepData.GetPreStepPoint();
476     const G4StepPoint* postStep = stepData.GetPostStepPoint();
477     G4ThreeVector r = preStep->GetPosition();
478     G4ThreeVector deltaR = postStep->GetPosition();
479     deltaR -= r;
480     G4double t = preStep->GetGlobalTime();
481     G4double deltaT = postStep->GetGlobalTime();
482     deltaT -= t;
483     G4double time, q;
484     G4ThreeVector position;
485 
486     for (size_t i=0; i<nSecondaries; i++) {
487 
488       G4DynamicParticle* part = (*deexcitationProducts)[i];
489       if (part != 0) {
490         G4double eSecondary = part->GetKineticEnergy();
491         edep -= eSecondary;
492   if (edep > 0.)
493     {
494       q = G4UniformRand();
495       time = deltaT*q + t;
496       position  = deltaR*q;
497       position += r;
498       G4Track* newTrack = new G4Track(part, time, position);
499       aParticleChange.AddSecondary(newTrack);
500     }
501   else
502     {
503       edep += eSecondary;
504       delete part;
505       part = 0;
506     }
507       }
508     }
509   }
510   delete deexcitationProducts;
511 
512   aParticleChange.ProposeLocalEnergyDeposit(edep);
513 
514   return &aParticleChange;
515 }
516 
517 //
518 
519