Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNABornExcitationModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNABornExcitationModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNABornExcitationModel.cc	(revision 1058)
@@ -0,0 +1,276 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNABornExcitationModel.cc,v 1.3 2009/02/16 11:00:11 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNABornExcitationModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNABornExcitationModel::G4DNABornExcitationModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  lowEnergyLimit = 500 * keV; 
+  highEnergyLimit = 10 * MeV;
+  SetLowEnergyLimit(lowEnergyLimit);
+  SetHighEnergyLimit(highEnergyLimit);
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  //
+  
+  table = 0;
+  
+  //
+  
+  G4cout << "Born excitation model is constructed " << G4endl
+         << "Energy range: "
+         << lowEnergyLimit / keV << " keV - "
+         << highEnergyLimit / MeV << " MeV"
+         << G4endl;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNABornExcitationModel::~G4DNABornExcitationModel()
+{ 
+  // Cross section
+  delete table;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNABornExcitationModel::Initialise(const G4ParticleDefinition* /*particle*/,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNABornExcitationModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  if (LowEnergyLimit() < lowEnergyLimit)
+  {
+    G4cout << "G4DNABornExcitationModel: low energy limit increased from " << 
+	LowEnergyLimit()/keV << " keV to " << lowEnergyLimit/keV << " keV" << G4endl;
+    SetLowEnergyLimit(lowEnergyLimit);
+  }
+
+  if (HighEnergyLimit() > highEnergyLimit)
+  {
+    G4cout << "G4DNABornExcitationModel: high energy limit decreased from " << 
+        HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
+    SetHighEnergyLimit(highEnergyLimit);
+  }
+
+  //
+  
+  if (table == 0)
+  {
+    table = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,(1e-22/3.343)*m*m );
+    table->LoadData("dna/sigma_excitation_p_born");
+  }
+
+  G4cout << "Born excitation model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / keV << " keV - "
+         << HighEnergyLimit() / MeV << " MeV " << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+  
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNABornExcitationModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double k,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNABornExcitationModel" << G4endl;
+
+ // Calculate total cross section for model
+
+  G4double crossSection=0;
+  
+  if (flagMaterialIsWater)
+  {
+    if (particleDefinition == G4Proton::ProtonDefinition())
+    {
+      if (k >= lowEnergyLimit && k < highEnergyLimit)
+      {
+        crossSection = table->FindValue(k); 
+      }
+
+      if (verboseLevel > 3)
+      {
+        G4cout << "---> Kinetic energy(keV)=" << k/keV << G4endl;
+        G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
+        G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*densityWater/(1./cm) << G4endl;
+      } 
+    }
+  } // if (flagMaterialIsWater)
+
+ return crossSection*densityWater;		   
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNABornExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicParticle,
+					      G4double,
+					      G4double)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNABornExcitationModel" << G4endl;
+
+  G4double k = aDynamicParticle->GetKineticEnergy();
+  
+  G4int level = RandomSelect(k);
+  G4double excitationEnergy = waterStructure.ExcitationEnergy(level);
+  G4double newEnergy = k - excitationEnergy;
+  
+  if (newEnergy > 0)
+  {
+      fParticleChangeForGamma->ProposeMomentumDirection(aDynamicParticle->GetMomentumDirection());
+      fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
+      fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
+  }
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNABornExcitationModel::RandomSelect(G4double k)
+{   
+  G4int level = 0;
+
+  G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
+
+  const size_t n(table->NumberOfComponents());
+  size_t i(n);
+  G4double value = 0.;
+  
+  while (i>0)
+  { 
+    i--;
+    valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
+    value += valuesBuffer[i];
+  }
+  
+  value *= G4UniformRand();
+  
+  i = n;
+  
+  while (i > 0)
+  {
+    i--;
+      
+    if (valuesBuffer[i] > value)
+    {
+      delete[] valuesBuffer;
+      return i;
+    }
+      value -= valuesBuffer[i];
+  }
+
+  if (valuesBuffer) delete[] valuesBuffer;
+
+  return level;
+}
+
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNABornIonisationModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNABornIonisationModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNABornIonisationModel.cc	(revision 1058)
@@ -0,0 +1,703 @@
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNABornIonisationModel.cc,v 1.4 2009/02/16 11:00:11 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNABornIonisationModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNABornIonisationModel::G4DNABornIonisationModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Born ionisation model is constructed " << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNABornIonisationModel::~G4DNABornIonisationModel()
+{  
+  // Cross section
+  
+  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+  for (pos = tableData.begin(); pos != tableData.end(); ++pos)
+  {
+    G4DNACrossSectionDataSet* table = pos->second;
+    delete table;
+  }
+  
+  // Final state
+  
+  eVecm.clear();
+  pVecm.clear();
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNABornIonisationModel::Initialise(const G4ParticleDefinition* particle,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNABornIonisationModel::Initialise()" << G4endl;
+
+  // Energy limits
+
+  G4String fileElectron("dna/sigma_ionisation_e_born");
+  G4String fileProton("dna/sigma_ionisation_p_born");
+
+  G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
+  G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
+
+  G4String electron;
+  G4String proton;
+  
+  G4double scaleFactor = (1.e-22 / 3.343) * m*m;
+
+  char *path = getenv("G4LEDATA");
+
+  if (electronDef != 0)
+  {
+    electron = electronDef->GetParticleName();
+
+    tableFile[electron] = fileElectron;
+
+    lowEnergyLimit[electron] = 12.61 * eV; 
+    highEnergyLimit[electron] = 30. * keV;
+
+    // Cross section
+    
+    G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
+    tableE->LoadData(fileElectron);
+      
+    tableData[electron] = tableE;
+    
+    // Final state
+    
+    std::ostringstream eFullFileName;
+    eFullFileName << path << "/dna/sigmadiff_ionisation_e_born.dat";
+    std::ifstream eDiffCrossSection(eFullFileName.str().c_str());
+
+    if (!eDiffCrossSection)
+    { 
+      G4Exception("G4DNABornIonisationModel::ERROR OPENING electron DATA FILE");
+    }
+      
+    eTdummyVec.push_back(0.);
+    while(!eDiffCrossSection.eof())
+    {
+      double tDummy;
+      double eDummy;
+      eDiffCrossSection>>tDummy>>eDummy;
+      if (tDummy != eTdummyVec.back()) eTdummyVec.push_back(tDummy);
+      for (int j=0; j<5; j++)
+      {
+        eDiffCrossSection>>eDiffCrossSectionData[j][tDummy][eDummy];
+
+        // SI - only if eof is not reached !
+        if (!eDiffCrossSection.eof()) eDiffCrossSectionData[j][tDummy][eDummy]*=scaleFactor;
+
+        eVecm[tDummy].push_back(eDummy);
+
+      }
+    }
+
+    //
+  }
+  else
+  {
+    G4Exception("G4DNABornIonisationModel::Initialise(): electron is not defined");
+  }
+
+  if (protonDef != 0)
+  {
+    proton = protonDef->GetParticleName();
+
+    tableFile[proton] = fileProton;
+
+    lowEnergyLimit[proton] = 500. * keV;
+    highEnergyLimit[proton] = 10. * MeV;
+
+    // Cross section
+    
+    G4DNACrossSectionDataSet* tableP = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
+    tableP->LoadData(fileProton);
+      
+    tableData[proton] = tableP;
+    
+    // Final state
+
+    std::ostringstream pFullFileName;
+    pFullFileName << path << "/dna/sigmadiff_ionisation_p_born.dat";
+    std::ifstream pDiffCrossSection(pFullFileName.str().c_str());
+    
+    if (!pDiffCrossSection)
+    { 
+      G4Exception("G4DNABornIonisationModel::ERROR OPENING proton DATA FILE");
+    }
+      
+    pTdummyVec.push_back(0.);
+    while(!pDiffCrossSection.eof())
+    {
+      double tDummy;
+      double eDummy;
+      pDiffCrossSection>>tDummy>>eDummy;
+      if (tDummy != pTdummyVec.back()) pTdummyVec.push_back(tDummy);
+      for (int j=0; j<5; j++)
+      {
+        pDiffCrossSection>>pDiffCrossSectionData[j][tDummy][eDummy];
+
+        // SI - only if eof is not reached !
+        if (!pDiffCrossSection.eof()) pDiffCrossSectionData[j][tDummy][eDummy]*=scaleFactor;
+
+        pVecm[tDummy].push_back(eDummy);
+      }
+    }
+  
+  }
+  else
+  {
+    G4Exception("G4DNABornIonisationModel::Initialise(): proton is not defined");
+  }
+
+  if (particle==electronDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[electron]);
+    SetHighEnergyLimit(highEnergyLimit[electron]);
+  }
+
+  if (particle==protonDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[proton]);
+    SetHighEnergyLimit(highEnergyLimit[proton]);
+  }
+
+  G4cout << "Born ionisation model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / eV << " eV - "
+         << HighEnergyLimit() / keV << " keV for "
+         << particle->GetParticleName()
+         << G4endl;
+
+  //
+  
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double ekin,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNABornIonisationModel" << G4endl;
+
+  if (
+      particleDefinition != G4Proton::ProtonDefinition()
+      &&
+      particleDefinition != G4Electron::ElectronDefinition()
+     )
+   	    
+    return 0;
+  
+  // Calculate total cross section for model
+
+  G4double lowLim = 0;
+  G4double highLim = 0;
+  G4double sigma=0;
+
+  if (flagMaterialIsWater)
+  {
+    const G4String& particleName = particleDefinition->GetParticleName();
+ 
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+    pos1 = lowEnergyLimit.find(particleName);
+    if (pos1 != lowEnergyLimit.end())
+    {
+      lowLim = pos1->second;
+    }
+  
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+    pos2 = highEnergyLimit.find(particleName);
+    if (pos2 != highEnergyLimit.end())
+    {
+      highLim = pos2->second;
+    }
+
+    if (ekin >= lowLim && ekin < highLim)
+    {
+      std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+      pos = tableData.find(particleName);
+	
+      if (pos != tableData.end())
+      {
+        G4DNACrossSectionDataSet* table = pos->second;
+        if (table != 0)
+        {
+	  sigma = table->FindValue(ekin);
+        }
+      }
+      else
+      {
+        G4Exception("G4DNABornIonisationModel::CrossSectionPerVolume: attempting to calculate cross section for wrong particle");
+      }
+    }
+
+    if (verboseLevel > 3)
+    {
+      G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
+      G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
+      G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
+    } 
+ 
+  } // if (waterMaterial)
+ 
+ return sigma*densityWater;		   
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNABornIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* particle,
+					      G4double,
+					      G4double)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNABornIonisationModel" << G4endl;
+
+  G4double lowLim = 0;
+  G4double highLim = 0;
+
+  G4double k = particle->GetKineticEnergy();
+
+  const G4String& particleName = particle->GetDefinition()->GetParticleName();
+
+  std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+  pos1 = lowEnergyLimit.find(particleName);
+
+  if (pos1 != lowEnergyLimit.end())
+  {
+    lowLim = pos1->second;
+  }
+
+  std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+  pos2 = highEnergyLimit.find(particleName);
+
+  if (pos2 != highEnergyLimit.end())
+  {
+    highLim = pos2->second;
+  }
+
+  if (k >= lowLim && k < highLim)
+  {
+    G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
+    G4double particleMass = particle->GetDefinition()->GetPDGMass();
+    G4double totalEnergy = k + particleMass;
+    G4double pSquare = k * (totalEnergy + particleMass);
+    G4double totalMomentum = std::sqrt(pSquare);
+
+    G4int ionizationShell = RandomSelect(k,particleName);
+  
+    G4double secondaryKinetic = RandomizeEjectedElectronEnergy(particle->GetDefinition(),k,ionizationShell);
+  
+    G4double bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
+
+    G4double cosTheta = 0.;
+    G4double phi = 0.; 
+    RandomizeEjectedElectronDirection(particle->GetDefinition(), k,secondaryKinetic, cosTheta, phi);
+
+    G4double sinTheta = std::sqrt(1.-cosTheta*cosTheta);
+    G4double dirX = sinTheta*std::cos(phi);
+    G4double dirY = sinTheta*std::sin(phi);
+    G4double dirZ = cosTheta;
+    G4ThreeVector deltaDirection(dirX,dirY,dirZ);
+    deltaDirection.rotateUz(primaryDirection);
+
+    G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
+
+    G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
+    G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
+    G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
+    G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz);
+    finalPx /= finalMomentum;
+    finalPy /= finalMomentum;
+    finalPz /= finalMomentum;
+    
+    G4ThreeVector direction;
+    direction.set(finalPx,finalPy,finalPz);
+    
+    fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
+    fParticleChangeForGamma->SetProposedKineticEnergy(k-bindingEnergy-secondaryKinetic);
+    fParticleChangeForGamma->ProposeLocalEnergyDeposit(bindingEnergy);
+
+    G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
+    fvect->push_back(dp);
+  }
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNABornIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefinition* particleDefinition, 
+G4double k, G4int shell)
+{
+  if (particleDefinition == G4Electron::ElectronDefinition()) 
+  {
+    G4double maximumEnergyTransfer=0.;
+    if ((k+waterStructure.IonisationEnergy(shell))/2. > k) maximumEnergyTransfer=k;
+    else maximumEnergyTransfer = (k+waterStructure.IonisationEnergy(shell))/2.;
+    
+    G4double crossSectionMaximum = 0.;
+    for(G4double value=waterStructure.IonisationEnergy(shell); value<=maximumEnergyTransfer; value+=0.1*eV)
+    {
+      G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
+      if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
+    }
+ 
+    G4double secondaryElectronKineticEnergy=0.;
+    do 
+    {
+      secondaryElectronKineticEnergy = G4UniformRand() * (maximumEnergyTransfer-waterStructure.IonisationEnergy(shell));
+    } while(G4UniformRand()*crossSectionMaximum >
+      DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+waterStructure.IonisationEnergy(shell))/eV,shell));
+
+    return secondaryElectronKineticEnergy;
+ 
+  }
+  
+  if (particleDefinition == G4Proton::ProtonDefinition()) 
+  {
+    G4double maximumKineticEnergyTransfer = 4.* (electron_mass_c2 / proton_mass_c2) * k - (waterStructure.IonisationEnergy(shell));
+
+    G4double crossSectionMaximum = 0.;
+    for (G4double value = waterStructure.IonisationEnergy(shell); 
+         value<=4.*waterStructure.IonisationEnergy(shell) ; 
+         value+=0.1*eV)
+    {
+      G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
+      if (differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
+    }
+
+    G4double secondaryElectronKineticEnergy = 0.;
+    do
+    {
+      secondaryElectronKineticEnergy = G4UniformRand() * maximumKineticEnergyTransfer;
+    } while(G4UniformRand()*crossSectionMaximum >= 
+	      DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+waterStructure.IonisationEnergy(shell))/eV,shell));
+
+    return secondaryElectronKineticEnergy;
+  }
+
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4DNABornIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition, 
+								   G4double k, 
+								   G4double secKinetic, 
+								   G4double & cosTheta, 
+								   G4double & phi )
+{
+  if (particleDefinition == G4Electron::ElectronDefinition()) 
+  {
+    phi = twopi * G4UniformRand();
+    if (secKinetic < 50.*eV) cosTheta = (2.*G4UniformRand())-1.;
+    else if (secKinetic <= 200.*eV) 	
+    {
+      if (G4UniformRand() <= 0.1) cosTheta = (2.*G4UniformRand())-1.;
+      else cosTheta = G4UniformRand()*(std::sqrt(2.)/2);
+    }
+    else	
+    {
+      G4double sin2O = (1.-secKinetic/k) / (1.+secKinetic/(2.*electron_mass_c2));
+      cosTheta = std::sqrt(1.-sin2O);
+    }
+  }
+ 
+  if (particleDefinition == G4Proton::ProtonDefinition()) 
+  {
+    G4double maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
+    phi = twopi * G4UniformRand();
+    cosTheta = std::sqrt(secKinetic / maxSecKinetic);
+  }			
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+double G4DNABornIonisationModel::DifferentialCrossSection(G4ParticleDefinition * particleDefinition, 
+							    G4double k, 
+							    G4double energyTransfer, 
+							    G4int ionizationLevelIndex)
+{
+  G4double sigma = 0.;
+
+  if (energyTransfer >= waterStructure.IonisationEnergy(ionizationLevelIndex))
+  {
+    G4double valueT1 = 0;
+    G4double valueT2 = 0;
+    G4double valueE21 = 0;
+    G4double valueE22 = 0;
+    G4double valueE12 = 0;
+    G4double valueE11 = 0;
+
+    G4double xs11 = 0;   
+    G4double xs12 = 0; 
+    G4double xs21 = 0; 
+    G4double xs22 = 0; 
+
+    if (particleDefinition == G4Electron::ElectronDefinition()) 
+    {
+      // k should be in eV and energy transfer eV also
+
+      std::vector<double>::iterator t2 = std::upper_bound(eTdummyVec.begin(),eTdummyVec.end(), k);
+
+      std::vector<double>::iterator t1 = t2-1;
+
+      // SI : the following condition avoids situations where energyTransfer >last vector element
+      if (energyTransfer <= eVecm[(*t1)].back())
+      {
+        std::vector<double>::iterator e12 = std::upper_bound(eVecm[(*t1)].begin(),eVecm[(*t1)].end(), energyTransfer);
+        std::vector<double>::iterator e11 = e12-1;
+
+        std::vector<double>::iterator e22 = std::upper_bound(eVecm[(*t2)].begin(),eVecm[(*t2)].end(), energyTransfer);
+        std::vector<double>::iterator e21 = e22-1;
+
+        valueT1  =*t1;
+        valueT2  =*t2;
+        valueE21 =*e21;
+        valueE22 =*e22;
+        valueE12 =*e12;
+        valueE11 =*e11;
+
+        xs11 = eDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
+        xs12 = eDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
+        xs21 = eDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
+        xs22 = eDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
+      }
+
+    }
+  
+   if (particleDefinition == G4Proton::ProtonDefinition()) 
+   {
+      // k should be in eV and energy transfer eV also
+      std::vector<double>::iterator t2 = std::upper_bound(pTdummyVec.begin(),pTdummyVec.end(), k);
+      std::vector<double>::iterator t1 = t2-1;
+      
+        std::vector<double>::iterator e12 = std::upper_bound(pVecm[(*t1)].begin(),pVecm[(*t1)].end(), energyTransfer);
+        std::vector<double>::iterator e11 = e12-1;
+
+        std::vector<double>::iterator e22 = std::upper_bound(pVecm[(*t2)].begin(),pVecm[(*t2)].end(), energyTransfer);
+        std::vector<double>::iterator e21 = e22-1;
+ 
+        valueT1  =*t1;
+        valueT2  =*t2;
+        valueE21 =*e21;
+        valueE22 =*e22;
+        valueE12 =*e12;
+        valueE11 =*e11;
+
+        xs11 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
+        xs12 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
+        xs21 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
+        xs22 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
+
+   }
+  
+   G4double xsProduct = xs11 * xs12 * xs21 * xs22;
+   if (xsProduct != 0.)
+   {
+     sigma = QuadInterpolator(     valueE11, valueE12, 
+				   valueE21, valueE22, 
+				   xs11, xs12, 
+				   xs21, xs22, 
+				   valueT1, valueT2, 
+				   k, energyTransfer);
+   }
+  
+ }
+  
+  return sigma;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNABornIonisationModel::LogLogInterpolate(G4double e1, 
+						       G4double e2, 
+						       G4double e, 
+						       G4double xs1, 
+						       G4double xs2)
+{
+  G4double a = (std::log10(xs2)-std::log10(xs1)) / (std::log10(e2)-std::log10(e1));
+  G4double b = std::log10(xs2) - a*std::log10(e2);
+  G4double sigma = a*std::log10(e) + b;
+  G4double value = (std::pow(10.,sigma));
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNABornIonisationModel::QuadInterpolator(G4double e11, G4double e12, 
+						      G4double e21, G4double e22, 
+						      G4double xs11, G4double xs12, 
+						      G4double xs21, G4double xs22, 
+						      G4double t1, G4double t2, 
+						      G4double t, G4double e)
+{
+  G4double interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
+  G4double interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
+  G4double value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNABornIonisationModel::RandomSelect(G4double k, const G4String& particle )
+{   
+  G4int level = 0;
+
+  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+  pos = tableData.find(particle);
+
+  if (pos != tableData.end())
+  {
+    G4DNACrossSectionDataSet* table = pos->second;
+
+    if (table != 0)
+    {
+      G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
+      const size_t n(table->NumberOfComponents());
+      size_t i(n);
+      G4double value = 0.;
+	    
+      while (i>0)
+      { 
+	i--;
+	valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
+	value += valuesBuffer[i];
+      }
+	    
+      value *= G4UniformRand();
+    
+      i = n;
+	    
+      while (i > 0)
+      {
+	i--;
+
+	if (valuesBuffer[i] > value)
+        {
+          delete[] valuesBuffer;
+          return i;
+        }
+	value -= valuesBuffer[i];
+      }
+	    
+      if (valuesBuffer) delete[] valuesBuffer;
+    
+    }
+  }
+  else
+  {
+    G4Exception("G4DNABornIonisationModel::RandomSelect attempting to calculate cross section for wrong particle");
+  }
+      
+  return level;
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChampionElasticModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChampionElasticModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChampionElasticModel.cc	(revision 1058)
@@ -0,0 +1,488 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAChampionElasticModel.cc,v 1.5 2009/04/29 17:25:21 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNAChampionElasticModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAChampionElasticModel::G4DNAChampionElasticModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  killBelowEnergy = 8.23*eV; // Minimum e- energy for energy loss by excitation
+  lowEnergyLimit = 0 * eV; 
+  lowEnergyLimitOfModel = 7 * eV; // The model lower energy is 7 eV
+  highEnergyLimit = 10 * MeV;
+  SetLowEnergyLimit(lowEnergyLimit);
+  SetHighEnergyLimit(highEnergyLimit);
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Champion Elastic model is constructed " << G4endl
+         << "Energy range: "
+         << lowEnergyLimit / eV << " eV - "
+         << highEnergyLimit / MeV << " MeV"
+         << G4endl;
+ 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAChampionElasticModel::~G4DNAChampionElasticModel()
+{  
+  // For total cross section
+  
+  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+  for (pos = tableData.begin(); pos != tableData.end(); ++pos)
+  {
+    G4DNACrossSectionDataSet* table = pos->second;
+    delete table;
+  }
+
+   // For final state
+   
+   eVecm.clear();
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* /*particle*/,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNAChampionElasticModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  if (LowEnergyLimit() < lowEnergyLimit)
+  {
+    G4cout << "G4DNAChampionElasticModel: low energy limit increased from " << 
+	LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
+    SetLowEnergyLimit(lowEnergyLimit);
+    }
+
+  if (HighEnergyLimit() > highEnergyLimit)
+  {
+    G4cout << "G4DNAChampionElasticModel: high energy limit decreased from " << 
+        HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
+    SetHighEnergyLimit(highEnergyLimit);
+  }
+
+  // Reading of data files 
+  
+  G4double scaleFactor = 1e-16*cm*cm;
+
+  G4String fileElectron("dna/sigma_elastic_e_champion");
+
+  G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
+  G4String electron;
+ 
+  if (electronDef != 0)
+  {
+    // For total cross section
+    
+    electron = electronDef->GetParticleName();
+
+    tableFile[electron] = fileElectron;
+
+    G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
+    tableE->LoadData(fileElectron);
+    tableData[electron] = tableE;
+    
+    // For final state
+    
+    char *path = getenv("G4LEDATA");
+ 
+    if (!path)
+    G4Exception("G4FinalStateElasticChampion::Initialise: G4LEDATA environment variable not set");
+
+    std::ostringstream eFullFileName;
+    eFullFileName << path << "/dna/sigmadiff_elastic_e_champion.dat";
+    std::ifstream eDiffCrossSection(eFullFileName.str().c_str());
+     
+    if (!eDiffCrossSection) G4Exception("G4DNAChampionElasticModel::Initialise: error opening electron DATA FILE");
+      
+    eTdummyVec.push_back(0.);
+
+    while(!eDiffCrossSection.eof())
+    {
+	double tDummy;
+	double eDummy;
+	eDiffCrossSection>>tDummy>>eDummy;
+
+	// SI : mandatory eVecm initialization
+        if (tDummy != eTdummyVec.back()) 
+        { 
+          eTdummyVec.push_back(tDummy); 
+          eVecm[tDummy].push_back(0.);
+        }
+	  
+        eDiffCrossSection>>eDiffCrossSectionData[tDummy][eDummy];
+
+	// SI : only if not end of file reached !
+        if (!eDiffCrossSection.eof()) eDiffCrossSectionData[tDummy][eDummy]*=scaleFactor;
+	  
+        if (eDummy != eVecm[tDummy].back()) eVecm[tDummy].push_back(eDummy);
+          
+    }
+
+    // End final state
+  
+  }
+  else G4Exception("G4DNAChampionElasticModel::Initialise: electron is not defined");
+  
+  if (verboseLevel > 2) 
+    G4cout << "Loaded cross section files for Champion Elastic model" << G4endl;
+
+  G4cout << "Champion Elastic model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / eV << " eV - "
+         << HighEnergyLimit() / MeV << " MeV"
+         << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAChampionElasticModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* p,
+					   G4double ekin,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNAChampionElasticModel" << G4endl;
+
+ // Calculate total cross section for model
+
+ G4double sigma=0;
+ 
+ if (flagMaterialIsWater)
+ {
+  const G4String& particleName = p->GetParticleName();
+
+  if (ekin < highEnergyLimit)
+  {
+      //SI : XS must not be zero otherwise sampling of secondaries method ignored
+      if (ekin < lowEnergyLimitOfModel) ekin = lowEnergyLimitOfModel;
+      //      
+      
+	std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+	pos = tableData.find(particleName);
+	
+	if (pos != tableData.end())
+	{
+	  G4DNACrossSectionDataSet* table = pos->second;
+	  if (table != 0)
+	  {
+	    sigma = table->FindValue(ekin);
+	  }
+	}
+	else
+	{
+	    G4Exception("G4DNAChampionElasticModel::ComputeCrossSectionPerVolume: attempting to calculate cross section for wrong particle");
+	}
+  }
+
+  if (verboseLevel > 3)
+  {
+    G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
+    G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
+    G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
+  } 
+
+ } // if (flagMaterialIsWater)
+         
+ return sigma*densityWater;		   
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAChampionElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicElectron,
+					      G4double,
+					      G4double)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNAChampionElasticModel" << G4endl;
+
+  G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
+  
+  if (electronEnergy0 < killBelowEnergy)
+  {
+    fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
+    fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
+    return ;
+  }
+
+  if (electronEnergy0>= killBelowEnergy && electronEnergy0 < highEnergyLimit)
+  {  
+    G4double cosTheta = RandomizeCosTheta(electronEnergy0);
+  
+    G4double phi = 2. * pi * G4UniformRand();
+
+    G4ThreeVector zVers = aDynamicElectron->GetMomentumDirection();
+    G4ThreeVector xVers = zVers.orthogonal();
+    G4ThreeVector yVers = zVers.cross(xVers);
+
+    G4double xDir = std::sqrt(1. - cosTheta*cosTheta);
+    G4double yDir = xDir;
+    xDir *= std::cos(phi);
+    yDir *= std::sin(phi);
+
+    G4ThreeVector zPrimeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
+
+    fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit()) ;
+
+    fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
+  }
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAChampionElasticModel::DifferentialCrossSection
+  (G4ParticleDefinition * particleDefinition, G4double k, G4double theta) 							  
+{
+
+  G4double sigma = 0.;
+  G4double valueT1 = 0;
+  G4double valueT2 = 0;
+  G4double valueE21 = 0;
+  G4double valueE22 = 0;
+  G4double valueE12 = 0;
+  G4double valueE11 = 0;
+  G4double xs11 = 0;   
+  G4double xs12 = 0; 
+  G4double xs21 = 0; 
+  G4double xs22 = 0; 
+
+  //SI : ensure the correct computation of cross section at the 180*deg limit
+  if (theta==180.) theta=theta-1e-9;
+
+  if (particleDefinition == G4Electron::ElectronDefinition()) 
+  {
+    std::vector<double>::iterator t2 = std::upper_bound(eTdummyVec.begin(),eTdummyVec.end(), k);
+    std::vector<double>::iterator t1 = t2-1;
+ 
+    std::vector<double>::iterator e12 = std::upper_bound(eVecm[(*t1)].begin(),eVecm[(*t1)].end(), theta);
+    std::vector<double>::iterator e11 = e12-1;
+	  
+    std::vector<double>::iterator e22 = std::upper_bound(eVecm[(*t2)].begin(),eVecm[(*t2)].end(), theta);
+    std::vector<double>::iterator e21 = e22-1;
+	  	
+    valueT1  =*t1;
+    valueT2  =*t2;
+    valueE21 =*e21;
+    valueE22 =*e22;
+    valueE12 =*e12;
+    valueE11 =*e11;
+
+    xs11 = eDiffCrossSectionData[valueT1][valueE11];
+    xs12 = eDiffCrossSectionData[valueT1][valueE12];
+    xs21 = eDiffCrossSectionData[valueT2][valueE21];
+    xs22 = eDiffCrossSectionData[valueT2][valueE22];
+
+}
+     
+  G4double xsProduct = xs11 * xs12 * xs21 * xs22;
+  
+  if (xs11==0 || xs12==0 ||xs21==0 ||xs22==0) return (0.);
+     
+  if (xsProduct != 0.)
+  {
+    sigma = QuadInterpolator(  valueE11, valueE12, 
+    			       valueE21, valueE22, 
+			       xs11, xs12, 
+			       xs21, xs22, 
+			       valueT1, valueT2, 
+			       k, theta );
+  }
+
+  return sigma;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAChampionElasticModel::LinLogInterpolate(G4double e1, 
+						        G4double e2, 
+						        G4double e, 
+						        G4double xs1, 
+						        G4double xs2)
+{
+  G4double d1 = std::log(xs1);
+  G4double d2 = std::log(xs2);
+  G4double value = std::exp(d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAChampionElasticModel::LogLogInterpolate(G4double e1, 
+						        G4double e2, 
+						        G4double e, 
+						        G4double xs1, 
+						        G4double xs2)
+{
+  G4double a = (std::log10(xs2)-std::log10(xs1)) / (std::log10(e2)-std::log10(e1));
+  G4double b = std::log10(xs2) - a*std::log10(e2);
+  G4double sigma = a*std::log10(e) + b;
+  G4double value = (std::pow(10.,sigma));
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAChampionElasticModel::QuadInterpolator(G4double e11, G4double e12, 
+						       G4double e21, G4double e22, 
+						       G4double xs11, G4double xs12, 
+						       G4double xs21, G4double xs22, 
+						       G4double t1, G4double t2, 
+						       G4double t, G4double e)
+{
+// Log-Log
+/*
+  G4double interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
+  G4double interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
+  G4double value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
+*/
+
+// Lin-Log
+  G4double interpolatedvalue1 = LinLogInterpolate(e11, e12, e, xs11, xs12);
+  G4double interpolatedvalue2 = LinLogInterpolate(e21, e22, e, xs21, xs22);
+  G4double value = LinLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAChampionElasticModel::RandomizeCosTheta(G4double k) 
+{
+ // ***** Similar method as for screened Rutherford scattering
+
+ G4int iMax=180;
+ G4double max=0;
+ G4double tmp=0;
+ 
+ // Look for maximum :
+ for (G4int i=0; i<iMax; i++) 
+ {
+   tmp = DifferentialCrossSection(G4Electron::ElectronDefinition(),k/eV,G4double(i)*180./(iMax-1));
+   if (tmp>max) max = tmp;
+ }
+
+ G4double oneOverMax=0;
+ if (max!=0) oneOverMax = 1./max;
+  
+ G4double cosTheta = 0.;
+ G4double fCosTheta = 0.;
+  
+ do
+ {
+    cosTheta = 2. * G4UniformRand() - 1.;
+    fCosTheta = oneOverMax * DifferentialCrossSection(G4Electron::ElectronDefinition(),k/eV,std::acos(cosTheta)*180./pi);
+ }
+ while (fCosTheta < G4UniformRand());
+
+ if (verboseLevel > 3)
+ {
+   G4cout << "---> Cos(theta)=" << cosTheta << G4endl;
+ } 
+
+ return cosTheta; 
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChargeDecrease.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChargeDecrease.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChargeDecrease.cc	(revision 1058)
@@ -0,0 +1,95 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAChargeDecrease.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+
+#include "G4DNAChargeDecrease.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+using namespace std;
+
+G4DNAChargeDecrease::G4DNAChargeDecrease(const G4String& processName,
+  G4ProcessType type):G4VEmProcess (processName, type),
+    isInitialised(false)
+{
+  SetProcessSubType(51);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+ 
+G4DNAChargeDecrease::~G4DNAChargeDecrease()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+ 
+G4bool G4DNAChargeDecrease::IsApplicable(const G4ParticleDefinition& p)
+{
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  return 
+    (
+       &p == G4Proton::ProtonDefinition()
+    || &p == instance->GetIon("alpha++")
+    || &p == instance->GetIon("alpha+")
+    );
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAChargeDecrease::InitialiseProcess(const G4ParticleDefinition* p)
+{
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+    SetBuildTableFlag(false);
+    
+    G4String name = p->GetParticleName();
+
+    if( name == "proton" || name == "alpha" || name == "alpha+" )
+    {
+      if(!Model()) SetModel(new G4DNADingfelderChargeDecreaseModel);
+      Model()->SetLowEnergyLimit(1*keV);
+      Model()->SetHighEnergyLimit(10*MeV);
+
+      AddEmModel(1, Model());   
+    }
+    
+  } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4DNAChargeDecrease::PrintInfo()
+{
+  G4cout
+    << " Total cross sections computed from " << Model()->GetName() << " model"
+    << G4endl;
+}         
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChargeIncrease.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChargeIncrease.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAChargeIncrease.cc	(revision 1058)
@@ -0,0 +1,95 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAChargeIncrease.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+
+#include "G4DNAChargeIncrease.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+using namespace std;
+
+G4DNAChargeIncrease::G4DNAChargeIncrease(const G4String& processName,
+  G4ProcessType type):G4VEmProcess (processName, type),
+    isInitialised(false)
+{
+  SetProcessSubType(51);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+ 
+G4DNAChargeIncrease::~G4DNAChargeIncrease()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4bool G4DNAChargeIncrease::IsApplicable(const G4ParticleDefinition& p)
+{
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  return 
+    (
+       &p == instance->GetIon("hydrogen")
+    || &p == instance->GetIon("alpha+")
+    || &p == instance->GetIon("helium")
+    );
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAChargeIncrease::InitialiseProcess(const G4ParticleDefinition* p)
+{
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+    SetBuildTableFlag(false);
+
+    G4String name = p->GetParticleName();
+
+    if( name == "hydrogen" || name =="alpha+" || name =="helium" )
+    {
+      if(!Model()) SetModel(new G4DNADingfelderChargeIncreaseModel);
+      Model()->SetLowEnergyLimit(1*keV);
+      Model()->SetHighEnergyLimit(10*MeV);
+
+      AddEmModel(1, Model());   
+    }
+    
+  } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4DNAChargeIncrease::PrintInfo()
+{
+  G4cout
+    << " Total cross sections computed from " << Model()->GetName() << " model"
+    << G4endl;
+}         
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNADingfelderChargeDecreaseModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNADingfelderChargeDecreaseModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNADingfelderChargeDecreaseModel.cc	(revision 1058)
@@ -0,0 +1,598 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNADingfelderChargeDecreaseModel.cc,v 1.3 2009/02/16 11:00:11 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNADingfelderChargeDecreaseModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNADingfelderChargeDecreaseModel::G4DNADingfelderChargeDecreaseModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Dingfelder charge decrease model is constructed " << G4endl;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNADingfelderChargeDecreaseModel::~G4DNADingfelderChargeDecreaseModel()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNADingfelderChargeDecreaseModel::Initialise(const G4ParticleDefinition* particle,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNADingfelderChargeDecreaseModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
+  G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
+  G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
+
+  G4String proton;
+  G4String alphaPlusPlus;
+  G4String alphaPlus;
+
+  if (protonDef != 0)
+  {
+    proton = protonDef->GetParticleName();
+    lowEnergyLimit[proton] = 1. * keV;
+    highEnergyLimit[proton] = 10. * MeV;
+  }
+  else
+  {
+    G4Exception("G4DNADingfelderChargeDecreaseModel::Initialise: proton is not defined");
+  }
+
+  if (alphaPlusPlusDef != 0)
+  {
+    alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
+    lowEnergyLimit[alphaPlusPlus] = 1. * keV;
+    highEnergyLimit[alphaPlusPlus] = 10. * MeV;
+  }
+  else
+  {
+    G4Exception("G4DNADingfelderChargeDecreaseModel::Initialise: alphaPlusPlus is not defined");
+  }
+
+  if (alphaPlusDef != 0)
+  {
+    alphaPlus = alphaPlusDef->GetParticleName();
+    lowEnergyLimit[alphaPlus] = 1. * keV;
+    highEnergyLimit[alphaPlus] = 10. * MeV;
+  }
+  else
+  {
+    G4Exception("G4DNADingfelderChargeDecreaseModel::Initialise: alphaPlus is not defined");
+  }
+
+  if (particle==protonDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[proton]);
+    SetHighEnergyLimit(highEnergyLimit[proton]);
+  }
+
+  if (particle==alphaPlusPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
+  }
+
+  if (particle==alphaPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
+  }
+
+  // Final state
+  
+    //PROTON
+  f0[0][0]=1.;
+  a0[0][0]=-0.180;
+  a1[0][0]=-3.600;
+  b0[0][0]=-18.22;
+  b1[0][0]=-1.997;
+  c0[0][0]=0.215;
+  d0[0][0]=3.550;
+  x0[0][0]=3.450;
+  x1[0][0]=5.251;
+
+  numberOfPartialCrossSections[0] = 1;
+
+  //ALPHA++
+  f0[0][1]=1.;  a0[0][1]=0.95;
+  a1[0][1]=-2.75;
+  b0[0][1]=-23.00;
+  c0[0][1]=0.215;
+  d0[0][1]=2.95;
+  x0[0][1]=3.50;
+
+  f0[1][1]=1.;
+  a0[1][1]=0.95;
+  a1[1][1]=-2.75;
+  b0[1][1]=-23.73;
+  c0[1][1]=0.250;
+  d0[1][1]=3.55;
+  x0[1][1]=3.72;
+
+  x1[0][1]=-1.;
+  b1[0][1]=-1.;
+
+  x1[1][1]=-1.;
+  b1[1][1]=-1.;  
+ 
+  numberOfPartialCrossSections[1] = 2;
+
+  // ALPHA+
+  f0[0][2]=1.;
+  a0[0][2]=0.65;
+  a1[0][2]=-2.75;
+  b0[0][2]=-21.81;
+  c0[0][2]=0.232;
+  d0[0][2]=2.95;
+  x0[0][2]=3.53;
+
+  x1[0][2]=-1.;
+  b1[0][2]=-1.;
+ 
+  numberOfPartialCrossSections[2] = 1;
+
+  //
+  
+  G4cout << "Dingfelder charge decrease model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / keV << " keV - "
+         << HighEnergyLimit() / MeV << " MeV for "
+         << particle->GetParticleName()
+         << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+  
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double k,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNADingfelderChargeDecreaseModel" << G4endl;
+
+ // Calculate total cross section for model
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (
+      particleDefinition != G4Proton::ProtonDefinition()
+      &&
+      particleDefinition != instance->GetIon("alpha++")
+      &&
+      particleDefinition != instance->GetIon("alpha+")
+     )
+   	    
+    return 0;
+
+  G4double lowLim = 0;
+  G4double highLim = 0;
+  G4double crossSection = 0.;
+
+  if (flagMaterialIsWater)
+  {
+    const G4String& particleName = particleDefinition->GetParticleName();
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+    pos1 = lowEnergyLimit.find(particleName);
+
+    if (pos1 != lowEnergyLimit.end())
+    {
+      lowLim = pos1->second;
+    }
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+    pos2 = highEnergyLimit.find(particleName);
+
+    if (pos2 != highEnergyLimit.end())
+    {
+      highLim = pos2->second;
+    }
+
+    if (k >= lowLim && k < highLim)
+    {
+      crossSection = Sum(k,particleDefinition);
+    }
+ 
+    if (verboseLevel > 3)
+    {
+      G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
+      G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
+      G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*densityWater/(1./cm) << G4endl;
+    } 
+
+  } // if (flagMaterialIsWater)
+
+ return crossSection*densityWater;		   
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNADingfelderChargeDecreaseModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicParticle,
+					      G4double,
+					      G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNADingfelderChargeDecreaseModel" << G4endl;
+
+  G4double inK = aDynamicParticle->GetKineticEnergy();
+  
+  G4ParticleDefinition* definition = aDynamicParticle->GetDefinition();
+
+  G4int finalStateIndex = RandomSelect(inK,definition);
+ 
+  G4int n = NumberOfFinalStates(definition, finalStateIndex);
+  G4double waterBindingEnergy = WaterBindingEnergyConstant(definition, finalStateIndex);
+  G4double outgoingParticleBindingEnergy = OutgoingParticleBindingEnergyConstant(definition, finalStateIndex);
+  
+  G4double outK = 0.;
+  if (definition==G4Proton::Proton())
+    outK = inK - n*(inK*electron_mass_c2/proton_mass_c2) - waterBindingEnergy + outgoingParticleBindingEnergy;
+  else
+    outK = inK - n*(inK*electron_mass_c2/(3728*MeV)) - waterBindingEnergy + outgoingParticleBindingEnergy;
+  
+  if (outK<0)
+  {
+    G4String message;
+    message="G4DNADingfelderChargeDecreaseModel::SampleSecondaries: final kinetic energy is below 0! Process ";
+    G4Exception(message);
+  }
+  
+  fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
+  fParticleChangeForGamma->ProposeLocalEnergyDeposit(waterBindingEnergy);
+  
+  G4DynamicParticle* dp = new G4DynamicParticle (OutgoingParticleDefinition(definition, finalStateIndex), 
+							aDynamicParticle->GetMomentumDirection(), 
+							outK) ;
+  fvect->push_back(dp);
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNADingfelderChargeDecreaseModel::NumberOfFinalStates(G4ParticleDefinition* particleDefinition, 
+						      G4int finalStateIndex )
+  
+{
+  if (particleDefinition == G4Proton::Proton()) return 1;
+  
+  G4DNAGenericIonsManager*instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  
+  if (particleDefinition == instance->GetIon("alpha++") ) 
+  {
+    if (finalStateIndex==0)  return 1;
+    return 2;   
+  }
+  
+  if (particleDefinition == instance->GetIon("alpha+") ) return 1;
+  
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4ParticleDefinition* G4DNADingfelderChargeDecreaseModel::OutgoingParticleDefinition (G4ParticleDefinition* particleDefinition, 
+									      G4int finalStateIndex) 
+{
+  G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
+  
+  if (particleDefinition == G4Proton::Proton()) return instance->GetIon("hydrogen"); 
+  
+  if (particleDefinition == instance->GetIon("alpha++") ) 
+  {
+    if (finalStateIndex == 0) return instance->GetIon("alpha+"); 
+    return instance->GetIon("helium");    
+  }
+  
+  if (particleDefinition == instance->GetIon("alpha+") ) return instance->GetIon("helium");    
+  
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeDecreaseModel::WaterBindingEnergyConstant(G4ParticleDefinition* particleDefinition, 
+								G4int finalStateIndex )
+{
+  // Ionization energy of first water shell
+  // Rad. Phys. Chem. 59 p.267 by Dingf. et al.
+  // W + 10.79 eV -> W+ + e-
+  
+  G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
+  
+  if(particleDefinition == G4Proton::Proton()) return 10.79*eV;
+
+  if (particleDefinition == instance->GetIon("alpha++") ) 
+  {
+      // Binding energy for    W+ -> W++ + e-    10.79 eV
+      // Binding energy for    W  -> W+  + e-    10.79 eV
+      //
+      // Ionization energy of first water shell
+      // Rad. Phys. Chem. 59 p.267 by Dingf. et al.
+
+      if (finalStateIndex == 0) return 10.79*eV;
+  
+      return 10.79*2*eV;
+  }
+
+  if (particleDefinition == instance->GetIon("alpha+") ) 
+  {
+      // Binding energy for    W+ -> W++ + e-    10.79 eV
+      // Binding energy for    W  -> W+  + e-    10.79 eV
+      //
+      // Ionization energy of first water shell
+      // Rad. Phys. Chem. 59 p.267 by Dingf. et al.
+
+      return 10.79*eV;
+  }
+  
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeDecreaseModel::OutgoingParticleBindingEnergyConstant(G4ParticleDefinition* particleDefinition, 
+									   G4int finalStateIndex)
+{
+  G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
+  
+  if(particleDefinition == G4Proton::Proton()) return 13.6*eV;
+
+  if (particleDefinition == instance->GetIon("alpha++") ) 
+  {
+      // Binding energy for    He+ -> He++ + e-    54.509 eV
+      // Binding energy for    He  -> He+  + e-    24.587 eV
+
+      if (finalStateIndex==0)	return 54.509*eV;
+      
+      return (54.509 + 24.587)*eV;
+  }
+  
+  if (particleDefinition == instance->GetIon("alpha+") ) 
+  {
+      // Binding energy for    He+ -> He++ + e-    54.509 eV
+      // Binding energy for    He  -> He+  + e-    24.587 eV
+      
+      return 24.587*eV;
+  }  
+  
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeDecreaseModel::PartialCrossSection(G4double k, G4int index, 
+							   const G4ParticleDefinition* particleDefinition)
+{
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager* instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
+  if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
+
+  //
+  // sigma(T) = f0 10 ^ y(log10(T/eV))
+  //
+  //         /  a0 x + b0                    x < x0
+  //         |
+  // y(x) = <   a0 x + b0 - c0 (x - x0)^d0   x0 <= x < x1
+  //         |
+  //         \  a1 x + b1                    x >= x1
+  //
+  //
+  // f0, a0, a1, b0, b1, c0, d0, x0, x1 are parameters that change for protons and helium (0, +, ++)
+  //
+  // f0 has been added to the code in order to manage partial (shell-dependent) cross sections (if no shell dependence is present. f0=1. Sum of f0 over the considered shells should give 1)
+  //
+  // From Rad. Phys. and Chem. 59 (2000) 255-275, M. Dingfelder et al.
+  // Inelastic-collision cross sections of liquid water for interactions of energetic proton
+  //
+  
+  if (x1[index][particleTypeIndex]<x0[index][particleTypeIndex])
+  {
+      //
+      // if x1 < x0 means that x1 and b1 will be calculated with the following formula (this piece of code is run on all alphas and not on protons)
+      //
+      // x1 = x0 + ((a0 - a1)/(c0 * d0)) ^ (1 / (d0 - 1))
+      //
+      // b1 = (a0 - a1) * x1 + b0 - c0 * (x1 - x0) ^ d0
+      //
+ 
+      x1[index][particleTypeIndex]=x0[index][particleTypeIndex] + std::pow((a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) 
+									   / (c0[index][particleTypeIndex] * d0[index][particleTypeIndex]), 1. / (d0[index][particleTypeIndex] - 1.));
+      b1[index][particleTypeIndex]=(a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) * x1[index][particleTypeIndex] 
+	+ b0[index][particleTypeIndex] - c0[index][particleTypeIndex] * std::pow(x1[index][particleTypeIndex] 
+										 - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
+  }
+
+  G4double x(std::log10(k/eV));
+  G4double y;
+  
+  if (x<x0[index][particleTypeIndex])
+    y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex];
+  else if (x<x1[index][particleTypeIndex])
+    y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex] - c0[index][particleTypeIndex] 
+      * std::pow(x - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
+  else
+    y=a1[index][particleTypeIndex] * x + b1[index][particleTypeIndex];
+
+  return f0[index][particleTypeIndex] * std::pow(10., y)*m*m;
+  
+}
+
+G4int G4DNADingfelderChargeDecreaseModel::RandomSelect(G4double k, 
+							const G4ParticleDefinition* particleDefinition)
+{
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex = 0;
+  if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex = 1;
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex = 2;
+
+  const G4int n = numberOfPartialCrossSections[particleTypeIndex];
+  G4double* values(new G4double[n]);
+  G4double value(0);
+  G4int i = n;
+  
+  while (i>0)
+  {
+      i--;
+      values[i]=PartialCrossSection(k, i, particleDefinition);
+      value+=values[i];
+  }
+  
+  value*=G4UniformRand();
+  
+  i=n;
+  while (i>0)
+  {
+      i--;
+   
+      if (values[i]>value)
+	break;
+  
+      value-=values[i];
+  }
+  
+  delete[] values;
+  
+  return i;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeDecreaseModel::Sum(G4double k, const G4ParticleDefinition* particleDefinition)
+{
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager* instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
+  if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
+
+  G4double totalCrossSection = 0.;
+
+  for (G4int i=0; i<numberOfPartialCrossSections[particleTypeIndex]; i++)
+  {
+    totalCrossSection += PartialCrossSection(k,i,particleDefinition);
+  }
+  return totalCrossSection;
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNADingfelderChargeIncreaseModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNADingfelderChargeIncreaseModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNADingfelderChargeIncreaseModel.cc	(revision 1058)
@@ -0,0 +1,569 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNADingfelderChargeIncreaseModel.cc,v 1.3 2009/02/16 11:00:11 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNADingfelderChargeIncreaseModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNADingfelderChargeIncreaseModel::G4DNADingfelderChargeIncreaseModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Dingfelder charge increase model is constructed " << G4endl;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNADingfelderChargeIncreaseModel::~G4DNADingfelderChargeIncreaseModel()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNADingfelderChargeIncreaseModel::Initialise(const G4ParticleDefinition* particle,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNADingfelderChargeIncreaseModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
+  G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
+  G4ParticleDefinition* heliumDef = instance->GetIon("helium");
+
+  G4String hydrogen;
+  G4String alphaPlus;
+  G4String helium;
+
+  if (hydrogenDef != 0)
+  {
+    hydrogen = hydrogenDef->GetParticleName();
+    lowEnergyLimit[hydrogen] = 1. * keV;
+    highEnergyLimit[hydrogen] = 10. * MeV;
+  }
+  else
+  {
+    G4Exception("G4DNADingfelderChargeIncreaseModel::Initialise: hydrogen is not defined");
+  }
+
+  if (alphaPlusDef != 0)
+  {
+    alphaPlus = alphaPlusDef->GetParticleName();
+    lowEnergyLimit[alphaPlus] = 1. * keV;
+    highEnergyLimit[alphaPlus] = 10. * MeV;
+  }
+  else
+  {
+    G4Exception("G4DNADingfelderChargeIncreaseModel::Initialise: alphaPlus is not defined");
+  }
+
+  if (heliumDef != 0)
+  {
+    helium = heliumDef->GetParticleName();
+    lowEnergyLimit[helium] = 1. * keV;
+    highEnergyLimit[helium] = 10. * MeV;
+  }
+  else
+  {
+    G4Exception("G4DNADingfelderChargeIncreaseModel::Initialise: helium is not defined");
+  }
+  
+  if (particle==hydrogenDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[hydrogen]);
+    SetHighEnergyLimit(highEnergyLimit[hydrogen]);
+  }
+
+  if (particle==alphaPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
+  }
+
+  if (particle==heliumDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[helium]);
+    SetHighEnergyLimit(highEnergyLimit[helium]);
+  }
+
+  // Final state
+  
+  //ALPHA+
+
+  f0[0][0]=1.;
+  a0[0][0]=2.25;
+  a1[0][0]=-0.75;
+  b0[0][0]=-32.10;
+  c0[0][0]=0.600;
+  d0[0][0]=2.40;
+  x0[0][0]=4.60;
+
+  x1[0][0]=-1.;
+  b1[0][0]=-1.;
+   
+  numberOfPartialCrossSections[0]=1;
+
+  //HELIUM
+
+  f0[0][1]=1.;
+  a0[0][1]=2.25;
+  a1[0][1]=-0.75;
+  b0[0][1]=-30.93;
+  c0[0][1]=0.590;
+  d0[0][1]=2.35;
+  x0[0][1]=4.29;
+
+  f0[1][1]=1.;
+  a0[1][1]=2.25;
+  a1[1][1]=-0.75;
+  b0[1][1]=-32.61;
+  c0[1][1]=0.435;
+  d0[1][1]=2.70;
+  x0[1][1]=4.45;
+
+  x1[0][1]=-1.;
+  b1[0][1]=-1.;
+
+  x1[1][1]=-1.;
+  b1[1][1]=-1.;
+
+  numberOfPartialCrossSections[1]=2;
+  
+  //
+  
+  G4cout << "Dingfelder charge increase model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / keV << " keV - "
+         << HighEnergyLimit() / MeV << " MeV for "
+         << particle->GetParticleName()
+         << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+  
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double k,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNADingfelderChargeIncreaseModel" << G4endl;
+
+ // Calculate total cross section for model
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (
+      particleDefinition != instance->GetIon("hydrogen")
+      &&
+      particleDefinition != instance->GetIon("alpha+")
+      &&
+      particleDefinition != instance->GetIon("helium")
+      )
+         	    
+    return 0;
+
+  G4double lowLim = 0;
+  G4double highLim = 0;
+  G4double totalCrossSection = 0.;
+ 
+  if (flagMaterialIsWater)
+  {
+    const G4String& particleName = particleDefinition->GetParticleName();
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+    pos1 = lowEnergyLimit.find(particleName);
+
+    if (pos1 != lowEnergyLimit.end())
+    {
+      lowLim = pos1->second;
+    }
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+    pos2 = highEnergyLimit.find(particleName);
+
+    if (pos2 != highEnergyLimit.end())
+    {
+      highLim = pos2->second;
+    }
+
+    if (k >= lowLim && k < highLim)
+    {
+      //HYDROGEN
+      if (particleDefinition == instance->GetIon("hydrogen"))
+      {
+	  const  G4double aa = 2.835;
+	  const  G4double bb = 0.310;
+	  const  G4double cc = 2.100;
+	  const  G4double dd = 0.760;
+	  const  G4double fac = 1.0e-18;
+	  const  G4double rr = 13.606 * eV;  
+	  
+	  G4double t = k / (proton_mass_c2/electron_mass_c2); 
+	  G4double x = t / rr; 
+	  G4double temp = 4.0 * pi * Bohr_radius/nm * Bohr_radius/nm * fac;
+	  G4double sigmal =  temp * cc * (std::pow(x,dd));
+	  G4double sigmah = temp * (aa * std::log(1.0 + x) + bb) / x;
+	  totalCrossSection = 1.0/(1.0/sigmal + 1.0/sigmah) *m*m;
+      }
+      else
+      {
+	  totalCrossSection = Sum(k,particleDefinition);
+      }
+    }
+ 
+    if (verboseLevel > 3)
+    {
+      G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
+      G4cout << " - Cross section per water molecule (cm^2)=" << totalCrossSection/cm/cm << G4endl;
+      G4cout << " - Cross section per water molecule (cm^-1)=" << totalCrossSection*densityWater/(1./cm) << G4endl;
+    } 
+
+  } // if (flagMaterialIsWater)
+
+  return totalCrossSection*densityWater;		   
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNADingfelderChargeIncreaseModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicParticle,
+					      G4double,
+					      G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNADingfelderChargeIncreaseModel" << G4endl;
+
+  fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
+  fParticleChangeForGamma->ProposeLocalEnergyDeposit(0.);
+
+  G4ParticleDefinition* definition = aDynamicParticle->GetDefinition();
+ 
+  G4double inK = aDynamicParticle->GetKineticEnergy();
+
+  G4int finalStateIndex = RandomSelect(inK,definition);
+
+  G4int n = NumberOfFinalStates(definition,finalStateIndex);
+  
+  G4double outK = inK - IncomingParticleBindingEnergyConstant(definition,finalStateIndex);
+
+  G4DNAGenericIonsManager* instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  G4double electronK;
+  if (definition == instance->GetIon("hydrogen")) electronK = inK*electron_mass_c2/proton_mass_c2;
+  else electronK = inK*electron_mass_c2/(3728*MeV);
+  
+  if (outK<0)
+  {
+    G4String message;
+    message="G4DNADingfelderChargeIncreaseModel::SampleSecondaries: final kinetic energy is below 0! Process ";
+  }
+  
+  G4DynamicParticle* dp = new G4DynamicParticle 
+  
+  (OutgoingParticleDefinition(definition,finalStateIndex), 
+   aDynamicParticle->GetMomentumDirection(), 
+   outK) ;
+
+  fvect->push_back(dp);
+
+  n = n - 1;
+  
+  while (n>0)
+  {
+    n--;
+    fvect->push_back(new G4DynamicParticle 
+    (G4Electron::Electron(), aDynamicParticle->GetMomentumDirection(), electronK) );
+  }
+        
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNADingfelderChargeIncreaseModel::NumberOfFinalStates(G4ParticleDefinition* particleDefinition, 
+						      G4int finalStateIndex )
+  
+{
+  G4DNAGenericIonsManager* instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  if (particleDefinition == instance->GetIon("hydrogen")) return 2;
+  if (particleDefinition == instance->GetIon("alpha+")) return 2;
+  
+  if (particleDefinition == instance->GetIon("helium")) 
+  {    if (finalStateIndex==0) return 2;
+       return 3;
+  }
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4ParticleDefinition* G4DNADingfelderChargeIncreaseModel::OutgoingParticleDefinition (G4ParticleDefinition* particleDefinition, 
+									      G4int finalStateIndex) 
+{
+  G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
+  if (particleDefinition == instance->GetIon("hydrogen")) return G4Proton::Proton(); 
+  if (particleDefinition == instance->GetIon("alpha+")) return instance->GetIon("alpha++");
+
+  if (particleDefinition == instance->GetIon("alpha+")) return instance->GetIon("helium");
+  {
+    if (finalStateIndex==0) return instance->GetIon("alpha+"); 
+    return instance->GetIon("alpha++");
+  }
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeIncreaseModel::IncomingParticleBindingEnergyConstant(G4ParticleDefinition* particleDefinition, 
+									   G4int finalStateIndex )
+{
+  G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
+  if(particleDefinition == instance->GetIon("hydrogen")) return 13.6*eV;
+  
+  if(particleDefinition == instance->GetIon("alpha+"))
+  {
+      // Binding energy for    He+ -> He++ + e-    54.509 eV
+      // Binding energy for    He  -> He+  + e-    24.587 eV
+      return 54.509*eV;
+  }
+   
+  if(particleDefinition == instance->GetIon("helium"))
+  {
+      // Binding energy for    He+ -> He++ + e-    54.509 eV
+      // Binding energy for    He  -> He+  + e-    24.587 eV
+
+      if (finalStateIndex==0) return 24.587*eV;
+      return (54.509 + 24.587)*eV;
+  }  
+
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeIncreaseModel::PartialCrossSection(G4double k, G4int index, 
+							   const G4ParticleDefinition* particleDefinition)
+{
+
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=0;
+  if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=1;
+
+  //
+  // sigma(T) = f0 10 ^ y(log10(T/eV))
+  //
+  //         /  a0 x + b0                    x < x0
+  //         |
+  // y(x) = <   a0 x + b0 - c0 (x - x0)^d0   x0 <= x < x1
+  //         |
+  //         \  a1 x + b1                    x >= x1
+  //
+  //
+  // f0, a0, a1, b0, b1, c0, d0, x0, x1 are parameters that change for protons and helium (0, +, ++)
+  //
+  // f0 has been added to the code in order to manage partial (shell-dependent) cross sections (if no shell dependence is present. f0=1. Sum of f0 over the considered shells should give 1)
+  //
+  // From Rad. Phys. and Chem. 59 (2000) 255-275, M. Dingfelder et al.
+  // Inelastic-collision cross sections of liquid water for interactions of energetic proton
+  //
+  
+  if (x1[index][particleTypeIndex]<x0[index][particleTypeIndex])
+  {
+      //
+      // if x1 < x0 means that x1 and b1 will be calculated with the following formula (this piece of code is run on all alphas and not on protons)
+      //
+      // x1 = x0 + ((a0 - a1)/(c0 * d0)) ^ (1 / (d0 - 1))
+      //
+      // b1 = (a0 - a1) * x1 + b0 - c0 * (x1 - x0) ^ d0
+      //
+ 
+      x1[index][particleTypeIndex]=x0[index][particleTypeIndex] + std::pow((a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) / (c0[index][particleTypeIndex] * d0[index][particleTypeIndex]), 1. / (d0[index][particleTypeIndex] - 1.));
+      b1[index][particleTypeIndex]=(a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) * x1[index][particleTypeIndex] + b0[index][particleTypeIndex] - c0[index][particleTypeIndex] * std::pow(x1[index][particleTypeIndex] - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
+  }
+
+  G4double x(std::log10(k/eV));
+  G4double y;
+  
+  if (x<x0[index][particleTypeIndex])
+    y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex];
+  else if (x<x1[index][particleTypeIndex])
+    y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex] - c0[index][particleTypeIndex] * std::pow(x - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
+  else
+    y=a1[index][particleTypeIndex] * x + b1[index][particleTypeIndex];
+
+  return f0[index][particleTypeIndex] * std::pow(10., y)*m*m;
+  
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNADingfelderChargeIncreaseModel::RandomSelect(G4double k, 
+							const G4ParticleDefinition* particleDefinition)
+{
+
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == instance->GetIon("hydrogen")) return 0;
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=0;
+  if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=1;
+
+  const G4int n = numberOfPartialCrossSections[particleTypeIndex];
+  G4double* values(new G4double[n]);
+  G4double value = 0;
+  G4int i = n;
+  
+  while (i>0)
+  {
+      i--;
+      values[i]=PartialCrossSection(k, i, particleDefinition);
+      value+=values[i];
+  }
+  
+  value*=G4UniformRand();
+  
+  i=n;
+  while (i>0)
+  {
+      i--;
+   
+      if (values[i]>value)
+	break;
+  
+      value-=values[i];
+  }
+  
+  delete[] values;
+  
+  return i;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNADingfelderChargeIncreaseModel::Sum(G4double k, const G4ParticleDefinition* particleDefinition)
+{
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=0;
+  if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=1;
+
+  G4double totalCrossSection = 0.;
+
+  for (G4int i=0; i<numberOfPartialCrossSections[particleTypeIndex]; i++)
+  {
+    totalCrossSection += PartialCrossSection(k,i,particleDefinition);
+  }
+  return totalCrossSection;
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAElastic.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAElastic.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAElastic.cc	(revision 1058)
@@ -0,0 +1,78 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAElastic.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+
+#include "G4DNAElastic.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+using namespace std;
+
+G4DNAElastic::G4DNAElastic(const G4String& processName,
+  G4ProcessType type):G4VEmProcess (processName, type),
+    isInitialised(false)
+{
+  SetProcessSubType(51);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+ 
+G4DNAElastic::~G4DNAElastic()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4bool G4DNAElastic::IsApplicable(const G4ParticleDefinition& p)
+{
+  return (&p == G4Electron::Electron());
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAElastic::InitialiseProcess(const G4ParticleDefinition*)
+{
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+    SetBuildTableFlag(false);
+    if(!Model()) SetModel(new G4DNAScreenedRutherfordElasticModel);
+    Model()->SetLowEnergyLimit(0*eV);
+    Model()->SetHighEnergyLimit(10*MeV);
+    AddEmModel(1, Model());
+  } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4DNAElastic::PrintInfo()
+{
+  G4cout
+    << " Total cross sections computed from " << Model()->GetName() << " model"
+    << G4endl;
+}         
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAEmfietzoglouExcitationModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAEmfietzoglouExcitationModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAEmfietzoglouExcitationModel.cc	(revision 1058)
@@ -0,0 +1,322 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAEmfietzoglouExcitationModel.cc,v 1.5 2009/02/16 12:46:58 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNAEmfietzoglouExcitationModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAEmfietzoglouExcitationModel::G4DNAEmfietzoglouExcitationModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  lowEnergyLimit = 8.23 * eV; 
+  highEnergyLimit = 10 * MeV;
+  SetLowEnergyLimit(lowEnergyLimit);
+  SetHighEnergyLimit(highEnergyLimit);
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  if (verboseLevel > 3)
+
+  G4cout << "Emfietzoglou Excitation model is constructed " << G4endl
+         << "Energy range: "
+         << lowEnergyLimit / eV << " eV - "
+         << highEnergyLimit / MeV << " MeV"
+         << G4endl;
+ 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAEmfietzoglouExcitationModel::~G4DNAEmfietzoglouExcitationModel()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAEmfietzoglouExcitationModel::Initialise(const G4ParticleDefinition* /*particle*/,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNAEmfietzoglouExcitationModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  if (LowEnergyLimit() < lowEnergyLimit)
+  {
+    G4cout << "G4DNAEmfietzoglouExcitationModel: low energy limit increased from " << 
+	LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
+    SetLowEnergyLimit(lowEnergyLimit);
+    }
+
+  if (HighEnergyLimit() > highEnergyLimit)
+  {
+    G4cout << "G4DNAEmfietzoglouExcitationModel: high energy limit decreased from " << 
+        HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
+    SetHighEnergyLimit(highEnergyLimit);
+  }
+
+  //
+  
+  nLevels = waterExcitation.NumberOfLevels();
+
+  //
+  
+  G4cout << "Emfietzoglou Excitation model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / eV << " eV - "
+         << HighEnergyLimit() / MeV << " MeV"
+         << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAEmfietzoglouExcitationModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double ekin,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNAEmfietzoglouExcitationModel" << G4endl;
+
+ // Calculate total cross section for model
+
+ G4double sigma=0;
+ 
+ if (flagMaterialIsWater)
+ {
+
+  if (particleDefinition == G4Electron::ElectronDefinition())
+  {
+    if (ekin >= lowEnergyLimit && ekin < highEnergyLimit)
+    {
+      sigma = Sum(ekin);
+    }
+  }
+  
+  if (verboseLevel > 3)
+  {
+    G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
+    G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
+    G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
+  } 
+
+ } // if (flagMaterialIsWater)
+         
+ return sigma*densityWater;		   
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAEmfietzoglouExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicElectron,
+					      G4double,
+					      G4double)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNAEmfietzoglouExcitationModel" << G4endl;
+
+  G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
+  
+  G4int level = RandomSelect(electronEnergy0);
+
+  G4double excitationEnergy = waterExcitation.ExcitationEnergy(level);
+  G4double newEnergy = electronEnergy0 - excitationEnergy;
+  
+  if (electronEnergy0 < highEnergyLimit)
+  {
+    if (newEnergy >= lowEnergyLimit)
+    {
+      fParticleChangeForGamma->ProposeMomentumDirection(aDynamicElectron->GetMomentumDirection());
+      fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
+      fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
+    }
+ 
+    else   
+    {
+      fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
+      fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
+    }
+  }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAEmfietzoglouExcitationModel::PartialCrossSection(G4double t, G4int level)
+{
+  //                 Aj                        T
+  // Sigma(T) = ------------- (Bj /  T) ln(Cj ---) [1 - Bj / T]^Pj
+  //             2 pi alpha0                   R
+  //
+  // Sigma is the macroscopic cross section = N sigma, where N = number of target particles per unit volume
+  // and sigma is the microscopic cross section
+  // T      is the incoming electron kinetic energy
+  // alpha0 is the Bohr Radius (Bohr_radius)
+  // Aj, Bj, Cj & Pj are parameters that can be found in Emfietzoglou's papers
+  //
+  // From Phys. Med. Biol. 48 (2003) 2355-2371, D.Emfietzoglou,
+  // Monte Carlo Simulation of the energy loss of low energy electrons in liquid Water
+  //
+  // Scaling for macroscopic cross section: number of water moleculs per unit volume
+  // const G4double sigma0 = (10. / 3.343e22) * cm2;
+
+  const G4double density = 3.34192e+19 * mm3;
+
+  const G4double aj[]={0.0205, 0.0209, 0.0130, 0.0026, 0.0025};
+  const G4double cj[]={4.9801, 3.3850, 2.8095, 1.9242, 3.4624};
+  const G4double pj[]={0.4757, 0.3483, 0.4443, 0.3429, 0.4379};
+  const G4double r = 13.6 * eV;
+  
+  G4double sigma = 0.;
+  
+  G4double exc = waterExcitation.ExcitationEnergy(level);
+  
+  if (t >= exc)
+  {
+      G4double excitationSigma = ( aj[level] / (2.*pi*Bohr_radius)) 
+	* (exc / t) 
+	* std::log(cj[level]*(t/r)) 
+	* std::pow((1.- (exc/t)), pj[level]);
+      sigma = excitationSigma / density;
+  }
+  return sigma;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNAEmfietzoglouExcitationModel::RandomSelect(G4double k)
+{
+  G4int i = nLevels;
+  G4double value = 0.;
+  std::deque<double> values;
+  
+  while (i > 0)
+  {
+    i--;
+    G4double partial = PartialCrossSection(k,i);
+    values.push_front(partial);
+    value += partial;
+  }
+
+  value *= G4UniformRand();
+    
+  i = nLevels;
+
+  while (i > 0)
+  {
+    i--;
+    if (values[i] > value) return i;
+    value -= values[i];
+  }
+    
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAEmfietzoglouExcitationModel::Sum(G4double k)
+{
+  G4double totalCrossSection = 0.;
+
+  for (G4int i=0; i<nLevels; i++)
+  {
+    totalCrossSection += PartialCrossSection(k,i);
+  }
+  return totalCrossSection;
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAExcitation.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAExcitation.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAExcitation.cc	(revision 1058)
@@ -0,0 +1,134 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAExcitation.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+
+#include "G4DNAExcitation.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+using namespace std;
+
+G4DNAExcitation::G4DNAExcitation(const G4String& processName,
+  G4ProcessType type):G4VEmProcess (processName, type),
+    isInitialised(false)
+{
+  SetProcessSubType(51);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+ 
+G4DNAExcitation::~G4DNAExcitation()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4bool G4DNAExcitation::IsApplicable(const G4ParticleDefinition& p)
+{
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  return 
+    (
+       &p == G4Electron::Electron() 
+    || &p == G4Proton::ProtonDefinition()
+    || &p == instance->GetIon("alpha++")
+    || &p == instance->GetIon("alpha+")
+    || &p == instance->GetIon("helium")
+    );
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAExcitation::InitialiseProcess(const G4ParticleDefinition* p)
+{
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+    SetBuildTableFlag(false);
+    
+    G4String name = p->GetParticleName();
+
+    if(name == "e-")
+    {
+      if(!Model()) SetModel(new G4DNAEmfietzoglouExcitationModel);
+      Model()->SetLowEnergyLimit(8.23*eV);
+      Model()->SetHighEnergyLimit(10*MeV);
+
+      AddEmModel(1, Model());   
+    }
+    
+    if(name == "proton")
+    {
+      if(!Model(1)) SetModel(new G4DNAMillerGreenExcitationModel,1);
+      Model(1)->SetLowEnergyLimit(10*eV);
+      Model(1)->SetHighEnergyLimit(500*keV);
+
+      if(!Model(2)) SetModel(new G4DNABornExcitationModel,2);
+      Model(2)->SetLowEnergyLimit(500*keV);
+      Model(2)->SetHighEnergyLimit(10*MeV);
+    
+      AddEmModel(1, Model(1));   
+      AddEmModel(2, Model(2));   
+    }
+
+    if( name == "alpha" || name == "alpha+" || name == "helium" )
+    {
+      if(!Model()) SetModel(new G4DNAMillerGreenExcitationModel);
+      Model()->SetLowEnergyLimit(1*keV);
+      Model()->SetHighEnergyLimit(10*MeV);
+
+      AddEmModel(1, Model());   
+    }
+
+  } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4DNAExcitation::PrintInfo()
+{
+  if (Model(2))
+  {
+    G4cout
+      << " Total cross sections computed from " 
+      << Model(1)->GetName() 
+      << " and "
+      << Model(2)->GetName() 
+      << " models"
+      << G4endl;
+  } 
+  else
+  {
+    G4cout
+      << " Total cross sections computed from " 
+      << Model()->GetName() 
+      << G4endl;
+  }
+}         
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAIonisation.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAIonisation.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAIonisation.cc	(revision 1058)
@@ -0,0 +1,143 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAIonisation.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+
+#include "G4DNAIonisation.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+using namespace std;
+
+G4DNAIonisation::G4DNAIonisation(const G4String& processName,
+  G4ProcessType type):G4VEmProcess (processName, type),
+    isInitialised(false)
+{
+  SetProcessSubType(51);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+ 
+G4DNAIonisation::~G4DNAIonisation()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4bool G4DNAIonisation::IsApplicable(const G4ParticleDefinition& p)
+{
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  return 
+  (
+      &p == G4Electron::Electron() 
+   || &p == G4Proton::Proton() 
+   || &p == instance->GetIon("hydrogen")
+   || &p == instance->GetIon("alpha++")
+   || &p == instance->GetIon("alpha+")
+   || &p == instance->GetIon("helium")
+  );
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAIonisation::InitialiseProcess(const G4ParticleDefinition* p)
+{
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+    SetBuildTableFlag(false);
+
+    G4String name = p->GetParticleName();
+
+    if(name == "e-")
+    {
+      if(!Model()) SetModel(new G4DNABornIonisationModel);
+      Model()->SetLowEnergyLimit(12.61*eV);
+      Model()->SetHighEnergyLimit(30*keV);
+
+      AddEmModel(1, Model());   
+    }
+
+    if(name == "proton")
+    {
+      if(!Model(1)) SetModel(new G4DNARuddIonisationModel,1);
+      Model(1)->SetLowEnergyLimit(0*eV);
+      Model(1)->SetHighEnergyLimit(500*keV);
+
+      if(!Model(2)) SetModel(new G4DNABornIonisationModel,2);
+      Model(2)->SetLowEnergyLimit(500*keV);
+      Model(2)->SetHighEnergyLimit(10*MeV);
+    
+      AddEmModel(1, Model(1));   
+      AddEmModel(2, Model(2));   
+    }
+
+    if(name == "hydrogen")
+    {
+      if(!Model()) SetModel(new G4DNARuddIonisationModel);
+      Model()->SetLowEnergyLimit(0*eV);
+      Model()->SetHighEnergyLimit(100*MeV);
+
+      AddEmModel(1, Model());   
+    }
+
+    if(name == "alpha" || name == "alpha+" || name == "helium" )
+    {
+      if(!Model()) SetModel(new G4DNARuddIonisationModel);
+      Model()->SetLowEnergyLimit(0*keV);
+      Model()->SetHighEnergyLimit(10*MeV);
+
+      AddEmModel(1, Model());   
+    }
+
+  } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4DNAIonisation::PrintInfo()
+{
+  if (Model(2))
+  {
+    G4cout
+      << " Total cross sections computed from " 
+      << Model(1)->GetName() 
+      << " and "
+      << Model(2)->GetName() 
+      << " models"
+      << G4endl;
+  } 
+  else
+  {
+    G4cout
+      << " Total cross sections computed from " 
+      << Model()->GetName() 
+      << G4endl;
+  }
+}         
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAMillerGreenExcitationModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAMillerGreenExcitationModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAMillerGreenExcitationModel.cc	(revision 1058)
@@ -0,0 +1,595 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAMillerGreenExcitationModel.cc,v 1.3 2009/02/16 11:00:11 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNAMillerGreenExcitationModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAMillerGreenExcitationModel::G4DNAMillerGreenExcitationModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Miller & Green excitation model is constructed " << G4endl;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAMillerGreenExcitationModel::~G4DNAMillerGreenExcitationModel()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* particle,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNAMillerGreenExcitationModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
+  G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
+  G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
+  G4ParticleDefinition* heliumDef = instance->GetIon("helium");
+
+  G4String proton;
+  G4String alphaPlusPlus;
+  G4String alphaPlus;
+  G4String helium;
+
+  if (protonDef != 0)
+  {
+    proton = protonDef->GetParticleName();
+    lowEnergyLimit[proton] = 10. * eV;
+    highEnergyLimit[proton] = 500. * keV;
+    
+    kineticEnergyCorrection[0] = 1.;
+    slaterEffectiveCharge[0][0] = 0.;
+    slaterEffectiveCharge[1][0] = 0.;
+    slaterEffectiveCharge[2][0] = 0.;
+    sCoefficient[0][0] = 0.;
+    sCoefficient[1][0] = 0.;
+    sCoefficient[2][0] = 0.;
+  }
+  else
+  {
+    G4Exception("G4DNAMillerGreenExcitationModel::Initialise: proton is not defined");
+  }
+
+  if (alphaPlusPlusDef != 0)
+  {
+    alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
+    lowEnergyLimit[alphaPlusPlus] = 1. * keV;
+    highEnergyLimit[alphaPlusPlus] = 10. * MeV;
+
+    kineticEnergyCorrection[1] = 0.9382723/3.727417;
+    slaterEffectiveCharge[0][1]=0.;
+    slaterEffectiveCharge[1][1]=0.;
+    slaterEffectiveCharge[2][1]=0.;
+    sCoefficient[0][1]=0.;
+    sCoefficient[1][1]=0.;
+    sCoefficient[2][1]=0.;
+  }
+  else
+  {
+      G4Exception("G4DNAMillerGreenExcitationModel::Initialise: alphaPlusPlus is not defined");
+  }
+
+  if (alphaPlusDef != 0)
+  {
+    alphaPlus = alphaPlusDef->GetParticleName();
+    lowEnergyLimit[alphaPlus] = 1. * keV;
+    highEnergyLimit[alphaPlus] = 10. * MeV;
+
+    kineticEnergyCorrection[2] = 0.9382723/3.727417;
+    slaterEffectiveCharge[0][2]=2.0;
+    slaterEffectiveCharge[1][2]=1.15;
+    slaterEffectiveCharge[2][2]=1.15;
+    sCoefficient[0][2]=0.7;
+    sCoefficient[1][2]=0.15;
+    sCoefficient[2][2]=0.15;
+  }
+  else
+  {
+    G4Exception("G4DNAMillerGreenExcitationModel::Initialise: alphaPlus is not defined");
+  }
+
+  if (heliumDef != 0)
+  {
+    helium = heliumDef->GetParticleName();
+    lowEnergyLimit[helium] = 1. * keV;
+    highEnergyLimit[helium] = 10. * MeV;
+    
+    kineticEnergyCorrection[3] = 0.9382723/3.727417;
+    slaterEffectiveCharge[0][3]=1.7;
+    slaterEffectiveCharge[1][3]=1.15;
+    slaterEffectiveCharge[2][3]=1.15;
+    sCoefficient[0][3]=0.5;
+    sCoefficient[1][3]=0.25;
+    sCoefficient[2][3]=0.25;
+  }
+  else
+  {
+    G4Exception("G4DNAMillerGreenExcitationModel::Initialise: helium is not defined");
+  }
+
+  if (particle==protonDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[proton]);
+    SetHighEnergyLimit(highEnergyLimit[proton]);
+  }
+
+  if (particle==alphaPlusPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
+  }
+
+  if (particle==alphaPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
+  }
+
+  if (particle==heliumDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[helium]);
+    SetHighEnergyLimit(highEnergyLimit[helium]);
+  }
+
+  //
+  
+  nLevels = waterExcitation.NumberOfLevels();
+
+  //
+  
+  G4cout << "Miller & Green excitation model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / eV << " eV - "
+         << HighEnergyLimit() / keV << " keV for "
+         << particle->GetParticleName()
+         << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+  
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material* material,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double k,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNAMillerGreenExcitationModel" << G4endl;
+
+ // Calculate total cross section for model
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (
+      particleDefinition != G4Proton::ProtonDefinition()
+      &&
+      particleDefinition != instance->GetIon("alpha++")
+      &&
+      particleDefinition != instance->GetIon("alpha+")
+      &&
+      particleDefinition != instance->GetIon("helium")
+     )
+   	    
+    return 0;
+
+  G4double lowLim = 0;
+  G4double highLim = 0;
+  G4double crossSection = 0.;
+
+  if (flagMaterialIsWater)
+  {
+    const G4String& particleName = particleDefinition->GetParticleName();
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+    pos1 = lowEnergyLimit.find(particleName);
+
+    if (pos1 != lowEnergyLimit.end())
+    {
+      lowLim = pos1->second;
+    }
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+    pos2 = highEnergyLimit.find(particleName);
+
+    if (pos2 != highEnergyLimit.end())
+    {
+      highLim = pos2->second;
+    }
+
+    if (k >= lowLim && k < highLim)
+    {
+      crossSection = Sum(k,particleDefinition);
+
+      G4DNAGenericIonsManager *instance;
+      instance = G4DNAGenericIonsManager::Instance();
+
+      // add ONE or TWO electron-water excitation for alpha+ and helium
+  
+      if ( particleDefinition == instance->GetIon("alpha+") 
+           ||
+           particleDefinition == instance->GetIon("helium")
+         ) 
+      {
+	  G4DNAEmfietzoglouExcitationModel * excitationXS = new G4DNAEmfietzoglouExcitationModel();
+
+	  G4double sigmaExcitation=0;
+	  G4double tmp =0.;
+	  
+	  if (k*0.511/3728 > 7.4*eV && k*0.511/3728 < 10*keV) sigmaExcitation = 
+	    excitationXS->CrossSectionPerVolume(material,particleDefinition,k*0.511/3728,tmp,tmp)/densityWater;
+       
+	  if ( particleDefinition == instance->GetIon("alpha+") ) 
+	    crossSection = crossSection +  sigmaExcitation ;
+	  
+	  if ( particleDefinition == instance->GetIon("helium") ) 
+	    crossSection = crossSection + 2*sigmaExcitation ;
+	  
+	  delete excitationXS;
+      }      
+
+    }
+
+    if (verboseLevel > 3)
+    {
+      G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
+      G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
+      G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*densityWater/(1./cm) << G4endl;
+    } 
+
+  } // if (flagMaterialIsWater)
+
+ return crossSection*densityWater;		   
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAMillerGreenExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicParticle,
+					      G4double,
+					      G4double)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNAMillerGreenExcitationModel" << G4endl;
+
+  G4double particleEnergy0 = aDynamicParticle->GetKineticEnergy();
+  
+  G4int level = RandomSelect(particleEnergy0,aDynamicParticle->GetDefinition());
+
+  G4double excitationEnergy = waterExcitation.ExcitationEnergy(level);
+  G4double newEnergy = particleEnergy0 - excitationEnergy;
+  
+  if (newEnergy>0)
+  {
+      fParticleChangeForGamma->ProposeMomentumDirection(aDynamicParticle->GetMomentumDirection());
+      fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
+      fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
+  }
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int excitationLevel, 
+								  const G4ParticleDefinition* particleDefinition)
+{
+  //                               ( ( z * aj ) ^ omegaj ) * ( t - ej ) ^ nu
+  // sigma(t) = zEff^2 * sigma0 * --------------------------------------------
+  //                               jj ^ ( omegaj + nu ) + t ^ ( omegaj + nu )
+  //
+  // where t is the kinetic energy corrected by Helium mass over proton mass for Helium ions
+  //
+  // zEff is:
+  //  1 for protons
+  //  2 for alpha++
+  //  and  2 - c1 S_1s - c2 S_2s - c3 S_2p for alpha+ and He
+  //
+  // Dingfelder et al., RPC 59, 255-275, 2000 from Miller and Green (1973)
+  // Formula (34) and Table 2
+  
+  const G4double sigma0(1.E+8 * barn);
+  const G4double nu(1.);
+  const G4double aj[]={876.*eV, 2084.* eV, 1373.*eV, 692.*eV, 900.*eV};
+  const G4double jj[]={19820.*eV, 23490.*eV, 27770.*eV, 30830.*eV, 33080.*eV};
+  const G4double omegaj[]={0.85, 0.88, 0.88, 0.78, 0.78};
+  
+  G4int particleTypeIndex = 0;
+  G4DNAGenericIonsManager* instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
+  if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
+  if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
+  if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=3;
+ 
+  G4double tCorrected;
+  tCorrected = k * kineticEnergyCorrection[particleTypeIndex];
+
+  // SI - added protection 
+  if (tCorrected < waterExcitation.ExcitationEnergy(excitationLevel)) return 0;
+  //
+  
+  G4int z = 10;
+
+  G4double numerator;
+  numerator = std::pow(z * aj[excitationLevel], omegaj[excitationLevel]) * 
+    std::pow(tCorrected - waterExcitation.ExcitationEnergy(excitationLevel), nu);
+
+  G4double power;
+  power = omegaj[excitationLevel] + nu;
+
+  G4double denominator;
+  denominator = std::pow(jj[excitationLevel], power) + std::pow(tCorrected, power);
+
+  G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
+
+  zEff -= ( sCoefficient[0][particleTypeIndex] * S_1s(k, waterExcitation.ExcitationEnergy(excitationLevel), slaterEffectiveCharge[0][particleTypeIndex], 1.) +
+	    sCoefficient[1][particleTypeIndex] * S_2s(k, waterExcitation.ExcitationEnergy(excitationLevel), slaterEffectiveCharge[1][particleTypeIndex], 2.) +
+	    sCoefficient[2][particleTypeIndex] * S_2p(k, waterExcitation.ExcitationEnergy(excitationLevel), slaterEffectiveCharge[2][particleTypeIndex], 2.) );
+
+  G4double cross = sigma0 * zEff * zEff * numerator / denominator;
+
+  return cross;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleDefinition* particle)
+{
+  G4int i = nLevels;
+  G4double value = 0.;
+  std::deque<double> values;
+  
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if ( particle == instance->GetIon("alpha++") ||
+       particle == G4Proton::ProtonDefinition()  )
+  {  
+     while (i > 0)
+     {
+	i--;
+	G4double partial = PartialCrossSection(k,i,particle);
+	values.push_front(partial);
+	value += partial;
+     }
+
+     value *= G4UniformRand();
+    
+     i = nLevels;
+
+     while (i > 0)
+     {
+	i--;
+	if (values[i] > value) return i;
+	value -= values[i];
+     }
+  } 
+
+  // add ONE or TWO electron-water excitation for alpha+ and helium
+   
+  if ( particle == instance->GetIon("alpha+") 
+       ||
+       particle == instance->GetIon("helium")
+     ) 
+  {
+    while (i>0)
+    {
+	  i--;
+         
+          G4DNAEmfietzoglouExcitationModel * excitationXS = new G4DNAEmfietzoglouExcitationModel();
+         
+	  G4double sigmaExcitation=0;
+
+	  if (k*0.511/3728 > 7.4*eV && k*0.511/3728 < 10*keV) sigmaExcitation = excitationXS->PartialCrossSection(k*0.511/3728,i);
+ 
+	  G4double partial = PartialCrossSection(k,i,particle);
+	  if (particle == instance->GetIon("alpha+")) partial = PartialCrossSection(k,i,particle) + sigmaExcitation;
+	  if (particle == instance->GetIon("helium")) partial = PartialCrossSection(k,i,particle) + 2*sigmaExcitation;
+	  values.push_front(partial);
+	  value += partial;
+	  delete excitationXS;
+    }
+  
+    value*=G4UniformRand();
+  
+    i=5;
+    while (i>0)
+    {
+	  i--;
+   
+	  if (values[i]>value) return i;
+  
+	  value-=values[i];
+    }
+  }    	
+
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAMillerGreenExcitationModel::Sum(G4double k, const G4ParticleDefinition* particle)
+{
+  G4double totalCrossSection = 0.;
+
+  for (G4int i=0; i<nLevels; i++)
+  {
+    totalCrossSection += PartialCrossSection(k,i,particle);
+  }
+  return totalCrossSection;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAMillerGreenExcitationModel::S_1s(G4double t,
+							  G4double energyTransferred,
+							  G4double slaterEffectiveCharge,
+							  G4double shellNumber)
+{
+  // 1 - e^(-2r) * ( 1 + 2 r + 2 r^2)
+  // Dingfelder, in Chattanooga 2005 proceedings, formula (7)
+ 
+  G4double r = R(t, energyTransferred, slaterEffectiveCharge, shellNumber);
+  G4double value = 1. - std::exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. );
+  
+  return value;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAMillerGreenExcitationModel::S_2s(G4double t,
+							  G4double energyTransferred,
+							  G4double slaterEffectiveCharge,
+							  G4double shellNumber)
+{
+  // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4)
+  // Dingfelder, in Chattanooga 2005 proceedings, formula (8)
+
+  G4double r = R(t, energyTransferred, slaterEffectiveCharge, shellNumber);
+  G4double value =  1. - std::exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.);
+
+  return value;
+ 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAMillerGreenExcitationModel::S_2p(G4double t,
+							  G4double energyTransferred,
+							  G4double slaterEffectiveCharge,
+							  G4double shellNumber)
+{
+  // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4)
+  // Dingfelder, in Chattanooga 2005 proceedings, formula (9)
+
+  G4double r = R(t, energyTransferred, slaterEffectiveCharge, shellNumber);
+  G4double value =  1. - std::exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r  + 1.);
+
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAMillerGreenExcitationModel::R(G4double t,
+						       G4double energyTransferred,
+						       G4double slaterEffectiveCharge,
+						       G4double shellNumber) 
+{
+  // tElectron = m_electron / m_alpha * t
+  // Dingfelder, in Chattanooga 2005 proceedings, p 4
+
+  G4double tElectron = 0.511/3728. * t;
+  G4double value = 2. * tElectron * slaterEffectiveCharge / (energyTransferred * shellNumber);
+  
+  return value;
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNARuddIonisationModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNARuddIonisationModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNARuddIonisationModel.cc	(revision 1058)
@@ -0,0 +1,1059 @@
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNARuddIonisationModel.cc,v 1.4 2009/02/16 11:00:11 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNARuddIonisationModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNARuddIonisationModel::G4DNARuddIonisationModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+  lowEnergyLimitForZ1 = 0 * eV; 
+  lowEnergyLimitForZ2 = 0 * eV; 
+  lowEnergyLimitOfModelForZ1 = 100 * eV; 
+  lowEnergyLimitOfModelForZ2 = 1 * keV; 
+  killBelowEnergyForZ1 = lowEnergyLimitOfModelForZ1; 
+  killBelowEnergyForZ2 = lowEnergyLimitOfModelForZ2; 
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Rudd ionisation model is constructed " << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNARuddIonisationModel::~G4DNARuddIonisationModel()
+{  
+  // Cross section
+  
+  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+  for (pos = tableData.begin(); pos != tableData.end(); ++pos)
+  {
+    G4DNACrossSectionDataSet* table = pos->second;
+    delete table;
+  }
+  
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNARuddIonisationModel::Initialise()" << G4endl;
+
+  // Energy limits
+
+  G4String fileProton("dna/sigma_ionisation_p_rudd");
+  G4String fileHydrogen("dna/sigma_ionisation_h_rudd");
+  G4String fileAlphaPlusPlus("dna/sigma_ionisation_alphaplusplus_rudd");
+  G4String fileAlphaPlus("dna/sigma_ionisation_alphaplus_rudd");
+  G4String fileHelium("dna/sigma_ionisation_he_rudd");
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
+  G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
+  G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
+  G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
+  G4ParticleDefinition* heliumDef = instance->GetIon("helium");
+
+  G4String proton;
+  G4String hydrogen;
+  G4String alphaPlusPlus;
+  G4String alphaPlus;
+  G4String helium;
+
+  G4double scaleFactor = 1 * m*m;
+
+  if (protonDef != 0)
+  {
+    proton = protonDef->GetParticleName();
+    tableFile[proton] = fileProton;
+
+    lowEnergyLimit[proton] = lowEnergyLimitForZ1;
+    highEnergyLimit[proton] = 500. * keV;
+
+    // Cross section
+
+    G4DNACrossSectionDataSet* tableProton = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, 
+									   eV,
+									   scaleFactor );
+    tableProton->LoadData(fileProton);
+    tableData[proton] = tableProton;
+  }
+  else
+  {
+    G4Exception("G4DNARuddIonisationModel::Initialise: proton is not defined");
+  }
+
+  if (hydrogenDef != 0)
+  {
+    hydrogen = hydrogenDef->GetParticleName();
+    tableFile[hydrogen] = fileHydrogen;
+
+    lowEnergyLimit[hydrogen] = lowEnergyLimitForZ1;
+    highEnergyLimit[hydrogen] = 100. * MeV;
+
+    // Cross section
+
+    G4DNACrossSectionDataSet* tableHydrogen = new G4DNACrossSectionDataSet(new G4LogLogInterpolation,
+									     eV,
+									     scaleFactor );
+    tableHydrogen->LoadData(fileHydrogen);
+      
+    tableData[hydrogen] = tableHydrogen;
+  }
+  else
+  {
+    G4Exception("G4DNARuddIonisationModel::Initialise: hydrogen is not defined");
+  }
+
+  if (alphaPlusPlusDef != 0)
+  {
+    alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
+    tableFile[alphaPlusPlus] = fileAlphaPlusPlus;
+
+    lowEnergyLimit[alphaPlusPlus] = lowEnergyLimitForZ2;
+    highEnergyLimit[alphaPlusPlus] = 10. * MeV;
+
+    // Cross section
+
+    G4DNACrossSectionDataSet* tableAlphaPlusPlus = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, 
+										  eV,
+										  scaleFactor );
+    tableAlphaPlusPlus->LoadData(fileAlphaPlusPlus);
+      
+    tableData[alphaPlusPlus] = tableAlphaPlusPlus;
+  }
+  else
+  {
+    G4Exception("G4DNARuddIonisationModel::Initialise: alphaPlusPlus is not defined");
+  }
+
+  if (alphaPlusDef != 0)
+  {
+    alphaPlus = alphaPlusDef->GetParticleName();
+    tableFile[alphaPlus] = fileAlphaPlus;
+
+    lowEnergyLimit[alphaPlus] = lowEnergyLimitForZ2;
+    highEnergyLimit[alphaPlus] = 10. * MeV;
+
+    // Cross section
+
+    G4DNACrossSectionDataSet* tableAlphaPlus = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, 
+									      eV,
+									      scaleFactor );
+    tableAlphaPlus->LoadData(fileAlphaPlus);
+    tableData[alphaPlus] = tableAlphaPlus;
+  }
+  else
+  {
+    G4Exception("G4DNARuddIonisationModel::Initialise: alphaPlus is not defined");
+  }
+
+  if (heliumDef != 0)
+  {
+    helium = heliumDef->GetParticleName();
+    tableFile[helium] = fileHelium;
+
+    lowEnergyLimit[helium] = lowEnergyLimitForZ2;
+    highEnergyLimit[helium] = 10. * MeV;
+
+    // Cross section
+
+    G4DNACrossSectionDataSet* tableHelium = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, 
+									   eV,
+									   scaleFactor );
+    tableHelium->LoadData(fileHelium);
+    tableData[helium] = tableHelium;
+    }
+  else
+  {
+    G4Exception("G4DNARuddIonisationModel::Initialise: helium is not defined");
+  }
+
+  if (particle==protonDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[proton]);
+    SetHighEnergyLimit(highEnergyLimit[proton]);
+  }
+
+  if (particle==hydrogenDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[hydrogen]);
+    SetHighEnergyLimit(highEnergyLimit[hydrogen]);
+  }
+
+  if (particle==heliumDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[helium]);
+    SetHighEnergyLimit(highEnergyLimit[helium]);
+  }
+
+  if (particle==alphaPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
+  }
+
+  if (particle==alphaPlusPlusDef) 
+  {
+    SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
+    SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
+  }
+
+  G4cout << "Rudd ionisation model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / eV << " eV - "
+         << HighEnergyLimit() / keV << " keV for "
+         << particle->GetParticleName()
+         << G4endl;
+
+  //
+  
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition* particleDefinition,
+					   G4double k,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNARuddIonisationModel" << G4endl;
+
+ // Calculate total cross section for model
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (
+      particleDefinition != G4Proton::ProtonDefinition()
+      &&
+      particleDefinition != instance->GetIon("hydrogen")
+      &&
+      particleDefinition != instance->GetIon("alpha++")
+      &&
+      particleDefinition != instance->GetIon("alpha+")
+      &&
+      particleDefinition != instance->GetIon("helium")
+     )
+   	    
+    return 0;
+
+  G4double lowLim = 0;
+  
+  if (     particleDefinition == G4Proton::ProtonDefinition()
+       ||  particleDefinition == instance->GetIon("hydrogen")
+     )
+       
+       lowLim = lowEnergyLimitOfModelForZ1;
+       
+  if (     particleDefinition == instance->GetIon("alpha++")
+       ||  particleDefinition == instance->GetIon("alpha+")
+       ||  particleDefinition == instance->GetIon("helium")
+     )
+       
+       lowLim = lowEnergyLimitOfModelForZ2;
+
+  G4double highLim = 0;
+  G4double sigma=0;
+
+  if (flagMaterialIsWater)
+  {
+    const G4String& particleName = particleDefinition->GetParticleName();
+    
+    // SI - the following is useless since lowLim is already defined 
+    /*
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+    pos1 = lowEnergyLimit.find(particleName);
+
+    if (pos1 != lowEnergyLimit.end())
+    {
+      lowLim = pos1->second;
+    }
+    */
+
+    std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+    pos2 = highEnergyLimit.find(particleName);
+
+    if (pos2 != highEnergyLimit.end())
+    {
+      highLim = pos2->second;
+    }
+
+    if (k < highLim)
+    {
+      
+      //SI : XS must not be zero otherwise sampling of secondaries method ignored
+
+      if (k < lowLim) k = lowLim;
+
+      //      
+      
+      std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+      pos = tableData.find(particleName);
+	
+      if (pos != tableData.end())
+      {
+         G4DNACrossSectionDataSet* table = pos->second;
+         if (table != 0)
+         {
+	      sigma = table->FindValue(k);
+
+	      // BEGIN ELECTRON CORRECTION
+	      // add ONE or TWO electron-water excitation for alpha+ and helium
+   
+	      if ( particleDefinition == instance->GetIon("alpha+") 
+		   ||
+		   particleDefinition == instance->GetIon("helium")
+		   ) 
+	      {
+      
+		  G4DNACrossSectionDataSet* electronDataset = new G4DNACrossSectionDataSet 
+		    (new G4LogLogInterpolation, eV, (1./3.343e22)*m*m);
+       
+		  electronDataset->LoadData("dna/sigma_ionisation_e_born");
+
+		  G4double kElectron = k * 0.511/3728;
+
+		  if ( particleDefinition == instance->GetIon("alpha+") ) 
+		  {
+		      G4double tmp1 = table->FindValue(k) + electronDataset->FindValue(kElectron);
+		      delete electronDataset;
+		      if (verboseLevel > 3)
+                      {
+                        G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
+                        G4cout << " - Cross section per water molecule (cm^2)=" << tmp1/cm/cm << G4endl;
+                        G4cout << " - Cross section per water molecule (cm^-1)=" << tmp1*densityWater/(1./cm) << G4endl;
+                      } 
+		      return tmp1*densityWater;
+		  }
+
+		  if ( particleDefinition == instance->GetIon("helium") ) 
+		  {
+		      G4double tmp2 = table->FindValue(k) +  2. * electronDataset->FindValue(kElectron);
+		      delete electronDataset;
+		      if (verboseLevel > 3)
+                      {
+                        G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
+                        G4cout << " - Cross section per water molecule (cm^2)=" << tmp2/cm/cm << G4endl;
+                        G4cout << " - Cross section per water molecule (cm^-1)=" << tmp2*densityWater/(1./cm) << G4endl;
+                      } 
+		      return tmp2*densityWater;
+		  }
+              }      
+
+	      // END ELECTRON CORRECTION
+         }
+      }
+      else
+      {
+	G4Exception("G4DNARuddIonisationModel::CrossSectionPerVolume: attempting to calculate cross section for wrong particle");
+      }
+  
+    } // if (k >= lowLim && k < highLim)
+    
+    if (verboseLevel > 3)
+    {
+      G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
+      G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
+      G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
+    } 
+ 
+  } // if (waterMaterial)
+ 
+ return sigma*densityWater;		   
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNARuddIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* particle,
+					      G4double,
+					      G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNARuddIonisationModel" << G4endl;
+
+  G4double lowLim = 0;
+  G4double highLim = 0;
+
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (     particle->GetDefinition() == G4Proton::ProtonDefinition()
+       ||  particle->GetDefinition() == instance->GetIon("hydrogen")
+     )
+       
+       lowLim = killBelowEnergyForZ1;
+       
+  if (     particle->GetDefinition() == instance->GetIon("alpha++")
+       ||  particle->GetDefinition() == instance->GetIon("alpha+")
+       ||  particle->GetDefinition() == instance->GetIon("helium")
+     )
+       
+       lowLim = killBelowEnergyForZ2;
+
+  G4double k = particle->GetKineticEnergy();
+
+  const G4String& particleName = particle->GetDefinition()->GetParticleName();
+
+  // SI - the following is useless since lowLim is already defined 
+  /* 
+  std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+  pos1 = lowEnergyLimit.find(particleName);
+
+  if (pos1 != lowEnergyLimit.end())
+  {
+    lowLim = pos1->second;
+  }
+  */
+
+  std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+  pos2 = highEnergyLimit.find(particleName);
+
+  if (pos2 != highEnergyLimit.end())
+  {
+    highLim = pos2->second;
+  }
+
+  if (k >= lowLim && k < highLim)
+  {
+      G4ParticleDefinition* definition = particle->GetDefinition();
+      G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
+      G4double particleMass = definition->GetPDGMass();
+      G4double totalEnergy = k + particleMass;
+      G4double pSquare = k*(totalEnergy+particleMass);
+      G4double totalMomentum = std::sqrt(pSquare);
+
+      G4int ionizationShell = RandomSelect(k,particleName);
+  
+      G4double secondaryKinetic = RandomizeEjectedElectronEnergy(definition,k,ionizationShell);
+  
+      G4double bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
+
+      G4double cosTheta = 0.;
+      G4double phi = 0.; 
+      RandomizeEjectedElectronDirection(definition, k,secondaryKinetic, cosTheta, phi);
+
+      G4double sinTheta = std::sqrt(1.-cosTheta*cosTheta);
+      G4double dirX = sinTheta*std::cos(phi);
+      G4double dirY = sinTheta*std::sin(phi);
+      G4double dirZ = cosTheta;
+      G4ThreeVector deltaDirection(dirX,dirY,dirZ);
+      deltaDirection.rotateUz(primaryDirection);
+
+      G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
+
+      G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
+      G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
+      G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
+      G4double finalMomentum = std::sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
+      finalPx /= finalMomentum;
+      finalPy /= finalMomentum;
+      finalPz /= finalMomentum;
+
+      G4ThreeVector direction;
+      direction.set(finalPx,finalPy,finalPz);
+
+      fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
+      fParticleChangeForGamma->SetProposedKineticEnergy(k-bindingEnergy-secondaryKinetic);
+      fParticleChangeForGamma->ProposeLocalEnergyDeposit(bindingEnergy);
+
+      G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
+      fvect->push_back(dp);
+
+  }
+
+  // SI - not useful since low energy of model is 0 eV
+  
+  if (k < lowLim) 
+  {  
+    fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
+    fParticleChangeForGamma->ProposeLocalEnergyDeposit(k);
+  }
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefinition* particleDefinition, 
+								    G4double k, 
+								    G4int shell)
+{
+  G4double maximumKineticEnergyTransfer = 0.;
+ 
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == G4Proton::ProtonDefinition() 
+      || particleDefinition == instance->GetIon("hydrogen"))
+  { 
+      maximumKineticEnergyTransfer= 4.* (electron_mass_c2 / proton_mass_c2) * k;
+  }
+
+  if (particleDefinition == instance->GetIon("helium") 
+      || particleDefinition == instance->GetIon("alpha+")
+      || particleDefinition == instance->GetIon("alpha++"))
+  { 
+      maximumKineticEnergyTransfer= 4.* (0.511 / 3728) * k;
+  }
+
+  G4double crossSectionMaximum = 0.;
+  
+  for(G4double value=waterStructure.IonisationEnergy(shell); value<=4.*waterStructure.IonisationEnergy(shell) ; value+=0.1*eV)
+  {
+      G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k, value, shell);
+      if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
+  }
+  
+  G4double secElecKinetic = 0.;
+  
+  do
+  {
+    secElecKinetic = G4UniformRand() * maximumKineticEnergyTransfer;
+  } while(G4UniformRand()*crossSectionMaximum > DifferentialCrossSection(particleDefinition, 
+									 k,
+									 secElecKinetic+waterStructure.IonisationEnergy(shell),
+									 shell));
+
+  return(secElecKinetic);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+
+void G4DNARuddIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition, 
+								   G4double k, 
+								   G4double secKinetic, 
+								   G4double & cosTheta, 
+								   G4double & phi )
+{
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  G4double maxSecKinetic = 0.;
+ 
+  if (particleDefinition == G4Proton::ProtonDefinition() 
+      || particleDefinition == instance->GetIon("hydrogen")) 
+  { 
+      maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
+  }
+  
+  if (particleDefinition == instance->GetIon("helium") 
+      || particleDefinition == instance->GetIon("alpha+")
+      || particleDefinition == instance->GetIon("alpha++"))
+  { 
+      maxSecKinetic = 4.* (0.511 / 3728) * k;
+  }
+  
+  phi = twopi * G4UniformRand();
+  cosTheta = std::sqrt(secKinetic / maxSecKinetic);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+
+G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition* particleDefinition, 
+							      G4double k, 
+							      G4double energyTransfer, 
+							      G4int ionizationLevelIndex)
+{
+  // Shells ids are 0 1 2 3 4 (4 is k shell)
+  // !!Attention, "energyTransfer" here is the energy transfered to the electron which means
+  //             that the secondary kinetic energy is w = energyTransfer - bindingEnergy
+  //
+  //   ds            S                F1(nu) + w * F2(nu)
+  //  ---- = G(k) * ----     -------------------------------------------
+  //   dw            Bj       (1+w)^3 * [1 + exp{alpha * (w - wc) / nu}]
+  //
+  // w is the secondary electron kinetic Energy in eV
+  //
+  // All the other parameters can be found in Rudd's Papers
+  //
+  // M.Eugene Rudd, 1988, User-Friendly model for the energy distribution of
+  // electrons from protons or electron collisions. Nucl. Tracks Rad. Meas.Vol 16 N0 2/3 pp 219-218
+  //
+
+  const G4int j=ionizationLevelIndex;
+
+  G4double A1 ; 
+  G4double B1 ; 
+  G4double C1 ; 
+  G4double D1 ; 
+  G4double E1 ;
+  G4double A2 ; 
+  G4double B2 ; 
+  G4double C2 ; 
+  G4double D2 ; 
+  G4double alphaConst ;
+
+  if (j == 4) 
+  {
+      //Data For Liquid Water K SHELL from Dingfelder (Protons in Water)
+      A1 = 1.25; 
+      B1 = 0.5; 
+      C1 = 1.00; 
+      D1 = 1.00; 
+      E1 = 3.00; 
+      A2 = 1.10; 
+      B2 = 1.30;
+      C2 = 1.00; 
+      D2 = 0.00; 
+      alphaConst = 0.66;
+  }
+  else 
+  {
+      //Data For Liquid Water from Dingfelder (Protons in Water)
+      A1 = 1.02; 
+      B1 = 82.0; 
+      C1 = 0.45; 
+      D1 = -0.80; 
+      E1 = 0.38; 
+      A2 = 1.07; 
+      B2 = 14.6;
+      C2 = 0.60; 
+      D2 = 0.04; 
+      alphaConst = 0.64;
+  }
+  
+  const G4double n = 2.;
+  const G4double Gj[5] = {0.99, 1.11, 1.11, 0.52, 1.};
+
+  G4DNAGenericIonsManager* instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  G4double wBig = (energyTransfer - waterStructure.IonisationEnergy(ionizationLevelIndex));
+  G4double w = wBig / waterStructure.IonisationEnergy(ionizationLevelIndex);
+  G4double Ry = 13.6*eV;
+
+  G4double tau = 0.;
+
+  if (particleDefinition == G4Proton::ProtonDefinition() 
+      || particleDefinition == instance->GetIon("hydrogen")) 
+  {
+      tau = (electron_mass_c2/proton_mass_c2) * k ;
+  }
+   
+  if ( particleDefinition == instance->GetIon("helium") 
+       || particleDefinition == instance->GetIon("alpha+")
+       || particleDefinition == instance->GetIon("alpha++")) 
+  {
+      tau = (0.511/3728.) * k ;
+  }
+ 
+  G4double S = 4.*pi * Bohr_radius*Bohr_radius * n * std::pow((Ry/waterStructure.IonisationEnergy(ionizationLevelIndex)),2);
+  G4double v2 = tau / waterStructure.IonisationEnergy(ionizationLevelIndex);
+  G4double v = std::sqrt(v2);
+  G4double wc = 4.*v2 - 2.*v - (Ry/(4.*waterStructure.IonisationEnergy(ionizationLevelIndex)));
+
+  G4double L1 = (C1* std::pow(v,(D1))) / (1.+ E1*std::pow(v, (D1+4.)));
+  G4double L2 = C2*std::pow(v,(D2));
+  G4double H1 = (A1*std::log(1.+v2)) / (v2+(B1/v2));
+  G4double H2 = (A2/v2) + (B2/(v2*v2));
+
+  G4double F1 = L1+H1;
+  G4double F2 = (L2*H2)/(L2+H2);
+
+  G4double sigma = CorrectionFactor(particleDefinition, k/eV) 
+    * Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex)) 
+    * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
+
+  if (    particleDefinition == G4Proton::ProtonDefinition() 
+	  || particleDefinition == instance->GetIon("hydrogen")
+	  ) 
+  {
+      return(sigma);
+  }
+
+  if (particleDefinition == instance->GetIon("alpha++") ) 
+  {
+      slaterEffectiveCharge[0]=0.;
+      slaterEffectiveCharge[1]=0.;
+      slaterEffectiveCharge[2]=0.;
+      sCoefficient[0]=0.;
+      sCoefficient[1]=0.;
+      sCoefficient[2]=0.;
+  }
+
+  if (particleDefinition == instance->GetIon("alpha+") ) 
+  {
+      slaterEffectiveCharge[0]=2.0;
+      slaterEffectiveCharge[1]=1.15;
+      slaterEffectiveCharge[2]=1.15;
+      sCoefficient[0]=0.7;
+      sCoefficient[1]=0.15;
+      sCoefficient[2]=0.15;
+  }
+
+  if (particleDefinition == instance->GetIon("helium") ) 
+  {
+      slaterEffectiveCharge[0]=1.7;
+      slaterEffectiveCharge[1]=1.15;
+      slaterEffectiveCharge[2]=1.15;
+      sCoefficient[0]=0.5;
+      sCoefficient[1]=0.25;
+      sCoefficient[2]=0.25;
+  }
+  
+  if (    particleDefinition == instance->GetIon("helium") 
+	  || particleDefinition == instance->GetIon("alpha+")
+	  || particleDefinition == instance->GetIon("alpha++")
+	  ) 
+  {
+      sigma = Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex)) * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
+    
+      G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
+  
+      zEff -= ( sCoefficient[0] * S_1s(k, energyTransfer, slaterEffectiveCharge[0], 1.) +
+		sCoefficient[1] * S_2s(k, energyTransfer, slaterEffectiveCharge[1], 2.) +
+		sCoefficient[2] * S_2p(k, energyTransfer, slaterEffectiveCharge[2], 2.) );
+	   
+      return zEff * zEff * sigma ;
+  }  
+  
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::S_1s(G4double t, 
+					  G4double energyTransferred, 
+					  G4double slaterEffectiveChg, 
+					  G4double shellNumber)
+{
+  // 1 - e^(-2r) * ( 1 + 2 r + 2 r^2)
+  // Dingfelder, in Chattanooga 2005 proceedings, formula (7)
+ 
+  G4double r = R(t, energyTransferred, slaterEffectiveChg, shellNumber);
+  G4double value = 1. - std::exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. );
+  
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::S_2s(G4double t,
+					  G4double energyTransferred, 
+					  G4double slaterEffectiveChg, 
+					  G4double shellNumber)
+{
+  // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4)
+  // Dingfelder, in Chattanooga 2005 proceedings, formula (8)
+
+  G4double r = R(t, energyTransferred, slaterEffectiveChg, shellNumber);
+  G4double value =  1. - std::exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.);
+
+  return value;
+ 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::S_2p(G4double t, 
+					  G4double energyTransferred,
+					  G4double slaterEffectiveChg, 
+					  G4double shellNumber)
+{
+  // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4)
+  // Dingfelder, in Chattanooga 2005 proceedings, formula (9)
+
+  G4double r = R(t, energyTransferred, slaterEffectiveChg, shellNumber);
+  G4double value =  1. - std::exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r  + 1.);
+
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::R(G4double t,
+				       G4double energyTransferred,
+				       G4double slaterEffectiveChg,
+				       G4double shellNumber) 
+{
+  // tElectron = m_electron / m_alpha * t
+  // Dingfelder, in Chattanooga 2005 proceedings, p 4
+
+  G4double tElectron = 0.511/3728. * t;
+  G4double value = 2. * tElectron * slaterEffectiveChg / (energyTransferred * shellNumber);
+  
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::CorrectionFactor(G4ParticleDefinition* particleDefinition, G4double k) 
+{
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+
+  if (particleDefinition == G4Proton::Proton()) 
+  {
+      return(1.);
+  }
+  else 
+    if (particleDefinition == instance->GetIon("hydrogen")) 
+    { 
+	G4double value = (std::log(k/eV)-4.2)/0.5;
+	return((0.8/(1+std::exp(value))) + 0.9);
+    }
+    else 
+    {    
+	return(1.);
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4int G4DNARuddIonisationModel::RandomSelect(G4double k, const G4String& particle )
+{   
+  
+  // BEGIN PART 1/2 OF ELECTRON CORRECTION
+
+  // add ONE or TWO electron-water excitation for alpha+ and helium
+   
+  G4DNAGenericIonsManager *instance;
+  instance = G4DNAGenericIonsManager::Instance();
+  G4double kElectron(0);
+  G4double electronComponent(0);
+  G4DNACrossSectionDataSet * electronDataset = new G4DNACrossSectionDataSet (new G4LogLogInterpolation, eV, (1./3.343e22)*m*m);
+ 
+  if ( particle == instance->GetIon("alpha+")->GetParticleName()
+       ||
+       particle == instance->GetIon("helium")->GetParticleName()
+       ) 
+  {     
+      electronDataset->LoadData("dna/sigma_ionisation_e_born");
+
+      kElectron = k * 0.511/3728;
+       
+      electronComponent = electronDataset->FindValue(kElectron);
+       
+  }      
+  
+  delete electronDataset;
+  
+  // END PART 1/2 OF ELECTRON CORRECTION
+  
+  G4int level = 0;
+
+  // Retrieve data table corresponding to the current particle type  
+
+  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+  pos = tableData.find(particle);
+
+  if (pos != tableData.end())
+  {
+      G4DNACrossSectionDataSet* table = pos->second;
+
+      if (table != 0)
+      {
+	  G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
+	    
+	  const size_t n(table->NumberOfComponents());
+	  size_t i(n);
+	  G4double value = 0.;
+	    
+	  while (i>0)
+	  { 
+	      i--;
+	      valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
+
+	      // BEGIN PART 2/2 OF ELECTRON CORRECTION
+
+	      if (particle == instance->GetIon("alpha+")->GetParticleName()) 
+		{valuesBuffer[i]=table->GetComponent(i)->FindValue(k) + electronComponent; }
+     
+	      if (particle == instance->GetIon("helium")->GetParticleName()) 
+		{valuesBuffer[i]=table->GetComponent(i)->FindValue(k) + 2*electronComponent; }
+      
+	      // BEGIN PART 2/2 OF ELECTRON CORRECTION
+
+	      value += valuesBuffer[i];
+	  }
+	    
+	  value *= G4UniformRand();
+	    
+	  i = n;
+	    
+	  while (i > 0)
+	  {
+	      i--;
+		
+	      if (valuesBuffer[i] > value)
+	      {
+		  delete[] valuesBuffer;
+		  return i;
+	      }
+	      value -= valuesBuffer[i];
+	  }
+	    
+	  if (valuesBuffer) delete[] valuesBuffer;
+	    
+      }
+  }
+  else
+  {
+    G4Exception("G4DNARuddIonisationModel::RandomSelect: attempting to calculate cross section for wrong particle");
+  }
+      
+  return level;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::PartialCrossSection(const G4Track& track )
+{
+  G4double sigma = 0.;
+
+  const G4DynamicParticle* particle = track.GetDynamicParticle();
+  G4double k = particle->GetKineticEnergy();
+  
+  G4double lowLim = 0;
+  G4double highLim = 0;
+
+  const G4String& particleName = particle->GetDefinition()->GetParticleName();
+
+  std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
+  pos1 = lowEnergyLimit.find(particleName);
+
+  if (pos1 != lowEnergyLimit.end())
+  {
+    lowLim = pos1->second;
+  }
+
+  std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
+  pos2 = highEnergyLimit.find(particleName);
+
+  if (pos2 != highEnergyLimit.end())
+  {
+    highLim = pos2->second;
+  }
+
+  if (k >= lowLim && k <= highLim)
+  {
+      std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
+      pos = tableData.find(particleName);
+	
+      if (pos != tableData.end())
+      {
+	  G4DNACrossSectionDataSet* table = pos->second;
+	  if (table != 0)
+          {
+	      sigma = table->FindValue(k);
+          }
+      }
+      else
+      {
+	  G4Exception("G4DNARuddIonisationModel::PartialCrossSection: attempting to calculate cross section for wrong particle");
+      }
+  }
+
+  return sigma;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNARuddIonisationModel::Sum(G4double /* energy */, const G4String& /* particle */)
+{
+  return 0;
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4DNAScreenedRutherfordElasticModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4DNAScreenedRutherfordElasticModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4DNAScreenedRutherfordElasticModel.cc	(revision 1058)
@@ -0,0 +1,535 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4DNAScreenedRutherfordElasticModel.cc,v 1.5 2009/04/29 13:43:00 sincerti Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+
+#include "G4DNAScreenedRutherfordElasticModel.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+using namespace std;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAScreenedRutherfordElasticModel::G4DNAScreenedRutherfordElasticModel
+(const G4ParticleDefinition*, const G4String& nam)
+:G4VEmModel(nam),isInitialised(false)
+{
+
+  killBelowEnergy = 8.23*eV; // Minimum e- energy for energy loss by excitation
+  lowEnergyLimit = 0 * eV; 
+  lowEnergyLimitOfModel = 7 * eV; // The model lower energy is 7 eV
+  intermediateEnergyLimit = 200 * eV; // Switch between two final state models
+  highEnergyLimit = 10 * MeV;
+  SetLowEnergyLimit(lowEnergyLimit);
+  SetHighEnergyLimit(highEnergyLimit);
+
+  verboseLevel= 0;
+  // Verbosity scale:
+  // 0 = nothing 
+  // 1 = warning for energy non-conservation 
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+  
+  G4cout << "Screened Rutherford Elastic model is constructed " << G4endl
+         << "Energy range: "
+         << lowEnergyLimit / eV << " eV - "
+         << highEnergyLimit / MeV << " MeV"
+         << G4endl;
+ 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4DNAScreenedRutherfordElasticModel::~G4DNAScreenedRutherfordElasticModel()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAScreenedRutherfordElasticModel::Initialise(const G4ParticleDefinition* /*particle*/,
+                                       const G4DataVector& /*cuts*/)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling G4DNAScreenedRutherfordElasticModel::Initialise()" << G4endl;
+
+  // Energy limits
+  
+  if (LowEnergyLimit() < lowEnergyLimit)
+  {
+    G4cout << "G4DNAScreenedRutherfordElasticModel: low energy limit increased from " << 
+	LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
+    SetLowEnergyLimit(lowEnergyLimit);
+    }
+
+  if (HighEnergyLimit() > highEnergyLimit)
+  {
+    G4cout << "G4DNAScreenedRutherfordElasticModel: high energy limit decreased from " << 
+        HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
+    SetHighEnergyLimit(highEnergyLimit);
+  }
+
+  // Constants for final stae by Brenner & Zaider
+  
+  betaCoeff.push_back(7.51525);
+  betaCoeff.push_back(-0.41912);    
+  betaCoeff.push_back(7.2017E-3);
+  betaCoeff.push_back(-4.646E-5);    
+  betaCoeff.push_back(1.02897E-7);
+
+  deltaCoeff.push_back(2.9612); 
+  deltaCoeff.push_back(-0.26376); 
+  deltaCoeff.push_back(4.307E-3); 
+  deltaCoeff.push_back(-2.6895E-5);
+  deltaCoeff.push_back(5.83505E-8);
+
+  gamma035_10Coeff.push_back(-1.7013); 
+  gamma035_10Coeff.push_back(-1.48284); 
+  gamma035_10Coeff.push_back(0.6331); 
+  gamma035_10Coeff.push_back(-0.10911); 
+  gamma035_10Coeff.push_back(8.358E-3); 
+  gamma035_10Coeff.push_back(-2.388E-4);
+
+  gamma10_100Coeff.push_back(-3.32517); 
+  gamma10_100Coeff.push_back(0.10996); 
+  gamma10_100Coeff.push_back(-4.5255E-3); 
+  gamma10_100Coeff.push_back(5.8372E-5); 
+  gamma10_100Coeff.push_back(-2.4659E-7);
+
+  gamma100_200Coeff.push_back(2.4775E-2);
+  gamma100_200Coeff.push_back(-2.96264E-5);
+  gamma100_200Coeff.push_back(-1.20655E-7);
+
+  //
+
+  G4cout << "Screened Rutherford elastic model is initialized " << G4endl
+         << "Energy range: "
+         << LowEnergyLimit() / eV << " eV - "
+         << HighEnergyLimit() / MeV << " MeV"
+         << G4endl;
+
+  if(!isInitialised) 
+  {
+    isInitialised = true;
+  
+    if(pParticleChange)
+      fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
+    else
+      fParticleChangeForGamma = new G4ParticleChangeForGamma();
+  }    
+
+  // InitialiseElementSelectors(particle,cuts);
+
+  // Test if water material
+
+  flagMaterialIsWater= false;
+  densityWater = 0;
+
+  const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
+
+  if(theCoupleTable) 
+  {
+    G4int numOfCouples = theCoupleTable->GetTableSize();
+  
+    if(numOfCouples>0) 
+    {
+	  for (G4int i=0; i<numOfCouples; i++) 
+	  {
+	    const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
+	    const G4Material* material = couple->GetMaterial();
+
+            size_t j = material->GetNumberOfElements();
+            while (j>0)
+            {
+               j--;
+               const G4Element* element(material->GetElement(j));
+               if (element->GetZ() == 8.)
+	       {
+	          G4double density = material->GetAtomicNumDensityVector()[j];
+                  if (density > 0.) 
+		  { 
+		    flagMaterialIsWater = true; 
+		    densityWater = density; 
+		    
+		    if (verboseLevel > 3) 
+                    G4cout << "Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
+		  }
+	       }
+            }
+  
+          }
+   } // if(numOfCouples>0)
+
+  } // if (theCoupleTable)
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAScreenedRutherfordElasticModel::CrossSectionPerVolume(const G4Material*,
+					   const G4ParticleDefinition*,
+					   G4double ekin,
+					   G4double,
+					   G4double)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4DNAScreenedRutherfordElasticModel" << G4endl;
+
+ // Calculate total cross section for model
+
+ G4double sigma=0;
+ 
+ if (flagMaterialIsWater)
+ {
+
+  if (ekin < highEnergyLimit)
+  {
+      
+      //SI : XS must not be zero otherwise sampling of secondaries method ignored
+      if (ekin < lowEnergyLimitOfModel) ekin = lowEnergyLimitOfModel;
+      //
+      
+      G4double z = 10.;
+      G4double n = ScreeningFactor(ekin,z);
+      G4double crossSection = RutherfordCrossSection(ekin, z);
+      sigma = pi *  crossSection / (n * (n + 1.));  
+  }
+
+  if (verboseLevel > 3)
+  {
+    G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
+    G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
+    G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
+  } 
+
+ } // if (flagMaterialIsWater)
+
+ return sigma*densityWater;		   
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAScreenedRutherfordElasticModel::RutherfordCrossSection(G4double k, G4double z)
+{
+  //   
+  //                               e^4         /      K + m_e c^2      \^2
+  // sigma_Ruth(K) = Z (Z+1) -------------------- | --------------------- |
+  //                          (4 pi epsilon_0)^2  \  K * (K + 2 m_e c^2)  /
+  //
+  // Where K is the electron non-relativistic kinetic energy
+  // 
+  // NIM 155, pp. 145-156, 1978
+  
+  G4double length =(e_squared * (k + electron_mass_c2)) / (4 * pi *epsilon0 * k * ( k + 2 * electron_mass_c2));
+  G4double cross = z * ( z + 1) * length * length;
+  
+  return cross;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAScreenedRutherfordElasticModel::ScreeningFactor(G4double k, G4double z)
+{
+  //
+  //         alpha_1 + beta_1 ln(K/eV)   constK Z^(2/3)
+  // n(T) = -------------------------- -----------------
+  //              K/(m_e c^2)            2 + K/(m_e c^2)
+  //
+  // Where K is the electron non-relativistic kinetic energy
+  //
+  // n(T) > 0 for T < ~ 400 MeV
+  // 
+  // NIM 155, pp. 145-156, 1978
+  // Formulae (2) and (5)
+
+  const G4double alpha_1(1.64);
+  const G4double beta_1(-0.0825);
+  const G4double constK(1.7E-5);
+
+  G4double numerator = (alpha_1 + beta_1 * std::log(k/eV)) * constK * std::pow(z, 2./3.);
+
+  k /= electron_mass_c2;
+
+  G4double denominator = k * (2 + k);
+
+  G4double value = 0.;
+  if (denominator > 0.) value = numerator / denominator;
+
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4DNAScreenedRutherfordElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
+					      const G4MaterialCutsCouple* /*couple*/,
+					      const G4DynamicParticle* aDynamicElectron,
+					      G4double,
+					      G4double)
+{
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4DNAScreenedRutherfordElasticModel" << G4endl;
+
+  G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
+  
+  if (electronEnergy0 < killBelowEnergy)
+  {
+    fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
+    fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
+    return ;
+  }
+
+  G4double cosTheta = 0.;
+
+  if (electronEnergy0>= killBelowEnergy && electronEnergy0 < highEnergyLimit)
+  {  
+    if (electronEnergy0<intermediateEnergyLimit)
+    {
+    if (verboseLevel > 3) G4cout << "---> Using Brenner & Zaider model" << G4endl;
+    cosTheta = BrennerZaiderRandomizeCosTheta(electronEnergy0);
+    } 
+
+    if (electronEnergy0>=intermediateEnergyLimit)
+    {
+    if (verboseLevel > 3) G4cout << "---> Using Screened Rutherford model" << G4endl;
+    G4double z = 10.;
+    cosTheta = ScreenedRutherfordRandomizeCosTheta(electronEnergy0,z);
+    } 
+
+    G4double phi = 2. * pi * G4UniformRand();
+
+    G4ThreeVector zVers = aDynamicElectron->GetMomentumDirection();
+    G4ThreeVector xVers = zVers.orthogonal();
+    G4ThreeVector yVers = zVers.cross(xVers);
+
+    G4double xDir = std::sqrt(1. - cosTheta*cosTheta);
+    G4double yDir = xDir;
+    xDir *= std::cos(phi);
+    yDir *= std::sin(phi);
+
+    G4ThreeVector zPrimeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
+
+    fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit()) ;
+
+    fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
+  }
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4DNAScreenedRutherfordElasticModel::BrennerZaiderRandomizeCosTheta(G4double k)
+{
+  //  d sigma_el                         1                                 beta(K)
+  // ------------ (K) ~ --------------------------------- + ---------------------------------
+  //   d Omega           (1 + 2 gamma(K) - cos(theta))^2     (1 + 2 delta(K) + cos(theta))^2
+  //
+  // Maximum is < 1/(4 gamma(K)^2) + beta(K)/((2+2delta(K))^2)
+  //
+  // Phys. Med. Biol. 29 N.4 (1983) 443-447
+  
+  // gamma(K), beta(K) and delta(K) are polynomials with coefficients for energy measured in eV
+
+  k /= eV;
+  
+  G4double beta = std::exp(CalculatePolynomial(k,betaCoeff)); 
+  G4double delta = std::exp(CalculatePolynomial(k,deltaCoeff)); 
+  G4double gamma;
+  
+  if (k > 100.)
+  {
+      gamma = CalculatePolynomial(k, gamma100_200Coeff); 
+      // Only in this case it is not the exponent of the polynomial
+  }  
+  else 
+  {
+      if (k>10)
+      {
+	  gamma = std::exp(CalculatePolynomial(k, gamma10_100Coeff));
+      }
+      else
+      {
+	  gamma = std::exp(CalculatePolynomial(k, gamma035_10Coeff));
+      }
+  }
+
+  // ***** Original method 
+
+  G4double oneOverMax = 1. / (1./(4.*gamma*gamma) + beta/( (2.+2.*delta)*(2.+2.*delta) ));
+  
+  G4double cosTheta = 0.;
+  G4double leftDenominator = 0.;
+  G4double rightDenominator = 0.;
+  G4double fCosTheta = 0.;
+  
+  do
+  {
+      cosTheta = 2. * G4UniformRand() - 1.;
+      
+      leftDenominator = (1. + 2.*gamma - cosTheta);
+      rightDenominator = (1. + 2.*delta + cosTheta);
+      if ( (leftDenominator * rightDenominator) != 0. )
+      {
+	  fCosTheta = oneOverMax * (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator));
+      }
+  }
+  while (fCosTheta < G4UniformRand());
+
+  return cosTheta; 
+
+  // ***** Alternative method using cumulative probability 
+/* 
+ G4double cosTheta = -1;
+ G4double cumul = 0;
+ G4double value = 0;
+ G4double leftDenominator = 0.;
+ G4double rightDenominator = 0.;
+  
+ // Number of integration steps in the -1,1 range
+ G4int iMax=200;
+ 
+ G4double random = G4UniformRand();
+ 
+ // Cumulate differential cross section
+ for (G4int i=0; i<iMax; i++) 
+ {
+   cosTheta = -1 + i*2./(iMax-1);
+   leftDenominator = (1. + 2.*gamma - cosTheta);
+   rightDenominator = (1. + 2.*delta + cosTheta);
+   if ( (leftDenominator * rightDenominator) != 0. )
+   {
+     cumul = cumul + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator));
+   }
+ }
+ 
+ // Select cosTheta
+ for (G4int i=0; i<iMax; i++) 
+ {
+   cosTheta = -1 + i*2./(iMax-1);
+   leftDenominator = (1. + 2.*gamma - cosTheta);
+   rightDenominator = (1. + 2.*delta + cosTheta);
+   if (cumul !=0 && (leftDenominator * rightDenominator) != 0.) 
+       value = value + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator)) / cumul;
+   if (random < value) break; 
+ } 
+
+ return cosTheta;
+*/
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAScreenedRutherfordElasticModel::CalculatePolynomial(G4double k, std::vector<G4double>& vec)
+{
+  // Sum_{i=0}^{size-1} vector_i k^i
+  //
+  // Phys. Med. Biol. 29 N.4 (1983) 443-447
+
+  G4double result = 0.;
+  size_t size = vec.size();
+
+  while (size>0)
+    {
+      size--; 
+      
+      result *= k;
+      result += vec[size];
+    }
+  
+  return result;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4double G4DNAScreenedRutherfordElasticModel::ScreenedRutherfordRandomizeCosTheta(G4double k, G4double z)
+{
+
+ //  d sigma_el                sigma_Ruth(K)
+ // ------------ (K) ~ -----------------------------
+ //   d Omega           (1 + 2 n(K) - cos(theta))^2
+ //
+ // We extract cos(theta) distributed as (1 + 2 n(K) - cos(theta))^-2
+ //
+ // Maximum is for theta=0: 1/(4 n(K)^2) (When n(K) is positive, that is always satisfied within the validity of the process)
+ //
+ // Phys. Med. Biol. 45 (2000) 3171-3194
+
+ // ***** Original method 
+
+ G4double n = ScreeningFactor(k, z);
+
+ G4double oneOverMax = (4.*n*n);
+
+ G4double cosTheta = 0.;
+ G4double fCosTheta;
+
+ do 
+ { 
+   cosTheta = 2. * G4UniformRand() - 1.;
+//G4cout << "SR cos=" << cosTheta << G4endl;
+   fCosTheta = (1 + 2.*n - cosTheta);
+   if (fCosTheta !=0.) fCosTheta = oneOverMax / (fCosTheta*fCosTheta);
+ }
+ while (fCosTheta < G4UniformRand());
+ 
+ return cosTheta;
+  
+ // ***** Alternative method using cumulative probability 
+/*
+ G4double cosTheta = -1;
+ G4double cumul = 0;
+ G4double value = 0;
+ G4double n = ScreeningFactor(k, z);
+ G4double fCosTheta;
+  
+ // Number of integration steps in the -1,1 range
+ G4int iMax=200;
+ 
+ G4double random = G4UniformRand();
+ 
+ // Cumulate differential cross section
+ for (G4int i=0; i<iMax; i++) 
+ {
+   cosTheta = -1 + i*2./(iMax-1);
+   fCosTheta = (1 + 2.*n - cosTheta);
+   if (fCosTheta !=0.) cumul = cumul + 1./(fCosTheta*fCosTheta);
+ }
+ 
+ // Select cosTheta
+ for (G4int i=0; i<iMax; i++) 
+ {
+   cosTheta = -1 + i*2./(iMax-1);
+   fCosTheta = (1 + 2.*n - cosTheta);
+   if (cumul !=0.) value = value + (1./(fCosTheta*fCosTheta)) / cumul;
+   if (random < value) break; 
+ } 
+ return cosTheta;
+*/
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4IonDEDXHandler.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4IonDEDXHandler.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4IonDEDXHandler.cc	(revision 1058)
@@ -0,0 +1,547 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+//
+// ===========================================================================
+// GEANT4 class source file
+//
+// Class:                G4IonDEDXHandler
+//
+// Author:               Anton Lechner (Anton.Lechner@cern.ch)
+//
+// First implementation: 11. 03. 2009
+//
+// Modifications: 
+//
+//
+// Class description:
+//    Ion dE/dx table handler. 
+//
+// Comments:
+//
+// =========================================================================== 
+
+
+#include "G4IonDEDXHandler.hh"
+#include "G4VIonDEDXTable.hh"
+#include "G4VIonDEDXScalingAlgorithm.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4Material.hh"
+#include "G4LPhysicsFreeVector.hh"
+#include <iomanip>
+
+//#define PRINT_DEBUG
+
+
+// #########################################################################
+
+G4IonDEDXHandler::G4IonDEDXHandler(
+                            G4VIonDEDXTable* ionTable,
+                            G4VIonDEDXScalingAlgorithm* ionAlgorithm,
+                            const G4String& name,
+                            G4int maxCacheSize,
+                            G4bool splines) :
+  table(ionTable),
+  algorithm(ionAlgorithm),
+  tableName(name),
+  useSplines(splines),
+  maxCacheEntries(maxCacheSize) {
+
+  if(table == 0) {
+     G4cerr << "G4IonDEDXHandler::G4IonDEDXHandler() "
+            << " Pointer to G4VIonDEDXTable object is null-pointer." 
+            << G4endl;
+  }
+
+  if(algorithm == 0) {
+     G4cerr << "G4IonDEDXHandler::G4IonDEDXHandler() "
+            << " Pointer to G4VIonDEDXScalingAlgorithm object is null-pointer." 
+            << G4endl;
+  }
+
+  if(maxCacheEntries <= 0) {
+     G4cerr << "G4IonDEDXHandler::G4IonDEDXHandler() "
+            << " Cache size <=0. Resetting to 5." 
+            << G4endl;
+     maxCacheEntries = 5;
+  }
+}
+
+// #########################################################################
+
+G4IonDEDXHandler::~G4IonDEDXHandler() {
+
+  ClearCache();
+
+  // All stopping power vectors built according to Bragg's addivitiy rule
+  // are deleted. All other stopping power vectors are expected to be
+  // deleted by their creator class (sub-class of G4VIonDEDXTable). 
+  DEDXTableBraggRule::iterator iter = stoppingPowerTableBragg.begin();
+  DEDXTableBraggRule::iterator iter_end = stoppingPowerTableBragg.end();
+
+  for(;iter != iter_end; iter++) delete iter -> second;
+  stoppingPowerTableBragg.clear();
+
+  stoppingPowerTable.clear();
+
+  if(table != 0) delete table;
+  if(algorithm != 0) delete algorithm;
+}
+
+// #########################################################################
+
+G4bool G4IonDEDXHandler::IsApplicable(
+                 const G4ParticleDefinition* particle,  // Projectile (ion) 
+                 const G4Material* material) {          // Target material 
+
+  G4bool isApplicable = true; 
+
+  if(table == 0 || algorithm == 0) {
+     isApplicable = false;
+  }
+  else {
+
+     G4int atomicNumberIon = particle -> GetAtomicNumber();
+     G4int atomicNumberBase = 
+                algorithm -> AtomicNumberBaseIon(atomicNumberIon, material);
+
+     G4IonKey key = std::make_pair(atomicNumberBase, material);
+
+     DEDXTable::iterator iter = stoppingPowerTable.find(key);
+     if(iter == stoppingPowerTable.end()) isApplicable = false; 
+  }
+
+  return isApplicable; 
+}
+
+// #########################################################################
+
+G4double G4IonDEDXHandler::GetDEDX(
+                 const G4ParticleDefinition* particle,  // Projectile (ion) 
+                 const G4Material* material,   // Target material 
+                 G4double kineticEnergy) {     // Kinetic energy of projectile
+
+  G4double dedx = 0.0;
+
+  G4CacheValue value = GetCacheValue(particle, material); 
+     
+  if(kineticEnergy <= 0.0) dedx = 0.0;
+  else if(value.dedxVector != 0) {
+ 
+     G4bool b;
+     G4double factor = value.density;
+
+     factor *= algorithm -> ScalingFactorDEDX(particle, 
+                                             material,
+                                             kineticEnergy);
+     G4double scaledKineticEnergy = kineticEnergy * value.energyScaling;
+
+     if(scaledKineticEnergy < value.lowerEnergyEdge) {
+
+        factor *= std::sqrt(scaledKineticEnergy / value.lowerEnergyEdge);
+        scaledKineticEnergy = value.lowerEnergyEdge;
+     }
+
+     dedx = factor * value.dedxVector -> GetValue(scaledKineticEnergy, b);
+
+     if(dedx < 0.0) dedx = 0.0;
+  }
+  else dedx = 0.0;
+
+#ifdef PRINT_DEBUG
+     G4cout << "G4IonDEDXHandler::GetDEDX() E = " 
+            << kineticEnergy / MeV << " MeV * "
+            << value.energyScaling << " = "
+            << kineticEnergy * value.energyScaling / MeV 
+            << " MeV, dE/dx = " << dedx / MeV * cm << " MeV/cm"
+            << ", material = " << material -> GetName()
+            << G4endl;
+#endif
+
+  return dedx;
+}
+
+// #########################################################################
+
+G4bool G4IonDEDXHandler::BuildDEDXTable(
+                 const G4ParticleDefinition* particle,  // Projectile (ion) 
+                 const G4Material* material) {          // Target material 
+
+  G4int atomicNumberIon = particle -> GetAtomicNumber();
+
+  G4bool isApplicable = BuildDEDXTable(atomicNumberIon, material);
+
+  return isApplicable;
+}
+
+
+// #########################################################################
+
+G4bool G4IonDEDXHandler::BuildDEDXTable(
+                 G4int atomicNumberIon,                // Projectile (ion) 
+                 const G4Material* material) {         // Target material 
+
+  G4bool isApplicable = true; 
+
+  if(table == 0 || algorithm == 0) {
+     isApplicable = false;
+     return isApplicable;
+  }
+
+  G4int atomicNumberBase = 
+                algorithm -> AtomicNumberBaseIon(atomicNumberIon, material);
+
+  // Checking if vector is already built, and returns if this is indeed 
+  // the case
+  G4IonKey key = std::make_pair(atomicNumberBase, material);
+
+  DEDXTable::iterator iter = stoppingPowerTable.find(key);
+  if(iter != stoppingPowerTable.end()) return isApplicable;
+
+  // Checking if table contains stopping power vector for given material name
+  // or chemical formula
+  const G4String& chemFormula = material -> GetChemicalFormula();
+  const G4String& materialName = material -> GetName();
+
+  isApplicable = table -> IsApplicable(atomicNumberBase, chemFormula);
+
+  if(isApplicable) { 
+     stoppingPowerTable[key] = 
+              table -> GetPhysicsVector(atomicNumberBase, chemFormula);
+     return isApplicable;
+  }
+
+  isApplicable = table -> IsApplicable(atomicNumberBase, materialName);
+  if(isApplicable) { 
+     stoppingPowerTable[key] = 
+              table -> GetPhysicsVector(atomicNumberBase, materialName);
+     return isApplicable;
+  }
+
+  // Building the stopping power vector based on Bragg's additivity rule
+  const G4ElementVector* elementVector = material -> GetElementVector() ;
+
+  std::vector<G4PhysicsVector*> dEdxTable;
+
+  size_t nmbElements = material -> GetNumberOfElements();
+
+  for(size_t i = 0; i < nmbElements; i++) {
+
+      G4int atomicNumberMat = G4int((*elementVector)[i] -> GetZ());
+
+      isApplicable = table -> IsApplicable(atomicNumberBase, atomicNumberMat);
+
+      if(isApplicable) { 
+
+         G4PhysicsVector* dEdx = 
+                  table -> GetPhysicsVector(atomicNumberBase, atomicNumberMat);
+         dEdxTable.push_back(dEdx);
+      }
+      else {
+
+         dEdxTable.clear();
+         break;
+      }
+  }
+     
+  if(isApplicable) {
+
+     if(dEdxTable.size() > 0) {
+
+        size_t nmbdEdxBins = dEdxTable[0] -> GetVectorLength();
+        G4double lowerEdge = dEdxTable[0] -> GetLowEdgeEnergy(0);
+        G4double upperEdge = dEdxTable[0] -> GetLowEdgeEnergy(nmbdEdxBins);
+
+        G4LPhysicsFreeVector* dEdxBragg = 
+                    new G4LPhysicsFreeVector(nmbdEdxBins,
+                                             lowerEdge,
+                                             upperEdge);
+        dEdxBragg -> SetSpline(useSplines);
+
+        const G4double* massFractionVector = material -> GetFractionVector();
+
+        G4bool b;
+        for(size_t j = 0; j < nmbdEdxBins; j++) {
+
+            G4double edge = dEdxTable[0] -> GetLowEdgeEnergy(j);
+
+            G4double value = 0.0;
+  	    for(size_t i = 0; i < nmbElements; i++) {
+ 
+                value += (dEdxTable[i] -> GetValue(edge ,b)) *
+                                                       massFractionVector[i];
+	    }
+
+            dEdxBragg -> PutValues(j, edge, value); 
+	}
+
+#ifdef PRINT_DEBUG
+        G4cout << "G4IonDEDXHandler::BuildPhysicsVector() for ion with Z="
+               << atomicNumberBase << " in "
+               << material -> GetName()
+               << G4endl;
+
+        G4cout << *dEdxBragg;
+#endif
+
+	stoppingPowerTable[key] = dEdxBragg;
+	stoppingPowerTableBragg[key] = dEdxBragg;
+     }
+  }  
+
+  ClearCache();
+
+  return isApplicable;
+}
+
+// #########################################################################
+
+G4CacheValue G4IonDEDXHandler::UpdateCacheValue(
+              const G4ParticleDefinition* particle,  // Projectile (ion) 
+              const G4Material* material) {          // Target material 
+
+  G4CacheValue value;
+
+  G4int atomicNumberIon = particle -> GetAtomicNumber();
+  G4int atomicNumberBase = 
+                algorithm -> AtomicNumberBaseIon(atomicNumberIon, material);
+
+  G4IonKey key = std::make_pair(atomicNumberBase, material);
+
+  DEDXTable::iterator iter = stoppingPowerTable.find(key);
+
+  if(iter != stoppingPowerTable.end()) {
+     value.dedxVector = iter -> second;
+ 
+     G4double nmbNucleons = G4double(particle -> GetAtomicMass());
+     value.energyScaling = 
+            algorithm -> ScalingFactorEnergy(particle) / nmbNucleons;
+
+     size_t nmbdEdxBins = value.dedxVector -> GetVectorLength();
+     value.lowerEnergyEdge = value.dedxVector -> GetLowEdgeEnergy(0);
+   
+     value.upperEnergyEdge = 
+                       value.dedxVector -> GetLowEdgeEnergy(nmbdEdxBins-1);
+     value.density = material -> GetDensity();
+  }
+  else {
+     value.dedxVector = 0;
+     value.energyScaling = 0.0; 
+     value.lowerEnergyEdge = 0.0;
+     value.upperEnergyEdge = 0.0;
+     value.density = 0.0;
+  }
+
+#ifdef PRINT_DEBUG
+  G4cout << "G4IonDEDXHandler::UpdateCacheValue() for " 
+         << particle -> GetParticleName() << " in "
+         << material -> GetName() 
+         << G4endl;
+#endif
+
+  return value;
+}
+
+// #########################################################################
+
+G4CacheValue G4IonDEDXHandler::GetCacheValue(
+              const G4ParticleDefinition* particle,  // Projectile (ion) 
+              const G4Material* material) {          // Target material 
+
+  G4CacheKey key = std::make_pair(particle, material);
+
+  G4CacheEntry entry;
+  CacheEntryList::iterator* pointerIter = 
+                  (CacheEntryList::iterator*) cacheKeyPointers[key];
+
+  if(!pointerIter) {
+      entry.value = UpdateCacheValue(particle, material);
+
+      entry.key = key;
+      cacheEntries.push_front(entry);
+
+      CacheEntryList::iterator* pointerIter = 
+                                   new CacheEntryList::iterator();
+      *pointerIter = cacheEntries.begin();
+      cacheKeyPointers[key] = pointerIter;
+
+      if(G4int(cacheEntries.size()) > maxCacheEntries) {
+
+  	 G4CacheEntry lastEntry = cacheEntries.back();
+	          
+         void* pointerIter = cacheKeyPointers[lastEntry.key];
+         CacheEntryList::iterator* listPointerIter = 
+                      	  (CacheEntryList::iterator*) pointerIter;
+
+         cacheEntries.erase(*listPointerIter);
+
+         delete listPointerIter;
+         cacheKeyPointers.erase(lastEntry.key);
+      }
+  }
+  else {
+      entry = *(*pointerIter);
+      // Cache entries are currently not re-ordered. 
+      // Uncomment for activating re-ordering:
+      //      cacheEntries.erase(*pointerIter);
+      //      cacheEntries.push_front(entry);
+      //      *pointerIter = cacheEntries.begin();
+  }
+  return entry.value;
+}
+
+// #########################################################################
+
+void G4IonDEDXHandler::ClearCache() {
+
+  CacheIterPointerMap::iterator iter = cacheKeyPointers.begin();
+  CacheIterPointerMap::iterator iter_end = cacheKeyPointers.end();
+  
+  for(;iter != iter_end; iter++) {
+      void* pointerIter = iter -> second;
+      CacheEntryList::iterator* listPointerIter = 
+                      	  (CacheEntryList::iterator*) pointerIter;
+
+      delete listPointerIter;
+  }
+ 
+  cacheEntries.clear();
+  cacheKeyPointers.clear();
+}
+
+// #########################################################################
+
+void G4IonDEDXHandler::PrintDEDXTable(
+                  const G4ParticleDefinition* particle,  // Projectile (ion) 
+                  const G4Material* material,  // Target material
+                  G4double lowerBoundary,      // Minimum energy per nucleon
+                  G4double upperBoundary,      // Maximum energy per nucleon
+                  G4int nmbBins,               // Number of bins
+                  G4bool logScaleEnergy) {     // Logarithmic scaling of energy
+
+  G4double atomicMassNumber = particle -> GetAtomicMass();
+  G4double materialDensity = material -> GetDensity();
+
+  G4cout << "# dE/dx table for " << particle -> GetParticleName() 
+         << " in material " << material -> GetName()
+         << " of density " << materialDensity / g * cm3
+         << " g/cm3"
+         << G4endl
+         << "# Projectile mass number A1 = " << atomicMassNumber
+         << G4endl
+         << "# Energy range (per nucleon) of tabulation: " 
+         << GetLowerEnergyEdge(particle, material) / atomicMassNumber / MeV
+         << " - " 
+         << GetUpperEnergyEdge(particle, material) / atomicMassNumber / MeV
+         << " MeV"
+         << G4endl
+         << "# ------------------------------------------------------"
+         << G4endl;
+  G4cout << "#"
+         << std::setw(13) << std::right << "E"
+         << std::setw(14) << "E/A1"
+         << std::setw(14) << "dE/dx"
+         << std::setw(14) << "1/rho*dE/dx"
+         << G4endl;
+  G4cout << "#"
+         << std::setw(13) << std::right << "(MeV)"
+         << std::setw(14) << "(MeV)"
+         << std::setw(14) << "(MeV/cm)"
+         << std::setw(14) << "(MeV*cm2/mg)"
+         << G4endl
+         << "# ------------------------------------------------------"
+         << G4endl;
+
+  G4CacheValue value = GetCacheValue(particle, material); 
+
+  G4double energyLowerBoundary = lowerBoundary * atomicMassNumber;
+  G4double energyUpperBoundary = upperBoundary * atomicMassNumber; 
+
+  if(logScaleEnergy) {
+
+     energyLowerBoundary = std::log(energyLowerBoundary);
+     energyUpperBoundary = std::log(energyUpperBoundary); 
+  }
+
+  G4double deltaEnergy = (energyUpperBoundary - energyLowerBoundary) / 
+                                                           G4double(nmbBins);
+
+  G4cout.precision(6);
+  for(int i = 0; i < nmbBins + 1; i++) {
+
+      G4double energy = energyLowerBoundary + i * deltaEnergy;
+      if(logScaleEnergy) energy = std::exp(energy);
+
+      G4double loss = GetDEDX(particle, material, energy);
+
+      G4cout << std::setw(14) << std::right << energy / MeV
+             << std::setw(14) << energy / atomicMassNumber / MeV
+             << std::setw(14) << loss / MeV * cm
+             << std::setw(14) << loss / materialDensity / (MeV*cm2/(0.001*g)) 
+             << G4endl;
+  }
+}
+
+// #########################################################################
+
+G4double G4IonDEDXHandler::GetLowerEnergyEdge(
+                 const G4ParticleDefinition* particle,  // Projectile (ion) 
+                 const G4Material* material) {          // Target material 
+
+  G4double edge = 0.0; 
+
+  G4CacheValue value = GetCacheValue(particle, material); 
+     
+  if(value.energyScaling > 0) 
+          edge = value.lowerEnergyEdge / value.energyScaling;
+
+  return edge;
+}
+
+// #########################################################################
+
+G4double G4IonDEDXHandler::GetUpperEnergyEdge(
+                 const G4ParticleDefinition* particle,  // Projectile (ion) 
+                 const G4Material* material) {          // Target material 
+
+  G4double edge = 0.0; 
+
+  G4CacheValue value = GetCacheValue(particle, material); 
+     
+  if(value.energyScaling > 0) 
+          edge = value.upperEnergyEdge / value.energyScaling;
+
+  return edge;
+}
+
+// #########################################################################
+
+G4String G4IonDEDXHandler::GetName() {
+
+  return tableName;
+}
+
+// #########################################################################
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4IonDEDXScalingICRU73.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4IonDEDXScalingICRU73.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4IonDEDXScalingICRU73.cc	(revision 1058)
@@ -0,0 +1,185 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+//
+// ===========================================================================
+// GEANT4 class source file
+//
+// Class:                G4IonDEDXScalingICRU73
+//
+// Base class:           G4VIonDEDXScalingAlgorithm
+//
+// Author:               Anton Lechner (Anton.Lechner@cern.ch)
+//
+// First implementation: 10. 05. 2009
+//
+// Modifications: 
+//
+//
+// Class description:
+//    dE/dx scaling algorithm applied on top of ICRU 73 data (for ions not
+//    covered by the ICRU 73 report) 
+//
+// Comments:
+//
+// =========================================================================== 
+
+#include "G4IonDEDXScalingICRU73.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4ParticleTable.hh"
+#include "G4Material.hh"
+
+
+// ###########################################################################
+
+G4IonDEDXScalingICRU73::G4IonDEDXScalingICRU73(
+                          G4int minAtomicNumberIon,
+                          G4int maxAtomicNumberIon,
+                          G4int atomicNumberReference, 
+                          G4int massNumberReference) :
+     minAtomicNumber( minAtomicNumberIon ),
+     maxAtomicNumber( maxAtomicNumberIon ),
+     excludedIon( false ),
+     reference( 0 ),
+     atomicNumberRef( atomicNumberReference ),
+     massNumberRef( massNumberReference ) { 
+
+}
+
+// ###########################################################################
+
+G4IonDEDXScalingICRU73::~G4IonDEDXScalingICRU73() {
+
+}
+
+// ###########################################################################
+
+void G4IonDEDXScalingICRU73::CreateReferenceParticle() {
+
+   
+  G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
+
+  G4double excitationEnergy = 0.0;
+
+  reference = 
+    particleTable -> GetIon(atomicNumberRef, massNumberRef, excitationEnergy); 
+  
+  massRef = reference -> GetPDGMass();
+  chargeRef = reference -> GetPDGCharge();
+
+  atomicNumberRefPow23 = std::pow(atomicNumberRef, 2./3.);
+}
+
+
+// ###########################################################################
+
+
+G4double G4IonDEDXScalingICRU73::ScalingFactorEnergy (
+            const G4ParticleDefinition* particle) {    // Projectile (ion) 
+                                                         
+  G4double factor = 1.0;
+ 
+  UpdateCache(particle);
+
+  if(! excludedIon &&
+     cacheAtomicNumber >= minAtomicNumber &&
+     cacheAtomicNumber <= maxAtomicNumber) {
+
+     if(reference == 0) CreateReferenceParticle();
+
+     factor = cacheMassNumber * (massRef / cacheMass) / massNumberRef;
+  }
+
+  return factor;
+}
+
+// ###########################################################################
+
+G4double G4IonDEDXScalingICRU73::ScalingFactorDEDX(
+             const G4ParticleDefinition* particle,     // Projectile (ion) 
+             const G4Material*,                        // Target material
+             G4double kineticEnergy) {                 // Kinetic energy
+
+  G4double factor = 1.0;
+
+  UpdateCache(particle);
+
+  if(! excludedIon &&
+     cacheAtomicNumber >= minAtomicNumber &&
+     cacheAtomicNumber <= maxAtomicNumber) {
+      
+      if(reference == 0) CreateReferenceParticle();
+
+      G4double equilibriumCharge = EquilibriumCharge(cacheMass,
+                                                     cacheCharge,
+                                                     cacheAtomicNumberPow23,
+                                                     kineticEnergy);
+
+      G4double scaledKineticEnergy = kineticEnergy * (massRef / cacheMass);
+      
+      G4double equilibriumChargeRef = EquilibriumCharge(massRef,
+                                                        chargeRef,
+                                                        atomicNumberRefPow23,
+                                                        scaledKineticEnergy);
+
+      factor = equilibriumCharge * equilibriumCharge/ 
+                ( equilibriumChargeRef * equilibriumChargeRef );
+ }  
+
+  return factor;
+}
+
+// ###########################################################################
+
+G4int G4IonDEDXScalingICRU73::AtomicNumberBaseIon(
+             G4int atomicNumberIon,           // Atomic number of ion 
+             const G4Material*) {             // Target material
+
+  G4int atomicNumber = atomicNumberIon;
+
+  if(atomicNumberIon >= minAtomicNumber &&
+     atomicNumberIon <= maxAtomicNumber) {
+ 
+     G4bool ionIsExcluded = false;
+     size_t nmb = excludedAtomicNumbers.size();
+ 
+     for(size_t i = 0; i < nmb; i++) {
+        
+        if(atomicNumberIon == excludedAtomicNumbers[i]) 
+           ionIsExcluded = true;
+     }
+
+     if(! ionIsExcluded) {
+        if(reference == 0) CreateReferenceParticle();
+
+        atomicNumber = atomicNumberRef;
+     }
+  }
+
+  return atomicNumber;
+}
+
+// ###########################################################################
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4LivermoreBremsstrahlungModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4LivermoreBremsstrahlungModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4LivermoreBremsstrahlungModel.cc	(revision 1058)
@@ -0,0 +1,391 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4LivermoreBremsstrahlungModel.cc,v 1.4 2009/05/19 14:57:01 pandola Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 03 Mar 2009   L Pandola    Migration from process to model 
+// 12 Apr 2009   V Ivanchenko Cleanup initialisation and generation of secondaries:
+//                  - apply internal high-energy limit only in constructor 
+//                  - do not apply low-energy limit (default is 0)
+//                  - added MinEnergyCut method
+//                  - do not change track status
+//                  - do not initialize element selectors
+//                  - use cut value from the interface 
+//                  - fixed bug in sampling of angles between keV and MeV
+// 19 May 2009   L Pandola    Explicitely set to zero pointers deleted in 
+//                            Initialise(), since they might be checked later on
+//
+
+#include "G4LivermoreBremsstrahlungModel.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4MaterialCutsCouple.hh"
+
+#include "G4DynamicParticle.hh"
+#include "G4Element.hh"
+#include "G4Gamma.hh"
+#include "G4Electron.hh"
+#include "G4SemiLogInterpolation.hh"
+//
+#include "G4VBremAngularDistribution.hh"
+#include "G4ModifiedTsai.hh"
+#include "G4Generator2BS.hh"
+#include "G4Generator2BN.hh"
+//
+#include "G4BremsstrahlungCrossSectionHandler.hh"
+//
+#include "G4VEnergySpectrum.hh"
+#include "G4eBremsstrahlungSpectrum.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4LivermoreBremsstrahlungModel::G4LivermoreBremsstrahlungModel(const G4ParticleDefinition*,
+							       const G4String& nam)
+  :G4VEmModel(nam),isInitialised(false),crossSectionHandler(0),
+   energySpectrum(0)
+{
+  fIntrinsicLowEnergyLimit = 10.0*eV;
+  fIntrinsicHighEnergyLimit = 100.0*GeV;
+  fNBinEnergyLoss = 360;
+  //  SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
+  SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
+  //
+  verboseLevel = 0;
+  //
+  generatorName = "tsai";
+  angularDistribution = new G4ModifiedTsai("TsaiGenerator"); //default generator
+  //
+  TsaiAngularDistribution = new G4ModifiedTsai("TsaiGenerator");
+  //
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4LivermoreBremsstrahlungModel::~G4LivermoreBremsstrahlungModel()
+{
+  if (crossSectionHandler) delete crossSectionHandler;
+  if (energySpectrum) delete energySpectrum;
+  energyBins.clear();
+  delete angularDistribution;
+  delete TsaiAngularDistribution;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreBremsstrahlungModel::Initialise(const G4ParticleDefinition* particle,
+						const G4DataVector& cuts)
+{
+  //Check that the Livermore Bremsstrahlung is NOT attached to e+
+  if (particle != G4Electron::Electron())
+    {
+      G4cout << "ERROR: Livermore Bremsstrahlung Model is applicable only to electrons" 
+	     << G4endl;
+      G4cout << "It cannot be registered to " << particle->GetParticleName() << G4endl;
+      G4Exception();
+    }
+  //Prepare energy spectrum
+  if (energySpectrum) 
+    {
+      delete energySpectrum;
+      energySpectrum = 0;
+    }
+
+  energyBins.clear();
+  for(size_t i=0; i<15; i++) 
+    {
+      G4double x = 0.1*((G4double)i);
+      if(i == 0)  x = 0.01;
+      if(i == 10) x = 0.95;
+      if(i == 11) x = 0.97;
+      if(i == 12) x = 0.99;
+      if(i == 13) x = 0.995;
+      if(i == 14) x = 1.0;
+      energyBins.push_back(x);
+    }
+  const G4String dataName("/brem/br-sp.dat");
+  energySpectrum = new G4eBremsstrahlungSpectrum(energyBins,dataName);
+  
+  if (verboseLevel > 0)
+    G4cout << "G4eBremsstrahlungSpectrum is initialized" << G4endl;
+
+  //Initialize cross section handler
+  if (crossSectionHandler) 
+    {
+      delete crossSectionHandler;
+      crossSectionHandler = 0;
+    }
+  G4VDataSetAlgorithm* interpolation = new G4SemiLogInterpolation();
+  crossSectionHandler = new G4BremsstrahlungCrossSectionHandler(energySpectrum,interpolation);
+  crossSectionHandler->Initialise(0,LowEnergyLimit(),HighEnergyLimit(),
+				  fNBinEnergyLoss);
+  crossSectionHandler->Clear();
+  crossSectionHandler->LoadShellData("brem/br-cs-");
+  //This is used to retrieve cross section values later on
+  crossSectionHandler->BuildMeanFreePathForMaterials(&cuts);
+  
+  if (verboseLevel > 0)
+    {
+      G4cout << "Livermore Bremsstrahlung model is initialized " << G4endl
+	     << "Energy range: "
+	     << LowEnergyLimit() / keV << " keV - "
+	     << HighEnergyLimit() / GeV << " GeV"
+	     << G4endl;
+    }
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "Cross section data: " << G4endl; 
+      crossSectionHandler->PrintData();
+      G4cout << "Parameters: " << G4endl;
+      energySpectrum->PrintData();
+    }
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForLoss();
+  isInitialised = true; 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4LivermoreBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
+						      const G4MaterialCutsCouple*)
+{
+  return 250.*eV;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double 
+G4LivermoreBremsstrahlungModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+							   G4double energy,
+							   G4double Z, G4double,
+							   G4double cutEnergy, 
+							   G4double)
+{
+  G4int iZ = (G4int) Z;
+  if (!crossSectionHandler)
+    {
+      G4cout << "G4LivermoreBremsstrahlungModel::ComputeCrossSectionPerAtom" << G4endl;
+      G4cout << "The cross section handler is not correctly initialized" << G4endl;
+      G4Exception();
+    }
+  
+  //The cut is already included in the crossSectionHandler
+  G4double cs = 
+    crossSectionHandler->GetCrossSectionAboveThresholdForElement(energy,cutEnergy,iZ);
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "G4LivermoreBremsstrahlungModel " << G4endl;
+      G4cout << "Cross section for gamma emission > " << cutEnergy/keV << " keV at " <<
+	energy/keV << " keV and Z = " << iZ << " --> " << cs/barn << " barn" << G4endl;
+    }
+  return cs;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4LivermoreBremsstrahlungModel::ComputeDEDXPerVolume(const G4Material* material,
+                             		   const G4ParticleDefinition* ,
+                               		   G4double kineticEnergy,
+                               		   G4double cutEnergy)
+{
+  G4double sPower = 0.0;
+
+  const G4ElementVector* theElementVector = material->GetElementVector();
+  size_t NumberOfElements = material->GetNumberOfElements() ;
+  const G4double* theAtomicNumDensityVector =
+                    material->GetAtomicNumDensityVector();
+
+  // loop for elements in the material
+  for (size_t iel=0; iel<NumberOfElements; iel++ ) 
+    {
+      G4int iZ = (G4int)((*theElementVector)[iel]->GetZ());
+      G4double e = energySpectrum->AverageEnergy(iZ, 0.0,cutEnergy,
+						 kineticEnergy);
+      G4double cs= crossSectionHandler->FindValue(iZ,kineticEnergy);
+      sPower   += e * cs * theAtomicNumDensityVector[iel];
+    }
+
+  if (verboseLevel > 2)
+    {
+      G4cout << "G4LivermoreBremsstrahlungModel " << G4endl;
+      G4cout << "Stopping power < " << cutEnergy/keV << " keV at " << 
+	kineticEnergy/keV << " keV = " << sPower/(keV/mm) << " keV/mm" << G4endl;
+    }
+    
+  return sPower;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+					      const G4MaterialCutsCouple* couple,
+					      const G4DynamicParticle* aDynamicParticle,
+					      G4double energyCut,
+					      G4double)
+{
+  
+  G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
+
+  // this is neede for pathalogical cases of no ionisation
+  if (kineticEnergy <= fIntrinsicLowEnergyLimit)
+    {
+      fParticleChange->SetProposedKineticEnergy(0.);
+      fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy);
+      return;
+    }
+
+  //Sample material
+  G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
+
+  //Sample gamma energy
+  G4double tGamma = energySpectrum->SampleEnergy(Z, energyCut, kineticEnergy, kineticEnergy);
+  G4double totalEnergy = kineticEnergy + electron_mass_c2;
+  G4double finalEnergy = kineticEnergy - tGamma; // electron final energy  
+  G4double theta = 0;
+
+  if (tGamma == 0.) //nothing happens
+    return;
+
+  //Sample gamma direction
+  //Use alternative algorithms, if it is the case.
+  if((kineticEnergy < MeV && kineticEnergy > keV))
+    { 
+      theta = angularDistribution->PolarAngle(kineticEnergy,finalEnergy,Z);
+    }
+  else
+    //Otherwise, use tsai
+    {
+      theta = TsaiAngularDistribution->PolarAngle(kineticEnergy,finalEnergy,Z);
+    }  
+
+  G4double phi   = twopi * G4UniformRand();
+  G4double dirZ  = std::cos(theta);
+  G4double sinTheta  = std::sqrt(1. - dirZ*dirZ);
+  G4double dirX  = sinTheta*std::cos(phi);
+  G4double dirY  = sinTheta*std::sin(phi);
+
+  G4ThreeVector gammaDirection (dirX, dirY, dirZ);
+  G4ThreeVector electronDirection = aDynamicParticle->GetMomentumDirection();
+
+  //Update the incident particle
+  gammaDirection.rotateUz(electronDirection);   
+    
+  if (finalEnergy < 0.) 
+    {
+      // Kinematic problem
+      tGamma = kineticEnergy;
+      fParticleChange->SetProposedKineticEnergy(0.);
+    }
+  else
+    {
+      G4double momentum = std::sqrt((totalEnergy + electron_mass_c2)*kineticEnergy);
+      G4double finalX = momentum*electronDirection.x() - tGamma*gammaDirection.x();
+      G4double finalY = momentum*electronDirection.y() - tGamma*gammaDirection.y();
+      G4double finalZ = momentum*electronDirection.z() - tGamma*gammaDirection.z();
+      G4double norm = 1./std::sqrt(finalX*finalX + finalY*finalY + finalZ*finalZ);
+      
+      fParticleChange->ProposeMomentumDirection(finalX*norm, finalY*norm, finalZ*norm);
+      fParticleChange->SetProposedKineticEnergy(finalEnergy);
+    }
+
+  //Generate the bremsstrahlung gamma
+  G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
+						    gammaDirection, tGamma);
+  fvect->push_back(aGamma);
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Energy balance from G4LivermoreBremsstrahlung" << G4endl;
+      G4cout << "Incoming primary energy: " << kineticEnergy/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Outgoing primary energy: " << finalEnergy/keV << " keV" << G4endl;
+      G4cout << "Gamma ray " << tGamma/keV << " keV" << G4endl;
+      G4cout << "Total final state: " << (finalEnergy+tGamma)/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+    }
+  if (verboseLevel > 0)
+    {
+      G4double energyDiff = std::fabs(finalEnergy+tGamma-kineticEnergy);
+      if (energyDiff > 0.05*keV)
+	G4cout << "G4LivermoreBremsstrahlung WARNING: problem with energy conservation: " 
+	       << (finalEnergy+tGamma)/keV << " keV (final) vs. " 
+	       << kineticEnergy/keV << " keV (initial)" << G4endl;
+    }
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void 
+G4LivermoreBremsstrahlungModel::SetAngularGenerator(G4VBremAngularDistribution* distribution)
+{
+  if(angularDistribution == distribution) return;
+  if(angularDistribution) delete angularDistribution;
+  angularDistribution = distribution;
+  angularDistribution->PrintGeneratorInformation();
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreBremsstrahlungModel::SetAngularGenerator(const G4String& name)
+{
+  if(name == generatorName) return;
+  if (name == "tsai") 
+    {
+      delete angularDistribution;
+      angularDistribution = new G4ModifiedTsai("TsaiGenerator");
+      generatorName = name;
+    }
+  else if (name == "2bn")
+    {
+      delete angularDistribution;
+      angularDistribution = new G4Generator2BN("2BNGenerator");
+      generatorName = name;
+    }
+  else if (name == "2bs")
+    {
+      delete angularDistribution;
+      angularDistribution = new G4Generator2BS("2BSGenerator");
+      generatorName = name;
+    }
+  else
+    {
+      G4cout << "### G4LivermoreBremsstrahlungModel::SetAngularGenerator WARNING:"
+	     << " generator <" << name << "> is not known" << G4endl;
+      return; 
+
+    }
+
+  angularDistribution->PrintGeneratorInformation();
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4LivermoreIonisationModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4LivermoreIonisationModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4LivermoreIonisationModel.cc	(revision 1058)
@@ -0,0 +1,665 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4LivermoreIonisationModel.cc,v 1.4 2009/05/19 14:57:01 pandola Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 12 Jan 2009   L Pandola    Migration from process to model 
+// 03 Mar 2009   L Pandola    Bug fix (release memory in the destructor)
+// 15 Apr 2009   V Ivanchenko Cleanup initialisation and generation of secondaries:
+//                  - apply internal high-energy limit only in constructor 
+//                  - do not apply low-energy limit (default is 0)
+//                  - simplify sampling of deexcitation by using cut in energy
+//                  - set activation of Auger "false"
+//                  - remove initialisation of element selectors
+// 19 May 2009   L Pandola    Explicitely set to zero pointers deleted in 
+//                            Initialise(), since they might be checked later on
+//
+
+#include "G4LivermoreIonisationModel.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4MaterialCutsCouple.hh"
+#include "G4ProductionCutsTable.hh"
+#include "G4DynamicParticle.hh"
+#include "G4Element.hh"
+#include "G4AtomicTransitionManager.hh"
+#include "G4AtomicDeexcitation.hh"
+#include "G4AtomicShell.hh"
+#include "G4Gamma.hh"
+#include "G4Electron.hh"
+#include "G4CrossSectionHandler.hh"
+#include "G4AtomicDeexcitation.hh"
+#include "G4ProcessManager.hh"
+#include "G4VEMDataSet.hh"
+#include "G4EMDataSet.hh"
+#include "G4eIonisationCrossSectionHandler.hh"
+#include "G4eIonisationSpectrum.hh"
+#include "G4VDataSetAlgorithm.hh"
+#include "G4SemiLogInterpolation.hh"
+#include "G4ShellVacancy.hh"
+#include "G4VDataSetAlgorithm.hh"
+#include "G4LogLogInterpolation.hh"
+#include "G4CompositeEMDataSet.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4LivermoreIonisationModel::G4LivermoreIonisationModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+  :G4VEmModel(nam),isInitialised(false),crossSectionHandler(0),
+   energySpectrum(0),shellVacancy(0)
+{
+  fIntrinsicLowEnergyLimit = 10.0*eV;
+  fIntrinsicHighEnergyLimit = 100.0*GeV;
+  fNBinEnergyLoss = 360;
+  //  SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
+  SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
+  //
+  verboseLevel = 0;
+  //
+  fUseAtomicDeexcitation = true;
+  ActivateAuger(false);
+  //
+  // Notice: the fluorescence along step is generated only if it is 
+  // set by the PROCESS (e.g. G4eIonisation) via the command
+  // process->ActivateDeexcitation(true);
+  //  
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4LivermoreIonisationModel::~G4LivermoreIonisationModel()
+{
+  if (energySpectrum) delete energySpectrum;
+  if (crossSectionHandler) delete crossSectionHandler;
+  if (shellVacancy) delete shellVacancy;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreIonisationModel::Initialise(const G4ParticleDefinition* particle,
+					    const G4DataVector& cuts)
+{
+  //Check that the Livermore Ionisation is NOT attached to e+
+  if (particle != G4Electron::Electron())
+    {
+      G4cout << "ERROR: Livermore Ionisation Model is applicable only to electrons" << G4endl;
+      G4cout << "It cannot be registered to " << particle->GetParticleName() << G4endl;
+      G4Exception();
+    }
+
+  //Read energy spectrum
+  if (energySpectrum) 
+    {
+      delete energySpectrum;
+      energySpectrum = 0;
+    }
+  energySpectrum = new G4eIonisationSpectrum();
+  if (verboseLevel > 0)
+    G4cout << "G4VEnergySpectrum is initialized" << G4endl;
+
+  //Initialize cross section handler
+  if (crossSectionHandler) 
+    {
+      delete crossSectionHandler;
+      crossSectionHandler = 0;
+    }
+
+  G4VDataSetAlgorithm* interpolation = new G4SemiLogInterpolation();
+  crossSectionHandler = new G4eIonisationCrossSectionHandler(energySpectrum,interpolation,
+							     LowEnergyLimit(),HighEnergyLimit(),
+							     fNBinEnergyLoss);
+  crossSectionHandler->Clear();
+  crossSectionHandler->LoadShellData("ioni/ion-ss-cs-");
+  //This is used to retrieve cross section values later on
+  crossSectionHandler->BuildMeanFreePathForMaterials(&cuts);
+  
+  //Fluorescence data
+  transitionManager = G4AtomicTransitionManager::Instance();
+  if (shellVacancy) delete shellVacancy;
+  shellVacancy = new G4ShellVacancy();
+  InitialiseFluorescence();
+
+  if (verboseLevel > 0)
+    {
+      G4cout << "Livermore Ionisation model is initialized " << G4endl
+	     << "Energy range: "
+	     << LowEnergyLimit() / keV << " keV - "
+	     << HighEnergyLimit() / GeV << " GeV"
+	     << G4endl;
+    }
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "Cross section data: " << G4endl; 
+      crossSectionHandler->PrintData();
+      G4cout << "Parameters: " << G4endl;
+      energySpectrum->PrintData();
+    }
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForLoss();
+  isInitialised = true; 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4LivermoreIonisationModel::MinEnergyCut(const G4ParticleDefinition*,
+						  const G4MaterialCutsCouple*)
+{
+  return 250.*eV;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4LivermoreIonisationModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+								G4double energy,
+								G4double Z, G4double,
+								G4double cutEnergy, 
+								G4double)
+{
+  G4int iZ = (G4int) Z;
+  if (!crossSectionHandler)
+    {
+      G4cout << "G4LivermoreIonisationModel::ComputeCrossSectionPerAtom" << G4endl;
+      G4cout << "The cross section handler is not correctly initialized" << G4endl;
+      G4Exception();
+    }
+  
+  //The cut is already included in the crossSectionHandler
+  G4double cs = 
+    crossSectionHandler->GetCrossSectionAboveThresholdForElement(energy,cutEnergy,iZ);
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "G4LivermoreIonisationModel " << G4endl;
+      G4cout << "Cross section for delta emission > " << cutEnergy/keV << " keV at " <<
+	energy/keV << " keV and Z = " << iZ << " --> " << cs/barn << " barn" << G4endl;
+    }
+  return cs;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4LivermoreIonisationModel::ComputeDEDXPerVolume(const G4Material* material,
+							  const G4ParticleDefinition* ,
+							  G4double kineticEnergy,
+							  G4double cutEnergy)
+{
+  G4double sPower = 0.0;
+
+  const G4ElementVector* theElementVector = material->GetElementVector();
+  size_t NumberOfElements = material->GetNumberOfElements() ;
+  const G4double* theAtomicNumDensityVector =
+                    material->GetAtomicNumDensityVector();
+
+  // loop for elements in the material
+  for (size_t iel=0; iel<NumberOfElements; iel++ ) 
+    {
+      G4int iZ = (G4int)((*theElementVector)[iel]->GetZ());
+      G4int nShells = transitionManager->NumberOfShells(iZ);
+      for (G4int n=0; n<nShells; n++) 
+	{
+	  G4double e = energySpectrum->AverageEnergy(iZ, 0.0,cutEnergy,
+						     kineticEnergy, n);
+	  G4double cs= crossSectionHandler->FindValue(iZ,kineticEnergy, n);
+	  sPower   += e * cs * theAtomicNumDensityVector[iel];
+	}
+      G4double esp = energySpectrum->Excitation(iZ,kineticEnergy);
+      sPower   += esp * theAtomicNumDensityVector[iel];
+    }
+
+  if (verboseLevel > 2)
+    {
+      G4cout << "G4LivermoreIonisationModel " << G4endl;
+      G4cout << "Stopping power < " << cutEnergy/keV << " keV at " << 
+	kineticEnergy/keV << " keV = " << sPower/(keV/mm) << " keV/mm" << G4endl;
+    }
+  
+  return sPower;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+						   const G4MaterialCutsCouple* couple,
+						   const G4DynamicParticle* aDynamicParticle,
+						   G4double cutE,
+						   G4double maxE)
+{
+  
+  G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
+
+  if (kineticEnergy <= fIntrinsicLowEnergyLimit)
+    {
+      fParticleChange->SetProposedKineticEnergy(0.);
+      fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy);
+      return ;
+    }
+
+   // Select atom and shell
+  G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
+  G4int shell = crossSectionHandler->SelectRandomShell(Z, kineticEnergy);
+  const G4AtomicShell* atomicShell =
+                (G4AtomicTransitionManager::Instance())->Shell(Z, shell);
+  G4double bindingEnergy = atomicShell->BindingEnergy();
+  G4int shellId = atomicShell->ShellId();
+
+  // Sample delta energy using energy interval for delta-electrons 
+  G4double energyMax = 
+    std::min(maxE,energySpectrum->MaxEnergyOfSecondaries(kineticEnergy));
+  G4double energyDelta = energySpectrum->SampleEnergy(Z, cutE, energyMax,
+						      kineticEnergy, shell);
+
+  if (energyDelta == 0.) //nothing happens
+    return;
+
+  // Transform to shell potential
+  G4double deltaKinE = energyDelta + 2.0*bindingEnergy;
+  G4double primaryKinE = kineticEnergy + 2.0*bindingEnergy;
+
+  // sampling of scattering angle neglecting atomic motion
+  G4double deltaMom = std::sqrt(deltaKinE*(deltaKinE + 2.0*electron_mass_c2));
+  G4double primaryMom = std::sqrt(primaryKinE*(primaryKinE + 2.0*electron_mass_c2));
+
+  G4double cost = deltaKinE * (primaryKinE + 2.0*electron_mass_c2)
+                            / (deltaMom * primaryMom);
+  if (cost > 1.) cost = 1.;
+  G4double sint = std::sqrt(1. - cost*cost);
+  G4double phi  = twopi * G4UniformRand();
+  G4double dirx = sint * std::cos(phi);
+  G4double diry = sint * std::sin(phi);
+  G4double dirz = cost;
+  
+  // Rotate to incident electron direction
+  G4ThreeVector primaryDirection = aDynamicParticle->GetMomentumDirection();
+  G4ThreeVector deltaDir(dirx,diry,dirz);
+  deltaDir.rotateUz(primaryDirection);
+  //Updated components
+  dirx = deltaDir.x();
+  diry = deltaDir.y();
+  dirz = deltaDir.z();
+
+  // Take into account atomic motion del is relative momentum of the motion
+  // kinetic energy of the motion == bindingEnergy in V.Ivanchenko model
+  cost = 2.0*G4UniformRand() - 1.0;
+  sint = std::sqrt(1. - cost*cost);
+  phi  = twopi * G4UniformRand();
+  G4double del = std::sqrt(bindingEnergy *(bindingEnergy + 2.0*electron_mass_c2))
+               / deltaMom;
+  dirx += del* sint * std::cos(phi);
+  diry += del* sint * std::sin(phi);
+  dirz += del* cost;
+
+  // Find out new primary electron direction
+  G4double finalPx = primaryMom*primaryDirection.x() - deltaMom*dirx;
+  G4double finalPy = primaryMom*primaryDirection.y() - deltaMom*diry;
+  G4double finalPz = primaryMom*primaryDirection.z() - deltaMom*dirz;
+
+  //Ok, ready to create the delta ray
+  G4DynamicParticle* theDeltaRay = new G4DynamicParticle();
+  theDeltaRay->SetKineticEnergy(energyDelta);
+  G4double norm = 1.0/std::sqrt(dirx*dirx + diry*diry + dirz*dirz);
+  dirx *= norm;
+  diry *= norm;
+  dirz *= norm;
+  theDeltaRay->SetMomentumDirection(dirx, diry, dirz);
+  theDeltaRay->SetDefinition(G4Electron::Electron());
+  fvect->push_back(theDeltaRay);
+
+  //This is the amount of energy available for fluorescence
+  G4double theEnergyDeposit = bindingEnergy;
+
+  // fill ParticleChange
+  // changed energy and momentum of the actual particle
+  G4double finalKinEnergy = kineticEnergy - energyDelta - theEnergyDeposit;
+  if(finalKinEnergy < 0.0) 
+    {
+      theEnergyDeposit += finalKinEnergy;
+      finalKinEnergy    = 0.0;
+    } 
+  else 
+    {
+      G4double norm = 1.0/std::sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
+      finalPx *= norm;
+      finalPy *= norm;
+      finalPz *= norm;
+      fParticleChange->ProposeMomentumDirection(finalPx, finalPy, finalPz);
+    }
+  fParticleChange->SetProposedKineticEnergy(finalKinEnergy);
+
+  // deexcitation may be active per G4Region
+  if(DeexcitationFlag() && Z > 5) 
+    {
+      G4ProductionCutsTable* theCoupleTable = 
+	G4ProductionCutsTable::GetProductionCutsTable();
+      // Retrieve cuts for gammas
+      G4double cutG = (*theCoupleTable->GetEnergyCutsVector(0))[couple->GetIndex()];
+      if(theEnergyDeposit > cutG || theEnergyDeposit > cutE) 
+	{
+	  deexcitationManager.SetCutForSecondaryPhotons(cutG);
+	  deexcitationManager.SetCutForAugerElectrons(cutE);
+	  std::vector<G4DynamicParticle*>* secondaryVector = 
+	    deexcitationManager.GenerateParticles(Z, shellId);
+	  G4DynamicParticle* aSecondary;
+
+	  if (secondaryVector) 
+	    {
+	      for (size_t i = 0; i<secondaryVector->size(); i++) 
+		{
+		  aSecondary = (*secondaryVector)[i];
+		  //Check if it is a valid secondary
+		  if (aSecondary) 
+		    {
+		      G4double e = aSecondary->GetKineticEnergy();
+		      if (e < theEnergyDeposit) 
+			{		      
+			  theEnergyDeposit -= e;
+			  fvect->push_back(aSecondary);
+			} 
+		      else 
+			{
+			  delete aSecondary;
+			  (*secondaryVector)[i] = 0;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  if (theEnergyDeposit < 0)
+    {
+      G4cout <<  "G4LivermoreIonisationModel: Negative energy deposit: "
+	     << theEnergyDeposit/eV << " eV" << G4endl;
+      theEnergyDeposit = 0.0;
+    }
+
+  //Assign local energy deposit
+  fParticleChange->ProposeLocalEnergyDeposit(theEnergyDeposit);
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Energy balance from G4LivermoreIonisation" << G4endl;
+      G4cout << "Incoming primary energy: " << kineticEnergy/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Outgoing primary energy: " << finalKinEnergy/keV << " keV" << G4endl;
+      G4cout << "Delta ray " << energyDelta/keV << " keV" << G4endl;
+      G4cout << "Fluorescence: " << (bindingEnergy-theEnergyDeposit)/keV << " keV" << G4endl;
+      G4cout << "Local energy deposit " << theEnergyDeposit/keV << " keV" << G4endl;
+      G4cout << "Total final state: " << (finalKinEnergy+energyDelta+bindingEnergy+
+					  theEnergyDeposit)/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+    }
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* theMaterial,
+							     const G4Track& theTrack,
+							     G4double& eloss)
+{
+  //No call if there is no deexcitation along step
+  if (!DeexcitationFlag()) return;
+
+  //This method gets the energy loss calculated "Along the Step" and 
+  //(including fluctuations) and produces explicit fluorescence/Auger 
+  //secondaries. The eloss value is updated.
+  G4double energyLossBefore = eloss;
+  if (verboseLevel > 2)
+    G4cout << "Energy loss along step before deexcitation : " << energyLossBefore/keV << 
+      " keV" << G4endl;
+
+  G4double incidentEnergy = theTrack.GetDynamicParticle()->GetKineticEnergy();
+
+  G4ProductionCutsTable* theCoupleTable = 
+    G4ProductionCutsTable::GetProductionCutsTable();
+  const G4MaterialCutsCouple* couple = theTrack.GetMaterialCutsCouple();
+  size_t index = couple->GetIndex();
+  G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
+  G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
+  
+  //Notice: in LowEnergyIonisation, fluorescence is always generated above 250 eV
+  //not above the tracking cut.
+  //G4double cutForLowEnergySecondaryParticles = 250.0*eV;
+
+  std::vector<G4DynamicParticle*>* deexcitationProducts =
+    new std::vector<G4DynamicParticle*>;
+
+  if(eloss > cute || eloss > cutg)
+    {
+      const G4AtomicTransitionManager* transitionManager =
+	G4AtomicTransitionManager::Instance();
+      deexcitationManager.SetCutForSecondaryPhotons(cutg);
+      deexcitationManager.SetCutForAugerElectrons(cute);
+      
+      size_t nElements = theMaterial->GetNumberOfElements();
+      const G4ElementVector* theElementVector = theMaterial->GetElementVector();
+
+      std::vector<G4DynamicParticle*>* secVector = 0;
+      G4DynamicParticle* aSecondary = 0;
+      //G4ParticleDefinition* type = 0;
+      G4double e;
+      G4ThreeVector position;
+      G4int shell, shellId;
+
+      // sample secondaries  
+      G4double eTot = 0.0;
+      std::vector<G4int> n =
+	shellVacancy->GenerateNumberOfIonisations(couple,
+						  incidentEnergy,eloss);
+      for (size_t i=0; i<nElements; i++) 
+	{
+	  G4int Z = (G4int)((*theElementVector)[i]->GetZ());
+	  size_t nVacancies = n[i];
+	  G4double maxE = transitionManager->Shell(Z, 0)->BindingEnergy();
+	  if (nVacancies > 0 && Z > 5 && (maxE > cute || maxE > cutg))
+	    {     
+	      for (size_t j=0; j<nVacancies; j++) 
+		{
+		  shell = crossSectionHandler->SelectRandomShell(Z, incidentEnergy);
+		  shellId = transitionManager->Shell(Z, shell)->ShellId();
+		  G4double maxEShell =
+		    transitionManager->Shell(Z, shell)->BindingEnergy();
+		  if (maxEShell > cute || maxEShell > cutg ) 
+		    {
+		      secVector = deexcitationManager.GenerateParticles(Z, shellId);
+		      if (secVector) 
+			{
+			  for (size_t l = 0; l<secVector->size(); l++) {
+			    aSecondary = (*secVector)[l];
+			    if (aSecondary) 
+			      {
+				e = aSecondary->GetKineticEnergy();
+				if ( eTot + e <= eloss )
+				  {
+				    eTot += e;
+				    deexcitationProducts->push_back(aSecondary);
+				  } 
+				else
+				  { 
+				    delete aSecondary;
+				  }
+			      }
+			  }
+			  delete secVector;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  size_t nSecondaries = deexcitationProducts->size();
+  if (nSecondaries > 0) 
+    {
+      fParticleChange->SetNumberOfSecondaries(nSecondaries);
+      const G4StepPoint* preStep = theTrack.GetStep()->GetPreStepPoint();
+      const G4StepPoint* postStep = theTrack.GetStep()->GetPostStepPoint();
+      G4ThreeVector r = preStep->GetPosition();
+      G4ThreeVector deltaR = postStep->GetPosition();
+      deltaR -= r;
+      G4double t = preStep->GetGlobalTime();
+      G4double deltaT = postStep->GetGlobalTime();
+      deltaT -= t;
+      G4double time, q;
+      G4ThreeVector position;
+      
+      for (size_t i=0; i<nSecondaries; i++) 
+	{
+	  G4DynamicParticle* part = (*deexcitationProducts)[i];
+	  if (part) 
+	    {
+	      G4double eSecondary = part->GetKineticEnergy();
+	      eloss -= eSecondary;
+	      if (eloss > 0.)
+		{
+		  q = G4UniformRand();
+		  time = deltaT*q + t;
+		  position  = deltaR*q;
+		  position += r;
+		  G4Track* newTrack = new G4Track(part, time, position);
+		  pParticleChange->AddSecondary(newTrack);
+		}
+	      else
+		{
+		  eloss += eSecondary;
+		  delete part;
+		  part = 0;
+		}
+	    }
+	}
+    }
+  delete deexcitationProducts;
+  
+  if (verboseLevel > 2)
+    G4cout << "Energy loss along step after deexcitation : " << eloss/keV <<  
+      " keV" << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreIonisationModel::InitialiseFluorescence()
+{
+  G4DataVector* ksi = 0;
+  G4DataVector* energyVector = 0;
+  size_t binForFluo = fNBinEnergyLoss/10;
+
+  G4PhysicsLogVector* eVector = new G4PhysicsLogVector(LowEnergyLimit(),HighEnergyLimit(),
+						       binForFluo);
+  const G4ProductionCutsTable* theCoupleTable=
+    G4ProductionCutsTable::GetProductionCutsTable();
+  size_t numOfCouples = theCoupleTable->GetTableSize();
+
+  // Loop on couples
+  for (size_t m=0; m<numOfCouples; m++) 
+    {
+       const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(m);
+       const G4Material* material= couple->GetMaterial();
+
+       const G4ElementVector* theElementVector = material->GetElementVector();
+       size_t NumberOfElements = material->GetNumberOfElements() ;
+       const G4double* theAtomicNumDensityVector =
+	 material->GetAtomicNumDensityVector();
+
+       G4VDataSetAlgorithm* interp = new G4LogLogInterpolation();
+       G4VEMDataSet* xsis = new G4CompositeEMDataSet(interp, 1., 1.);
+       //loop on elements
+       G4double energyCut = (*(theCoupleTable->GetEnergyCutsVector(1)))[m];
+       for (size_t iel=0; iel<NumberOfElements; iel++ ) 
+	 {
+	   G4int iZ = (G4int)((*theElementVector)[iel]->GetZ());
+	   energyVector = new G4DataVector();
+	   ksi    = new G4DataVector();
+	   //Loop on energy
+	   for (size_t j = 0; j<binForFluo; j++) 
+	     {
+	       G4double energy = eVector->GetLowEdgeEnergy(j);
+	       G4double cross   = 0.;
+	       G4double eAverage= 0.;
+	       G4int nShells = transitionManager->NumberOfShells(iZ);
+
+	       for (G4int n=0; n<nShells; n++) 
+		 {
+		   G4double e = energySpectrum->AverageEnergy(iZ, 0.0,energyCut,
+							      energy, n);
+		   G4double pro = energySpectrum->Probability(iZ, 0.0,energyCut,
+							      energy, n);
+		   G4double cs= crossSectionHandler->FindValue(iZ, energy, n);
+		   eAverage   += e * cs * theAtomicNumDensityVector[iel];
+		   cross      += cs * pro * theAtomicNumDensityVector[iel];
+		   if(verboseLevel > 1) 
+		     {
+		       G4cout << "Z= " << iZ
+			    << " shell= " << n
+			    << " E(keV)= " << energy/keV
+			    << " Eav(keV)= " << e/keV
+			    << " pro= " << pro
+			    << " cs= " << cs
+			    << G4endl;
+		     }
+		 }
+	       
+	       G4double coeff = 0.0;
+	       if(eAverage > 0.) 
+		 {
+		   coeff = cross/eAverage;
+		   eAverage /= cross;
+		 }
+	       
+	       if(verboseLevel > 1) 
+		 {
+		   G4cout << "Ksi Coefficient for Z= " << iZ
+			  << " E(keV)= " << energy/keV
+			  << " Eav(keV)= " << eAverage/keV
+			  << " coeff= " << coeff
+			  << G4endl;
+		 }	       
+	       energyVector->push_back(energy);
+	       ksi->push_back(coeff);
+	     }
+	   G4VEMDataSet* p = new G4EMDataSet(iZ,energyVector,ksi,interp,1.,1.);
+	   xsis->AddComponent(p);
+	 }
+       if(verboseLevel>0) xsis->PrintData();
+       shellVacancy->AddXsiTable(xsis);
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4LivermoreIonisationModel::ActivateAuger(G4bool val)
+{
+  deexcitationManager.ActivateAugerElectronProduction(val);
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeBremsstrahlungModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeBremsstrahlungModel.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeBremsstrahlungModel.cc	(revision 1058)
@@ -0,0 +1,500 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4PenelopeBremsstrahlungModel.cc,v 1.5 2009/05/14 10:56:09 pandola Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+// Author: Luciano Pandola
+// --------
+// 05 Dec 2008   L Pandola    Migration from process to model
+// 25 Mar 2008   L Pandola    Fixed .unit() call
+// 16 Apr 2009   V Ivanchenko Cleanup initialisation and generation of secondaries:
+//                  - apply internal high-energy limit only in constructor 
+//                  - do not apply low-energy limit (default is 0)
+//                  - added MinEnergyCut method
+//                  - do not change track status
+// 14 May 2009   L Pandola    Explicitely set to zero pointers deleted in 
+//                            Initialise(), since they are checked later on
+//
+#include "G4PenelopeBremsstrahlungModel.hh"
+#include "G4PenelopeBremsstrahlungContinuous.hh"
+#include "G4PenelopeBremsstrahlungAngular.hh"
+#include "G4eBremsstrahlungSpectrum.hh"
+#include "G4CrossSectionHandler.hh"
+#include "G4VEMDataSet.hh"
+#include "G4DataVector.hh"
+#include "G4Positron.hh"
+#include "G4Electron.hh"
+#include "G4Gamma.hh"
+#include "G4MaterialCutsCouple.hh"
+#include "G4LogLogInterpolation.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeBremsstrahlungModel::G4PenelopeBremsstrahlungModel(const G4ParticleDefinition*,
+							     const G4String& nam)
+  :G4VEmModel(nam),isInitialised(false),energySpectrum(0),
+   angularData(0),stoppingPowerData(0),crossSectionHandler(0)
+{
+  fIntrinsicLowEnergyLimit = 100.0*eV;
+  fIntrinsicHighEnergyLimit = 100.0*GeV;
+  //  SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
+  SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
+  //
+  
+  verboseLevel= 0;
+   
+  // Verbosity scale:
+  // 0 = nothing
+  // 1 = warning for energy non-conservation
+  // 2 = details of energy budget
+  // 3 = calculation of cross sections, file openings, sampling of atoms
+  // 4 = entering in methods
+   
+  //These vectors do not change when materials or cut change.
+  //Therefore I can read it at the constructor
+  angularData = new std::map<G4int,G4PenelopeBremsstrahlungAngular*>;
+ 
+  //These data do not depend on materials and cuts.
+  G4DataVector eBins;
+ 
+  eBins.push_back(1.0e-12);
+  eBins.push_back(0.05);
+  eBins.push_back(0.075);
+  eBins.push_back(0.1);
+  eBins.push_back(0.125);
+  eBins.push_back(0.15);
+  eBins.push_back(0.2);
+  eBins.push_back(0.25);
+  eBins.push_back(0.3);
+  eBins.push_back(0.35);
+  eBins.push_back(0.40);
+  eBins.push_back(0.45);
+  eBins.push_back(0.50);
+  eBins.push_back(0.55);
+  eBins.push_back(0.60);
+  eBins.push_back(0.65);
+  eBins.push_back(0.70);
+  eBins.push_back(0.75);
+  eBins.push_back(0.80);
+  eBins.push_back(0.85);
+  eBins.push_back(0.90);
+  eBins.push_back(0.925);
+  eBins.push_back(0.95);
+  eBins.push_back(0.97);
+  eBins.push_back(0.99);
+  eBins.push_back(0.995);
+  eBins.push_back(0.999);
+  eBins.push_back(0.9995);
+  eBins.push_back(0.9999);
+  eBins.push_back(0.99995);
+  eBins.push_back(0.99999);
+  eBins.push_back(1.0);
+ 
+  const G4String dataName("/penelope/br-sp-pen.dat");
+  energySpectrum = new G4eBremsstrahlungSpectrum(eBins,dataName);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeBremsstrahlungModel::~G4PenelopeBremsstrahlungModel()
+{
+  if (crossSectionHandler)
+    delete crossSectionHandler;
+  
+  if (energySpectrum) 
+    delete energySpectrum;
+  
+  if (angularData)
+    {
+      std::map <G4int,G4PenelopeBremsstrahlungAngular*>::iterator i;
+      for (i=angularData->begin();i != angularData->end();i++)
+	if (i->second) delete i->second;
+      delete angularData;
+    }
+  
+  if (stoppingPowerData)
+    {
+      std::map <std::pair<G4int,G4double>,G4PenelopeBremsstrahlungContinuous*>::iterator j;
+      for (j=stoppingPowerData->begin();j != stoppingPowerData->end();j++)
+	if (j->second) delete j->second;
+      delete stoppingPowerData;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeBremsstrahlungModel::Initialise(const G4ParticleDefinition* particle,
+					       const G4DataVector& cuts)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling G4PenelopeBremsstrahlungModel::Initialise()" << G4endl;
+  
+  // Delete everything, but angular data (do not depend on cuts)
+  if (crossSectionHandler)
+    {
+      crossSectionHandler->Clear();
+      delete crossSectionHandler;
+      crossSectionHandler = 0;
+    }
+
+  if (stoppingPowerData)
+    {
+      std::map <std::pair<G4int,G4double>,G4PenelopeBremsstrahlungContinuous*>::iterator j;
+      for (j=stoppingPowerData->begin();j != stoppingPowerData->end();j++)
+	if (j->second) 
+	  { 
+	    delete j->second;
+	    j->second = 0;
+	  }
+      delete stoppingPowerData;
+      stoppingPowerData = 0;
+    }
+  
+  crossSectionHandler = new G4CrossSectionHandler();
+  crossSectionHandler->Clear();
+  //
+  if (particle==G4Electron::Electron())
+      crossSectionHandler->LoadData("brem/br-cs-");
+  else
+    crossSectionHandler->LoadData("penelope/br-cs-pos-"); //cross section for positrons
+    
+  //This is used to retrieve cross section values later on
+  crossSectionHandler->BuildMeanFreePathForMaterials();
+   
+  if (verboseLevel > 2)
+    G4cout << "Loaded cross section files for PenelopeBremsstrahlungModel" << G4endl;
+  
+  if (verboseLevel > 0) {
+    G4cout << "Penelope Bremsstrahlung model is initialized " << G4endl
+	   << "Energy range: "
+	   << LowEnergyLimit() / keV << " keV - "
+	   << HighEnergyLimit() / GeV << " GeV"
+	   << G4endl;
+  } 
+
+  //This has to be invoked AFTER the crossSectionHandler has been created, 
+  //because it makes use of ComputeCrossSectionPerAtom()
+  InitialiseElementSelectors(particle,cuts);
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForLoss();
+  isInitialised = true;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4PenelopeBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
+						     const G4MaterialCutsCouple*)
+{
+  return 250.*eV;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4PenelopeBremsstrahlungModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+								   G4double kinEnergy,
+								   G4double Z,
+								   G4double,
+								   G4double cutEnergy,
+								   G4double)
+{
+  // Penelope model to calculate cross section for hard bremsstrahlung emission 
+  // (gamma energy > cutEnergy).
+  //
+  // The total bremsstrahlung cross section is read from database, following data 
+  // reported in the EEDL library
+  //  D.E.Cullen et al., Report UCRL-50400 (Lawrence Livermore National Laboratory) (1989)
+  // The probability to have photon emission above a given threshold is calculated 
+  // analytically using the differential cross section model dSigma/dW = F(x)/x, where 
+  // W is the outgoing photon energy and x = W/E is the ratio of the photon energy to the 
+  // incident energy. The function F(x) is tabulated (for all elements) using 32 points in x 
+  // ranging from 1e-12 to 1. Data are derived from 
+  //  S.M.Seltzer and M.J.Berger, At.Data Nucl.Data Tables 35,345 (1986)
+  // Differential cross sections for electrons and positrons dSigma/dW are assumed to scale 
+  // with a function S(Z,E) which does not depend on W; therefore, only overall cross section 
+  // changes but not the shape of the photon energy spectrum.
+  //
+
+  if (verboseLevel > 3)
+    G4cout << "Calling ComputeCrossSectionPerAtom() of G4PenelopeBremsstrahlungModel" << G4endl;
+  
+  G4int iZ = (G4int) Z;
+
+  // VI - not needed in run time
+  // if (!crossSectionHandler)
+  //  {
+  //    G4cout << "G4PenelopeBremsstrahlungModel::ComputeCrossSectionPerAtom" << G4endl;
+  //    G4cout << "The cross section handler is not correctly initialized" << G4endl;
+  //    G4Exception();
+  //  }
+  G4double totalCs = crossSectionHandler->FindValue(iZ,kinEnergy);
+  G4double cs = totalCs * energySpectrum->Probability(iZ,cutEnergy,kinEnergy,kinEnergy);
+
+  if (verboseLevel > 2)
+    {
+      G4cout << "Bremsstrahlung cross section at " << kinEnergy/MeV << " MeV for Z=" << Z <<
+	" and energy > " << cutEnergy/keV << " keV --> " << cs/barn << " barn" << G4endl;
+      G4cout << "Total bremsstrahlung cross section at " << kinEnergy/MeV << " MeV for Z=" << 
+      Z << " --> " << totalCs/barn << " barn" << G4endl;
+    }
+  return cs;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+G4double 
+G4PenelopeBremsstrahlungModel::ComputeDEDXPerVolume(const G4Material* theMaterial,
+						    const G4ParticleDefinition* theParticle,
+						    G4double kineticEnergy,
+						    G4double cutEnergy)
+{
+  // Penelope model to calculate the stopping power (in [Energy]/[Length]) for soft 
+  // bremsstrahlung emission (gamma energy < cutEnergy).
+  //
+  // The actual calculation is performed by the helper class 
+  // G4PenelopeBremsstrahlungContinuous and its method CalculateStopping(). Notice:
+  // CalculateStopping() gives the stopping cross section, namely the first momentum of 
+  // dSigma/dW, restricted to W < cut (W = gamma energy) This is dimensionally:
+  //  [Energy]*[Surface]
+  // The calculation is performed by interpolation (in E = incident energy and 
+  // x=W/E) from the tabulated data derived from
+  //  M.J.Berger and S.M.Seltzer, Report NBSIR 82-2550 (National Bureau of Standards) (1982);
+  // for electrons.
+  // For positrons, dSigma/dW are assumed to scale with a function S(Z,E) with respect to electrons. 
+  // An analytical approximation for the scaling function S(Z,E) is given in
+  //  L.Kim et al., Phys.Rev.A 33,3002 (1986)
+  //
+  if (!stoppingPowerData)
+    stoppingPowerData = new std::map<std::pair<G4int,G4double>,
+      G4PenelopeBremsstrahlungContinuous*>;
+  
+  const G4ElementVector* theElementVector = theMaterial->GetElementVector();
+  const G4double* theAtomicNumDensityVector = theMaterial->GetAtomicNumDensityVector();
+
+  G4double sPower = 0.0;
+
+  //Loop on the elements of the material
+  for (size_t iel=0;iel<theMaterial->GetNumberOfElements();iel++)
+    {
+      G4int iZ = (G4int) ((*theElementVector)[iel]->GetZ());
+      G4PenelopeBremsstrahlungContinuous* theContinuousCalculator = 
+	GetStoppingPowerData(iZ,cutEnergy,theParticle);
+      sPower += theContinuousCalculator->CalculateStopping(kineticEnergy)*
+	theAtomicNumDensityVector[iel];
+    }
+  
+   if (verboseLevel > 2)
+    {
+      G4cout << "Bremsstrahlung stopping power at " << kineticEnergy/MeV 
+	     << " MeV for material " << theMaterial->GetName() 
+	     << " and energy < " << cutEnergy/keV << " keV --> " 
+	     << sPower/(keV/mm) << " keV/mm" << G4endl;
+    }
+
+  return sPower;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+						      const G4MaterialCutsCouple* couple,
+						      const G4DynamicParticle* aDynamicParticle,
+						      G4double cutG,G4double)
+{
+  // Penelope model to sample the final state for hard bremsstrahlung emission 
+  // (gamma energy < cutEnergy).
+  // The energy distributionof the emitted photons is sampled according to the F(x) 
+  // function tabulated in the database from 
+  //  S.M.Seltzer and M.J.Berger, At.Data Nucl.Data Tables 35,345 (1986)
+  // The database contains the function F(x) (32 points) for 57 energies of the
+  // incident electron between 1 keV and 100 GeV. For other primary energies,
+  // logarithmic interpolation is used to obtain the values of the function F(x).
+  // The double differential cross section dSigma/(dW dOmega), with W=photon energy,
+  // is described as 
+  //  dSigma/(dW dOmega) = dSigma/dW * p(Z,E,x,cosTheta)
+  // where the shape function p depends on atomic number, incident energy and x=W/E.
+  // Numerical values of the shape function, calculated by partial-waves methods, have been 
+  // reported in 
+  //  L.Kissel et al., At.Data Nucl.Data.Tab. 28,381 (1983); 
+  // for Z=2,8,13,47,79 and 92; E=1,5,10,50,100 and 500 keV; x=0,0.6,0.8 and 0.95. The 
+  // function p(Z,E,x,cosTheta) is approximated by a Lorentz-dipole function as reported in 
+  //  Penelope - A Code System for Monte Carlo Simulation of Electron and Photon Transport, 
+  //  Workshop Proceedings Issy-les-Moulineaux, France, 5-7 November 2001, AEN-NEA;
+  // The analytical function contains two adjustable parameters that are obtained by fitting 
+  // the complete solution from 
+  //  L.Kissel et al., At.Data Nucl.Data.Tab. 28,381 (1983); 
+  // This allows the evaluation of p(Z,E,x,cosTheta) for any choice of Z, E and x. The actual 
+  // sampling of cos(theta) is performed in the helper class
+  //  G4PenelopeBremsstrahlungAngular, method ExtractCosTheta()
+  // Energy and direction of the primary particle are updated according to energy-momentum 
+  // conservation. For positrons, it is sampled the same final state as for electrons.
+  //
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4PenelopeBremsstrahlungModel" << G4endl;
+
+  G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
+  const G4ParticleDefinition* theParticle = aDynamicParticle->GetDefinition();
+
+  if (kineticEnergy <= fIntrinsicLowEnergyLimit)
+   {
+     fParticleChange->SetProposedKineticEnergy(0.);
+     fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy);
+     return ;
+   }
+ 
+  G4ParticleMomentum particleDirection0 = aDynamicParticle->GetMomentumDirection();
+  //This is the momentum
+  G4ThreeVector initialMomentum =  aDynamicParticle->GetMomentum();
+ 
+  //One can use Vladimir's selector! 
+  if (verboseLevel > 2)
+    G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl;
+  // atom can be selected effitiantly if element selectors are initialised
+  const G4Element* anElement = SelectRandomAtom(couple,theParticle,kineticEnergy);
+  G4int iZ = (G4int) anElement->GetZ();
+  if (verboseLevel > 2)
+    G4cout << "Selected " << anElement->GetName() << G4endl;
+  //
+
+  //Sample gamma's energy according to the spectrum
+  G4double gammaEnergy = energySpectrum->SampleEnergy(iZ,cutG,kineticEnergy,kineticEnergy);
+  
+  //Now sample cosTheta for the Gamma
+  G4double cosThetaPrimary = GetAngularDataForZ(iZ)->ExtractCosTheta(kineticEnergy,gammaEnergy);
+  
+  G4double residualPrimaryEnergy = kineticEnergy-gammaEnergy;
+  if (residualPrimaryEnergy < 0)
+    {
+      //Ok we have a problem, all energy goes with the gamma
+      gammaEnergy += residualPrimaryEnergy;
+      residualPrimaryEnergy = 0.0;
+    }
+
+  //Get primary kinematics
+  G4double sinTheta = std::sqrt(1. - cosThetaPrimary*cosThetaPrimary);
+  G4double phi  = twopi * G4UniformRand(); 
+  G4ThreeVector gammaDirection1(sinTheta* std::cos(phi),
+				sinTheta* std::sin(phi),
+				cosThetaPrimary);
+  
+  gammaDirection1.rotateUz(particleDirection0);
+  
+  //Produce final state according to momentum conservation
+  G4ThreeVector particleDirection1 = initialMomentum - gammaEnergy*gammaDirection1;
+  particleDirection1 = particleDirection1.unit(); //normalize    
+
+  //Update the primary particle
+  if (residualPrimaryEnergy > 0.)
+    {
+      fParticleChange->ProposeMomentumDirection(particleDirection1);
+      fParticleChange->SetProposedKineticEnergy(residualPrimaryEnergy);
+    }
+  else
+    {
+      fParticleChange->SetProposedKineticEnergy(0.);
+    }
+
+  //Now produce the photon
+  G4DynamicParticle* theGamma = new G4DynamicParticle(G4Gamma::Gamma(),
+						      gammaDirection1,
+						      gammaEnergy);
+  fvect->push_back(theGamma);
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Energy balance from G4PenelopeBremsstrahlung" << G4endl;
+      G4cout << "Incoming primary energy: " << kineticEnergy/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Outgoing primary energy: " << residualPrimaryEnergy/keV << " keV" << G4endl;
+      G4cout << "Bremsstrahlung photon " << gammaEnergy/keV << " keV" << G4endl;
+      G4cout << "Total final state: " << (residualPrimaryEnergy+gammaEnergy)/keV 
+	     << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+    }
+  if (verboseLevel > 0)
+    {
+      G4double energyDiff = std::fabs(residualPrimaryEnergy+gammaEnergy-kineticEnergy);
+      if (energyDiff > 0.05*keV)
+        G4cout << "Warning from G4PenelopeBremsstrahlung: problem with energy conservation: " <<
+          (residualPrimaryEnergy+gammaEnergy)/keV <<
+          " keV (final) vs. " <<
+          kineticEnergy/keV << " keV (initial)" << G4endl;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeBremsstrahlungAngular* G4PenelopeBremsstrahlungModel::GetAngularDataForZ(G4int iZ)
+{  
+  if (!angularData)
+    angularData = new std::map<G4int,G4PenelopeBremsstrahlungAngular*>;
+
+  if (angularData->count(iZ)) //the material already exists
+    return angularData->find(iZ)->second;
+
+  //Otherwise create a new object, store it and return it
+  G4PenelopeBremsstrahlungAngular* theAngular = new G4PenelopeBremsstrahlungAngular(iZ);
+  angularData->insert(std::make_pair(iZ,theAngular));
+
+  if (angularData->count(iZ)) //the material should exist now
+    return angularData->find(iZ)->second;
+  else
+    {
+      G4Exception("Problem in G4PenelopeBremsstrahlungModel::GetAngularDataForZ()");
+      return 0;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeBremsstrahlungContinuous* 
+G4PenelopeBremsstrahlungModel::GetStoppingPowerData(G4int iZ,G4double energyCut,
+						    const G4ParticleDefinition* 
+						    theParticle)
+{  
+  if (!stoppingPowerData)
+    stoppingPowerData = new std::map<std::pair<G4int,G4double>,G4PenelopeBremsstrahlungContinuous*>;
+
+  std::pair<G4int,G4double> theKey = std::make_pair(iZ,energyCut);
+
+  if (stoppingPowerData->count(theKey)) //the material already exists
+    return stoppingPowerData->find(theKey)->second;
+
+  //Otherwise create a new object, store it and return it
+  G4String theParticleName = theParticle->GetParticleName();
+  G4PenelopeBremsstrahlungContinuous* theContinuous = new 
+    G4PenelopeBremsstrahlungContinuous(iZ,energyCut,LowEnergyLimit(),HighEnergyLimit(),theParticleName);
+  stoppingPowerData->insert(std::make_pair(theKey,theContinuous));
+
+  if (stoppingPowerData->count(theKey)) //the material should exist now
+    return stoppingPowerData->find(theKey)->second;
+  else
+    {
+      G4Exception("Problem in G4PenelopeBremsstrahlungModel::GetStoppingPowerData()");
+      return 0;
+    }
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4RayleighScattering.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4RayleighScattering.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4RayleighScattering.cc	(revision 1058)
@@ -0,0 +1,78 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+// $Id: G4RayleighScattering.cc,v 1.2 2009/03/18 13:45:51 pandola Exp $
+// GEANT4 tag $Name: geant4-09-03-beta-cand-01 $
+//
+// 
+// 19-12-2008, first implementation, Luciano Pandola 
+// 18-03-2009, clean up according to Vladimir's suggestions, Luciano Pandola
+//
+// -----------------------------------------------------------------------------
+
+#include "G4RayleighScattering.hh"
+#include "G4LivermoreRayleighModel.hh"
+#include "G4Gamma.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+G4RayleighScattering::G4RayleighScattering(const G4String& processName,
+  G4ProcessType type):G4VEmProcess (processName, type),
+    isInitialised(false)
+{
+  SetProcessSubType(fRayleigh);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+ 
+G4RayleighScattering::~G4RayleighScattering()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4bool G4RayleighScattering::IsApplicable(const G4ParticleDefinition& p)
+{
+  return (&p == G4Gamma::Gamma());
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4RayleighScattering::InitialiseProcess(const G4ParticleDefinition*)
+{
+  if(!isInitialised) {
+    isInitialised = true;
+    SetLambdaBinning(200); //use 200 bins instead of 90
+    SetBuildTableFlag(true);
+    if(!Model()) SetModel(new G4LivermoreRayleighModel);
+    AddEmModel(1, Model());
+  } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+void G4RayleighScattering::PrintInfo()
+{}         
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4VIonDEDXScalingAlgorithm.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4VIonDEDXScalingAlgorithm.cc	(revision 1058)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4VIonDEDXScalingAlgorithm.cc	(revision 1058)
@@ -0,0 +1,58 @@
+//
+// ********************************************************************
+// * License and Disclaimer                                           *
+// *                                                                  *
+// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+// * conditions of the Geant4 Software License,  included in the file *
+// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+// * include a list of copyright holders.                             *
+// *                                                                  *
+// * Neither the authors of this software system, nor their employing *
+// * institutes,nor the agencies providing financial support for this *
+// * work  make  any representation or  warranty, express or implied, *
+// * regarding  this  software system or assume any liability for its *
+// * use.  Please see the license in the file  LICENSE  and URL above *
+// * for the full disclaimer and the limitation of liability.         *
+// *                                                                  *
+// * This  code  implementation is the result of  the  scientific and *
+// * technical work of the GEANT4 collaboration.                      *
+// * By using,  copying,  modifying or  distributing the software (or *
+// * any work based  on the software)  you  agree  to acknowledge its *
+// * use  in  resulting  scientific  publications,  and indicate your *
+// * acceptance of all terms of the Geant4 Software license.          *
+// ********************************************************************
+//
+//
+//
+// ===========================================================================
+// GEANT4 class source file
+//
+// Class:                G4VIonDEDXScalingAlgorithm
+//
+// Author:               Anton Lechner (Anton.Lechner@cern.ch)
+//
+// First implementation: 11. 03. 2009
+//
+// Modifications: 
+//
+//
+// Class description:
+//    Base class for dE/dx scaling algorithms, used by G4IonDEDXHandler
+//
+// Comments:
+//
+// =========================================================================== 
+
+
+#include "G4VIonDEDXScalingAlgorithm.hh"
+
+
+G4VIonDEDXScalingAlgorithm::G4VIonDEDXScalingAlgorithm() {
+
+}
+
+
+G4VIonDEDXScalingAlgorithm::~G4VIonDEDXScalingAlgorithm() {
+
+}
