Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/pii/src/G4hImpactIonisation.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/pii/src/G4hImpactIonisation.cc (Version 11.3.0) and /processes/electromagnetic/pii/src/G4hImpactIonisation.cc (Version 10.7.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 // -------------------------------------------     28 // ------------------------------------------------------------
 29 // G4RDHadronIonisation                            29 // G4RDHadronIonisation
 30 //                                                 30 //
 31 //                                                 31 //
 32 // Author: Maria Grazia Pia (MariaGrazia.Pia@g     32 // Author: Maria Grazia Pia (MariaGrazia.Pia@ge.infn.it)
 33 //                                                 33 //
 34 // 08 Sep 2008 - MGP - Created (initially base     34 // 08 Sep 2008 - MGP - Created (initially based on G4hLowEnergyIonisation) 
 35 //                     Added PIXE capabilities     35 //                     Added PIXE capabilities
 36 //                     Partial clean-up of the     36 //                     Partial clean-up of the implementation (more needed)
 37 //                     Calculation of Microsco     37 //                     Calculation of MicroscopicCrossSection delegated to specialised cla// Documentation available in:
 38 // M.G. Pia et al., PIXE Simulation With Geant     38 // M.G. Pia et al., PIXE Simulation With Geant4,
 39 // IEEE Trans. Nucl. Sci., vol. 56, no. 6, pp.     39 // IEEE Trans. Nucl. Sci., vol. 56, no. 6, pp. 3614-3649, Dec. 2009.
 40                                                    40 
 41 //                                                 41 //
 42 // -------------------------------------------     42 // ------------------------------------------------------------
 43                                                    43  
 44 #include "G4hImpactIonisation.hh"                  44 #include "G4hImpactIonisation.hh"
 45 #include "globals.hh"                              45 #include "globals.hh"
 46 #include "G4ios.hh"                                46 #include "G4ios.hh"
 47 #include "Randomize.hh"                            47 #include "Randomize.hh"
 48 #include "G4PhysicalConstants.hh"                  48 #include "G4PhysicalConstants.hh"
 49 #include "G4SystemOfUnits.hh"                      49 #include "G4SystemOfUnits.hh"
 50 #include "G4Poisson.hh"                            50 #include "G4Poisson.hh"
 51 #include "G4UnitsTable.hh"                         51 #include "G4UnitsTable.hh"
 52 #include "G4EnergyLossTables.hh"                   52 #include "G4EnergyLossTables.hh"
 53 #include "G4Material.hh"                           53 #include "G4Material.hh"
 54 #include "G4DynamicParticle.hh"                    54 #include "G4DynamicParticle.hh"
 55 #include "G4ParticleDefinition.hh"                 55 #include "G4ParticleDefinition.hh"
 56 #include "G4AtomicDeexcitation.hh"                 56 #include "G4AtomicDeexcitation.hh"
 57 #include "G4AtomicTransitionManager.hh"            57 #include "G4AtomicTransitionManager.hh"
 58 #include "G4PixeCrossSectionHandler.hh"            58 #include "G4PixeCrossSectionHandler.hh"
 59 #include "G4IInterpolator.hh"                      59 #include "G4IInterpolator.hh"
 60 #include "G4LogLogInterpolator.hh"                 60 #include "G4LogLogInterpolator.hh"
 61 #include "G4Gamma.hh"                              61 #include "G4Gamma.hh"
 62 #include "G4Electron.hh"                           62 #include "G4Electron.hh"
 63 #include "G4Proton.hh"                             63 #include "G4Proton.hh"               
 64 #include "G4ProcessManager.hh"                     64 #include "G4ProcessManager.hh"
 65 #include "G4ProductionCutsTable.hh"                65 #include "G4ProductionCutsTable.hh"
 66 #include "G4PhysicsLogVector.hh"                   66 #include "G4PhysicsLogVector.hh"       
 67 #include "G4PhysicsLinearVector.hh"                67 #include "G4PhysicsLinearVector.hh"    
 68                                                    68 
 69 #include "G4VLowEnergyModel.hh"                    69 #include "G4VLowEnergyModel.hh"
 70 #include "G4hNuclearStoppingModel.hh"              70 #include "G4hNuclearStoppingModel.hh"  
 71 #include "G4hBetheBlochModel.hh"                   71 #include "G4hBetheBlochModel.hh"       
 72 #include "G4hParametrisedLossModel.hh"             72 #include "G4hParametrisedLossModel.hh" 
 73 #include "G4QAOLowEnergyLoss.hh"                   73 #include "G4QAOLowEnergyLoss.hh"       
 74 #include "G4hIonEffChargeSquare.hh"                74 #include "G4hIonEffChargeSquare.hh"    
 75 #include "G4IonChuFluctuationModel.hh"             75 #include "G4IonChuFluctuationModel.hh" 
 76 #include "G4IonYangFluctuationModel.hh"            76 #include "G4IonYangFluctuationModel.hh"
 77                                                    77 
 78 #include "G4MaterialCutsCouple.hh"                 78 #include "G4MaterialCutsCouple.hh"
 79 #include "G4Track.hh"                              79 #include "G4Track.hh"
 80 #include "G4Step.hh"                               80 #include "G4Step.hh"
 81                                                    81 
 82 G4hImpactIonisation::G4hImpactIonisation(const     82 G4hImpactIonisation::G4hImpactIonisation(const G4String& processName)
 83   : G4hRDEnergyLoss(processName),                  83   : G4hRDEnergyLoss(processName),
 84     betheBlochModel(0),                            84     betheBlochModel(0),
 85     protonModel(0),                                85     protonModel(0),
 86     antiprotonModel(0),                            86     antiprotonModel(0),
 87     theIonEffChargeModel(0),                       87     theIonEffChargeModel(0),
 88     theNuclearStoppingModel(0),                    88     theNuclearStoppingModel(0),
 89     theIonChuFluctuationModel(0),                  89     theIonChuFluctuationModel(0),
 90     theIonYangFluctuationModel(0),                 90     theIonYangFluctuationModel(0),
 91     protonTable("ICRU_R49p"),                      91     protonTable("ICRU_R49p"),
 92     antiprotonTable("ICRU_R49p"),                  92     antiprotonTable("ICRU_R49p"),
 93     theNuclearTable("ICRU_R49"),                   93     theNuclearTable("ICRU_R49"),
 94     nStopping(true),                               94     nStopping(true),
 95     theBarkas(true),                               95     theBarkas(true),
 96     theMeanFreePathTable(0),                       96     theMeanFreePathTable(0),
 97     paramStepLimit (0.005),                        97     paramStepLimit (0.005),
 98     pixeCrossSectionHandler(0)                     98     pixeCrossSectionHandler(0)
 99 {                                                  99 { 
100   InitializeMe();                                 100   InitializeMe();
101 }                                                 101 }
102                                                   102 
103                                                   103 
104                                                   104 
105 void G4hImpactIonisation::InitializeMe()          105 void G4hImpactIonisation::InitializeMe()
106 {                                                 106 {
107   LowestKineticEnergy  = 10.0*eV ;                107   LowestKineticEnergy  = 10.0*eV ;
108   HighestKineticEnergy = 100.0*GeV ;              108   HighestKineticEnergy = 100.0*GeV ;
109   MinKineticEnergy     = 10.0*eV ;                109   MinKineticEnergy     = 10.0*eV ; 
110   TotBin               = 360 ;                    110   TotBin               = 360 ;
111   protonLowEnergy      = 1.*keV ;                 111   protonLowEnergy      = 1.*keV ;
112   protonHighEnergy     = 100.*MeV ;               112   protonHighEnergy     = 100.*MeV ;
113   antiprotonLowEnergy  = 25.*keV ;                113   antiprotonLowEnergy  = 25.*keV ;
114   antiprotonHighEnergy = 2.*MeV ;                 114   antiprotonHighEnergy = 2.*MeV ;
115   minGammaEnergy       = 100 * eV;                115   minGammaEnergy       = 100 * eV;
116   minElectronEnergy    = 250.* eV;                116   minElectronEnergy    = 250.* eV;
117   verboseLevel         = 0;                       117   verboseLevel         = 0;
118                                                   118  
119   // Min and max energy of incident particle f    119   // Min and max energy of incident particle for the calculation of shell cross sections
120   // for PIXE generation                          120   // for PIXE generation
121   eMinPixe = 1.* keV;                             121   eMinPixe = 1.* keV;
122   eMaxPixe = 200. * MeV;                          122   eMaxPixe = 200. * MeV;
123                                                   123   
124   G4String defaultPixeModel("ecpssr");            124   G4String defaultPixeModel("ecpssr"); 
125   modelK = defaultPixeModel;                      125   modelK = defaultPixeModel;
126   modelL = defaultPixeModel;                      126   modelL = defaultPixeModel;
127   modelM = defaultPixeModel;                      127   modelM = defaultPixeModel;
128                                                << 
129   // Calculated on the fly, but should be init << 
130   fdEdx = 0.0;                                 << 
131   fRangeNow = 0.0;                             << 
132   charge = 0.0;                                << 
133   chargeSquare = 0.0;                          << 
134   initialMass = 0.0;                           << 
135   fBarkas = 0.0;                               << 
136 }                                                 128 }
137                                                   129 
138                                                   130 
139 G4hImpactIonisation::~G4hImpactIonisation()       131 G4hImpactIonisation::~G4hImpactIonisation()
140 {                                                 132 {
141   if (theMeanFreePathTable)                       133   if (theMeanFreePathTable) 
142     {                                             134     {
143       theMeanFreePathTable->clearAndDestroy();    135       theMeanFreePathTable->clearAndDestroy();
144       delete theMeanFreePathTable;                136       delete theMeanFreePathTable;
145     }                                             137     }
146                                                   138 
147   if (betheBlochModel) delete betheBlochModel;    139   if (betheBlochModel) delete betheBlochModel;
148   if (protonModel) delete protonModel;            140   if (protonModel) delete protonModel;
149   if (antiprotonModel) delete antiprotonModel;    141   if (antiprotonModel) delete antiprotonModel;
150   if (theNuclearStoppingModel) delete theNucle    142   if (theNuclearStoppingModel) delete theNuclearStoppingModel;
151   if (theIonEffChargeModel) delete theIonEffCh    143   if (theIonEffChargeModel) delete theIonEffChargeModel;
152   if (theIonChuFluctuationModel) delete theIon    144   if (theIonChuFluctuationModel) delete theIonChuFluctuationModel;
153   if (theIonYangFluctuationModel) delete theIo    145   if (theIonYangFluctuationModel) delete theIonYangFluctuationModel;
154                                                   146 
155   delete pixeCrossSectionHandler;                 147   delete pixeCrossSectionHandler;
156                                                   148 
157   // ---- MGP ---- The following is to be chec    149   // ---- MGP ---- The following is to be checked
158   //  if (shellVacancy) delete shellVacancy;      150   //  if (shellVacancy) delete shellVacancy;
159                                                   151 
160   cutForDelta.clear();                            152   cutForDelta.clear();
161 }                                                 153 }
162                                                   154 
163 // -------------------------------------------    155 // --------------------------------------------------------------------
164 void G4hImpactIonisation::SetElectronicStoppin    156 void G4hImpactIonisation::SetElectronicStoppingPowerModel(const G4ParticleDefinition* particle,
165                 const G4String& dedxTable)        157                 const G4String& dedxTable)
166 // This method defines the ionisation parametr    158 // This method defines the ionisation parametrisation method via its name 
167 {                                                 159 {
168   if (particle->GetPDGCharge() > 0 )              160   if (particle->GetPDGCharge() > 0 ) 
169     {                                             161     {
170       // Positive charge                          162       // Positive charge
171       SetProtonElectronicStoppingPowerModel(de    163       SetProtonElectronicStoppingPowerModel(dedxTable) ;
172     }                                             164     } 
173   else                                            165   else 
174     {                                             166     {
175       // Antiprotons                              167       // Antiprotons
176       SetAntiProtonElectronicStoppingPowerMode    168       SetAntiProtonElectronicStoppingPowerModel(dedxTable) ;
177     }                                             169     }
178 }                                                 170 }
179                                                   171 
180                                                   172 
181 // -------------------------------------------    173 // --------------------------------------------------------------------
182 void G4hImpactIonisation::InitializeParametris    174 void G4hImpactIonisation::InitializeParametrisation() 
183                                                   175 
184 {                                                 176 {
185   // Define models for parametrisation of elec    177   // Define models for parametrisation of electronic energy losses
186   betheBlochModel = new G4hBetheBlochModel("Be    178   betheBlochModel = new G4hBetheBlochModel("Bethe-Bloch") ;
187   protonModel = new G4hParametrisedLossModel(p    179   protonModel = new G4hParametrisedLossModel(protonTable) ;
188   protonHighEnergy = std::min(protonHighEnergy    180   protonHighEnergy = std::min(protonHighEnergy,protonModel->HighEnergyLimit(0, 0));
189   antiprotonModel = new G4QAOLowEnergyLoss(ant    181   antiprotonModel = new G4QAOLowEnergyLoss(antiprotonTable) ;
190   theNuclearStoppingModel = new G4hNuclearStop    182   theNuclearStoppingModel = new G4hNuclearStoppingModel(theNuclearTable) ;
191   theIonEffChargeModel = new G4hIonEffChargeSq    183   theIonEffChargeModel = new G4hIonEffChargeSquare("Ziegler1988") ;
192   theIonChuFluctuationModel = new G4IonChuFluc    184   theIonChuFluctuationModel = new G4IonChuFluctuationModel("Chu") ;
193   theIonYangFluctuationModel = new G4IonYangFl    185   theIonYangFluctuationModel = new G4IonYangFluctuationModel("Yang") ;
194 }                                                 186 }
195                                                   187 
196                                                   188 
197 // -------------------------------------------    189 // --------------------------------------------------------------------
198 void G4hImpactIonisation::BuildPhysicsTable(co    190 void G4hImpactIonisation::BuildPhysicsTable(const G4ParticleDefinition& particleDef)
199                                                   191 
200 //  just call BuildLossTable+BuildLambdaTable     192 //  just call BuildLossTable+BuildLambdaTable
201 {                                                 193 {
202                                                   194 
203   // Verbose print-out                            195   // Verbose print-out
204   if(verboseLevel > 0)                            196   if(verboseLevel > 0) 
205     {                                             197     {
206       G4cout << "G4hImpactIonisation::BuildPhy    198       G4cout << "G4hImpactIonisation::BuildPhysicsTable for "
207        << particleDef.GetParticleName()           199        << particleDef.GetParticleName()
208        << " mass(MeV)= " << particleDef.GetPDG    200        << " mass(MeV)= " << particleDef.GetPDGMass()/MeV
209        << " charge= " << particleDef.GetPDGCha    201        << " charge= " << particleDef.GetPDGCharge()/eplus
210        << " type= " << particleDef.GetParticle    202        << " type= " << particleDef.GetParticleType()
211        << G4endl;                                 203        << G4endl;
212                                                   204       
213       if(verboseLevel > 1)                        205       if(verboseLevel > 1) 
214   {                                               206   {
215     G4ProcessVector* pv = particleDef.GetProce    207     G4ProcessVector* pv = particleDef.GetProcessManager()->GetProcessList();
216                                                   208     
217     G4cout << " 0: " << (*pv)[0]->GetProcessNa    209     G4cout << " 0: " << (*pv)[0]->GetProcessName() << " " << (*pv)[0]
218      << " 1: " << (*pv)[1]->GetProcessName() <    210      << " 1: " << (*pv)[1]->GetProcessName() << " " << (*pv)[1]
219       //        << " 2: " << (*pv)[2]->GetProc    211       //        << " 2: " << (*pv)[2]->GetProcessName() << " " << (*pv)[2]
220      << G4endl;                                   212      << G4endl;
221     G4cout << "ionModel= " << theIonEffChargeM    213     G4cout << "ionModel= " << theIonEffChargeModel
222      << " MFPtable= " << theMeanFreePathTable     214      << " MFPtable= " << theMeanFreePathTable
223      << " iniMass= " << initialMass               215      << " iniMass= " << initialMass
224      << G4endl;                                   216      << G4endl;
225   }                                               217   }
226     }                                             218     }
227   // End of verbose print-out                     219   // End of verbose print-out
228                                                   220 
229   if (particleDef.GetParticleType() == "nucleu    221   if (particleDef.GetParticleType() == "nucleus" &&
230       particleDef.GetParticleName() != "Generi    222       particleDef.GetParticleName() != "GenericIon" &&
231       particleDef.GetParticleSubType() == "gen    223       particleDef.GetParticleSubType() == "generic")
232     {                                             224     {
233                                                   225 
234       G4EnergyLossTables::Register(&particleDe    226       G4EnergyLossTables::Register(&particleDef,
235            theDEDXpTable,                         227            theDEDXpTable,
236            theRangepTable,                        228            theRangepTable,
237            theInverseRangepTable,                 229            theInverseRangepTable,
238            theLabTimepTable,                      230            theLabTimepTable,
239            theProperTimepTable,                   231            theProperTimepTable,
240            LowestKineticEnergy, HighestKinetic    232            LowestKineticEnergy, HighestKineticEnergy,
241            proton_mass_c2/particleDef.GetPDGMa    233            proton_mass_c2/particleDef.GetPDGMass(),
242            TotBin);                               234            TotBin);
243                                                   235 
244       return;                                     236       return;
245     }                                             237     }
246                                                   238 
247   if( !CutsWhereModified() && theLossTable) re    239   if( !CutsWhereModified() && theLossTable) return;
248                                                   240 
249   InitializeParametrisation() ;                   241   InitializeParametrisation() ;
250   G4Proton* proton = G4Proton::Proton();          242   G4Proton* proton = G4Proton::Proton();
251   G4AntiProton* antiproton = G4AntiProton::Ant    243   G4AntiProton* antiproton = G4AntiProton::AntiProton();
252                                                   244 
253   charge = particleDef.GetPDGCharge() / eplus;    245   charge = particleDef.GetPDGCharge() / eplus;
254   chargeSquare = charge*charge ;                  246   chargeSquare = charge*charge ;
255                                                   247 
256   const G4ProductionCutsTable* theCoupleTable=    248   const G4ProductionCutsTable* theCoupleTable=
257     G4ProductionCutsTable::GetProductionCutsTa    249     G4ProductionCutsTable::GetProductionCutsTable();
258   G4int numOfCouples = (G4int)theCoupleTable-> << 250   size_t numOfCouples = theCoupleTable->GetTableSize();
259                                                   251 
260   cutForDelta.clear();                            252   cutForDelta.clear();
261   cutForGamma.clear();                            253   cutForGamma.clear();
262                                                   254 
263   for (G4int j=0; j<numOfCouples; ++j) {       << 255   for (size_t j=0; j<numOfCouples; j++) {
264                                                   256 
265     // get material parameters needed for the     257     // get material parameters needed for the energy loss calculation
266     const G4MaterialCutsCouple* couple = theCo    258     const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
267     const G4Material* material= couple->GetMat    259     const G4Material* material= couple->GetMaterial();
268                                                   260 
269     // the cut cannot be below lowest limit       261     // the cut cannot be below lowest limit
270     G4double tCut = (*(theCoupleTable->GetEner    262     G4double tCut = (*(theCoupleTable->GetEnergyCutsVector(1)))[j];
271     if(tCut > HighestKineticEnergy) tCut = Hig    263     if(tCut > HighestKineticEnergy) tCut = HighestKineticEnergy;
272                                                   264 
273     G4double excEnergy = material->GetIonisati    265     G4double excEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
274                                                   266 
275     tCut = std::max(tCut,excEnergy);              267     tCut = std::max(tCut,excEnergy);
276     cutForDelta.push_back(tCut);                  268     cutForDelta.push_back(tCut);
277                                                   269 
278     // the cut cannot be below lowest limit       270     // the cut cannot be below lowest limit
279     tCut = (*(theCoupleTable->GetEnergyCutsVec    271     tCut = (*(theCoupleTable->GetEnergyCutsVector(0)))[j];
280     if(tCut > HighestKineticEnergy) tCut = Hig    272     if(tCut > HighestKineticEnergy) tCut = HighestKineticEnergy;
281     tCut = std::max(tCut,minGammaEnergy);         273     tCut = std::max(tCut,minGammaEnergy);
282     cutForGamma.push_back(tCut);                  274     cutForGamma.push_back(tCut);
283   }                                               275   }
284                                                   276 
285   if(verboseLevel > 0) {                          277   if(verboseLevel > 0) {
286     G4cout << "Cuts are defined " << G4endl;      278     G4cout << "Cuts are defined " << G4endl;
287   }                                               279   }
288                                                   280 
289   if(0.0 < charge)                                281   if(0.0 < charge)
290     {                                             282     {
291       {                                           283       {
292         BuildLossTable(*proton) ;                 284         BuildLossTable(*proton) ;
293                                                   285 
294   //      The following vector has a fixed dim    286   //      The following vector has a fixed dimension (see src/G4hImpactLoss.cc for more details)        
295   //      It happended in the past that caused    287   //      It happended in the past that caused memory corruption errors. The problem is still pending, even if temporary solved
296   //        G4cout << "[NOTE]: __LINE__=" << _    288   //        G4cout << "[NOTE]: __LINE__=" << __LINE__ << ", particleDef=" << particleDef.GetParticleName() << ", proton=" << proton << ", theLossTable=" << theLossTable << ", CounterOfpProcess=" << CounterOfpProcess << G4endl;
297                                                   289         
298         RecorderOfpProcess[CounterOfpProcess]     290         RecorderOfpProcess[CounterOfpProcess] = theLossTable ;
299         CounterOfpProcess++;                      291         CounterOfpProcess++;
300       }                                           292       }
301     } else {                                      293     } else {
302     {                                             294     {
303       BuildLossTable(*antiproton) ;               295       BuildLossTable(*antiproton) ;
304                                                   296         
305       //      The following vector has a fixed    297       //      The following vector has a fixed dimension (see src/G4hImpactLoss.cc for more details)        
306       //      It happended in the past that ca    298       //      It happended in the past that caused memory corruption errors. The problem is still pending, even if temporary solved
307       //        G4cout << "[NOTE]: __LINE__="     299       //        G4cout << "[NOTE]: __LINE__=" << __LINE__ << ", particleDef=" << particleDef.GetParticleName() << ", antiproton=" << antiproton << ", theLossTable=" << theLossTable << ", CounterOfpbarProcess=" << CounterOfpbarProcess << G4endl;
308                                                   300         
309       RecorderOfpbarProcess[CounterOfpbarProce    301       RecorderOfpbarProcess[CounterOfpbarProcess] = theLossTable ;
310       CounterOfpbarProcess++;                     302       CounterOfpbarProcess++;
311     }                                             303     }
312   }                                               304   }
313                                                   305 
314   if(verboseLevel > 0) {                          306   if(verboseLevel > 0) {
315     G4cout << "G4hImpactIonisation::BuildPhysi    307     G4cout << "G4hImpactIonisation::BuildPhysicsTable: "
316            << "Loss table is built "              308            << "Loss table is built "
317       //     << theLossTable                      309       //     << theLossTable
318      << G4endl;                                   310      << G4endl;
319   }                                               311   }
320                                                   312 
321   BuildLambdaTable(particleDef) ;                 313   BuildLambdaTable(particleDef) ;
322   //  BuildDataForFluorescence(particleDef);      314   //  BuildDataForFluorescence(particleDef);
323                                                   315 
324   if(verboseLevel > 1) {                          316   if(verboseLevel > 1) {
325     G4cout << (*theMeanFreePathTable) << G4end    317     G4cout << (*theMeanFreePathTable) << G4endl;
326   }                                               318   }
327                                                   319 
328   if(verboseLevel > 0) {                          320   if(verboseLevel > 0) {
329     G4cout << "G4hImpactIonisation::BuildPhysi    321     G4cout << "G4hImpactIonisation::BuildPhysicsTable: "
330            << "DEDX table will be built "         322            << "DEDX table will be built "
331       //     << theDEDXpTable << " " << theDED    323       //     << theDEDXpTable << " " << theDEDXpbarTable
332       //     << " " << theRangepTable << " " <    324       //     << " " << theRangepTable << " " << theRangepbarTable
333      << G4endl;                                   325      << G4endl;
334   }                                               326   }
335                                                   327 
336   BuildDEDXTable(particleDef) ;                   328   BuildDEDXTable(particleDef) ;
337                                                   329 
338   if(verboseLevel > 1) {                          330   if(verboseLevel > 1) {
339     G4cout << (*theDEDXpTable) << G4endl;         331     G4cout << (*theDEDXpTable) << G4endl;
340   }                                               332   }
341                                                   333 
342   if((&particleDef == proton) ||  (&particleDe    334   if((&particleDef == proton) ||  (&particleDef == antiproton)) PrintInfoDefinition() ;
343                                                   335 
344   if(verboseLevel > 0) {                          336   if(verboseLevel > 0) {
345     G4cout << "G4hImpactIonisation::BuildPhysi    337     G4cout << "G4hImpactIonisation::BuildPhysicsTable: end for "
346            << particleDef.GetParticleName() <<    338            << particleDef.GetParticleName() << G4endl;
347   }                                               339   }
348 }                                                 340 }
349                                                   341 
350                                                   342 
351                                                   343 
352                                                   344 
353                                                   345 
354 // -------------------------------------------    346 // --------------------------------------------------------------------
355 void G4hImpactIonisation::BuildLossTable(const    347 void G4hImpactIonisation::BuildLossTable(const G4ParticleDefinition& particleDef)
356 {                                                 348 {
357   // Initialisation                               349   // Initialisation
358   G4double lowEdgeEnergy , ionloss, ionlossBB,    350   G4double lowEdgeEnergy , ionloss, ionlossBB, paramB ;
359   //G4double lowEnergy, highEnergy;               351   //G4double lowEnergy, highEnergy;
360   G4double highEnergy;                            352   G4double highEnergy;
361   G4Proton* proton = G4Proton::Proton();          353   G4Proton* proton = G4Proton::Proton();
362                                                   354 
363   if (particleDef == *proton)                     355   if (particleDef == *proton) 
364     {                                             356     {
365       //lowEnergy = protonLowEnergy ;             357       //lowEnergy = protonLowEnergy ;
366       highEnergy = protonHighEnergy ;             358       highEnergy = protonHighEnergy ;
367       charge = 1. ;                               359       charge = 1. ;
368     }                                             360     } 
369   else                                            361   else 
370     {                                             362     {
371       //lowEnergy = antiprotonLowEnergy ;         363       //lowEnergy = antiprotonLowEnergy ;
372       highEnergy = antiprotonHighEnergy ;         364       highEnergy = antiprotonHighEnergy ;
373       charge = -1. ;                              365       charge = -1. ;
374     }                                             366     }
375   chargeSquare = 1. ;                             367   chargeSquare = 1. ;
376                                                   368 
377   const G4ProductionCutsTable* theCoupleTable=    369   const G4ProductionCutsTable* theCoupleTable=
378     G4ProductionCutsTable::GetProductionCutsTa    370     G4ProductionCutsTable::GetProductionCutsTable();
379   G4int numOfCouples = (G4int)theCoupleTable-> << 371   size_t numOfCouples = theCoupleTable->GetTableSize();
380                                                   372 
381   if ( theLossTable)                              373   if ( theLossTable) 
382     {                                             374     {
383       theLossTable->clearAndDestroy();            375       theLossTable->clearAndDestroy();
384       delete theLossTable;                        376       delete theLossTable;
385     }                                             377     }
386                                                   378 
387   theLossTable = new G4PhysicsTable(numOfCoupl    379   theLossTable = new G4PhysicsTable(numOfCouples);
388                                                   380 
389   //  loop for materials                          381   //  loop for materials
390   for (G4int j=0; j<numOfCouples; ++j) {       << 382   for (size_t j=0; j<numOfCouples; j++) {
391                                                   383 
392     // create physics vector and fill it          384     // create physics vector and fill it
393     G4PhysicsLogVector* aVector = new G4Physic    385     G4PhysicsLogVector* aVector = new G4PhysicsLogVector(LowestKineticEnergy,
394                                                   386                                                          HighestKineticEnergy,
395                                                   387                                                          TotBin);
396                                                   388 
397     // get material parameters needed for the     389     // get material parameters needed for the energy loss calculation
398     const G4MaterialCutsCouple* couple = theCo    390     const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
399     const G4Material* material= couple->GetMat    391     const G4Material* material= couple->GetMaterial();
400                                                   392 
401     if ( charge > 0.0 ) {                         393     if ( charge > 0.0 ) {
402       ionloss = ProtonParametrisedDEDX(couple,    394       ionloss = ProtonParametrisedDEDX(couple,highEnergy) ;
403     } else {                                      395     } else {
404       ionloss = AntiProtonParametrisedDEDX(cou    396       ionloss = AntiProtonParametrisedDEDX(couple,highEnergy) ;
405     }                                             397     }
406                                                   398 
407     ionlossBB = betheBlochModel->TheValue(&par    399     ionlossBB = betheBlochModel->TheValue(&particleDef,material,highEnergy) ;
408     ionlossBB -= DeltaRaysEnergy(couple,highEn    400     ionlossBB -= DeltaRaysEnergy(couple,highEnergy,proton_mass_c2) ;
409                                                   401 
410                                                   402 
411     paramB =  ionloss/ionlossBB - 1.0 ;           403     paramB =  ionloss/ionlossBB - 1.0 ;
412                                                   404 
413     // now comes the loop for the kinetic ener    405     // now comes the loop for the kinetic energy values
414     for (G4int i = 0 ; i < TotBin ; i++) {        406     for (G4int i = 0 ; i < TotBin ; i++) {
415       lowEdgeEnergy = aVector->GetLowEdgeEnerg    407       lowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
416                                                   408 
417       // low energy part for this material, pa    409       // low energy part for this material, parametrised energy loss formulae
418       if ( lowEdgeEnergy < highEnergy ) {         410       if ( lowEdgeEnergy < highEnergy ) {
419                                                   411 
420         if ( charge > 0.0 ) {                     412         if ( charge > 0.0 ) {
421           ionloss = ProtonParametrisedDEDX(cou    413           ionloss = ProtonParametrisedDEDX(couple,lowEdgeEnergy) ;
422   } else {                                        414   } else {
423           ionloss = AntiProtonParametrisedDEDX    415           ionloss = AntiProtonParametrisedDEDX(couple,lowEdgeEnergy) ;
424   }                                               416   }
425                                                   417 
426       } else {                                    418       } else {
427                                                   419 
428         // high energy part for this material,    420         // high energy part for this material, Bethe-Bloch formula
429         ionloss = betheBlochModel->TheValue(pr    421         ionloss = betheBlochModel->TheValue(proton,material,
430               lowEdgeEnergy) ;                    422               lowEdgeEnergy) ;
431                                                   423 
432         ionloss -= DeltaRaysEnergy(couple,lowE    424         ionloss -= DeltaRaysEnergy(couple,lowEdgeEnergy,proton_mass_c2) ;
433                                                   425 
434   ionloss *= (1.0 + paramB*highEnergy/lowEdgeE    426   ionloss *= (1.0 + paramB*highEnergy/lowEdgeEnergy) ;
435       }                                           427       }
436                                                   428 
437       // now put the loss into the vector         429       // now put the loss into the vector
438       if(verboseLevel > 1) {                      430       if(verboseLevel > 1) {
439         G4cout << "E(MeV)= " << lowEdgeEnergy/    431         G4cout << "E(MeV)= " << lowEdgeEnergy/MeV
440                << "  dE/dx(MeV/mm)= " << ionlo    432                << "  dE/dx(MeV/mm)= " << ionloss*mm/MeV
441                << " in " << material->GetName(    433                << " in " << material->GetName() << G4endl;
442       }                                           434       }
443       aVector->PutValue(i,ionloss) ;              435       aVector->PutValue(i,ionloss) ;
444     }                                             436     }
445     // Insert vector for this material into th    437     // Insert vector for this material into the table
446     theLossTable->insert(aVector) ;               438     theLossTable->insert(aVector) ;
447   }                                               439   }
448 }                                                 440 }
449                                                   441 
450                                                   442 
451                                                   443 
452 // -------------------------------------------    444 // --------------------------------------------------------------------
453 void G4hImpactIonisation::BuildLambdaTable(con    445 void G4hImpactIonisation::BuildLambdaTable(const G4ParticleDefinition& particleDef)
454                                                   446 
455 {                                                 447 {
456   // Build mean free path tables for the delta    448   // Build mean free path tables for the delta ray production process
457   //     tables are built for MATERIALS           449   //     tables are built for MATERIALS
458                                                   450 
459   if(verboseLevel > 1) {                          451   if(verboseLevel > 1) {
460     G4cout << "G4hImpactIonisation::BuildLambd    452     G4cout << "G4hImpactIonisation::BuildLambdaTable for "
461            << particleDef.GetParticleName() <<    453            << particleDef.GetParticleName() << " is started" << G4endl;
462   }                                               454   }
463                                                   455 
464                                                   456 
465   G4double lowEdgeEnergy, value;                  457   G4double lowEdgeEnergy, value;
466   charge = particleDef.GetPDGCharge()/eplus ;     458   charge = particleDef.GetPDGCharge()/eplus ;
467   chargeSquare = charge*charge ;                  459   chargeSquare = charge*charge ;
468   initialMass = particleDef.GetPDGMass();         460   initialMass = particleDef.GetPDGMass();
469                                                   461 
470   const G4ProductionCutsTable* theCoupleTable=    462   const G4ProductionCutsTable* theCoupleTable=
471     G4ProductionCutsTable::GetProductionCutsTa    463     G4ProductionCutsTable::GetProductionCutsTable();
472   G4int numOfCouples = (G4int)theCoupleTable-> << 464   size_t numOfCouples = theCoupleTable->GetTableSize();
473                                                   465 
474                                                   466 
475   if (theMeanFreePathTable) {                     467   if (theMeanFreePathTable) {
476     theMeanFreePathTable->clearAndDestroy();      468     theMeanFreePathTable->clearAndDestroy();
477     delete theMeanFreePathTable;                  469     delete theMeanFreePathTable;
478   }                                               470   }
479                                                   471 
480   theMeanFreePathTable = new G4PhysicsTable(nu    472   theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
481                                                   473 
482   // loop for materials                           474   // loop for materials
483                                                   475 
484   for (G4int j=0 ; j < numOfCouples; ++j) {    << 476   for (size_t j=0 ; j < numOfCouples; j++) {
485                                                   477 
486     //create physics vector then fill it ....     478     //create physics vector then fill it ....
487     G4PhysicsLogVector* aVector = new G4Physic    479     G4PhysicsLogVector* aVector = new G4PhysicsLogVector(LowestKineticEnergy,
488                                                   480                                                          HighestKineticEnergy,
489                                                   481                                                          TotBin);
490                                                   482 
491     // compute the (macroscopic) cross section    483     // compute the (macroscopic) cross section first
492     const G4MaterialCutsCouple* couple = theCo    484     const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
493     const G4Material* material= couple->GetMat    485     const G4Material* material= couple->GetMaterial();
494                                                   486 
495     const G4ElementVector* theElementVector =     487     const G4ElementVector* theElementVector =  material->GetElementVector() ;
496     const G4double* theAtomicNumDensityVector     488     const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
497     const G4int numberOfElements = (G4int)mate << 489     const G4int numberOfElements = material->GetNumberOfElements() ;
498                                                   490 
499     // get the electron kinetic energy cut for    491     // get the electron kinetic energy cut for the actual material,
500     //  it will be used in ComputeMicroscopicC    492     //  it will be used in ComputeMicroscopicCrossSection
501     // ( it is the SAME for ALL the ELEMENTS i    493     // ( it is the SAME for ALL the ELEMENTS in THIS MATERIAL )
502     //   -------------------------------------    494     //   ------------------------------------------------------
503                                                   495 
504     G4double deltaCut = cutForDelta[j];           496     G4double deltaCut = cutForDelta[j];
505                                                   497 
506     for ( G4int i = 0 ; i < TotBin ; i++ ) {      498     for ( G4int i = 0 ; i < TotBin ; i++ ) {
507       lowEdgeEnergy = aVector->GetLowEdgeEnerg    499       lowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
508       G4double sigma = 0.0 ;                      500       G4double sigma = 0.0 ;
509       G4int Z;                                    501       G4int Z;
510                                                   502       
511       for (G4int iel=0; iel<numberOfElements;     503       for (G4int iel=0; iel<numberOfElements; iel++ ) 
512   {                                               504   {
513     Z = (G4int) (*theElementVector)[iel]->GetZ    505     Z = (G4int) (*theElementVector)[iel]->GetZ();
514     // ---- MGP --- Corrected duplicated cross    506     // ---- MGP --- Corrected duplicated cross section calculation here from
515     // G4hLowEnergyIonisation original            507     // G4hLowEnergyIonisation original
516     G4double microCross = MicroscopicCrossSect    508     G4double microCross = MicroscopicCrossSection( particleDef,
517                lowEdgeEnergy,                     509                lowEdgeEnergy,
518                Z,                                 510                Z,
519                deltaCut ) ;                       511                deltaCut ) ; 
520     //totalCrossSectionMap [Z] = microCross;      512     //totalCrossSectionMap [Z] = microCross;
521     sigma += theAtomicNumDensityVector[iel] *     513     sigma += theAtomicNumDensityVector[iel] * microCross ; 
522   }                                               514   }
523                                                   515 
524       // mean free path = 1./macroscopic cross    516       // mean free path = 1./macroscopic cross section
525                                                   517 
526       value = sigma<=0 ? DBL_MAX : 1./sigma ;     518       value = sigma<=0 ? DBL_MAX : 1./sigma ;
527                                                   519 
528       aVector->PutValue(i, value) ;               520       aVector->PutValue(i, value) ;
529     }                                             521     }
530                                                   522 
531     theMeanFreePathTable->insert(aVector);        523     theMeanFreePathTable->insert(aVector);
532   }                                               524   }
533                                                   525 
534 }                                                 526 }
535                                                   527 
536                                                   528 
537 // -------------------------------------------    529 // --------------------------------------------------------------------
538 G4double G4hImpactIonisation::MicroscopicCross    530 G4double G4hImpactIonisation::MicroscopicCrossSection(const G4ParticleDefinition& particleDef,
539                   G4double kineticEnergy,         531                   G4double kineticEnergy,
540                   G4double atomicNumber,          532                   G4double atomicNumber,
541                   G4double deltaCutInEnergy) c    533                   G4double deltaCutInEnergy) const
542 {                                                 534 {
543   //******************************************    535   //******************************************************************
544     // cross section formula is OK for spin=0,    536     // cross section formula is OK for spin=0, 1/2, 1 only !
545     // ***************************************    537     // *****************************************************************
546                                                   538 
547     // Calculates the microscopic cross sectio    539     // Calculates the microscopic cross section in GEANT4 internal units
548     // Formula documented in Geant4 Phys. Ref.    540     // Formula documented in Geant4 Phys. Ref. Manual
549     // ( it is called for elements, AtomicNumb    541     // ( it is called for elements, AtomicNumber = z )
550                                                   542 
551     G4double totalCrossSection = 0.;              543     G4double totalCrossSection = 0.;
552                                                   544 
553   // Particle mass and energy                     545   // Particle mass and energy
554   G4double particleMass = initialMass;            546   G4double particleMass = initialMass;
555   G4double energy = kineticEnergy + particleMa    547   G4double energy = kineticEnergy + particleMass;
556                                                   548 
557   // Some kinematics                              549   // Some kinematics
558   G4double gamma = energy / particleMass;         550   G4double gamma = energy / particleMass;
559   G4double beta2 = 1. - 1. / (gamma * gamma);     551   G4double beta2 = 1. - 1. / (gamma * gamma);
560   G4double var = electron_mass_c2 / particleMa    552   G4double var = electron_mass_c2 / particleMass;
561   G4double tMax   = 2. * electron_mass_c2 * (g    553   G4double tMax   = 2. * electron_mass_c2 * (gamma*gamma - 1.) / (1. + 2.* gamma*var + var*var);
562                                                   554 
563   // Calculate the total cross section            555   // Calculate the total cross section
564                                                   556 
565   if ( tMax > deltaCutInEnergy )                  557   if ( tMax > deltaCutInEnergy ) 
566     {                                             558     {
567       var = deltaCutInEnergy / tMax;              559       var = deltaCutInEnergy / tMax;
568       totalCrossSection = (1. - var * (1. - be    560       totalCrossSection = (1. - var * (1. - beta2 * std::log(var))) / deltaCutInEnergy ;
569                                                   561       
570       G4double spin = particleDef.GetPDGSpin()    562       G4double spin = particleDef.GetPDGSpin() ;
571                                                   563       
572       // +term for spin=1/2 particle              564       // +term for spin=1/2 particle
573       if (spin == 0.5)                            565       if (spin == 0.5) 
574   {                                               566   {
575     totalCrossSection +=  0.5 * (tMax - deltaC    567     totalCrossSection +=  0.5 * (tMax - deltaCutInEnergy) / (energy*energy);
576   }                                               568   }
577       // +term for spin=1 particle                569       // +term for spin=1 particle
578       else if (spin > 0.9 )                       570       else if (spin > 0.9 )
579   {                                               571   {
580     totalCrossSection += -std::log(var) /         572     totalCrossSection += -std::log(var) / 
581       (3. * deltaCutInEnergy) + (tMax - deltaC    573       (3. * deltaCutInEnergy) + (tMax - deltaCutInEnergy) * ( (5. + 1. /var)*0.25 / (energy*energy) -
582                     beta2 / (tMax * deltaCutIn    574                     beta2 / (tMax * deltaCutInEnergy) ) / 3. ;
583   }                                               575   }
584       totalCrossSection *= twopi_mc2_rcl2 * at    576       totalCrossSection *= twopi_mc2_rcl2 * atomicNumber / beta2 ;
585     }                                             577     }
586                                                   578 
587   //std::cout << "Microscopic = " << totalCros    579   //std::cout << "Microscopic = " << totalCrossSection/barn 
588   //    << ", e = " << kineticEnergy/MeV <<std    580   //    << ", e = " << kineticEnergy/MeV <<std:: endl; 
589                                                   581 
590   return totalCrossSection ;                      582   return totalCrossSection ;
591 }                                                 583 }
592                                                   584 
593                                                   585 
594                                                   586 
595 // -------------------------------------------    587 // --------------------------------------------------------------------
596 G4double G4hImpactIonisation::GetMeanFreePath(    588 G4double G4hImpactIonisation::GetMeanFreePath(const G4Track& track,
597                 G4double, // previousStepSize     589                 G4double, // previousStepSize
598                 enum G4ForceCondition* conditi    590                 enum G4ForceCondition* condition)
599 {                                                 591 {
600   const G4DynamicParticle* dynamicParticle = t    592   const G4DynamicParticle* dynamicParticle = track.GetDynamicParticle();
601   const G4MaterialCutsCouple* couple = track.G    593   const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
602   const G4Material* material = couple->GetMate    594   const G4Material* material = couple->GetMaterial();
603                                                   595 
604   G4double meanFreePath = DBL_MAX;                596   G4double meanFreePath = DBL_MAX;
605   // ---- MGP ---- What is the meaning of the     597   // ---- MGP ---- What is the meaning of the local variable isOutOfRange?
606   G4bool isOutRange = false;                      598   G4bool isOutRange = false;
607                                                   599 
608   *condition = NotForced ;                        600   *condition = NotForced ;
609                                                   601 
610   G4double kineticEnergy = (dynamicParticle->G    602   G4double kineticEnergy = (dynamicParticle->GetKineticEnergy())*initialMass/(dynamicParticle->GetMass());
611   charge = dynamicParticle->GetCharge()/eplus;    603   charge = dynamicParticle->GetCharge()/eplus;
612   chargeSquare = theIonEffChargeModel->TheValu    604   chargeSquare = theIonEffChargeModel->TheValue(dynamicParticle, material);
613                                                   605 
614   if (kineticEnergy < LowestKineticEnergy)        606   if (kineticEnergy < LowestKineticEnergy) 
615     {                                             607     {
616       meanFreePath = DBL_MAX;                     608       meanFreePath = DBL_MAX;
617     }                                             609     }
618   else                                            610   else 
619     {                                             611     {
620       if (kineticEnergy > HighestKineticEnergy    612       if (kineticEnergy > HighestKineticEnergy)  kineticEnergy = HighestKineticEnergy;
621       meanFreePath = (((*theMeanFreePathTable)    613       meanFreePath = (((*theMeanFreePathTable)(couple->GetIndex()))->
622           GetValue(kineticEnergy,isOutRange))/    614           GetValue(kineticEnergy,isOutRange))/chargeSquare;
623     }                                             615     }
624                                                   616 
625   return meanFreePath ;                           617   return meanFreePath ;
626 }                                                 618 }
627                                                   619 
628                                                   620 
629 // -------------------------------------------    621 // --------------------------------------------------------------------
630 G4double G4hImpactIonisation::GetConstraints(c    622 G4double G4hImpactIonisation::GetConstraints(const G4DynamicParticle* particle,
631                const G4MaterialCutsCouple* cou    623                const G4MaterialCutsCouple* couple)
632 {                                                 624 {
633   // returns the Step limit                       625   // returns the Step limit
634   // dEdx is calculated as well as the range      626   // dEdx is calculated as well as the range
635   // based on Effective Charge Approach           627   // based on Effective Charge Approach
636                                                   628 
637   const G4Material* material = couple->GetMate    629   const G4Material* material = couple->GetMaterial();
638   G4Proton* proton = G4Proton::Proton();          630   G4Proton* proton = G4Proton::Proton();
639   G4AntiProton* antiproton = G4AntiProton::Ant    631   G4AntiProton* antiproton = G4AntiProton::AntiProton();
640                                                   632 
641   G4double stepLimit = 0.;                        633   G4double stepLimit = 0.;
642   G4double dx, highEnergy;                        634   G4double dx, highEnergy;
643                                                   635 
644   G4double massRatio = proton_mass_c2/(particl    636   G4double massRatio = proton_mass_c2/(particle->GetMass()) ;
645   G4double kineticEnergy = particle->GetKineti    637   G4double kineticEnergy = particle->GetKineticEnergy() ;
646                                                   638 
647   // Scale the kinetic energy                     639   // Scale the kinetic energy
648                                                   640 
649   G4double tScaled = kineticEnergy*massRatio ;    641   G4double tScaled = kineticEnergy*massRatio ;
650   fBarkas = 0.;                                   642   fBarkas = 0.;
651                                                   643 
652   if (charge > 0.)                                644   if (charge > 0.) 
653     {                                             645     {
654       highEnergy = protonHighEnergy ;             646       highEnergy = protonHighEnergy ;
655       fRangeNow = G4EnergyLossTables::GetRange    647       fRangeNow = G4EnergyLossTables::GetRange(proton, tScaled, couple);
656       dx = G4EnergyLossTables::GetRange(proton    648       dx = G4EnergyLossTables::GetRange(proton, highEnergy, couple);
657       fdEdx = G4EnergyLossTables::GetDEDX(prot    649       fdEdx = G4EnergyLossTables::GetDEDX(proton, tScaled, couple)
658   * chargeSquare ;                                650   * chargeSquare ;
659                                                   651       
660       // Correction for positive ions             652       // Correction for positive ions
661       if (theBarkas && tScaled > highEnergy)      653       if (theBarkas && tScaled > highEnergy) 
662   {                                               654   { 
663     fBarkas = BarkasTerm(material,tScaled)*std    655     fBarkas = BarkasTerm(material,tScaled)*std::sqrt(chargeSquare)*chargeSquare
664       + BlochTerm(material,tScaled,chargeSquar    656       + BlochTerm(material,tScaled,chargeSquare);
665   }                                               657   }
666       // Antiprotons and negative hadrons         658       // Antiprotons and negative hadrons
667     }                                             659     } 
668   else                                            660   else 
669     {                                             661     {
670       highEnergy = antiprotonHighEnergy ;         662       highEnergy = antiprotonHighEnergy ;
671       fRangeNow = G4EnergyLossTables::GetRange    663       fRangeNow = G4EnergyLossTables::GetRange(antiproton, tScaled, couple);
672       dx = G4EnergyLossTables::GetRange(antipr    664       dx = G4EnergyLossTables::GetRange(antiproton, highEnergy, couple);
673       fdEdx = G4EnergyLossTables::GetDEDX(anti    665       fdEdx = G4EnergyLossTables::GetDEDX(antiproton, tScaled, couple) * chargeSquare ;
674                                                   666       
675       if (theBarkas && tScaled > highEnergy)      667       if (theBarkas && tScaled > highEnergy) 
676   {                                               668   { 
677     fBarkas = -BarkasTerm(material,tScaled)*st    669     fBarkas = -BarkasTerm(material,tScaled)*std::sqrt(chargeSquare)*chargeSquare
678       + BlochTerm(material,tScaled,chargeSquar    670       + BlochTerm(material,tScaled,chargeSquare);
679   }                                               671   } 
680     }                                             672     } 
681   /*                                              673   /*
682     const G4Material* mat = couple->GetMateria    674     const G4Material* mat = couple->GetMaterial();
683     G4double fac = gram/(MeV*cm2*mat->GetDensi    675     G4double fac = gram/(MeV*cm2*mat->GetDensity());
684     G4cout << particle->GetDefinition()->GetPa    676     G4cout << particle->GetDefinition()->GetParticleName()
685     << " in " << mat->GetName()                   677     << " in " << mat->GetName()
686     << " E(MeV)= " << kineticEnergy/MeV           678     << " E(MeV)= " << kineticEnergy/MeV
687     << " dedx(MeV*cm^2/g)= " << fdEdx*fac         679     << " dedx(MeV*cm^2/g)= " << fdEdx*fac
688     << " barcas(MeV*cm^2/gram)= " << fBarkas*f    680     << " barcas(MeV*cm^2/gram)= " << fBarkas*fac
689     << " Q^2= " << chargeSquare                   681     << " Q^2= " << chargeSquare
690     << G4endl;                                    682     << G4endl;
691   */                                              683   */
692   // scaling back                                 684   // scaling back
693   fRangeNow /= (chargeSquare*massRatio) ;         685   fRangeNow /= (chargeSquare*massRatio) ;
694   dx        /= (chargeSquare*massRatio) ;         686   dx        /= (chargeSquare*massRatio) ;
695                                                   687 
696   stepLimit  = fRangeNow ;                        688   stepLimit  = fRangeNow ;
697   G4double r = std::min(finalRange, couple->Ge    689   G4double r = std::min(finalRange, couple->GetProductionCuts()
698       ->GetProductionCut(idxG4ElectronCut));      690       ->GetProductionCut(idxG4ElectronCut));
699                                                   691 
700   if (fRangeNow > r)                              692   if (fRangeNow > r) 
701     {                                             693     {  
702       stepLimit = dRoverRange*fRangeNow + r*(1    694       stepLimit = dRoverRange*fRangeNow + r*(1.0 - dRoverRange)*(2.0 - r/fRangeNow);
703       if (stepLimit > fRangeNow) stepLimit = f    695       if (stepLimit > fRangeNow) stepLimit = fRangeNow;
704     }                                             696     }  
705   //   compute the (random) Step limit in stan    697   //   compute the (random) Step limit in standard energy range
706   if(tScaled > highEnergy )                       698   if(tScaled > highEnergy ) 
707     {                                             699     {    
708       // add Barkas correction directly to ded    700       // add Barkas correction directly to dedx
709       fdEdx  += fBarkas;                          701       fdEdx  += fBarkas;
710                                                   702       
711       if(stepLimit > fRangeNow - dx*0.9) stepL    703       if(stepLimit > fRangeNow - dx*0.9) stepLimit = fRangeNow - dx*0.9 ;
712                                                   704       
713       // Step limit in low energy range           705       // Step limit in low energy range
714     }                                             706     } 
715   else                                            707   else 
716     {                                             708     {
717       G4double x = dx*paramStepLimit;             709       G4double x = dx*paramStepLimit;
718       if (stepLimit > x) stepLimit = x;           710       if (stepLimit > x) stepLimit = x;
719     }                                             711     }
720   return stepLimit;                               712   return stepLimit;
721 }                                                 713 }
722                                                   714 
723                                                   715 
724 // -------------------------------------------    716 // --------------------------------------------------------------------
725 G4VParticleChange* G4hImpactIonisation::AlongS    717 G4VParticleChange* G4hImpactIonisation::AlongStepDoIt(const G4Track& track,
726                   const G4Step& step)             718                   const G4Step& step)
727 {                                                 719 {
728   // compute the energy loss after a step         720   // compute the energy loss after a step
729   G4Proton* proton = G4Proton::Proton();          721   G4Proton* proton = G4Proton::Proton();
730   G4AntiProton* antiproton = G4AntiProton::Ant    722   G4AntiProton* antiproton = G4AntiProton::AntiProton();
731   G4double finalT = 0.;                           723   G4double finalT = 0.;
732                                                   724 
733   aParticleChange.Initialize(track) ;             725   aParticleChange.Initialize(track) ;
734                                                   726 
735   const G4MaterialCutsCouple* couple = track.G    727   const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
736   const G4Material* material = couple->GetMate    728   const G4Material* material = couple->GetMaterial();
737                                                   729 
738   // get the actual (true) Step length from st    730   // get the actual (true) Step length from step
739   const G4double stepLength = step.GetStepLeng    731   const G4double stepLength = step.GetStepLength() ;
740                                                   732 
741   const G4DynamicParticle* particle = track.Ge    733   const G4DynamicParticle* particle = track.GetDynamicParticle() ;
742                                                   734 
743   G4double kineticEnergy = particle->GetKineti    735   G4double kineticEnergy = particle->GetKineticEnergy() ;
744   G4double massRatio = proton_mass_c2/(particl    736   G4double massRatio = proton_mass_c2/(particle->GetMass()) ;
745   G4double tScaled = kineticEnergy * massRatio    737   G4double tScaled = kineticEnergy * massRatio ;
746   G4double eLoss = 0.0 ;                          738   G4double eLoss = 0.0 ;
747   G4double nLoss = 0.0 ;                          739   G4double nLoss = 0.0 ;
748                                                   740 
749                                                   741 
750   // very small particle energy                   742   // very small particle energy
751   if (kineticEnergy < MinKineticEnergy)           743   if (kineticEnergy < MinKineticEnergy) 
752     {                                             744     {
753       eLoss = kineticEnergy ;                     745       eLoss = kineticEnergy ;
754       // particle energy outside tabulated ene    746       // particle energy outside tabulated energy range
755     }                                             747     } 
756                                                   748   
757   else if( kineticEnergy > HighestKineticEnerg    749   else if( kineticEnergy > HighestKineticEnergy) 
758     {                                             750     {
759       eLoss = stepLength * fdEdx ;                751       eLoss = stepLength * fdEdx ;
760       // big step                                 752       // big step
761     }                                             753     } 
762   else if (stepLength >= fRangeNow )              754   else if (stepLength >= fRangeNow ) 
763     {                                             755     {
764       eLoss = kineticEnergy ;                     756       eLoss = kineticEnergy ;
765                                                   757       
766       // tabulated range                          758       // tabulated range
767     }                                             759     } 
768   else                                            760   else 
769     {                                             761     {
770       // step longer than linear step limit       762       // step longer than linear step limit
771       if(stepLength > linLossLimit * fRangeNow    763       if(stepLength > linLossLimit * fRangeNow) 
772   {                                               764   {
773     G4double rScaled = fRangeNow * massRatio *    765     G4double rScaled = fRangeNow * massRatio * chargeSquare ;
774     G4double sScaled = stepLength * massRatio     766     G4double sScaled = stepLength * massRatio * chargeSquare ;
775                                                   767     
776     if(charge > 0.0)                              768     if(charge > 0.0) 
777       {                                           769       {
778         eLoss = G4EnergyLossTables::GetPrecise    770         eLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(proton,rScaled, couple) -
779     G4EnergyLossTables::GetPreciseEnergyFromRa    771     G4EnergyLossTables::GetPreciseEnergyFromRange(proton,rScaled-sScaled,couple) ;
780                                                   772       
781       }                                           773       } 
782     else                                          774     else 
783       {                                           775       {
784         // Antiproton                             776         // Antiproton
785         eLoss = G4EnergyLossTables::GetPrecise    777         eLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(antiproton,rScaled,couple) -
786     G4EnergyLossTables::GetPreciseEnergyFromRa    778     G4EnergyLossTables::GetPreciseEnergyFromRange(antiproton,rScaled-sScaled,couple) ;
787       }                                           779       }
788     eLoss /= massRatio ;                          780     eLoss /= massRatio ;
789                                                   781     
790     // Barkas correction at big step              782     // Barkas correction at big step      
791     eLoss += fBarkas * stepLength;                783     eLoss += fBarkas * stepLength;
792                                                   784     
793     // step shorter than linear step limit        785     // step shorter than linear step limit
794   }                                               786   } 
795       else                                        787       else 
796   {                                               788   {
797     eLoss = stepLength *fdEdx  ;                  789     eLoss = stepLength *fdEdx  ;
798   }                                               790   }
799       if (nStopping && tScaled < protonHighEne    791       if (nStopping && tScaled < protonHighEnergy) 
800   {                                               792   {
801     nLoss = (theNuclearStoppingModel->TheValue    793     nLoss = (theNuclearStoppingModel->TheValue(particle, material)) * stepLength;
802   }                                               794   }
803     }                                             795     }
804                                                   796   
805   if (eLoss < 0.0) eLoss = 0.0;                   797   if (eLoss < 0.0) eLoss = 0.0;
806                                                   798 
807   finalT = kineticEnergy - eLoss - nLoss;         799   finalT = kineticEnergy - eLoss - nLoss;
808                                                   800 
809   if ( EnlossFlucFlag && 0.0 < eLoss && finalT    801   if ( EnlossFlucFlag && 0.0 < eLoss && finalT > MinKineticEnergy) 
810     {                                             802     {
811                                                   803       
812       //  now the electron loss with fluctuati    804       //  now the electron loss with fluctuation
813       eLoss = ElectronicLossFluctuation(partic    805       eLoss = ElectronicLossFluctuation(particle, couple, eLoss, stepLength) ;
814       if (eLoss < 0.0) eLoss = 0.0;               806       if (eLoss < 0.0) eLoss = 0.0;
815       finalT = kineticEnergy - eLoss - nLoss;     807       finalT = kineticEnergy - eLoss - nLoss;
816     }                                             808     }
817                                                   809 
818   //  stop particle if the kinetic energy <= M    810   //  stop particle if the kinetic energy <= MinKineticEnergy
819   if (finalT*massRatio <= MinKineticEnergy )      811   if (finalT*massRatio <= MinKineticEnergy ) 
820     {                                             812     {
821                                                   813       
822       finalT = 0.0;                               814       finalT = 0.0;
823       if (!particle->GetDefinition()->GetProce    815       if (!particle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
824         aParticleChange.ProposeTrackStatus(fSt    816         aParticleChange.ProposeTrackStatus(fStopAndKill);
825       else                                        817       else
826         aParticleChange.ProposeTrackStatus(fSt    818         aParticleChange.ProposeTrackStatus(fStopButAlive);
827     }                                             819     }
828                                                   820 
829   aParticleChange.ProposeEnergy( finalT );        821   aParticleChange.ProposeEnergy( finalT );
830   eLoss = kineticEnergy-finalT;                   822   eLoss = kineticEnergy-finalT;
831                                                   823 
832   aParticleChange.ProposeLocalEnergyDeposit(eL    824   aParticleChange.ProposeLocalEnergyDeposit(eLoss);
833   return &aParticleChange ;                       825   return &aParticleChange ;
834 }                                                 826 }
835                                                   827 
836                                                   828 
837                                                   829 
838 // -------------------------------------------    830 // --------------------------------------------------------------------
839 G4double G4hImpactIonisation::ProtonParametris    831 G4double G4hImpactIonisation::ProtonParametrisedDEDX(const G4MaterialCutsCouple* couple,
840                  G4double kineticEnergy) const    832                  G4double kineticEnergy) const
841 {                                                 833 {
842   const G4Material* material = couple->GetMate    834   const G4Material* material = couple->GetMaterial();
843   G4Proton* proton = G4Proton::Proton();          835   G4Proton* proton = G4Proton::Proton();
844   G4double eLoss = 0.;                            836   G4double eLoss = 0.;
845                                                   837 
846   // Free Electron Gas Model                      838   // Free Electron Gas Model
847   if(kineticEnergy < protonLowEnergy) {           839   if(kineticEnergy < protonLowEnergy) {
848     eLoss = (protonModel->TheValue(proton, mat    840     eLoss = (protonModel->TheValue(proton, material, protonLowEnergy))
849       * std::sqrt(kineticEnergy/protonLowEnerg    841       * std::sqrt(kineticEnergy/protonLowEnergy) ;
850                                                   842 
851     // Parametrisation                            843     // Parametrisation
852   } else {                                        844   } else {
853     eLoss = protonModel->TheValue(proton, mate    845     eLoss = protonModel->TheValue(proton, material, kineticEnergy) ;
854   }                                               846   }
855                                                   847 
856   // Delta rays energy                            848   // Delta rays energy
857   eLoss -= DeltaRaysEnergy(couple,kineticEnerg    849   eLoss -= DeltaRaysEnergy(couple,kineticEnergy,proton_mass_c2) ;
858                                                   850 
859   if(verboseLevel > 2) {                          851   if(verboseLevel > 2) {
860     G4cout << "p E(MeV)= " << kineticEnergy/Me    852     G4cout << "p E(MeV)= " << kineticEnergy/MeV
861            << " dE/dx(MeV/mm)= " << eLoss*mm/M    853            << " dE/dx(MeV/mm)= " << eLoss*mm/MeV
862            << " for " << material->GetName()      854            << " for " << material->GetName()
863            << " model: " << protonModel << G4e    855            << " model: " << protonModel << G4endl;
864   }                                               856   }
865                                                   857 
866   if(eLoss < 0.0) eLoss = 0.0 ;                   858   if(eLoss < 0.0) eLoss = 0.0 ;
867                                                   859 
868   return eLoss ;                                  860   return eLoss ;
869 }                                                 861 }
870                                                   862 
871                                                   863 
872                                                   864 
873 // -------------------------------------------    865 // --------------------------------------------------------------------
874 G4double G4hImpactIonisation::AntiProtonParame    866 G4double G4hImpactIonisation::AntiProtonParametrisedDEDX(const G4MaterialCutsCouple* couple,
875                G4double kineticEnergy) const      867                G4double kineticEnergy) const
876 {                                                 868 {
877   const G4Material* material = couple->GetMate    869   const G4Material* material = couple->GetMaterial();
878   G4AntiProton* antiproton = G4AntiProton::Ant    870   G4AntiProton* antiproton = G4AntiProton::AntiProton();
879   G4double eLoss = 0.0 ;                          871   G4double eLoss = 0.0 ;
880                                                   872 
881   // Antiproton model is used                     873   // Antiproton model is used
882   if(antiprotonModel->IsInCharge(antiproton,ma    874   if(antiprotonModel->IsInCharge(antiproton,material)) {
883     if(kineticEnergy < antiprotonLowEnergy) {     875     if(kineticEnergy < antiprotonLowEnergy) {
884       eLoss = antiprotonModel->TheValue(antipr    876       eLoss = antiprotonModel->TheValue(antiproton,material,antiprotonLowEnergy)
885   * std::sqrt(kineticEnergy/antiprotonLowEnerg    877   * std::sqrt(kineticEnergy/antiprotonLowEnergy) ;
886                                                   878 
887       // Parametrisation                          879       // Parametrisation
888     } else {                                      880     } else {
889       eLoss = antiprotonModel->TheValue(antipr    881       eLoss = antiprotonModel->TheValue(antiproton,material,
890           kineticEnergy);                         882           kineticEnergy);
891     }                                             883     }
892                                                   884 
893     // The proton model is used + Barkas corre    885     // The proton model is used + Barkas correction
894   } else {                                        886   } else {
895     if(kineticEnergy < protonLowEnergy) {         887     if(kineticEnergy < protonLowEnergy) {
896       eLoss = protonModel->TheValue(G4Proton::    888       eLoss = protonModel->TheValue(G4Proton::Proton(),material,protonLowEnergy)
897   * std::sqrt(kineticEnergy/protonLowEnergy) ;    889   * std::sqrt(kineticEnergy/protonLowEnergy) ;
898                                                   890 
899       // Parametrisation                          891       // Parametrisation
900     } else {                                      892     } else {
901       eLoss = protonModel->TheValue(G4Proton::    893       eLoss = protonModel->TheValue(G4Proton::Proton(),material,
902             kineticEnergy);                       894             kineticEnergy);
903     }                                             895     }
904     //if(theBarkas) eLoss -= 2.0*BarkasTerm(ma    896     //if(theBarkas) eLoss -= 2.0*BarkasTerm(material, kineticEnergy);
905   }                                               897   }
906                                                   898 
907   // Delta rays energy                            899   // Delta rays energy
908   eLoss -= DeltaRaysEnergy(couple,kineticEnerg    900   eLoss -= DeltaRaysEnergy(couple,kineticEnergy,proton_mass_c2) ;
909                                                   901 
910   if(verboseLevel > 2) {                          902   if(verboseLevel > 2) {
911     G4cout << "pbar E(MeV)= " << kineticEnergy    903     G4cout << "pbar E(MeV)= " << kineticEnergy/MeV
912            << " dE/dx(MeV/mm)= " << eLoss*mm/M    904            << " dE/dx(MeV/mm)= " << eLoss*mm/MeV
913            << " for " << material->GetName()      905            << " for " << material->GetName()
914            << " model: " << protonModel << G4e    906            << " model: " << protonModel << G4endl;
915   }                                               907   }
916                                                   908 
917   if(eLoss < 0.0) eLoss = 0.0 ;                   909   if(eLoss < 0.0) eLoss = 0.0 ;
918                                                   910 
919   return eLoss ;                                  911   return eLoss ;
920 }                                                 912 }
921                                                   913 
922                                                   914 
923 // -------------------------------------------    915 // --------------------------------------------------------------------
924 G4double G4hImpactIonisation::DeltaRaysEnergy(    916 G4double G4hImpactIonisation::DeltaRaysEnergy(const G4MaterialCutsCouple* couple,
925                 G4double kineticEnergy,           917                 G4double kineticEnergy,
926                 G4double particleMass) const      918                 G4double particleMass) const
927 {                                                 919 {
928   G4double dLoss = 0.;                            920   G4double dLoss = 0.;
929                                                   921 
930   G4double deltaCutNow = cutForDelta[(couple->    922   G4double deltaCutNow = cutForDelta[(couple->GetIndex())] ;
931   const G4Material* material = couple->GetMate    923   const G4Material* material = couple->GetMaterial();
932   G4double electronDensity = material->GetElec    924   G4double electronDensity = material->GetElectronDensity();
933   G4double excitationEnergy = material->GetIon    925   G4double excitationEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
934                                                   926 
935   G4double tau = kineticEnergy / particleMass     927   G4double tau = kineticEnergy / particleMass ;
936   G4double rateMass = electron_mass_c2/particl    928   G4double rateMass = electron_mass_c2/particleMass ;
937                                                   929 
938   // some local variables                         930   // some local variables
939                                                   931 
940   G4double gamma = tau + 1.0 ;                    932   G4double gamma = tau + 1.0 ;
941   G4double bg2 = tau*(tau+2.0) ;                  933   G4double bg2 = tau*(tau+2.0) ;
942   G4double beta2 = bg2/(gamma*gamma) ;            934   G4double beta2 = bg2/(gamma*gamma) ;
943   G4double tMax = 2.*electron_mass_c2*bg2/(1.0    935   G4double tMax = 2.*electron_mass_c2*bg2/(1.0+2.0*gamma*rateMass+rateMass*rateMass) ;
944                                                   936 
945   // Validity range for delta electron cross s    937   // Validity range for delta electron cross section
946   G4double deltaCut = std::max(deltaCutNow, ex    938   G4double deltaCut = std::max(deltaCutNow, excitationEnergy);
947                                                   939 
948   if ( deltaCut < tMax)                           940   if ( deltaCut < tMax) 
949     {                                             941     {
950       G4double x = deltaCut / tMax ;              942       G4double x = deltaCut / tMax ;
951       dLoss = ( beta2 * (x-1.) - std::log(x) )    943       dLoss = ( beta2 * (x-1.) - std::log(x) ) * twopi_mc2_rcl2 * electronDensity / beta2 ;
952     }                                             944     }
953   return dLoss ;                                  945   return dLoss ;
954 }                                                 946 }
955                                                   947 
956                                                   948 
957 // -------------------------------------------    949 // -------------------------------------------------------------------------
958                                                   950 
959 G4VParticleChange* G4hImpactIonisation::PostSt    951 G4VParticleChange* G4hImpactIonisation::PostStepDoIt(const G4Track& track,
960                  const G4Step& step)              952                  const G4Step& step)
961 {                                                 953 {
962   // Units are expressed in GEANT4 internal un    954   // Units are expressed in GEANT4 internal units.
963                                                   955 
964   //  std::cout << "----- Calling PostStepDoIt    956   //  std::cout << "----- Calling PostStepDoIt ----- " << std::endl;
965                                                   957 
966   aParticleChange.Initialize(track) ;             958   aParticleChange.Initialize(track) ;
967   const G4MaterialCutsCouple* couple = track.G    959   const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();  
968   const G4DynamicParticle* aParticle = track.G    960   const G4DynamicParticle* aParticle = track.GetDynamicParticle() ;
969                                                   961   
970   // Some kinematics                              962   // Some kinematics
971                                                   963 
972   G4ParticleDefinition* definition = track.Get    964   G4ParticleDefinition* definition = track.GetDefinition();
973   G4double mass = definition->GetPDGMass();       965   G4double mass = definition->GetPDGMass();
974   G4double kineticEnergy = aParticle->GetKinet    966   G4double kineticEnergy = aParticle->GetKineticEnergy();
975   G4double totalEnergy = kineticEnergy + mass     967   G4double totalEnergy = kineticEnergy + mass ;
976   G4double pSquare = kineticEnergy *( totalEne    968   G4double pSquare = kineticEnergy *( totalEnergy + mass) ;
977   G4double eSquare = totalEnergy * totalEnergy    969   G4double eSquare = totalEnergy * totalEnergy;
978   G4double betaSquare = pSquare / eSquare;        970   G4double betaSquare = pSquare / eSquare;
979   G4ThreeVector particleDirection = aParticle-    971   G4ThreeVector particleDirection = aParticle->GetMomentumDirection() ;
980                                                   972 
981   G4double gamma = kineticEnergy / mass + 1.;     973   G4double gamma = kineticEnergy / mass + 1.;
982   G4double r = electron_mass_c2 / mass;           974   G4double r = electron_mass_c2 / mass;
983   G4double tMax = 2. * electron_mass_c2 *(gamm    975   G4double tMax = 2. * electron_mass_c2 *(gamma*gamma - 1.) / (1. + 2.*gamma*r + r*r);
984                                                   976 
985   // Validity range for delta electron cross s    977   // Validity range for delta electron cross section
986   G4double deltaCut = cutForDelta[couple->GetI    978   G4double deltaCut = cutForDelta[couple->GetIndex()];
987                                                   979 
988   // This should not be a case                    980   // This should not be a case
989   if (deltaCut >= tMax)                           981   if (deltaCut >= tMax)
990     return G4VContinuousDiscreteProcess::PostS    982     return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
991                                                   983 
992   G4double xc = deltaCut / tMax;                  984   G4double xc = deltaCut / tMax;
993   G4double rate = tMax / totalEnergy;             985   G4double rate = tMax / totalEnergy;
994   rate = rate*rate ;                              986   rate = rate*rate ;
995   G4double spin = aParticle->GetDefinition()->    987   G4double spin = aParticle->GetDefinition()->GetPDGSpin() ;
996                                                   988 
997   // Sampling follows ...                         989   // Sampling follows ...
998   G4double x = 0.;                                990   G4double x = 0.;
999   G4double gRej = 0.;                             991   G4double gRej = 0.;
1000                                                  992 
1001   do {                                           993   do {
1002     x = xc / (1. - (1. - xc) * G4UniformRand(    994     x = xc / (1. - (1. - xc) * G4UniformRand());
1003                                                  995     
1004     if (0.0 == spin)                             996     if (0.0 == spin) 
1005       {                                          997       {
1006   gRej = 1.0 - betaSquare * x ;                  998   gRej = 1.0 - betaSquare * x ;
1007       }                                          999       }
1008     else if (0.5 == spin)                        1000     else if (0.5 == spin) 
1009       {                                          1001       {
1010   gRej = (1. - betaSquare * x + 0.5 * x*x * r    1002   gRej = (1. - betaSquare * x + 0.5 * x*x * rate) / (1. + 0.5 * rate) ;
1011       }                                          1003       } 
1012     else                                         1004     else 
1013       {                                          1005       {
1014   gRej = (1. - betaSquare * x ) * (1. + x/(3.    1006   gRej = (1. - betaSquare * x ) * (1. + x/(3.*xc)) +
1015     x*x * rate * (1. + 0.5*x/xc) / 3.0 /         1007     x*x * rate * (1. + 0.5*x/xc) / 3.0 /
1016     (1. + 1./(3.*xc) + rate *(1.+ 0.5/xc) / 3    1008     (1. + 1./(3.*xc) + rate *(1.+ 0.5/xc) / 3.);
1017       }                                          1009       }
1018                                                  1010     
1019   } while( G4UniformRand() > gRej );             1011   } while( G4UniformRand() > gRej );
1020                                                  1012 
1021   G4double deltaKineticEnergy = x * tMax;        1013   G4double deltaKineticEnergy = x * tMax;
1022   G4double deltaTotalMomentum = std::sqrt(del    1014   G4double deltaTotalMomentum = std::sqrt(deltaKineticEnergy * 
1023             (deltaKineticEnergy + 2. * electr    1015             (deltaKineticEnergy + 2. * electron_mass_c2 ));
1024   G4double totalMomentum = std::sqrt(pSquare)    1016   G4double totalMomentum = std::sqrt(pSquare) ;
1025   G4double cosTheta = deltaKineticEnergy * (t    1017   G4double cosTheta = deltaKineticEnergy * (totalEnergy + electron_mass_c2) / (deltaTotalMomentum*totalMomentum);
1026                                                  1018 
1027   //  protection against cosTheta > 1 or < -1    1019   //  protection against cosTheta > 1 or < -1 
1028   if ( cosTheta < -1. ) cosTheta = -1.;          1020   if ( cosTheta < -1. ) cosTheta = -1.;
1029   if ( cosTheta > 1. ) cosTheta = 1.;            1021   if ( cosTheta > 1. ) cosTheta = 1.;
1030                                                  1022 
1031   //  direction of the delta electron            1023   //  direction of the delta electron 
1032   G4double phi = twopi * G4UniformRand();        1024   G4double phi = twopi * G4UniformRand();
1033   G4double sinTheta = std::sqrt(1. - cosTheta    1025   G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
1034   G4double dirX = sinTheta * std::cos(phi);      1026   G4double dirX = sinTheta * std::cos(phi);
1035   G4double dirY = sinTheta * std::sin(phi);      1027   G4double dirY = sinTheta * std::sin(phi);
1036   G4double dirZ = cosTheta;                      1028   G4double dirZ = cosTheta;
1037                                                  1029 
1038   G4ThreeVector deltaDirection(dirX,dirY,dirZ    1030   G4ThreeVector deltaDirection(dirX,dirY,dirZ);
1039   deltaDirection.rotateUz(particleDirection);    1031   deltaDirection.rotateUz(particleDirection);
1040                                                  1032 
1041   // create G4DynamicParticle object for delt    1033   // create G4DynamicParticle object for delta ray
1042   G4DynamicParticle* deltaRay = new G4Dynamic    1034   G4DynamicParticle* deltaRay = new G4DynamicParticle;
1043   deltaRay->SetKineticEnergy( deltaKineticEne    1035   deltaRay->SetKineticEnergy( deltaKineticEnergy );
1044   deltaRay->SetMomentumDirection(deltaDirecti    1036   deltaRay->SetMomentumDirection(deltaDirection.x(),
1045          deltaDirection.y(),                     1037          deltaDirection.y(),
1046          deltaDirection.z());                    1038          deltaDirection.z());
1047   deltaRay->SetDefinition(G4Electron::Electro    1039   deltaRay->SetDefinition(G4Electron::Electron());
1048                                                  1040 
1049   // fill aParticleChange                        1041   // fill aParticleChange
1050   G4double finalKineticEnergy = kineticEnergy    1042   G4double finalKineticEnergy = kineticEnergy - deltaKineticEnergy;
1051   std::size_t totalNumber = 1;                << 1043   size_t totalNumber = 1;
1052                                                  1044 
1053   // Atomic relaxation                           1045   // Atomic relaxation
1054                                                  1046 
1055   // ---- MGP ---- Temporary limitation: curr    1047   // ---- MGP ---- Temporary limitation: currently PIXE only for incident protons
1056                                                  1048 
1057   std::size_t nSecondaries = 0;               << 1049   size_t nSecondaries = 0;
1058   std::vector<G4DynamicParticle*>* secondaryV    1050   std::vector<G4DynamicParticle*>* secondaryVector = 0;
1059                                                  1051 
1060   if (definition == G4Proton::ProtonDefinitio    1052   if (definition == G4Proton::ProtonDefinition())
1061     {                                            1053     {
1062       const G4Material* material = couple->Ge    1054       const G4Material* material = couple->GetMaterial();
1063                                                  1055 
1064       // Lazy initialization of pixeCrossSect    1056       // Lazy initialization of pixeCrossSectionHandler
1065       if (pixeCrossSectionHandler == 0)          1057       if (pixeCrossSectionHandler == 0)
1066   {                                              1058   {
1067     // Instantiate pixeCrossSectionHandler wi    1059     // Instantiate pixeCrossSectionHandler with selected shell cross section models
1068     // Ownership of interpolation is transfer    1060     // Ownership of interpolation is transferred to pixeCrossSectionHandler
1069     G4IInterpolator* interpolation = new G4Lo    1061     G4IInterpolator* interpolation = new G4LogLogInterpolator();
1070     pixeCrossSectionHandler =                    1062     pixeCrossSectionHandler = 
1071       new G4PixeCrossSectionHandler(interpola    1063       new G4PixeCrossSectionHandler(interpolation,modelK,modelL,modelM,eMinPixe,eMaxPixe);
1072     G4String fileName("proton");                 1064     G4String fileName("proton");
1073     pixeCrossSectionHandler->LoadShellData(fi    1065     pixeCrossSectionHandler->LoadShellData(fileName);
1074     //    pixeCrossSectionHandler->PrintData(    1066     //    pixeCrossSectionHandler->PrintData();
1075   }                                              1067   }
1076                                                  1068       
1077       // Select an atom in the current materi    1069       // Select an atom in the current material based on the total shell cross sections
1078       G4int Z = pixeCrossSectionHandler->Sele    1070       G4int Z = pixeCrossSectionHandler->SelectRandomAtom(material,kineticEnergy);
1079       //      std::cout << "G4hImpactIonisati    1071       //      std::cout << "G4hImpactIonisation::PostStepDoIt - Z = " << Z << std::endl;
1080                                                  1072 
1081       //      G4double microscopicCross = Mic    1073       //      G4double microscopicCross = MicroscopicCrossSection(*definition,
1082       //                        kineticEnergy    1074       //                        kineticEnergy,
1083       //            Z, deltaCut);                1075       //            Z, deltaCut);
1084   //    G4double crossFromShells = pixeCrossS    1076   //    G4double crossFromShells = pixeCrossSectionHandler->FindValue(Z,kineticEnergy);
1085                                                  1077 
1086       //std::cout << "G4hImpactIonisation: Z=    1078       //std::cout << "G4hImpactIonisation: Z= "
1087       //    << Z                                 1079       //    << Z
1088       //    << ", energy = "                     1080       //    << ", energy = "
1089       //    << kineticEnergy/MeV                 1081       //    << kineticEnergy/MeV
1090       //    <<" MeV, microscopic = "             1082       //    <<" MeV, microscopic = "
1091       //    << microscopicCross/barn             1083       //    << microscopicCross/barn 
1092       //    << " barn, from shells = "           1084       //    << " barn, from shells = "
1093       //    << crossFromShells/barn              1085       //    << crossFromShells/barn
1094       //    << " barn"                           1086       //    << " barn" 
1095       //    << std::endl;                        1087       //    << std::endl;
1096                                                  1088 
1097       // Select a shell in the target atom ba    1089       // Select a shell in the target atom based on the individual shell cross sections
1098       G4int shellIndex = pixeCrossSectionHand    1090       G4int shellIndex = pixeCrossSectionHandler->SelectRandomShell(Z,kineticEnergy);
1099                                                  1091     
1100       G4AtomicTransitionManager* transitionMa    1092       G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
1101       const G4AtomicShell* atomicShell = tran    1093       const G4AtomicShell* atomicShell = transitionManager->Shell(Z,shellIndex);
1102       G4double bindingEnergy = atomicShell->B    1094       G4double bindingEnergy = atomicShell->BindingEnergy();
1103                                                  1095       
1104       //     if (verboseLevel > 1)               1096       //     if (verboseLevel > 1) 
1105       //       {                                 1097       //       {
1106       //   G4cout << "G4hImpactIonisation::Po    1098       //   G4cout << "G4hImpactIonisation::PostStepDoIt - Z = " 
1107       //         << Z                            1099       //         << Z 
1108       //   << ", shell = "                       1100       //   << ", shell = " 
1109       //   << shellIndex                         1101       //   << shellIndex
1110       //   << ", bindingE (keV) = "              1102       //   << ", bindingE (keV) = " 
1111       //   << bindingEnergy/keV                  1103       //   << bindingEnergy/keV
1112       //   << G4endl;                            1104       //   << G4endl;
1113       //       }                                 1105       //       }
1114                                                  1106       
1115       // Generate PIXE if binding energy larg    1107       // Generate PIXE if binding energy larger than cut for photons or electrons
1116                                                  1108       
1117       G4ParticleDefinition* type = 0;            1109       G4ParticleDefinition* type = 0;
1118                                                  1110       
1119       if (finalKineticEnergy >= bindingEnergy    1111       if (finalKineticEnergy >= bindingEnergy)
1120   //    && (bindingEnergy >= minGammaEnergy |    1112   //    && (bindingEnergy >= minGammaEnergy ||  bindingEnergy >= minElectronEnergy) ) 
1121   {                                              1113   {
1122     // Vacancy in subshell shellIndex; shellI    1114     // Vacancy in subshell shellIndex; shellId is the subshell identifier in EADL jargon 
1123     G4int shellId = atomicShell->ShellId();      1115     G4int shellId = atomicShell->ShellId();
1124     // Atomic relaxation: generate secondarie    1116     // Atomic relaxation: generate secondaries
1125     secondaryVector = atomicDeexcitation.Gene    1117     secondaryVector = atomicDeexcitation.GenerateParticles(Z, shellId);
1126                                                  1118 
1127     // ---- Debug ----                           1119     // ---- Debug ----
1128     //std::cout << "ShellId = "                  1120     //std::cout << "ShellId = "
1129     //    <<shellId << " ---- Atomic relaxati    1121     //    <<shellId << " ---- Atomic relaxation secondaries: ---- " 
1130     //    << secondaryVector->size()             1122     //    << secondaryVector->size()
1131     //    << std::endl;                          1123     //    << std::endl;
1132                                                  1124 
1133     // ---- End debug ---                        1125     // ---- End debug ---
1134                                                  1126 
1135     if (secondaryVector != 0)                    1127     if (secondaryVector != 0) 
1136       {                                          1128       {
1137         nSecondaries = secondaryVector->size(    1129         nSecondaries = secondaryVector->size();
1138         for (std::size_t i = 0; i<nSecondarie << 1130         for (size_t i = 0; i<nSecondaries; i++) 
1139     {                                            1131     {
1140       G4DynamicParticle* aSecondary = (*secon    1132       G4DynamicParticle* aSecondary = (*secondaryVector)[i];
1141       if (aSecondary)                            1133       if (aSecondary) 
1142         {                                        1134         {
1143           G4double e = aSecondary->GetKinetic    1135           G4double e = aSecondary->GetKineticEnergy();
1144           type = aSecondary->GetDefinition();    1136           type = aSecondary->GetDefinition();
1145                                                  1137 
1146           // ---- Debug ----                     1138           // ---- Debug ----
1147           //if (type == G4Gamma::GammaDefinit    1139           //if (type == G4Gamma::GammaDefinition())
1148           //  {                                  1140           //  {     
1149           //    std::cout << "Z = " << Z         1141           //    std::cout << "Z = " << Z 
1150           //        << ", shell: " << shellId    1142           //        << ", shell: " << shellId
1151           //        << ", PIXE photon energy     1143           //        << ", PIXE photon energy (keV) = " << e/keV 
1152           //        << std::endl;                1144           //        << std::endl;
1153           //  }                                  1145           //  }
1154           // ---- End debug ---                  1146           // ---- End debug ---
1155                                                  1147 
1156           if (e < finalKineticEnergy &&          1148           if (e < finalKineticEnergy &&
1157         ((type == G4Gamma::Gamma() && e > min    1149         ((type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
1158          (type == G4Electron::Electron() && e    1150          (type == G4Electron::Electron() && e > minElectronEnergy ))) 
1159       {                                          1151       {
1160         // Subtract the energy of the emitted    1152         // Subtract the energy of the emitted secondary from the primary
1161         finalKineticEnergy -= e;                 1153         finalKineticEnergy -= e;
1162         totalNumber++;                           1154         totalNumber++;
1163         // ---- Debug ----                       1155         // ---- Debug ----
1164         //if (type == G4Gamma::GammaDefinitio    1156         //if (type == G4Gamma::GammaDefinition())
1165         //  {                                    1157         //  {     
1166         //    std::cout << "Z = " << Z           1158         //    std::cout << "Z = " << Z 
1167         //        << ", shell: " << shellId      1159         //        << ", shell: " << shellId
1168         //        << ", PIXE photon energy (k    1160         //        << ", PIXE photon energy (keV) = " << e/keV
1169         //        << std::endl;                  1161         //        << std::endl;
1170         //  }                                    1162         //  }
1171         // ---- End debug ---                    1163         // ---- End debug ---
1172       }                                          1164       } 
1173           else                                   1165           else 
1174       {                                          1166       {
1175         // The atomic relaxation product has     1167         // The atomic relaxation product has energy below the cut
1176         // ---- Debug ----                       1168         // ---- Debug ----
1177         // if (type == G4Gamma::GammaDefiniti    1169         // if (type == G4Gamma::GammaDefinition())
1178         //  {                                    1170         //  {     
1179         //    std::cout << "Z = " << Z           1171         //    std::cout << "Z = " << Z 
1180         //                                       1172         //
1181         //        << ", PIXE photon energy =     1173         //        << ", PIXE photon energy = " << e/keV 
1182         //          << " keV below threshold     1174         //          << " keV below threshold " << minGammaEnergy/keV << " keV"
1183         //        << std::endl;                  1175         //        << std::endl;
1184         //  }                                    1176         //  }   
1185         // ---- End debug ---                    1177         // ---- End debug ---
1186                                                  1178      
1187         delete aSecondary;                       1179         delete aSecondary;
1188         (*secondaryVector)[i] = 0;               1180         (*secondaryVector)[i] = 0;
1189       }                                          1181       }
1190         }                                        1182         }
1191     }                                            1183     }
1192       }                                          1184       }
1193   }                                              1185   }
1194     }                                            1186     }
1195                                                  1187 
1196                                                  1188 
1197   // Save delta-electrons                        1189   // Save delta-electrons
1198                                                  1190 
1199   G4double eDeposit = 0.;                        1191   G4double eDeposit = 0.;
1200                                                  1192 
1201   if (finalKineticEnergy > MinKineticEnergy)     1193   if (finalKineticEnergy > MinKineticEnergy)
1202     {                                            1194     {
1203       G4double finalPx = totalMomentum*partic    1195       G4double finalPx = totalMomentum*particleDirection.x() - deltaTotalMomentum*deltaDirection.x();
1204       G4double finalPy = totalMomentum*partic    1196       G4double finalPy = totalMomentum*particleDirection.y() - deltaTotalMomentum*deltaDirection.y();
1205       G4double finalPz = totalMomentum*partic    1197       G4double finalPz = totalMomentum*particleDirection.z() - deltaTotalMomentum*deltaDirection.z();
1206       G4double finalMomentum = std::sqrt(fina    1198       G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz) ;
1207       finalPx /= finalMomentum;                  1199       finalPx /= finalMomentum;
1208       finalPy /= finalMomentum;                  1200       finalPy /= finalMomentum;
1209       finalPz /= finalMomentum;                  1201       finalPz /= finalMomentum;
1210                                                  1202 
1211       aParticleChange.ProposeMomentumDirectio    1203       aParticleChange.ProposeMomentumDirection( finalPx,finalPy,finalPz );
1212     }                                            1204     }
1213   else                                           1205   else
1214     {                                            1206     {
1215       eDeposit = finalKineticEnergy;             1207       eDeposit = finalKineticEnergy;
1216       finalKineticEnergy = 0.;                   1208       finalKineticEnergy = 0.;
1217       aParticleChange.ProposeMomentumDirectio    1209       aParticleChange.ProposeMomentumDirection(particleDirection.x(),
1218                  particleDirection.y(),          1210                  particleDirection.y(),
1219                  particleDirection.z());         1211                  particleDirection.z());
1220       if(!aParticle->GetDefinition()->GetProc    1212       if(!aParticle->GetDefinition()->GetProcessManager()->
1221    GetAtRestProcessVector()->size())             1213    GetAtRestProcessVector()->size())
1222         aParticleChange.ProposeTrackStatus(fS    1214         aParticleChange.ProposeTrackStatus(fStopAndKill);
1223       else                                       1215       else
1224         aParticleChange.ProposeTrackStatus(fS    1216         aParticleChange.ProposeTrackStatus(fStopButAlive);
1225     }                                            1217     }
1226                                                  1218 
1227   aParticleChange.ProposeEnergy(finalKineticE    1219   aParticleChange.ProposeEnergy(finalKineticEnergy);
1228   aParticleChange.ProposeLocalEnergyDeposit (    1220   aParticleChange.ProposeLocalEnergyDeposit (eDeposit);
1229   aParticleChange.SetNumberOfSecondaries((G4i << 1221   aParticleChange.SetNumberOfSecondaries(totalNumber);
1230   aParticleChange.AddSecondary(deltaRay);        1222   aParticleChange.AddSecondary(deltaRay);
1231                                                  1223 
1232   // ---- Debug ----                             1224   // ---- Debug ----
1233   //  std::cout << "RDHadronIonisation - fina    1225   //  std::cout << "RDHadronIonisation - finalKineticEnergy (MeV) = " 
1234   //      << finalKineticEnergy/MeV              1226   //      << finalKineticEnergy/MeV 
1235   //      << ", delta KineticEnergy (keV) = "    1227   //      << ", delta KineticEnergy (keV) = " 
1236   //      << deltaKineticEnergy/keV              1228   //      << deltaKineticEnergy/keV 
1237   //      << ", energy deposit (MeV) = "         1229   //      << ", energy deposit (MeV) = "
1238   //      << eDeposit/MeV                        1230   //      << eDeposit/MeV
1239   //      << std::endl;                          1231   //      << std::endl;
1240   // ---- End debug ---                          1232   // ---- End debug ---
1241                                                  1233   
1242   // Save Fluorescence and Auger                 1234   // Save Fluorescence and Auger
1243                                                  1235 
1244   if (secondaryVector != 0)                      1236   if (secondaryVector != 0) 
1245     {                                            1237     { 
1246       for (std::size_t l = 0; l < nSecondarie << 1238       for (size_t l = 0; l < nSecondaries; l++) 
1247   {                                              1239   { 
1248     G4DynamicParticle* secondary = (*secondar    1240     G4DynamicParticle* secondary = (*secondaryVector)[l];
1249     if (secondary) aParticleChange.AddSeconda    1241     if (secondary) aParticleChange.AddSecondary(secondary);
1250                                                  1242 
1251     // ---- Debug ----                           1243     // ---- Debug ----
1252     //if (secondary != 0)                        1244     //if (secondary != 0) 
1253     // {                                         1245     // {
1254     //   if (secondary->GetDefinition() == G4    1246     //   if (secondary->GetDefinition() == G4Gamma::GammaDefinition())
1255     //  {                                        1247     //  {
1256     //    G4double eX = secondary->GetKinetic    1248     //    G4double eX = secondary->GetKineticEnergy();      
1257     //    std::cout << " PIXE photon of energ    1249     //    std::cout << " PIXE photon of energy " << eX/keV 
1258     //        << " keV added to ParticleChang    1250     //        << " keV added to ParticleChange; total number of secondaries is " << totalNumber 
1259     //        << std::endl;                      1251     //        << std::endl;
1260     //  }                                        1252     //  }
1261     //}                                          1253     //}
1262     // ---- End debug ---                        1254     // ---- End debug ---   
1263                                                  1255 
1264   }                                              1256   }
1265       delete secondaryVector;                    1257       delete secondaryVector;
1266     }                                            1258     }
1267                                                  1259 
1268   return G4VContinuousDiscreteProcess::PostSt    1260   return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
1269 }                                                1261 }
1270                                                  1262 
1271 // ------------------------------------------    1263 // -------------------------------------------------------------------------
1272                                                  1264 
1273 G4double G4hImpactIonisation::ComputeDEDX(con    1265 G4double G4hImpactIonisation::ComputeDEDX(const G4ParticleDefinition* aParticle,
1274             const G4MaterialCutsCouple* coupl    1266             const G4MaterialCutsCouple* couple,
1275             G4double kineticEnergy)              1267             G4double kineticEnergy)
1276 {                                                1268 {
1277   const G4Material* material = couple->GetMat    1269   const G4Material* material = couple->GetMaterial();
1278   G4Proton* proton = G4Proton::Proton();         1270   G4Proton* proton = G4Proton::Proton();
1279   G4AntiProton* antiproton = G4AntiProton::An    1271   G4AntiProton* antiproton = G4AntiProton::AntiProton();
1280   G4double dedx = 0.;                            1272   G4double dedx = 0.;
1281                                                  1273 
1282   G4double tScaled = kineticEnergy * proton_m    1274   G4double tScaled = kineticEnergy * proton_mass_c2 / (aParticle->GetPDGMass()) ;
1283   charge  = aParticle->GetPDGCharge() ;          1275   charge  = aParticle->GetPDGCharge() ;
1284                                                  1276 
1285   if( charge > 0.)                               1277   if( charge > 0.) 
1286     {                                            1278     {
1287       if (tScaled > protonHighEnergy)            1279       if (tScaled > protonHighEnergy) 
1288   {                                              1280   {
1289     dedx = G4EnergyLossTables::GetDEDX(proton    1281     dedx = G4EnergyLossTables::GetDEDX(proton,tScaled,couple) ;  
1290   }                                              1282   }
1291       else                                       1283       else 
1292   {                                              1284   {
1293     dedx = ProtonParametrisedDEDX(couple,tSca    1285     dedx = ProtonParametrisedDEDX(couple,tScaled) ;
1294   }                                              1286   }
1295     }                                            1287     } 
1296   else                                           1288   else 
1297     {                                            1289     {
1298       if (tScaled > antiprotonHighEnergy)        1290       if (tScaled > antiprotonHighEnergy) 
1299   {                                              1291   {
1300     dedx = G4EnergyLossTables::GetDEDX(antipr    1292     dedx = G4EnergyLossTables::GetDEDX(antiproton,tScaled,couple);
1301   }                                              1293   } 
1302       else                                       1294       else
1303   {                                              1295   {
1304     dedx = AntiProtonParametrisedDEDX(couple,    1296     dedx = AntiProtonParametrisedDEDX(couple,tScaled) ;
1305   }                                              1297   }
1306     }                                            1298     }
1307   dedx *= theIonEffChargeModel->TheValue(aPar    1299   dedx *= theIonEffChargeModel->TheValue(aParticle, material, kineticEnergy) ;
1308                                                  1300   
1309   return dedx ;                                  1301   return dedx ;
1310 }                                                1302 }
1311                                                  1303 
1312                                                  1304 
1313 G4double G4hImpactIonisation::BarkasTerm(cons    1305 G4double G4hImpactIonisation::BarkasTerm(const G4Material* material,
1314            G4double kineticEnergy) const         1306            G4double kineticEnergy) const
1315 //Function to compute the Barkas term for pro    1307 //Function to compute the Barkas term for protons:
1316 //                                               1308 //
1317 //Ref. Z_1^3 effect in the stopping power of     1309 //Ref. Z_1^3 effect in the stopping power of matter for charged particles
1318 //     J.C Ashley and R.H.Ritchie                1310 //     J.C Ashley and R.H.Ritchie
1319 //     Physical review B Vol.5 No.7 1 April 1    1311 //     Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397
1320 //                                               1312 //
1321 {                                                1313 {
1322   static G4ThreadLocal G4double FTable[47][2]    1314   static G4ThreadLocal G4double FTable[47][2] = {
1323     { 0.02, 21.5},                               1315     { 0.02, 21.5},
1324     { 0.03, 20.0},                               1316     { 0.03, 20.0},
1325     { 0.04, 18.0},                               1317     { 0.04, 18.0},
1326     { 0.05, 15.6},                               1318     { 0.05, 15.6},
1327     { 0.06, 15.0},                               1319     { 0.06, 15.0},
1328     { 0.07, 14.0},                               1320     { 0.07, 14.0},
1329     { 0.08, 13.5},                               1321     { 0.08, 13.5},
1330     { 0.09, 13.},                                1322     { 0.09, 13.},
1331     { 0.1,  12.2},                               1323     { 0.1,  12.2},
1332     { 0.2,  9.25},                               1324     { 0.2,  9.25},
1333     { 0.3,  7.0},                                1325     { 0.3,  7.0},
1334     { 0.4,  6.0},                                1326     { 0.4,  6.0},
1335     { 0.5,  4.5},                                1327     { 0.5,  4.5},
1336     { 0.6,  3.5},                                1328     { 0.6,  3.5},
1337     { 0.7,  3.0},                                1329     { 0.7,  3.0},
1338     { 0.8,  2.5},                                1330     { 0.8,  2.5},
1339     { 0.9,  2.0},                                1331     { 0.9,  2.0},
1340     { 1.0,  1.7},                                1332     { 1.0,  1.7},
1341     { 1.2,  1.2},                                1333     { 1.2,  1.2},
1342     { 1.3,  1.0},                                1334     { 1.3,  1.0},
1343     { 1.4,  0.86},                               1335     { 1.4,  0.86},
1344     { 1.5,  0.7},                                1336     { 1.5,  0.7},
1345     { 1.6,  0.61},                               1337     { 1.6,  0.61},
1346     { 1.7,  0.52},                               1338     { 1.7,  0.52},
1347     { 1.8,  0.5},                                1339     { 1.8,  0.5},
1348     { 1.9,  0.43},                               1340     { 1.9,  0.43},
1349     { 2.0,  0.42},                               1341     { 2.0,  0.42},
1350     { 2.1,  0.3},                                1342     { 2.1,  0.3},
1351     { 2.4,  0.2},                                1343     { 2.4,  0.2},
1352     { 3.0,  0.13},                               1344     { 3.0,  0.13},
1353     { 3.08, 0.1},                                1345     { 3.08, 0.1},
1354     { 3.1,  0.09},                               1346     { 3.1,  0.09},
1355     { 3.3,  0.08},                               1347     { 3.3,  0.08},
1356     { 3.5,  0.07},                               1348     { 3.5,  0.07},
1357     { 3.8,  0.06},                               1349     { 3.8,  0.06},
1358     { 4.0,  0.051},                              1350     { 4.0,  0.051},
1359     { 4.1,  0.04},                               1351     { 4.1,  0.04},
1360     { 4.8,  0.03},                               1352     { 4.8,  0.03},
1361     { 5.0,  0.024},                              1353     { 5.0,  0.024},
1362     { 5.1,  0.02},                               1354     { 5.1,  0.02},
1363     { 6.0,  0.013},                              1355     { 6.0,  0.013},
1364     { 6.5,  0.01},                               1356     { 6.5,  0.01},
1365     { 7.0,  0.009},                              1357     { 7.0,  0.009},
1366     { 7.1,  0.008},                              1358     { 7.1,  0.008},
1367     { 8.0,  0.006},                              1359     { 8.0,  0.006},
1368     { 9.0,  0.0032},                             1360     { 9.0,  0.0032},
1369     { 10.0, 0.0025} };                           1361     { 10.0, 0.0025} };
1370                                                  1362 
1371   // Information on particle and material        1363   // Information on particle and material
1372   G4double kinE  = kineticEnergy ;               1364   G4double kinE  = kineticEnergy ;
1373   if(0.5*MeV > kinE) kinE = 0.5*MeV ;            1365   if(0.5*MeV > kinE) kinE = 0.5*MeV ;
1374   G4double gamma = 1.0 + kinE / proton_mass_c    1366   G4double gamma = 1.0 + kinE / proton_mass_c2 ;
1375   G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;     1367   G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;
1376   if(0.0 >= beta2) return 0.0;                   1368   if(0.0 >= beta2) return 0.0;
1377                                                  1369 
1378   G4double BTerm = 0.0;                          1370   G4double BTerm = 0.0;
1379   //G4double AMaterial = 0.0;                    1371   //G4double AMaterial = 0.0;
1380   G4double ZMaterial = 0.0;                      1372   G4double ZMaterial = 0.0;
1381   const G4ElementVector* theElementVector = m    1373   const G4ElementVector* theElementVector = material->GetElementVector();
1382   G4int numberOfElements = (G4int)material->G << 1374   G4int numberOfElements = material->GetNumberOfElements();
1383                                                  1375 
1384   for (G4int i = 0; i<numberOfElements; i++)     1376   for (G4int i = 0; i<numberOfElements; i++) {
1385                                                  1377 
1386     //AMaterial = (*theElementVector)[i]->Get    1378     //AMaterial = (*theElementVector)[i]->GetA()*mole/g;
1387     ZMaterial = (*theElementVector)[i]->GetZ(    1379     ZMaterial = (*theElementVector)[i]->GetZ();
1388                                                  1380 
1389     G4double X = 137.0 * 137.0 * beta2 / ZMat    1381     G4double X = 137.0 * 137.0 * beta2 / ZMaterial;
1390                                                  1382 
1391     // Variables to compute L_1                  1383     // Variables to compute L_1
1392     G4double Eta0Chi = 0.8;                      1384     G4double Eta0Chi = 0.8;
1393     G4double EtaChi = Eta0Chi * ( 1.0 + 6.02*    1385     G4double EtaChi = Eta0Chi * ( 1.0 + 6.02*std::pow( ZMaterial,-1.19 ) );
1394     G4double W = ( EtaChi * std::pow( ZMateri    1386     G4double W = ( EtaChi * std::pow( ZMaterial,1.0/6.0 ) ) / std::sqrt(X);
1395     G4double FunctionOfW = FTable[46][1]*FTab    1387     G4double FunctionOfW = FTable[46][1]*FTable[46][0]/W ;
1396                                                  1388 
1397     for(G4int j=0; j<47; j++) {                  1389     for(G4int j=0; j<47; j++) {
1398                                                  1390 
1399       if( W < FTable[j][0] ) {                   1391       if( W < FTable[j][0] ) {
1400                                                  1392 
1401         if(0 == j) {                             1393         if(0 == j) {
1402         FunctionOfW = FTable[0][1] ;             1394         FunctionOfW = FTable[0][1] ;
1403                                                  1395 
1404         } else {                                 1396         } else {
1405           FunctionOfW = (FTable[j][1] - FTabl    1397           FunctionOfW = (FTable[j][1] - FTable[j-1][1]) * (W - FTable[j-1][0])
1406       / (FTable[j][0] - FTable[j-1][0])          1398       / (FTable[j][0] - FTable[j-1][0])
1407       +  FTable[j-1][1] ;                        1399       +  FTable[j-1][1] ;
1408   }                                              1400   }
1409                                                  1401 
1410         break;                                   1402         break;
1411       }                                          1403       }
1412                                                  1404 
1413     }                                            1405     }
1414                                                  1406 
1415     BTerm += FunctionOfW /( std::sqrt(ZMateri    1407     BTerm += FunctionOfW /( std::sqrt(ZMaterial * X) * X);
1416   }                                              1408   }
1417                                                  1409 
1418   BTerm *= twopi_mc2_rcl2 * (material->GetEle    1410   BTerm *= twopi_mc2_rcl2 * (material->GetElectronDensity()) / beta2 ;
1419                                                  1411 
1420   return BTerm;                                  1412   return BTerm;
1421 }                                                1413 }
1422                                                  1414 
1423                                                  1415 
1424                                                  1416 
1425 G4double G4hImpactIonisation::BlochTerm(const    1417 G4double G4hImpactIonisation::BlochTerm(const G4Material* material,
1426           G4double kineticEnergy,                1418           G4double kineticEnergy,
1427           G4double cSquare) const                1419           G4double cSquare) const
1428 //Function to compute the Bloch term for prot    1420 //Function to compute the Bloch term for protons:
1429 //                                               1421 //
1430 //Ref. Z_1^3 effect in the stopping power of     1422 //Ref. Z_1^3 effect in the stopping power of matter for charged particles
1431 //     J.C Ashley and R.H.Ritchie                1423 //     J.C Ashley and R.H.Ritchie
1432 //     Physical review B Vol.5 No.7 1 April 1    1424 //     Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397
1433 //                                               1425 //
1434 {                                                1426 {
1435   G4double eLoss = 0.0 ;                         1427   G4double eLoss = 0.0 ;
1436   G4double gamma = 1.0 + kineticEnergy / prot    1428   G4double gamma = 1.0 + kineticEnergy / proton_mass_c2 ;
1437   G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;     1429   G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;
1438   G4double y = cSquare / (137.0*137.0*beta2)     1430   G4double y = cSquare / (137.0*137.0*beta2) ;
1439                                                  1431 
1440   if(y < 0.05) {                                 1432   if(y < 0.05) {
1441     eLoss = 1.202 ;                              1433     eLoss = 1.202 ;
1442                                                  1434 
1443   } else {                                       1435   } else {
1444     eLoss = 1.0 / (1.0 + y) ;                    1436     eLoss = 1.0 / (1.0 + y) ;
1445     G4double de = eLoss ;                        1437     G4double de = eLoss ;
1446                                                  1438 
1447     for(G4int i=2; de>eLoss*0.01; i++) {         1439     for(G4int i=2; de>eLoss*0.01; i++) {
1448       de = 1.0/( i * (i*i + y)) ;                1440       de = 1.0/( i * (i*i + y)) ;
1449       eLoss += de ;                              1441       eLoss += de ;
1450     }                                            1442     }
1451   }                                              1443   }
1452   eLoss *= -1.0 * y * cSquare * twopi_mc2_rcl    1444   eLoss *= -1.0 * y * cSquare * twopi_mc2_rcl2 *
1453     (material->GetElectronDensity()) / beta2     1445     (material->GetElectronDensity()) / beta2 ;
1454                                                  1446 
1455   return eLoss;                                  1447   return eLoss;
1456 }                                                1448 }
1457                                                  1449 
1458                                                  1450 
1459                                                  1451 
1460 G4double G4hImpactIonisation::ElectronicLossF    1452 G4double G4hImpactIonisation::ElectronicLossFluctuation(
1461               const G4DynamicParticle* partic    1453               const G4DynamicParticle* particle,
1462               const G4MaterialCutsCouple* cou    1454               const G4MaterialCutsCouple* couple,
1463               G4double meanLoss,                 1455               G4double meanLoss,
1464               G4double step) const               1456               G4double step) const
1465 //  calculate actual loss from the mean loss     1457 //  calculate actual loss from the mean loss
1466 //  The model used to get the fluctuation is     1458 //  The model used to get the fluctuation is essentially the same
1467 // as in Glandz in Geant3.                       1459 // as in Glandz in Geant3.
1468 {                                                1460 {
1469   // data members to speed up the fluctuation    1461   // data members to speed up the fluctuation calculation
1470   //  G4int imat ;                               1462   //  G4int imat ;
1471   //  G4double f1Fluct,f2Fluct,e1Fluct,e2Fluc    1463   //  G4double f1Fluct,f2Fluct,e1Fluct,e2Fluct,rateFluct,ipotFluct;
1472   //  G4double e1LogFluct,e2LogFluct,ipotLogF    1464   //  G4double e1LogFluct,e2LogFluct,ipotLogFluct;
1473                                                  1465 
1474   static const G4double minLoss = 1.*eV ;        1466   static const G4double minLoss = 1.*eV ;
1475   static const G4double kappa = 10. ;            1467   static const G4double kappa = 10. ;
1476   static const G4double theBohrBeta2 = 50.0 *    1468   static const G4double theBohrBeta2 = 50.0 * keV/proton_mass_c2 ;
1477                                                  1469 
1478   const G4Material* material = couple->GetMat    1470   const G4Material* material = couple->GetMaterial();
1479   G4int    imaterial   = couple->GetIndex() ;    1471   G4int    imaterial   = couple->GetIndex() ;
1480   G4double ipotFluct   = material->GetIonisat    1472   G4double ipotFluct   = material->GetIonisation()->GetMeanExcitationEnergy() ;
1481   G4double electronDensity = material->GetEle    1473   G4double electronDensity = material->GetElectronDensity() ;
1482   G4double zeff = electronDensity/(material->    1474   G4double zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume()) ;
1483                                                  1475 
1484   // get particle data                           1476   // get particle data
1485   G4double tkin   = particle->GetKineticEnerg    1477   G4double tkin   = particle->GetKineticEnergy();
1486   G4double particleMass = particle->GetMass()    1478   G4double particleMass = particle->GetMass() ;
1487   G4double deltaCutInKineticEnergyNow = cutFo    1479   G4double deltaCutInKineticEnergyNow = cutForDelta[imaterial];
1488                                                  1480 
1489   // shortcut for very very small loss           1481   // shortcut for very very small loss
1490   if(meanLoss < minLoss) return meanLoss ;       1482   if(meanLoss < minLoss) return meanLoss ;
1491                                                  1483 
1492   // Validity range for delta electron cross     1484   // Validity range for delta electron cross section
1493   G4double threshold = std::max(deltaCutInKin    1485   G4double threshold = std::max(deltaCutInKineticEnergyNow,ipotFluct);
1494   G4double loss, siga;                           1486   G4double loss, siga;
1495                                                  1487 
1496   G4double rmass = electron_mass_c2/particleM    1488   G4double rmass = electron_mass_c2/particleMass;
1497   G4double tau   = tkin/particleMass;            1489   G4double tau   = tkin/particleMass;
1498   G4double tau1 = tau+1.0;                       1490   G4double tau1 = tau+1.0;
1499   G4double tau2 = tau*(tau+2.);                  1491   G4double tau2 = tau*(tau+2.);
1500   G4double tMax    = 2.*electron_mass_c2*tau2    1492   G4double tMax    = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
1501                                                  1493 
1502                                                  1494 
1503   if(tMax > threshold) tMax = threshold;         1495   if(tMax > threshold) tMax = threshold;
1504   G4double beta2 = tau2/(tau1*tau1);             1496   G4double beta2 = tau2/(tau1*tau1);
1505                                                  1497 
1506   // Gaussian fluctuation                        1498   // Gaussian fluctuation
1507   if(meanLoss > kappa*tMax || tMax < kappa*ip    1499   if(meanLoss > kappa*tMax || tMax < kappa*ipotFluct )
1508     {                                            1500     {
1509       siga = tMax * (1.0-0.5*beta2) * step *     1501       siga = tMax * (1.0-0.5*beta2) * step * twopi_mc2_rcl2
1510   * electronDensity / beta2 ;                    1502   * electronDensity / beta2 ;
1511                                                  1503 
1512       // High velocity or negatively charged     1504       // High velocity or negatively charged particle
1513       if( beta2 > 3.0*theBohrBeta2*zeff || ch    1505       if( beta2 > 3.0*theBohrBeta2*zeff || charge < 0.0) {
1514   siga = std::sqrt( siga * chargeSquare ) ;      1506   siga = std::sqrt( siga * chargeSquare ) ;
1515                                                  1507 
1516   // Low velocity - additional ion charge flu    1508   // Low velocity - additional ion charge fluctuations according to
1517   // Q.Yang et al., NIM B61(1991)149-155.        1509   // Q.Yang et al., NIM B61(1991)149-155.
1518       } else {                                   1510       } else {
1519   G4double chu = theIonChuFluctuationModel->T    1511   G4double chu = theIonChuFluctuationModel->TheValue(particle, material);
1520   G4double yang = theIonYangFluctuationModel-    1512   G4double yang = theIonYangFluctuationModel->TheValue(particle, material);
1521   siga = std::sqrt( siga * (chargeSquare * ch    1513   siga = std::sqrt( siga * (chargeSquare * chu + yang)) ;
1522       }                                          1514       }
1523                                                  1515 
1524       do {                                       1516       do {
1525         loss = G4RandGauss::shoot(meanLoss,si    1517         loss = G4RandGauss::shoot(meanLoss,siga);
1526       } while (loss < 0. || loss > 2.0*meanLo    1518       } while (loss < 0. || loss > 2.0*meanLoss);
1527       return loss;                               1519       return loss;
1528     }                                            1520     }
1529                                                  1521 
1530   // Non Gaussian fluctuation                    1522   // Non Gaussian fluctuation
1531   static const G4double probLim = 0.01 ;         1523   static const G4double probLim = 0.01 ;
1532   static const G4double sumaLim = -std::log(p    1524   static const G4double sumaLim = -std::log(probLim) ;
1533   static const G4double alim = 10.;              1525   static const G4double alim = 10.;
1534                                                  1526 
1535   G4double suma,w1,w2,C,e0,lossc,w;              1527   G4double suma,w1,w2,C,e0,lossc,w;
1536   G4double a1,a2,a3;                             1528   G4double a1,a2,a3;
1537   G4int p1,p2,p3;                                1529   G4int p1,p2,p3;
1538   G4int nb;                                      1530   G4int nb;
1539   G4double corrfac, na,alfa,rfac,namean,sa,al    1531   G4double corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
1540   G4double dp3;                                  1532   G4double dp3;
1541                                                  1533 
1542   G4double f1Fluct     = material->GetIonisat    1534   G4double f1Fluct     = material->GetIonisation()->GetF1fluct();
1543   G4double f2Fluct     = material->GetIonisat    1535   G4double f2Fluct     = material->GetIonisation()->GetF2fluct();
1544   G4double e1Fluct     = material->GetIonisat    1536   G4double e1Fluct     = material->GetIonisation()->GetEnergy1fluct();
1545   G4double e2Fluct     = material->GetIonisat    1537   G4double e2Fluct     = material->GetIonisation()->GetEnergy2fluct();
1546   G4double e1LogFluct  = material->GetIonisat    1538   G4double e1LogFluct  = material->GetIonisation()->GetLogEnergy1fluct();
1547   G4double e2LogFluct  = material->GetIonisat    1539   G4double e2LogFluct  = material->GetIonisation()->GetLogEnergy2fluct();
1548   G4double rateFluct   = material->GetIonisat    1540   G4double rateFluct   = material->GetIonisation()->GetRateionexcfluct();
1549   G4double ipotLogFluct= material->GetIonisat    1541   G4double ipotLogFluct= material->GetIonisation()->GetLogMeanExcEnergy();
1550                                                  1542 
1551   w1 = tMax/ipotFluct;                           1543   w1 = tMax/ipotFluct;
1552   w2 = std::log(2.*electron_mass_c2*tau2);       1544   w2 = std::log(2.*electron_mass_c2*tau2);
1553                                                  1545 
1554   C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluc    1546   C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
1555                                                  1547 
1556   a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluc    1548   a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
1557   a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluc    1549   a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
1558   a3 = rateFluct*meanLoss*(tMax-ipotFluct)/(i    1550   a3 = rateFluct*meanLoss*(tMax-ipotFluct)/(ipotFluct*tMax*std::log(w1));
1559   if(a1 < 0.0) a1 = 0.0;                         1551   if(a1 < 0.0) a1 = 0.0;
1560   if(a2 < 0.0) a2 = 0.0;                         1552   if(a2 < 0.0) a2 = 0.0;
1561   if(a3 < 0.0) a3 = 0.0;                         1553   if(a3 < 0.0) a3 = 0.0;
1562                                                  1554 
1563   suma = a1+a2+a3;                               1555   suma = a1+a2+a3;
1564                                                  1556 
1565   loss = 0.;                                     1557   loss = 0.;
1566                                                  1558 
1567                                                  1559 
1568   if(suma < sumaLim)             // very smal    1560   if(suma < sumaLim)             // very small Step
1569     {                                            1561     {
1570       e0 = material->GetIonisation()->GetEner    1562       e0 = material->GetIonisation()->GetEnergy0fluct();
1571                                                  1563 
1572       if(tMax == ipotFluct)                      1564       if(tMax == ipotFluct)
1573   {                                              1565   {
1574     a3 = meanLoss/e0;                            1566     a3 = meanLoss/e0;
1575                                                  1567 
1576     if(a3>alim)                                  1568     if(a3>alim)
1577       {                                          1569       {
1578         siga=std::sqrt(a3) ;                     1570         siga=std::sqrt(a3) ;
1579         p3 = std::max(0,G4int(G4RandGauss::sh    1571         p3 = std::max(0,G4int(G4RandGauss::shoot(a3,siga)+0.5));
1580       }                                          1572       }
1581     else                                         1573     else
1582       p3 = (G4int)G4Poisson(a3);              << 1574       p3 = G4Poisson(a3);
1583                                                  1575 
1584     loss = p3*e0 ;                               1576     loss = p3*e0 ;
1585                                                  1577 
1586     if(p3 > 0)                                   1578     if(p3 > 0)
1587       loss += (1.-2.*G4UniformRand())*e0 ;       1579       loss += (1.-2.*G4UniformRand())*e0 ;
1588                                                  1580 
1589   }                                              1581   }
1590       else                                       1582       else
1591   {                                              1583   {
1592     tMax = tMax-ipotFluct+e0 ;                   1584     tMax = tMax-ipotFluct+e0 ;
1593     a3 = meanLoss*(tMax-e0)/(tMax*e0*std::log    1585     a3 = meanLoss*(tMax-e0)/(tMax*e0*std::log(tMax/e0));
1594                                                  1586 
1595     if(a3>alim)                                  1587     if(a3>alim)
1596       {                                          1588       {
1597         siga=std::sqrt(a3) ;                     1589         siga=std::sqrt(a3) ;
1598         p3 = std::max(0,int(G4RandGauss::shoo    1590         p3 = std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
1599       }                                          1591       }
1600     else                                         1592     else
1601       p3 = (G4int)G4Poisson(a3);              << 1593       p3 = G4Poisson(a3);
1602                                                  1594 
1603     if(p3 > 0)                                   1595     if(p3 > 0)
1604       {                                          1596       {
1605         w = (tMax-e0)/tMax ;                     1597         w = (tMax-e0)/tMax ;
1606         if(p3 > nmaxCont2)                       1598         if(p3 > nmaxCont2)
1607     {                                            1599     {
1608       dp3 = G4float(p3) ;                        1600       dp3 = G4float(p3) ;
1609       corrfac = dp3/G4float(nmaxCont2) ;         1601       corrfac = dp3/G4float(nmaxCont2) ;
1610       p3 = G4int(nmaxCont2) ;                 << 1602       p3 = nmaxCont2 ;
1611     }                                            1603     }
1612         else                                     1604         else
1613     corrfac = 1. ;                               1605     corrfac = 1. ;
1614                                                  1606 
1615         for(G4int i=0; i<p3; i++) loss += 1./    1607         for(G4int i=0; i<p3; i++) loss += 1./(1.-w*G4UniformRand()) ;
1616         loss *= e0*corrfac ;                     1608         loss *= e0*corrfac ;
1617       }                                          1609       }
1618   }                                              1610   }
1619     }                                            1611     }
1620                                                  1612 
1621   else                              // not so    1613   else                              // not so small Step
1622     {                                            1614     {
1623       // excitation type 1                       1615       // excitation type 1
1624       if(a1>alim)                                1616       if(a1>alim)
1625   {                                              1617   {
1626     siga=std::sqrt(a1) ;                         1618     siga=std::sqrt(a1) ;
1627     p1 = std::max(0,G4int(G4RandGauss::shoot(    1619     p1 = std::max(0,G4int(G4RandGauss::shoot(a1,siga)+0.5));
1628   }                                              1620   }
1629       else                                       1621       else
1630   p1 = (G4int)G4Poisson(a1);                  << 1622   p1 = G4Poisson(a1);
1631                                                  1623 
1632       // excitation type 2                       1624       // excitation type 2
1633       if(a2>alim)                                1625       if(a2>alim)
1634   {                                              1626   {
1635     siga=std::sqrt(a2) ;                         1627     siga=std::sqrt(a2) ;
1636     p2 = std::max(0,G4int(G4RandGauss::shoot(    1628     p2 = std::max(0,G4int(G4RandGauss::shoot(a2,siga)+0.5));
1637   }                                              1629   }
1638       else                                       1630       else
1639         p2 = (G4int)G4Poisson(a2);            << 1631         p2 = G4Poisson(a2);
1640                                                  1632 
1641       loss = p1*e1Fluct+p2*e2Fluct;              1633       loss = p1*e1Fluct+p2*e2Fluct;
1642                                                  1634 
1643       // smearing to avoid unphysical peaks      1635       // smearing to avoid unphysical peaks
1644       if(p2 > 0)                                 1636       if(p2 > 0)
1645         loss += (1.-2.*G4UniformRand())*e2Flu    1637         loss += (1.-2.*G4UniformRand())*e2Fluct;
1646       else if (loss>0.)                          1638       else if (loss>0.)
1647         loss += (1.-2.*G4UniformRand())*e1Flu    1639         loss += (1.-2.*G4UniformRand())*e1Fluct;
1648                                                  1640 
1649       // ionisation .........................    1641       // ionisation .......................................
1650       if(a3 > 0.)                                1642       if(a3 > 0.)
1651   {                                              1643   {
1652     if(a3>alim)                                  1644     if(a3>alim)
1653       {                                          1645       {
1654         siga=std::sqrt(a3) ;                     1646         siga=std::sqrt(a3) ;
1655         p3 = std::max(0,G4int(G4RandGauss::sh    1647         p3 = std::max(0,G4int(G4RandGauss::shoot(a3,siga)+0.5));
1656       }                                          1648       }
1657     else                                         1649     else
1658       p3 = (G4int)G4Poisson(a3);              << 1650       p3 = G4Poisson(a3);
1659                                                  1651 
1660     lossc = 0.;                                  1652     lossc = 0.;
1661     if(p3 > 0)                                   1653     if(p3 > 0)
1662       {                                          1654       {
1663         na = 0.;                                 1655         na = 0.;
1664         alfa = 1.;                               1656         alfa = 1.;
1665         if (p3 > nmaxCont2)                      1657         if (p3 > nmaxCont2)
1666     {                                            1658     {
1667       dp3        = G4float(p3);                  1659       dp3        = G4float(p3);
1668       rfac       = dp3/(G4float(nmaxCont2)+dp    1660       rfac       = dp3/(G4float(nmaxCont2)+dp3);
1669       namean     = G4float(p3)*rfac;             1661       namean     = G4float(p3)*rfac;
1670       sa         = G4float(nmaxCont1)*rfac;      1662       sa         = G4float(nmaxCont1)*rfac;
1671       na         = G4RandGauss::shoot(namean,    1663       na         = G4RandGauss::shoot(namean,sa);
1672       if (na > 0.)                               1664       if (na > 0.)
1673         {                                        1665         {
1674           alfa   = w1*G4float(nmaxCont2+p3)/     1666           alfa   = w1*G4float(nmaxCont2+p3)/
1675       (w1*G4float(nmaxCont2)+G4float(p3));       1667       (w1*G4float(nmaxCont2)+G4float(p3));
1676           alfa1  = alfa*std::log(alfa)/(alfa-    1668           alfa1  = alfa*std::log(alfa)/(alfa-1.);
1677           ea     = na*ipotFluct*alfa1;           1669           ea     = na*ipotFluct*alfa1;
1678           sea    = ipotFluct*std::sqrt(na*(al    1670           sea    = ipotFluct*std::sqrt(na*(alfa-alfa1*alfa1));
1679           lossc += G4RandGauss::shoot(ea,sea)    1671           lossc += G4RandGauss::shoot(ea,sea);
1680         }                                        1672         }
1681     }                                            1673     }
1682                                                  1674 
1683         nb = G4int(G4float(p3)-na);              1675         nb = G4int(G4float(p3)-na);
1684         if (nb > 0)                              1676         if (nb > 0)
1685     {                                            1677     {
1686       w2 = alfa*ipotFluct;                       1678       w2 = alfa*ipotFluct;
1687       w  = (tMax-w2)/tMax;                       1679       w  = (tMax-w2)/tMax;
1688       for (G4int k=0; k<nb; k++) lossc += w2/    1680       for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
1689     }                                            1681     }
1690       }                                          1682       }
1691     loss += lossc;                               1683     loss += lossc;
1692   }                                              1684   }
1693     }                                            1685     }
1694                                                  1686 
1695   return loss ;                                  1687   return loss ;
1696 }                                                1688 }
1697                                                  1689 
1698                                                  1690 
1699                                                  1691 
1700 void G4hImpactIonisation::SetCutForSecondaryP    1692 void G4hImpactIonisation::SetCutForSecondaryPhotons(G4double cut)
1701 {                                                1693 {
1702   minGammaEnergy = cut;                          1694   minGammaEnergy = cut;
1703 }                                                1695 }
1704                                                  1696 
1705                                                  1697 
1706                                                  1698 
1707 void G4hImpactIonisation::SetCutForAugerElect    1699 void G4hImpactIonisation::SetCutForAugerElectrons(G4double cut)
1708 {                                                1700 {
1709   minElectronEnergy = cut;                       1701   minElectronEnergy = cut;
1710 }                                                1702 }
1711                                                  1703 
1712                                                  1704 
1713                                                  1705 
1714 void G4hImpactIonisation::ActivateAugerElectr    1706 void G4hImpactIonisation::ActivateAugerElectronProduction(G4bool val)
1715 {                                                1707 {
1716   atomicDeexcitation.ActivateAugerElectronPro    1708   atomicDeexcitation.ActivateAugerElectronProduction(val);
1717 }                                                1709 }
1718                                                  1710 
1719                                                  1711 
1720                                                  1712 
1721 void G4hImpactIonisation::PrintInfoDefinition    1713 void G4hImpactIonisation::PrintInfoDefinition() const
1722 {                                                1714 {
1723   G4String comments = "  Knock-on electron cr    1715   G4String comments = "  Knock-on electron cross sections . ";
1724   comments += "\n        Good description abo    1716   comments += "\n        Good description above the mean excitation energy.\n";
1725   comments += "        Delta ray energy sampl    1717   comments += "        Delta ray energy sampled from  differential Xsection.";
1726                                                  1718 
1727   G4cout << G4endl << GetProcessName() << ":     1719   G4cout << G4endl << GetProcessName() << ":  " << comments
1728          << "\n        PhysicsTables from " <    1720          << "\n        PhysicsTables from " << LowestKineticEnergy / eV << " eV "
1729          << " to " << HighestKineticEnergy /     1721          << " to " << HighestKineticEnergy / TeV << " TeV "
1730          << " in " << TotBin << " bins."         1722          << " in " << TotBin << " bins."
1731    << "\n        Electronic stopping power mo    1723    << "\n        Electronic stopping power model is  "
1732    << protonTable                                1724    << protonTable
1733          << "\n        from " << protonLowEne    1725          << "\n        from " << protonLowEnergy / keV << " keV "
1734          << " to " << protonHighEnergy / MeV     1726          << " to " << protonHighEnergy / MeV << " MeV " << "." << G4endl ;
1735   G4cout << "\n        Parametrisation model     1727   G4cout << "\n        Parametrisation model for antiprotons is  "
1736          << antiprotonTable                      1728          << antiprotonTable
1737          << "\n        from " << antiprotonLo    1729          << "\n        from " << antiprotonLowEnergy / keV << " keV "
1738          << " to " << antiprotonHighEnergy /     1730          << " to " << antiprotonHighEnergy / MeV << " MeV " << "." << G4endl ;
1739   if(theBarkas){                                 1731   if(theBarkas){
1740     G4cout << "        Parametrization of the    1732     G4cout << "        Parametrization of the Barkas effect is switched on."
1741      << G4endl ;                                 1733      << G4endl ;
1742   }                                              1734   }
1743   if(nStopping) {                                1735   if(nStopping) {
1744     G4cout << "        Nuclear stopping power    1736     G4cout << "        Nuclear stopping power model is " << theNuclearTable
1745      << G4endl ;                                 1737      << G4endl ;
1746   }                                              1738   }
1747                                                  1739 
1748   G4bool printHead = true;                       1740   G4bool printHead = true;
1749                                                  1741 
1750   const G4ProductionCutsTable* theCoupleTable    1742   const G4ProductionCutsTable* theCoupleTable=
1751     G4ProductionCutsTable::GetProductionCutsT    1743     G4ProductionCutsTable::GetProductionCutsTable();
1752   G4int numOfCouples = (G4int)theCoupleTable- << 1744   size_t numOfCouples = theCoupleTable->GetTableSize();
1753                                                  1745 
1754   // loop for materials                          1746   // loop for materials
1755                                                  1747 
1756   for (G4int j=0 ; j < numOfCouples; ++j) {   << 1748   for (size_t j=0 ; j < numOfCouples; j++) {
1757                                                  1749 
1758     const G4MaterialCutsCouple* couple = theC    1750     const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
1759     const G4Material* material= couple->GetMa    1751     const G4Material* material= couple->GetMaterial();
1760     G4double deltaCutNow = cutForDelta[(coupl    1752     G4double deltaCutNow = cutForDelta[(couple->GetIndex())] ;
1761     G4double excitationEnergy = material->Get    1753     G4double excitationEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
1762                                                  1754 
1763     if(excitationEnergy > deltaCutNow) {         1755     if(excitationEnergy > deltaCutNow) {
1764       if(printHead) {                            1756       if(printHead) {
1765         printHead = false ;                      1757         printHead = false ;
1766                                                  1758 
1767         G4cout << "           material           1759         G4cout << "           material       min.delta energy(keV) " << G4endl;
1768         G4cout << G4endl;                        1760         G4cout << G4endl;
1769       }                                          1761       }
1770                                                  1762 
1771       G4cout << std::setw(20) << material->Ge    1763       G4cout << std::setw(20) << material->GetName()
1772        << std::setw(15) << excitationEnergy/k    1764        << std::setw(15) << excitationEnergy/keV << G4endl;
1773     }                                            1765     }
1774   }                                              1766   }
1775 }                                                1767 }
1776                                                  1768