Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4IonParametrisedLossModel.cc

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

Diff markup

Differences between /processes/electromagnetic/lowenergy/src/G4IonParametrisedLossModel.cc (Version 11.3.0) and /processes/electromagnetic/lowenergy/src/G4IonParametrisedLossModel.cc (Version 11.0.p1)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 //                                                 26 //
 27 // ===========================================     27 // ===========================================================================
 28 // GEANT4 class source file                        28 // GEANT4 class source file
 29 //                                                 29 //
 30 // Class:                G4IonParametrisedLoss     30 // Class:                G4IonParametrisedLossModel
 31 //                                                 31 //
 32 // Base class:           G4VEmModel (utils)        32 // Base class:           G4VEmModel (utils)
 33 //                                                 33 //
 34 // Author:               Anton Lechner (Anton.     34 // Author:               Anton Lechner (Anton.Lechner@cern.ch)
 35 //                                                 35 //
 36 // First implementation: 10. 11. 2008              36 // First implementation: 10. 11. 2008
 37 //                                                 37 //
 38 // Modifications: 03. 02. 2009 - Bug fix itera     38 // Modifications: 03. 02. 2009 - Bug fix iterators (AL)
 39 //                11. 03. 2009 - Introduced ne     39 //                11. 03. 2009 - Introduced new table handler(G4IonDEDXHandler)
 40 //                               and modified      40 //                               and modified method to add/remove tables
 41 //                               (tables are n     41 //                               (tables are now built in init. phase),
 42 //                               Minor bug fix     42 //                               Minor bug fix in ComputeDEDXPerVolume (AL)
 43 //                11. 05. 2009 - Introduced sc     43 //                11. 05. 2009 - Introduced scaling algorithm for heavier ions:
 44 //                               G4IonDEDXScal     44 //                               G4IonDEDXScalingICRU73 (AL)
 45 //                12. 11. 2009 - Moved from or     45 //                12. 11. 2009 - Moved from original ICRU 73 classes to new
 46 //                               class (G4IonS     46 //                               class (G4IonStoppingData), which is capable
 47 //                               of reading st     47 //                               of reading stopping power data files stored
 48 //                               in G4LEDATA (     48 //                               in G4LEDATA (requires G4EMLOW6.8 or higher).
 49 //                               Simultanesoul     49 //                               Simultanesouly, the upper energy limit of
 50 //                               ICRU 73 is in     50 //                               ICRU 73 is increased to 1 GeV/nucleon.
 51 //                             - Removed nucle     51 //                             - Removed nuclear stopping from Corrections-
 52 //                               AlongStep sin     52 //                               AlongStep since dedicated process was created.
 53 //                             - Added functio     53 //                             - Added function for switching off scaling
 54 //                               of heavy ions     54 //                               of heavy ions from ICRU 73 data
 55 //                             - Minor fix in      55 //                             - Minor fix in ComputeLossForStep function
 56 //                             - Minor fix in      56 //                             - Minor fix in ComputeDEDXPerVolume (AL)
 57 //                23. 11. 2009 - Changed energ     57 //                23. 11. 2009 - Changed energy loss limit from 0.15 to 0.01
 58 //                               to improve ac     58 //                               to improve accuracy for large steps (AL)
 59 //                24. 11. 2009 - Bug fix: Rang     59 //                24. 11. 2009 - Bug fix: Range calculation corrected if same
 60 //                               materials app     60 //                               materials appears with different cuts in diff.
 61 //                               regions (adde     61 //                               regions (added UpdateRangeCache function and
 62 //                               modified Buil     62 //                               modified BuildRangeVector, ComputeLossForStep
 63 //                               functions acc     63 //                               functions accordingly, added new cache param.)
 64 //                             - Removed GetRa     64 //                             - Removed GetRange function (AL)
 65 //                04. 11. 2010 - Moved virtual     65 //                04. 11. 2010 - Moved virtual methods to the source (VI)
 66 //                                                 66 //
 67 //                                                 67 //
 68 // Class description:                              68 // Class description:
 69 //    Model for computing the energy loss of i     69 //    Model for computing the energy loss of ions by employing a
 70 //    parameterisation of dE/dx tables (by def     70 //    parameterisation of dE/dx tables (by default ICRU 73 tables). For
 71 //    ion-material combinations and/or project     71 //    ion-material combinations and/or projectile energies not covered
 72 //    by this model, the G4BraggIonModel and G     72 //    by this model, the G4BraggIonModel and G4BetheBloch models are
 73 //    employed.                                    73 //    employed.
 74 //                                                 74 //
 75 // Comments:                                       75 // Comments:
 76 //                                                 76 //
 77 // ===========================================     77 // ===========================================================================
 78 #include "G4IonParametrisedLossModel.hh"           78 #include "G4IonParametrisedLossModel.hh"
 79 #include "G4PhysicalConstants.hh"                  79 #include "G4PhysicalConstants.hh"
 80 #include "G4SystemOfUnits.hh"                      80 #include "G4SystemOfUnits.hh"
 81 #include "G4PhysicsFreeVector.hh"                  81 #include "G4PhysicsFreeVector.hh"
 82 #include "G4IonStoppingData.hh"                    82 #include "G4IonStoppingData.hh"
 83 #include "G4VIonDEDXTable.hh"                      83 #include "G4VIonDEDXTable.hh"
 84 #include "G4VIonDEDXScalingAlgorithm.hh"           84 #include "G4VIonDEDXScalingAlgorithm.hh"
 85 #include "G4IonDEDXScalingICRU73.hh"               85 #include "G4IonDEDXScalingICRU73.hh"
 86 #include "G4BraggIonModel.hh"                      86 #include "G4BraggIonModel.hh"
 87 #include "G4BetheBlochModel.hh"                    87 #include "G4BetheBlochModel.hh"
 88 #include "G4ProductionCutsTable.hh"                88 #include "G4ProductionCutsTable.hh"
 89 #include "G4ParticleChangeForLoss.hh"              89 #include "G4ParticleChangeForLoss.hh"
 90 #include "G4LossTableManager.hh"                   90 #include "G4LossTableManager.hh"
 91 #include "G4EmParameters.hh"                       91 #include "G4EmParameters.hh"
 92 #include "G4GenericIon.hh"                         92 #include "G4GenericIon.hh"
 93 #include "G4Electron.hh"                           93 #include "G4Electron.hh"
 94 #include "G4DeltaAngle.hh"                         94 #include "G4DeltaAngle.hh"
 95 #include "Randomize.hh"                            95 #include "Randomize.hh"
 96 #include "G4Exp.hh"                                96 #include "G4Exp.hh"
 97                                                    97 
 98 //#define PRINT_TABLE_BUILT                        98 //#define PRINT_TABLE_BUILT
 99 // ###########################################     99 // #########################################################################
100                                                   100 
101 G4IonParametrisedLossModel::G4IonParametrisedL    101 G4IonParametrisedLossModel::G4IonParametrisedLossModel(
102              const G4ParticleDefinition*,         102              const G4ParticleDefinition*,
103              const G4String& nam)                 103              const G4String& nam)
104   : G4VEmModel(nam),                              104   : G4VEmModel(nam),
105     braggIonModel(0),                             105     braggIonModel(0),
106     betheBlochModel(0),                           106     betheBlochModel(0),
107     nmbBins(90),                                  107     nmbBins(90),
108     nmbSubBins(100),                              108     nmbSubBins(100),
109     particleChangeLoss(0),                        109     particleChangeLoss(0),
110     corrFactor(1.0),                              110     corrFactor(1.0),
111     energyLossLimit(0.01),                        111     energyLossLimit(0.01),
112     cutEnergies(0),                               112     cutEnergies(0),
113     isInitialised(false)                          113     isInitialised(false)
114 {                                                 114 {
115   genericIon = G4GenericIon::Definition();        115   genericIon = G4GenericIon::Definition();
116   genericIonPDGMass = genericIon->GetPDGMass()    116   genericIonPDGMass = genericIon->GetPDGMass();
117   corrections = G4LossTableManager::Instance()    117   corrections = G4LossTableManager::Instance()->EmCorrections();
118                                                   118 
119   // The Bragg ion and Bethe Bloch models are     119   // The Bragg ion and Bethe Bloch models are instantiated
120   braggIonModel = new G4BraggIonModel();          120   braggIonModel = new G4BraggIonModel();
121   betheBlochModel = new G4BetheBlochModel();      121   betheBlochModel = new G4BetheBlochModel();
122                                                   122 
123   // The boundaries for the range tables are s    123   // The boundaries for the range tables are set
124   lowerEnergyEdgeIntegr = 0.025 * MeV;            124   lowerEnergyEdgeIntegr = 0.025 * MeV;
125   upperEnergyEdgeIntegr = betheBlochModel -> H    125   upperEnergyEdgeIntegr = betheBlochModel -> HighEnergyLimit();
126                                                   126 
127   // Cache parameters are set                     127   // Cache parameters are set
128   cacheParticle = 0;                              128   cacheParticle = 0;
129   cacheMass = 0;                                  129   cacheMass = 0;
130   cacheElecMassRatio = 0;                         130   cacheElecMassRatio = 0;
131   cacheChargeSquare = 0;                          131   cacheChargeSquare = 0;
132                                                   132 
133   // Cache parameters are set                     133   // Cache parameters are set
134   rangeCacheParticle = 0;                         134   rangeCacheParticle = 0;
135   rangeCacheMatCutsCouple = 0;                    135   rangeCacheMatCutsCouple = 0;
136   rangeCacheEnergyRange = 0;                      136   rangeCacheEnergyRange = 0;
137   rangeCacheRangeEnergy = 0;                      137   rangeCacheRangeEnergy = 0;
138                                                   138 
139   // Cache parameters are set                     139   // Cache parameters are set
140   dedxCacheParticle = 0;                          140   dedxCacheParticle = 0;
141   dedxCacheMaterial = 0;                          141   dedxCacheMaterial = 0;
142   dedxCacheEnergyCut = 0;                         142   dedxCacheEnergyCut = 0;
143   dedxCacheIter = lossTableList.end();            143   dedxCacheIter = lossTableList.end();
144   dedxCacheTransitionEnergy = 0.0;                144   dedxCacheTransitionEnergy = 0.0;
145   dedxCacheTransitionFactor = 0.0;                145   dedxCacheTransitionFactor = 0.0;
146   dedxCacheGenIonMassRatio = 0.0;                 146   dedxCacheGenIonMassRatio = 0.0;
147                                                   147 
148   // default generator                            148   // default generator
149   SetAngularDistribution(new G4DeltaAngle());     149   SetAngularDistribution(new G4DeltaAngle());
150 }                                                 150 }
151                                                   151 
152 // ###########################################    152 // #########################################################################
153                                                   153 
154 G4IonParametrisedLossModel::~G4IonParametrised    154 G4IonParametrisedLossModel::~G4IonParametrisedLossModel() {
155                                                   155 
156   // dE/dx table objects are deleted and the c    156   // dE/dx table objects are deleted and the container is cleared
157   LossTableList::iterator iterTables = lossTab    157   LossTableList::iterator iterTables = lossTableList.begin();
158   LossTableList::iterator iterTables_end = los    158   LossTableList::iterator iterTables_end = lossTableList.end();
159                                                   159 
160   for(;iterTables != iterTables_end; ++iterTab    160   for(;iterTables != iterTables_end; ++iterTables) { delete *iterTables; }
161   lossTableList.clear();                          161   lossTableList.clear();
162                                                   162 
163   // range table                                  163   // range table
164   RangeEnergyTable::iterator itr = r.begin();     164   RangeEnergyTable::iterator itr = r.begin();
165   RangeEnergyTable::iterator itr_end = r.end()    165   RangeEnergyTable::iterator itr_end = r.end();
166   for(;itr != itr_end; ++itr) { delete itr->se    166   for(;itr != itr_end; ++itr) { delete itr->second; }
167   r.clear();                                      167   r.clear();
168                                                   168 
169   // inverse range                                169   // inverse range
170   EnergyRangeTable::iterator ite = E.begin();     170   EnergyRangeTable::iterator ite = E.begin();
171   EnergyRangeTable::iterator ite_end = E.end()    171   EnergyRangeTable::iterator ite_end = E.end();
172   for(;ite != ite_end; ++ite) { delete ite->se    172   for(;ite != ite_end; ++ite) { delete ite->second; }
173   E.clear();                                      173   E.clear();
174                                                   174 
175 }                                                 175 }
176                                                   176 
177 // ###########################################    177 // #########################################################################
178                                                   178 
179 G4double G4IonParametrisedLossModel::MinEnergy    179 G4double G4IonParametrisedLossModel::MinEnergyCut(
180                                        const G    180                                        const G4ParticleDefinition*,
181                                        const G    181                                        const G4MaterialCutsCouple* couple) {
182                                                   182 
183   return couple->GetMaterial()->GetIonisation(    183   return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
184 }                                                 184 }
185                                                   185 
186 // ###########################################    186 // #########################################################################
187                                                   187 
188 G4double G4IonParametrisedLossModel::MaxSecond    188 G4double G4IonParametrisedLossModel::MaxSecondaryEnergy(
189                              const G4ParticleD    189                              const G4ParticleDefinition* particle,
190                              G4double kineticE    190                              G4double kineticEnergy) {
191                                                   191 
192   // ############## Maximum energy of secondar    192   // ############## Maximum energy of secondaries ##########################
193   // Function computes maximum energy of secon    193   // Function computes maximum energy of secondary electrons which are
194   // released by an ion                           194   // released by an ion
195   //                                              195   //
196   // See Geant4 physics reference manual (vers    196   // See Geant4 physics reference manual (version 9.1), section 9.1.1
197   //                                              197   //
198   // Ref.: W.M. Yao et al, Jour. of Phys. G 33    198   // Ref.: W.M. Yao et al, Jour. of Phys. G 33 (2006) 1.
199   //       C.Caso et al. (Part. Data Group), E    199   //       C.Caso et al. (Part. Data Group), Europ. Phys. Jour. C 3 1 (1998).
200   //       B. Rossi, High energy particles, Ne    200   //       B. Rossi, High energy particles, New York, NY: Prentice-Hall (1952).
201   //                                              201   //
202   // (Implementation adapted from G4BraggIonMo    202   // (Implementation adapted from G4BraggIonModel)
203                                                   203 
204   if(particle != cacheParticle) UpdateCache(pa    204   if(particle != cacheParticle) UpdateCache(particle);
205                                                   205 
206   G4double tau  = kineticEnergy/cacheMass;        206   G4double tau  = kineticEnergy/cacheMass;
207   G4double tmax = 2.0 * electron_mass_c2 * tau    207   G4double tmax = 2.0 * electron_mass_c2 * tau * (tau + 2.) /
208                   (1. + 2.0 * (tau + 1.) * cac    208                   (1. + 2.0 * (tau + 1.) * cacheElecMassRatio +
209                   cacheElecMassRatio * cacheEl    209                   cacheElecMassRatio * cacheElecMassRatio);
210                                                   210 
211   return tmax;                                    211   return tmax;
212 }                                                 212 }
213                                                   213 
214 // ###########################################    214 // #########################################################################
215                                                   215 
216 G4double G4IonParametrisedLossModel::GetCharge    216 G4double G4IonParametrisedLossModel::GetChargeSquareRatio(
217                              const G4ParticleD    217                              const G4ParticleDefinition* particle,
218            const G4Material* material,            218            const G4Material* material,
219                              G4double kineticE    219                              G4double kineticEnergy) {    // Kinetic energy
220                                                   220 
221   G4double chargeSquareRatio = corrections ->     221   G4double chargeSquareRatio = corrections ->
222                                      Effective    222                                      EffectiveChargeSquareRatio(particle,
223                                                   223                                                                 material,
224                                                   224                                                                 kineticEnergy);
225   corrFactor = chargeSquareRatio *                225   corrFactor = chargeSquareRatio *
226                        corrections -> Effectiv    226                        corrections -> EffectiveChargeCorrection(particle,
227                                                   227                                                                 material,
228                                                   228                                                                 kineticEnergy);
229   return corrFactor;                              229   return corrFactor;
230 }                                                 230 }
231                                                   231 
232 // ###########################################    232 // #########################################################################
233                                                   233 
234 G4double G4IonParametrisedLossModel::GetPartic    234 G4double G4IonParametrisedLossModel::GetParticleCharge(
235                              const G4ParticleD    235                              const G4ParticleDefinition* particle,
236            const G4Material* material,            236            const G4Material* material,
237                              G4double kineticE    237                              G4double kineticEnergy) {   // Kinetic energy
238                                                   238 
239   return corrections -> GetParticleCharge(part    239   return corrections -> GetParticleCharge(particle, material, kineticEnergy);
240 }                                                 240 }
241                                                   241 
242 // ###########################################    242 // #########################################################################
243                                                   243 
244 void G4IonParametrisedLossModel::Initialise(      244 void G4IonParametrisedLossModel::Initialise(
245                                        const G    245                                        const G4ParticleDefinition* particle,
246                                        const G    246                                        const G4DataVector& cuts) {
247                                                   247 
248   // Cached parameters are reset                  248   // Cached parameters are reset
249   cacheParticle = 0;                              249   cacheParticle = 0;
250   cacheMass = 0;                                  250   cacheMass = 0;
251   cacheElecMassRatio = 0;                         251   cacheElecMassRatio = 0;
252   cacheChargeSquare = 0;                          252   cacheChargeSquare = 0;
253                                                   253 
254   // Cached parameters are reset                  254   // Cached parameters are reset
255   rangeCacheParticle = 0;                         255   rangeCacheParticle = 0;
256   rangeCacheMatCutsCouple = 0;                    256   rangeCacheMatCutsCouple = 0;
257   rangeCacheEnergyRange = 0;                      257   rangeCacheEnergyRange = 0;
258   rangeCacheRangeEnergy = 0;                      258   rangeCacheRangeEnergy = 0;
259                                                   259 
260   // Cached parameters are reset                  260   // Cached parameters are reset
261   dedxCacheParticle = 0;                          261   dedxCacheParticle = 0;
262   dedxCacheMaterial = 0;                          262   dedxCacheMaterial = 0;
263   dedxCacheEnergyCut = 0;                         263   dedxCacheEnergyCut = 0;
264   dedxCacheIter = lossTableList.end();            264   dedxCacheIter = lossTableList.end();
265   dedxCacheTransitionEnergy = 0.0;                265   dedxCacheTransitionEnergy = 0.0;
266   dedxCacheTransitionFactor = 0.0;                266   dedxCacheTransitionFactor = 0.0;
267   dedxCacheGenIonMassRatio = 0.0;                 267   dedxCacheGenIonMassRatio = 0.0;
268                                                   268 
269   // By default ICRU 73 stopping power tables     269   // By default ICRU 73 stopping power tables are loaded:
270   if(!isInitialised) {                            270   if(!isInitialised) {
271     G4bool icru90 = G4EmParameters::Instance()    271     G4bool icru90 = G4EmParameters::Instance()->UseICRU90Data();
272     isInitialised = true;                         272     isInitialised = true;
273     AddDEDXTable("ICRU73",                        273     AddDEDXTable("ICRU73",
274      new G4IonStoppingData("ion_stopping_data/    274      new G4IonStoppingData("ion_stopping_data/icru",icru90),
275      new G4IonDEDXScalingICRU73());               275      new G4IonDEDXScalingICRU73());
276   }                                               276   }
277   // The cache of loss tables is cleared          277   // The cache of loss tables is cleared
278   LossTableList::iterator iterTables = lossTab    278   LossTableList::iterator iterTables = lossTableList.begin();
279   LossTableList::iterator iterTables_end = los    279   LossTableList::iterator iterTables_end = lossTableList.end();
280                                                   280 
281   for(;iterTables != iterTables_end; ++iterTab    281   for(;iterTables != iterTables_end; ++iterTables) {
282     (*iterTables) -> ClearCache();                282     (*iterTables) -> ClearCache();
283   }                                               283   }
284                                                   284 
285   // Range vs energy and energy vs range vecto    285   // Range vs energy and energy vs range vectors from previous runs are
286   // cleared                                      286   // cleared
287   RangeEnergyTable::iterator iterRange = r.beg    287   RangeEnergyTable::iterator iterRange = r.begin();
288   RangeEnergyTable::iterator iterRange_end = r    288   RangeEnergyTable::iterator iterRange_end = r.end();
289                                                   289 
290   for(;iterRange != iterRange_end; ++iterRange    290   for(;iterRange != iterRange_end; ++iterRange) {
291     delete iterRange->second;                     291     delete iterRange->second;
292   }                                               292   }
293   r.clear();                                      293   r.clear();
294                                                   294 
295   EnergyRangeTable::iterator iterEnergy = E.be    295   EnergyRangeTable::iterator iterEnergy = E.begin();
296   EnergyRangeTable::iterator iterEnergy_end =     296   EnergyRangeTable::iterator iterEnergy_end = E.end();
297                                                   297 
298   for(;iterEnergy != iterEnergy_end; ++iterEne << 298   for(;iterEnergy != iterEnergy_end; iterEnergy++) {
299     delete iterEnergy->second;                    299     delete iterEnergy->second;
300   }                                               300   }
301   E.clear();                                      301   E.clear();
302                                                   302 
303   // The cut energies                             303   // The cut energies 
304   cutEnergies = cuts;                             304   cutEnergies = cuts;
305                                                   305 
306   // All dE/dx vectors are built                  306   // All dE/dx vectors are built
307   const G4ProductionCutsTable* coupleTable=       307   const G4ProductionCutsTable* coupleTable=
308                      G4ProductionCutsTable::Ge    308                      G4ProductionCutsTable::GetProductionCutsTable();
309   G4int nmbCouples = (G4int)coupleTable->GetTa << 309   size_t nmbCouples = coupleTable->GetTableSize();
310                                                   310 
311 #ifdef PRINT_TABLE_BUILT                          311 #ifdef PRINT_TABLE_BUILT
312     G4cout << "G4IonParametrisedLossModel::Ini    312     G4cout << "G4IonParametrisedLossModel::Initialise():"
313            << " Building dE/dx vectors:"          313            << " Building dE/dx vectors:"
314            << G4endl;                             314            << G4endl;
315 #endif                                            315 #endif
316                                                   316 
317   for (G4int i = 0; i < nmbCouples; ++i) {     << 317   for (size_t i = 0; i < nmbCouples; ++i) {
318                                                   318 
319     const G4MaterialCutsCouple* couple = coupl    319     const G4MaterialCutsCouple* couple = coupleTable->GetMaterialCutsCouple(i);
320     const G4Material* material = couple->GetMa    320     const G4Material* material = couple->GetMaterial();
321                                                   321 
322     for(G4int atomicNumberIon = 3; atomicNumbe    322     for(G4int atomicNumberIon = 3; atomicNumberIon < 102; ++atomicNumberIon) {
323                                                   323 
324        LossTableList::iterator iter = lossTabl    324        LossTableList::iterator iter = lossTableList.begin();
325        LossTableList::iterator iter_end = loss    325        LossTableList::iterator iter_end = lossTableList.end();
326                                                   326 
327        for(;iter != iter_end; ++iter) {           327        for(;iter != iter_end; ++iter) {
328                                                   328 
329           if(*iter == 0) {                        329           if(*iter == 0) {
330               G4cout << "G4IonParametrisedLoss    330               G4cout << "G4IonParametrisedLossModel::Initialise():"
331                      << " Skipping illegal tab    331                      << " Skipping illegal table."
332                      << G4endl;                   332                      << G4endl;
333           }                                       333           }
334                                                   334     
335     if((*iter)->BuildDEDXTable(atomicNumberIon    335     if((*iter)->BuildDEDXTable(atomicNumberIon, material)) {
336                                                   336 
337 #ifdef PRINT_TABLE_BUILT                          337 #ifdef PRINT_TABLE_BUILT
338              G4cout << "  Atomic Number Ion =     338              G4cout << "  Atomic Number Ion = " << atomicNumberIon
339                     << ", Material = " << mate    339                     << ", Material = " << material -> GetName()
340                     << ", Table = " << (*iter)    340                     << ", Table = " << (*iter) -> GetName()
341                     << G4endl;                    341                     << G4endl;
342 #endif                                            342 #endif
343              break;                               343              break;
344     }                                             344     }
345        }                                          345        }
346     }                                             346     }
347   }                                               347   }
348                                                   348 
349   // The particle change object                   349   // The particle change object
350   if(! particleChangeLoss) {                      350   if(! particleChangeLoss) {
351     particleChangeLoss = GetParticleChangeForL    351     particleChangeLoss = GetParticleChangeForLoss();
352     braggIonModel->SetParticleChange(particleC    352     braggIonModel->SetParticleChange(particleChangeLoss, 0);
353     betheBlochModel->SetParticleChange(particl    353     betheBlochModel->SetParticleChange(particleChangeLoss, 0);
354   }                                               354   }
355                                                   355 
356   // The G4BraggIonModel and G4BetheBlochModel    356   // The G4BraggIonModel and G4BetheBlochModel instances are initialised with
357   // the same settings as the current model:      357   // the same settings as the current model:
358   braggIonModel -> Initialise(particle, cuts);    358   braggIonModel -> Initialise(particle, cuts);
359   betheBlochModel -> Initialise(particle, cuts    359   betheBlochModel -> Initialise(particle, cuts);
360 }                                                 360 }
361                                                   361 
362 // ###########################################    362 // #########################################################################
363                                                   363 
364 G4double G4IonParametrisedLossModel::ComputeCr    364 G4double G4IonParametrisedLossModel::ComputeCrossSectionPerAtom(
365                                    const G4Par    365                                    const G4ParticleDefinition* particle,
366                                    G4double ki    366                                    G4double kineticEnergy,
367            G4double atomicNumber,                 367            G4double atomicNumber,
368                                    G4double,      368                                    G4double,
369                                    G4double cu    369                                    G4double cutEnergy,
370                                    G4double ma    370                                    G4double maxKinEnergy) {
371                                                   371 
372   // ############## Cross section per atom  ##    372   // ############## Cross section per atom  ################################
373   // Function computes ionization cross sectio    373   // Function computes ionization cross section per atom
374   //                                              374   //
375   // See Geant4 physics reference manual (vers    375   // See Geant4 physics reference manual (version 9.1), section 9.1.3
376   //                                              376   //
377   // Ref.: W.M. Yao et al, Jour. of Phys. G 33    377   // Ref.: W.M. Yao et al, Jour. of Phys. G 33 (2006) 1.
378   //       B. Rossi, High energy particles, Ne    378   //       B. Rossi, High energy particles, New York, NY: Prentice-Hall (1952).
379   //                                              379   //
380   // (Implementation adapted from G4BraggIonMo    380   // (Implementation adapted from G4BraggIonModel)
381                                                   381 
382   G4double crosssection     = 0.0;                382   G4double crosssection     = 0.0;
383   G4double tmax      = MaxSecondaryEnergy(part    383   G4double tmax      = MaxSecondaryEnergy(particle, kineticEnergy);
384   G4double maxEnergy = std::min(tmax, maxKinEn    384   G4double maxEnergy = std::min(tmax, maxKinEnergy);
385                                                   385 
386   if(cutEnergy < tmax) {                          386   if(cutEnergy < tmax) {
387                                                   387 
388      G4double energy  = kineticEnergy + cacheM    388      G4double energy  = kineticEnergy + cacheMass;
389      G4double betaSquared  = kineticEnergy *      389      G4double betaSquared  = kineticEnergy *
390                                      (energy +    390                                      (energy + cacheMass) / (energy * energy);
391                                                   391 
392      crosssection = 1.0 / cutEnergy - 1.0 / ma    392      crosssection = 1.0 / cutEnergy - 1.0 / maxEnergy -
393                          betaSquared * std::lo    393                          betaSquared * std::log(maxEnergy / cutEnergy) / tmax;
394                                                   394 
395      crosssection *= twopi_mc2_rcl2 * cacheCha    395      crosssection *= twopi_mc2_rcl2 * cacheChargeSquare / betaSquared;
396   }                                               396   }
397                                                   397 
398 #ifdef PRINT_DEBUG_CS                             398 #ifdef PRINT_DEBUG_CS
399   G4cout << "#################################    399   G4cout << "########################################################"
400          << G4endl                                400          << G4endl
401          << "# G4IonParametrisedLossModel::Com    401          << "# G4IonParametrisedLossModel::ComputeCrossSectionPerAtom"
402          << G4endl                                402          << G4endl
403          << "# particle =" << particle -> GetP    403          << "# particle =" << particle -> GetParticleName()
404          <<  G4endl                               404          <<  G4endl
405          << "# cut(MeV) = " << cutEnergy/MeV      405          << "# cut(MeV) = " << cutEnergy/MeV
406          << G4endl;                               406          << G4endl;
407                                                   407 
408   G4cout << "#"                                   408   G4cout << "#"
409          << std::setw(13) << std::right << "E(    409          << std::setw(13) << std::right << "E(MeV)"
410          << std::setw(14) << "CS(um)"             410          << std::setw(14) << "CS(um)"
411          << std::setw(14) << "E_max_sec(MeV)"     411          << std::setw(14) << "E_max_sec(MeV)"
412          << G4endl                                412          << G4endl
413          << "# -------------------------------    413          << "# ------------------------------------------------------"
414          << G4endl;                               414          << G4endl;
415                                                   415 
416   G4cout << std::setw(14) << std::right << kin    416   G4cout << std::setw(14) << std::right << kineticEnergy / MeV
417          << std::setw(14) << crosssection / (u    417          << std::setw(14) << crosssection / (um * um)
418          << std::setw(14) << tmax / MeV           418          << std::setw(14) << tmax / MeV
419          << G4endl;                               419          << G4endl;
420 #endif                                            420 #endif
421                                                   421 
422   crosssection *= atomicNumber;                   422   crosssection *= atomicNumber;
423                                                   423 
424   return crosssection;                            424   return crosssection;
425 }                                                 425 }
426                                                   426 
427 // ###########################################    427 // #########################################################################
428                                                   428 
429 G4double G4IonParametrisedLossModel::CrossSect    429 G4double G4IonParametrisedLossModel::CrossSectionPerVolume(
430            const G4Material* material,            430            const G4Material* material,
431                                    const G4Par    431                                    const G4ParticleDefinition* particle,
432                                    G4double ki    432                                    G4double kineticEnergy,
433                                    G4double cu    433                                    G4double cutEnergy,
434                                    G4double ma    434                                    G4double maxEnergy) {
435                                                   435 
436   G4double nbElecPerVolume = material -> GetTo    436   G4double nbElecPerVolume = material -> GetTotNbOfElectPerVolume();
437   G4double cross = ComputeCrossSectionPerAtom(    437   G4double cross = ComputeCrossSectionPerAtom(particle,
438                                                   438                                               kineticEnergy,
439                                                   439                                               nbElecPerVolume, 0,
440                                                   440                                               cutEnergy,
441                                                   441                                               maxEnergy);
442                                                   442 
443   return cross;                                   443   return cross;
444 }                                                 444 }
445                                                   445 
446 // ###########################################    446 // #########################################################################
447                                                   447 
448 G4double G4IonParametrisedLossModel::ComputeDE    448 G4double G4IonParametrisedLossModel::ComputeDEDXPerVolume(
449                                       const G4    449                                       const G4Material* material,
450                     const G4ParticleDefinition    450                     const G4ParticleDefinition* particle,
451               G4double kineticEnergy,             451               G4double kineticEnergy,
452               G4double cutEnergy) {               452               G4double cutEnergy) {
453                                                   453 
454   // ############## dE/dx ####################    454   // ############## dE/dx ##################################################
455   // Function computes dE/dx values, where fol    455   // Function computes dE/dx values, where following rules are adopted:
456   //   A. If the ion-material pair is covered     456   //   A. If the ion-material pair is covered by any native ion data
457   //      parameterisation, then:                 457   //      parameterisation, then:
458   //      * This parameterization is used for     458   //      * This parameterization is used for energies below a given energy
459   //        limit,                                459   //        limit,
460   //      * whereas above the limit the Bethe-    460   //      * whereas above the limit the Bethe-Bloch model is applied, in
461   //        combination with an effective char    461   //        combination with an effective charge estimate and high order
462   //        correction terms.                     462   //        correction terms.
463   //      A smoothing procedure is applied to     463   //      A smoothing procedure is applied to dE/dx values computed with
464   //      the second approach. The smoothing f    464   //      the second approach. The smoothing factor is based on the dE/dx
465   //      values of both approaches at the tra    465   //      values of both approaches at the transition energy (high order
466   //      correction terms are included in the    466   //      correction terms are included in the calculation of the transition
467   //      factor).                                467   //      factor).
468   //   B. If the particle is a generic ion, th    468   //   B. If the particle is a generic ion, the BraggIon and Bethe-Bloch
469   //      models are used and a smoothing proc    469   //      models are used and a smoothing procedure is applied to values
470   //      obtained with the second approach.      470   //      obtained with the second approach.
471   //   C. If the ion-material is not covered b    471   //   C. If the ion-material is not covered by any ion data parameterization
472   //      then:                                   472   //      then:
473   //      * The BraggIon model is used for ene    473   //      * The BraggIon model is used for energies below a given energy
474   //        limit,                                474   //        limit,
475   //      * whereas above the limit the Bethe-    475   //      * whereas above the limit the Bethe-Bloch model is applied, in
476   //        combination with an effective char    476   //        combination with an effective charge estimate and high order
477   //        correction terms.                     477   //        correction terms.
478   //      Also in this case, a smoothing proce    478   //      Also in this case, a smoothing procedure is applied to dE/dx values
479   //      computed with the second model.         479   //      computed with the second model.
480                                                   480 
481   G4double dEdx = 0.0;                            481   G4double dEdx = 0.0;
482   UpdateDEDXCache(particle, material, cutEnerg    482   UpdateDEDXCache(particle, material, cutEnergy);
483                                                   483 
484   LossTableList::iterator iter = dedxCacheIter    484   LossTableList::iterator iter = dedxCacheIter;
485                                                   485 
486   if(iter != lossTableList.end()) {               486   if(iter != lossTableList.end()) {
487                                                   487 
488      G4double transitionEnergy = dedxCacheTran    488      G4double transitionEnergy = dedxCacheTransitionEnergy;
489                                                   489 
490      if(transitionEnergy > kineticEnergy) {       490      if(transitionEnergy > kineticEnergy) {
491                                                   491 
492         dEdx = (*iter) -> GetDEDX(particle, ma    492         dEdx = (*iter) -> GetDEDX(particle, material, kineticEnergy);
493                                                   493 
494         G4double dEdxDeltaRays = DeltaRayMeanE    494         G4double dEdxDeltaRays = DeltaRayMeanEnergyTransferRate(material,
495                                            par    495                                            particle,
496                                            kin    496                                            kineticEnergy,
497                                            cut    497                                            cutEnergy);
498         dEdx -= dEdxDeltaRays;                    498         dEdx -= dEdxDeltaRays;
499      }                                            499      }
500      else {                                       500      else {
501         G4double massRatio = dedxCacheGenIonMa    501         G4double massRatio = dedxCacheGenIonMassRatio;
502                                                   502 
503         G4double chargeSquare =                   503         G4double chargeSquare =
504                        GetChargeSquareRatio(pa    504                        GetChargeSquareRatio(particle, material, kineticEnergy);
505                                                   505 
506         G4double scaledKineticEnergy = kinetic    506         G4double scaledKineticEnergy = kineticEnergy * massRatio;
507         G4double scaledTransitionEnergy = tran    507         G4double scaledTransitionEnergy = transitionEnergy * massRatio;
508                                                   508 
509         G4double lowEnergyLimit = betheBlochMo    509         G4double lowEnergyLimit = betheBlochModel -> LowEnergyLimit();
510                                                   510 
511         if(scaledTransitionEnergy >= lowEnergy    511         if(scaledTransitionEnergy >= lowEnergyLimit) {
512                                                   512 
513            dEdx = betheBlochModel -> ComputeDE    513            dEdx = betheBlochModel -> ComputeDEDXPerVolume(
514                                       material    514                                       material, genericIon,
515                   scaledKineticEnergy, cutEner    515                   scaledKineticEnergy, cutEnergy);
516                                                   516 
517            dEdx *= chargeSquare;                  517            dEdx *= chargeSquare;
518                                                   518 
519            dEdx += corrections -> ComputeIonCo    519            dEdx += corrections -> ComputeIonCorrections(particle,
520                                                   520                                                  material, kineticEnergy);
521                                                   521 
522            G4double factor = 1.0 + dedxCacheTr    522            G4double factor = 1.0 + dedxCacheTransitionFactor /
523                                                   523                                                            kineticEnergy;
524                                                   524 
525      dEdx *= factor;                              525      dEdx *= factor;
526   }                                               526   }
527      }                                            527      }
528   }                                               528   }
529   else {                                          529   else {
530      G4double massRatio = 1.0;                    530      G4double massRatio = 1.0;
531      G4double chargeSquare = 1.0;                 531      G4double chargeSquare = 1.0;
532                                                   532 
533      if(particle != genericIon) {                 533      if(particle != genericIon) {
534                                                   534 
535         chargeSquare = GetChargeSquareRatio(pa    535         chargeSquare = GetChargeSquareRatio(particle, material, kineticEnergy);
536         massRatio = genericIonPDGMass / partic    536         massRatio = genericIonPDGMass / particle -> GetPDGMass();
537      }                                            537      }
538                                                   538 
539      G4double scaledKineticEnergy = kineticEne    539      G4double scaledKineticEnergy = kineticEnergy * massRatio;
540                                                   540 
541      G4double lowEnergyLimit = betheBlochModel    541      G4double lowEnergyLimit = betheBlochModel -> LowEnergyLimit();
542      if(scaledKineticEnergy < lowEnergyLimit)     542      if(scaledKineticEnergy < lowEnergyLimit) {
543         dEdx = braggIonModel -> ComputeDEDXPer    543         dEdx = braggIonModel -> ComputeDEDXPerVolume(
544                                       material    544                                       material, genericIon,
545                   scaledKineticEnergy, cutEner    545                   scaledKineticEnergy, cutEnergy);
546                                                   546 
547         dEdx *= chargeSquare;                     547         dEdx *= chargeSquare;
548      }                                            548      }
549      else {                                       549      else {
550         G4double dEdxLimitParam = braggIonMode    550         G4double dEdxLimitParam = braggIonModel -> ComputeDEDXPerVolume(
551                                       material    551                                       material, genericIon,
552                   lowEnergyLimit, cutEnergy);     552                   lowEnergyLimit, cutEnergy);
553                                                   553 
554         G4double dEdxLimitBetheBloch = betheBl    554         G4double dEdxLimitBetheBloch = betheBlochModel -> ComputeDEDXPerVolume(
555                                       material    555                                       material, genericIon,
556                   lowEnergyLimit, cutEnergy);     556                   lowEnergyLimit, cutEnergy);
557                                                   557 
558         if(particle != genericIon) {              558         if(particle != genericIon) {
559            G4double chargeSquareLowEnergyLimit    559            G4double chargeSquareLowEnergyLimit =
560                GetChargeSquareRatio(particle,     560                GetChargeSquareRatio(particle, material,
561                                     lowEnergyL    561                                     lowEnergyLimit / massRatio);
562                                                   562 
563            dEdxLimitParam *= chargeSquareLowEn    563            dEdxLimitParam *= chargeSquareLowEnergyLimit;
564            dEdxLimitBetheBloch *= chargeSquare    564            dEdxLimitBetheBloch *= chargeSquareLowEnergyLimit;
565                                                   565 
566            dEdxLimitBetheBloch +=                 566            dEdxLimitBetheBloch +=
567                     corrections -> ComputeIonC    567                     corrections -> ComputeIonCorrections(particle,
568                                       material    568                                       material, lowEnergyLimit / massRatio);
569         }                                         569         }
570                                                   570 
571         G4double factor = (1.0 + (dEdxLimitPar    571         G4double factor = (1.0 + (dEdxLimitParam/dEdxLimitBetheBloch - 1.0)
572                                * lowEnergyLimi    572                                * lowEnergyLimit / scaledKineticEnergy);
573                                                   573 
574         dEdx = betheBlochModel -> ComputeDEDXP    574         dEdx = betheBlochModel -> ComputeDEDXPerVolume(
575                                       material    575                                       material, genericIon,
576                   scaledKineticEnergy, cutEner    576                   scaledKineticEnergy, cutEnergy);
577                                                   577 
578         dEdx *= chargeSquare;                     578         dEdx *= chargeSquare;
579                                                   579 
580         if(particle != genericIon) {              580         if(particle != genericIon) {
581            dEdx += corrections -> ComputeIonCo    581            dEdx += corrections -> ComputeIonCorrections(particle,
582                                       material    582                                       material, kineticEnergy);
583         }                                         583         }
584                                                   584 
585         dEdx *= factor;                           585         dEdx *= factor;
586      }                                            586      }
587                                                   587 
588   }                                               588   }
589                                                   589 
590   if (dEdx < 0.0) dEdx = 0.0;                     590   if (dEdx < 0.0) dEdx = 0.0;
591                                                   591 
592   return dEdx;                                    592   return dEdx;
593 }                                                 593 }
594                                                   594 
595 // ###########################################    595 // #########################################################################
596                                                   596 
597 void G4IonParametrisedLossModel::PrintDEDXTabl    597 void G4IonParametrisedLossModel::PrintDEDXTable(
598                    const G4ParticleDefinition*    598                    const G4ParticleDefinition* particle,  // Projectile (ion)
599                    const G4Material* material,    599                    const G4Material* material,  // Absorber material
600                    G4double lowerBoundary,        600                    G4double lowerBoundary,      // Minimum energy per nucleon
601                    G4double upperBoundary,        601                    G4double upperBoundary,      // Maximum energy per nucleon
602                    G4int numBins,                 602                    G4int numBins,               // Number of bins
603                    G4bool logScaleEnergy) {       603                    G4bool logScaleEnergy) {     // Logarithmic scaling of energy
604                                                   604 
605   G4double atomicMassNumber = particle -> GetA    605   G4double atomicMassNumber = particle -> GetAtomicMass();
606   G4double materialDensity = material -> GetDe    606   G4double materialDensity = material -> GetDensity();
607                                                   607 
608   G4cout << "# dE/dx table for " << particle -    608   G4cout << "# dE/dx table for " << particle -> GetParticleName()
609          << " in material " << material -> Get    609          << " in material " << material -> GetName()
610          << " of density " << materialDensity     610          << " of density " << materialDensity / g * cm3
611          << " g/cm3"                              611          << " g/cm3"
612          << G4endl                                612          << G4endl
613          << "# Projectile mass number A1 = " <    613          << "# Projectile mass number A1 = " << atomicMassNumber
614          << G4endl                                614          << G4endl
615          << "# -------------------------------    615          << "# ------------------------------------------------------"
616          << G4endl;                               616          << G4endl;
617   G4cout << "#"                                   617   G4cout << "#"
618          << std::setw(13) << std::right << "E"    618          << std::setw(13) << std::right << "E"
619          << std::setw(14) << "E/A1"               619          << std::setw(14) << "E/A1"
620          << std::setw(14) << "dE/dx"              620          << std::setw(14) << "dE/dx"
621          << std::setw(14) << "1/rho*dE/dx"        621          << std::setw(14) << "1/rho*dE/dx"
622          << G4endl;                               622          << G4endl;
623   G4cout << "#"                                   623   G4cout << "#"
624          << std::setw(13) << std::right << "(M    624          << std::setw(13) << std::right << "(MeV)"
625          << std::setw(14) << "(MeV)"              625          << std::setw(14) << "(MeV)"
626          << std::setw(14) << "(MeV/cm)"           626          << std::setw(14) << "(MeV/cm)"
627          << std::setw(14) << "(MeV*cm2/mg)"       627          << std::setw(14) << "(MeV*cm2/mg)"
628          << G4endl                                628          << G4endl
629          << "# -------------------------------    629          << "# ------------------------------------------------------"
630          << G4endl;                               630          << G4endl;
631                                                   631 
632   G4double energyLowerBoundary = lowerBoundary    632   G4double energyLowerBoundary = lowerBoundary * atomicMassNumber;
633   G4double energyUpperBoundary = upperBoundary    633   G4double energyUpperBoundary = upperBoundary * atomicMassNumber;
634                                                   634 
635   if(logScaleEnergy) {                            635   if(logScaleEnergy) {
636                                                   636 
637      energyLowerBoundary = std::log(energyLowe    637      energyLowerBoundary = std::log(energyLowerBoundary);
638      energyUpperBoundary = std::log(energyUppe    638      energyUpperBoundary = std::log(energyUpperBoundary);
639   }                                               639   }
640                                                   640 
641   G4double deltaEnergy = (energyUpperBoundary     641   G4double deltaEnergy = (energyUpperBoundary - energyLowerBoundary) /
642                                                   642                                                            G4double(nmbBins);
643                                                   643 
644   for(int i = 0; i < numBins + 1; i++) {          644   for(int i = 0; i < numBins + 1; i++) {
645                                                   645 
646       G4double energy = energyLowerBoundary +     646       G4double energy = energyLowerBoundary + i * deltaEnergy;
647       if(logScaleEnergy) energy = G4Exp(energy    647       if(logScaleEnergy) energy = G4Exp(energy);
648                                                   648 
649       G4double dedx = ComputeDEDXPerVolume(mat    649       G4double dedx = ComputeDEDXPerVolume(material, particle, energy, DBL_MAX);
650       G4cout.precision(6);                        650       G4cout.precision(6);
651       G4cout << std::setw(14) << std::right <<    651       G4cout << std::setw(14) << std::right << energy / MeV
652              << std::setw(14) << energy / atom    652              << std::setw(14) << energy / atomicMassNumber / MeV
653              << std::setw(14) << dedx / MeV *     653              << std::setw(14) << dedx / MeV * cm
654              << std::setw(14) << dedx / materi    654              << std::setw(14) << dedx / materialDensity / (MeV*cm2/(0.001*g))
655              << G4endl;                           655              << G4endl;
656   }                                               656   }
657 }                                                 657 }
658                                                   658 
659 // ###########################################    659 // #########################################################################
660                                                   660 
661 void G4IonParametrisedLossModel::PrintDEDXTabl    661 void G4IonParametrisedLossModel::PrintDEDXTableHandlers(
662                    const G4ParticleDefinition*    662                    const G4ParticleDefinition* particle,  // Projectile (ion)
663                    const G4Material* material,    663                    const G4Material* material,  // Absorber material
664                    G4double lowerBoundary,        664                    G4double lowerBoundary,      // Minimum energy per nucleon
665                    G4double upperBoundary,        665                    G4double upperBoundary,      // Maximum energy per nucleon
666                    G4int numBins,                 666                    G4int numBins,               // Number of bins
667                    G4bool logScaleEnergy) {       667                    G4bool logScaleEnergy) {     // Logarithmic scaling of energy
668                                                   668 
669   LossTableList::iterator iter = lossTableList    669   LossTableList::iterator iter = lossTableList.begin();
670   LossTableList::iterator iter_end = lossTable    670   LossTableList::iterator iter_end = lossTableList.end();
671                                                   671 
672   for(;iter != iter_end; iter++) {                672   for(;iter != iter_end; iter++) {
673       G4bool isApplicable =  (*iter) -> IsAppl    673       G4bool isApplicable =  (*iter) -> IsApplicable(particle, material);
674       if(isApplicable) {                          674       if(isApplicable) {
675   (*iter) -> PrintDEDXTable(particle, material    675   (*iter) -> PrintDEDXTable(particle, material,
676                                   lowerBoundar    676                                   lowerBoundary, upperBoundary,
677                                   numBins,logS    677                                   numBins,logScaleEnergy);
678         break;                                    678         break;
679       }                                           679       }
680   }                                               680   }
681 }                                                 681 }
682                                                   682 
683 // ###########################################    683 // #########################################################################
684                                                   684 
685 void G4IonParametrisedLossModel::SampleSeconda    685 void G4IonParametrisedLossModel::SampleSecondaries(
686                              std::vector<G4Dyn    686                              std::vector<G4DynamicParticle*>* secondaries,
687            const G4MaterialCutsCouple* couple,    687            const G4MaterialCutsCouple* couple,
688            const G4DynamicParticle* particle,     688            const G4DynamicParticle* particle,
689            G4double cutKinEnergySec,              689            G4double cutKinEnergySec,
690            G4double userMaxKinEnergySec) {        690            G4double userMaxKinEnergySec) {
691   // ############## Sampling of secondaries ##    691   // ############## Sampling of secondaries #################################
692   // The probability density function (pdf) of    692   // The probability density function (pdf) of the kinetic energy T of a
693   // secondary electron may be written as:        693   // secondary electron may be written as:
694   //    pdf(T) = f(T) * g(T)                      694   //    pdf(T) = f(T) * g(T)
695   // where                                        695   // where
696   //    f(T) = (Tmax - Tcut) / (Tmax * Tcut) *    696   //    f(T) = (Tmax - Tcut) / (Tmax * Tcut) * (1 / T^2)
697   //    g(T) = 1 - beta^2 * T / Tmax              697   //    g(T) = 1 - beta^2 * T / Tmax
698   // where Tmax is the maximum kinetic energy     698   // where Tmax is the maximum kinetic energy of the secondary, Tcut
699   // is the lower energy cut and beta is the k    699   // is the lower energy cut and beta is the kinetic energy of the
700   // projectile.                                  700   // projectile.
701   //                                              701   //
702   // Sampling of the kinetic energy of a secon    702   // Sampling of the kinetic energy of a secondary electron:
703   //  1) T0 is sampled from f(T) using the cum    703   //  1) T0 is sampled from f(T) using the cumulated distribution function
704   //     F(T) = int_Tcut^T f(T')dT'               704   //     F(T) = int_Tcut^T f(T')dT'
705   //  2) T is accepted or rejected by evaluati    705   //  2) T is accepted or rejected by evaluating the rejection function g(T)
706   //     at the sampled energy T0 against a ra    706   //     at the sampled energy T0 against a randomly sampled value
707   //                                              707   //
708   //                                              708   //
709   // See Geant4 physics reference manual (vers    709   // See Geant4 physics reference manual (version 9.1), section 9.1.4
710   //                                              710   //
711   //                                              711   //
712   // Reference pdf: W.M. Yao et al, Jour. of P    712   // Reference pdf: W.M. Yao et al, Jour. of Phys. G 33 (2006) 1.
713   //                                              713   //
714   // (Implementation adapted from G4BraggIonMo    714   // (Implementation adapted from G4BraggIonModel)
715                                                   715 
716   G4double rossiMaxKinEnergySec = MaxSecondary    716   G4double rossiMaxKinEnergySec = MaxSecondaryKinEnergy(particle);
717   G4double maxKinEnergySec =                      717   G4double maxKinEnergySec =
718                         std::min(rossiMaxKinEn    718                         std::min(rossiMaxKinEnergySec, userMaxKinEnergySec);
719                                                   719 
720   if(cutKinEnergySec >= maxKinEnergySec) retur    720   if(cutKinEnergySec >= maxKinEnergySec) return;
721                                                   721 
722   G4double kineticEnergy = particle -> GetKine    722   G4double kineticEnergy = particle -> GetKineticEnergy();
723                                                   723 
724   G4double energy  = kineticEnergy + cacheMass    724   G4double energy  = kineticEnergy + cacheMass;
725   G4double betaSquared = kineticEnergy * (ener    725   G4double betaSquared = kineticEnergy * (energy + cacheMass)
726     / (energy * energy);                          726     / (energy * energy);
727                                                   727 
728   G4double kinEnergySec;                          728   G4double kinEnergySec;
729   G4double grej;                                  729   G4double grej;
730                                                   730 
731   do {                                            731   do {
732                                                   732 
733     // Sampling kinetic energy from f(T) (usin    733     // Sampling kinetic energy from f(T) (using F(T)):
734     G4double xi = G4UniformRand();                734     G4double xi = G4UniformRand();
735     kinEnergySec = cutKinEnergySec * maxKinEne    735     kinEnergySec = cutKinEnergySec * maxKinEnergySec /
736                         (maxKinEnergySec * (1.    736                         (maxKinEnergySec * (1.0 - xi) + cutKinEnergySec * xi);
737                                                   737 
738     // Deriving the value of the rejection fun    738     // Deriving the value of the rejection function at the obtained kinetic
739     // energy:                                    739     // energy:
740     grej = 1.0 - betaSquared * kinEnergySec /     740     grej = 1.0 - betaSquared * kinEnergySec / rossiMaxKinEnergySec;
741                                                   741 
742     if(grej > 1.0) {                              742     if(grej > 1.0) {
743         G4cout << "G4IonParametrisedLossModel:    743         G4cout << "G4IonParametrisedLossModel::SampleSecondary Warning: "
744                << "Majorant 1.0 < "               744                << "Majorant 1.0 < "
745                << grej << " for e= " << kinEne    745                << grej << " for e= " << kinEnergySec
746                << G4endl;                         746                << G4endl;
747     }                                             747     }
748                                                   748 
749   } while( G4UniformRand() >= grej );             749   } while( G4UniformRand() >= grej );
750                                                   750 
751   const G4Material* mat =  couple->GetMaterial    751   const G4Material* mat =  couple->GetMaterial();
752   G4int Z = SelectRandomAtomNumber(mat);          752   G4int Z = SelectRandomAtomNumber(mat);
753                                                   753 
754   const G4ParticleDefinition* electron = G4Ele    754   const G4ParticleDefinition* electron = G4Electron::Electron();
755                                                   755 
756   G4DynamicParticle* delta = new G4DynamicPart    756   G4DynamicParticle* delta = new G4DynamicParticle(electron,
757     GetAngularDistribution()->SampleDirection(    757     GetAngularDistribution()->SampleDirection(particle, kinEnergySec,
758                                                   758                                               Z, mat),
759                                                   759                                                    kinEnergySec);
760                                                   760 
761   secondaries->push_back(delta);                  761   secondaries->push_back(delta);
762                                                   762 
763   // Change kinematics of primary particle        763   // Change kinematics of primary particle
764   G4ThreeVector direction = particle ->GetMome    764   G4ThreeVector direction = particle ->GetMomentumDirection();
765   G4double totalMomentum = std::sqrt(kineticEn    765   G4double totalMomentum = std::sqrt(kineticEnergy*(energy + cacheMass));
766                                                   766 
767   G4ThreeVector finalP = totalMomentum*directi    767   G4ThreeVector finalP = totalMomentum*direction - delta->GetMomentum();
768   finalP               = finalP.unit();           768   finalP               = finalP.unit();
769                                                   769 
770   kineticEnergy       -= kinEnergySec;            770   kineticEnergy       -= kinEnergySec;
771                                                   771 
772   particleChangeLoss->SetProposedKineticEnergy    772   particleChangeLoss->SetProposedKineticEnergy(kineticEnergy);
773   particleChangeLoss->SetProposedMomentumDirec    773   particleChangeLoss->SetProposedMomentumDirection(finalP);
774 }                                                 774 }
775                                                   775 
776 // ###########################################    776 // #########################################################################
777                                                   777 
778 void G4IonParametrisedLossModel::UpdateRangeCa    778 void G4IonParametrisedLossModel::UpdateRangeCache(
779                      const G4ParticleDefinitio    779                      const G4ParticleDefinition* particle,
780                      const G4MaterialCutsCoupl    780                      const G4MaterialCutsCouple* matCutsCouple) {
781                                                   781 
782   // ############## Caching ##################    782   // ############## Caching ##################################################
783   // If the ion-material-cut combination is co    783   // If the ion-material-cut combination is covered by any native ion data
784   // parameterisation (for low energies), rang    784   // parameterisation (for low energies), range vectors are computed
785                                                   785 
786   if(particle == rangeCacheParticle &&            786   if(particle == rangeCacheParticle &&
787      matCutsCouple == rangeCacheMatCutsCouple)    787      matCutsCouple == rangeCacheMatCutsCouple) {
788   }                                               788   }
789   else{                                           789   else{
790      rangeCacheParticle = particle;               790      rangeCacheParticle = particle;
791      rangeCacheMatCutsCouple = matCutsCouple;     791      rangeCacheMatCutsCouple = matCutsCouple;
792                                                   792 
793      const G4Material* material = matCutsCoupl    793      const G4Material* material = matCutsCouple -> GetMaterial();
794      LossTableList::iterator iter = IsApplicab    794      LossTableList::iterator iter = IsApplicable(particle, material);
795                                                   795 
796      // If any table is applicable, the transi    796      // If any table is applicable, the transition factor is computed:
797      if(iter != lossTableList.end()) {            797      if(iter != lossTableList.end()) {
798                                                   798 
799         // Build range-energy and energy-range    799         // Build range-energy and energy-range vectors if they don't exist
800         IonMatCouple ionMatCouple = std::make_    800         IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
801         RangeEnergyTable::iterator iterRange =    801         RangeEnergyTable::iterator iterRange = r.find(ionMatCouple);
802                                                   802 
803         if(iterRange == r.end()) BuildRangeVec    803         if(iterRange == r.end()) BuildRangeVector(particle, matCutsCouple);
804                                                   804 
805         rangeCacheEnergyRange = E[ionMatCouple    805         rangeCacheEnergyRange = E[ionMatCouple];
806         rangeCacheRangeEnergy = r[ionMatCouple    806         rangeCacheRangeEnergy = r[ionMatCouple];
807      }                                            807      }
808      else {                                       808      else {
809         rangeCacheEnergyRange = 0;                809         rangeCacheEnergyRange = 0;
810         rangeCacheRangeEnergy = 0;                810         rangeCacheRangeEnergy = 0;
811      }                                            811      }
812   }                                               812   }
813 }                                                 813 }
814                                                   814 
815 // ###########################################    815 // #########################################################################
816                                                   816 
817 void G4IonParametrisedLossModel::UpdateDEDXCac    817 void G4IonParametrisedLossModel::UpdateDEDXCache(
818                      const G4ParticleDefinitio    818                      const G4ParticleDefinition* particle,
819                      const G4Material* materia    819                      const G4Material* material,
820                      G4double cutEnergy) {        820                      G4double cutEnergy) {
821                                                   821 
822   // ############## Caching ##################    822   // ############## Caching ##################################################
823   // If the ion-material combination is covere    823   // If the ion-material combination is covered by any native ion data
824   // parameterisation (for low energies), a tr    824   // parameterisation (for low energies), a transition factor is computed
825   // which is applied to Bethe-Bloch results a    825   // which is applied to Bethe-Bloch results at higher energies to
826   // guarantee a smooth transition.               826   // guarantee a smooth transition.
827   // This factor only needs to be calculated f    827   // This factor only needs to be calculated for the first step an ion
828   // performs inside a certain material.          828   // performs inside a certain material.
829                                                   829 
830   if(particle == dedxCacheParticle &&             830   if(particle == dedxCacheParticle &&
831      material == dedxCacheMaterial &&             831      material == dedxCacheMaterial &&
832      cutEnergy == dedxCacheEnergyCut) {           832      cutEnergy == dedxCacheEnergyCut) {
833   }                                               833   }
834   else {                                          834   else {
835                                                   835 
836      dedxCacheParticle = particle;                836      dedxCacheParticle = particle;
837      dedxCacheMaterial = material;                837      dedxCacheMaterial = material;
838      dedxCacheEnergyCut = cutEnergy;              838      dedxCacheEnergyCut = cutEnergy;
839                                                   839 
840      G4double massRatio = genericIonPDGMass /     840      G4double massRatio = genericIonPDGMass / particle -> GetPDGMass();
841      dedxCacheGenIonMassRatio = massRatio;        841      dedxCacheGenIonMassRatio = massRatio;
842                                                   842 
843      LossTableList::iterator iter = IsApplicab    843      LossTableList::iterator iter = IsApplicable(particle, material);
844      dedxCacheIter = iter;                        844      dedxCacheIter = iter;
845                                                   845 
846      // If any table is applicable, the transi    846      // If any table is applicable, the transition factor is computed:
847      if(iter != lossTableList.end()) {            847      if(iter != lossTableList.end()) {
848                                                   848 
849         // Retrieving the transition energy fr    849         // Retrieving the transition energy from the parameterisation table
850         G4double transitionEnergy =               850         G4double transitionEnergy =
851                  (*iter) -> GetUpperEnergyEdge    851                  (*iter) -> GetUpperEnergyEdge(particle, material);
852         dedxCacheTransitionEnergy = transition    852         dedxCacheTransitionEnergy = transitionEnergy;
853                                                   853 
854         // Computing dE/dx from low-energy par    854         // Computing dE/dx from low-energy parameterisation at
855         // transition energy                      855         // transition energy
856         G4double dEdxParam = (*iter) -> GetDED    856         G4double dEdxParam = (*iter) -> GetDEDX(particle, material,
857                                            tra    857                                            transitionEnergy);
858                                                   858 
859         G4double dEdxDeltaRays = DeltaRayMeanE    859         G4double dEdxDeltaRays = DeltaRayMeanEnergyTransferRate(material,
860                                            par    860                                            particle,
861                                            tra    861                                            transitionEnergy,
862                                            cut    862                                            cutEnergy);
863         dEdxParam -= dEdxDeltaRays;               863         dEdxParam -= dEdxDeltaRays;
864                                                   864 
865         // Computing dE/dx from Bethe-Bloch fo    865         // Computing dE/dx from Bethe-Bloch formula at transition
866         // energy                                 866         // energy
867         G4double transitionChargeSquare =         867         G4double transitionChargeSquare =
868               GetChargeSquareRatio(particle, m    868               GetChargeSquareRatio(particle, material, transitionEnergy);
869                                                   869 
870         G4double scaledTransitionEnergy = tran    870         G4double scaledTransitionEnergy = transitionEnergy * massRatio;
871                                                   871 
872         G4double dEdxBetheBloch =                 872         G4double dEdxBetheBloch =
873                            betheBlochModel ->     873                            betheBlochModel -> ComputeDEDXPerVolume(
874                                         materi    874                                         material, genericIon,
875                     scaledTransitionEnergy, cu    875                     scaledTransitionEnergy, cutEnergy);
876         dEdxBetheBloch *= transitionChargeSqua    876         dEdxBetheBloch *= transitionChargeSquare;
877                                                   877 
878         // Additionally, high order correction    878         // Additionally, high order corrections are added
879         dEdxBetheBloch +=                         879         dEdxBetheBloch +=
880             corrections -> ComputeIonCorrectio    880             corrections -> ComputeIonCorrections(particle,
881                                                   881                                                  material, transitionEnergy);
882                                                   882 
883         // Computing transition factor from bo    883         // Computing transition factor from both dE/dx values
884         dedxCacheTransitionFactor =               884         dedxCacheTransitionFactor =
885                      (dEdxParam - dEdxBetheBlo    885                      (dEdxParam - dEdxBetheBloch)/dEdxBetheBloch
886                              * transitionEnerg    886                              * transitionEnergy;
887      }                                            887      }
888      else {                                       888      else {
889                                                   889 
890         dedxCacheParticle = particle;             890         dedxCacheParticle = particle;
891         dedxCacheMaterial = material;             891         dedxCacheMaterial = material;
892         dedxCacheEnergyCut = cutEnergy;           892         dedxCacheEnergyCut = cutEnergy;
893                                                   893 
894         dedxCacheGenIonMassRatio =                894         dedxCacheGenIonMassRatio =
895                              genericIonPDGMass    895                              genericIonPDGMass / particle -> GetPDGMass();
896                                                   896 
897         dedxCacheTransitionEnergy = 0.0;          897         dedxCacheTransitionEnergy = 0.0;
898         dedxCacheTransitionFactor = 0.0;          898         dedxCacheTransitionFactor = 0.0;
899      }                                            899      }
900   }                                               900   }
901 }                                                 901 }
902                                                   902 
903 // ###########################################    903 // #########################################################################
904                                                   904 
905 void G4IonParametrisedLossModel::CorrectionsAl    905 void G4IonParametrisedLossModel::CorrectionsAlongStep(
906                              const G4MaterialC    906                              const G4MaterialCutsCouple* couple,
907            const G4DynamicParticle* dynamicPar    907            const G4DynamicParticle* dynamicParticle,
908                              const G4double& l    908                              const G4double& length,
909            G4double& eloss) {                     909            G4double& eloss) {
910                                                   910 
911   // ############## Corrections for along step    911   // ############## Corrections for along step energy loss calculation ######
912   // The computed energy loss (due to electron    912   // The computed energy loss (due to electronic stopping) is overwritten
913   // by this function if an ion data parameter    913   // by this function if an ion data parameterization is available for the
914   // current ion-material pair.                   914   // current ion-material pair.
915   // No action on the energy loss (due to elec    915   // No action on the energy loss (due to electronic stopping) is performed
916   // if no parameterization is available. In t    916   // if no parameterization is available. In this case the original
917   // generic ion tables (in combination with t    917   // generic ion tables (in combination with the effective charge) are used
918   // in the along step DoIt function.             918   // in the along step DoIt function.
919   //                                              919   //
920   //                                              920   //
921   // (Implementation partly adapted from G4Bra    921   // (Implementation partly adapted from G4BraggIonModel/G4BetheBlochModel)
922                                                   922 
923   const G4ParticleDefinition* particle = dynam    923   const G4ParticleDefinition* particle = dynamicParticle -> GetDefinition();
924   const G4Material* material = couple -> GetMa    924   const G4Material* material = couple -> GetMaterial();
925                                                   925 
926   G4double kineticEnergy = dynamicParticle ->     926   G4double kineticEnergy = dynamicParticle -> GetKineticEnergy();
927                                                   927 
928   if(kineticEnergy == eloss) { return; }          928   if(kineticEnergy == eloss) { return; }
929                                                   929 
930   G4double cutEnergy = DBL_MAX;                   930   G4double cutEnergy = DBL_MAX;
931   std::size_t cutIndex = couple -> GetIndex(); << 931   size_t cutIndex = couple -> GetIndex();
932   cutEnergy = cutEnergies[cutIndex];              932   cutEnergy = cutEnergies[cutIndex];
933                                                   933 
934   UpdateDEDXCache(particle, material, cutEnerg    934   UpdateDEDXCache(particle, material, cutEnergy);
935                                                   935 
936   LossTableList::iterator iter = dedxCacheIter    936   LossTableList::iterator iter = dedxCacheIter;
937                                                   937 
938   // If parameterization for ions is available    938   // If parameterization for ions is available the electronic energy loss
939   // is overwritten                               939   // is overwritten
940   if(iter != lossTableList.end()) {               940   if(iter != lossTableList.end()) {
941                                                   941 
942      // The energy loss is calculated using th    942      // The energy loss is calculated using the ComputeDEDXPerVolume function
943      // and the step length (it is assumed tha    943      // and the step length (it is assumed that dE/dx does not change
944      // considerably along the step)              944      // considerably along the step)
945      eloss =                                      945      eloss =
946         length * ComputeDEDXPerVolume(material    946         length * ComputeDEDXPerVolume(material, particle,
947                                       kineticE    947                                       kineticEnergy, cutEnergy);
948                                                   948 
949 #ifdef PRINT_DEBUG                                949 #ifdef PRINT_DEBUG
950   G4cout.precision(6);                            950   G4cout.precision(6);
951   G4cout << "#################################    951   G4cout << "########################################################"
952          << G4endl                                952          << G4endl
953          << "# G4IonParametrisedLossModel::Cor    953          << "# G4IonParametrisedLossModel::CorrectionsAlongStep"
954          << G4endl                                954          << G4endl
955          << "# cut(MeV) = " << cutEnergy/MeV      955          << "# cut(MeV) = " << cutEnergy/MeV
956          << G4endl;                               956          << G4endl;
957                                                   957 
958   G4cout << "#"                                   958   G4cout << "#"
959          << std::setw(13) << std::right << "E(    959          << std::setw(13) << std::right << "E(MeV)"
960          << std::setw(14) << "l(um)"              960          << std::setw(14) << "l(um)"
961          << std::setw(14) << "l*dE/dx(MeV)"       961          << std::setw(14) << "l*dE/dx(MeV)"
962          << std::setw(14) << "(l*dE/dx)/E"        962          << std::setw(14) << "(l*dE/dx)/E"
963          << G4endl                                963          << G4endl
964          << "# -------------------------------    964          << "# ------------------------------------------------------"
965          << G4endl;                               965          << G4endl;
966                                                   966 
967   G4cout << std::setw(14) << std::right << kin    967   G4cout << std::setw(14) << std::right << kineticEnergy / MeV
968          << std::setw(14) << length / um          968          << std::setw(14) << length / um
969          << std::setw(14) << eloss / MeV          969          << std::setw(14) << eloss / MeV
970          << std::setw(14) << eloss / kineticEn    970          << std::setw(14) << eloss / kineticEnergy * 100.0
971          << G4endl;                               971          << G4endl;
972 #endif                                            972 #endif
973                                                   973 
974      // If the energy loss exceeds a certain f    974      // If the energy loss exceeds a certain fraction of the kinetic energy
975      // (the fraction is indicated by the para    975      // (the fraction is indicated by the parameter "energyLossLimit") then
976      // the range tables are used to derive a     976      // the range tables are used to derive a more accurate value of the
977      // energy loss                               977      // energy loss
978      if(eloss > energyLossLimit * kineticEnerg    978      if(eloss > energyLossLimit * kineticEnergy) {
979                                                   979 
980         eloss = ComputeLossForStep(couple, par    980         eloss = ComputeLossForStep(couple, particle,
981                                    kineticEner    981                                    kineticEnergy,length);
982                                                   982 
983 #ifdef PRINT_DEBUG                                983 #ifdef PRINT_DEBUG
984   G4cout << "# Correction applied:"               984   G4cout << "# Correction applied:"
985          << G4endl;                               985          << G4endl;
986                                                   986 
987   G4cout << std::setw(14) << std::right << kin    987   G4cout << std::setw(14) << std::right << kineticEnergy / MeV
988          << std::setw(14) << length / um          988          << std::setw(14) << length / um
989          << std::setw(14) << eloss / MeV          989          << std::setw(14) << eloss / MeV
990          << std::setw(14) << eloss / kineticEn    990          << std::setw(14) << eloss / kineticEnergy * 100.0
991          << G4endl;                               991          << G4endl;
992 #endif                                            992 #endif
993                                                   993 
994      }                                            994      }
995   }                                               995   }
996                                                   996 
997   // For all corrections below a kinetic energ    997   // For all corrections below a kinetic energy between the Pre- and
998   // Post-step energy values is used              998   // Post-step energy values is used
999   G4double energy = kineticEnergy - eloss * 0.    999   G4double energy = kineticEnergy - eloss * 0.5;
1000   if(energy < 0.0) energy = kineticEnergy * 0    1000   if(energy < 0.0) energy = kineticEnergy * 0.5;
1001                                                  1001 
1002   G4double chargeSquareRatio = corrections ->    1002   G4double chargeSquareRatio = corrections ->
1003                                      Effectiv    1003                                      EffectiveChargeSquareRatio(particle,
1004                                                  1004                                                                 material,
1005                                                  1005                                                                 energy);
1006   GetModelOfFluctuations() -> SetParticleAndC    1006   GetModelOfFluctuations() -> SetParticleAndCharge(particle,
1007                                                  1007                                                    chargeSquareRatio);
1008                                                  1008 
1009   // A correction is applied considering the     1009   // A correction is applied considering the change of the effective charge
1010   // along the step (the parameter "corrFacto    1010   // along the step (the parameter "corrFactor" refers to the effective
1011   // charge at the beginning of the step). No    1011   // charge at the beginning of the step). Note: the correction is not
1012   // applied for energy loss values deriving     1012   // applied for energy loss values deriving directly from parameterized
1013   // ion stopping power tables                   1013   // ion stopping power tables
1014   G4double transitionEnergy = dedxCacheTransi    1014   G4double transitionEnergy = dedxCacheTransitionEnergy;
1015                                                  1015 
1016   if(iter != lossTableList.end() && transitio    1016   if(iter != lossTableList.end() && transitionEnergy < kineticEnergy) {
1017      chargeSquareRatio *= corrections -> Effe    1017      chargeSquareRatio *= corrections -> EffectiveChargeCorrection(particle,
1018                                                  1018                                                                 material,
1019                                                  1019                                                                 energy);
1020                                                  1020 
1021      G4double chargeSquareRatioCorr = chargeS    1021      G4double chargeSquareRatioCorr = chargeSquareRatio/corrFactor;
1022      eloss *= chargeSquareRatioCorr;             1022      eloss *= chargeSquareRatioCorr;
1023   }                                              1023   }
1024   else if (iter == lossTableList.end()) {        1024   else if (iter == lossTableList.end()) {
1025                                                  1025 
1026      chargeSquareRatio *= corrections -> Effe    1026      chargeSquareRatio *= corrections -> EffectiveChargeCorrection(particle,
1027                                                  1027                                                                 material,
1028                                                  1028                                                                 energy);
1029                                                  1029 
1030      G4double chargeSquareRatioCorr = chargeS    1030      G4double chargeSquareRatioCorr = chargeSquareRatio/corrFactor;
1031      eloss *= chargeSquareRatioCorr;             1031      eloss *= chargeSquareRatioCorr;
1032   }                                              1032   }
1033                                                  1033 
1034   // Ion high order corrections are applied i    1034   // Ion high order corrections are applied if the current model does not
1035   // overwrite the energy loss (i.e. when the    1035   // overwrite the energy loss (i.e. when the effective charge approach is
1036   // used)                                       1036   // used)
1037   if(iter == lossTableList.end()) {              1037   if(iter == lossTableList.end()) {
1038                                                  1038 
1039      G4double scaledKineticEnergy = kineticEn    1039      G4double scaledKineticEnergy = kineticEnergy * dedxCacheGenIonMassRatio;
1040      G4double lowEnergyLimit = betheBlochMode    1040      G4double lowEnergyLimit = betheBlochModel -> LowEnergyLimit();
1041                                                  1041 
1042      // Corrections are only applied in the B    1042      // Corrections are only applied in the Bethe-Bloch energy region
1043      if(scaledKineticEnergy > lowEnergyLimit)    1043      if(scaledKineticEnergy > lowEnergyLimit)
1044        eloss += length *                         1044        eloss += length *
1045             corrections -> IonHighOrderCorrec    1045             corrections -> IonHighOrderCorrections(particle, couple, energy);
1046   }                                              1046   }
1047 }                                                1047 }
1048                                                  1048 
1049 // ##########################################    1049 // #########################################################################
1050                                                  1050 
1051 void G4IonParametrisedLossModel::BuildRangeVe    1051 void G4IonParametrisedLossModel::BuildRangeVector(
1052                      const G4ParticleDefiniti    1052                      const G4ParticleDefinition* particle,
1053                      const G4MaterialCutsCoup    1053                      const G4MaterialCutsCouple* matCutsCouple) {
1054                                                  1054 
1055   G4double cutEnergy = DBL_MAX;                  1055   G4double cutEnergy = DBL_MAX;
1056   std::size_t cutIndex = matCutsCouple -> Get << 1056   size_t cutIndex = matCutsCouple -> GetIndex();
1057   cutEnergy = cutEnergies[cutIndex];             1057   cutEnergy = cutEnergies[cutIndex];
1058                                                  1058 
1059   const G4Material* material = matCutsCouple     1059   const G4Material* material = matCutsCouple -> GetMaterial();
1060                                                  1060 
1061   G4double massRatio = genericIonPDGMass / pa    1061   G4double massRatio = genericIonPDGMass / particle -> GetPDGMass();
1062                                                  1062 
1063   G4double lowerEnergy = lowerEnergyEdgeInteg    1063   G4double lowerEnergy = lowerEnergyEdgeIntegr / massRatio;
1064   G4double upperEnergy = upperEnergyEdgeInteg    1064   G4double upperEnergy = upperEnergyEdgeIntegr / massRatio;
1065                                                  1065 
1066   G4double logLowerEnergyEdge = std::log(lowe    1066   G4double logLowerEnergyEdge = std::log(lowerEnergy);
1067   G4double logUpperEnergyEdge = std::log(uppe    1067   G4double logUpperEnergyEdge = std::log(upperEnergy);
1068                                                  1068 
1069   G4double logDeltaEnergy = (logUpperEnergyEd    1069   G4double logDeltaEnergy = (logUpperEnergyEdge - logLowerEnergyEdge) /
1070                                                  1070                                                         G4double(nmbBins);
1071                                                  1071 
1072   G4double logDeltaIntegr = logDeltaEnergy /     1072   G4double logDeltaIntegr = logDeltaEnergy / G4double(nmbSubBins);
1073                                                  1073 
1074   G4PhysicsFreeVector* energyRangeVector =       1074   G4PhysicsFreeVector* energyRangeVector =
1075     new G4PhysicsFreeVector(nmbBins+1,           1075     new G4PhysicsFreeVector(nmbBins+1,
1076           lowerEnergy,                           1076           lowerEnergy,
1077           upperEnergy,                           1077           upperEnergy,
1078           /*spline=*/true);                      1078           /*spline=*/true);
1079                                                  1079 
1080   G4double dedxLow = ComputeDEDXPerVolume(mat    1080   G4double dedxLow = ComputeDEDXPerVolume(material,
1081                                           par    1081                                           particle,
1082                                           low    1082                                           lowerEnergy,
1083                                           cut    1083                                           cutEnergy);
1084                                                  1084 
1085   G4double range = 2.0 * lowerEnergy / dedxLo    1085   G4double range = 2.0 * lowerEnergy / dedxLow;
1086                                                  1086 
1087   energyRangeVector -> PutValues(0, lowerEner    1087   energyRangeVector -> PutValues(0, lowerEnergy, range);
1088                                                  1088 
1089   G4double logEnergy = std::log(lowerEnergy);    1089   G4double logEnergy = std::log(lowerEnergy);
1090   for(std::size_t i = 1; i < nmbBins+1; ++i)  << 1090   for(size_t i = 1; i < nmbBins+1; i++) {
1091                                                  1091 
1092       G4double logEnergyIntegr = logEnergy;      1092       G4double logEnergyIntegr = logEnergy;
1093                                                  1093 
1094       for(std::size_t j = 0; j < nmbSubBins;  << 1094       for(size_t j = 0; j < nmbSubBins; j++) {
1095                                                  1095 
1096           G4double binLowerBoundary = G4Exp(l    1096           G4double binLowerBoundary = G4Exp(logEnergyIntegr);
1097           logEnergyIntegr += logDeltaIntegr;     1097           logEnergyIntegr += logDeltaIntegr;
1098                                                  1098 
1099           G4double binUpperBoundary = G4Exp(l    1099           G4double binUpperBoundary = G4Exp(logEnergyIntegr);
1100           G4double deltaIntegr = binUpperBoun    1100           G4double deltaIntegr = binUpperBoundary - binLowerBoundary;
1101                                                  1101 
1102           G4double energyIntegr = binLowerBou    1102           G4double energyIntegr = binLowerBoundary + 0.5 * deltaIntegr;
1103                                                  1103 
1104           G4double dedxValue = ComputeDEDXPer    1104           G4double dedxValue = ComputeDEDXPerVolume(material,
1105                                                  1105                                                     particle,
1106                                                  1106                                                     energyIntegr,
1107                 cutEnergy);                      1107                 cutEnergy);
1108                                                  1108 
1109           if(dedxValue > 0.0) range += deltaI    1109           if(dedxValue > 0.0) range += deltaIntegr / dedxValue;
1110                                                  1110 
1111 #ifdef PRINT_DEBUG_DETAILS                       1111 #ifdef PRINT_DEBUG_DETAILS
1112               G4cout << "   E = "<< energyInt    1112               G4cout << "   E = "<< energyIntegr/MeV
1113                      << " MeV -> dE = " << de    1113                      << " MeV -> dE = " << deltaIntegr/MeV
1114                      << " MeV -> dE/dx = " <<    1114                      << " MeV -> dE/dx = " << dedxValue/MeV*mm
1115                      << " MeV/mm -> dE/(dE/dx    1115                      << " MeV/mm -> dE/(dE/dx) = " << deltaIntegr /
1116                                                  1116                                                                dedxValue / mm
1117                      << " mm -> range = " <<     1117                      << " mm -> range = " << range / mm
1118                      << " mm " << G4endl;        1118                      << " mm " << G4endl;
1119 #endif                                           1119 #endif
1120       }                                          1120       }
1121                                                  1121 
1122       logEnergy += logDeltaEnergy;               1122       logEnergy += logDeltaEnergy;
1123                                                  1123 
1124       G4double energy = G4Exp(logEnergy);        1124       G4double energy = G4Exp(logEnergy);
1125                                                  1125 
1126       energyRangeVector -> PutValues(i, energ    1126       energyRangeVector -> PutValues(i, energy, range);
1127                                                  1127 
1128 #ifdef PRINT_DEBUG_DETAILS                       1128 #ifdef PRINT_DEBUG_DETAILS
1129       G4cout << "G4IonParametrisedLossModel::    1129       G4cout << "G4IonParametrisedLossModel::BuildRangeVector() bin = "
1130              << i <<", E = "                     1130              << i <<", E = "
1131              << energy / MeV << " MeV, R = "     1131              << energy / MeV << " MeV, R = "
1132              << range / mm << " mm"              1132              << range / mm << " mm"
1133              << G4endl;                          1133              << G4endl;
1134 #endif                                           1134 #endif
1135                                                  1135 
1136   }                                              1136   }
1137   //vector is filled: activate spline            1137   //vector is filled: activate spline
1138   energyRangeVector -> FillSecondDerivatives(    1138   energyRangeVector -> FillSecondDerivatives();
1139                                                  1139 
1140   G4double lowerRangeEdge =                      1140   G4double lowerRangeEdge =
1141                     energyRangeVector -> Valu    1141                     energyRangeVector -> Value(lowerEnergy);
1142   G4double upperRangeEdge =                      1142   G4double upperRangeEdge =
1143                     energyRangeVector -> Valu    1143                     energyRangeVector -> Value(upperEnergy);
1144                                                  1144 
1145   G4PhysicsFreeVector* rangeEnergyVector         1145   G4PhysicsFreeVector* rangeEnergyVector
1146     = new G4PhysicsFreeVector(nmbBins+1,         1146     = new G4PhysicsFreeVector(nmbBins+1,
1147             lowerRangeEdge,                      1147             lowerRangeEdge,
1148             upperRangeEdge,                      1148             upperRangeEdge,
1149             /*spline=*/true);                    1149             /*spline=*/true);
1150                                                  1150 
1151   for(std::size_t i = 0; i < nmbBins+1; ++i)  << 1151   for(size_t i = 0; i < nmbBins+1; i++) {
1152       G4double energy = energyRangeVector ->     1152       G4double energy = energyRangeVector -> Energy(i);
1153       rangeEnergyVector ->                       1153       rangeEnergyVector ->
1154              PutValues(i, energyRangeVector -    1154              PutValues(i, energyRangeVector -> Value(energy), energy);
1155   }                                              1155   }
1156                                                  1156 
1157   rangeEnergyVector -> FillSecondDerivatives(    1157   rangeEnergyVector -> FillSecondDerivatives();
1158                                                  1158 
1159 #ifdef PRINT_DEBUG_TABLES                        1159 #ifdef PRINT_DEBUG_TABLES
1160   G4cout << *energyLossVector                    1160   G4cout << *energyLossVector
1161          << *energyRangeVector                   1161          << *energyRangeVector
1162          << *rangeEnergyVector << G4endl;        1162          << *rangeEnergyVector << G4endl;
1163 #endif                                           1163 #endif
1164                                                  1164 
1165   IonMatCouple ionMatCouple = std::make_pair(    1165   IonMatCouple ionMatCouple = std::make_pair(particle, matCutsCouple);
1166                                                  1166 
1167   E[ionMatCouple] = energyRangeVector;           1167   E[ionMatCouple] = energyRangeVector;
1168   r[ionMatCouple] = rangeEnergyVector;           1168   r[ionMatCouple] = rangeEnergyVector;
1169 }                                                1169 }
1170                                                  1170 
1171 // ##########################################    1171 // #########################################################################
1172                                                  1172 
1173 G4double G4IonParametrisedLossModel::ComputeL    1173 G4double G4IonParametrisedLossModel::ComputeLossForStep(
1174                      const G4MaterialCutsCoup    1174                      const G4MaterialCutsCouple* matCutsCouple,
1175                      const G4ParticleDefiniti    1175                      const G4ParticleDefinition* particle,
1176                      G4double kineticEnergy,     1176                      G4double kineticEnergy,
1177                      G4double stepLength) {      1177                      G4double stepLength) {
1178                                                  1178 
1179   G4double loss = 0.0;                           1179   G4double loss = 0.0;
1180                                                  1180 
1181   UpdateRangeCache(particle, matCutsCouple);     1181   UpdateRangeCache(particle, matCutsCouple);
1182                                                  1182 
1183   G4PhysicsVector* energyRange = rangeCacheEn    1183   G4PhysicsVector* energyRange = rangeCacheEnergyRange;
1184   G4PhysicsVector* rangeEnergy = rangeCacheRa    1184   G4PhysicsVector* rangeEnergy = rangeCacheRangeEnergy;
1185                                                  1185 
1186   if(energyRange != 0 && rangeEnergy != 0) {     1186   if(energyRange != 0 && rangeEnergy != 0) {
1187                                                  1187 
1188      G4double lowerEnEdge = energyRange -> En    1188      G4double lowerEnEdge = energyRange -> Energy( 0 );
1189      G4double lowerRangeEdge = rangeEnergy ->    1189      G4double lowerRangeEdge = rangeEnergy -> Energy( 0 );
1190                                                  1190 
1191      // Computing range for pre-step kinetic     1191      // Computing range for pre-step kinetic energy:
1192      G4double range = energyRange -> Value(ki    1192      G4double range = energyRange -> Value(kineticEnergy);
1193                                                  1193 
1194      // Energy below vector boundary:            1194      // Energy below vector boundary:
1195      if(kineticEnergy < lowerEnEdge) {           1195      if(kineticEnergy < lowerEnEdge) {
1196                                                  1196 
1197         range =  energyRange -> Value(lowerEn    1197         range =  energyRange -> Value(lowerEnEdge);
1198         range *= std::sqrt(kineticEnergy / lo    1198         range *= std::sqrt(kineticEnergy / lowerEnEdge);
1199      }                                           1199      }
1200                                                  1200 
1201 #ifdef PRINT_DEBUG                               1201 #ifdef PRINT_DEBUG
1202      G4cout << "G4IonParametrisedLossModel::C    1202      G4cout << "G4IonParametrisedLossModel::ComputeLossForStep() range = "
1203             << range / mm << " mm, step = " <    1203             << range / mm << " mm, step = " << stepLength / mm << " mm"
1204             << G4endl;                           1204             << G4endl;
1205 #endif                                           1205 #endif
1206                                                  1206 
1207      // Remaining range:                         1207      // Remaining range:
1208      G4double remRange = range - stepLength;     1208      G4double remRange = range - stepLength;
1209                                                  1209 
1210      // If range is smaller than step length,    1210      // If range is smaller than step length, the loss is set to kinetic
1211      // energy                                   1211      // energy
1212      if(remRange < 0.0) loss = kineticEnergy;    1212      if(remRange < 0.0) loss = kineticEnergy;
1213      else if(remRange < lowerRangeEdge) {        1213      else if(remRange < lowerRangeEdge) {
1214                                                  1214 
1215         G4double ratio = remRange / lowerRang    1215         G4double ratio = remRange / lowerRangeEdge;
1216         loss = kineticEnergy - ratio * ratio     1216         loss = kineticEnergy - ratio * ratio * lowerEnEdge;
1217      }                                           1217      }
1218      else {                                      1218      else {
1219                                                  1219 
1220         G4double energy = rangeEnergy -> Valu    1220         G4double energy = rangeEnergy -> Value(range - stepLength);
1221         loss = kineticEnergy - energy;           1221         loss = kineticEnergy - energy;
1222      }                                           1222      }
1223   }                                              1223   }
1224                                                  1224 
1225   if(loss < 0.0) loss = 0.0;                     1225   if(loss < 0.0) loss = 0.0;
1226                                                  1226 
1227   return loss;                                   1227   return loss;
1228 }                                                1228 }
1229                                                  1229 
1230 // ##########################################    1230 // #########################################################################
1231                                                  1231 
1232 G4bool G4IonParametrisedLossModel::AddDEDXTab    1232 G4bool G4IonParametrisedLossModel::AddDEDXTable(
1233                                 const G4Strin    1233                                 const G4String& nam,
1234                                 G4VIonDEDXTab    1234                                 G4VIonDEDXTable* table,
1235                                 G4VIonDEDXSca    1235                                 G4VIonDEDXScalingAlgorithm* algorithm) {
1236                                                  1236 
1237   if(table == 0) {                               1237   if(table == 0) {
1238      G4cout << "G4IonParametrisedLossModel::A    1238      G4cout << "G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1239             << " add table: Invalid pointer."    1239             << " add table: Invalid pointer."
1240             << G4endl;                           1240             << G4endl;
1241                                                  1241 
1242      return false;                               1242      return false;
1243   }                                              1243   }
1244                                                  1244 
1245   // Checking uniqueness of name                 1245   // Checking uniqueness of name
1246   LossTableList::iterator iter = lossTableLis    1246   LossTableList::iterator iter = lossTableList.begin();
1247   LossTableList::iterator iter_end = lossTabl    1247   LossTableList::iterator iter_end = lossTableList.end();
1248                                                  1248 
1249   for(;iter != iter_end; ++iter) {               1249   for(;iter != iter_end; ++iter) {
1250      const G4String& tableName = (*iter)->Get    1250      const G4String& tableName = (*iter)->GetName();
1251                                                  1251 
1252      if(tableName == nam) {                      1252      if(tableName == nam) {
1253         G4cout << "G4IonParametrisedLossModel    1253         G4cout << "G4IonParametrisedLossModel::AddDEDXTable() Cannot "
1254                << " add table: Name already e    1254                << " add table: Name already exists."
1255                << G4endl;                        1255                << G4endl;
1256                                                  1256 
1257         return false;                            1257         return false;
1258      }                                           1258      }
1259   }                                              1259   }
1260                                                  1260 
1261   G4VIonDEDXScalingAlgorithm* scalingAlgorith    1261   G4VIonDEDXScalingAlgorithm* scalingAlgorithm = algorithm;
1262   if(scalingAlgorithm == 0)                      1262   if(scalingAlgorithm == 0)
1263      scalingAlgorithm = new G4VIonDEDXScaling    1263      scalingAlgorithm = new G4VIonDEDXScalingAlgorithm;
1264                                                  1264 
1265   G4IonDEDXHandler* handler =                    1265   G4IonDEDXHandler* handler =
1266                       new G4IonDEDXHandler(ta    1266                       new G4IonDEDXHandler(table, scalingAlgorithm, nam);
1267                                                  1267 
1268   lossTableList.push_front(handler);             1268   lossTableList.push_front(handler);
1269                                                  1269 
1270   return true;                                   1270   return true;
1271 }                                                1271 }
1272                                                  1272 
1273 // ##########################################    1273 // #########################################################################
1274                                                  1274 
1275 G4bool G4IonParametrisedLossModel::RemoveDEDX    1275 G4bool G4IonParametrisedLossModel::RemoveDEDXTable(
1276          const G4String& nam) {                  1276          const G4String& nam) {
1277                                                  1277 
1278   LossTableList::iterator iter = lossTableLis    1278   LossTableList::iterator iter = lossTableList.begin();
1279   LossTableList::iterator iter_end = lossTabl    1279   LossTableList::iterator iter_end = lossTableList.end();
1280                                                  1280 
1281   for(;iter != iter_end; iter++) {               1281   for(;iter != iter_end; iter++) {
1282      G4String tableName = (*iter) -> GetName(    1282      G4String tableName = (*iter) -> GetName();
1283                                                  1283 
1284      if(tableName == nam) {                      1284      if(tableName == nam) {
1285         delete (*iter);                          1285         delete (*iter);
1286                                                  1286 
1287         // Remove from table list                1287         // Remove from table list
1288         lossTableList.erase(iter);               1288         lossTableList.erase(iter);
1289                                                  1289 
1290         // Range vs energy and energy vs rang    1290         // Range vs energy and energy vs range vectors are cleared
1291         RangeEnergyTable::iterator iterRange     1291         RangeEnergyTable::iterator iterRange = r.begin();
1292         RangeEnergyTable::iterator iterRange_    1292         RangeEnergyTable::iterator iterRange_end = r.end();
1293                                                  1293 
1294         for(;iterRange != iterRange_end; iter    1294         for(;iterRange != iterRange_end; iterRange++)
1295                                             d    1295                                             delete iterRange -> second;
1296         r.clear();                               1296         r.clear();
1297                                                  1297 
1298         EnergyRangeTable::iterator iterEnergy    1298         EnergyRangeTable::iterator iterEnergy = E.begin();
1299         EnergyRangeTable::iterator iterEnergy    1299         EnergyRangeTable::iterator iterEnergy_end = E.end();
1300                                                  1300 
1301         for(;iterEnergy != iterEnergy_end; it    1301         for(;iterEnergy != iterEnergy_end; iterEnergy++)
1302                                             d    1302                                             delete iterEnergy -> second;
1303         E.clear();                               1303         E.clear();
1304                                                  1304 
1305         return true;                             1305         return true;
1306      }                                           1306      }
1307   }                                              1307   }
1308                                                  1308 
1309   return false;                                  1309   return false;
1310 }                                                1310 }
1311                                                  1311