Geant4 Cross Reference

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