Geant4  10.03.p01
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4hRDEnergyLoss.cc
Go to the documentation of this file.
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 // $Id: G4hRDEnergyLoss.cc 70904 2013-06-07 10:34:25Z gcosmo $
28 //
29 // -----------------------------------------------------------
30 // GEANT 4 class implementation file
31 //
32 // History: based on object model of
33 // 2nd December 1995, G.Cosmo
34 // ---------- G4hEnergyLoss physics process -----------
35 // by Laszlo Urban, 30 May 1997
36 //
37 // **************************************************************
38 // It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
39 // It calculates the energy loss of charged hadrons.
40 // **************************************************************
41 //
42 // 7/10/98 bug fixes + some cleanup , L.Urban
43 // 22/10/98 cleanup , L.Urban
44 // 07/12/98 works for ions as well+ bug corrected, L.Urban
45 // 02/02/99 several bugs fixed, L.Urban
46 // 31/03/00 rename to lowenergy as G4hRDEnergyLoss.cc V.Ivanchenko
47 // 05/11/00 new method to calculate particle ranges
48 // 10/05/01 V.Ivanchenko Clean up againist Linux compilation with -Wall
49 // 23/11/01 V.Ivanchenko Move static member-functions from header to source
50 // 28/10/02 V.Ivanchenko Optimal binning for dE/dx
51 // 21/01/03 V.Ivanchenko Cut per region
52 // 23/01/03 V.Ivanchenko Fix in table build
53 
54 // 31 Jul 2008 MGP Short term supply of energy loss of hadrons through clone of
55 // former G4hLowEnergyLoss (with some initial cleaning)
56 // To be replaced by reworked class to deal with condensed/discrete
57 // issues properly
58 
59 // 25 Nov 2010 MGP Added some protections for FPE (mostly division by 0)
60 // The whole energy loss domain would profit from a design iteration
61 
62 // 20 Jun 2011 MGP Corrected some compilation warnings. The whole class will be heavily refactored anyway.
63 
64 // --------------------------------------------------------------
65 
66 #include "G4hRDEnergyLoss.hh"
67 #include "G4PhysicalConstants.hh"
68 #include "G4SystemOfUnits.hh"
69 #include "G4EnergyLossTables.hh"
70 #include "G4Poisson.hh"
71 #include "G4ProductionCutsTable.hh"
72 
73 
74 // Initialisation of static members ******************************************
75 // contributing processes : ion.loss ->NumberOfProcesses is initialized
76 // to 1 . YOU DO NOT HAVE TO CHANGE this variable for a 'normal' run.
77 // You have to change NumberOfProcesses
78 // if you invent a new process contributing to the cont. energy loss,
79 // NumberOfProcesses should be 2 in this case,
80 // or for debugging purposes.
81 // The NumberOfProcesses data member can be changed using the (public static)
82 // functions Get/Set/Plus/MinusNumberOfProcesses (see G4hRDEnergyLoss.hh)
83 
84 
85 // The following vectors have a fixed dimension this means that if they are
86 // filled in with more than 100 elements will corrupt the memory.
87 G4ThreadLocal G4int G4hRDEnergyLoss::NumberOfProcesses = 1 ;
88 
89 G4ThreadLocal G4int G4hRDEnergyLoss::CounterOfProcess = 0 ;
90 G4ThreadLocal G4PhysicsTable** G4hRDEnergyLoss::RecorderOfProcess = 0 ;
91 
94 
97 
108 
109 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::thepRangeCoeffATable = 0 ;
110 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::thepRangeCoeffBTable = 0 ;
111 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::thepRangeCoeffCTable = 0 ;
112 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::thepbarRangeCoeffATable = 0 ;
113 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::thepbarRangeCoeffBTable = 0 ;
114 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::thepbarRangeCoeffCTable = 0 ;
115 
116 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theDEDXTable = 0 ;
117 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theRangeTable = 0 ;
118 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theInverseRangeTable = 0 ;
119 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theLabTimeTable = 0 ;
120 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theProperTimeTable = 0 ;
121 
122 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theRangeCoeffATable = 0 ;
123 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theRangeCoeffBTable = 0 ;
124 G4ThreadLocal G4PhysicsTable* G4hRDEnergyLoss::theRangeCoeffCTable = 0 ;
125 
126 //const G4Proton* G4hRDEnergyLoss::theProton=G4Proton::Proton() ;
127 //const G4AntiProton* G4hRDEnergyLoss::theAntiProton=G4AntiProton::AntiProton() ;
128 
132 
133 G4ThreadLocal G4double G4hRDEnergyLoss::Mass,
134  G4hRDEnergyLoss::taulow,
135  G4hRDEnergyLoss::tauhigh,
136  G4hRDEnergyLoss::ltaulow,
137  G4hRDEnergyLoss::ltauhigh;
138 
140 G4ThreadLocal G4double G4hRDEnergyLoss::finalRange = 0.2; // 200.*micrometer
141 
144  // 2.*(1.-(0.20))*(200.*micrometer)
146  // -(1.-(0.20))*(200.*micrometer)*(200.*micrometer)
147 
149 
152 
157 
158 //--------------------------------------------------------------------------------
159 
160 // constructor and destructor
161 
163  : G4VContinuousDiscreteProcess (processName),
164  MaxExcitationNumber (1.e6),
165  probLimFluct (0.01),
166  nmaxDirectFluct (100),
167  nmaxCont1(4),
168  nmaxCont2(16),
169  theLossTable(0),
170  linLossLimit(0.05),
171  MinKineticEnergy(0.0)
172 {
175  if (!RecorderOfProcess) RecorderOfProcess = new G4PhysicsTable*[100];
176 }
177 
178 //--------------------------------------------------------------------------------
179 
181 {
182  if(theLossTable)
183  {
185  delete theLossTable;
186  }
187 }
188 
189 //--------------------------------------------------------------------------------
190 
192 {
193  return NumberOfProcesses;
194 }
195 
196 //--------------------------------------------------------------------------------
197 
199 {
200  NumberOfProcesses=number;
201 }
202 
203 //--------------------------------------------------------------------------------
204 
206 {
207  NumberOfProcesses++;
208 }
209 
210 //--------------------------------------------------------------------------------
211 
213 {
214  NumberOfProcesses--;
215 }
216 
217 //--------------------------------------------------------------------------------
218 
220 {
221  dRoverRange = value;
222 }
223 
224 //--------------------------------------------------------------------------------
225 
227 {
229 }
230 
231 //--------------------------------------------------------------------------------
232 
234 {
236 }
237 
238 //--------------------------------------------------------------------------------
239 
241 {
242  dRoverRange = c1;
243  finalRange = c2;
247 }
248 
249 //--------------------------------------------------------------------------------
250 
252 {
253  // calculate data members TotBin,LOGRTable,RTable first
254 
257  if (!RecorderOfProcess) RecorderOfProcess = new G4PhysicsTable*[100];
258 
259  const G4ProductionCutsTable* theCoupleTable=
261  size_t numOfCouples = theCoupleTable->GetTableSize();
262 
263  // create/fill proton or antiproton tables depending on the charge
264  Charge = aParticleType.GetPDGCharge()/eplus;
265  ParticleMass = aParticleType.GetPDGMass() ;
266 
267  if (Charge>0.) {theDEDXTable= theDEDXpTable;}
268  else {theDEDXTable= theDEDXpbarTable;}
269 
270  if( ((Charge>0.) && (theDEDXTable==0)) ||
271  ((Charge<0.) && (theDEDXTable==0))
272  )
273  {
274 
275  // Build energy loss table as a sum of the energy loss due to the
276  // different processes.
277  if( Charge >0.)
278  {
279  RecorderOfProcess=RecorderOfpProcess;
280  CounterOfProcess=CounterOfpProcess;
281 
282  if(CounterOfProcess == NumberOfProcesses)
283  {
284  if(theDEDXpTable)
286  delete theDEDXpTable; }
287  theDEDXpTable = new G4PhysicsTable(numOfCouples);
288  theDEDXTable = theDEDXpTable;
289  }
290  }
291  else
292  {
293  RecorderOfProcess=RecorderOfpbarProcess;
294  CounterOfProcess=CounterOfpbarProcess;
295 
296  if(CounterOfProcess == NumberOfProcesses)
297  {
298  if(theDEDXpbarTable)
300  delete theDEDXpbarTable; }
301  theDEDXpbarTable = new G4PhysicsTable(numOfCouples);
302  theDEDXTable = theDEDXpbarTable;
303  }
304  }
305 
306  if(CounterOfProcess == NumberOfProcesses)
307  {
308  // loop for materials
309  G4double LowEdgeEnergy , Value ;
310  G4bool isOutRange ;
311  G4PhysicsTable* pointer ;
312 
313  for (size_t J=0; J<numOfCouples; J++)
314  {
315  // create physics vector and fill it
316  G4PhysicsLogVector* aVector =
319 
320  // loop for the kinetic energy
321  for (G4int i=0; i<TotBin; i++)
322  {
323  LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
324  Value = 0. ;
325 
326  // loop for the contributing processes
327  for (G4int process=0; process < NumberOfProcesses; process++)
328  {
329  pointer= RecorderOfProcess[process];
330  Value += (*pointer)[J]->
331  GetValue(LowEdgeEnergy,isOutRange) ;
332  }
333 
334  aVector->PutValue(i,Value) ;
335  }
336 
337  theDEDXTable->insert(aVector) ;
338  }
339 
340  // reset counter to zero ..................
341  if( Charge >0.)
343  else
345 
346  // Build range table
347  BuildRangeTable( aParticleType);
348 
349  // Build lab/proper time tables
350  BuildTimeTables( aParticleType) ;
351 
352  // Build coeff tables for the energy loss calculation
353  BuildRangeCoeffATable( aParticleType);
354  BuildRangeCoeffBTable( aParticleType);
355  BuildRangeCoeffCTable( aParticleType);
356 
357  // invert the range table
358 
359  BuildInverseRangeTable(aParticleType);
360  }
361  }
362  // make the energy loss and the range table available
363 
364  G4EnergyLossTables::Register(&aParticleType,
365  (Charge>0)?
367  (Charge>0)?
369  (Charge>0)?
371  (Charge>0)?
373  (Charge>0)?
376  proton_mass_c2/aParticleType.GetPDGMass(),
377  TotBin);
378 
379 }
380 
381 //--------------------------------------------------------------------------------
382 
383 void G4hRDEnergyLoss::BuildRangeTable(const G4ParticleDefinition& aParticleType)
384 {
385  // Build range table from the energy loss table
386 
387  Mass = aParticleType.GetPDGMass();
388 
389  const G4ProductionCutsTable* theCoupleTable=
391  size_t numOfCouples = theCoupleTable->GetTableSize();
392 
393  if( Charge >0.)
394  {
395  if(theRangepTable)
397  delete theRangepTable; }
398  theRangepTable = new G4PhysicsTable(numOfCouples);
399  theRangeTable = theRangepTable ;
400  }
401  else
402  {
405  delete theRangepbarTable; }
406  theRangepbarTable = new G4PhysicsTable(numOfCouples);
407  theRangeTable = theRangepbarTable ;
408  }
409 
410  // loop for materials
411 
412  for (size_t J=0; J<numOfCouples; J++)
413  {
414  G4PhysicsLogVector* aVector;
417 
418  BuildRangeVector(J, aVector);
419  theRangeTable->insert(aVector);
420  }
421 }
422 
423 //--------------------------------------------------------------------------------
424 
425 void G4hRDEnergyLoss::BuildTimeTables(const G4ParticleDefinition& aParticleType)
426 {
427  const G4ProductionCutsTable* theCoupleTable=
429  size_t numOfCouples = theCoupleTable->GetTableSize();
430 
431  if(&aParticleType == G4Proton::Proton())
432  {
433  if(theLabTimepTable)
435  delete theLabTimepTable; }
436  theLabTimepTable = new G4PhysicsTable(numOfCouples);
437  theLabTimeTable = theLabTimepTable ;
438 
441  delete theProperTimepTable; }
442  theProperTimepTable = new G4PhysicsTable(numOfCouples);
443  theProperTimeTable = theProperTimepTable ;
444  }
445 
446  if(&aParticleType == G4AntiProton::AntiProton())
447  {
450  delete theLabTimepbarTable; }
451  theLabTimepbarTable = new G4PhysicsTable(numOfCouples);
452  theLabTimeTable = theLabTimepbarTable ;
453 
456  delete theProperTimepbarTable; }
457  theProperTimepbarTable = new G4PhysicsTable(numOfCouples);
458  theProperTimeTable = theProperTimepbarTable ;
459  }
460 
461  for (size_t J=0; J<numOfCouples; J++)
462  {
463  G4PhysicsLogVector* aVector;
464  G4PhysicsLogVector* bVector;
465 
468 
469  BuildLabTimeVector(J, aVector);
470  theLabTimeTable->insert(aVector);
471 
474 
475  BuildProperTimeVector(J, bVector);
476  theProperTimeTable->insert(bVector);
477  }
478 }
479 
480 //--------------------------------------------------------------------------------
481 
482 void G4hRDEnergyLoss::BuildRangeVector(G4int materialIndex,
483  G4PhysicsLogVector* rangeVector)
484 {
485  // create range vector for a material
486 
487  G4bool isOut;
488  G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
489  G4double energy1 = rangeVector->GetLowEdgeEnergy(0);
490  G4double dedx = physicsVector->GetValue(energy1,isOut);
491  G4double range = 0.5*energy1/dedx;
492  rangeVector->PutValue(0,range);
493  G4int n = 100;
494  G4double del = 1.0/(G4double)n ;
495 
496  for (G4int j=1; j<TotBin; j++) {
497 
498  G4double energy2 = rangeVector->GetLowEdgeEnergy(j);
499  G4double de = (energy2 - energy1) * del ;
500  G4double dedx1 = dedx ;
501 
502  for (G4int i=1; i<n; i++) {
503  G4double energy = energy1 + i*de ;
504  G4double dedx2 = physicsVector->GetValue(energy,isOut);
505  range += 0.5*de*(1.0/dedx1 + 1.0/dedx2);
506  dedx1 = dedx2;
507  }
508  rangeVector->PutValue(j,range);
509  dedx = dedx1 ;
510  energy1 = energy2 ;
511  }
512 }
513 
514 //--------------------------------------------------------------------------------
515 
516 void G4hRDEnergyLoss::BuildLabTimeVector(G4int materialIndex,
517  G4PhysicsLogVector* timeVector)
518 {
519  // create lab time vector for a material
520 
521  G4int nbin=100;
522  G4bool isOut;
523  G4double tlim=5.*keV,parlowen=0.4,ppar=0.5-parlowen ;
524  //G4double losslim,clim,taulim,timelim,ltaulim,ltaumax,
525  G4double losslim,clim,taulim,timelim,
526  LowEdgeEnergy,tau,Value ;
527 
528  G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
529 
530  // low energy part first...
531  losslim = physicsVector->GetValue(tlim,isOut);
532  taulim=tlim/ParticleMass ;
533  clim=std::sqrt(ParticleMass*tlim/2.)/(c_light*losslim*ppar) ;
534  //ltaulim = std::log(taulim);
535  //ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
536 
537  G4int i=-1;
538  G4double oldValue = 0. ;
539  G4double tauold ;
540  do
541  {
542  i += 1 ;
543  LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
544  tau = LowEdgeEnergy/ParticleMass ;
545  if ( tau <= taulim )
546  {
547  Value = clim*std::exp(ppar*std::log(tau/taulim)) ;
548  }
549  else
550  {
551  timelim=clim ;
552  ltaulow = std::log(taulim);
553  ltauhigh = std::log(tau);
554  Value = timelim+LabTimeIntLog(physicsVector,nbin);
555  }
556  timeVector->PutValue(i,Value);
557  oldValue = Value ;
558  tauold = tau ;
559  } while (tau<=taulim) ;
560 
561  i += 1 ;
562  for (G4int j=i; j<TotBin; j++)
563  {
564  LowEdgeEnergy = timeVector->GetLowEdgeEnergy(j);
565  tau = LowEdgeEnergy/ParticleMass ;
566  ltaulow = std::log(tauold);
567  ltauhigh = std::log(tau);
568  Value = oldValue+LabTimeIntLog(physicsVector,nbin);
569  timeVector->PutValue(j,Value);
570  oldValue = Value ;
571  tauold = tau ;
572  }
573 }
574 
575 //--------------------------------------------------------------------------------
576 
577 void G4hRDEnergyLoss::BuildProperTimeVector(G4int materialIndex,
578  G4PhysicsLogVector* timeVector)
579 {
580  // create proper time vector for a material
581 
582  G4int nbin=100;
583  G4bool isOut;
584  G4double tlim=5.*keV,parlowen=0.4,ppar=0.5-parlowen ;
585  //G4double losslim,clim,taulim,timelim,ltaulim,ltaumax,
586  G4double losslim,clim,taulim,timelim,
587  LowEdgeEnergy,tau,Value ;
588 
589  G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
590 
591  // low energy part first...
592  losslim = physicsVector->GetValue(tlim,isOut);
593  taulim=tlim/ParticleMass ;
594  clim=std::sqrt(ParticleMass*tlim/2.)/(c_light*losslim*ppar) ;
595  //ltaulim = std::log(taulim);
596  //ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
597 
598  G4int i=-1;
599  G4double oldValue = 0. ;
600  G4double tauold ;
601  do
602  {
603  i += 1 ;
604  LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
605  tau = LowEdgeEnergy/ParticleMass ;
606  if ( tau <= taulim )
607  {
608  Value = clim*std::exp(ppar*std::log(tau/taulim)) ;
609  }
610  else
611  {
612  timelim=clim ;
613  ltaulow = std::log(taulim);
614  ltauhigh = std::log(tau);
615  Value = timelim+ProperTimeIntLog(physicsVector,nbin);
616  }
617  timeVector->PutValue(i,Value);
618  oldValue = Value ;
619  tauold = tau ;
620  } while (tau<=taulim) ;
621 
622  i += 1 ;
623  for (G4int j=i; j<TotBin; j++)
624  {
625  LowEdgeEnergy = timeVector->GetLowEdgeEnergy(j);
626  tau = LowEdgeEnergy/ParticleMass ;
627  ltaulow = std::log(tauold);
628  ltauhigh = std::log(tau);
629  Value = oldValue+ProperTimeIntLog(physicsVector,nbin);
630  timeVector->PutValue(j,Value);
631  oldValue = Value ;
632  tauold = tau ;
633  }
634 }
635 
636 //--------------------------------------------------------------------------------
637 
638 G4double G4hRDEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
639  G4int nbin)
640 {
641  // num. integration, linear binning
642 
643  G4double dtau,Value,taui,ti,lossi,ci;
644  G4bool isOut;
645  dtau = (tauhigh-taulow)/nbin;
646  Value = 0.;
647 
648  for (G4int i=0; i<=nbin; i++)
649  {
650  taui = taulow + dtau*i ;
651  ti = Mass*taui;
652  lossi = physicsVector->GetValue(ti,isOut);
653  if(i==0)
654  ci=0.5;
655  else
656  {
657  if(i<nbin)
658  ci=1.;
659  else
660  ci=0.5;
661  }
662  Value += ci/lossi;
663  }
664  Value *= Mass*dtau;
665  return Value;
666 }
667 
668 //--------------------------------------------------------------------------------
669 
670 G4double G4hRDEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
671  G4int nbin)
672 {
673  // num. integration, logarithmic binning
674 
675  G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
676  G4bool isOut;
677  ltt = ltauhigh-ltaulow;
678  dltau = ltt/nbin;
679  Value = 0.;
680 
681  for (G4int i=0; i<=nbin; i++)
682  {
683  ui = ltaulow+dltau*i;
684  taui = std::exp(ui);
685  ti = Mass*taui;
686  lossi = physicsVector->GetValue(ti,isOut);
687  if(i==0)
688  ci=0.5;
689  else
690  {
691  if(i<nbin)
692  ci=1.;
693  else
694  ci=0.5;
695  }
696  Value += ci*taui/lossi;
697  }
698  Value *= Mass*dltau;
699  return Value;
700 }
701 
702 //--------------------------------------------------------------------------------
703 
704 G4double G4hRDEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
705  G4int nbin)
706 {
707  // num. integration, logarithmic binning
708 
709  G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
710  G4bool isOut;
711  ltt = ltauhigh-ltaulow;
712  dltau = ltt/nbin;
713  Value = 0.;
714 
715  for (G4int i=0; i<=nbin; i++)
716  {
717  ui = ltaulow+dltau*i;
718  taui = std::exp(ui);
719  ti = ParticleMass*taui;
720  lossi = physicsVector->GetValue(ti,isOut);
721  if(i==0)
722  ci=0.5;
723  else
724  {
725  if(i<nbin)
726  ci=1.;
727  else
728  ci=0.5;
729  }
730  Value += ci*taui*(ti+ParticleMass)/(std::sqrt(ti*(ti+2.*ParticleMass))*lossi);
731  }
732  Value *= ParticleMass*dltau/c_light;
733  return Value;
734 }
735 
736 //--------------------------------------------------------------------------------
737 
738 G4double G4hRDEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
739  G4int nbin)
740 {
741  // num. integration, logarithmic binning
742 
743  G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
744  G4bool isOut;
745  ltt = ltauhigh-ltaulow;
746  dltau = ltt/nbin;
747  Value = 0.;
748 
749  for (G4int i=0; i<=nbin; i++)
750  {
751  ui = ltaulow+dltau*i;
752  taui = std::exp(ui);
753  ti = ParticleMass*taui;
754  lossi = physicsVector->GetValue(ti,isOut);
755  if(i==0)
756  ci=0.5;
757  else
758  {
759  if(i<nbin)
760  ci=1.;
761  else
762  ci=0.5;
763  }
764  Value += ci*taui*ParticleMass/(std::sqrt(ti*(ti+2.*ParticleMass))*lossi);
765  }
766  Value *= ParticleMass*dltau/c_light;
767  return Value;
768 }
769 
770 //--------------------------------------------------------------------------------
771 
772 void G4hRDEnergyLoss::BuildRangeCoeffATable( const G4ParticleDefinition& )
773 {
774  // Build tables of coefficients for the energy loss calculation
775  // create table for coefficients "A"
776 
778 
779  if(Charge>0.)
780  {
781  if(thepRangeCoeffATable)
782  { thepRangeCoeffATable->clearAndDestroy();
783  delete thepRangeCoeffATable; }
784  thepRangeCoeffATable = new G4PhysicsTable(numOfCouples);
785  theRangeCoeffATable = thepRangeCoeffATable ;
786  theRangeTable = theRangepTable ;
787  }
788  else
789  {
790  if(thepbarRangeCoeffATable)
791  { thepbarRangeCoeffATable->clearAndDestroy();
792  delete thepbarRangeCoeffATable; }
793  thepbarRangeCoeffATable = new G4PhysicsTable(numOfCouples);
794  theRangeCoeffATable = thepbarRangeCoeffATable ;
795  theRangeTable = theRangepbarTable ;
796  }
797 
798  G4double R2 = RTable*RTable ;
799  G4double R1 = RTable+1.;
800  G4double w = R1*(RTable-1.)*(RTable-1.);
801  G4double w1 = RTable/w , w2 = -RTable*R1/w , w3 = R2/w ;
802  G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
803  G4bool isOut;
804 
805  // loop for materials
806  for (G4int J=0; J<numOfCouples; J++)
807  {
808  G4int binmax=TotBin ;
809  G4PhysicsLinearVector* aVector =
810  new G4PhysicsLinearVector(0.,binmax, TotBin);
811  Ti = LowestKineticEnergy ;
812  if (Ti < DBL_MIN) Ti = 1.e-8;
813  G4PhysicsVector* rangeVector= (*theRangeTable)[J];
814 
815  for ( G4int i=0; i<TotBin; i++)
816  {
817  Ri = rangeVector->GetValue(Ti,isOut) ;
818  if (Ti < DBL_MIN) Ti = 1.e-8;
819  if ( i==0 )
820  Rim = 0. ;
821  else
822  {
823  // ---- MGP ---- Modified to avoid a floating point exception
824  // The correction is just a temporary patch, the whole class should be redesigned
825  // Original: Tim = Ti/RTable results in 0./0.
826  if (RTable != 0.)
827  {
828  Tim = Ti/RTable ;
829  }
830  else
831  {
832  Tim = 0.;
833  }
834  Rim = rangeVector->GetValue(Tim,isOut);
835  }
836  if ( i==(TotBin-1))
837  Rip = Ri ;
838  else
839  {
840  Tip = Ti*RTable ;
841  Rip = rangeVector->GetValue(Tip,isOut);
842  }
843  Value = (w1*Rip + w2*Ri + w3*Rim)/(Ti*Ti) ;
844 
845  aVector->PutValue(i,Value);
846  Ti = RTable*Ti ;
847  }
848 
849  theRangeCoeffATable->insert(aVector);
850  }
851 }
852 
853 //--------------------------------------------------------------------------------
854 
855 void G4hRDEnergyLoss::BuildRangeCoeffBTable( const G4ParticleDefinition& )
856 {
857  // Build tables of coefficients for the energy loss calculation
858  // create table for coefficients "B"
859 
860  G4int numOfCouples =
862 
863  if(Charge>0.)
864  {
865  if(thepRangeCoeffBTable)
866  { thepRangeCoeffBTable->clearAndDestroy();
867  delete thepRangeCoeffBTable; }
868  thepRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
869  theRangeCoeffBTable = thepRangeCoeffBTable ;
870  theRangeTable = theRangepTable ;
871  }
872  else
873  {
874  if(thepbarRangeCoeffBTable)
875  { thepbarRangeCoeffBTable->clearAndDestroy();
876  delete thepbarRangeCoeffBTable; }
877  thepbarRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
878  theRangeCoeffBTable = thepbarRangeCoeffBTable ;
879  theRangeTable = theRangepbarTable ;
880  }
881 
882  G4double R2 = RTable*RTable ;
883  G4double R1 = RTable+1.;
884  G4double w = R1*(RTable-1.)*(RTable-1.);
885  if (w < DBL_MIN) w = DBL_MIN;
886  G4double w1 = -R1/w , w2 = R1*(R2+1.)/w , w3 = -R2*R1/w ;
887  G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
888  G4bool isOut;
889 
890  // loop for materials
891  for (G4int J=0; J<numOfCouples; J++)
892  {
893  G4int binmax=TotBin ;
894  G4PhysicsLinearVector* aVector =
895  new G4PhysicsLinearVector(0.,binmax, TotBin);
896  Ti = LowestKineticEnergy ;
897  if (Ti < DBL_MIN) Ti = 1.e-8;
898  G4PhysicsVector* rangeVector= (*theRangeTable)[J];
899 
900  for ( G4int i=0; i<TotBin; i++)
901  {
902  Ri = rangeVector->GetValue(Ti,isOut) ;
903  if (Ti < DBL_MIN) Ti = 1.e-8;
904  if ( i==0 )
905  Rim = 0. ;
906  else
907  {
908  if (RTable < DBL_MIN) RTable = DBL_MIN;
909  Tim = Ti/RTable ;
910  Rim = rangeVector->GetValue(Tim,isOut);
911  }
912  if ( i==(TotBin-1))
913  Rip = Ri ;
914  else
915  {
916  Tip = Ti*RTable ;
917  Rip = rangeVector->GetValue(Tip,isOut);
918  }
919  if (Ti < DBL_MIN) Ti = DBL_MIN;
920  Value = (w1*Rip + w2*Ri + w3*Rim)/Ti;
921 
922  aVector->PutValue(i,Value);
923  Ti = RTable*Ti ;
924  }
925  theRangeCoeffBTable->insert(aVector);
926  }
927 }
928 
929 //--------------------------------------------------------------------------------
930 
931 void G4hRDEnergyLoss::BuildRangeCoeffCTable( const G4ParticleDefinition& )
932 {
933  // Build tables of coefficients for the energy loss calculation
934  // create table for coefficients "C"
935 
936  G4int numOfCouples =
938 
939  if(Charge>0.)
940  {
941  if(thepRangeCoeffCTable)
942  { thepRangeCoeffCTable->clearAndDestroy();
943  delete thepRangeCoeffCTable; }
944  thepRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
945  theRangeCoeffCTable = thepRangeCoeffCTable ;
946  theRangeTable = theRangepTable ;
947  }
948  else
949  {
950  if(thepbarRangeCoeffCTable)
951  { thepbarRangeCoeffCTable->clearAndDestroy();
952  delete thepbarRangeCoeffCTable; }
953  thepbarRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
954  theRangeCoeffCTable = thepbarRangeCoeffCTable ;
955  theRangeTable = theRangepbarTable ;
956  }
957 
958  G4double R2 = RTable*RTable ;
959  G4double R1 = RTable+1.;
960  G4double w = R1*(RTable-1.)*(RTable-1.);
961  G4double w1 = 1./w , w2 = -RTable*R1/w , w3 = RTable*R2/w ;
962  G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
963  G4bool isOut;
964 
965  // loop for materials
966  for (G4int J=0; J<numOfCouples; J++)
967  {
968  G4int binmax=TotBin ;
969  G4PhysicsLinearVector* aVector =
970  new G4PhysicsLinearVector(0.,binmax, TotBin);
971  Ti = LowestKineticEnergy ;
972  G4PhysicsVector* rangeVector= (*theRangeTable)[J];
973 
974  for ( G4int i=0; i<TotBin; i++)
975  {
976  Ri = rangeVector->GetValue(Ti,isOut) ;
977  if ( i==0 )
978  Rim = 0. ;
979  else
980  {
981  Tim = Ti/RTable ;
982  Rim = rangeVector->GetValue(Tim,isOut);
983  }
984  if ( i==(TotBin-1))
985  Rip = Ri ;
986  else
987  {
988  Tip = Ti*RTable ;
989  Rip = rangeVector->GetValue(Tip,isOut);
990  }
991  Value = w1*Rip + w2*Ri + w3*Rim ;
992 
993  aVector->PutValue(i,Value);
994  Ti = RTable*Ti ;
995  }
996  theRangeCoeffCTable->insert(aVector);
997  }
998 }
999 
1000 //--------------------------------------------------------------------------------
1001 
1002 void G4hRDEnergyLoss::
1003 BuildInverseRangeTable(const G4ParticleDefinition& aParticleType)
1004 {
1005  // Build inverse table of the range table
1006 
1007  G4bool b;
1008 
1009  const G4ProductionCutsTable* theCoupleTable=
1011  size_t numOfCouples = theCoupleTable->GetTableSize();
1012 
1013  if(&aParticleType == G4Proton::Proton())
1014  {
1017  delete theInverseRangepTable; }
1018  theInverseRangepTable = new G4PhysicsTable(numOfCouples);
1019  theInverseRangeTable = theInverseRangepTable ;
1020  theRangeTable = theRangepTable ;
1021  theDEDXTable = theDEDXpTable ;
1022  theRangeCoeffATable = thepRangeCoeffATable ;
1023  theRangeCoeffBTable = thepRangeCoeffBTable ;
1024  theRangeCoeffCTable = thepRangeCoeffCTable ;
1025  }
1026 
1027  if(&aParticleType == G4AntiProton::AntiProton())
1028  {
1031  delete theInverseRangepbarTable; }
1032  theInverseRangepbarTable = new G4PhysicsTable(numOfCouples);
1033  theInverseRangeTable = theInverseRangepbarTable ;
1034  theRangeTable = theRangepbarTable ;
1035  theDEDXTable = theDEDXpbarTable ;
1036  theRangeCoeffATable = thepbarRangeCoeffATable ;
1037  theRangeCoeffBTable = thepbarRangeCoeffBTable ;
1038  theRangeCoeffCTable = thepbarRangeCoeffCTable ;
1039  }
1040 
1041  // loop for materials
1042  for (size_t i=0; i<numOfCouples; i++)
1043  {
1044 
1045  G4PhysicsVector* pv = (*theRangeTable)[i];
1046  size_t nbins = pv->GetVectorLength();
1047  G4double elow = pv->GetLowEdgeEnergy(0);
1048  G4double ehigh = pv->GetLowEdgeEnergy(nbins-1);
1049  G4double rlow = pv->GetValue(elow, b);
1050  G4double rhigh = pv->GetValue(ehigh, b);
1051 
1052  if (rlow <DBL_MIN) rlow = 1.e-8;
1053  if (rhigh > 1.e16) rhigh = 1.e16;
1054  if (rhigh < 1.e-8) rhigh =1.e-8;
1055  G4double tmpTrick = rhigh/rlow;
1056 
1057  //std::cout << nbins << ", elow " << elow << ", ehigh " << ehigh
1058  // << ", rlow " << rlow << ", rhigh " << rhigh
1059  // << ", trick " << tmpTrick << std::endl;
1060 
1061  if (tmpTrick <= 0. || tmpTrick < DBL_MIN) tmpTrick = 1.e-8;
1062  if (tmpTrick > 1.e16) tmpTrick = 1.e16;
1063 
1064  rhigh *= std::exp(std::log(tmpTrick)/((G4double)(nbins-1)));
1065 
1066  G4PhysicsLogVector* v = new G4PhysicsLogVector(rlow, rhigh, nbins);
1067 
1068  v->PutValue(0,elow);
1069  G4double energy1 = elow;
1070  G4double range1 = rlow;
1071  G4double energy2 = elow;
1072  G4double range2 = rlow;
1073  size_t ilow = 0;
1074  size_t ihigh;
1075 
1076  for (size_t j=1; j<nbins; j++) {
1077 
1078  G4double range = v->GetLowEdgeEnergy(j);
1079 
1080  for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
1081  energy2 = pv->GetLowEdgeEnergy(ihigh);
1082  range2 = pv->GetValue(energy2, b);
1083  if(range2 >= range || ihigh == nbins-1) {
1084  ilow = ihigh - 1;
1085  energy1 = pv->GetLowEdgeEnergy(ilow);
1086  range1 = pv->GetValue(energy1, b);
1087  break;
1088  }
1089  }
1090 
1091  G4double e = std::log(energy1) + std::log(energy2/energy1)*std::log(range/range1)/std::log(range2/range1);
1092 
1093  v->PutValue(j,std::exp(e));
1094  }
1095  theInverseRangeTable->insert(v);
1096 
1097  }
1098 }
1099 
1100 //--------------------------------------------------------------------------------
1101 
1102 void G4hRDEnergyLoss::InvertRangeVector(G4int materialIndex,
1103  G4PhysicsLogVector* aVector)
1104 {
1105  // invert range vector for a material
1106 
1107  G4double LowEdgeRange,A,B,C,discr,KineticEnergy ;
1109  G4double rangebin = 0.0 ;
1110  G4int binnumber = -1 ;
1111  G4bool isOut ;
1112 
1113 
1114  //loop for range values
1115  for( G4int i=0; i<TotBin; i++)
1116  {
1117  LowEdgeRange = aVector->GetLowEdgeEnergy(i) ; //i.e. GetLowEdgeValue(i)
1118 
1119  if( rangebin < LowEdgeRange )
1120  {
1121  do
1122  {
1123  binnumber += 1 ;
1124  Tbin *= RTable ;
1125  rangebin = (*theRangeTable)(materialIndex)->GetValue(Tbin,isOut) ;
1126  }
1127  while ((rangebin < LowEdgeRange) && (binnumber < TotBin )) ;
1128  }
1129 
1130  if(binnumber == 0)
1131  KineticEnergy = LowestKineticEnergy ;
1132  else if(binnumber == TotBin-1)
1133  KineticEnergy = HighestKineticEnergy ;
1134  else
1135  {
1136  A = (*(*theRangeCoeffATable)(materialIndex))(binnumber-1) ;
1137  B = (*(*theRangeCoeffBTable)(materialIndex))(binnumber-1) ;
1138  C = (*(*theRangeCoeffCTable)(materialIndex))(binnumber-1) ;
1139  if(A==0.)
1140  KineticEnergy = (LowEdgeRange -C )/B ;
1141  else
1142  {
1143  discr = B*B - 4.*A*(C-LowEdgeRange);
1144  discr = discr>0. ? std::sqrt(discr) : 0.;
1145  KineticEnergy = 0.5*(discr-B)/A ;
1146  }
1147  }
1148 
1149  aVector->PutValue(i,KineticEnergy) ;
1150  }
1151 }
1152 
1153 //------------------------------------------------------------------------------
1154 
1156 {
1157  G4bool wasModified = false;
1158  const G4ProductionCutsTable* theCoupleTable=
1160  size_t numOfCouples = theCoupleTable->GetTableSize();
1161 
1162  for (size_t j=0; j<numOfCouples; j++){
1163  if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
1164  wasModified = true;
1165  break;
1166  }
1167  }
1168  return wasModified;
1169 }
1170 
1171 //-----------------------------------------------------------------------
1172 //--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
1173 
1174 //G4bool G4hRDEnergyLoss::IsApplicable(const G4ParticleDefinition&
1175 // particle)
1176 //{
1177 // return((particle.GetPDGCharge()!= 0.) && (particle.GetLeptonNumber() == 0));
1178 //}
1179 
1180 //G4double G4hRDEnergyLoss::GetContinuousStepLimit(
1181 // const G4Track& track,
1182 // G4double,
1183 // G4double currentMinimumStep,
1184 // G4double&)
1185 //{
1186 //
1187 // G4double Step =
1188 // GetConstraints(track.GetDynamicParticle(),track.GetMaterial()) ;
1189 //
1190 // if((Step>0.0)&&(Step<currentMinimumStep))
1191 // currentMinimumStep = Step ;
1192 //
1193 // return Step ;
1194 //}
static G4ThreadLocal G4double RTable
static G4ThreadLocal G4PhysicsTable * theProperTimepTable
static G4ThreadLocal G4double LowestKineticEnergy
static G4ThreadLocal G4PhysicsTable * theRangepbarTable
static G4ThreadLocal G4PhysicsTable * theLabTimepTable
static G4ThreadLocal G4PhysicsTable * theDEDXpbarTable
G4double GetValue(G4double theEnergy, G4bool &isOutRange) const
static void MinusNumberOfProcesses()
static G4int GetNumberOfProcesses()
void insert(G4PhysicsVector *)
static constexpr double proton_mass_c2
static G4ThreadLocal G4bool rndmStepFlag
static G4ThreadLocal G4double c3lim
static G4ThreadLocal G4double LOGRTable
static G4ThreadLocal G4double ParticleMass
static G4ThreadLocal G4double Charge
G4bool IsRecalcNeeded() const
static G4ThreadLocal G4double c1lim
static G4ThreadLocal G4PhysicsTable ** RecorderOfpbarProcess
double C(double temp)
static G4ThreadLocal G4PhysicsTable * theProperTimepbarTable
double B(double temperature)
size_t GetVectorLength() const
static G4ThreadLocal G4double finalRange
G4double GetLowEdgeEnergy(size_t binNumber) const
#define G4ThreadLocal
Definition: tls.hh:89
static G4ThreadLocal G4PhysicsTable * theInverseRangepbarTable
int G4int
Definition: G4Types.hh:78
static G4ThreadLocal G4int TotBin
static G4ThreadLocal G4PhysicsTable ** RecorderOfpProcess
double A(double temperature)
const XML_Char int const XML_Char * value
Definition: expat.h:331
static G4ThreadLocal G4PhysicsTable * theRangepTable
static G4AntiProton * AntiProton()
Definition: G4AntiProton.cc:93
bool G4bool
Definition: G4Types.hh:79
static constexpr double eplus
Definition: G4SIunits.hh:199
void PutValue(size_t index, G4double theValue)
static G4Proton * Proton()
Definition: G4Proton.cc:93
static G4ThreadLocal G4double dRoverRange
static G4ThreadLocal G4int CounterOfpProcess
static void BuildDEDXTable(const G4ParticleDefinition &aParticleType)
static G4ThreadLocal G4double HighestKineticEnergy
static G4ProductionCutsTable * GetProductionCutsTable()
static G4ThreadLocal G4int CounterOfpbarProcess
G4double GetPDGMass() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static void SetNumberOfProcesses(G4int number)
static void PlusNumberOfProcesses()
static G4ThreadLocal G4double pbartableElectronCutInRange
G4double energy(const ThreeVector &p, const G4double m)
G4bool CutsWhereModified()
static G4ThreadLocal G4bool EnlossFlucFlag
G4hRDEnergyLoss(const G4String &)
static G4ThreadLocal G4double c2lim
static constexpr double c_light
static void SetRndmStep(G4bool value)
#define DBL_MIN
Definition: templates.hh:75
static void SetdRoverRange(G4double value)
G4PhysicsTable * theLossTable
static G4ThreadLocal G4PhysicsTable * theLabTimepbarTable
double G4double
Definition: G4Types.hh:76
static void Register(const G4ParticleDefinition *p, const G4PhysicsTable *tDEDX, const G4PhysicsTable *tRange, const G4PhysicsTable *tInverseRange, const G4PhysicsTable *tLabTime, const G4PhysicsTable *tProperTime, G4double lowestKineticEnergy, G4double highestKineticEnergy, G4double massRatio, G4int NumberOfBins)
G4double GetPDGCharge() const
static G4ThreadLocal G4PhysicsTable * theInverseRangepTable
static constexpr double keV
Definition: G4SIunits.hh:216
static void SetEnlossFluc(G4bool value)
static void SetStepFunction(G4double c1, G4double c2)
static G4ThreadLocal G4double ptableElectronCutInRange
void clearAndDestroy()
static G4ThreadLocal G4PhysicsTable * theDEDXpTable