source: trunk/source/processes/electromagnetic/lowenergy/src/G4hLowEnergyLoss.cc @ 1066

Last change on this file since 1066 was 1055, checked in by garnier, 15 years ago

maj sur la beta de geant 4.9.3

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