Index: trunk/source/processes/electromagnetic/lowenergy/include/G4AnalyticalEcpssrKCrossSection.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4AnalyticalEcpssrKCrossSection.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4AnalyticalEcpssrKCrossSection.hh	(revision 1316)
@@ -0,0 +1,92 @@
+//
+// ********************************************************************
+// * 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: G4AnalyticalEcpssrKCrossSection.hh,v 1.1 2010/06/06 23:40:35 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+
+#ifndef G4ANALYTICALECPSSRKCROSSSECTION_HH
+#define G4ANALYTICALECPSSRKCROSSSECTION_HH 1
+
+#include "G4VecpssrKModel.hh"
+#include "globals.hh"
+#include <map>
+#include <vector>
+
+#include "G4DNACrossSectionDataSet.hh"
+
+
+class G4AnalyticalEcpssrKCrossSection : public G4VecpssrKModel
+{
+public:
+
+  G4AnalyticalEcpssrKCrossSection();
+
+  ~G4AnalyticalEcpssrKCrossSection();
+			     
+  
+  G4double CalculateCrossSection(G4int, G4double, G4double);//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+  
+  G4double  ExpIntFunction(G4int n,G4double x);//Exponential Integral Function
+  
+private:
+  
+  G4AnalyticalEcpssrKCrossSection(const G4AnalyticalEcpssrKCrossSection&);
+  G4AnalyticalEcpssrKCrossSection & operator = (const G4AnalyticalEcpssrKCrossSection &right);
+
+  G4double FunctionFK(G4double k, G4double theta);
+
+  G4double LogLogInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2);
+   
+  G4double LinLogInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2);
+   
+  G4double QuadInterpolator(G4double e11, 
+ 		            G4double e12, 
+			    G4double e21, 
+			    G4double e22, 
+			    G4double x11,
+			    G4double x12, 
+			    G4double x21, 
+			    G4double x22, 
+			    G4double t1, 
+			    G4double t2, 
+			    G4double t, 
+			    G4double e);
+
+  typedef std::map<double, std::map<double, double> > TriDimensionMap;
+
+  TriDimensionMap FKData;
+  std::vector<double> dummyVec;
+
+  typedef std::map<double, std::vector<double> > VecMap;
+  VecMap aVecMap;
+
+  G4int verboseLevel;
+
+  G4DNACrossSectionDataSet* tableC1;
+  G4DNACrossSectionDataSet* tableC2;
+  G4DNACrossSectionDataSet* tableC3;
+};
+  
+#endif
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4AnalyticalEcpssrLiCrossSection.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4AnalyticalEcpssrLiCrossSection.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4AnalyticalEcpssrLiCrossSection.hh	(revision 1316)
@@ -0,0 +1,126 @@
+
+//
+// ********************************************************************
+// * 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: G4AnalyticalEcpssrLiCrossSection.hh,v 1.1 2010/06/06 23:40:35 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Haifa Ben Abdelouahed
+//         
+//
+// History:
+// -----------
+//  23 Apr 2008   H. Ben Abdelouahed   1st implementation
+//  28 Apr 2008   MGP        Major revision according to a design iteration
+//  29 Apr 2009   ALF Updated Desing for Integration
+//  01 Sep 2009   ALF Updated to G4AnalyticalEcpssrLiCrossSection
+//
+// -------------------------------------------------------------------
+
+// Class description:
+// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
+// Further documentation available from http://www.ge.infn.it/geant4/lowE
+
+// -------------------------------------------------------------------
+
+
+#ifndef G4ANALYTICALECPSSRLICROSSSECTION_HH
+#define G4ANALYTICALECPSSRLICROSSSECTION_HH 1
+
+#include "G4VecpssrLiModel.hh"
+#include "globals.hh"
+#include <map>
+#include <vector>
+
+class G4AnalyticalEcpssrLiCrossSection : public G4VecpssrLiModel
+
+{
+public:
+
+  G4AnalyticalEcpssrLiCrossSection();
+
+  ~G4AnalyticalEcpssrLiCrossSection();
+			     
+  G4double CalculateL1CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident);//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+
+  G4double CalculateL2CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident);//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+
+  G4double CalculateL3CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident);//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+				    
+  G4double CalculateVelocity(G4int subShell, G4int zTarget,G4double massIncident, G4double energyIncident); 
+			      
+  G4double  ExpIntFunction(G4int n,G4double x);//Exponential Integral Function
+
+   
+
+private:
+
+
+  G4AnalyticalEcpssrLiCrossSection(const G4AnalyticalEcpssrLiCrossSection&);
+  G4AnalyticalEcpssrLiCrossSection & operator = (const G4AnalyticalEcpssrLiCrossSection &right);
+
+  G4double FunctionFL1(G4double k, G4double theta);
+  
+  G4double FunctionFL2(G4double k, G4double theta);
+
+
+  G4double LogLogInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2);
+   
+  G4double LinLogInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2);
+ 
+  G4double LinLinInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2);
+  
+  G4double QuadInterpolator(G4double e11, 
+ 		            G4double e12, 
+			    G4double e21, 
+			    G4double e22, 
+			    G4double x11,
+			    G4double x12, 
+			    G4double x21, 
+			    G4double x22, 
+			    G4double t1, 
+			    G4double t2, 
+			    G4double t, 
+			    G4double e);
+
+  typedef std::map<double, std::map<double, double> > TriDimensionMap;
+
+  TriDimensionMap FL1Data;
+  
+  TriDimensionMap FL2Data;
+  std::vector<double> dummyVec1;
+  std::vector<double> dummyVec2;
+
+
+
+  typedef std::map<double, std::vector<double> > VecMap;
+  VecMap aVecMap1;
+  VecMap aVecMap2;
+
+  G4int verboseLevel;
+
+};
+
+#endif
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08ComptonModel.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08ComptonModel.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08ComptonModel.hh	(revision 1316)
@@ -0,0 +1,132 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08ComptonModel.hh,v 1.2 2010/03/19 11:33:24 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// -----------
+// 15 Feb 2010   L. Pandola   1st implementation. 
+// 18 Mar 2010   L. Pandola   Removed GetAtomsPerMolecule(), now demanded 
+//                            to G4PenelopeOscillatorManager
+//
+// -------------------------------------------------------------------
+//*
+// Class description:
+// Low Energy Electromagnetic Physics, Compton Scattering
+// with Penelope Model, version 2008
+// -------------------------------------------------------------------
+
+#ifndef G4PENELOPE08COMPTONMODEL_HH
+#define G4PENELOPE08COMPTONMODEL_HH 1
+
+#include "globals.hh"
+#include "G4VEmModel.hh"
+#include "G4DataVector.hh"
+#include "G4ParticleChangeForGamma.hh"
+#include "G4AtomicDeexcitation.hh"
+
+class G4ParticleDefinition;
+class G4DynamicParticle;
+class G4MaterialCutsCouple;
+class G4Material;
+class G4PenelopeOscillatorManager;
+class G4PenelopeOscillator;
+
+class G4Penelope08ComptonModel : public G4VEmModel 
+{
+
+public:
+  
+  G4Penelope08ComptonModel(const G4ParticleDefinition* p=0,
+			 const G4String& processName ="PenCompton");
+  
+  virtual ~G4Penelope08ComptonModel();
+
+  virtual void Initialise(const G4ParticleDefinition*, const G4DataVector&);
+
+  virtual G4double CrossSectionPerVolume(const G4Material*,
+                                         const G4ParticleDefinition*,
+                                         G4double kineticEnergy,
+                                         G4double cutEnergy = 0.0,
+                                         G4double maxEnergy = DBL_MAX);
+  
+  //This is a dummy method. Never inkoved by the tracking, it just issues 
+  //a warning if one tries to get Cross Sections per Atom via the 
+  //G4EmCalculator.
+  virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+                                              G4double,
+                                              G4double,
+                                              G4double,
+                                              G4double,
+                                              G4double);
+
+  virtual void SampleSecondaries(std::vector<G4DynamicParticle*>*,
+				 const G4MaterialCutsCouple*,
+				 const G4DynamicParticle*,
+				 G4double tmin,
+				 G4double maxEnergy);
+
+  void SetVerbosityLevel(G4int lev){verboseLevel = lev;};
+  G4int GetVerbosityLevel(){return verboseLevel;};
+
+  void ActivateAuger(G4bool);
+
+protected:
+  G4ParticleChangeForGamma* fParticleChange;
+
+private:
+  //Differential cross section which is numerically integrated
+  G4double DifferentialCrossSection (G4double cdt,G4double energy,
+				     G4PenelopeOscillator* osc);
+
+  G4double OscillatorTotalCrossSection(G4double energy,
+				       G4PenelopeOscillator* osc);
+
+  G4double KleinNishinaCrossSection(G4double energy,const G4Material*);
+
+  G4Penelope08ComptonModel & operator=(const G4Penelope08ComptonModel &right);
+  G4Penelope08ComptonModel(const G4Penelope08ComptonModel&);
+
+  //Intrinsic energy limits of the model: 
+  //cannot be extended by the parent process
+  G4double fIntrinsicLowEnergyLimit;
+  G4double fIntrinsicHighEnergyLimit;
+
+  G4int verboseLevel;
+
+  G4bool isInitialised;
+
+  G4AtomicDeexcitation deexcitationManager;
+
+  G4PenelopeOscillatorManager* oscManager;
+
+
+};
+
+#endif
+
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08GammaConversionModel.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08GammaConversionModel.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08GammaConversionModel.hh	(revision 1316)
@@ -0,0 +1,124 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08GammaConversionModel.hh,v 1.1 2010/03/17 14:19:04 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// -----------
+// 13 Jan 2010   L. Pandola  First implementation
+//
+// -------------------------------------------------------------------
+//
+// Class description:
+// Low Energy Electromagnetic Physics, Gamma Conversion 
+// with Penelope Model, version 2008
+// -------------------------------------------------------------------
+
+#ifndef G4PENELOPE08GAMMACONVERSIONMODEL_HH
+#define G4PENELOPE08GAMMACONVERSIONMODEL_HH 1
+
+#include "globals.hh"
+#include "G4VEmModel.hh"
+#include "G4DataVector.hh"
+#include "G4ParticleChangeForGamma.hh"
+
+class G4ParticleDefinition;
+class G4DynamicParticle;
+class G4MaterialCutsCouple;
+class G4Material;
+class G4PhysicsFreeVector;
+
+class G4Penelope08GammaConversionModel : public G4VEmModel 
+{
+
+public:
+  
+  G4Penelope08GammaConversionModel(const G4ParticleDefinition* p=0,
+			 const G4String& processName ="PenConversion");
+  
+  virtual ~G4Penelope08GammaConversionModel();
+
+  virtual void Initialise(const G4ParticleDefinition*, const G4DataVector&);
+
+  virtual G4double ComputeCrossSectionPerAtom(
+					      const G4ParticleDefinition*,
+					      G4double kinEnergy,
+					      G4double Z,
+					      G4double A=0,
+					      G4double cut=0,
+					      G4double emax=DBL_MAX);
+
+  virtual void SampleSecondaries(std::vector<G4DynamicParticle*>*,
+				 const G4MaterialCutsCouple*,
+				 const G4DynamicParticle*,
+				 G4double tmin,
+				 G4double maxEnergy);
+
+  void SetVerbosityLevel(G4int lev){verboseLevel = lev;};
+  G4int GetVerbosityLevel(){return verboseLevel;};
+
+protected:
+  G4ParticleChangeForGamma* fParticleChange;
+
+private:
+  G4Penelope08GammaConversionModel & operator=(const 
+					       G4Penelope08GammaConversionModel &right);
+  G4Penelope08GammaConversionModel(const G4Penelope08GammaConversionModel&);
+
+
+  //Intrinsic energy limits of the model: cannot be extended by the parent process
+  G4double fIntrinsicLowEnergyLimit;
+  G4double fIntrinsicHighEnergyLimit;
+
+  //Use a quicker sampling algorithm if E < smallEnergy
+  G4double fSmallEnergy; 
+
+  std::map<const G4int,G4PhysicsFreeVector*> *logAtomicCrossSection;
+  void ReadDataFile(const G4int Z);
+
+  void InitializeScreeningRadii();
+  G4double fAtomicScreeningRadius[99];
+
+  void InitializeScreeningFunctions(const G4Material*);
+  //Effective (scalar) properties attached to materials:
+  // effective charge
+  std::map<const G4Material*,G4double> *fEffectiveCharge;
+  // 2/Rs (Rs = screening radius), BCB array in Penelope
+  std::map<const G4Material*,G4double> *fMaterialInvScreeningRadius;
+  // Parameters of screening functions
+  std::map<const G4Material*,std::pair<G4double,G4double> > *fScreeningFunction;
+
+  std::pair<G4double,G4double> GetScreeningFunctions(G4double);	
+
+
+  G4int verboseLevel;
+  G4bool isInitialised;
+};
+
+#endif
+
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08PhotoElectricModel.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08PhotoElectricModel.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08PhotoElectricModel.hh	(revision 1316)
@@ -0,0 +1,125 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08PhotoElectricModel.hh,v 1.1 2010/03/17 14:19:04 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// -----------
+// 08 Jan 2010   L. Pandola   1st implementation. 
+//
+// -------------------------------------------------------------------
+//
+// Class description:
+// Low Energy Electromagnetic Physics, Photo-electric effect
+// with Penelope Model, version 2008
+// -------------------------------------------------------------------
+
+#ifndef G4PENELOPE08PHOTOELECTRICMODEL_HH
+#define G4PENELOPE08PHOTOELECTRICMODEL_HH 1
+
+#include "globals.hh"
+#include "G4VEmModel.hh"
+#include "G4DataVector.hh"
+#include "G4ParticleChangeForGamma.hh"
+#include "G4AtomicDeexcitation.hh"
+
+class G4ParticleDefinition;
+class G4DynamicParticle;
+class G4MaterialCutsCouple;
+class G4Material;
+
+class G4Penelope08PhotoElectricModel : public G4VEmModel 
+{
+
+public:
+  
+  G4Penelope08PhotoElectricModel(const G4ParticleDefinition* p=0,
+			 const G4String& processName ="PenPhotoElec");
+  
+  virtual ~G4Penelope08PhotoElectricModel();
+
+  virtual void Initialise(const G4ParticleDefinition*, const G4DataVector&);
+
+  virtual G4double ComputeCrossSectionPerAtom(
+					      const G4ParticleDefinition*,
+					      G4double kinEnergy,
+					      G4double Z,
+					      G4double A=0,
+					      G4double cut=0,
+					      G4double emax=DBL_MAX);
+
+  virtual void SampleSecondaries(std::vector<G4DynamicParticle*>*,
+				 const G4MaterialCutsCouple*,
+				 const G4DynamicParticle*,
+				 G4double tmin,
+				 G4double maxEnergy);
+
+  void SetVerbosityLevel(G4int lev){verboseLevel = lev;};
+  G4int GetVerbosityLevel(){return verboseLevel;};
+
+  void ActivateAuger(G4bool);
+
+  //testing purposes
+  size_t GetNumberOfShellXS(G4int);
+  G4double GetShellCrossSection(G4int Z,size_t shellID,G4double energy);
+
+
+protected:
+  G4ParticleChangeForGamma* fParticleChange;
+
+private:
+  G4Penelope08PhotoElectricModel & operator=(const G4Penelope08PhotoElectricModel &right);
+  G4Penelope08PhotoElectricModel(const G4Penelope08PhotoElectricModel&);
+
+  G4double SampleElectronDirection(G4double energy);
+
+  //Intrinsic energy limits of the model: cannot be extended by the parent process
+  G4double fIntrinsicLowEnergyLimit;
+  G4double fIntrinsicHighEnergyLimit;
+
+  G4int verboseLevel;
+  G4bool isInitialised;
+
+  G4AtomicDeexcitation deexcitationManager;
+
+  void ReadDataFile(G4int Z);
+
+  //For each Z, the PhysicsTable contains nShell+1 physics vectors
+  //with log(E) vs. log(XS)
+  //Element [0] of the table is the total XS, element [iS] is the 
+  //partial cross section for shell iS-1
+  std::map<const G4int,G4PhysicsTable*> *logAtomicShellXS;
+
+  size_t SelectRandomShell(G4int Z,G4double energy);
+  G4String WriteTargetShell(size_t shellID);
+
+
+};
+
+#endif
+
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08RayleighModel.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08RayleighModel.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4Penelope08RayleighModel.hh	(revision 1316)
@@ -0,0 +1,127 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08RayleighModel.hh,v 1.1 2010/03/17 14:19:04 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// -----------
+// 03 Dec 2009   L. Pandola   1st implementation. 
+//
+// -------------------------------------------------------------------
+//
+// Class description:
+// Low Energy Electromagnetic Physics, Rayleigh Scattering
+// with the model from Penelope, version 2008
+// -------------------------------------------------------------------
+
+#ifndef G4PENELOPE08RAYLEIGHMODEL_HH
+#define G4PENELOPE08RAYLEIGHMODEL_HH 1
+
+#include "globals.hh"
+#include "G4VEmModel.hh"
+#include "G4DataVector.hh"
+#include "G4ParticleChangeForGamma.hh"
+
+class G4ParticleDefinition;
+class G4DynamicParticle;
+class G4MaterialCutsCouple;
+class G4Material;
+class G4PhysicsFreeVector;
+class G4PenelopeSamplingData;
+
+class G4Penelope08RayleighModel : public G4VEmModel 
+{
+
+public:  
+  G4Penelope08RayleighModel(const G4ParticleDefinition* p=0,
+			  const G4String& processName ="PenRayleigh");
+  
+  virtual ~G4Penelope08RayleighModel();
+  
+  virtual void Initialise(const G4ParticleDefinition*, const G4DataVector&);
+  
+  virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+                                              G4double kinEnergy,
+                                              G4double Z,
+                                              G4double A=0,
+                                              G4double cut=0,
+                                              G4double emax=DBL_MAX);
+
+  virtual void SampleSecondaries(std::vector<G4DynamicParticle*>*,
+				 const G4MaterialCutsCouple*,
+				 const G4DynamicParticle*,
+				 G4double tmin,
+				 G4double maxEnergy);
+    
+  void SetVerbosityLevel(G4int lev){verboseLevel = lev;};
+  G4int GetVerbosityLevel(){return verboseLevel;};
+  
+  //Testing purposes
+  void DumpFormFactorTable(const G4Material*);
+
+protected:
+  G4ParticleChangeForGamma* fParticleChange;
+  
+private:
+  G4Penelope08RayleighModel& operator=(const G4Penelope08RayleighModel &right);
+  G4Penelope08RayleighModel(const G4Penelope08RayleighModel&);
+    
+  //Intrinsic energy limits of the model: cannot be extended by 
+  //the parent process
+  G4double fIntrinsicLowEnergyLimit;
+  G4double fIntrinsicHighEnergyLimit;
+  
+  G4int verboseLevel;
+  G4bool isInitialised;
+
+  //Internal tables and manager methods
+  std::map<const G4int,G4PhysicsFreeVector*> *logAtomicCrossSection;
+  std::map<const G4int,G4PhysicsFreeVector*> *atomicFormFactor;
+
+
+  G4DataVector logQSquareGrid; //log(Q^2) grid for interpolation
+  std::map<const G4Material*,G4PhysicsFreeVector*> *logFormFactorTable; //log(Q^2) vs. log(F^2)
+ 
+  G4DataVector logEnergyGridPMax; //energy grid for PMac (and originally for the x-section)
+  std::map<const G4Material*,G4PhysicsFreeVector*> *pMaxTable; //E vs. Pmax
+
+  std::map<const G4Material*,G4PenelopeSamplingData*> *samplingTable;
+
+  //Helper methods
+  void ReadDataFile(G4int); 
+  void ClearTables();
+  void BuildFormFactorTable(const G4Material*);
+  void GetPMaxTable(const G4Material*);
+
+  G4double GetFSquared(const G4Material*,const G4double);
+  void InitializeSamplingAlgorithm(const G4Material*);
+
+};
+
+#endif
+
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeOscillator.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeOscillator.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeOscillator.hh	(revision 1316)
@@ -0,0 +1,107 @@
+//
+// ********************************************************************
+// * 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.          *
+// ********************************************************************
+//
+//
+// Author: Luciano Pandola
+//
+// History:
+// -----------
+// 18 Dec 2008   L. Pandola   First implementation
+//                            
+//
+// -------------------------------------------------------------------
+//
+// Class description:
+// Class designed to contain data of atomic oscillators that are used by 
+// several Penelope models. Objects of G4PenelopeOscillators are managed 
+// by a dedicated G4PenelopeOscillatorManager.
+// -------------------------------------------------------------------
+
+#ifndef G4PENELOPEOSCILLATOR_HH
+#define G4PENELOPEOSCILLATOR_HH 1
+
+#include "globals.hh"
+
+class G4PenelopeOscillator 
+{
+
+ public:
+  G4PenelopeOscillator();
+  G4PenelopeOscillator(const G4PenelopeOscillator&);
+  
+  ~G4PenelopeOscillator(){;};
+
+  //I need to overload the following operators: > < == =
+  const G4PenelopeOscillator& operator=(const G4PenelopeOscillator&);
+  int operator==(const G4PenelopeOscillator&) const;
+  int operator>(const G4PenelopeOscillator&) const;
+  int operator<(const G4PenelopeOscillator&) const;
+  
+  //Setters and getters
+  G4double GetHartreeFactor() {return hartreeFactor;};
+  void SetHartreeFactor(G4double hf) {hartreeFactor = hf;};
+  //
+  G4double GetIonisationEnergy() {return ionisationEnergy;};
+  void SetIonisationEnergy(G4double ie) {ionisationEnergy = ie;};
+  //
+  G4double GetResonanceEnergy() const {return resonanceEnergy;};
+  void SetResonanceEnergy(G4double re) {resonanceEnergy = re;};
+  //
+  G4double GetOscillatorStrength() {return oscillatorStrength;};
+  void SetOscillatorStrength(G4double ostr) {oscillatorStrength=ostr;};
+  //
+  G4int GetShellFlag() {return shellFlag;};
+  void SetShellFlag(G4int theflag) {shellFlag=theflag;};
+  //
+  G4double GetParentZ() {return parentZ;};
+  void SetParentZ(G4double parZ) {parentZ = parZ;};
+  //
+  G4int GetParentShellID() {return parentShellID;};
+  void SetParentShellID(G4int psID) {parentShellID = psID;};
+  //
+  G4double GetCutoffRecoilResonantEnergy(){return cutoffRecoilResonantEnergy;};
+  void SetCutoffRecoilResonantEnergy(G4double ene){cutoffRecoilResonantEnergy = ene;};
+
+private:
+  G4double hartreeFactor;
+  G4double ionisationEnergy;
+  G4double resonanceEnergy;
+  G4double oscillatorStrength;
+  G4int shellFlag;
+  G4double parentZ;
+  G4int parentShellID; //necessary for interface to AtomicDeexcitationManager
+  G4double cutoffRecoilResonantEnergy;
+};
+
+struct G4PenelopeOscillatorResEnergyComparator
+{
+public:
+  int operator()(const G4PenelopeOscillator& left,
+		 const G4PenelopeOscillator& right) 
+  {return ((left.GetResonanceEnergy() < right.GetResonanceEnergy()) ? 1 : 0);};
+};
+
+#endif
+
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeOscillatorManager.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeOscillatorManager.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeOscillatorManager.hh	(revision 1316)
@@ -0,0 +1,137 @@
+//
+// ********************************************************************
+// * 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.          *
+// ********************************************************************
+//
+//
+//
+// Authors: Luciano Pandola (luciano.pandola at lngs.infn.it)
+//
+// History:
+// -----------
+//  
+//  03 Dec 2009  First implementation, Luciano Pandola
+//  16 Feb 2010  Added methods to calculate and store also A and Z 
+//               for molecules. Luciano Pandola
+//  16 Mar 2010  Added methods to calculate and store mean exc energy
+//               and plasma energy (used for Ionisation). L Pandola
+//  18 Mar 2010  Added method to retrieve number of atoms per 
+//               molecule. L. Pandola
+//
+// -------------------------------------------------------------------
+//
+//! Class description:
+//! Fills and manages G4PenelopeOscillator objects and takes care of 
+//! building and managing the G4PenelopeOscillatorTables for the materials 
+//! in the geometry. G4PenelopeOscillatorManager is a singleton.
+//! This is compliant with Penelope2008, so different tables (with different 
+//! grouping factors) are created for Ionisation and Compton processes.
+//
+
+// -------------------------------------------------------------------
+
+#ifndef G4PenelopeOscillatorManager_h
+#define G4PenelopeOscillatorManager_h 1
+
+#include "globals.hh"
+#include "G4PenelopeOscillator.hh"
+#include <vector>
+#include <map>
+
+class G4Material;
+
+typedef std::vector<G4PenelopeOscillator*> G4PenelopeOscillatorTable ;
+
+// This class is a singleton
+class G4PenelopeOscillatorManager {
+
+public: 
+
+  // The only way to get an instance of this class is to call the 
+  // function GetOscillatorManager() 
+  static G4PenelopeOscillatorManager* GetOscillatorManager();
+ 
+  //Clear() is invoked by Initialise() of the processes, if required
+  void Clear();
+  void Dump(const G4Material*);
+  
+  //For ionisation
+  G4PenelopeOscillatorTable* GetOscillatorTableIonisation(const G4Material*);  
+  G4PenelopeOscillator* GetOscillatorIonisation(const G4Material*,G4int);
+  
+  //For Compton
+  G4PenelopeOscillatorTable* GetOscillatorTableCompton(const G4Material*);  
+  G4PenelopeOscillator* GetOscillatorCompton(const G4Material*,G4int);
+
+  void SetVerbosityLevel(G4int vl){verbosityLevel = vl;};
+  G4int GetVerbosityLevel(){return verbosityLevel;};
+  
+  //These are cumulative for the molecule
+  G4double GetTotalZ(const G4Material*);
+  G4double GetTotalA(const G4Material*);
+  G4double GetMeanExcitationEnergy(const G4Material*);
+  G4double GetPlasmaEnergySquared(const G4Material*);
+  G4double GetAtomsPerMolecule(const G4Material*);
+
+protected:
+  G4PenelopeOscillatorManager();
+  ~G4PenelopeOscillatorManager();
+
+private:
+  // Hide copy constructor and assignment operator 
+  G4PenelopeOscillatorManager& operator=(const 
+					 G4PenelopeOscillatorManager& right);
+  G4PenelopeOscillatorManager(const G4PenelopeOscillatorManager&);
+ 
+  static G4PenelopeOscillatorManager* instance;
+  
+  //In Penelope2008, the Ionisation and Compton oscillator tables are 
+  //slightly different!
+  std::map<const G4Material*,G4PenelopeOscillatorTable*> 
+  *oscillatorStoreIonisation;
+
+  std::map<const G4Material*,G4PenelopeOscillatorTable*> 
+  *oscillatorStoreCompton;
+
+  std::map<const G4Material*,G4double> *atomicNumber;
+  std::map<const G4Material*,G4double> *atomicMass;
+
+  std::map<const G4Material*,G4double> *excitationEnergy;
+  std::map<const G4Material*,G4double> *plasmaSquared;
+
+  std::map<const G4Material*,G4double> *atomsPerMolecule;
+
+  //create both tables simultaneously
+  void CheckForTablesCreated();
+
+  void ReadElementData();
+  G4double elementData[5][2000];
+  G4bool fReadElementData;
+
+  void BuildOscillatorTable(const G4Material*);
+
+  G4int verbosityLevel;
+
+};
+
+#endif
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeSamplingData.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeSamplingData.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4PenelopeSamplingData.hh	(revision 1316)
@@ -0,0 +1,92 @@
+//
+// ********************************************************************
+// * 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: G4PenelopeSamplingData.hh,v 1.1 2010/03/17 14:19:04 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// -----------
+// 09 Dec 2009   L. Pandola   1st implementation. 
+//
+// -------------------------------------------------------------------
+//
+// Class description:
+// This is a container of data that are used for sampling algorithm
+// of Penelope08 Rayleigh scattering
+// -------------------------------------------------------------------
+
+#ifndef G4PENELOPESAMPLINGDATA_HH
+#define G4PENELOPESAMPLINGDATA_HH 1
+
+#include "globals.hh"
+#include "G4DataVector.hh"
+//
+//This is a container of data that are used for sampling algoritm
+//
+class G4PenelopeSamplingData
+{
+
+public:
+  G4PenelopeSamplingData(G4int npoints=150);
+  ~G4PenelopeSamplingData();
+
+  void AddPoint(G4double x0,G4double pac0,G4double a0,G4double b0,size_t ITTL0,
+		size_t ITTU0);
+  size_t GetNumberOfStoredPoints();
+  void Clear();
+  void DumpTable();
+  
+  G4double GetX(size_t index);
+  G4double GetPAC(size_t index);
+  G4double GetA(size_t index);
+  G4double GetB(size_t index);
+
+  G4double SampleValue(G4double rndm);
+
+private:
+  G4PenelopeSamplingData & operator=(const G4PenelopeSamplingData &right);
+  G4PenelopeSamplingData(const G4PenelopeSamplingData&);
+  
+  //G4double xlow;
+  //G4double xhigh;
+  
+  G4DataVector* x; //grid points, in increasing order
+  G4DataVector* pac; //value of the cumulative pdf at x_i
+  G4DataVector* a; // rational inverse cumulative inverse distribution parameters
+  G4DataVector* b;
+  
+  std::vector<size_t> *ITTL; //largest j for which pac(j) < (i-1)/(np-1)
+  std::vector<size_t> *ITTU; //smallest k for which pac(k) > i/(np-1)
+
+  G4int np; //number of grid points
+
+  
+
+};
+
+#endif
+
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4VecpssrKModel.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4VecpssrKModel.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4VecpssrKModel.hh	(revision 1316)
@@ -0,0 +1,69 @@
+
+//
+// ********************************************************************
+// * 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.          *
+// ********************************************************************
+//
+//
+// Author: Alfonso Mantero
+//         
+//
+// History:
+// -----------
+//  01 Sep 2009   Alf Created
+//
+// -------------------------------------------------------------------
+
+// Class description:
+// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
+// Further documentation available from http://www.ge.infn.it/geant4/lowE
+
+// -------------------------------------------------------------------
+
+
+#ifndef G4VECPSSRKMODEL_HH
+#define G4VECPSSRKMODEL_HH 1
+
+#include "globals.hh"
+
+class G4VecpssrKModel 
+
+{
+public:
+
+  G4VecpssrKModel();
+
+  ~G4VecpssrKModel();
+			     
+  virtual G4double CalculateCrossSection(G4int zTarget,G4double massIncident, G4double energyIncident) = 0;
+   
+
+private:
+
+
+  G4VecpssrKModel(const G4VecpssrKModel&);
+  G4VecpssrKModel & operator = (const G4VecpssrKModel &right);
+
+};
+
+#endif
Index: trunk/source/processes/electromagnetic/lowenergy/include/G4VecpssrLiModel.hh
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/include/G4VecpssrLiModel.hh	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/include/G4VecpssrLiModel.hh	(revision 1316)
@@ -0,0 +1,79 @@
+
+//
+// ********************************************************************
+// * 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: G4VecpssrLiModel.hh,v 1.2 2010/06/06 23:52:28 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Haifa Ben Abdelouahed
+//         
+//
+// History:
+// -----------
+//  23 Apr 2008   H. Ben Abdelouahed   1st implementation
+//  28 Apr 2008   MGP        Major revision according to a design iteration
+//  29 Apr 2009   ALF Updated Desing for Integration
+//
+// -------------------------------------------------------------------
+
+// Class description:
+// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
+// Further documentation available from http://www.ge.infn.it/geant4/lowE
+
+// -------------------------------------------------------------------
+
+
+#ifndef G4VECPSSRLIMODEL_HH
+#define G4VECPSSRLIMODEL_HH 1
+
+#include "globals.hh"
+
+class G4VecpssrLiModel 
+{
+
+public:
+
+  G4VecpssrLiModel();
+
+  ~G4VecpssrLiModel();
+			     
+  virtual G4double CalculateL1CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident) = 0;//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+
+  virtual G4double CalculateL2CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident) = 0;//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+
+  virtual G4double CalculateL3CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident) = 0;//according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)
+				    
+
+   
+
+private:
+
+
+  G4VecpssrLiModel(const G4VecpssrLiModel&);
+  G4VecpssrLiModel & operator = (const G4VecpssrLiModel &right);
+
+};
+
+#endif
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4AnalyticalEcpssrKCrossSection.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4AnalyticalEcpssrKCrossSection.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4AnalyticalEcpssrKCrossSection.cc	(revision 1316)
@@ -0,0 +1,644 @@
+//
+// ********************************************************************
+// * 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: G4AnalyticalEcpssrKCrossSection.cc,v 1.2 2010/06/09 07:15:50 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+#include "globals.hh"
+#include "G4AnalyticalEcpssrKCrossSection.hh"
+#include "G4AtomicTransitionManager.hh"
+#include "G4NistManager.hh"
+#include "G4Proton.hh"
+#include "G4Alpha.hh"
+#include <math.h>
+#include <iostream>
+#include "G4SemiLogInterpolation.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4AnalyticalEcpssrKCrossSection::G4AnalyticalEcpssrKCrossSection()
+{ 
+    // Storing FK data needed for medium velocities region
+
+    char *path = getenv("G4LEDATA");
+ 
+    if (!path)
+    G4Exception("G4AnalyticalEcpssrKCrossSection::G4AnalyticalEcpssrKCrossSection() G4LEDATA environment variable not set");
+
+    std::ostringstream fileName;
+    fileName << path << "/pixe/uf/FK.dat";
+    std::ifstream FK(fileName.str().c_str());
+
+    if (!FK) G4Exception("G4AnalyticalEcpssrKCrossSection::G4AnalyticalEcpssrKCrossSection() error opening FK data file");
+      
+    dummyVec.push_back(0.);
+
+    while(!FK.eof())
+    {
+	double x;
+	double y;
+	
+	FK>>x>>y;
+
+	//  Mandatory vector initialization
+        if (x != dummyVec.back()) 
+        { 
+          dummyVec.push_back(x); 
+          aVecMap[x].push_back(-1.);
+        }
+	  
+        FK>>FKData[x][y];
+
+        if (y != aVecMap[x].back()) aVecMap[x].push_back(y);
+          
+    }
+
+  // Storing C coefficients for high velocity formula
+
+  G4String fileC1("pixe/uf/c1");
+  tableC1 = new G4DNACrossSectionDataSet(new G4SemiLogInterpolation, 1.,1.);
+  tableC1->LoadData(fileC1);
+
+  G4String fileC2("pixe/uf/c2");
+  tableC2 = new G4DNACrossSectionDataSet(new G4SemiLogInterpolation, 1.,1.);
+  tableC2->LoadData(fileC2);
+
+  G4String fileC3("pixe/uf/c3");
+  tableC3 = new G4DNACrossSectionDataSet(new G4SemiLogInterpolation, 1.,1.);
+  tableC3->LoadData(fileC3);
+
+  //
+
+  verboseLevel=0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void print (G4double elem)
+{
+  G4cout << elem << " ";
+}
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4AnalyticalEcpssrKCrossSection::~G4AnalyticalEcpssrKCrossSection()
+{ 
+
+  delete tableC1;
+  delete tableC2;
+  delete tableC3;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrKCrossSection::ExpIntFunction(G4int n,G4double x)
+
+{
+// this "ExpIntFunction" function allows fast evaluation of the n order exponential integral function En(x)
+
+  G4int i;
+  G4int ii;
+  G4int nm1;
+  G4double a;
+  G4double b;
+  G4double c;
+  G4double d;
+  G4double del;
+  G4double fact;
+  G4double h;
+  G4double psi;
+  G4double ans = 0;
+  const G4double euler= 0.5772156649;
+  const G4int maxit= 100;
+  const G4double fpmin = 1.0e-30;
+  const G4double eps = 1.0e-7;
+  nm1=n-1;
+  if (n<0 || x<0.0 || (x==0.0 && (n==0 || n==1))) {
+    G4cout << "G4AnalyticalEcpssrKCrossSection::ExpIntFunction: VERY Bad arguments in ExpIntFunction" << G4endl;
+    G4cout << n << ", " << x << G4endl;
+  }
+  else {
+       if (n==0) ans=std::exp(-x)/x;
+        else {
+           if (x==0.0) ans=1.0/nm1;
+              else {
+                   if (x > 1.0) {
+                         	b=x+n;
+                        	c=1.0/fpmin;
+                        	d=1.0/b;
+				h=d;
+				for (i=1;i<=maxit;i++) {
+				  a=-i*(nm1+i);
+				  b +=2.0;
+				  d=1.0/(a*d+b);
+				  c=b+a/c;
+				  del=c*d;
+				  h *=del;
+				      if (std::fabs(del-1.0) < eps) {
+					ans=h*std::exp(-x);
+					return ans;
+				      }
+				}
+		   } else {
+		     ans = (nm1!=0 ? 1.0/nm1 : -std::log(x)-euler);
+		     fact=1.0;
+		     for (i=1;i<=maxit;i++) {
+		       fact *=-x/i;
+		       if (i !=nm1) del = -fact/(i-nm1);
+		       else {
+			 psi = -euler;
+			 for (ii=1;ii<=nm1;ii++) psi +=1.0/ii;
+			 del=fact*(-std::log(x)+psi);
+		       }
+		       ans += del;
+		       if (std::fabs(del) < std::fabs(ans)*eps) return ans;
+		     }
+		   }
+	      }
+	}
+  }
+return ans;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+ 
+
+G4double G4AnalyticalEcpssrKCrossSection::CalculateCrossSection(G4int zTarget,G4double massIncident, G4double energyIncident) 
+ 
+{
+
+  // this K-CrossSection calculation method is done according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)//					                
+  
+  G4NistManager* massManager = G4NistManager::Instance();   
+
+  G4AtomicTransitionManager*  transitionManager =  G4AtomicTransitionManager::Instance();
+
+  G4double  zIncident = 0; 
+  G4Proton* aProtone = G4Proton::Proton();
+  G4Alpha* aAlpha = G4Alpha::Alpha();
+
+  if (massIncident == aProtone->GetPDGMass() )
+  {
+   zIncident = (aProtone->GetPDGCharge())/eplus; 
+  }
+  else
+    {
+      if (massIncident == aAlpha->GetPDGMass())
+	{
+	  zIncident  = (aAlpha->GetPDGCharge())/eplus; 
+	}
+      else
+	{ 
+	  G4cout << "*** WARNING in G4AnalyticalEcpssrKCrossSection::CalculateCrossSection : we can treat only Proton or Alpha incident particles " << G4endl;
+	  return 0;
+	}
+  }
+  
+    if (verboseLevel>0) G4cout << "  massIncident=" << massIncident<< G4endl;
+
+  G4double kBindingEnergy = transitionManager->Shell(zTarget,0)->BindingEnergy();
+
+    if (verboseLevel>0) G4cout << "  kBindingEnergy=" << kBindingEnergy/eV<< G4endl;
+
+  G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
+    
+    if (verboseLevel>0) G4cout << "  massTarget=" <<  massTarget<< G4endl;
+ 
+  G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2; //the mass of the system (projectile, target) 
+  
+    if (verboseLevel>0) G4cout << "  systemMass=" <<  systemMass<< G4endl;
+
+  const G4double zkshell= 0.3;
+
+  G4double screenedzTarget = zTarget-zkshell; // screenedzTarget is the screened nuclear charge of the target
+
+  const G4double rydbergMeV= 13.6056923e-6;
+ 
+  G4double tetaK = kBindingEnergy/((screenedzTarget*screenedzTarget)*rydbergMeV);  //tetaK denotes the reduced binding energy of the electron
+  
+    if (verboseLevel>0) G4cout << "  tetaK=" <<  tetaK<< G4endl;
+
+  G4double velocity =(2./(tetaK*screenedzTarget))*std::pow(((energyIncident*electron_mass_c2)/(massIncident*rydbergMeV)),0.5);
+    
+    if (verboseLevel>0) G4cout << "  velocity=" << velocity<< G4endl;
+
+  const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ;        
+  
+    if (verboseLevel>0) G4cout << "  bohrPow2Barn=" <<  bohrPow2Barn<< G4endl;
+
+  G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);     //sigma0 is the initial cross section of K shell at stable state
+    
+    if (verboseLevel>0) G4cout << "  sigma0=" <<  sigma0<< G4endl;
+
+  const G4double kAnalyticalApproximation= 1.5; 
+ 
+  G4double x = kAnalyticalApproximation/velocity;
+  
+    if (verboseLevel>0) G4cout << "  x=" << x<< G4endl;
+
+  G4double electrIonizationEnergy;                                         
+                                       
+  if ((0.< x) && (x <= 0.035))
+    {
+      electrIonizationEnergy= 0.75*pi*(std::log(1./(x*x))-1.);
+    }
+  else
+    {
+      if ( (0.035 < x) && (x <=3.))
+	{
+	  electrIonizationEnergy =std::exp(-2.*x)/(0.031+(0.213*std::pow(x,0.5))+(0.005*x)-(0.069*std::pow(x,3./2.))+(0.324*x*x));
+	}
+
+      else
+	{
+	  if ( (3.< x) && (x<=11.))
+	   {
+	     electrIonizationEnergy =2.*std::exp(-2.*x)/std::pow(x,1.6);
+	   }
+
+	  else electrIonizationEnergy =0.;
+	}
+    }
+
+    if (verboseLevel>0) G4cout << "  electrIonizationEnergy=" << electrIonizationEnergy<< G4endl;
+
+  G4double hFunction =(electrIonizationEnergy*2.)/(tetaK*std::pow(velocity,3)); //hFunction represents the correction for polarization effet
+  
+    if (verboseLevel>0) G4cout << "  hFunction=" << hFunction<< G4endl;
+    
+  G4double gFunction = (1.+(9.*velocity)+(31.*velocity*velocity)+(98.*std::pow(velocity,3.))+(12.*std::pow(velocity,4.))+(25.*std::pow(velocity,5.))
+			+(4.2*std::pow(velocity,6.))+(0.515*std::pow(velocity,7.)))/std::pow(1.+velocity,9.); //gFunction represents the correction for binding effet
+    if (verboseLevel>0) G4cout << "  gFunction=" << gFunction<< G4endl;
+ 
+  //-----------------------------------------------------------------------------------------------------------------------------
+
+  G4double sigmaPSS = 1.+(((2.*zIncident)/(screenedzTarget*tetaK))*(gFunction-hFunction)); //describes the perturbed stationnairy state of the affected atomic electon
+    
+    if (verboseLevel>0) G4cout << "  sigmaPSS=" << sigmaPSS<< G4endl;
+    
+    if (verboseLevel>0) G4cout << "  sigmaPSS*tetaK=" << sigmaPSS*tetaK<< G4endl;
+
+  //----------------------------------------------------------------------------------------------------------------------------
+  
+  const G4double cNaturalUnit= 1/fine_structure_const;  // it's the speed of light according to Atomic-Unit-System
+   
+    if (verboseLevel>0) G4cout << "  cNaturalUnit=" << cNaturalUnit<< G4endl;
+  
+  G4double ykFormula=0.4*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocity/sigmaPSS);
+    
+    if (verboseLevel>0) G4cout << "  ykFormula=" << ykFormula<< G4endl;
+ 
+  G4double relativityCorrection = std::pow((1.+(1.1*ykFormula*ykFormula)),0.5)+ykFormula;// the relativistic correction parameter
+    
+    if (verboseLevel>0) G4cout << "  relativityCorrection=" << relativityCorrection<< G4endl;
+
+  G4double reducedVelocity = velocity*std::pow(relativityCorrection,0.5);  // presents the reduced collision velocity parameter 
+    
+    if (verboseLevel>0) G4cout << "  reducedVelocity=" << reducedVelocity<< G4endl;
+
+  G4double etaOverTheta2 = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget)
+                           /(sigmaPSS*tetaK)/(sigmaPSS*tetaK);
+    
+    if (verboseLevel>0) G4cout << "  etaOverTheta2=" << etaOverTheta2<< G4endl;
+
+  G4double universalFunction = 0;
+  
+  // low velocity formula
+  
+  if ( velocity < 1. )
+    {
+      if (verboseLevel>0) G4cout << "  Notice : FK is computed from low velocity formula" << G4endl;
+      
+      universalFunction = (std::pow(2.,9.)/45.)*std::pow(reducedVelocity/sigmaPSS,8.)*std::pow((1.+(1.72*(reducedVelocity/sigmaPSS)*(reducedVelocity/sigmaPSS))),-4.);// is the reduced universal cross section
+      
+      
+      if (verboseLevel>0) G4cout << "  universalFunction by Brandt 1981 =" << universalFunction<< G4endl;
+
+    }
+
+  else
+    
+  {
+    
+    if ( etaOverTheta2 > 86.6 && (sigmaPSS*tetaK) > 0.4 && (sigmaPSS*tetaK) < 2.9996 )
+    {
+      // High and medium energies. Method from Rice 1977 on tabvles from Benka 1978
+      
+      if (verboseLevel>0) G4cout << "  Notice : FK is computed from high velocity formula" << G4endl;
+
+      if (verboseLevel>0) G4cout << "  sigmaPSS*tetaK=" << sigmaPSS*tetaK << G4endl;
+    
+      G4double C1= tableC1->FindValue(sigmaPSS*tetaK);
+      G4double C2= tableC2->FindValue(sigmaPSS*tetaK);
+      G4double C3= tableC3->FindValue(sigmaPSS*tetaK);
+      
+        if (verboseLevel>0) G4cout << "  C1=" << C1 << G4endl;
+        if (verboseLevel>0) G4cout << "  C2=" << C2 << G4endl;
+        if (verboseLevel>0) G4cout << "  C3=" << C3 << G4endl;
+   
+      G4double etaK = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
+      
+        if (verboseLevel>0) G4cout << "  etaK=" << etaK << G4endl;
+
+      G4double etaT = (sigmaPSS*tetaK)*(sigmaPSS*tetaK)*(86.6); // at any theta, the largest tabulated etaOverTheta2 is 86.6
+      
+        if (verboseLevel>0) G4cout << "  etaT=" << etaT << G4endl;
+    
+      G4double fKT = FunctionFK((sigmaPSS*tetaK),86.6)*(etaT/(sigmaPSS*tetaK));
+
+      if (FunctionFK((sigmaPSS*tetaK),86.6)<=0.) 
+	{
+        G4cout << 
+        "*** WARNING in G4AnalyticalEcpssrKCrossSection::CalculateCrossSection : unable to interpolate FK function in high velocity region ! ***" << G4endl;
+	return 0;
+	}
+
+        if (verboseLevel>0) G4cout << "  FunctionFK=" << FunctionFK((sigmaPSS*tetaK),86.6) << G4endl;
+      
+        if (verboseLevel>0) G4cout << "  fKT=" << fKT << G4endl;
+    
+      G4double GK = C2/(4*etaK) + C3/(32*etaK*etaK);
+        
+	if (verboseLevel>0) G4cout << "  GK=" << GK << G4endl;
+      
+      G4double GT = C2/(4*etaT) + C3/(32*etaT*etaT);
+      
+        if (verboseLevel>0) G4cout << "  GT=" << GT << G4endl;
+    
+      G4double DT = fKT - C1*std::log(etaT) + GT;
+      
+        if (verboseLevel>0) G4cout << "  DT=" << DT << G4endl;
+
+      G4double fKK = C1*std::log(etaK) + DT - GK;
+      
+        if (verboseLevel>0) G4cout << "  fKK=" << fKK << G4endl;
+    
+      G4double universalFunction3= fKK/(etaK/tetaK);
+      
+        if (verboseLevel>0) G4cout << "  universalFunction3=" << universalFunction3 << G4endl;
+
+      universalFunction=universalFunction3;
+    
+    }
+    
+    else if ( etaOverTheta2 >= 1.e-3 && etaOverTheta2 <= 86.6 && (sigmaPSS*tetaK) >= 0.4 && (sigmaPSS*tetaK) <= 2.9996 )
+
+    {
+      // From Benka 1978
+      
+      if (verboseLevel>0) G4cout << "  Notice : FK is computed from INTERPOLATED data" << G4endl;
+     
+      G4double universalFunction2 = FunctionFK((sigmaPSS*tetaK),etaOverTheta2);
+
+      if (universalFunction2<=0) 
+      {
+        G4cout << 
+        "*** WARNING : G4AnalyticalEcpssrKCrossSection::CalculateCrossSection is unable to interpolate FK function in medium velocity region ! ***" << G4endl;
+	return 0;
+      }
+      
+      if (verboseLevel>0) G4cout << "  universalFunction2=" << universalFunction2 << " for theta=" << sigmaPSS*tetaK << " and etaOverTheta2=" << etaOverTheta2 << G4endl;
+      
+      universalFunction=universalFunction2;
+    }
+        
+  }
+  
+  //----------------------------------------------------------------------------------------------------------------------
+
+  G4double sigmaPSSR = (sigma0/(sigmaPSS*tetaK))*universalFunction; //sigmaPSSR is the straight-line K-shell ionization cross section
+  
+    if (verboseLevel>0) G4cout << "  sigmaPSSR=" << sigmaPSSR<< G4endl;
+  
+  //-----------------------------------------------------------------------------------------------------------------------
+
+  G4double pssDeltaK = (4./(systemMass*sigmaPSS*tetaK))*(sigmaPSS/velocity)*(sigmaPSS/velocity);
+    
+    if (verboseLevel>0) G4cout << "  pssDeltaK=" << pssDeltaK<< G4endl;
+
+  G4double energyLoss = std::pow(1-pssDeltaK,0.5); //energyLoss incorporates the straight-line energy-loss 
+    
+    if (verboseLevel>0) G4cout << "  energyLoss=" << energyLoss<< G4endl;
+
+  G4double energyLossFunction = (std::pow(2.,-9)/8.)*((((9.*energyLoss)-1.)*std::pow(1.+energyLoss,9.))+(((9.*energyLoss)+1.)*std::pow(1.-energyLoss,9.)));//energy loss function 
+    
+    if (verboseLevel>0) G4cout << "  energyLossFunction=" <<  energyLossFunction<< G4endl;
+
+  //----------------------------------------------------------------------------------------------------------------------------------------------
+
+  G4double coulombDeflection = (4.*pi*zIncident/systemMass)*std::pow(tetaK*sigmaPSS,-2.)*std::pow(velocity/sigmaPSS,-3.)*(zTarget/screenedzTarget); //incorporates Coulomb deflection parameter 
+ 
+    if (verboseLevel>0) G4cout << "  cParameter-short=" << coulombDeflection<< G4endl;
+
+  G4double cParameter = 2.*coulombDeflection/(energyLoss*(energyLoss+1.));
+  
+    if (verboseLevel>0) G4cout << "  cParameter-full=" << cParameter<< G4endl;
+
+  G4double coulombDeflectionFunction = 9.*ExpIntFunction(10,cParameter);                         //this function describes Coulomb-deflection effect
+  
+    if (verboseLevel>0) G4cout << "  ExpIntFunction(10,cParameter) =" << ExpIntFunction(10,cParameter) << G4endl;
+    
+    if (verboseLevel>0) G4cout << "  coulombDeflectionFunction =" << coulombDeflectionFunction << G4endl;
+
+  //--------------------------------------------------------------------------------------------------------------------------------------------------
+ 
+  G4double crossSection =  0;
+  
+  crossSection = energyLossFunction* coulombDeflectionFunction*sigmaPSSR;  //this ECPSSR cross section is estimated at perturbed-stationnairy-state(PSS)
+                                                                           //and it's reduced by the energy-loss(E),the Coulomb deflection(C),
+                                                                           //and the relativity(R) effects
+
+  //--------------------------------------------------------------------------------------------------------------------------------------------------   
+
+  if (crossSection >= 0) {
+    return crossSection;
+  }
+  else {return 0;}
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrKCrossSection::FunctionFK(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; 
+
+  // PROTECTION TO ALLOW INTERPOLATION AT MINIMUM AND MAXIMUM EtaK/Theta2 values 
+  // (in particular for FK computation at 8.66EXX for high velocity formula)
+  
+  if (
+  theta==8.66e-3 ||
+  theta==8.66e-2 ||
+  theta==8.66e-1 ||
+  theta==8.66e+0 ||
+  theta==8.66e+1 
+  ) theta=theta-1e-12;
+
+  if (
+  theta==1.e-3 ||
+  theta==1.e-2 ||
+  theta==1.e-1 ||
+  theta==1.e+00 ||
+  theta==1.e+01
+  ) theta=theta+1e-12;
+
+  // END PROTECTION
+  
+    std::vector<double>::iterator t2 = std::upper_bound(dummyVec.begin(),dummyVec.end(), k);
+    std::vector<double>::iterator t1 = t2-1;
+ 
+    std::vector<double>::iterator e12 = std::upper_bound(aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), theta);
+    std::vector<double>::iterator e11 = e12-1; 
+	  
+    std::vector<double>::iterator e22 = std::upper_bound(aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), theta);
+    std::vector<double>::iterator e21 = e22-1;
+	  	
+    valueT1  =*t1;
+    valueT2  =*t2;
+    valueE21 =*e21;
+    valueE22 =*e22;
+    valueE12 =*e12;
+    valueE11 =*e11;
+
+    xs11 = FKData[valueT1][valueE11];
+    xs12 = FKData[valueT1][valueE12];
+    xs21 = FKData[valueT2][valueE21];
+    xs22 = FKData[valueT2][valueE22];
+
+/*
+    if (verboseLevel>0)
+    {
+      G4cout << "x1= " << valueT1 << G4endl;
+      G4cout << " vector of y for x1" << G4endl;
+        for_each (aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), print);
+      G4cout << G4endl;
+      G4cout << "x2= " << valueT2 << G4endl;
+      G4cout << " vector of y for x2" << G4endl;
+        for_each (aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), print);
+
+      G4cout << G4endl;
+      G4cout 
+        << "  " 
+        << valueT1 << " "
+        << valueT2 << " "
+        << valueE11 << " "
+        << valueE12 << " "
+        << valueE21<< " "
+        << valueE22 << " " 
+        << xs11 << " " 
+        << xs12 << " " 
+        << xs21 << " " 
+        << xs22 << " " 
+        << G4endl;
+    }
+*/
+
+  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 G4AnalyticalEcpssrKCrossSection::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 G4AnalyticalEcpssrKCrossSection::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 G4AnalyticalEcpssrKCrossSection::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;
+}
+
+
+
+
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4AnalyticalEcpssrLiCrossSection.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4AnalyticalEcpssrLiCrossSection.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4AnalyticalEcpssrLiCrossSection.cc	(revision 1316)
@@ -0,0 +1,983 @@
+//
+// ********************************************************************
+// * 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: G4AnalyticalEcpssrLiCrossSection.cc,v 1.1 2010/06/06 23:40:35 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+
+#include "globals.hh"
+#include "G4AnalyticalEcpssrLiCrossSection.hh"
+#include "G4AtomicTransitionManager.hh"
+#include "G4NistManager.hh"
+#include "G4Proton.hh"
+#include "G4Alpha.hh"
+#include <math.h>
+#include <iostream>
+#include "G4LinLogInterpolation.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4AnalyticalEcpssrLiCrossSection::G4AnalyticalEcpssrLiCrossSection()
+{
+
+    // Storing FLi data needed for 0.2 to 3.0  velocities region
+
+    char *path = getenv("G4LEDATA");
+
+    if (!path)
+    G4Exception("G4ecpssrLCrossSection::G4AnalyticalEcpssrLiCrossSection() G4LEDDATA environment variable not set");
+
+    std::ostringstream fileName1;
+    std::ostringstream fileName2;
+    
+    fileName1 << path << "/pixe/uf/FL1.dat";
+    fileName2 << path << "/pixe/uf/FL2.dat";
+
+    // Reading of FL1.dat
+
+    std::ifstream FL1(fileName1.str().c_str());
+    if (!FL1) G4Exception("G4ecpssrLCrossSection::G4AnalyticalEcpssrLiCrossSection() error opening FL1 data file");
+  
+    dummyVec1.push_back(0.);
+
+    while(!FL1.eof())
+    {
+	double x1;
+	double y1;
+
+	FL1>>x1>>y1;
+
+	//  Mandatory vector initialization
+        if (x1 != dummyVec1.back())
+        {
+          dummyVec1.push_back(x1);
+          aVecMap1[x1].push_back(-1.);
+        }
+
+        FL1>>FL1Data[x1][y1];
+
+        if (y1 != aVecMap1[x1].back()) aVecMap1[x1].push_back(y1);
+    }
+
+    // Reading of FL2.dat
+    
+    std::ifstream FL2(fileName2.str().c_str());
+    if (!FL2) G4Exception("G4ecpssrLCrossSection::G4AnalyticalEcpssrLiCrossSection() error opening FL2 data file");
+    
+    dummyVec2.push_back(0.);
+
+    while(!FL2.eof())
+    {
+	double x2;
+	double y2;
+
+	FL2>>x2>>y2;
+
+	//  Mandatory vector initialization
+        if (x2 != dummyVec2.back())
+        {
+          dummyVec2.push_back(x2);
+          aVecMap2[x2].push_back(-1.);
+        }
+
+        FL2>>FL2Data[x2][y2];
+
+        if (y2 != aVecMap2[x2].back()) aVecMap2[x2].push_back(y2);
+    }
+
+    // Verbose level
+    verboseLevel=0;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4AnalyticalEcpssrLiCrossSection::~G4AnalyticalEcpssrLiCrossSection()
+{}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrLiCrossSection::ExpIntFunction(G4int n,G4double x)
+
+{
+// this function allows fast evaluation of the n order exponential integral function En(x)
+
+  G4int i;
+  G4int ii;
+  G4int nm1;
+  G4double a;
+  G4double b;
+  G4double c;
+  G4double d;
+  G4double del;
+  G4double fact;
+  G4double h;
+  G4double psi;
+  G4double ans = 0;
+  const G4double euler= 0.5772156649;
+  const G4int maxit= 100;
+  const G4double fpmin = 1.0e-30;
+  const G4double eps = 1.0e-7;
+  nm1=n-1;
+  if (n<0 || x<0.0 || (x==0.0 && (n==0 || n==1)))
+  G4cout << "bad arguments in ExpIntFunction" << G4endl;
+  else {
+       if (n==0) ans=exp(-x)/x;
+        else {
+           if (x==0.0) ans=1.0/nm1;
+              else {
+                   if (x > 1.0) {
+                         	b=x+n;
+                        	c=1.0/fpmin;
+                        	d=1.0/b;
+				h=d;
+				for (i=1;i<=maxit;i++) {
+				  a=-i*(nm1+i);
+				  b +=2.0;
+				  d=1.0/(a*d+b);
+				  c=b+a/c;
+				  del=c*d;
+				  h *=del;
+				      if (fabs(del-1.0) < eps) {
+					ans=h*exp(-x);
+					return ans;
+				      }
+				}
+		   } else {
+		     ans = (nm1!=0 ? 1.0/nm1 : -log(x)-euler);
+		     fact=1.0;
+		     for (i=1;i<=maxit;i++) {
+		       fact *=-x/i;
+		       if (i !=nm1) del = -fact/(i-nm1);
+		       else {
+			 psi = -euler;
+			 for (ii=1;ii<=nm1;ii++) psi +=1.0/ii;
+			 del=fact*(-log(x)+psi);
+		       }
+		       ans += del;
+		       if (fabs(del) < fabs(ans)*eps) return ans;
+		     }
+		   }
+	      }
+	}
+  }
+return ans;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrLiCrossSection::CalculateL1CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
+{
+
+ //this L1-CrossSection calculation method is done according to Werner Brandt and Grzegorz Lapicki, Phys.Rev.A20 N2 (1979),
+ //and using data tables of O. Benka et al. At.Data Nucl.Data Tables Vol.22 No.3 (1978).
+
+  G4NistManager* massManager = G4NistManager::Instance();
+
+  G4AtomicTransitionManager*  transitionManager =  G4AtomicTransitionManager::Instance();
+
+  G4double  zIncident = 0;
+  G4Proton* aProtone = G4Proton::Proton();
+  G4Alpha* aAlpha = G4Alpha::Alpha();
+
+  if (massIncident == aProtone->GetPDGMass() )
+
+   zIncident = (aProtone->GetPDGCharge())/eplus;
+
+  else
+    {
+      if (massIncident == aAlpha->GetPDGMass())
+
+	  zIncident  = (aAlpha->GetPDGCharge())/eplus;
+
+      else
+	{
+	  G4cout << "*** WARNING in G4AnalyticalEcpssrLiCrossSection::CalculateL1CrossSection : Proton or Alpha incident particles only. " << G4endl;
+	  G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
+	  return 0;
+	}
+    }
+
+  G4double l1BindingEnergy = transitionManager->Shell(zTarget,1)->BindingEnergy(); //Observed binding energy of L1-subshell
+
+  G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
+
+  G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2; //Mass of the system (projectile, target)
+
+  const G4double zlshell= 4.15;
+
+  G4double screenedzTarget = zTarget-zlshell; //Effective nuclear charge as seen by electrons in L1-sub shell
+
+  const G4double rydbergMeV= 13.6056923e-6;
+
+  const G4double nl= 2.;
+
+  G4double tetal1 = (l1BindingEnergy*nl*nl)/((screenedzTarget*screenedzTarget)*rydbergMeV); //Screening parameter
+
+    if (verboseLevel>0) G4cout << "  tetal1=" <<  tetal1<< G4endl;
+
+  G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
+
+  const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ; //Bohr radius of hydrogen
+
+  G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);
+
+  G4double velocityl1 = CalculateVelocity(1, zTarget, massIncident, energyIncident); // Scaled velocity
+
+    if (verboseLevel>0) G4cout << "  velocityl1=" << velocityl1<< G4endl;
+
+  const G4double l1AnalyticalApproximation= 1.5;
+
+  G4double x1 =(nl*l1AnalyticalApproximation)/velocityl1;
+
+   if (verboseLevel>0) G4cout << "  x1=" << x1<< G4endl;
+
+  G4double electrIonizationEnergyl1=0.;
+
+  if ( x1<=0.035)  electrIonizationEnergyl1= 0.75*pi*(log(1./(x1*x1))-1.);
+  else
+    {
+      if ( x1<=3.)
+        electrIonizationEnergyl1 =exp(-2.*x1)/(0.031+(0.213*pow(x1,0.5))+(0.005*x1)-(0.069*pow(x1,3./2.))+(0.324*x1*x1));
+      else
+	{if ( x1<=11.) electrIonizationEnergyl1 =2.*exp(-2.*x1)/pow(x1,1.6);}
+    }
+
+  G4double hFunctionl1 =(electrIonizationEnergyl1*2.*nl)/(tetal1*pow(velocityl1,3)); //takes into account the polarization effect
+
+    if (verboseLevel>0) G4cout << "  hFunctionl1=" << hFunctionl1<< G4endl;
+
+  G4double gFunctionl1 = (1.+(9.*velocityl1)+(31.*velocityl1*velocityl1)+(49.*pow(velocityl1,3.))+(162.*pow(velocityl1,4.))+(63.*pow(velocityl1,5.))+(18.*pow(velocityl1,6.))+(1.97*pow(velocityl1,7.)))/pow(1.+velocityl1,9.);//takes into account the reduced binding effect
+
+    if (verboseLevel>0) G4cout << "  gFunctionl1=" << gFunctionl1<< G4endl;
+
+  G4double sigmaPSS_l1 = 1.+(((2.*zIncident)/(screenedzTarget*tetal1))*(gFunctionl1-hFunctionl1)); //Binding-polarization factor
+
+    if (verboseLevel>0) G4cout << "sigmaPSS_l1 =" << sigmaPSS_l1<< G4endl;
+
+const G4double cNaturalUnit= 137.;
+  
+G4double yl1Formula=0.4*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(nl*velocityl1/sigmaPSS_l1);
+    
+G4double l1relativityCorrection = std::pow((1.+(1.1*yl1Formula*yl1Formula)),0.5)+yl1Formula; // Relativistic correction parameter
+  
+//G4double reducedVelocity_l1 = velocityl1*std::pow(l1relativityCorrection,0.5); //Reduced velocity parameter
+
+
+G4double L1etaOverTheta2;
+
+G4double  universalFunction_l1 = 0.;
+
+G4double sigmaPSSR_l1;
+
+if ( velocityl1 <5.  )
+  {
+
+L1etaOverTheta2 =(reducedEnergy* l1relativityCorrection)/((tetal1*sigmaPSS_l1)*(tetal1*sigmaPSS_l1));
+    
+ if ( ((tetal1*sigmaPSS_l1) >=0.2) && ((tetal1*sigmaPSS_l1) <=2.6670) && (L1etaOverTheta2>=0.1e-3) && (L1etaOverTheta2<=0.866e2) )
+  
+universalFunction_l1 = FunctionFL1((tetal1*sigmaPSS_l1),L1etaOverTheta2);
+
+ if (verboseLevel>0) G4cout << "at low velocity range, universalFunction_l1  =" << universalFunction_l1 << G4endl;
+
+sigmaPSSR_l1 = (sigma0/(tetal1*sigmaPSS_l1))*universalFunction_l1;// Plane-wave Born -Aproximation L1-subshell ionisation Cross Section
+
+ if (verboseLevel>0) G4cout << "  at low velocity range, sigma PWBA L1 CS  = " << sigmaPSSR_l1<< G4endl;
+
+
+}
+
+else
+
+{
+
+ L1etaOverTheta2 = reducedEnergy/(tetal1*tetal1);
+
+ if ( (tetal1 >=0.2) && (tetal1 <=2.6670) && (L1etaOverTheta2>=0.1e-3) && (L1etaOverTheta2<=0.866e2) ) 
+    
+universalFunction_l1 = FunctionFL1(tetal1,L1etaOverTheta2);
+
+if (verboseLevel>0) G4cout << "at medium and high velocity range, universalFunction_l1  =" << universalFunction_l1 << G4endl;
+
+sigmaPSSR_l1 = (sigma0/tetal1)*universalFunction_l1;// Plane-wave Born -Aproximation L1-subshell ionisation Cross Section
+
+ if (verboseLevel>0) G4cout << "  sigma PWBA L1 CS at medium and high velocity range = " << sigmaPSSR_l1<< G4endl;    
+}
+ 
+ G4double pssDeltal1 = (4./(systemMass *sigmaPSS_l1*tetal1))*(sigmaPSS_l1/velocityl1)*(sigmaPSS_l1/velocityl1);
+
+    if (verboseLevel>0) G4cout << "  pssDeltal1=" << pssDeltal1<< G4endl;
+
+  G4double energyLossl1 = pow(1-pssDeltal1,0.5);
+
+    if (verboseLevel>0) G4cout << "  energyLossl1=" << energyLossl1<< G4endl;
+
+  G4double coulombDeflectionl1 = 
+(8.*pi*zIncident/systemMass)*pow(tetal1*sigmaPSS_l1,-2.)*pow(velocityl1/sigmaPSS_l1,-3.)*(zTarget/screenedzTarget);
+
+ G4double cParameterl1 =2.* coulombDeflectionl1/(energyLossl1*(energyLossl1+1.));
+
+  G4double coulombDeflectionFunction_l1 = 9.*ExpIntFunction(10,cParameterl1); //Coulomb-deflection effect correction
+
+ if (verboseLevel>0) G4cout << "  coulombDeflectionFunction_l1 =" << coulombDeflectionFunction_l1 << G4endl;
+
+G4double crossSection_L1 = coulombDeflectionFunction_l1 * sigmaPSSR_l1;
+
+  //ECPSSR L1 -subshell cross section is estimated at perturbed-stationnairy-state(PSS)
+  //and reduced by the energy-loss(E),the Coulomb deflection(C),and the relativity(R) effects
+
+    if (verboseLevel>0) G4cout << "  crossSection_L1 =" << crossSection_L1 << G4endl;
+
+  if (crossSection_L1 >= 0) {
+
+    return crossSection_L1;
+  }
+  
+  else {return 0;}
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrLiCrossSection::CalculateL2CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
+
+{
+
+  // this L2-CrossSection calculation method is done according to Werner Brandt and Grzegorz Lapicki, Phys.Rev.A20 N2 (1979),
+  // and using data tables of O. Benka et al. At.Data Nucl.Data Tables Vol.22 No.3 (1978).
+
+  G4NistManager* massManager = G4NistManager::Instance();
+
+  G4AtomicTransitionManager*  transitionManager =  G4AtomicTransitionManager::Instance();
+
+  G4double  zIncident = 0;
+  
+  G4Proton* aProtone = G4Proton::Proton();
+  G4Alpha* aAlpha = G4Alpha::Alpha();
+
+  if (massIncident == aProtone->GetPDGMass() )
+
+   zIncident = (aProtone->GetPDGCharge())/eplus;
+
+  else
+    {
+      if (massIncident == aAlpha->GetPDGMass())
+
+	  zIncident  = (aAlpha->GetPDGCharge())/eplus;
+
+      else
+	{
+	  G4cout << "*** WARNING in G4AnalyticalEcpssrLiCrossSection::CalculateL2CrossSection : Proton or Alpha incident particles only. " << G4endl;
+	  G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
+	  return 0;
+	}
+    }
+
+  G4double l2BindingEnergy = transitionManager->Shell(zTarget,2)->BindingEnergy(); //Observed binding energy of L2-subshell
+
+  G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
+
+  G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2; //Mass of the system (projectile, target)
+
+  const G4double zlshell= 4.15;
+
+  G4double screenedzTarget = zTarget-zlshell; //Effective nuclear charge as seen by electrons in L2-subshell
+
+  const G4double rydbergMeV= 13.6056923e-6;
+
+  const G4double nl= 2.;
+
+  G4double tetal2 = (l2BindingEnergy*nl*nl)/((screenedzTarget*screenedzTarget)*rydbergMeV); //Screening parameter
+
+    if (verboseLevel>0) G4cout << "  tetal2=" <<  tetal2<< G4endl;
+
+  G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget); 
+
+  const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ; //Bohr radius of hydrogen
+
+  G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);
+
+  G4double velocityl2 = CalculateVelocity(2,  zTarget, massIncident, energyIncident); // Scaled velocity
+
+    if (verboseLevel>0) G4cout << "  velocityl2=" << velocityl2<< G4endl;
+
+  const G4double l23AnalyticalApproximation= 1.25;
+
+  G4double x2 = (nl*l23AnalyticalApproximation)/velocityl2;
+    
+    if (verboseLevel>0) G4cout << "  x2=" << x2<< G4endl;
+
+  G4double electrIonizationEnergyl2=0.;
+
+  if ( x2<=0.035)  electrIonizationEnergyl2= 0.75*pi*(log(1./(x2*x2))-1.);
+  else
+    {
+      if ( x2<=3.)
+        electrIonizationEnergyl2 =exp(-2.*x2)/(0.031+(0.210*pow(x2,0.5))+(0.005*x2)-(0.069*pow(x2,3./2.))+(0.324*x2*x2));
+      else
+        {if ( x2<=11.) electrIonizationEnergyl2 =2.*exp(-2.*x2)/pow(x2,1.6);  }
+    }
+
+ G4double hFunctionl2 =(electrIonizationEnergyl2*2.*nl)/(tetal2*pow(velocityl2,3)); //takes into account  the polarization effect
+
+   if (verboseLevel>0) G4cout << "  hFunctionl2=" << hFunctionl2<< G4endl;
+
+  G4double gFunctionl2 = (1.+(10.*velocityl2)+(45.*velocityl2*velocityl2)+(102.*pow(velocityl2,3.))+(331.*pow(velocityl2,4.))+(6.7*pow(velocityl2,5.))+(58.*pow(velocityl2,6.))+(7.8*pow(velocityl2,7.))+ (0.888*pow(velocityl2,8.)) )/pow(1.+velocityl2,10.);
+  //takes into account the reduced binding effect
+
+    if (verboseLevel>0) G4cout << "  gFunctionl2=" << gFunctionl2<< G4endl;
+
+  G4double sigmaPSS_l2 = 1.+(((2.*zIncident)/(screenedzTarget*tetal2))*(gFunctionl2-hFunctionl2)); //Binding-polarization factor
+
+    if (verboseLevel>0) G4cout << "  sigmaPSS_l2=" << sigmaPSS_l2<< G4endl;
+
+const G4double cNaturalUnit= 137.;
+     
+G4double yl2Formula=0.15*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocityl2/sigmaPSS_l2);
+  
+G4double l2relativityCorrection = std::pow((1.+(1.1*yl2Formula*yl2Formula)),0.5)+yl2Formula; // Relativistic correction parameter
+    
+
+G4double L2etaOverTheta2;
+
+G4double  universalFunction_l2 = 0.;
+
+G4double sigmaPSSR_l2 ;
+ 
+if ( velocityl2 < 5. )
+  {
+
+L2etaOverTheta2 = (reducedEnergy*l2relativityCorrection)/((sigmaPSS_l2*tetal2)*(sigmaPSS_l2*tetal2));
+
+if ( (tetal2*sigmaPSS_l2>=0.2) && (tetal2*sigmaPSS_l2<=2.6670) && (L2etaOverTheta2>=0.1e-3) && (L2etaOverTheta2<=0.866e2) )
+
+universalFunction_l2 = FunctionFL2((tetal2*sigmaPSS_l2),L2etaOverTheta2);
+
+sigmaPSSR_l2 = (sigma0/(tetal2*sigmaPSS_l2))*universalFunction_l2;
+
+ if (verboseLevel>0) G4cout << "  sigma PWBA L2 CS at low velocity range = " << sigmaPSSR_l2<< G4endl;
+
+}    
+
+else
+
+{ 
+    
+L2etaOverTheta2 = reducedEnergy /(tetal2*tetal2);
+
+if ( (tetal2>=0.2) && (tetal2<=2.6670) && (L2etaOverTheta2>=0.1e-3) && (L2etaOverTheta2<=0.866e2) )
+
+universalFunction_l2 = FunctionFL2((tetal2),L2etaOverTheta2);
+   
+sigmaPSSR_l2 = (sigma0/tetal2)*universalFunction_l2;
+
+ if (verboseLevel>0) G4cout << "  sigma PWBA L2 CS at medium and high velocity range = " << sigmaPSSR_l2<< G4endl;
+
+}
+ 
+G4double pssDeltal2 = (4./(systemMass*sigmaPSS_l2*tetal2))*(sigmaPSS_l2/velocityl2)*(sigmaPSS_l2/velocityl2);
+
+G4double energyLossl2 = pow(1-pssDeltal2,0.5);
+ 
+  if (verboseLevel>0) G4cout << "  energyLossl2=" << energyLossl2<< G4endl;
+
+  G4double coulombDeflectionl2 
+=(8.*pi*zIncident/systemMass)*pow(tetal2*sigmaPSS_l2,-2.)*pow(velocityl2/sigmaPSS_l2,-3.)*(zTarget/screenedzTarget);
+
+  G4double cParameterl2 = 2.*coulombDeflectionl2/(energyLossl2*(energyLossl2+1.));
+
+  G4double coulombDeflectionFunction_l2 = 11.*ExpIntFunction(12,cParameterl2); //Coulomb-deflection effect correction
+
+    if (verboseLevel>0) G4cout << "  coulombDeflectionFunction_l2 =" << coulombDeflectionFunction_l2 << G4endl;
+
+  G4double crossSection_L2 = coulombDeflectionFunction_l2 * sigmaPSSR_l2;
+  //ECPSSR L2 -subshell cross section is estimated at perturbed-stationnairy-state(PSS)
+  //and reduced by the energy-loss(E),the Coulomb deflection(C),and the relativity(R) effects
+
+    if (verboseLevel>0) G4cout << "  crossSection_L2 =" << crossSection_L2 << G4endl;
+
+  if (crossSection_L2 >= 0) {
+     return crossSection_L2;
+      }
+  else {return 0;}
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4double G4AnalyticalEcpssrLiCrossSection::CalculateL3CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
+
+{
+
+  //this L3-CrossSection calculation method is done according to Werner Brandt and Grzegorz Lapicki, Phys.Rev.A20 N2 (1979),
+  //and using data tables of O. Benka et al. At.Data Nucl.Data Tables Vol.22 No.3 (1978).
+
+  G4NistManager* massManager = G4NistManager::Instance();
+
+  G4AtomicTransitionManager*  transitionManager =  G4AtomicTransitionManager::Instance();
+
+  G4double  zIncident = 0;
+
+  G4Proton* aProtone = G4Proton::Proton();
+  G4Alpha* aAlpha = G4Alpha::Alpha();
+
+  if (massIncident == aProtone->GetPDGMass() )
+
+   zIncident = (aProtone->GetPDGCharge())/eplus;
+
+  else
+    {
+      if (massIncident == aAlpha->GetPDGMass())
+
+	  zIncident  = (aAlpha->GetPDGCharge())/eplus;
+
+      else
+	{
+	  G4cout << "*** WARNING in G4AnalyticalEcpssrLiCrossSection::CalculateL3CrossSection : Proton or Alpha incident particles only. " << G4endl;
+	  G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
+	  return 0;
+	}
+    }
+
+  G4double l3BindingEnergy = transitionManager->Shell(zTarget,3)->BindingEnergy();
+
+  G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
+
+  G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2;//Mass of the system (projectile, target)
+
+  const G4double zlshell= 4.15;
+
+  G4double screenedzTarget = zTarget-zlshell;//Effective nuclear charge as seen by electrons in L3-subshell
+
+  const G4double rydbergMeV= 13.6056923e-6;
+
+  const G4double nl= 2.;
+
+  G4double tetal3 = (l3BindingEnergy*nl*nl)/((screenedzTarget*screenedzTarget)*rydbergMeV);//Screening parameter
+
+    if (verboseLevel>0) G4cout << "  tetal3=" <<  tetal3<< G4endl;
+
+  G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
+
+  const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ;//Bohr radius of hydrogen
+
+  G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);
+
+  G4double velocityl3 = CalculateVelocity(3, zTarget, massIncident, energyIncident);// Scaled velocity
+
+    if (verboseLevel>0) G4cout << "  velocityl3=" << velocityl3<< G4endl;
+
+  const G4double l23AnalyticalApproximation= 1.25;
+
+  G4double x3 = (nl*l23AnalyticalApproximation)/velocityl3;
+
+    if (verboseLevel>0) G4cout << "  x3=" << x3<< G4endl;
+
+  G4double electrIonizationEnergyl3=0.;
+
+  if ( x3<=0.035)  electrIonizationEnergyl3= 0.75*pi*(log(1./(x3*x3))-1.);
+    else
+    {
+      if ( x3<=3.) electrIonizationEnergyl3 =exp(-2.*x3)/(0.031+(0.210*pow(x3,0.5))+(0.005*x3)-(0.069*pow(x3,3./2.))+(0.324*x3*x3));
+      else
+	{
+	  if ( x3<=11.) electrIonizationEnergyl3 =2.*exp(-2.*x3)/pow(x3,1.6);}
+    }
+
+  G4double hFunctionl3 =(electrIonizationEnergyl3*2.*nl)/(tetal3*pow(velocityl3,3));//takes into account the polarization effect
+
+    if (verboseLevel>0) G4cout << "  hFunctionl3=" << hFunctionl3<< G4endl;
+
+  G4double gFunctionl3 = (1.+(10.*velocityl3)+(45.*velocityl3*velocityl3)+(102.*pow(velocityl3,3.))+(331.*pow(velocityl3,4.))+(6.7*pow(velocityl3,5.))+(58.*pow(velocityl3,6.))+(7.8*pow(velocityl3,7.))+ (0.888*pow(velocityl3,8.)) )/pow(1.+velocityl3,10.);
+  //takes into account the reduced binding effect
+
+    if (verboseLevel>0) G4cout << "  gFunctionl3=" << gFunctionl3<< G4endl;
+
+  G4double sigmaPSS_l3 = 1.+(((2.*zIncident)/(screenedzTarget*tetal3))*(gFunctionl3-hFunctionl3));//Binding-polarization factor
+
+    if (verboseLevel>0) G4cout << "sigmaPSS_l3 =" << sigmaPSS_l3<< G4endl;
+
+const G4double cNaturalUnit= 137.;
+        
+G4double yl3Formula=0.15*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocityl3/sigmaPSS_l3);
+        
+G4double l3relativityCorrection = std::pow((1.+(1.1*yl3Formula*yl3Formula)),0.5)+yl3Formula; // Relativistic correction parameter
+  
+G4double L3etaOverTheta2;
+ 
+G4double  universalFunction_l3 = 0.;
+ 
+G4double sigmaPSSR_l3;
+
+if ( velocityl3 < 5. )
+  {
+
+L3etaOverTheta2 = (reducedEnergy* l3relativityCorrection)/((sigmaPSS_l3*tetal3)*(sigmaPSS_l3*tetal3));
+
+if ( (tetal3*sigmaPSS_l3>=0.2) && (tetal3*sigmaPSS_l3<=2.6670) && (L3etaOverTheta2>=0.1e-3) && (L3etaOverTheta2<=0.866e2) )
+
+universalFunction_l3 = 2.*FunctionFL2((tetal3*sigmaPSS_l3), L3etaOverTheta2  );
+
+sigmaPSSR_l3 = (sigma0/(tetal3*sigmaPSS_l3))*universalFunction_l3;
+
+ if (verboseLevel>0) G4cout << "  sigma PWBA L3 CS at low velocity range = " << sigmaPSSR_l3<< G4endl;
+
+}
+
+else 
+
+{
+
+ L3etaOverTheta2 = reducedEnergy/(tetal3*tetal3);
+
+if ( (tetal3>=0.2) && (tetal3<=2.6670) && (L3etaOverTheta2>=0.1e-3) && (L3etaOverTheta2<=0.866e2) ) 
+     
+universalFunction_l3 = 2.*FunctionFL2(tetal3, L3etaOverTheta2  );
+
+ sigmaPSSR_l3 = (sigma0/tetal3)*universalFunction_l3;
+
+ if (verboseLevel>0) G4cout << "  sigma PWBA L3 CS at medium and high velocity range = " << sigmaPSSR_l3<< G4endl;
+
+}
+  
+G4double pssDeltal3 = (4./(systemMass*sigmaPSS_l3*tetal3))*(sigmaPSS_l3/velocityl3)*(sigmaPSS_l3/velocityl3);
+
+if (verboseLevel>0) G4cout << "  pssDeltal3=" << pssDeltal3<< G4endl;
+
+G4double energyLossl3 = pow(1-pssDeltal3,0.5);
+
+if (verboseLevel>0) G4cout << "  energyLossl3=" << energyLossl3<< G4endl;
+
+  G4double coulombDeflectionl3 = 
+(8.*pi*zIncident/systemMass)*pow(tetal3*sigmaPSS_l3,-2.)*pow(velocityl3/sigmaPSS_l3,-3.)*(zTarget/screenedzTarget);
+
+  G4double cParameterl3 = 2.*coulombDeflectionl3/(energyLossl3*(energyLossl3+1.));
+
+  G4double coulombDeflectionFunction_l3 = 11.*ExpIntFunction(12,cParameterl3);//Coulomb-deflection effect correction
+
+    if (verboseLevel>0) G4cout << "  coulombDeflectionFunction_l3 =" << coulombDeflectionFunction_l3 << G4endl;
+
+  G4double crossSection_L3 =  coulombDeflectionFunction_l3 * sigmaPSSR_l3;
+  //ECPSSR L3 -subshell cross section is estimated at perturbed-stationnairy-state(PSS)
+  //and reduced by the energy-loss(E),the Coulomb deflection(C),and the relativity(R) effects
+
+    if (verboseLevel>0) G4cout << "  crossSection_L3 =" << crossSection_L3 << G4endl;
+ 
+  if (crossSection_L3 >= 0) {
+    return crossSection_L3;
+  }
+  else {return 0;}
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrLiCrossSection::CalculateVelocity(G4int subShell, G4int zTarget, G4double massIncident,  G4double energyIncident)
+
+{
+
+  G4AtomicTransitionManager*  transitionManager =  G4AtomicTransitionManager::Instance();
+
+  G4double liBindingEnergy = transitionManager->Shell(zTarget,subShell)->BindingEnergy();
+
+  G4Proton* aProtone = G4Proton::Proton();
+  G4Alpha* aAlpha = G4Alpha::Alpha();
+
+  if (!((massIncident == aProtone->GetPDGMass()) || (massIncident == aAlpha->GetPDGMass())))
+    {
+      G4cout << "*** WARNING in G4AnalyticalEcpssrLiCrossSection::CalculateVelocity : Proton or Alpha incident particles only. " << G4endl;
+      G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
+      return 0;
+    }
+
+  const G4double zlshell= 4.15;
+
+  G4double screenedzTarget = zTarget- zlshell;
+
+  const G4double rydbergMeV= 13.6056923e-6;
+
+  const G4double nl= 2.;
+
+  G4double tetali = (liBindingEnergy*nl*nl)/(screenedzTarget*screenedzTarget*rydbergMeV);
+
+  G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
+
+  G4double velocity = 2.*nl*std::pow(reducedEnergy,0.5)/tetali;
+
+  return velocity;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrLiCrossSection::FunctionFL1(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;
+
+  // PROTECTION TO ALLOW INTERPOLATION AT MINIMUM AND MAXIMUM Eta/Theta2 values
+
+  if (
+       theta==8.66e-4 ||
+       theta==8.66e-3 ||
+       theta==8.66e-2 ||
+       theta==8.66e-1 ||
+       theta==8.66e+00 ||
+       theta==8.66e+01
+  ) theta=theta-1e-12;
+
+  if (
+       theta==1.e-4 ||
+       theta==1.e-3 ||
+       theta==1.e-2 ||
+       theta==1.e-1 ||
+       theta==1.e+00 ||
+       theta==1.e+01
+  ) theta=theta+1e-12;
+
+  // END PROTECTION
+
+    std::vector<double>::iterator t2 = std::upper_bound(dummyVec1.begin(),dummyVec1.end(), k);
+    std::vector<double>::iterator t1 = t2-1;
+
+    std::vector<double>::iterator e12 = std::upper_bound(aVecMap1[(*t1)].begin(),aVecMap1[(*t1)].end(), theta);
+    std::vector<double>::iterator e11 = e12-1;
+
+    std::vector<double>::iterator e22 = std::upper_bound(aVecMap1[(*t2)].begin(),aVecMap1[(*t2)].end(), theta);
+    std::vector<double>::iterator e21 = e22-1;
+
+    valueT1  =*t1;
+    valueT2  =*t2;
+    valueE21 =*e21;
+    valueE22 =*e22;
+    valueE12 =*e12;
+    valueE11 =*e11;
+
+    xs11 = FL1Data[valueT1][valueE11];
+    xs12 = FL1Data[valueT1][valueE12];
+    xs21 = FL1Data[valueT2][valueE21];
+    xs22 = FL1Data[valueT2][valueE22];
+
+  if (verboseLevel>0) 
+    G4cout 
+    << valueT1 << " "
+    << valueT2 << " "
+    << valueE11 << " "
+    << valueE12 << " "
+    << valueE21 << " "
+    << valueE22 << " "
+    << xs11 << " "
+    << xs12 << " "
+    << xs21 << " "
+    << xs22 << " "
+    << G4endl;
+
+  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 G4AnalyticalEcpssrLiCrossSection::FunctionFL2(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;
+
+  // PROTECTION TO ALLOW INTERPOLATION AT MINIMUM AND MAXIMUM Eta/Theta2 values
+
+  if (
+       theta==8.66e-4 ||
+       theta==8.66e-3 ||
+       theta==8.66e-2 ||
+       theta==8.66e-1 ||
+       theta==8.66e+00 ||
+       theta==8.66e+01
+  ) theta=theta-1e-12;
+
+  if (
+       theta==1.e-4 ||
+       theta==1.e-3 ||
+       theta==1.e-2 ||
+       theta==1.e-1 ||
+       theta==1.e+00 ||
+       theta==1.e+01
+  ) theta=theta+1e-12;
+
+  // END PROTECTION
+
+    std::vector<double>::iterator t2 = std::upper_bound(dummyVec2.begin(),dummyVec2.end(), k);
+    std::vector<double>::iterator t1 = t2-1;
+
+    std::vector<double>::iterator e12 = std::upper_bound(aVecMap2[(*t1)].begin(),aVecMap2[(*t1)].end(), theta);
+    std::vector<double>::iterator e11 = e12-1;
+
+    std::vector<double>::iterator e22 = std::upper_bound(aVecMap2[(*t2)].begin(),aVecMap2[(*t2)].end(), theta);
+    std::vector<double>::iterator e21 = e22-1;
+
+    valueT1  =*t1;
+    valueT2  =*t2;
+    valueE21 =*e21;
+    valueE22 =*e22;
+    valueE12 =*e12;
+    valueE11 =*e11;
+
+    xs11 = FL2Data[valueT1][valueE11];
+    xs12 = FL2Data[valueT1][valueE12];
+    xs21 = FL2Data[valueT2][valueE21];
+    xs22 = FL2Data[valueT2][valueE22];
+
+  if (verboseLevel>0) 
+    G4cout 
+    << valueT1 << " "
+    << valueT2 << " "
+    << valueE11 << " "
+    << valueE12 << " "
+    << valueE21 << " "
+    << valueE22 << " "
+    << xs11 << " "
+    << xs12 << " "
+    << xs21 << " "
+    << xs22 << " "
+    << G4endl;
+
+  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 G4AnalyticalEcpssrLiCrossSection::LinLinInterpolate(G4double e1,
+						        G4double e2,
+						        G4double e,
+						        G4double xs1,
+						        G4double xs2)
+{
+  G4double value = xs1 + (xs2 - xs1)*(e - e1)/ (e2 - e1);
+  return value;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4AnalyticalEcpssrLiCrossSection::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 G4AnalyticalEcpssrLiCrossSection::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 G4AnalyticalEcpssrLiCrossSection::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);
+*/
+
+/*
+// Lin-Lin
+  G4double interpolatedvalue1 = LinLinInterpolate(e11, e12, e, xs11, xs12);
+  G4double interpolatedvalue2 = LinLinInterpolate(e21, e22, e, xs21, xs22);
+  G4double value = LinLinInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
+*/
+  return value;
+
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08ComptonModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08ComptonModel.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08ComptonModel.cc	(revision 1316)
@@ -0,0 +1,840 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08ComptonModel.cc,v 1.6 2010/04/12 13:53:29 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 15 Feb 2010   L Pandola    Implementation
+// 18 Mar 2010   L. Pandola   Removed GetAtomsPerMolecule(), now demanded 
+//                            to G4PenelopeOscillatorManager
+//
+#include "G4Penelope08ComptonModel.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4MaterialCutsCouple.hh"
+#include "G4ProductionCutsTable.hh"
+#include "G4DynamicParticle.hh"
+#include "G4VEMDataSet.hh"
+#include "G4PhysicsTable.hh"
+#include "G4ElementTable.hh"
+#include "G4Element.hh"
+#include "G4PhysicsLogVector.hh"
+#include "G4AtomicTransitionManager.hh"
+#include "G4AtomicShell.hh"
+#include "G4Gamma.hh"
+#include "G4Electron.hh"
+#include "G4PenelopeOscillatorManager.hh"
+#include "G4PenelopeOscillator.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4Penelope08ComptonModel::G4Penelope08ComptonModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+  :G4VEmModel(nam),isInitialised(false),oscManager(0)
+{
+  fIntrinsicLowEnergyLimit = 100.0*eV;
+  fIntrinsicHighEnergyLimit = 100.0*GeV;
+  //  SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
+  SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
+  //
+  oscManager = G4PenelopeOscillatorManager::GetOscillatorManager();
+
+  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
+
+  //by default, the model will use atomic deexcitation
+  SetDeexcitationFlag(true);
+  ActivateAuger(false);
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4Penelope08ComptonModel::~G4Penelope08ComptonModel()
+{;}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08ComptonModel::Initialise(const G4ParticleDefinition*,
+					  const G4DataVector&)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling G4Penelope08ComptonModel::Initialise()" << G4endl;
+
+  if (verboseLevel > 0) {
+    G4cout << "Penelope Compton model is initialized " << G4endl
+	   << "Energy range: "
+	   << LowEnergyLimit() / keV << " keV - "
+	   << HighEnergyLimit() / GeV << " GeV"
+	   << G4endl;
+  }
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForGamma();
+  isInitialised = true; 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08ComptonModel::CrossSectionPerVolume(const G4Material* material,
+                                               const G4ParticleDefinition* p,
+                                               G4double energy,
+                                               G4double,
+                                               G4double)
+{
+  // Penelope model to calculate the Compton scattering cross section:
+  // D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
+  // 
+  // The cross section for Compton scattering is calculated according to the Klein-Nishina 
+  // formula for energy > 5 MeV.
+  // For E < 5 MeV it is used a parametrization for the differential cross-section dSigma/dOmega,
+  // which is integrated numerically in cos(theta), G4Penelope08ComptonModel::DifferentialCrossSection().
+  // The parametrization includes the J(p) 
+  // distribution profiles for the atomic shells, that are tabulated from Hartree-Fock calculations 
+  // from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201
+  //
+  if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerVolume() of G4Penelope08ComptonModel" << G4endl;
+ SetupForMaterial(p, material, energy);
+
+  //Retrieve the oscillator table for this material
+  G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableCompton(material);
+
+  G4double cs = 0;
+
+  if (energy < 5*MeV) //explicit calculation for E < 5 MeV
+    {
+      size_t numberOfOscillators = theTable->size();
+      for (size_t i=0;i<numberOfOscillators;i++)
+	{
+	  G4PenelopeOscillator* theOsc = (*theTable)[i];
+	  //sum contributions coming from each oscillator
+	  cs += OscillatorTotalCrossSection(energy,theOsc);
+	}
+    }
+  else //use Klein-Nishina for E>5 MeV
+    cs = KleinNishinaCrossSection(energy,material);
+       
+  //cross sections are in units of pi*classic_electr_radius^2
+  cs *= pi*classic_electr_radius*classic_electr_radius;
+
+  //Now, cs is the cross section *per molecule*, let's calculate the 
+  //cross section per volume
+
+  G4double atomDensity = material->GetTotNbOfAtomsPerVolume();
+  G4double atPerMol =  oscManager->GetAtomsPerMolecule(material);
+
+  if (verboseLevel > 3)
+    G4cout << "Material " << material->GetName() << " has " << atPerMol << 
+      "atoms per molecule" << G4endl;
+
+  G4double moleculeDensity = 0.;
+
+  if (atPerMol)
+    moleculeDensity = atomDensity/atPerMol;
+
+  G4double csvolume = cs*moleculeDensity;
+  
+  if (verboseLevel > 2)
+    G4cout << "Compton mean free path at " << energy/keV << " keV for material " << 
+            material->GetName() << " = " << (1./csvolume)/mm << " mm" << G4endl;
+  return csvolume;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+//This is a dummy method. Never inkoved by the tracking, it just issues
+//a warning if one tries to get Cross Sections per Atom via the
+//G4EmCalculator.
+G4double G4Penelope08ComptonModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+                                                             G4double,
+                                                             G4double,
+                                                             G4double,
+                                                             G4double,
+                                                             G4double)
+{
+  G4cout << "*** G4Penelope08ComptonModel -- WARNING ***" << G4endl;
+  G4cout << "Penelope Compton model does not calculate cross section _per atom_ " << G4endl;
+  G4cout << "so the result is always zero. For physics values, please invoke " << G4endl;
+  G4cout << "GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" << G4endl;
+  return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08ComptonModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+					      const G4MaterialCutsCouple* couple,
+					      const G4DynamicParticle* aDynamicGamma,
+					      G4double,
+					      G4double)
+{
+  
+  // Penelope model to sample the Compton scattering final state.
+  // D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
+  // The model determines also the original shell from which the electron is expelled, 
+  // in order to produce fluorescence de-excitation (from G4DeexcitationManager)
+  // 
+  // The final state for Compton scattering is calculated according to the Klein-Nishina 
+  // formula for energy > 5 MeV. In this case, the Doppler broadening is negligible and 
+  // one can assume that the target electron is at rest.
+  // For E < 5 MeV it is used the parametrization for the differential cross-section dSigma/dOmega,
+  // to sample the scattering angle and the energy of the emerging electron, which is  
+  // G4Penelope08ComptonModel::DifferentialCrossSection(). The rejection method is 
+  // used to sample cos(theta). The efficiency increases monotonically with photon energy and is 
+  // nearly independent on the Z; typical values are 35%, 80% and 95% for 1 keV, 1 MeV and 10 MeV, 
+  // respectively.
+  // The parametrization includes the J(p) distribution profiles for the atomic shells, that are 
+  // tabulated 
+  // from Hartree-Fock calculations from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201. 
+  // Doppler broadening is included.
+  //
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SampleSecondaries() of G4Penelope08ComptonModel" << G4endl;
+  
+  G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
+
+  if (photonEnergy0 <= fIntrinsicLowEnergyLimit)
+    {
+      fParticleChange->ProposeTrackStatus(fStopAndKill);
+      fParticleChange->SetProposedKineticEnergy(0.);
+      fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
+      return ;
+    }
+
+  G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
+  const G4Material* material = couple->GetMaterial();
+
+  G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableCompton(material); 
+
+  const G4int nmax = 64;
+  G4double rn[nmax],pac[nmax];
+  
+  G4double S=0.0;
+  G4double epsilon = 0.0;
+  G4double cosTheta = 1.0;
+  G4double hartreeFunc = 0.0;
+  G4double oscStren = 0.0;
+  size_t numberOfOscillators = theTable->size();
+  size_t targetOscillator = 0;
+  G4double ionEnergy = 0.0*eV;
+
+  G4double ek = photonEnergy0/electron_mass_c2;
+  G4double ek2 = 2.*ek+1.0;
+  G4double eks = ek*ek;
+  G4double ek1 = eks-ek2-1.0;
+
+  G4double taumin = 1.0/ek2;
+  G4double a1 = std::log(ek2);
+  G4double a2 = a1+2.0*ek*(1.0+ek)/(ek2*ek2);
+
+  G4double TST = 0;
+  G4double tau = 0.;
+ 
+  //If the incoming photon is above 5 MeV, the quicker approach based on the 
+  //pure Klein-Nishina formula is used
+  if (photonEnergy0 > 5*MeV)
+    {
+      do{
+	do{
+	  if ((a2*G4UniformRand()) < a1)
+	    tau = std::pow(taumin,G4UniformRand());	    
+	  else
+	    tau = std::sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));	    
+	  //rejection function
+	  TST = (1.0+tau*(ek1+tau*(ek2+tau*eks)))/(eks*tau*(1.0+tau*tau));
+	}while (G4UniformRand()> TST);
+	epsilon=tau;
+	cosTheta = 1.0 - (1.0-tau)/(ek*tau);
+
+	//Target shell electrons	
+	TST = oscManager->GetTotalZ(material)*G4UniformRand();
+	targetOscillator = numberOfOscillators-1; //last level
+	S=0.0;
+	G4bool levelFound = false;
+	for (size_t j=0;j<numberOfOscillators && !levelFound; j++)
+	  {
+	    S += (*theTable)[j]->GetOscillatorStrength();	    
+	    if (S > TST) 
+	      {
+		targetOscillator = j;
+		levelFound = true;
+	      }
+	  }
+	//check whether the level is valid
+	ionEnergy = (*theTable)[targetOscillator]->GetIonisationEnergy();
+      }while((epsilon*photonEnergy0-photonEnergy0+ionEnergy) >0);
+    }
+  else //photonEnergy0 < 5 MeV
+    {
+      //Incoherent scattering function for theta=PI
+      G4double s0=0.0;
+      G4double pzomc=0.0;
+      G4double rni=0.0;
+      G4double aux=0.0;
+      for (size_t i=0;i<numberOfOscillators;i++)
+	{
+	  ionEnergy = (*theTable)[i]->GetIonisationEnergy();
+	  if (photonEnergy0 > ionEnergy)
+	    {
+	      G4double aux = photonEnergy0*(photonEnergy0-ionEnergy)*2.0;
+	      hartreeFunc = (*theTable)[i]->GetHartreeFactor(); 
+	      oscStren = (*theTable)[i]->GetOscillatorStrength();
+	      pzomc = hartreeFunc*(aux-electron_mass_c2*ionEnergy)/
+		(electron_mass_c2*std::sqrt(2.0*aux+ionEnergy*ionEnergy));
+	      if (pzomc > 0) 	
+		rni = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
+				       (std::sqrt(0.5)+std::sqrt(2.0)*pzomc));		
+	      else		  
+		rni = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
+				   (std::sqrt(0.5)-std::sqrt(2.0)*pzomc));	    
+	      s0 += oscStren*rni;
+	    }
+	}      
+      //Sampling tau
+      G4double cdt1 = 0.;
+      do
+	{
+	  if ((G4UniformRand()*a2) < a1)	    
+	    tau = std::pow(taumin,G4UniformRand());	    
+	  else	    
+	    tau = std::sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));	    
+	  cdt1 = (1.0-tau)/(ek*tau);
+	  //Incoherent scattering function
+	  S = 0.;
+	  for (size_t i=0;i<numberOfOscillators;i++)
+	    {
+	      ionEnergy = (*theTable)[i]->GetIonisationEnergy();
+	      if (photonEnergy0 > ionEnergy) //sum only on excitable levels
+		{
+		  aux = photonEnergy0*(photonEnergy0-ionEnergy)*cdt1;
+		  hartreeFunc = (*theTable)[i]->GetHartreeFactor(); 
+		  oscStren = (*theTable)[i]->GetOscillatorStrength();
+		  pzomc = hartreeFunc*(aux-electron_mass_c2*ionEnergy)/
+		    (electron_mass_c2*std::sqrt(2.0*aux+ionEnergy*ionEnergy));
+		  if (pzomc > 0) 
+		    rn[i] = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
+					     (std::sqrt(0.5)+std::sqrt(2.0)*pzomc));		    
+		  else		    
+		    rn[i] = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
+					 (std::sqrt(0.5)-std::sqrt(2.0)*pzomc));		    
+		  S += oscStren*rn[i];
+		  pac[i] = S;
+		}
+	      else
+		pac[i] = S-1e-6;		
+	    }
+	  //Rejection function
+	  TST = S*(1.0+tau*(ek1+tau*(ek2+tau*eks)))/(eks*tau*(1.0+tau*tau));  
+	}while ((G4UniformRand()*s0) > TST);
+
+      cosTheta = 1.0 - cdt1;
+      G4double fpzmax=0.0,fpz=0.0;
+      G4double A=0.0;
+      //Target electron shell
+      do
+	{
+	  do
+	    {
+	      TST = S*G4UniformRand();
+	      targetOscillator = numberOfOscillators-1; //last level
+	      G4bool levelFound = false;
+	      for (size_t i=0;i<numberOfOscillators && !levelFound;i++)
+		{
+		  if (pac[i]>TST) 
+		    {		     
+		      targetOscillator = i;
+		      levelFound = true;
+		    }
+		}
+	      A = G4UniformRand()*rn[targetOscillator];
+	      hartreeFunc = (*theTable)[targetOscillator]->GetHartreeFactor(); 
+	      oscStren = (*theTable)[targetOscillator]->GetOscillatorStrength();
+	      if (A < 0.5) 
+		pzomc = (std::sqrt(0.5)-std::sqrt(0.5-std::log(2.0*A)))/
+		  (std::sqrt(2.0)*hartreeFunc);	      
+	      else		
+		pzomc = (std::sqrt(0.5-std::log(2.0-2.0*A))-std::sqrt(0.5))/
+		  (std::sqrt(2.0)*hartreeFunc);	
+	    } while (pzomc < -1);
+
+	  // F(EP) rejection
+	  G4double XQC = 1.0+tau*(tau-2.0*cosTheta);
+	  G4double AF = std::sqrt(XQC)*(1.0+tau*(tau-cosTheta)/XQC);
+	  if (AF > 0) 
+	    fpzmax = 1.0+AF*0.2;
+	  else
+	    fpzmax = 1.0-AF*0.2;	    
+	  fpz = 1.0+AF*std::max(std::min(pzomc,0.2),-0.2);
+	}while ((fpzmax*G4UniformRand())>fpz);
+  
+      //Energy of the scattered photon
+      G4double T = pzomc*pzomc;
+      G4double b1 = 1.0-T*tau*tau;
+      G4double b2 = 1.0-T*tau*cosTheta;
+      if (pzomc > 0.0)	
+	epsilon = (tau/b1)*(b2+std::sqrt(std::abs(b2*b2-b1*(1.0-T))));	
+      else	
+	epsilon = (tau/b1)*(b2-std::sqrt(std::abs(b2*b2-b1*(1.0-T))));	
+    } //energy < 5 MeV
+  
+  //Ok, the kinematics has been calculated.
+  G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
+  G4double phi = twopi * G4UniformRand() ;
+  G4double dirx = sinTheta * std::cos(phi);
+  G4double diry = sinTheta * std::sin(phi);
+  G4double dirz = cosTheta ;
+
+  // Update G4VParticleChange for the scattered photon
+  G4ThreeVector photonDirection1(dirx,diry,dirz);
+  photonDirection1.rotateUz(photonDirection0);
+  fParticleChange->ProposeMomentumDirection(photonDirection1) ;
+
+  G4double photonEnergy1 = epsilon * photonEnergy0;
+
+  if (photonEnergy1 > 0.)  
+    fParticleChange->SetProposedKineticEnergy(photonEnergy1) ;  
+  else
+  {
+    fParticleChange->SetProposedKineticEnergy(0.) ;
+    fParticleChange->ProposeTrackStatus(fStopAndKill);
+  }
+  
+  //Create scattered electron
+  G4double diffEnergy = photonEnergy0*(1-epsilon);
+  ionEnergy = (*theTable)[targetOscillator]->GetIonisationEnergy();
+
+  G4double Q2 = 
+    photonEnergy0*photonEnergy0+photonEnergy1*(photonEnergy1-2.0*photonEnergy0*cosTheta);
+  G4double cosThetaE = 0.; //scattering angle for the electron
+
+  if (Q2 > 1.0e-12)    
+    cosThetaE = (photonEnergy0-photonEnergy1*cosTheta)/std::sqrt(Q2);    
+  else    
+    cosThetaE = 1.0;    
+  G4double sinThetaE = std::sqrt(1-cosThetaE*cosThetaE);
+
+  //Now, try to handle fluorescence
+  //Notice: merged levels are indicated with Z=0 and flag=30
+  G4int shFlag = (*theTable)[targetOscillator]->GetShellFlag(); 
+  G4int Z = (G4int) (*theTable)[targetOscillator]->GetParentZ();
+
+  //initialize here, then check photons created by Atomic-Deexcitation, and the final state e-
+  std::vector<G4DynamicParticle*>* photonVector=0;  
+  const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
+  G4double bindingEnergy = 0.*eV;
+  G4int shellId = 0;
+
+  //Real level
+  if (Z > 0 && shFlag<30)
+    {
+      const G4AtomicShell* shell = transitionManager->Shell(Z,shFlag-1);
+      bindingEnergy = shell->BindingEnergy();
+      shellId = shell->ShellId();
+    }
+
+  G4double ionEnergyInPenelopeDatabase = ionEnergy;
+  //protection against energy non-conservation
+  ionEnergy = std::max(bindingEnergy,ionEnergyInPenelopeDatabase);  
+
+  //subtract the excitation energy. If not emitted by fluorescence
+  //the ionization energy is deposited as local energy deposition
+  G4double eKineticEnergy = diffEnergy - ionEnergy; 
+  G4double localEnergyDeposit = ionEnergy; 
+  G4double energyInFluorescence = 0.; //testing purposes only
+
+  if (eKineticEnergy < 0) 
+    {
+      //It means that there was some problem/mismatch between the two databases. 
+      //Try to make it work
+      //In this case available Energy (diffEnergy) < ionEnergy
+      //Full residual energy is deposited locally
+      localEnergyDeposit = diffEnergy;
+      eKineticEnergy = 0.0;
+    }
+
+  //the local energy deposit is what remains: part of this may be spent for fluorescence.
+  if(DeexcitationFlag() && Z > 5) {
+
+    const G4ProductionCutsTable* theCoupleTable=
+      G4ProductionCutsTable::GetProductionCutsTable();
+
+    size_t index = couple->GetIndex();
+    G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
+    G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
+
+    // Generation of fluorescence
+    // Data in EADL are available only for Z > 5
+    // Protection to avoid generating photons in the unphysical case of
+    // shell binding energy > photon energy
+    if (localEnergyDeposit > cutg || localEnergyDeposit > cute)
+      { 
+	G4DynamicParticle* aPhoton;
+	deexcitationManager.SetCutForSecondaryPhotons(cutg);
+	deexcitationManager.SetCutForAugerElectrons(cute);
+
+	photonVector = deexcitationManager.GenerateParticles(Z,shellId);
+	if(photonVector) 
+	  {
+	    size_t nPhotons = photonVector->size();
+	    for (size_t k=0; k<nPhotons; k++)
+	      {
+		aPhoton = (*photonVector)[k];
+		if (aPhoton)
+		  {
+		    G4double itsEnergy = aPhoton->GetKineticEnergy();
+		    if (itsEnergy <= localEnergyDeposit)
+		      {
+			localEnergyDeposit -= itsEnergy;
+			if (aPhoton->GetDefinition() == G4Gamma::Gamma()) 
+			  energyInFluorescence += itsEnergy;;
+			fvect->push_back(aPhoton);		    
+		      }
+		    else
+		      {
+			delete aPhoton;
+			(*photonVector)[k]=0;
+		      }
+		  }
+	      }
+	    delete photonVector;
+	  }
+      }
+  }
+
+  //Always produce explicitely the electron 
+  G4DynamicParticle* electron = 0;
+
+  G4double xEl = sinThetaE * std::cos(phi+pi); 
+  G4double yEl = sinThetaE * std::sin(phi+pi);
+  G4double zEl = cosThetaE;
+  G4ThreeVector eDirection(xEl,yEl,zEl); //electron direction
+  eDirection.rotateUz(photonDirection0);
+  electron = new G4DynamicParticle (G4Electron::Electron(),
+				    eDirection,eKineticEnergy) ;
+  fvect->push_back(electron);
+    
+
+  if (localEnergyDeposit < 0)
+    {
+      G4cout << "WARNING-" 
+	     << "G4Penelope08ComptonModel::SampleSecondaries - Negative energy deposit"
+	     << G4endl;
+      localEnergyDeposit=0.;
+    }
+  fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
+  
+  G4double electronEnergy = 0.;
+  if (verboseLevel > 1)
+    {
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Energy balance from G4Penelope08Compton" << G4endl;
+      G4cout << "Incoming photon energy: " << photonEnergy0/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Scattered photon: " << photonEnergy1/keV << " keV" << G4endl;
+      if (electron)
+	electronEnergy = eKineticEnergy;
+      G4cout << "Scattered electron " << electronEnergy/keV << " keV" << G4endl;
+      G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
+      G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
+      G4cout << "Total final state: " << (photonEnergy1+electronEnergy+energyInFluorescence+
+					  localEnergyDeposit)/keV << 
+	" keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+    }
+  if (verboseLevel > 0)
+    {
+      G4double energyDiff = std::fabs(photonEnergy1+
+				      electronEnergy+energyInFluorescence+
+				      localEnergyDeposit-photonEnergy0);
+      if (energyDiff > 0.05*keV)
+	G4cout << "Warning from G4Penelope08Compton: problem with energy conservation: " << 
+	  (photonEnergy1+electronEnergy+energyInFluorescence+localEnergyDeposit)/keV << 
+	  " keV (final) vs. " << 
+	  photonEnergy0/keV << " keV (initial)" << G4endl;
+    }    
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08ComptonModel::DifferentialCrossSection(G4double cosTheta,G4double energy,
+							    G4PenelopeOscillator* osc)
+{
+  //
+  // Penelope model. Single differential cross section *per electron* 
+  // for photon Compton scattering by 
+  // electrons in the given atomic oscillator, differential in the direction of the 
+  // scattering photon. This is in units of pi*classic_electr_radius**2 
+  //
+  // D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
+  // The parametrization includes the J(p) distribution profiles for the atomic shells, 
+  // that are tabulated from Hartree-Fock calculations 
+  // from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201
+  //
+  G4double ionEnergy = osc->GetIonisationEnergy();
+  G4double harFunc = osc->GetHartreeFactor(); 
+
+  const G4double k2 = std::sqrt(2.);
+  const G4double k1 = 1./k2; 
+
+  if (energy < ionEnergy)
+    return 0;
+
+  //energy of the Compton line
+  G4double cdt1 = 1.0-cosTheta;
+  G4double EOEC = 1.0+(energy/electron_mass_c2)*cdt1; 
+  G4double ECOE = 1.0/EOEC;
+
+  //Incoherent scattering function (analytical profile)
+  G4double aux = energy*(energy-ionEnergy)*cdt1;
+  G4double Pzimax = 
+    (aux - electron_mass_c2*ionEnergy)/(electron_mass_c2*std::sqrt(2*aux+ionEnergy*ionEnergy));
+  G4double sia = 0.0;
+  G4double x = harFunc*Pzimax;
+  if (x > 0) 
+    sia = 1.0-0.5*std::exp(0.5-(k1+k2*x)*(k1+k2*x));    
+  else    
+    sia = 0.5*std::exp(0.5-(k1-k2*x)*(k1-k2*x));
+   
+  //1st order correction, integral of Pz times the Compton profile.
+  //Calculated approximately using a free-electron gas profile
+  G4double pf = 3.0/(4.0*harFunc);
+  if (std::fabs(Pzimax) < pf)
+    {
+      G4double QCOE2 = 1.0+ECOE*ECOE-2.0*ECOE*cosTheta;
+      G4double p2 = Pzimax*Pzimax;
+      G4double dspz = std::sqrt(QCOE2)*
+	(1.0+ECOE*(ECOE-cosTheta)/QCOE2)*harFunc
+	*0.25*(2*p2-(p2*p2)/(pf*pf)-(pf*pf));
+      sia += std::max(dspz,-1.0*sia);
+    }
+
+  G4double XKN = EOEC+ECOE-1.0+cosTheta*cosTheta;
+
+  //Differential cross section (per electron, in units of pi*classic_electr_radius**2)
+  G4double diffCS = ECOE*ECOE*XKN*sia;
+
+  return diffCS;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08ComptonModel::ActivateAuger(G4bool augerbool)
+{
+  if (!DeexcitationFlag() && augerbool)
+    {
+      G4cout << "WARNING - G4Penelope08ComptonModel" << G4endl;
+      G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
+      G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
+    }
+  deexcitationManager.ActivateAugerElectronProduction(augerbool);
+  if (verboseLevel > 1)
+    G4cout << "Auger production set to " << augerbool << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08ComptonModel::OscillatorTotalCrossSection(G4double energy,G4PenelopeOscillator* osc)
+{
+  //Total cross section (integrated) for the given oscillator in units of 
+  //pi*classic_electr_radius^2
+
+  //Integrate differential cross section for each oscillator
+  G4double stre = osc->GetOscillatorStrength();
+  
+  // here one uses the  using the 20-point
+  // Gauss quadrature method with an adaptive bipartition scheme
+  const G4int npoints=10;
+  const G4int ncallsmax=20000;
+  const G4int nst=256;
+  static G4double Abscissas[10] = {7.652651133497334e-02,2.2778585114164508e-01,3.7370608871541956e-01,
+				   5.1086700195082710e-01,6.3605368072651503e-01,7.4633190646015079e-01,
+				   8.3911697182221882e-01,9.1223442825132591e-01,9.6397192727791379e-01,
+				   9.9312859918509492e-01};
+  static G4double Weights[10] = {1.5275338713072585e-01,1.4917298647260375e-01,1.4209610931838205e-01,
+				 1.3168863844917663e-01,1.1819453196151842e-01,1.0193011981724044e-01,
+				 8.3276741576704749e-02,6.2672048334109064e-02,4.0601429800386941e-02,
+				 1.7614007139152118e-02};
+
+  G4double MaxError = 1e-5;
+  //Error control
+  G4double Ctol = std::min(std::max(MaxError,1e-13),1e-02);
+  G4double Ptol = 0.01*Ctol;
+  G4double Err=1e35;
+
+  //Gauss integration from -1 to 1
+  G4double LowPoint = -1.0;
+  G4double HighPoint = 1.0;
+
+  G4double h=HighPoint-LowPoint;
+  G4double sumga=0.0;
+  G4double a=0.5*(HighPoint-LowPoint);
+  G4double b=0.5*(HighPoint+LowPoint);
+  G4double c=a*Abscissas[0];
+  G4double d= Weights[0]*
+    (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
+  for (G4int i=2;i<=npoints;i++)
+    {
+      c=a*Abscissas[i-1];
+      d += Weights[i-1]*
+	(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
+    }
+  G4int icall = 2*npoints;
+  G4int LH=1;
+  G4double S[nst],x[nst],sn[nst],xrn[nst];
+  S[0]=d*a;
+  x[0]=LowPoint;
+
+  G4bool loopAgain = true;
+
+  //Adaptive bipartition scheme
+  do{
+    G4double h0=h;
+    h=0.5*h; //bipartition
+    G4double sumr=0;
+    G4int LHN=0;
+    G4double si,xa,xb,xc;
+    for (G4int i=1;i<=LH;i++){
+      si=S[i-1];
+      xa=x[i-1];
+      xb=xa+h;
+      xc=xa+h0;
+      a=0.5*(xb-xa);
+      b=0.5*(xb+xa);
+      c=a*Abscissas[0];
+      G4double d = Weights[0]*
+	(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
+      
+      for (G4int j=1;j<npoints;j++)
+	{
+	  c=a*Abscissas[j];
+	  d += Weights[j]*
+	    (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
+	}    
+      G4double s1=d*a;
+      a=0.5*(xc-xb);
+      b=0.5*(xc+xb);
+      c=a*Abscissas[0];
+      d=Weights[0]*
+	(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
+      
+      for (G4int j=1;j<npoints;j++)
+	{
+	  c=a*Abscissas[j];
+	  d += Weights[j]*
+	    (DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
+	}    
+      G4double s2=d*a;
+      icall=icall+4*npoints;
+      G4double s12=s1+s2;
+      if (std::abs(s12-si)<std::max(Ptol*std::abs(s12),1e-35))
+	sumga += s12;
+      else
+	{
+	  sumr += s12;
+	  LHN += 2;
+	  sn[LHN-1]=s2;
+	  xrn[LHN-1]=xb;
+	  sn[LHN-2]=s1;
+	  xrn[LHN-2]=xa;
+	}
+      
+      if (icall>ncallsmax || LHN>nst)
+	{
+	  G4cout << "G4Penelope08ComptonModel: " << G4endl;
+	  G4cout << "LowPoint: " << LowPoint << ", High Point: " << HighPoint << G4endl;
+	  G4cout << "Tolerance: " << MaxError << G4endl;
+	  G4cout << "Calls: " << icall << ", Integral: " << sumga << ", Error: " << Err << G4endl;
+	  G4cout << "Number of open subintervals: " << LHN << G4endl;
+	  G4cout << "WARNING: the required accuracy has not been attained" << G4endl;
+	  loopAgain = false;
+	}
+    }
+    Err=std::abs(sumr)/std::max(std::abs(sumr+sumga),1e-35);
+    if (Err < Ctol || LHN == 0) 
+      loopAgain = false; //end of cycle
+    LH=LHN;
+    for (G4int i=0;i<LH;i++)
+      {
+	S[i]=sn[i];
+	x[i]=xrn[i];
+      }
+  }while(Ctol < 1.0 && loopAgain); 
+
+
+  G4double xs = stre*sumga;
+
+  return xs; 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08ComptonModel::KleinNishinaCrossSection(G4double energy,
+						   const G4Material* material)
+{
+  // use Klein-Nishina formula
+  // total cross section in units of pi*classic_electr_radius^2
+
+  G4double cs = 0;
+
+  G4double ek =energy/electron_mass_c2;
+  G4double eks = ek*ek;
+  G4double ek2 = 1.0+ek+ek;
+  G4double ek1 = eks-ek2-1.0;
+
+  G4double t0 = 1.0/ek2;
+  G4double csl = 0.5*eks*t0*t0+ek2*t0+ek1*std::log(t0)-(1.0/t0);
+
+  G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableCompton(material);
+
+  for (size_t i=0;i<theTable->size();i++)
+    {
+      G4PenelopeOscillator* theOsc = (*theTable)[i];
+      G4double ionEnergy = theOsc->GetIonisationEnergy();
+      G4double tau=(energy-ionEnergy)/energy;
+      if (tau > t0)
+	{
+	  G4double csu = 0.5*eks*tau*tau+ek2*tau+ek1*std::log(tau)-(1.0/tau);
+	  G4double stre = theOsc->GetOscillatorStrength();
+
+	  cs += stre*(csu-csl);
+	}
+    }
+
+  cs /= (ek*eks);
+
+  return cs;
+
+}
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08GammaConversionModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08GammaConversionModel.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08GammaConversionModel.cc	(revision 1316)
@@ -0,0 +1,615 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08GammaConversionModel.cc,v 1.2 2010/04/23 14:49:46 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 13 Jan 2010   L Pandola    First implementation (updated to Penelope08)
+//
+
+#include "G4Penelope08GammaConversionModel.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4MaterialCutsCouple.hh"
+#include "G4ProductionCutsTable.hh"
+#include "G4DynamicParticle.hh"
+#include "G4Element.hh"
+#include "G4Gamma.hh"
+#include "G4Electron.hh"
+#include "G4Positron.hh"
+#include "G4PhysicsFreeVector.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4Penelope08GammaConversionModel::G4Penelope08GammaConversionModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+  :G4VEmModel(nam),logAtomicCrossSection(0),fEffectiveCharge(0),fMaterialInvScreeningRadius(0),
+   fScreeningFunction(0),isInitialised(false)
+{
+  fIntrinsicLowEnergyLimit = 2.0*electron_mass_c2;
+  fIntrinsicHighEnergyLimit = 100.0*GeV;
+  fSmallEnergy = 1.1*MeV;
+  InitializeScreeningRadii();
+
+  //  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
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4Penelope08GammaConversionModel::~G4Penelope08GammaConversionModel()
+{
+  std::map <const G4int,G4PhysicsFreeVector*>::iterator i;
+  if (logAtomicCrossSection)
+    {
+      for (i=logAtomicCrossSection->begin();i != logAtomicCrossSection->end();i++)
+        if (i->second) delete i->second;
+      delete logAtomicCrossSection;
+    }
+  if (fEffectiveCharge)
+    delete fEffectiveCharge;
+  if (fMaterialInvScreeningRadius)
+    delete fMaterialInvScreeningRadius;
+  if (fScreeningFunction)
+    delete fScreeningFunction;
+
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08GammaConversionModel::Initialise(const G4ParticleDefinition*,
+						const G4DataVector&)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling  G4Penelope08GammaConversionModel::Initialise()" << G4endl;
+
+  // logAtomicCrossSection is created only once, since it is  never cleared
+  if (!logAtomicCrossSection)
+    logAtomicCrossSection =  new std::map<const G4int,G4PhysicsFreeVector*>;
+
+  //delete old material data...
+  if (fEffectiveCharge)
+    {
+      delete fEffectiveCharge;
+      fEffectiveCharge = 0;
+    }
+  if (fMaterialInvScreeningRadius)
+    {
+      delete fMaterialInvScreeningRadius;
+      fMaterialInvScreeningRadius = 0;
+    }
+  if (fScreeningFunction)
+    {
+      delete fScreeningFunction;
+      fScreeningFunction = 0;
+    }      
+  //and create new ones
+  fEffectiveCharge = new std::map<const G4Material*,G4double>;
+  fMaterialInvScreeningRadius = new std::map<const G4Material*,G4double>;
+  fScreeningFunction = new std::map<const G4Material*,std::pair<G4double,G4double> >;
+
+  if (verboseLevel > 0) { 
+    G4cout << "Penelope Gamma Conversion model is initialized " << G4endl
+	   << "Energy range: "
+	   << LowEnergyLimit() / MeV << " MeV - "
+	   << HighEnergyLimit() / GeV << " GeV"
+	   << G4endl;
+  }
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForGamma();
+  isInitialised = true;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08GammaConversionModel::ComputeCrossSectionPerAtom(
+                                       const G4ParticleDefinition*,
+                                             G4double energy,
+                                             G4double Z, G4double,
+                                             G4double, G4double)
+{
+  //
+  // Penelope model.
+  // Cross section (including triplet production) read from database and managed 
+  // through the G4CrossSectionHandler utility. Cross section data are from
+  // M.J. Berger and J.H. Hubbel (XCOM), Report NBSIR 887-3598
+  //
+  
+  if (energy < fIntrinsicLowEnergyLimit)
+    return 0;
+
+  G4int iZ = (G4int) Z;
+
+ //read data files
+  if (!logAtomicCrossSection->count(iZ))
+    ReadDataFile(iZ);
+  //now it should be ok
+  if (!logAtomicCrossSection->count(iZ))
+     {
+       G4cout << "Problem in G4Penelope08GammaConversion::ComputeCrossSectionPerAtom"
+              << G4endl;
+       G4Exception();
+     }
+
+  G4double cs = 0;
+  G4double logene = log(energy);
+  G4PhysicsFreeVector* theVec = logAtomicCrossSection->find(iZ)->second;
+
+  G4double logXS = theVec->Value(logene);
+  cs = exp(logXS);
+
+  if (verboseLevel > 2)
+    G4cout << "Gamma conversion cross section at " << energy/MeV << " MeV for Z=" << Z << 
+      " = " << cs/barn << " barn" << G4endl;
+  return cs;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void 
+G4Penelope08GammaConversionModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+						  const G4MaterialCutsCouple* couple,
+						  const G4DynamicParticle* aDynamicGamma,
+						  G4double,
+						  G4double)
+{
+  //
+  // Penelope model.
+  // Final state is sampled according to the Bethe-Heitler model with Coulomb
+  // corrections, according to the semi-empirical model of
+  //  J. Baro' et al., Radiat. Phys. Chem. 44 (1994) 531.
+  //
+  // The model uses the high energy Coulomb correction from 
+  //  H. Davies et al., Phys. Rev. 93 (1954) 788
+  // and atomic screening radii tabulated from 
+  //  J.H. Hubbel et al., J. Phys. Chem. Ref. Data 9 (1980) 1023
+  // for Z= 1 to 92. 
+  //
+  if (verboseLevel > 3)
+    G4cout << "Calling SamplingSecondaries() of G4Penelope08GammaConversionModel" << G4endl;
+
+  G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
+
+  // Always kill primary
+  fParticleChange->ProposeTrackStatus(fStopAndKill);
+  fParticleChange->SetProposedKineticEnergy(0.);
+
+  if (photonEnergy <= fIntrinsicLowEnergyLimit)
+    {
+      fParticleChange->ProposeLocalEnergyDeposit(photonEnergy);
+      return ;
+    }
+
+  G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
+  const G4Material* mat = couple->GetMaterial();
+
+  //check if material data are available
+  if (!fEffectiveCharge->count(mat))
+    InitializeScreeningFunctions(mat); 
+  if (!fEffectiveCharge->count(mat))
+    {
+      G4cout << "Problem in G4Penelope08GammaConversion::SampleSecondaries()" << G4endl;
+      G4cout << "Unable to allocate the EffectiveCharge data" << G4endl;
+      G4Exception();
+    }
+
+  // eps is the fraction of the photon energy assigned to e- (including rest mass)
+  G4double eps = 0;
+  G4double eki = electron_mass_c2/photonEnergy;
+
+  //Do it fast for photon energy < 1.1 MeV (close to threshold)
+  if (photonEnergy < fSmallEnergy)
+    eps = eki + (1.0-2.0*eki)*G4UniformRand();
+  else
+    {
+      //Complete calculation
+      G4double effC = fEffectiveCharge->find(mat)->second;
+      G4double alz = effC*fine_structure_const;
+      G4double T = sqrt(2.0*eki);
+      G4double F00=(-1.774-1.210e1*alz+1.118e1*alz*alz)*T
+         +(8.523+7.326e1*alz-4.441e1*alz*alz)*T*T
+         -(1.352e1+1.211e2*alz-9.641e1*alz*alz)*T*T*T
+	+(8.946+6.205e1*alz-6.341e1*alz*alz)*T*T*T*T;
+     
+      G4double F0b = fScreeningFunction->find(mat)->second.second;
+      G4double g0 = F0b + F00;
+      G4double invRad = fMaterialInvScreeningRadius->find(mat)->second;
+      G4double bmin = 4.0*eki/invRad;
+      std::pair<G4double,G4double> scree =  GetScreeningFunctions(bmin);
+      G4double g1 = scree.first;
+      G4double g2 = scree.second;
+      G4double g1min = g1+g0;
+      G4double g2min = g2+g0;
+      G4double xr = 0.5-eki;
+      G4double a1 = 2.*g1min*xr*xr/3.;      
+      G4double p1 = a1/(a1+g2min);
+
+      G4bool loopAgain = false;
+      //Random sampling of eps
+      do{
+	loopAgain = false;
+	if (G4UniformRand() <= p1)
+	  {
+	    G4double  ru2m1 = 2.0*G4UniformRand()-1.0;
+	    if (ru2m1 < 0)
+	      eps = 0.5-xr*pow(std::abs(ru2m1),1./3.);
+	    else
+	      eps = 0.5+xr*pow(ru2m1,1./3.);
+	    G4double B = eki/(invRad*eps*(1.0-eps));
+	    scree =  GetScreeningFunctions(B);
+	    g1 = scree.first;
+	    g1 = std::max(g1+g0,0.);
+	    if (G4UniformRand()*g1min > g1) 
+	      loopAgain = true;
+	  }
+	else
+	  {
+	    eps = eki+2.0*xr*G4UniformRand();
+	    G4double B = eki/(invRad*eps*(1.0-eps));
+	    scree =  GetScreeningFunctions(B);
+	    g2 = scree.second;
+	    g2 = std::max(g2+g0,0.);
+	    if (G4UniformRand()*g2min > g2)
+	      loopAgain = true;
+	  }      
+      }while(loopAgain);
+      
+    }
+  if (verboseLevel > 4)
+    G4cout << "Sampled eps = " << eps << G4endl;
+
+  G4double electronTotEnergy = eps*photonEnergy;
+  G4double positronTotEnergy = (1.0-eps)*photonEnergy;
+  
+  // Scattered electron (positron) angles. ( Z - axis along the parent photon)
+
+  //electron kinematics
+  G4double electronKineEnergy = std::max(0.,electronTotEnergy - electron_mass_c2) ; 
+  G4double costheta_el = G4UniformRand()*2.0-1.0;
+  G4double kk = std::sqrt(electronKineEnergy*(electronKineEnergy+2.*electron_mass_c2));
+  costheta_el = (costheta_el*electronTotEnergy+kk)/(electronTotEnergy+costheta_el*kk);
+  G4double phi_el  = twopi * G4UniformRand() ;
+  G4double dirX_el = std::sqrt(1.-costheta_el*costheta_el) * std::cos(phi_el);
+  G4double dirY_el = std::sqrt(1.-costheta_el*costheta_el) * std::sin(phi_el);
+  G4double dirZ_el = costheta_el;
+
+  //positron kinematics
+  G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
+  G4double costheta_po = G4UniformRand()*2.0-1.0;
+  kk = std::sqrt(positronKineEnergy*(positronKineEnergy+2.*electron_mass_c2));
+  costheta_po = (costheta_po*positronTotEnergy+kk)/(positronTotEnergy+costheta_po*kk);
+  G4double phi_po  = twopi * G4UniformRand() ;
+  G4double dirX_po = std::sqrt(1.-costheta_po*costheta_po) * std::cos(phi_po);
+  G4double dirY_po = std::sqrt(1.-costheta_po*costheta_po) * std::sin(phi_po);
+  G4double dirZ_po = costheta_po;
+
+  // Kinematics of the created pair:
+  // the electron and positron are assumed to have a symetric angular
+  // distribution with respect to the Z axis along the parent photon
+  G4double localEnergyDeposit = 0. ;
+ 
+  if (electronKineEnergy > 0.0)
+    {
+      G4ThreeVector electronDirection ( dirX_el, dirY_el, dirZ_el);
+      electronDirection.rotateUz(photonDirection);
+      G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
+							   electronDirection,
+							   electronKineEnergy);
+      fvect->push_back(electron);
+    }
+  else
+    {
+      localEnergyDeposit += electronKineEnergy;
+      electronKineEnergy = 0;
+    }
+
+  //Generate the positron. Real particle in any case, because it will annihilate. If below
+  //threshold, produce it at rest
+  if (positronKineEnergy < 0.0)
+    {
+      localEnergyDeposit += positronKineEnergy;
+      positronKineEnergy = 0; //produce it at rest
+    }
+  G4ThreeVector positronDirection(dirX_po,dirY_po,dirZ_po);
+  positronDirection.rotateUz(photonDirection);
+  G4DynamicParticle* positron = new G4DynamicParticle(G4Positron::Positron(),
+						      positronDirection, positronKineEnergy);
+  fvect->push_back(positron);
+
+  //Add rest of energy to the local energy deposit
+  fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
+  
+  if (verboseLevel > 1)
+    {
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Energy balance from G4Penelope08GammaConversion" << G4endl;
+      G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      if (electronKineEnergy)
+	G4cout << "Electron (explicitely produced) " << electronKineEnergy/keV << " keV" 
+	       << G4endl;
+      if (positronKineEnergy)
+	G4cout << "Positron (not at rest) " << positronKineEnergy/keV << " keV" << G4endl;
+      G4cout << "Rest masses of e+/- " << 2.0*electron_mass_c2/keV << " keV" << G4endl;
+      if (localEnergyDeposit)
+	G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
+      G4cout << "Total final state: " << (electronKineEnergy+positronKineEnergy+
+					  localEnergyDeposit+2.0*electron_mass_c2)/keV <<
+        " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+    }
+ if (verboseLevel > 0)
+    {
+      G4double energyDiff = std::fabs(electronKineEnergy+positronKineEnergy+
+				      localEnergyDeposit+2.0*electron_mass_c2-photonEnergy);
+      if (energyDiff > 0.05*keV)
+	G4cout << "Warning from G4Penelope08GammaConversion: problem with energy conservation: " 
+	       << (electronKineEnergy+positronKineEnergy+
+		   localEnergyDeposit+2.0*electron_mass_c2)/keV 
+	       << " keV (final) vs. " << photonEnergy/keV << " keV (initial)" << G4endl;
+    } 
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08GammaConversionModel::ReadDataFile(const G4int Z)
+{
+ if (verboseLevel > 2)
+    {
+      G4cout << "G4Penelope08GammaConversionModel::ReadDataFile()" << G4endl;
+      G4cout << "Going to read Gamma Conversion data files for Z=" << Z << G4endl;
+    }
+ 
+  char* path = getenv("G4LEDATA");
+  if (!path)
+    {
+      G4String excep = 
+	"G4Penelope08GammaConversionModel - G4LEDATA environment variable not set!";
+      G4Exception(excep);
+    }
+ 
+  /*
+    Read the cross section file
+  */
+  std::ostringstream ost;
+  if (Z>9)
+    ost << path << "/penelope/pairproduction/pdgpp" << Z << ".p08";
+  else
+    ost << path << "/penelope/pairproduction/pdgpp0" << Z << ".p08";
+  std::ifstream file(ost.str().c_str());
+  if (!file.is_open())
+    {
+      G4String excep = "G4Penelope08GammaConversionModel - data file " + 
+	G4String(ost.str()) + " not found!";
+      G4Exception(excep);
+    }
+
+  //I have to know in advance how many points are in the data list
+  //to initialize the G4PhysicsFreeVector()
+  size_t ndata=0;
+  G4String line;
+  while( getline(file, line) )
+    ndata++;
+  ndata -= 1; //remove one header line
+  //G4cout << "Found: " << ndata << " lines" << G4endl;
+
+  file.clear();
+  file.close();
+  file.open(ost.str().c_str());
+  G4int readZ =0;
+  file >> readZ; 
+
+  if (verboseLevel > 3)
+    G4cout << "Element Z=" << Z << G4endl;
+
+  //check the right file is opened.
+  if (readZ != Z)
+    {
+      G4cout << "G4Penelope08GammaConversionModel::ReadDataFile()" << G4endl;
+      G4cout << "Corrupted data file for Z=" << Z << G4endl;
+      G4Exception();
+    }
+
+  G4PhysicsFreeVector* theVec = new G4PhysicsFreeVector(ndata);
+  G4double ene=0,xs=0;
+  for (size_t i=0;i<ndata;i++)
+    {
+      file >> ene >> xs;
+      //dimensional quantities
+      ene *= eV;
+      xs *= barn;
+      if (xs < 1e-40*cm2) //protection against log(0)
+	xs = 1e-40*cm2;
+      theVec->PutValue(i,log(ene),log(xs));      
+    }
+  file.close();
+
+  if (!logAtomicCrossSection)
+    {
+      G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+      G4cout << "Problem with allocation of logAtomicCrossSection data table " << G4endl;
+      G4Exception();
+    }
+  logAtomicCrossSection->insert(std::make_pair(Z,theVec));
+
+  return;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08GammaConversionModel::InitializeScreeningRadii()
+{
+  G4double temp[99] = {1.2281e+02,7.3167e+01,6.9228e+01,6.7301e+01,6.4696e+01,
+		       6.1228e+01,5.7524e+01,5.4033e+01,5.0787e+01,4.7851e+01,4.6373e+01,
+		       4.5401e+01,4.4503e+01,4.3815e+01,4.3074e+01,4.2321e+01,4.1586e+01,
+		       4.0953e+01,4.0524e+01,4.0256e+01,3.9756e+01,3.9144e+01,3.8462e+01,
+		       3.7778e+01,3.7174e+01,3.6663e+01,3.5986e+01,3.5317e+01,3.4688e+01,
+		       3.4197e+01,3.3786e+01,3.3422e+01,3.3068e+01,3.2740e+01,3.2438e+01,
+		       3.2143e+01,3.1884e+01,3.1622e+01,3.1438e+01,3.1142e+01,3.0950e+01,
+		       3.0758e+01,3.0561e+01,3.0285e+01,3.0097e+01,2.9832e+01,2.9581e+01,
+		       2.9411e+01,2.9247e+01,2.9085e+01,2.8930e+01,2.8721e+01,2.8580e+01,
+		       2.8442e+01,2.8312e+01,2.8139e+01,2.7973e+01,2.7819e+01,2.7675e+01,
+		       2.7496e+01,2.7285e+01,2.7093e+01,2.6911e+01,2.6705e+01,2.6516e+01,
+		       2.6304e+01,2.6108e+01,2.5929e+01,2.5730e+01,2.5577e+01,2.5403e+01,
+		       2.5245e+01,2.5100e+01,2.4941e+01,2.4790e+01,2.4655e+01,2.4506e+01,
+		       2.4391e+01,2.4262e+01,2.4145e+01,2.4039e+01,2.3922e+01,2.3813e+01,
+		       2.3712e+01,2.3621e+01,2.3523e+01,2.3430e+01,2.3331e+01,2.3238e+01,
+		       2.3139e+01,2.3048e+01,2.2967e+01,2.2833e+01,2.2694e+01,2.2624e+01,
+		       2.2545e+01,2.2446e+01,2.2358e+01,2.2264e+01};
+
+  //copy temporary vector in class data member
+  for (G4int i=0;i<99;i++)
+    fAtomicScreeningRadius[i] = temp[i];
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08GammaConversionModel::InitializeScreeningFunctions(const G4Material* material)
+{
+  // This is subroutine GPPa0 of Penelope
+  //
+  // 1) calculate the effective Z for the purpose
+  //
+  G4double zeff = 0;
+  G4int intZ = 0;
+  G4int nElements = material->GetNumberOfElements();
+  const G4ElementVector* elementVector = material->GetElementVector();
+
+  //avoid calculations if only one building element!
+  if (nElements == 1)
+    {
+      zeff = (*elementVector)[0]->GetZ();
+      intZ = (G4int) zeff;
+    }
+  else // many elements...let's do the calculation
+    {
+      const G4double* fractionVector = material->GetVecNbOfAtomsPerVolume();
+      
+      G4double atot = 0;
+      for (G4int i=0;i<nElements;i++)
+	{
+	  G4double Zelement = (*elementVector)[i]->GetZ();
+	  G4double Aelement = (*elementVector)[i]->GetA();
+	  atot += Aelement*fractionVector[i];
+	  zeff += Zelement*Aelement*fractionVector[i]; //average with the number of nuclei
+	}
+      atot /= material->GetTotNbOfAtomsPerVolume();
+      zeff /= (material->GetTotNbOfAtomsPerVolume()*atot);
+      
+      intZ = (G4int) (zeff+0.25);
+      if (intZ <= 0)
+	intZ = 1;
+      if (intZ > 99)
+	intZ = 99;
+    }
+
+  if (fEffectiveCharge)
+    fEffectiveCharge->insert(std::make_pair(material,zeff));
+
+  //
+  // 2) Calculate Coulomb Correction
+  //
+  G4double alz = fine_structure_const*zeff;
+  G4double alzSquared = alz*alz;
+  G4double fc =  alzSquared*(0.202059-alzSquared*
+			     (0.03693-alzSquared*
+			      (0.00835-alzSquared*(0.00201-alzSquared*
+						   (0.00049-alzSquared*
+						    (0.00012-alzSquared*0.00003)))))
+			     +1.0/(alzSquared+1.0));
+  //
+  // 3) Screening functions and low-energy corrections
+  //
+  G4double matRadius = 2.0/ fAtomicScreeningRadius[intZ-1];
+  if (fMaterialInvScreeningRadius)
+    fMaterialInvScreeningRadius->insert(std::make_pair(material,matRadius));
+
+  std::pair<G4double,G4double> myPair(0,0);
+  G4double f0a = 4.0*log(fAtomicScreeningRadius[intZ-1]);
+  G4double f0b = f0a - 4.0*fc;
+  myPair.first = f0a;
+  myPair.second = f0b;
+
+  if (fScreeningFunction)
+    fScreeningFunction->insert(std::make_pair(material,myPair));
+
+  if (verboseLevel > 2)
+    {
+      G4cout << "Average Z for material " << material->GetName() << " = " << 
+	zeff << G4endl;
+      G4cout << "Effective radius for material " << material->GetName() << " = " << 
+	fAtomicScreeningRadius[intZ-1] << " m_e*c/hbar --> BCB = " << 
+	matRadius << G4endl;
+      G4cout << "Screening parameters F0 for material " << material->GetName() << " = " << 
+	f0a << "," << f0b << G4endl;
+    }
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+std::pair<G4double,G4double> 
+G4Penelope08GammaConversionModel::GetScreeningFunctions(G4double B)
+{
+  // This is subroutine SCHIFF of Penelope
+  //
+  // Screening Functions F1(B) and F2(B) in the Bethe-Heitler differential cross 
+  // section for pair production
+  //
+  std::pair<G4double,G4double> result(0.,0.);
+  G4double BSquared = B*B;
+  G4double f1 = 2.0-2.0*log(1.0+BSquared);
+  G4double f2 = f1 - 6.66666666e-1; // (-2/3)
+  if (B < 1.0e-10)
+    f1 = f1-twopi*B;
+  else
+    {
+      G4double a0 = 4.0*B*std::atan(1./B);
+      f1 = f1 - a0;
+      f2 += 2.0*BSquared*(4.0-a0-3.0*log((1.0+BSquared)/BSquared));
+    }
+  G4double g1 = 0.5*(3.0*f1-f2);
+  G4double g2 = 0.25*(3.0*f1+f2);
+
+  result.first = g1;
+  result.second = g2;
+
+  return result;
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08PhotoElectricModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08PhotoElectricModel.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08PhotoElectricModel.cc	(revision 1316)
@@ -0,0 +1,677 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08PhotoElectricModel.cc,v 1.3 2010/03/31 11:12:08 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 08 Jan 2010   L Pandola  First implementation
+
+#include "G4Penelope08PhotoElectricModel.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4MaterialCutsCouple.hh"
+#include "G4ProductionCutsTable.hh"
+#include "G4DynamicParticle.hh"
+#include "G4PhysicsTable.hh"
+#include "G4PhysicsFreeVector.hh"
+#include "G4ElementTable.hh"
+#include "G4Element.hh"
+#include "G4CrossSectionHandler.hh"
+#include "G4AtomicTransitionManager.hh"
+#include "G4AtomicShell.hh"
+#include "G4Gamma.hh"
+#include "G4Electron.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4Penelope08PhotoElectricModel::G4Penelope08PhotoElectricModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+  :G4VEmModel(nam),isInitialised(false),logAtomicShellXS(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
+
+  //by default the model will inkove the atomic deexcitation
+  SetDeexcitationFlag(true);  
+  ActivateAuger(false);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4Penelope08PhotoElectricModel::~G4Penelope08PhotoElectricModel()
+{  
+  std::map <const G4int,G4PhysicsTable*>::iterator i;
+  if (logAtomicShellXS)
+    {
+      for (i=logAtomicShellXS->begin();i != logAtomicShellXS->end();i++)
+	{
+	  G4PhysicsTable* tab = i->second;
+	  tab->clearAndDestroy();
+	  delete tab;
+	}
+    }
+  delete logAtomicShellXS;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08PhotoElectricModel::Initialise(const G4ParticleDefinition* particle,
+                                       const G4DataVector& cuts)
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling  G4Penelope08PhotoElectricModel::Initialise()" << G4endl;
+
+  // logAtomicShellXS is created only once, since it is  never cleared
+  if (!logAtomicShellXS)
+    logAtomicShellXS = new std::map<const G4int,G4PhysicsTable*>;
+
+  InitialiseElementSelectors(particle,cuts);
+
+  if (verboseLevel > 0) { 
+    G4cout << "Penelope Photo-Electric model is initialized " << G4endl
+	   << "Energy range: "
+	   << LowEnergyLimit() / MeV << " MeV - "
+	   << HighEnergyLimit() / GeV << " GeV"
+	   << G4endl;
+  }
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForGamma();
+  isInitialised = true;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08PhotoElectricModel::ComputeCrossSectionPerAtom(
+                                       const G4ParticleDefinition*,
+                                             G4double energy,
+                                             G4double Z, G4double,
+                                             G4double, G4double)
+{
+  //
+  // Penelope model. 
+  //
+
+  if (verboseLevel > 3)
+    G4cout << "Calling ComputeCrossSectionPerAtom() of G4Penelope08PhotoElectricModel" << G4endl;
+
+  G4int iZ = (G4int) Z;
+
+  //read data files
+  if (!logAtomicShellXS->count(iZ))
+    ReadDataFile(iZ);
+  //now it should be ok
+  if (!logAtomicShellXS->count(iZ))
+     {
+       G4cout << "Problem in G4Penelope08PhotoElectricModel::ComputeCrossSectionPerAtom"
+              << G4endl;
+       G4Exception();
+     }
+
+  G4double cross = 0;
+
+  G4PhysicsTable* theTable =  logAtomicShellXS->find(iZ)->second;
+  G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[0];
+
+   if (!totalXSLog)
+     {
+       G4cout << "Problem in G4Penelope08PhotoElectricModel::ComputeCrossSectionPerAtom"
+         << G4endl;
+       G4Exception();
+     }
+   G4double logene = log(energy);
+   G4double logXS = totalXSLog->Value(logene);
+   cross = exp(logXS);
+ 
+  if (verboseLevel > 2)
+    G4cout << "Photoelectric cross section at " << energy/MeV << " MeV for Z=" << Z <<
+      " = " << cross/barn << " barn" << G4endl;
+  return cross;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08PhotoElectricModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
+						       const G4MaterialCutsCouple* couple,
+						       const G4DynamicParticle* aDynamicGamma,
+						       G4double,
+						       G4double)
+{
+  //
+  // Photoelectric effect, Penelope model
+  //
+  // The target atom and the target shell are sampled according to the Livermore 
+  // database 
+  //  D.E. Cullen et al., Report UCRL-50400 (1989)
+  // The angular distribution of the electron in the final state is sampled 
+  // according to the Sauter distribution from 
+  //  F. Sauter, Ann. Phys. 11 (1931) 454
+  // The energy of the final electron is given by the initial photon energy minus 
+  // the binding energy. Fluorescence de-excitation is subsequently produced 
+  // (to fill the vacancy) according to the general Geant4 G4DeexcitationManager:
+  //  J. Stepanek, Comp. Phys. Comm. 1206 pp 1-1-9 (1997)
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SamplingSecondaries() of G4Penelope08PhotoElectricModel" << G4endl;
+
+  G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
+
+  // always kill primary
+  fParticleChange->ProposeTrackStatus(fStopAndKill);
+  fParticleChange->SetProposedKineticEnergy(0.);
+
+  if (photonEnergy <= fIntrinsicLowEnergyLimit)
+    {
+      fParticleChange->ProposeLocalEnergyDeposit(photonEnergy);
+      return ;
+    }
+
+  G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
+
+  // Select randomly one element in the current material
+  if (verboseLevel > 2)
+    G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl;
+
+  // atom can be selected efficiently if element selectors are initialised
+  const G4Element* anElement =
+    SelectRandomAtom(couple,G4Gamma::GammaDefinition(),photonEnergy);
+  G4int Z = (G4int) anElement->GetZ();
+  if (verboseLevel > 2)
+    G4cout << "Selected " << anElement->GetName() << G4endl;
+  
+  // Select the ionised shell in the current atom according to shell cross sections
+  //shellIndex = 0 --> K shell
+  //             1-3 --> L shells
+  //             4-8 --> M shells
+  //             9 --> outer shells cumulatively
+  //
+  size_t shellIndex = SelectRandomShell(Z,photonEnergy);
+
+  if (verboseLevel > 2)
+    G4cout << "Selected shell " << shellIndex << " of element " << anElement->GetName() << G4endl;
+
+  // Retrieve the corresponding identifier and binding energy of the selected shell
+  const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
+
+  //The number of shell cross section possibly reported in the Penelope database 
+  //might be different from the number of shells in the G4AtomicTransitionManager
+  //(namely, Penelope may contain more shell, especially for very light elements).
+  //In order to avoid a warning message from the G4AtomicTransitionManager, I 
+  //add this protection. Results are anyway changed, because when G4AtomicTransitionManager
+  //has a shellID>maxID, it sets the shellID to the last valid shell. 
+  size_t numberOfShells = (size_t) transitionManager->NumberOfShells(Z);
+  if (shellIndex >= numberOfShells)
+    shellIndex = numberOfShells-1;
+
+  const G4AtomicShell* shell = transitionManager->Shell(Z,shellIndex);
+  G4double bindingEnergy = shell->BindingEnergy();
+  G4int shellId = shell->ShellId();
+
+  //Penelope considers only K, L and M shells. Cross sections of outer shells are 
+  //not included in the Penelope database. If SelectRandomShell() returns 
+  //shellIndex = 9, it means that an outer shell was ionized. In this case the 
+  //Penelope recipe is to set bindingEnergy = 0 (the energy is entirely assigned 
+  //to the electron) and to disregard fluorescence.
+  if (shellIndex == 9)
+    bindingEnergy = 0.*eV;
+
+
+  G4double localEnergyDeposit = 0.0;
+  G4double cosTheta = 1.0;
+
+  // Primary outcoming electron
+  G4double eKineticEnergy = photonEnergy - bindingEnergy;
+  
+  // There may be cases where the binding energy of the selected shell is > photon energy
+  // In such cases do not generate secondaries
+  if (eKineticEnergy > 0.)
+    {
+      // The electron is created
+      // Direction sampled from the Sauter distribution
+      cosTheta = SampleElectronDirection(eKineticEnergy);
+      G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
+      G4double phi = twopi * G4UniformRand() ;
+      G4double dirx = sinTheta * std::cos(phi);
+      G4double diry = sinTheta * std::sin(phi);
+      G4double dirz = cosTheta ;
+      G4ThreeVector electronDirection(dirx,diry,dirz); //electron direction
+      electronDirection.rotateUz(photonDirection);
+      G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(), 
+							   electronDirection, 
+							   eKineticEnergy);
+      fvect->push_back(electron);
+    } 
+  else
+    {
+      bindingEnergy = photonEnergy;
+    }
+
+  G4double energyInFluorescence = 0; //testing purposes
+
+  //Now, take care of fluorescence, if required
+  if(DeexcitationFlag() && Z > 5) 
+    {
+      const G4ProductionCutsTable* theCoupleTable=
+	G4ProductionCutsTable::GetProductionCutsTable();
+      size_t indx = couple->GetIndex();
+      G4double cutG = (*(theCoupleTable->GetEnergyCutsVector(0)))[indx];
+      G4double cutE = (*(theCoupleTable->GetEnergyCutsVector(1)))[indx];
+      
+      // Protection to avoid generating photons in the unphysical case of 
+      // shell binding energy > photon energy
+      if (bindingEnergy > cutG || bindingEnergy > cutE)
+	{
+	  deexcitationManager.SetCutForSecondaryPhotons(cutG);
+	  deexcitationManager.SetCutForAugerElectrons(cutE);
+	  std::vector<G4DynamicParticle*>* photonVector = 
+	    deexcitationManager.GenerateParticles(Z,shellId); 
+	  //Check for secondaries
+          if(photonVector) 
+	    {
+	      for (size_t k=0; k< photonVector->size(); k++)
+		{
+		  G4DynamicParticle* aPhoton = (*photonVector)[k];
+		  if (aPhoton)
+		    {
+		      G4double itsEnergy = aPhoton->GetKineticEnergy();
+		      if (itsEnergy <= bindingEnergy)
+			{
+			  if(aPhoton->GetDefinition() == G4Gamma::Gamma())
+			    energyInFluorescence += itsEnergy;
+			  bindingEnergy -= itsEnergy;
+			  fvect->push_back(aPhoton);
+			}
+		      else
+			{
+			  delete aPhoton;
+			  (*photonVector)[k] = 0;
+			}
+		    }
+		}
+	      delete photonVector;
+	    }
+	}
+    }
+  //Residual energy is deposited locally
+  localEnergyDeposit += bindingEnergy;
+      
+  if (localEnergyDeposit < 0)
+    {
+      G4cout << "WARNING - "
+	     << "G4Penelope08PhotoElectric::PostStepDoIt - Negative energy deposit"
+	     << G4endl;
+      localEnergyDeposit = 0;
+    }
+
+  fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
+
+  if (verboseLevel > 1)
+    {
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      G4cout << "Energy balance from G4Penelope08PhotoElectric" << G4endl;
+      G4cout << "Selected shell: " << WriteTargetShell(shellIndex) << " of element " << 
+	anElement->GetName() << G4endl;
+      G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+      if (eKineticEnergy)
+	G4cout << "Outgoing electron " << eKineticEnergy/keV << " keV" << G4endl;
+      G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
+      G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
+      G4cout << "Total final state: " << (eKineticEnergy+energyInFluorescence+localEnergyDeposit)/keV << 
+	" keV" << G4endl;
+      G4cout << "-----------------------------------------------------------" << G4endl;
+    }
+  if (verboseLevel > 0)
+    {
+      G4double energyDiff = 
+	std::fabs(eKineticEnergy+energyInFluorescence+localEnergyDeposit-photonEnergy);
+      if (energyDiff > 0.05*keV)
+	G4cout << "Warning from G4Penelope08PhotoElectric: problem with energy conservation: " << 
+	  (eKineticEnergy+energyInFluorescence+localEnergyDeposit)/keV 
+	       << " keV (final) vs. " << 
+	  photonEnergy/keV << " keV (initial)" << G4endl;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08PhotoElectricModel::ActivateAuger(G4bool augerbool)
+{
+  if (!DeexcitationFlag() && augerbool)
+    {
+      G4cout << "WARNING - G4Penelope08PhotoElectricModel" << G4endl;
+      G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
+      G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
+    }
+  deexcitationManager.ActivateAugerElectronProduction(augerbool);
+  if (verboseLevel > 1)
+    G4cout << "Auger production set to " << augerbool << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08PhotoElectricModel::SampleElectronDirection(G4double energy)
+{
+  G4double costheta = 1.0;
+  if (energy>1*GeV) return costheta;
+ 
+  //1) initialize energy-dependent variables
+  // Variable naming according to Eq. (2.24) of Penelope Manual
+  // (pag. 44)
+  G4double gamma = 1.0 + energy/electron_mass_c2;
+  G4double gamma2 = gamma*gamma;
+  G4double beta = std::sqrt((gamma2-1.0)/gamma2);
+   
+  // ac corresponds to "A" of Eq. (2.31)
+  //
+  G4double ac = (1.0/beta) - 1.0;
+  G4double a1 = 0.5*beta*gamma*(gamma-1.0)*(gamma-2.0);
+  G4double a2 = ac + 2.0;
+  G4double gtmax = 2.0*(a1 + 1.0/ac);
+ 
+  G4double tsam = 0;
+  G4double gtr = 0;
+
+  //2) sampling. Eq. (2.31) of Penelope Manual
+  // tsam = 1-std::cos(theta)
+  // gtr = rejection function according to Eq. (2.28)
+  do{
+    G4double rand = G4UniformRand();
+    tsam = 2.0*ac * (2.0*rand + a2*std::sqrt(rand)) / (a2*a2 - 4.0*rand);
+    gtr = (2.0 - tsam) * (a1 + 1.0/(ac+tsam));
+  }while(G4UniformRand()*gtmax > gtr);
+  costheta = 1.0-tsam;
+  
+
+  return costheta;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08PhotoElectricModel::ReadDataFile(G4int Z)
+{
+  if (verboseLevel > 2)
+    {
+      G4cout << "G4Penelope08PhotoElectricModel::ReadDataFile()" << G4endl;
+      G4cout << "Going to read PhotoElectric data files for Z=" << Z << G4endl;
+    }
+ 
+  char* path = getenv("G4LEDATA");
+  if (!path)
+    {
+      G4String excep = "G4Penelope08PhotoElectricModel - G4LEDATA environment variable not set!";
+      G4Exception(excep);
+    }
+ 
+  /*
+    Read the cross section file
+  */
+  std::ostringstream ost;
+  if (Z>9)
+    ost << path << "/penelope/photoelectric/pdgph" << Z << ".p08";
+  else
+    ost << path << "/penelope/photoelectric/pdgph0" << Z << ".p08";
+  std::ifstream file(ost.str().c_str());
+  if (!file.is_open())
+    {
+      G4String excep = "G4Penelope08PhotoElectricModel - data file " + G4String(ost.str()) + " not found!";
+      G4Exception(excep);
+    }
+  //I have to know in advance how many points are in the data list
+  //to initialize the G4PhysicsFreeVector()
+  size_t ndata=0;
+  G4String line;
+  while( getline(file, line) )
+    ndata++;
+  ndata -= 1;
+  //G4cout << "Found: " << ndata << " lines" << G4endl;
+
+  file.clear();
+  file.close();
+  file.open(ost.str().c_str());
+
+  G4int readZ =0;
+  size_t nShells= 0;
+  file >> readZ >> nShells;
+
+  if (verboseLevel > 3)
+    G4cout << "Element Z=" << Z << " , nShells = " << nShells << G4endl;
+
+  //check the right file is opened.
+  if (readZ != Z || nShells <= 0)
+    {
+      G4cout << "G4Penelope08PhotoElectricModel::ReadDataFile()" << G4endl;
+      G4cout << "Corrupted data file for Z=" << Z << G4endl;
+      G4Exception();
+    }
+  G4PhysicsTable* thePhysicsTable = new G4PhysicsTable();
+
+  //the table has to contain nShell+1 G4PhysicsFreeVectors, 
+  //(theTable)[0] --> total cross section
+  //(theTable)[ishell] --> cross section for shell (ishell-1)
+
+
+
+  //reserve space for the vectors
+  //everything is log-log
+  for (size_t i=0;i<nShells+1;i++)
+    thePhysicsTable->push_back(new G4PhysicsFreeVector(ndata));
+
+  size_t k =0;
+  for (k=0;k<ndata && !file.eof();k++)
+    {
+      G4double energy = 0;
+      G4double aValue = 0;
+      file >> energy ;
+      energy *= eV;
+      G4double logene = log(energy);
+      //loop on the columns
+      for (size_t i=0;i<nShells+1;i++)
+	{
+	  file >> aValue;
+	  aValue *= barn;
+	  G4PhysicsFreeVector* theVec = (G4PhysicsFreeVector*) ((*thePhysicsTable)[i]);	 
+	  if (aValue < 1e-40*cm2) //protection against log(0)
+	    aValue = 1e-40*cm2;
+	  theVec->PutValue(k,logene,log(aValue));
+	}
+    }
+
+  if (verboseLevel > 2)
+    {
+      G4cout << "G4Penelope08PhotoElectricModel: read " << k << " points for element Z = " 
+	     << Z << G4endl;
+    }
+
+  logAtomicShellXS->insert(std::make_pair(Z,thePhysicsTable));
+ 
+  file.close();
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+size_t G4Penelope08PhotoElectricModel::SelectRandomShell(G4int Z,G4double energy)
+{
+  G4double logEnergy = log(energy);
+
+  //Check if data have been read (it should be!)
+  if (!logAtomicShellXS->count(Z))
+     {
+       G4cout << "Problem in G4Penelope08PhotoElectricModel::SelectRandomShell" << G4endl;
+       G4cout << "Cannot find data for Z=" << Z << G4endl;
+       G4Exception();
+     }
+
+  size_t shellIndex = 0;
+ 
+  G4PhysicsTable* theTable =  logAtomicShellXS->find(Z)->second;
+
+  G4DataVector* tempVector = new G4DataVector();
+
+  G4double sum = 0;
+  //loop on shell partial XS, retrieve the value for the given energy and store on 
+  //a temporary vector
+  tempVector->push_back(sum); //first element is zero
+
+  G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[0];
+  G4double logXS = totalXSLog->Value(logEnergy);
+  G4double totalXS = exp(logXS);
+					   
+  //Notice: totalXS is the total cross section and it does *not* correspond to 
+  //the sum of partialXS's, since these include only K, L and M shells.
+  //
+  // Therefore, here one have to consider the possibility of ionisation of 
+  // an outer shell. Conventionally, it is indicated with id=10 in Penelope
+  //
+  
+  for (size_t k=1;k<theTable->entries();k++)
+    {
+      G4PhysicsFreeVector* partialXSLog = (G4PhysicsFreeVector*) (*theTable)[k];
+      G4double logXS = partialXSLog->Value(logEnergy);
+      G4double partialXS = exp(logXS);
+      sum += partialXS;
+      tempVector->push_back(sum);     
+    }
+
+  tempVector->push_back(totalXS); //last element
+
+  G4double random = G4UniformRand()*totalXS; 
+
+  /*
+  for (size_t i=0;i<tempVector->size(); i++)
+    G4cout << i << " " << (*tempVector)[i]/totalXS << G4endl;
+  */
+  
+  //locate bin of tempVector
+  //Now one has to sample according to the elements in tempVector
+  //This gives the left edge of the interval...
+  size_t lowerBound = 0;
+  size_t upperBound = tempVector->size()-1; 
+  while (lowerBound <= upperBound)
+   {
+     size_t midBin = (lowerBound + upperBound)/2;
+     if( random < (*tempVector)[midBin])
+       upperBound = midBin-1; 
+     else
+       lowerBound = midBin+1; 
+   }
+ 
+  shellIndex = upperBound;
+
+  delete tempVector;
+  return shellIndex;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+size_t G4Penelope08PhotoElectricModel::GetNumberOfShellXS(G4int Z)
+{
+  //read data files
+  if (!logAtomicShellXS->count(Z))
+    ReadDataFile(Z);
+  //now it should be ok
+  if (!logAtomicShellXS->count(Z))
+     {
+       G4cout << "Problem in G4Penelope08PhotoElectricModel::GetNumberOfShellXS()"
+              << G4endl;
+       G4Exception();
+     }
+  //one vector is allocated for the _total_ cross section
+  size_t nEntries = logAtomicShellXS->find(Z)->second->entries();
+  return  (nEntries-1);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08PhotoElectricModel::GetShellCrossSection(G4int Z,size_t shellID,G4double energy)
+{
+  //this forces also the loading of the data
+  size_t entries = GetNumberOfShellXS(Z);
+
+  if (shellID >= entries)
+    {
+      G4cout << "Element Z=" << Z << " has data for " << entries << " shells only" << G4endl;
+      G4cout << "so shellID should be from 0 to " << entries-1 << G4endl;
+      return 0;
+    }
+  
+  G4PhysicsTable* theTable =  logAtomicShellXS->find(Z)->second;
+  //[0] is the total XS, shellID is in the element [shellID+1]
+  G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[shellID+1];
+ 
+  if (!totalXSLog)
+     {
+       G4cout << "Problem in G4Penelope08PhotoElectricModel::GetShellCrossSection()"
+         << G4endl;
+       G4Exception();
+     }
+   G4double logene = log(energy);
+   G4double logXS = totalXSLog->Value(logene);
+   G4double cross = exp(logXS);
+   if (cross < 2e-40*cm2) cross = 0;
+   return cross;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4String G4Penelope08PhotoElectricModel::WriteTargetShell(size_t shellID)
+{
+  G4String theShell = "outer shell";
+  if (shellID == 0)
+    theShell = "K";
+  else if (shellID == 1)
+    theShell = "L1";
+  else if (shellID == 2)
+    theShell = "L2";
+  else if (shellID == 3)
+    theShell = "L3";
+  else if (shellID == 4)
+    theShell = "M1";
+  else if (shellID == 5)
+    theShell = "M2";
+  else if (shellID == 6)
+    theShell = "M3";
+  else if (shellID == 7)
+    theShell = "M4";
+  else if (shellID == 8)
+    theShell = "M5";
+      
+  return theShell;
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08RayleighModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08RayleighModel.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4Penelope08RayleighModel.cc	(revision 1316)
@@ -0,0 +1,1157 @@
+//
+// ********************************************************************
+// * 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: G4Penelope08RayleighModel.cc,v 1.1 2010/03/17 14:18:50 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 03 Dec 2009   L Pandola    First implementation
+//
+
+#include "G4Penelope08RayleighModel.hh"
+#include "G4PenelopeSamplingData.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4MaterialCutsCouple.hh"
+#include "G4ProductionCutsTable.hh"
+#include "G4DynamicParticle.hh"
+#include "G4PhysicsTable.hh"
+#include "G4ElementTable.hh"
+#include "G4Element.hh"
+#include "G4PenelopeIntegrator.hh"
+#include "G4PhysicsFreeVector.hh"
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+
+G4Penelope08RayleighModel::G4Penelope08RayleighModel(const G4ParticleDefinition*,
+                                             const G4String& nam)
+  :G4VEmModel(nam),isInitialised(false),logAtomicCrossSection(0),   
+   atomicFormFactor(0),logFormFactorTable(0),pMaxTable(0),samplingTable(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 
+
+  //build the energy grid. It is the same for all materials
+  G4double logenergy = log(fIntrinsicLowEnergyLimit/2.);
+  G4double logmaxenergy = log(1.5*fIntrinsicHighEnergyLimit);
+  //finer grid below 160 keV
+  G4double logtransitionenergy = log(160*keV); 
+  G4double logfactor1 = log(10.)/250.;
+  G4double logfactor2 = logfactor1*10;
+  logEnergyGridPMax.push_back(logenergy);
+  do{
+    if (logenergy < logtransitionenergy)
+      logenergy += logfactor1;
+    else
+      logenergy += logfactor2;
+    logEnergyGridPMax.push_back(logenergy);      
+  }while (logenergy < logmaxenergy);
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4Penelope08RayleighModel::~G4Penelope08RayleighModel()
+{
+  std::map <const G4int,G4PhysicsFreeVector*>::iterator i;
+  if (logAtomicCrossSection)
+    {
+      for (i=logAtomicCrossSection->begin();i != logAtomicCrossSection->end();i++)
+	if (i->second) delete i->second;
+      delete logAtomicCrossSection;
+     }
+
+   if (atomicFormFactor)
+     {
+       for (i=atomicFormFactor->begin();i != atomicFormFactor->end();i++)
+	 if (i->second) delete i->second;
+       delete atomicFormFactor;
+     }
+
+  ClearTables();
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+void G4Penelope08RayleighModel::ClearTables()
+{
+   std::map <const G4Material*,G4PhysicsFreeVector*>::iterator i;
+ 
+   if (logFormFactorTable)
+     {
+       for (i=logFormFactorTable->begin(); i != logFormFactorTable->end(); i++)
+	 if (i->second) delete i->second;
+       delete logFormFactorTable;
+       logFormFactorTable = 0; //zero explicitely
+     }
+
+   if (pMaxTable)
+     {
+       for (i=pMaxTable->begin(); i != pMaxTable->end(); i++)
+	 if (i->second) delete i->second;
+       delete pMaxTable;
+       pMaxTable = 0; //zero explicitely
+     }
+
+   std::map<const G4Material*,G4PenelopeSamplingData*>::iterator ii;
+   if (samplingTable)
+     {
+       for (ii=samplingTable->begin(); ii != samplingTable->end(); ii++)
+	 if (ii->second) delete ii->second;
+       delete samplingTable;
+       samplingTable = 0; //zero explicitely
+     }     
+
+   return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08RayleighModel::Initialise(const G4ParticleDefinition* ,
+					 const G4DataVector& )
+{
+  if (verboseLevel > 3)
+    G4cout << "Calling G4Penelope08RayleighModel::Initialise()" << G4endl;
+
+  //clear tables depending on materials, not the atomic ones
+  ClearTables();
+  
+  //create new tables
+  //
+  // logAtomicCrossSection and atomicFormFactor are created only once,
+  // since they are never cleared
+  if (!logAtomicCrossSection)
+    logAtomicCrossSection = new std::map<const G4int,G4PhysicsFreeVector*>;
+  if (!atomicFormFactor)
+    atomicFormFactor = new std::map<const G4int,G4PhysicsFreeVector*>;
+
+  if (!logFormFactorTable)
+    logFormFactorTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
+  if (!pMaxTable)
+    pMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
+  if (!samplingTable)
+    samplingTable = new std::map<const G4Material*,G4PenelopeSamplingData*>;
+
+
+  if (verboseLevel > 0) {
+    G4cout << "Penelope08 Rayleigh model is initialized " << G4endl
+	   << "Energy range: "
+	   << LowEnergyLimit() / keV << " keV - "
+	   << HighEnergyLimit() / GeV << " GeV"
+	   << G4endl;
+  }
+
+  if(isInitialised) return;
+  fParticleChange = GetParticleChangeForGamma();
+  isInitialised = true;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08RayleighModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
+							       G4double energy,
+							       G4double Z,
+							       G4double,
+							       G4double,
+							       G4double)
+{
+  // Cross section of Rayleigh scattering in Penelope2008 is calculated by the EPDL97 
+  // tabulation, Cuellen et al. (1997), with non-relativistic form factors from Hubbel 
+  // et al. J. Phys. Chem. Ref. Data 4 (1975) 471; Erratum ibid. 6 (1977) 615.
+
+   if (verboseLevel > 3)
+    G4cout << "Calling CrossSectionPerAtom() of G4Penelope08RayleighModel" << G4endl;
+ 
+   G4int iZ = (G4int) Z;
+
+   //read data files
+   if (!logAtomicCrossSection->count(iZ))
+     ReadDataFile(iZ);
+   //now it should be ok
+   if (!logAtomicCrossSection->count(iZ))
+     {
+       G4cout << "Problem in G4Penelope08RayleighModel::ComputeCrossSectionPerAtom" 
+	      << G4endl;
+       G4Exception();
+     }
+
+   G4double cross = 0;
+
+   G4PhysicsFreeVector* atom = logAtomicCrossSection->find(iZ)->second;
+   if (!atom)
+     {
+       G4cout << "Problem in G4Penelope08RayleighModel::ComputeCrossSectionPerAtom" 
+	 << G4endl;
+       G4Exception();
+     }
+   G4double logene = log(energy);
+   G4double logXS = atom->Value(logene);
+   cross = exp(logXS);
+
+   if (verboseLevel > 2)
+    G4cout << "Compton cross Section at " << energy/keV << " keV for Z=" << Z << 
+      " = " << cross/barn << " barn" << G4endl;
+    return cross;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+void G4Penelope08RayleighModel::BuildFormFactorTable(const G4Material* material)
+{
+ 
+  /*
+    1) get composition and equivalent molecular density
+  */
+  
+  G4int nElements = material->GetNumberOfElements();
+  const G4ElementVector* elementVector = material->GetElementVector();
+  const G4double* fractionVector = material->GetFractionVector();
+
+  std::vector<G4double> *StechiometricFactors = new std::vector<G4double>;
+  for (G4int i=0;i<nElements;i++)
+    {
+      G4double fraction = fractionVector[i];
+      G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
+      StechiometricFactors->push_back(fraction/atomicWeigth);
+    }
+  //Find max
+  G4double MaxStechiometricFactor = 0.;
+  for (G4int i=0;i<nElements;i++)
+    {
+      if ((*StechiometricFactors)[i] > MaxStechiometricFactor)
+        MaxStechiometricFactor = (*StechiometricFactors)[i];
+    }
+  if (MaxStechiometricFactor<1e-16)
+    {
+      G4cout << "G4Penelope08RayleighModel::BuildFormFactorTable" << G4endl;
+      G4cout << "Problem with the mass composition of " << material->GetName() << G4endl;
+      G4Exception();
+    }
+  //Normalize
+  for (G4int i=0;i<nElements;i++)
+    (*StechiometricFactors)[i] /=  MaxStechiometricFactor;
+ 
+  // Equivalent atoms per molecule
+  G4double atomsPerMolecule = 0;
+  for (G4int i=0;i<nElements;i++)
+    atomsPerMolecule += (*StechiometricFactors)[i]; 
+ 
+  /*
+    CREATE THE FORM FACTOR TABLE
+  */
+  G4PhysicsFreeVector* theFFVec = new G4PhysicsFreeVector(logQSquareGrid.size());
+  theFFVec->SetSpline(true);
+
+  for (size_t k=0;k<logQSquareGrid.size();k++)
+    {
+      G4double ff2 = 0; //squared form factor
+      for (G4int i=0;i<nElements;i++)
+	{
+	  G4int iZ = (G4int) (*elementVector)[i]->GetZ();
+	  G4PhysicsFreeVector* theAtomVec = atomicFormFactor->find(iZ)->second;
+	  G4double f = (*theAtomVec)[k]; //the q-grid is always the same	    
+	  ff2 += f*f*(*StechiometricFactors)[i];
+	}
+      if (ff2)
+	theFFVec->PutValue(k,logQSquareGrid[k],log(ff2)); //NOTICE: THIS IS log(Q^2) vs. log(F^2)
+    }
+  logFormFactorTable->insert(std::make_pair(material,theFFVec));
+
+  delete StechiometricFactors;
+  
+  return;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08RayleighModel::SampleSecondaries(std::vector<G4DynamicParticle*>* ,
+						const G4MaterialCutsCouple* couple,
+						const G4DynamicParticle* aDynamicGamma,
+						G4double,
+						G4double)
+{
+  // Sampling of the Rayleigh final state (namely, scattering angle of the photon) 
+  // from the Penelope2008 model. The scattering angle is sampled from the atomic 
+  // cross section dOmega/d(cosTheta) from Born ("Atomic Phyisics", 1969), disregarding 
+  // anomalous scattering effects. The Form Factor F(Q) function which appears in the 
+  // analytical cross section is retrieved via the method GetFSquared(); atomic data 
+  // are tabulated for F(Q). Form factor for compounds is calculated according to 
+  // the additivity rule. The sampling from the F(Q) is made via a Rational Inverse 
+  // Transform with Aliasing (RITA) algorithm; RITA parameters are calculated once 
+  // for each material and managed by G4PenelopeSamplingData objects.
+  // The sampling algorithm (rejection method) has efficiency 67% at low energy, and 
+  // increases with energy. For E=100 keV the efficiency is 100% and 86% for 
+  // hydrogen and uranium, respectively.
+
+  if (verboseLevel > 3)
+    G4cout << "Calling SamplingSecondaries() of G4Penelope08RayleighModel" << G4endl;
+
+  G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
+ 
+  if (photonEnergy0 <= fIntrinsicLowEnergyLimit)
+    {
+      fParticleChange->ProposeTrackStatus(fStopAndKill);
+      fParticleChange->SetProposedKineticEnergy(0.);
+      fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
+      return ;
+    }
+
+  G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
+  
+  const G4Material* theMat = couple->GetMaterial();
+  
+  //1) Verify if tables are ready
+  if (!pMaxTable || !samplingTable)
+    {
+      G4cout << " G4Penelope08RayleighModel::SampleSecondaries" << G4endl;
+      G4cout << "Looks like the model is _not_ properly initialized" << G4endl;
+      G4Exception();
+    }
+  
+  //2) retrieve or build the sampling table
+  if (!(samplingTable->count(theMat)))
+    InitializeSamplingAlgorithm(theMat);
+  G4PenelopeSamplingData* theDataTable = samplingTable->find(theMat)->second;
+  
+  //3) retrieve or build the pMax data
+  if (!pMaxTable->count(theMat))
+    GetPMaxTable(theMat);
+  G4PhysicsFreeVector* thePMax = pMaxTable->find(theMat)->second;
+
+  G4double cosTheta = 1.0;
+  
+  //OK, ready to go!
+  G4double qmax = 2.0*photonEnergy0/electron_mass_c2; //this is non-dimensional now
+
+  if (qmax < 1e-10) //very low momentum transfer
+    {
+      G4bool loopAgain=false;
+      do
+	{
+	  loopAgain = false;
+	  cosTheta = 1.0-2.0*G4UniformRand();
+	  G4double G = 0.5*(1+cosTheta*cosTheta);
+	  if (G4UniformRand()>G)
+	    loopAgain = true;
+	}while(loopAgain);
+    }
+  else //larger momentum transfer
+    {
+      size_t nData = theDataTable->GetNumberOfStoredPoints();
+      G4double LastQ2inTheTable = theDataTable->GetX(nData-1);
+      G4double q2max = std::min(qmax*qmax,LastQ2inTheTable);
+
+      G4bool loopAgain = false;
+      G4double MaxPValue = thePMax->Value(photonEnergy0);
+      G4double xx=0;
+      
+      //Sampling by rejection method. The rejection function is 
+      //G = 0.5*(1+cos^2(theta))
+      //
+      do{
+	loopAgain = false;
+	G4double RandomMax = G4UniformRand()*MaxPValue;
+	xx = theDataTable->SampleValue(RandomMax);
+	//xx is a random value of q^2 in (0,q2max),sampled according to 
+	//F(Q^2) via the RITA algorithm
+	if (xx > q2max)
+	  loopAgain = true;
+	cosTheta = 1.0-2.0*xx/q2max;
+	G4double G = 0.5*(1+cosTheta*cosTheta);
+	if (G4UniformRand()>G)
+	  loopAgain = true;
+      }while(loopAgain);
+    }
+  
+  G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
+ 
+  // Scattered photon angles. ( Z - axis along the parent photon)
+  G4double phi = twopi * G4UniformRand() ;
+  G4double dirX = sinTheta*std::cos(phi);
+  G4double dirY = sinTheta*std::sin(phi);
+  G4double dirZ = cosTheta;
+  
+  // Update G4VParticleChange for the scattered photon 
+  G4ThreeVector photonDirection1(dirX, dirY, dirZ);
+
+  photonDirection1.rotateUz(photonDirection0);
+  fParticleChange->ProposeMomentumDirection(photonDirection1) ;
+  fParticleChange->SetProposedKineticEnergy(photonEnergy0) ;
+ 
+
+  return;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08RayleighModel::ReadDataFile(const G4int Z)
+{
+  if (verboseLevel > 2)
+    {
+      G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+      G4cout << "Going to read Rayleigh data files for Z=" << Z << G4endl;
+    }
+
+  char* path = getenv("G4LEDATA");
+  if (!path)
+    {
+      G4String excep = "G4Penelope08RayleighModel - G4LEDATA environment variable not set!";
+      G4Exception(excep);
+    }
+
+  /*
+    Read first the cross section file
+  */
+  std::ostringstream ost;
+  if (Z>9)
+    ost << path << "/penelope/rayleigh/pdgra" << Z << ".p08";
+  else
+    ost << path << "/penelope/rayleigh/pdgra0" << Z << ".p08";
+  std::ifstream file(ost.str().c_str());
+  if (!file.is_open())
+    {
+      G4String excep = "G4Penelope08RayleighModel - data file " + G4String(ost.str()) + " not found!";
+      G4Exception(excep);
+    }
+  G4int readZ =0;
+  size_t nPoints= 0;
+  file >> readZ >> nPoints;
+  //check the right file is opened.
+  if (readZ != Z || nPoints <= 0)
+    {
+      G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+      G4cout << "Corrupted data file for Z=" << Z << G4endl;
+      G4Exception();
+    }  
+  G4PhysicsFreeVector* theVec = new G4PhysicsFreeVector((size_t)nPoints);
+  G4double ene=0,f1=0,f2=0,xs=0;
+  for (size_t i=0;i<nPoints;i++)
+    {
+      file >> ene >> f1 >> f2 >> xs;
+      //dimensional quantities
+      ene *= eV;
+      xs *= cm2;
+      theVec->PutValue(i,log(ene),log(xs));
+      if (file.eof() && i != (nPoints-1)) //file ended too early
+	{
+	  G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+	  G4cout << "Corrupted data file for Z=" << Z << G4endl;
+	  G4cout << "Found less than " << nPoints << "entries " <<G4endl;
+	  G4Exception();
+	}
+    }
+  if (!logAtomicCrossSection)
+    {
+      G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+      G4cout << "Problem with allocation of logAtomicCrossSection data table " << G4endl;
+      G4Exception();
+    }
+  logAtomicCrossSection->insert(std::make_pair(Z,theVec));
+  file.close();
+
+  /*
+    Then read the form factor file
+  */
+  std::ostringstream ost2;
+  if (Z>9)
+    ost2 << path << "/penelope/rayleigh/pdaff" << Z << ".p08";
+  else
+    ost2 << path << "/penelope/rayleigh/pdaff0" << Z << ".p08";
+  file.open(ost2.str().c_str());
+  if (!file.is_open())
+    {
+      G4String excep = "G4Penelope08RayleighModel - data file " + G4String(ost2.str()) + " not found!";
+      G4Exception(excep);
+    }
+  file >> readZ >> nPoints;
+  //check the right file is opened.
+  if (readZ != Z || nPoints <= 0)
+    {
+      G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+      G4cout << "Corrupted data file for Z=" << Z << G4endl;
+      G4Exception();
+    }  
+  G4PhysicsFreeVector* theFFVec = new G4PhysicsFreeVector((size_t)nPoints);
+  G4double q=0,ff=0,incoh=0;
+  G4bool fillQGrid = false;
+  //fill this vector only the first time.
+  if (!logQSquareGrid.size())
+    fillQGrid = true;
+  for (size_t i=0;i<nPoints;i++)
+    {
+      file >> q >> ff >> incoh;
+      //q and ff are dimensionless (q is in units of (m_e*c)
+      theFFVec->PutValue(i,q,ff);
+      if (fillQGrid)
+	{
+	  logQSquareGrid.push_back(2.0*log(q));
+	}
+      if (file.eof() && i != (nPoints-1)) //file ended too early
+	{
+	  G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+	  G4cout << "Corrupted data file for Z=" << Z << G4endl;
+	  G4cout << "Found less than " << nPoints << "entries " <<G4endl;
+	  G4Exception();
+	}
+    }
+  if (!atomicFormFactor)
+    {
+      G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
+      G4cout << "Problem with allocation of atomicFormFactor data table " << G4endl;
+      G4Exception();
+    }
+  atomicFormFactor->insert(std::make_pair(Z,theFFVec));
+  file.close();
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4Penelope08RayleighModel::GetFSquared(const G4Material* mat, const G4double QSquared)
+{
+  G4double f2 = 0;
+  G4double logQSquared = log(QSquared);
+  //last value of the table
+  G4double maxlogQ2 = logQSquareGrid[logQSquareGrid.size()-1];
+  //If the table has not been built for the material, do it!
+  if (!logFormFactorTable->count(mat))
+    BuildFormFactorTable(mat);
+  
+  //now it should  be all right
+  G4PhysicsFreeVector* theVec = logFormFactorTable->find(mat)->second;
+
+  if (!theVec)
+    {
+      G4cout << " G4Penelope08RayleighModel::GetFSquared()" << G4endl;
+      G4cout << "Unable to retrieve F squared table for " << mat->GetName();
+      G4Exception();
+    }
+  if (logQSquared < -20) // Q < 1e-9
+    {
+      G4double logf2 = (*theVec)[0]; //first value of the table
+      f2 = exp(logf2);
+    }
+  else if (logQSquared > maxlogQ2)
+    f2 =0;
+  else
+    {
+      //log(Q^2) vs. log(F^2)
+      G4double logf2 = theVec->Value(logQSquared);
+      f2 = exp(logf2);
+
+    }
+  if (verboseLevel > 3)
+    {
+      G4cout << "G4Penelope08RayleighModel::GetFSquared() in " << mat->GetName() << G4endl;  
+      G4cout << "Q^2 = " <<  QSquared << " (units of 1/(m_e*c); F^2 = " << f2 << G4endl;
+    }
+  return f2;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08RayleighModel::InitializeSamplingAlgorithm(const G4Material* mat)
+{
+  G4double q2min = 0;
+  G4double q2max = 0;
+  const size_t np = 150; //hard-coded in Penelope
+  for (size_t i=1;i<logQSquareGrid.size();i++)
+    {
+      G4double Q2 = exp(logQSquareGrid[i]);
+      if (GetFSquared(mat,Q2) >  1e-35)
+	{
+	  q2max = exp(logQSquareGrid[i-1]);
+	}
+    }
+  
+  size_t nReducedPoints = np/4;
+
+  //check for errors
+  if (np < 16)
+    {
+      G4cout << "G4Penelope08RayleighModel::InitializeSamplingAlgorithm" << G4endl;
+      G4cout << "Too few points to initialize the sampling algorithm" << G4endl;
+      G4Exception();
+    }
+  if (q2min > (q2max-1e-10))
+    {
+      G4cout << "G4Penelope08RayleighModel::InitializeSamplingAlgorithm" << G4endl;
+      G4cout << "Too narrow grid to initialize the sampling algorithm" << G4endl;
+      G4Exception();
+    }
+
+  //This is subroutine RITAI0 of Penelope
+  //Create an object of type G4Penelope08RayleighSamplingData --> store in a map::Material*
+
+  //temporary vectors --> Then everything is stored in G4PenelopeSamplingData
+  G4DataVector* x = new G4DataVector();
+  
+  /*******************************************************************************
+    Start with a grid of NUNIF points uniformly spaced in the interval q2min,q2max
+  ********************************************************************************/
+  size_t NUNIF = std::min(std::max(((size_t)8),nReducedPoints),np/2);
+  const G4int nip = 51; //hard-coded in Penelope
+
+  G4double dx = (q2max-q2min)/((G4double) NUNIF-1);
+  x->push_back(q2min);
+  for (size_t i=1;i<NUNIF-1;i++)
+    {
+      G4double app = q2min + i*dx;
+      x->push_back(app); //increase 
+    }
+  x->push_back(q2max);
+  
+  if (verboseLevel> 3)
+    G4cout << "Vector x has " << x->size() << " points, while NUNIF = " << NUNIF << G4endl;
+
+  //Allocate temporary storage vectors
+  G4DataVector* area = new G4DataVector();
+  G4DataVector* a = new G4DataVector();
+  G4DataVector* b = new G4DataVector();
+  G4DataVector* c = new G4DataVector();
+  G4DataVector* err = new G4DataVector();
+
+  for (size_t i=0;i<NUNIF-1;i++) //build all points but the last
+    {      
+      //Temporary vectors for this loop
+      G4DataVector* pdfi = new G4DataVector();
+      G4DataVector* pdfih = new G4DataVector();
+      G4DataVector* sumi = new G4DataVector();
+
+      G4double dxi = ((*x)[i+1]-(*x)[i])/(G4double (nip-1));
+      G4double pdfmax = 0;
+      for (G4int k=0;k<nip;k++)
+	{
+	  G4double xik = (*x)[i]+k*dxi;
+	  G4double pdfk = std::max(GetFSquared(mat,xik),0.);
+	  pdfi->push_back(pdfk);
+	  pdfmax = std::max(pdfmax,pdfk);	
+	  if (k < (nip-1))
+	    {
+	      G4double xih = xik + 0.5*dxi;
+	      G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
+	      pdfih->push_back(pdfIK);
+	      pdfmax = std::max(pdfmax,pdfIK);
+	    }
+	}
+    
+      //Simpson's integration
+      G4double cons = dxi*0.5*(1./3.);
+      sumi->push_back(0.);
+      for (G4int k=1;k<nip;k++)
+	{
+	  G4double previous = (*sumi)[k-1];
+	  G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
+	  sumi->push_back(next);
+	}
+    
+      G4double lastIntegral = (*sumi)[sumi->size()-1];
+      area->push_back(lastIntegral);
+      //Normalize cumulative function
+      G4double factor = 1.0/lastIntegral;
+      for (size_t k=0;k<sumi->size();k++)
+	(*sumi)[k] *= factor;
+      
+      //When the PDF vanishes at one of the interval end points, its value is modified
+      if ((*pdfi)[0] < 1e-35) 
+	(*pdfi)[0] = 1e-5*pdfmax;
+      if ((*pdfi)[pdfi->size()-1] < 1e-35)
+	(*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
+
+      G4double pli = (*pdfi)[0]*factor;
+      G4double pui = (*pdfi)[pdfi->size()-1]*factor;
+      G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
+      G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
+      G4double C_temp = 1.0+A_temp+B_temp;
+      if (C_temp < 1e-35)
+	{
+	  a->push_back(0.);
+	  b->push_back(0.);
+	  c->push_back(1.);	  
+	}
+      else
+	{
+	  a->push_back(A_temp);
+	  b->push_back(B_temp);
+	  c->push_back(C_temp);
+	}
+
+      //OK, now get ERR(I), the integral of the absolute difference between the rational interpolation 
+      //and the true pdf, extended over the interval (X(I),X(I+1))
+      G4int icase = 1; //loop code
+      G4bool reLoop = false;
+      err->push_back(0.);
+      do
+	{
+	  reLoop = false;
+	  (*err)[i] = 0.; //zero variable
+	  for (G4int k=0;k<nip;k++)
+	    {
+	      G4double rr = (*sumi)[k];
+	      G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
+		((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
+	      if (k == 0 || k == nip-1)
+		(*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
+	      else
+		(*err)[i] += std::fabs(pap-(*pdfi)[k]);
+	    }
+	  (*err)[i] *= dxi;
+      
+	  //If err(I) is too large, the pdf is approximated by a uniform distribution
+	  if ((*err)[i] > 0.1*(*area)[i] && icase == 1) 
+	    {
+	      (*b)[i] = 0;
+	      (*a)[i] = 0;
+	      (*c)[i] = 1.;
+	      icase = 2;
+	      reLoop = true;
+	    }
+	}while(reLoop);
+
+      if (pdfi) delete pdfi;
+      if (pdfih) delete pdfih;
+      if (sumi) delete sumi;
+    } //end of first loop over i
+
+  //Now assign last point
+  (*x)[x->size()-1] = q2max;
+  a->push_back(0.);
+  b->push_back(0.);
+  c->push_back(0.);
+  err->push_back(0.);
+  area->push_back(0.);
+
+  if (x->size() != NUNIF || a->size() != NUNIF || 
+      err->size() != NUNIF || area->size() != NUNIF)
+    {
+      G4cout << "G4Penelope08RayleighModel::InitializeSamplingAlgorithm" << G4endl;
+      G4cout << "Problem in building the Table for Sampling: array dimensions do not match " << G4endl;
+      G4Exception();
+    }
+  
+  /*******************************************************************************
+   New grid points are added by halving the sub-intervals with the largest absolute error
+  This is done up to np=150 points in the grid
+  ********************************************************************************/
+  do
+    {
+      G4double maxError = 0.0;
+      size_t iErrMax = 0;
+      for (size_t i=0;i<err->size()-2;i++) 
+	{
+	  //maxError is the lagest of the interval errors err[i]
+	  if ((*err)[i] > maxError)
+	    {
+	      maxError = (*err)[i];
+	      iErrMax = i;
+	    }
+	}
+      
+      //OK, now I have to insert one new point in the position iErrMax
+      G4double newx = 0.5*((*x)[iErrMax]+(*x)[iErrMax+1]);
+      
+      x->insert(x->begin()+iErrMax+1,newx);
+      //Add place-holders in the other vectors
+      area->insert(area->begin()+iErrMax+1,0.);
+      a->insert(a->begin()+iErrMax+1,0.);
+      b->insert(b->begin()+iErrMax+1,0.);
+      c->insert(c->begin()+iErrMax+1,0.);
+      err->insert(err->begin()+iErrMax+1,0.);
+        
+      //Now calculate the other parameters
+      for (size_t i=iErrMax;i<=iErrMax+1;i++)
+	{
+	  //Temporary vectors for this loop
+	  G4DataVector* pdfi = new G4DataVector();
+	  G4DataVector* pdfih = new G4DataVector();
+	  G4DataVector* sumi = new G4DataVector();
+	  
+	  G4double dx = (*x)[i+1]-(*x)[i];
+	  G4double dxi = ((*x)[i+1]-(*x)[i])/(G4double (nip-1));
+	  G4double pdfmax = 0;
+	  for (G4int k=0;k<nip;k++)
+	    {
+	      G4double xik = (*x)[i]+k*dxi;
+	      G4double pdfk = std::max(GetFSquared(mat,xik),0.);
+	      pdfi->push_back(pdfk);
+	      pdfmax = std::max(pdfmax,pdfk);	
+	      if (k < (nip-1))
+		{
+		  G4double xih = xik + 0.5*dxi;
+		  G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
+		  pdfih->push_back(pdfIK);
+		  pdfmax = std::max(pdfmax,pdfIK);
+		}
+	    }
+	  
+	  //Simpson's integration
+	  G4double cons = dxi*0.5*(1./3.);
+	  sumi->push_back(0.);
+	  for (G4int k=1;k<nip;k++)
+	    {
+	      G4double previous = (*sumi)[k-1];
+	      G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
+	      sumi->push_back(next);
+	    }
+	  G4double lastIntegral = (*sumi)[sumi->size()-1];
+	  (*area)[i] = lastIntegral;
+	  
+	  //Normalize cumulative function
+	  G4double factor = 1.0/lastIntegral;
+	  for (size_t k=0;k<sumi->size();k++)
+	    (*sumi)[k] *= factor;
+	  
+	  //When the PDF vanishes at one of the interval end points, its value is modified
+	  if ((*pdfi)[0] < 1e-35) 
+	    (*pdfi)[0] = 1e-5*pdfmax;
+	  if ((*pdfi)[pdfi->size()-1] < 1e-35)
+	    (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
+	  
+	  G4double pli = (*pdfi)[0]*factor;
+	  G4double pui = (*pdfi)[pdfi->size()-1]*factor;
+	  G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
+	  G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
+	  G4double C_temp = 1.0+A_temp+B_temp;
+	  if (C_temp < 1e-35)
+	    {
+	      (*a)[i]= 0.;
+	      (*b)[i] = 0.;
+	      (*c)[i] = 0;
+	    }
+	  else
+	    {
+	      (*a)[i]= A_temp;
+	      (*b)[i] = B_temp;
+	      (*c)[i] = C_temp;
+	    }
+	  //OK, now get ERR(I), the integral of the absolute difference between the rational interpolation 
+	  //and the true pdf, extended over the interval (X(I),X(I+1))
+	  G4int icase = 1; //loop code
+	  G4bool reLoop = false;
+	  do
+	    {
+	      reLoop = false;
+	      (*err)[i] = 0.; //zero variable
+	      for (G4int k=0;k<nip;k++)
+		{
+		  G4double rr = (*sumi)[k];
+		  G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
+		    ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
+		  if (k == 0 || k == nip-1)
+		    (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
+		  else
+		    (*err)[i] += std::fabs(pap-(*pdfi)[k]);
+		}
+	      (*err)[i] *= dxi;
+	      
+	      //If err(I) is too large, the pdf is approximated by a uniform distribution
+	      if ((*err)[i] > 0.1*(*area)[i] && icase == 1) 
+		{
+		  (*b)[i] = 0;
+		  (*a)[i] = 0;
+		  (*c)[i] = 1.;
+		  icase = 2;
+		  reLoop = true;
+		}
+	    }while(reLoop);
+	  if (pdfi) delete pdfi;
+	  if (pdfih) delete pdfih;
+	  if (sumi) delete sumi;
+	}
+    }while(x->size() < np);
+
+  if (x->size() != np || a->size() != np || 
+      err->size() != np || area->size() != np)
+    {
+      G4cout << "G4Penelope08RayleighModel::InitializeSamplingAlgorithm" << G4endl;
+      G4cout << "Problem in building the extended Table for Sampling: array dimensions do not match " << G4endl;
+      G4Exception();
+    }
+
+  /*******************************************************************************
+   Renormalization
+  ********************************************************************************/
+  G4double ws = 0;
+  for (size_t i=0;i<np-1;i++)
+    ws += (*area)[i];
+  ws = 1.0/ws;
+  G4double errMax = 0;
+  for (size_t i=0;i<np-1;i++)
+    {
+      (*area)[i] *= ws;
+      (*err)[i] *= ws;
+      errMax = std::max(errMax,(*err)[i]);
+    }
+
+  //Vector with the normalized cumulative distribution
+  G4DataVector* PAC = new G4DataVector();
+  PAC->push_back(0.);
+  for (size_t i=0;i<np-1;i++)
+    {
+      G4double previous = (*PAC)[i];
+      PAC->push_back(previous+(*area)[i]);
+    }
+  (*PAC)[PAC->size()-1] = 1.;
+		     
+  /*******************************************************************************
+  Pre-calculated limits for the initial binary search for subsequent sampling
+  ********************************************************************************/
+
+  //G4DataVector* ITTL = new G4DataVector();
+  std::vector<size_t> *ITTL = new std::vector<size_t>;
+  std::vector<size_t> *ITTU = new std::vector<size_t>;
+
+  //Just create place-holders
+  for (size_t i=0;i<np;i++)
+    {
+      ITTL->push_back(0);
+      ITTU->push_back(0);
+    }
+
+  G4double bin = 1.0/(np-1);
+  (*ITTL)[0]=0;
+  for (size_t i=1;i<(np-1);i++)
+    {
+      G4double ptst = i*bin; 
+      G4bool found = false;
+      for (size_t j=(*ITTL)[i-1];j<np && !found;j++)
+	{
+	  if ((*PAC)[j] > ptst)
+	    {
+	      (*ITTL)[i] = j-1;
+	      (*ITTU)[i-1] = j;
+	      found = true;
+	    }
+	}
+    }
+  (*ITTU)[ITTU->size()-2] = ITTU->size()-1;
+  (*ITTU)[ITTU->size()-1] = ITTU->size()-1;
+  (*ITTL)[ITTL->size()-1] = ITTU->size()-2;
+
+  if (ITTU->size() != np || ITTU->size() != np)
+    {
+      G4cout << "G4Penelope08RayleighModel::InitializeSamplingAlgorithm" << G4endl;
+      G4cout << "Problem in building the Limit Tables for Sampling: array dimensions do not match " << G4endl;
+      G4Exception();
+    }
+
+
+  /********************************************************************************
+    Copy tables
+  ********************************************************************************/
+  G4PenelopeSamplingData* theTable = new G4PenelopeSamplingData(np);
+  for (size_t i=0;i<np;i++)
+    {
+      theTable->AddPoint((*x)[i],(*PAC)[i],(*a)[i],(*b)[i],(*ITTL)[i],(*ITTU)[i]);
+    }
+
+  if (verboseLevel > 2)
+    {
+      G4cout << "*************************************************************************" << G4endl;
+      G4cout << "Sampling table for Penelope Rayleigh scattering in " << mat->GetName() << G4endl;
+      theTable->DumpTable();
+    } 
+  samplingTable->insert(std::make_pair(mat,theTable));
+
+ 
+  //Clean up temporary vectors
+  if (x) delete x;
+  if (a) delete a;
+  if (b) delete b;
+  if (c) delete c;
+  if (err) delete err;
+  if (area) delete area;
+  if (PAC) delete PAC;
+  if (ITTL) delete ITTL;
+  if (ITTU) delete ITTU;
+
+  //DONE!
+  return;
+  
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08RayleighModel::GetPMaxTable(const G4Material* mat)
+{
+  if (!pMaxTable)
+    {
+      G4cout << "G4Penelope08RayleighModel::BuildPMaxTable" << G4endl;
+      G4cout << "Going to instanziate the pMaxTable !" << G4endl;
+      G4cout << "That should _not_ be here! " << G4endl;
+      pMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
+    }
+  //check if the table is already there
+  if (pMaxTable->count(mat))
+    return;
+
+  //otherwise build it
+  if (!samplingTable)
+    {
+      G4cout << "G4Penelope08RayleighModel::BuildPMaxTable" << G4endl;
+      G4cout << "WARNING: samplingTable is not properly instantiated" << G4endl;
+      G4Exception();
+    }
+
+  if (!samplingTable->count(mat))
+    InitializeSamplingAlgorithm(mat);      
+  
+  G4PenelopeSamplingData *theTable = samplingTable->find(mat)->second;
+  size_t tablePoints = theTable->GetNumberOfStoredPoints();
+
+  size_t nOfEnergyPoints = logEnergyGridPMax.size();
+  G4PhysicsFreeVector* theVec = new G4PhysicsFreeVector(nOfEnergyPoints);
+
+  const size_t nip = 51; //hard-coded in Penelope
+
+  for (size_t ie=0;ie<logEnergyGridPMax.size();ie++)
+    {
+      G4double energy = exp(logEnergyGridPMax[ie]);
+      G4double Qm = 2.0*energy/electron_mass_c2; //this is non-dimensional now
+      G4double Qm2 = Qm*Qm;
+      G4double firstQ2 = theTable->GetX(0);
+      G4double lastQ2 = theTable->GetX(tablePoints-1);
+      G4double thePMax = 0;
+      
+      if (Qm2 > firstQ2)
+	{
+	  if (Qm2 < lastQ2)
+	    {
+	      //bisection to look for the index of Qm
+	      size_t lowerBound = 0;
+	      size_t upperBound = tablePoints-1;
+	      while (lowerBound <= upperBound)
+		{
+		  size_t midBin = (lowerBound + upperBound)/2;
+		  if( Qm2 < theTable->GetX(midBin))
+		    { upperBound = midBin-1; }
+		  else
+		    { lowerBound = midBin+1; }
+		}
+	      //upperBound is the output (but also lowerBounf --> should be the same!)
+	      G4double Q1 = theTable->GetX(upperBound);
+ 	      G4double Q2 = Qm2;
+	      G4double DQ = (Q2-Q1)/((G4double)(nip-1));
+	      G4double theA = theTable->GetA(upperBound);
+	      G4double theB = theTable->GetB(upperBound);
+	      G4double thePAC = theTable->GetPAC(upperBound);
+	      G4DataVector* fun = new G4DataVector();
+	      for (size_t k=0;k<nip;k++)
+		{
+		  G4double qi = Q1 + k*DQ;
+		  G4double tau = (qi-Q1)/
+		    (theTable->GetX(upperBound+1)-Q1);
+		  G4double con1 = 2.0*theB*tau; 
+		  G4double ci = 1.0+theA+theB;
+		  G4double con2 = ci-theA*tau;
+		  G4double etap = 0;
+		  if (std::fabs(con1) > 1.0e-16*std::fabs(con2))
+		    etap = con2*(1.0-std::sqrt(1.0-2.0*tau*con1/(con2*con2)))/con1;
+		  else
+		    etap = tau/con2;
+		  G4double theFun = (theTable->GetPAC(upperBound+1)-thePAC)*
+		    (1.0+(theA+theB*etap)*etap)*(1.0+(theA+theB*etap)*etap)/
+		    ((1.0-theB*etap*etap)*ci*(theTable->GetX(upperBound+1)-Q1));
+		  fun->push_back(theFun);
+		}
+	      //Now intergrate numerically the fun Cavalieri-Simpson's method
+	      G4DataVector* sum = new G4DataVector;
+	      G4double CONS = DQ*(1./12.);
+	      G4double HCONS = 0.5*CONS;
+	      sum->push_back(0.);
+	      G4double secondPoint = (*sum)[0] + 
+		(5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*CONS;
+	      sum->push_back(secondPoint);
+	      for (size_t hh=2;hh<nip-1;hh++)
+		{
+		  G4double previous = (*sum)[hh-1];
+		  G4double next = previous+(13.0*((*fun)[hh-1]+(*fun)[hh])-
+					    (*fun)[hh+1]-(*fun)[hh-2])*HCONS;
+		  sum->push_back(next);
+		}
+	      G4double last = (*sum)[nip-2]+(5.0*(*fun)[nip-1]+8.0*(*fun)[nip-2]-
+					     (*fun)[nip-3])*CONS;
+	      sum->push_back(last);	 
+	      thePMax = thePAC + (*sum)[sum->size()-1]; //last point
+	      if (fun) delete fun;
+	      if (sum) delete sum;
+	    }
+	  else
+	    {
+	      thePMax = 1.0;
+	    }	 
+	}
+      else
+	{
+	  thePMax = theTable->GetPAC(0);
+	}
+
+      //Write number in the table
+      theVec->PutValue(ie,energy,thePMax);
+  }
+  
+  pMaxTable->insert(std::make_pair(mat,theVec));
+  return;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4Penelope08RayleighModel::DumpFormFactorTable(const G4Material* mat)
+{
+  G4cout << "*****************************************************************" << G4endl;
+  G4cout << "G4Penelope08RayleighModel: Form Factor Table for " << mat->GetName() << G4endl;
+  //try to use the same format as Penelope-Fortran, namely Q (/m_e*c) and F
+  G4cout <<  "Q/(m_e*c)                 F(Q)     " << G4endl;
+  G4cout << "*****************************************************************" << G4endl;
+  if (!logFormFactorTable->count(mat))
+    BuildFormFactorTable(mat);
+  
+  G4PhysicsFreeVector* theVec = logFormFactorTable->find(mat)->second;
+  for (size_t i=0;i<theVec->GetVectorLength();i++)
+    {
+      G4double logQ2 = theVec->GetLowEdgeEnergy(i);
+      G4double Q = exp(0.5*logQ2);
+      G4double logF2 = (*theVec)[i];
+      G4double F = exp(0.5*logF2);
+      G4cout << Q << "              " << F << G4endl;
+    }
+  //DONE
+  return;
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeOscillator.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeOscillator.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeOscillator.cc	(revision 1316)
@@ -0,0 +1,98 @@
+//
+// ********************************************************************
+// * 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.          *
+// ********************************************************************
+//
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 18 Dec 2008   L Pandola    First implementation 
+
+#include "G4PenelopeOscillator.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillator::G4PenelopeOscillator() :
+ hartreeFactor(0), ionisationEnergy(0*eV), resonanceEnergy(0*eV),
+ oscillatorStrength(0), shellFlag(-1), parentZ(0),
+ parentShellID(-1),cutoffRecoilResonantEnergy(0*eV)
+{;}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillator::G4PenelopeOscillator(const G4PenelopeOscillator& right)
+{
+  hartreeFactor = right.hartreeFactor;
+  ionisationEnergy = right.ionisationEnergy;
+  resonanceEnergy = right.resonanceEnergy;
+  oscillatorStrength = right.oscillatorStrength;
+  shellFlag = right.shellFlag;
+  parentZ = right.parentZ;
+  parentShellID = right.parentShellID;
+  cutoffRecoilResonantEnergy = right.cutoffRecoilResonantEnergy;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+const G4PenelopeOscillator& G4PenelopeOscillator::operator=(const G4PenelopeOscillator& right)
+{
+  hartreeFactor = right.hartreeFactor;
+  ionisationEnergy = right.ionisationEnergy;
+  resonanceEnergy = right.resonanceEnergy;
+  oscillatorStrength = right.oscillatorStrength;
+  shellFlag = right.shellFlag;
+  parentZ = right.parentZ;
+  parentShellID = right.parentShellID; 
+  cutoffRecoilResonantEnergy = right.cutoffRecoilResonantEnergy;
+  return *this;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+int G4PenelopeOscillator::operator==(const G4PenelopeOscillator& right) const
+{
+  //Oscillator are ordered according to the ionisation energy. They are considered to be
+  //equal if the ionisation energy is the same
+  return (ionisationEnergy == right.ionisationEnergy) ? 1 : 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+int G4PenelopeOscillator::operator>(const G4PenelopeOscillator& right) const
+{
+  //Oscillator are ordered according to the ionisation energy. 
+  return (ionisationEnergy > right.ionisationEnergy) ? 1 : 0;
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+int G4PenelopeOscillator::operator<(const G4PenelopeOscillator& right) const
+{
+  //Oscillator are ordered according to the ionisation energy. 
+  return (ionisationEnergy < right.ionisationEnergy) ? 1 : 0;
+}
+
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeOscillatorManager.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeOscillatorManager.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeOscillatorManager.cc	(revision 1316)
@@ -0,0 +1,1165 @@
+//
+// ********************************************************************
+// * 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.          *
+// ********************************************************************
+//
+// Authors: Luciano Pandola (luciano.pandola at lngs.infn.it)
+//
+// History:
+// -----------
+//  
+//  03 Dec 2009  First working version, Luciano Pandola
+//  16 Feb 2010  Added methods to store also total Z and A for the 
+//               molecule, Luciano Pandola 
+//  19 Feb 2010  Scale the Hartree factors in the Compton Oscillator 
+//               table by (1/fine_structure_const), since the models use 
+//               always the ratio (hartreeFactor/fine_structure_const)
+//  16 Mar 2010  Added methods to calculate and store mean exc energy
+//               and plasma energy (used for Ionisation). L Pandola
+//  18 Mar 2010  Added method to retrieve number of atoms per 
+//               molecule. L. Pandola
+//
+// -------------------------------------------------------------------
+
+#include "G4PenelopeOscillatorManager.hh"
+#include "G4Material.hh"
+#include "globals.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillatorManager::G4PenelopeOscillatorManager() : 
+  oscillatorStoreIonisation(0),oscillatorStoreCompton(0),atomicNumber(0),
+  atomicMass(0),excitationEnergy(0),plasmaSquared(0),atomsPerMolecule(0)
+{
+  fReadElementData = false;
+  for (G4int i=0;i<5;i++)
+    {
+      for (G4int j=0;j<2000;j++)
+	elementData[i][j] = 0.;
+    }
+  verbosityLevel = 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillatorManager::~G4PenelopeOscillatorManager()
+{
+  Clear();
+}
+ 
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillatorManager* G4PenelopeOscillatorManager::instance = 0;
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillatorManager* G4PenelopeOscillatorManager::GetOscillatorManager()
+{
+  if (!instance)
+    instance = new G4PenelopeOscillatorManager();
+  return instance;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeOscillatorManager::Clear()
+{
+  if (verbosityLevel > 1)
+    G4cout << " G4PenelopeOscillatorManager::Clear() - Clean Oscillator Tables" << G4endl;
+
+  //Clean up OscillatorStoreIonisation
+  std::map<const G4Material*,G4PenelopeOscillatorTable*>::iterator i;
+  for (i=oscillatorStoreIonisation->begin();i != oscillatorStoreIonisation->end();i++)
+    {
+      G4PenelopeOscillatorTable* table = i->second;
+      if (table)
+	{
+	  for (size_t k=0;k<table->size();k++) //clean individual oscillators
+	    {
+	      if ((*table)[k]) 
+		delete ((*table)[k]);
+	    }
+	  delete table;
+	}
+    }
+  delete oscillatorStoreIonisation;
+
+  //Clean up OscillatorStoreCompton
+  for (i=oscillatorStoreCompton->begin();i != oscillatorStoreCompton->end();i++)
+    {
+      G4PenelopeOscillatorTable* table = i->second;
+      if (table)
+	{
+	  for (size_t k=0;k<table->size();k++) //clean individual oscillators
+	    {
+	      if ((*table)[k]) 
+		delete ((*table)[k]);
+	    }
+	  delete table;
+	}
+    }
+  delete oscillatorStoreCompton;
+
+  if (atomicMass) delete atomicMass;
+  if (atomicNumber) delete atomicNumber;
+  if (excitationEnergy) delete excitationEnergy;
+  if (plasmaSquared) delete plasmaSquared;
+  if (atomsPerMolecule) delete atomsPerMolecule;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeOscillatorManager::Dump(const G4Material* material)
+{
+  G4PenelopeOscillatorTable* theTable = GetOscillatorTableIonisation(material);
+  if (!theTable)
+    {
+      G4cout << " G4PenelopeOscillatorManager::Dump " << G4endl;
+      G4cout << "Problem in retrieving the Ionisation Oscillator Table for " << material->GetName() << G4endl;
+      return;
+    }
+  G4cout << "*********************************************************************" << G4endl;
+  G4cout << " Penelope Oscillator Table Ionisation for " << material->GetName() << G4endl;
+  G4cout << "*********************************************************************" << G4endl;
+  G4cout << "The table contains " << theTable->size() << " oscillators " << G4endl;
+  G4cout << "*********************************************************************" << G4endl;
+  if (theTable->size() < 10)
+    for (size_t k=0;k<theTable->size();k++)
+      {
+	G4cout << "Oscillator # " << k << " Z = " << (*theTable)[k]->GetParentZ() <<
+	  " Shell Flag = " << (*theTable)[k]->GetShellFlag() << 
+	  " Parent shell ID = " << (*theTable)[k]->GetParentShellID() << G4endl;
+	G4cout << "Ionisation energy = " << (*theTable)[k]->GetIonisationEnergy()/eV << " eV" << G4endl;
+	G4cout << "Occupation number = " << (*theTable)[k]->GetOscillatorStrength() << G4endl;
+	G4cout << "Resonance energy = " << (*theTable)[k]->GetResonanceEnergy()/eV << " eV" << G4endl;
+	G4cout << "Cufoff resonance energy = " << 
+		(*theTable)[k]->GetCutoffRecoilResonantEnergy()/eV << " eV" << G4endl;
+	G4cout << "*********************************************************************" << G4endl;
+      }
+  for (size_t k=0;k<theTable->size();k++)
+    { 
+      G4cout << k << " " << (*theTable)[k]->GetOscillatorStrength() << " " << 
+	(*theTable)[k]->GetIonisationEnergy()/eV << " " << (*theTable)[k]->GetResonanceEnergy()/eV << " " << 
+	(*theTable)[k]->GetParentZ() << " " << (*theTable)[k]->GetShellFlag() << " " << 
+	(*theTable)[k]->GetParentShellID() << G4endl;
+    }
+  G4cout << "*********************************************************************" << G4endl;
+ 
+
+  //Compton table
+  theTable = GetOscillatorTableCompton(material);
+  if (!theTable)
+    {
+      G4cout << " G4PenelopeOscillatorManager::Dump " << G4endl;
+      G4cout << "Problem in retrieving the Compton Oscillator Table for " << material->GetName() << G4endl;
+      return;
+    }
+  G4cout << "*********************************************************************" << G4endl;
+  G4cout << " Penelope Oscillator Table Compton for " << material->GetName() << G4endl;
+  G4cout << "*********************************************************************" << G4endl;
+  G4cout << "The table contains " << theTable->size() << " oscillators " << G4endl;
+  G4cout << "*********************************************************************" << G4endl;
+  if (theTable->size() < 10)
+    for (size_t k=0;k<theTable->size();k++)
+      {
+	G4cout << "Oscillator # " << k << " Z = " << (*theTable)[k]->GetParentZ() <<
+	  " Shell Flag = " << (*theTable)[k]->GetShellFlag() << 
+	   " Parent shell ID = " << (*theTable)[k]->GetParentShellID() << G4endl;
+	G4cout << "Compton index = " << (*theTable)[k]->GetHartreeFactor() << G4endl;
+	G4cout << "Ionisation energy = " << (*theTable)[k]->GetIonisationEnergy()/eV << " eV" << G4endl;
+	G4cout << "Occupation number = " << (*theTable)[k]->GetOscillatorStrength() << G4endl;
+	G4cout << "*********************************************************************" << G4endl;
+      }
+  for (size_t k=0;k<theTable->size();k++)
+    { 
+      G4cout << k << " " << (*theTable)[k]->GetOscillatorStrength() << " " << 
+	(*theTable)[k]->GetIonisationEnergy()/eV << " " << (*theTable)[k]->GetHartreeFactor() << " " << 
+	(*theTable)[k]->GetParentZ() << " " << (*theTable)[k]->GetShellFlag() << " " << 
+	(*theTable)[k]->GetParentShellID() << G4endl;
+    }
+  G4cout << "*********************************************************************" << G4endl;
+  
+
+  //just to test it
+  //Clear();
+ 
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeOscillatorManager::CheckForTablesCreated()
+{
+  //Tables should be created at the same time, since they are both filled 
+  //simultaneously
+  if (!oscillatorStoreIonisation) 
+    {
+      oscillatorStoreIonisation = new std::map<const G4Material*,G4PenelopeOscillatorTable*>;
+      if (!fReadElementData)
+	ReadElementData();
+      if (!oscillatorStoreIonisation)
+	{
+	  //It should be ok now
+	  G4cout << "G4PenelopeOscillatorManager::GetOscillatorTableIonisation() " << G4endl;
+	  G4cout << "Problem in allocating the Oscillator Store for Ionisation" << G4endl;
+	  G4cout << "Abort execution" << G4endl;
+	  G4Exception();
+	}
+    }
+
+  if (!oscillatorStoreCompton) 
+    {
+      oscillatorStoreCompton = new std::map<const G4Material*,G4PenelopeOscillatorTable*>;
+      if (!fReadElementData)
+	ReadElementData();
+      if (!oscillatorStoreCompton)
+	{
+	  //It should be ok now
+	  G4cout << "G4PenelopeOscillatorManager::GetOscillatorTableCompton() " << G4endl;
+	  G4cout << "Problem in allocating the Oscillator Store for Compton" << G4endl;
+	  G4cout << "Abort execution" << G4endl;
+	  G4Exception();
+	}
+    }
+
+  if (!atomicNumber)
+    atomicNumber = new std::map<const G4Material*,G4double>;
+  if (!atomicMass)
+    atomicMass = new std::map<const G4Material*,G4double>;
+  if (!excitationEnergy)
+    excitationEnergy = new std::map<const G4Material*,G4double>;
+  if (!plasmaSquared)
+    plasmaSquared = new std::map<const G4Material*,G4double>;
+  if (!atomsPerMolecule)
+    atomsPerMolecule = new std::map<const G4Material*,G4double>;
+  
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4PenelopeOscillatorManager::GetTotalZ(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStores and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (atomicNumber->count(mat))
+    return atomicNumber->find(mat)->second;
+    
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (atomicNumber->count(mat))
+    return atomicNumber->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetTotalZ() " << G4endl;
+      G4cout << "Impossible to retrieve the total Z for " << mat->GetName() << G4endl;      
+      return 0;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4double G4PenelopeOscillatorManager::GetTotalA(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStores and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (atomicMass->count(mat))
+    return atomicMass->find(mat)->second;
+    
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (atomicMass->count(mat))
+    return atomicMass->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetTotalA() " << G4endl;
+      G4cout << "Impossible to retrieve the total A for " << mat->GetName() << G4endl;      
+      return 0;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillatorTable* G4PenelopeOscillatorManager::GetOscillatorTableIonisation(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStores and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (oscillatorStoreIonisation->count(mat))
+    {
+      //Ok, it exists
+      return oscillatorStoreIonisation->find(mat)->second;
+    }
+
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (oscillatorStoreIonisation->count(mat))
+    return oscillatorStoreIonisation->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetOscillatorTableIonisation() " << G4endl;
+      G4cout << "Impossible to create ionisation oscillator table for " << mat->GetName() << G4endl;      
+      return NULL;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillator* G4PenelopeOscillatorManager::GetOscillatorIonisation(const G4Material* material,
+									   G4int index)
+{
+  G4PenelopeOscillatorTable* theTable = GetOscillatorTableIonisation(material);
+  if (((size_t)index) < theTable->size())
+    return (*theTable)[index];
+  else
+    {
+      G4cout << "WARNING: Ionisation table for material " << material->GetName() << " has " << 
+	theTable->size() << " oscillators" << G4endl;
+      G4cout << "Oscillator #" << index << " cannot be retrieved" << G4endl;
+      G4cout << "Returning null pointer" << G4endl;
+      return NULL;
+    }     
+}
+
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillatorTable* G4PenelopeOscillatorManager::GetOscillatorTableCompton(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStore and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (oscillatorStoreCompton->count(mat))
+    {
+      //Ok, it exists
+      return oscillatorStoreCompton->find(mat)->second;
+    }
+
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (oscillatorStoreCompton->count(mat))
+    return oscillatorStoreCompton->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetOscillatorTableCompton() " << G4endl;
+      G4cout << "Impossible to create Compton oscillator table for " << mat->GetName() << G4endl;      
+      return NULL;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+G4PenelopeOscillator* G4PenelopeOscillatorManager::GetOscillatorCompton(const G4Material* material,
+									G4int index)
+{
+  G4PenelopeOscillatorTable* theTable = GetOscillatorTableCompton(material);
+  if (((size_t)index) < theTable->size())
+    return (*theTable)[index];
+  else
+    {
+      G4cout << "WARNING: Compton table for material " << material->GetName() << " has " << 
+	theTable->size() << " oscillators" << G4endl;
+      G4cout << "Oscillator #" << index << " cannot be retrieved" << G4endl;
+      G4cout << "Returning null pointer" << G4endl;
+      return NULL;
+    }     
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeOscillatorManager::BuildOscillatorTable(const G4Material* material)
+{
+  //THIS CORRESPONDS TO THE ROUTINE PEMATW of PENELOPE
+
+  G4double meanAtomExcitationEnergy[99] = {19.2*eV, 41.8*eV, 40.0*eV, 63.7*eV, 76.0*eV, 81.0*eV,
+					   82.0*eV, 95.0*eV,115.0*eV,137.0*eV,149.0*eV,156.0*eV,
+					   166.0*eV,
+					   173.0*eV,173.0*eV,180.0*eV,174.0*eV,188.0*eV,190.0*eV,191.0*eV,
+					   216.0*eV,233.0*eV,245.0*eV,257.0*eV,272.0*eV,286.0*eV,297.0*eV,
+					   311.0*eV,322.0*eV,330.0*eV,334.0*eV,350.0*eV,347.0*eV,348.0*eV,
+					   343.0*eV,352.0*eV,363.0*eV,366.0*eV,379.0*eV,393.0*eV,417.0*eV,
+					   424.0*eV,428.0*eV,441.0*eV,449.0*eV,470.0*eV,470.0*eV,469.0*eV,
+					   488.0*eV,488.0*eV,487.0*eV,485.0*eV,491.0*eV,482.0*eV,488.0*eV,
+					   491.0*eV,501.0*eV,523.0*eV,535.0*eV,546.0*eV,560.0*eV,574.0*eV,
+					   580.0*eV,591.0*eV,614.0*eV,628.0*eV,650.0*eV,658.0*eV,674.0*eV,
+					   684.0*eV,694.0*eV,705.0*eV,718.0*eV,727.0*eV,736.0*eV,746.0*eV,
+					   757.0*eV,790.0*eV,790.0*eV,800.0*eV,810.0*eV,823.0*eV,823.0*eV,
+					   830.0*eV,825.0*eV,794.0*eV,827.0*eV,826.0*eV,841.0*eV,847.0*eV,
+					   878.0*eV,890.0*eV,902.0*eV,921.0*eV,934.0*eV,939.0*eV,952.0*eV,
+					   966.0*eV,980.0*eV};
+
+  if (verbosityLevel > 0)
+    G4cout << "Going to build Oscillator Table for " << material->GetName() << G4endl;
+
+  G4int nElements = material->GetNumberOfElements();
+  const G4ElementVector* elementVector = material->GetElementVector();
+ 
+    
+  //At the moment, there's no way in Geant4 to know if a material
+  //is defined with atom numbers or fraction of weigth
+  const G4double* fractionVector = material->GetFractionVector();
+
+
+  //Take always the composition by fraction of mass. For the composition by 
+  //atoms: it is calculated by Geant4 but with some rounding to integers
+  G4double totalZ = 0;
+  G4double totalMolecularWeight = 0;
+  G4double meanExcitationEnergy = 0;
+
+  std::vector<G4double> *StechiometricFactors = new std::vector<G4double>;
+  
+  for (G4int i=0;i<nElements;i++)
+    {
+      //G4int iZ = (G4int) (*elementVector)[i]->GetZ();
+      G4double fraction = fractionVector[i];
+      G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
+      StechiometricFactors->push_back(fraction/atomicWeigth);
+    }      
+  //Find max
+  G4double MaxStechiometricFactor = 0.;
+  for (G4int i=0;i<nElements;i++)
+    {
+      if ((*StechiometricFactors)[i] > MaxStechiometricFactor)
+	MaxStechiometricFactor = (*StechiometricFactors)[i];
+    }
+  if (MaxStechiometricFactor<1e-16)
+    {
+      G4cout << "G4PenelopeOscillatorManager::BuildOscillatorTable" << G4endl;
+      G4cout << "Problem with the mass composition of " << material->GetName() << G4endl;
+      G4Exception();
+    }
+  //Normalize
+  for (G4int i=0;i<nElements;i++)
+    (*StechiometricFactors)[i] /=  MaxStechiometricFactor;
+
+  // Equivalent atoms per molecule
+  G4double theatomsPerMolecule = 0;
+  for (G4int i=0;i<nElements;i++)
+    theatomsPerMolecule += (*StechiometricFactors)[i];
+  G4double moleculeDensity = 
+    material->GetTotNbOfAtomsPerVolume()/theatomsPerMolecule; //molecules per unit volume
+
+
+  if (verbosityLevel > 1)
+    {
+      for (size_t i=0;i<StechiometricFactors->size();i++)
+	{
+	  G4cout << "Element " << (*elementVector)[i]->GetSymbol() << " (Z = " << 
+	    (*elementVector)[i]->GetZ() << ") --> " << 
+	    (*StechiometricFactors)[i] << " atoms/molecule " << G4endl;	      
+	}
+    }
+
+
+  for (G4int i=0;i<nElements;i++)
+    {
+      G4int iZ = (G4int) (*elementVector)[i]->GetZ();
+      totalZ += iZ * (*StechiometricFactors)[i];
+      totalMolecularWeight += (*elementVector)[i]->GetA() * (*StechiometricFactors)[i];
+      meanExcitationEnergy += iZ*log(meanAtomExcitationEnergy[iZ-1])*(*StechiometricFactors)[i];
+      /*
+      G4cout << iZ << " " << (*StechiometricFactors)[i] << " " << totalZ << " " << 
+	totalMolecularWeight/(g/mole) << " " << meanExcitationEnergy << " " << 
+	meanAtomExcitationEnergy[iZ-1]/eV << 
+	G4endl;
+      */
+    }
+  meanExcitationEnergy = exp(meanExcitationEnergy/totalZ);
+
+  atomicNumber->insert(std::make_pair(material,totalZ));
+  atomicMass->insert(std::make_pair(material,totalMolecularWeight));
+  excitationEnergy->insert(std::make_pair(material,meanExcitationEnergy));
+  atomsPerMolecule->insert(std::make_pair(material,theatomsPerMolecule));
+
+  if (verbosityLevel > 1)
+    {
+      G4cout << "Calculated mean excitation energy for " << material->GetName() << 
+	" = " << meanExcitationEnergy/eV << " eV" << G4endl;
+    }
+  
+  std::vector<G4PenelopeOscillator> *helper = new std::vector<G4PenelopeOscillator>;
+
+  //First Oscillator: conduction band. Tentativaly assumed to consist of valence electrons (each 
+  //atom contributes a number of electrons equal to its lowest chemical valence)
+  G4PenelopeOscillator newOsc; 
+  newOsc.SetOscillatorStrength(0.);
+  newOsc.SetIonisationEnergy(0*eV);
+  newOsc.SetHartreeFactor(0);
+  newOsc.SetParentZ(0);
+  newOsc.SetShellFlag(30);
+  newOsc.SetParentShellID(30); //does not correspond to any "real" level
+  helper->push_back(newOsc);
+
+  //Load elements and oscillators
+  for (G4int k=0;k<nElements;k++)
+    {
+      G4double Z = (*elementVector)[k]->GetZ();
+      G4bool finished = false;
+      for (G4int i=0;i<2000 && !finished;i++)
+	{
+	  /*
+	    elementData[0][i] = Z;
+	    elementData[1][i] = shellCode;
+	    elementData[2][i] = occupationNumber;
+	    elementData[3][i] = ionisationEnergy;
+	    elementData[4][i] = hartreeProfile;
+	  */
+	  if (elementData[0][i] == Z)
+	    {
+	      G4int shellID = (G4int) elementData[1][i];
+	      G4double occup = elementData[2][i];
+	      if (shellID > 0)
+		{
+		  if (fabs(occup) > 0)
+		    {
+		      G4PenelopeOscillator newOsc; 
+		      newOsc.SetOscillatorStrength(fabs(occup)*(*StechiometricFactors)[k]);
+		      newOsc.SetIonisationEnergy(elementData[3][i]);
+		      newOsc.SetHartreeFactor(elementData[4][i]/fine_structure_const);
+		      newOsc.SetParentZ(elementData[0][i]);
+		      //keep track of the origianl shell level
+		      newOsc.SetParentShellID((G4int)elementData[1][i]);
+		      //register only K, L and M shells. Outer shells all grouped with 
+		      //shellIndex = 30
+		      if (elementData[0][i] > 6 && elementData[1][i] < 10)
+			newOsc.SetShellFlag(((G4int)elementData[1][i]));
+		      else
+			newOsc.SetShellFlag(30);
+		      helper->push_back(newOsc);
+		      if (occup < 0)		  
+			{
+			  G4double ff = (*helper)[0].GetOscillatorStrength();
+			  ff += fabs(occup)*(*StechiometricFactors)[k];
+			  (*helper)[0].SetOscillatorStrength(ff);
+			}	
+		    }
+		}
+
+	    }
+	  if ( elementData[0][i] > Z)
+	    finished = true;	
+	}
+    }
+
+  delete StechiometricFactors;
+  
+  //NOW: sort oscillators according to increasing ionisation energy
+  //Notice: it works because helper is a vector of _object_, not a 
+  //vector to _pointers_
+  std::sort(helper->begin(),helper->end());
+  
+  // Plasma energy and conduction band excitation
+  G4double RydbergEnergy = 13.60569*eV;
+  G4double Omega = std::sqrt(4*pi*moleculeDensity*totalZ*Bohr_radius)*Bohr_radius*2.0*RydbergEnergy; 
+  G4double conductionStrength = (*helper)[0].GetOscillatorStrength();
+  G4double plasmaEnergy = Omega*std::sqrt(conductionStrength/totalZ);
+
+  plasmaSquared->insert(std::make_pair(material,Omega*Omega));
+
+  G4bool isAConductor = false;
+  G4int nullOsc = 0;
+
+  if (verbosityLevel > 1)
+    {
+      G4cout << "Estimated oscillator strenght and energy of plasmon: " << 
+	conductionStrength << " and " << plasmaEnergy/eV << " eV" << G4endl;
+    }
+
+  if (conductionStrength < 0.5 || plasmaEnergy<1.0*eV) //this is an insulator
+    {
+      //remove conduction band oscillator
+      helper->erase(helper->begin());
+    }
+  else //this is a conductor, Outer shells moved to conduction band
+    {
+      isAConductor = true;
+      //copy the conduction strenght.. The number is going to change.
+      G4double conductionStrengthCopy = conductionStrength;
+      G4bool quit = false;
+      for (size_t i = 1; i<helper->size() && !quit ;i++)
+	{
+	  G4double oscStre = (*helper)[i].GetOscillatorStrength();
+	  //loop is repeated over here
+	  if (oscStre < conductionStrength)
+	    {
+	      conductionStrengthCopy = conductionStrengthCopy-oscStre;
+	      (*helper)[i].SetOscillatorStrength(0.);
+	      nullOsc++;
+	    }
+	  else //this is passed only once - no goto - 
+	    {
+	      quit = true;
+	      (*helper)[i].SetOscillatorStrength(oscStre-conductionStrengthCopy);
+	      if (fabs((*helper)[i].GetOscillatorStrength()) < 1e-12)
+		{
+		  conductionStrength += (*helper)[i].GetOscillatorStrength(); 
+		  (*helper)[i].SetOscillatorStrength(0.);
+		  nullOsc++;
+		}
+	    }
+	}
+    
+      //Update conduction band
+      (*helper)[0].SetOscillatorStrength(conductionStrength);
+      (*helper)[0].SetIonisationEnergy(0.);
+      (*helper)[0].SetResonanceEnergy(plasmaEnergy);
+      G4double hartree = 0.75/std::sqrt(3.0*pi*pi*moleculeDensity*
+					Bohr_radius*Bohr_radius*Bohr_radius*conductionStrength);
+      (*helper)[0].SetHartreeFactor(hartree/fine_structure_const);
+    }
+  
+  //Check f-sum rule
+  G4double sum = 0;
+  for (size_t i=0;i<helper->size();i++)
+    {
+      sum += (*helper)[i].GetOscillatorStrength();
+    }
+  if (fabs(sum-totalZ) > (1e-6*totalZ))
+    {
+      G4cout << "G4PenelopeOscillatorManager - Inconsistent oscillator data " << G4endl;
+      G4cout << sum << " " << totalZ << G4endl;
+      G4Exception();
+    }
+  if (fabs(sum-totalZ) > (1e-12*totalZ))
+    {
+      G4double fact = totalZ/sum;
+      for (size_t i=0;i<helper->size();i++)
+	{
+	  G4double ff = (*helper)[i].GetOscillatorStrength()*fact;
+	  (*helper)[i].SetOscillatorStrength(ff); 
+	}
+    }
+
+   //Remove null items
+  for (G4int k=0;k<nullOsc;k++)
+    {     
+      G4bool exit=false;
+      for (size_t i=0;i<helper->size() && !exit;i++)
+	{
+	  if (fabs((*helper)[i].GetOscillatorStrength()) < 1e-12)
+	    {
+	      helper->erase(helper->begin()+i);
+	      exit = true;
+	    }
+	}
+    }
+
+
+  //Sternheimer's adjustment factor
+  G4double adjustmentFactor = 0;
+  if (helper->size() > 1)
+    {
+      G4double TST = totalZ*std::log(meanExcitationEnergy/eV);
+      G4double AALow = 0.5;
+      G4double AAHigh = 10.;
+      do
+	{
+	  adjustmentFactor = (AALow+AAHigh)*0.5;
+	  G4double sum = 0;
+	  for (size_t i=0;i<helper->size();i++)
+	    {
+	      if (i == 0 && isAConductor)	       
+		{
+		  G4double resEne = (*helper)[i].GetResonanceEnergy();
+		  sum += (*helper)[i].GetOscillatorStrength()*std::log(resEne/eV);
+		}
+	      else
+		{
+		  G4double ionEne = (*helper)[i].GetIonisationEnergy();
+		  G4double oscStre = (*helper)[i].GetOscillatorStrength();
+		  G4double WI2 = (adjustmentFactor*adjustmentFactor*ionEne*ionEne) + 
+		    2./3.*(oscStre/totalZ)*Omega*Omega;
+		  G4double resEne = std::sqrt(WI2);
+		  (*helper)[i].SetResonanceEnergy(resEne);
+		  sum +=  (*helper)[i].GetOscillatorStrength()*std::log(resEne/eV);
+		}	      
+	    }
+	  if (sum < TST)
+	    AALow = adjustmentFactor;
+	  else
+	    AAHigh = adjustmentFactor;
+	}while((AAHigh-AALow)>(1e-14*adjustmentFactor));      
+    }
+  else
+    {
+      G4double ionEne = (*helper)[0].GetIonisationEnergy();
+      (*helper)[0].SetIonisationEnergy(fabs(ionEne));
+      (*helper)[0].SetResonanceEnergy(meanExcitationEnergy);
+    }
+  if (verbosityLevel > 1)
+    {
+      G4cout << "Sternheimer's adjustment factor: " << adjustmentFactor << G4endl;
+    }
+
+  //Check again for data consistency
+  G4double xcheck = (*helper)[0].GetOscillatorStrength()*std::log((*helper)[0].GetResonanceEnergy());
+  G4double TST = (*helper)[0].GetOscillatorStrength();
+  for (size_t i=1;i<helper->size();i++)
+    {
+      xcheck += (*helper)[i].GetOscillatorStrength()*std::log((*helper)[i].GetResonanceEnergy());
+      TST += (*helper)[i].GetOscillatorStrength();
+    }
+  if (fabs(TST-totalZ)>1e-8*totalZ)
+    {
+      G4cout << "G4PenelopeOscillatorManager - Inconsistent oscillator data " << G4endl;
+      G4cout << TST << " " << totalZ << G4endl;
+      G4Exception();
+    }
+  xcheck = std::exp(xcheck/totalZ);
+  if (fabs(xcheck-meanExcitationEnergy) > 1e-8*meanExcitationEnergy)
+    {
+      G4cout << "G4PenelopeOscillatorManager - Error in Sterheimer factor calculation " << G4endl;
+      G4cout << xcheck/eV << " " << meanExcitationEnergy/eV << G4endl;
+      G4Exception();
+    }
+
+  //Selection of the lowest ionisation energy for inner shells. Only the K, L and M shells with 
+  //ionisation energy less than the N1 shell of the heaviest element in the material are considered as 
+  //inner shells. As a results, the inner/outer shell character of an atomic shell depends on the 
+  //composition of the material.
+  G4double Zmax = 0;
+  for (G4int k=0;k<nElements;k++)
+    {
+      G4double Z = (*elementVector)[k]->GetZ();
+      if (Z>Zmax) Zmax = Z;
+    }
+  //Find N1 level of the heaviest element (if any).
+  G4bool found = false;
+  G4double cutEnergy = 50*eV;
+  for (size_t i=0;i<helper->size() && !found;i++)
+    {
+      G4double Z = (*helper)[i].GetParentZ();
+      G4int shID = (*helper)[i].GetParentShellID(); //look for the N1 level
+      if (shID == 10 && Z == Zmax)
+	{
+	  found = true;
+	  if ((*helper)[i].GetIonisationEnergy() > cutEnergy)
+	    cutEnergy = (*helper)[i].GetIonisationEnergy();
+	}
+    }
+  //Make that cutEnergy cannot be higher than 250 eV, namely the fluorescence level by 
+  //Geant4
+  G4double lowEnergyLimitForFluorescence = 250*eV;
+  cutEnergy = std::min(cutEnergy,lowEnergyLimitForFluorescence);
+
+  if (verbosityLevel > 1)
+      G4cout << "Cutoff energy: " << cutEnergy/eV << " eV" << G4endl;
+  
+  //
+  //Copy helper in the oscillatorTable for Ionisation
+  //
+  //Oscillator table Ionisation for the material
+  G4PenelopeOscillatorTable* theTable = new G4PenelopeOscillatorTable(); //vector of oscillator
+  G4PenelopeOscillatorResEnergyComparator comparator;
+  std::sort(helper->begin(),helper->end(),comparator);
+
+  //COPY THE HELPER (vector of object) to theTable (vector of Pointers). 
+  for (size_t i=0;i<helper->size();i++)
+    {
+      //copy content --> one may need it later (e.g. to fill an other table, with variations)
+      G4PenelopeOscillator* theOsc = new G4PenelopeOscillator((*helper)[i]);
+      theTable->push_back(theOsc);
+    }
+
+  //Oscillators of outer shells with resonance energies differing by a factor less than
+  //Rgroup are grouped as a single oscillator  
+  G4double Rgroup = 1.05; 
+  size_t Nost = theTable->size();  
+ 
+  size_t firstIndex = (isAConductor) ? 1 : 0; //for conductors, skip conduction oscillator
+  G4bool loopAgain = false;
+  G4int removedLevels = 0;
+  do
+    {        
+      loopAgain = false;
+      if (Nost>firstIndex+1)
+	{
+	  removedLevels = 0;
+	  for (size_t i=firstIndex;i<Nost-1;i++)
+	    {
+	      G4bool skipLoop = false;
+	      G4int shellFlag = (*theTable)[i]->GetShellFlag();
+	      G4double ionEne = (*theTable)[i]->GetIonisationEnergy();
+	      G4double resEne = (*theTable)[i]->GetResonanceEnergy();
+	      G4double resEnePlus1 = (*theTable)[i+1]->GetResonanceEnergy();
+	      G4double oscStre = (*theTable)[i]->GetOscillatorStrength();
+	      G4double oscStrePlus1 = (*theTable)[i+1]->GetOscillatorStrength();
+	      //if (shellFlag < 10 && ionEne>cutEnergy) in Penelope
+	      if (ionEne>cutEnergy) //remove condition that shellFlag < 10!
+		skipLoop = true;
+	      if (resEne<1.0*eV || resEnePlus1<1.0*eV)
+		skipLoop = true;
+	      if (resEnePlus1 > Rgroup*resEne)
+		skipLoop = true;
+	      if (!skipLoop)
+		{
+		  G4double newRes = std::exp((oscStre*std::log(resEne)+
+					      oscStrePlus1*std::log(resEnePlus1))
+					     /(oscStre+oscStrePlus1));
+		  (*theTable)[i]->SetResonanceEnergy(newRes);
+		  G4double newIon = (oscStre*ionEne+
+				     oscStrePlus1*(*theTable)[i+1]->GetIonisationEnergy())/
+		    (oscStre+oscStrePlus1);
+		  (*theTable)[i]->SetIonisationEnergy(newIon);
+		  G4double newStre = oscStre+oscStrePlus1;
+		  (*theTable)[i]->SetOscillatorStrength(newStre);
+		  G4double newHartree = (oscStre*(*theTable)[i]->GetHartreeFactor()+
+					 oscStrePlus1*(*theTable)[i+1]->GetHartreeFactor())/
+		    (oscStre+oscStrePlus1);
+		  (*theTable)[i]->SetHartreeFactor(newHartree);
+		  if ((*theTable)[i]->GetParentZ() != (*theTable)[i+1]->GetParentZ())
+		    (*theTable)[i]->SetParentZ(0.);
+		  if (shellFlag < 10 || (*theTable)[i+1]->GetShellFlag() < 10)
+		    {
+		      G4int newFlag = std::min(shellFlag,(*theTable)[i+1]->GetShellFlag());
+		      (*theTable)[i]->SetShellFlag(newFlag);	    
+		    }
+		  else
+		    (*theTable)[i]->SetShellFlag(30);
+		  //We've lost anyway the track of the original level
+		  (*theTable)[i]->SetParentShellID((*theTable)[i]->GetShellFlag());
+
+		  if (i<Nost-2)
+		    {
+		      for (size_t ii=i+1;ii<Nost-1;ii++)
+			(*theTable)[ii] = (*theTable)[ii+1];		
+		    }
+		  //G4cout << theTable->size() << G4endl;
+		  //theTable->erase(theTable->end()); 
+		  theTable->erase(theTable->begin()+theTable->size()-1); //delete last element
+		  removedLevels++;
+		}		      
+	    }
+	}
+      if (removedLevels)
+	{
+	  Nost -= removedLevels;
+	  loopAgain = true;
+	}
+      if (Rgroup < 1.414213 || Nost > 64)
+	{
+	  Rgroup = Rgroup*Rgroup;
+	  loopAgain = true;
+	}
+    }while(loopAgain);
+
+  if (verbosityLevel > 1)
+    {
+      G4cout << "Final grouping factor for Ionisation: " << Rgroup << G4endl;
+    }
+
+  //Final Electron/Positron model parameters
+  for (size_t i=0;i<theTable->size();i++)
+    {
+      //Set cutoff recoil energy for the resonant mode
+      G4double ionEne = (*theTable)[i]->GetIonisationEnergy();
+      if (ionEne < 1e-3*eV)
+	{
+	  G4double resEne = (*theTable)[i]->GetResonanceEnergy();
+	  (*theTable)[i]->SetIonisationEnergy(0.*eV);
+	  (*theTable)[i]->SetCutoffRecoilResonantEnergy(resEne);
+	}
+      else
+	(*theTable)[i]->SetCutoffRecoilResonantEnergy(ionEne);	
+    }
+  
+  //Last step
+  oscillatorStoreIonisation->insert(std::make_pair(material,theTable));
+
+  
+  /*
+    SAME FOR COMPTON
+  */
+  //
+  //Copy helper in the oscillatorTable for Compton
+  //
+  //Oscillator table Ionisation for the material
+  G4PenelopeOscillatorTable* theTableC = new G4PenelopeOscillatorTable(); //vector of oscillator
+  //order by ionisation energy
+  std::sort(helper->begin(),helper->end());
+  //COPY THE HELPER (vector of object) to theTable (vector of Pointers). 
+  for (size_t i=0;i<helper->size();i++)
+    {
+      //copy content --> one may need it later (e.g. to fill an other table, with variations)
+      G4PenelopeOscillator* theOsc = new G4PenelopeOscillator((*helper)[i]);
+      theTableC->push_back(theOsc);
+    }  
+  //Oscillators of outer shells with resonance energies differing by a factor less than
+  //Rgroup are grouped as a single oscillator  
+  Rgroup = 1.5; 
+  Nost = theTableC->size();  
+  
+  firstIndex = (isAConductor) ? 1 : 0; //for conductors, skip conduction oscillator
+  loopAgain = false;
+  removedLevels = 0;
+  do
+    {        
+      loopAgain = false;
+      if (Nost>firstIndex+1)
+	{
+	  removedLevels = 0;
+	  for (size_t i=firstIndex;i<Nost-1;i++)
+	    {
+	      G4bool skipLoop = false;
+	      //G4int shellFlag = (*theTableC)[i]->GetShellFlag();
+	      G4double ionEne = (*theTableC)[i]->GetIonisationEnergy();
+	      G4double ionEnePlus1 = (*theTableC)[i+1]->GetIonisationEnergy();
+	      G4double oscStre = (*theTableC)[i]->GetOscillatorStrength();
+	      G4double oscStrePlus1 = (*theTableC)[i+1]->GetOscillatorStrength();
+	      //if (shellFlag < 10 && ionEne>cutEnergy) in Penelope
+	      if (ionEne>cutEnergy) 
+		skipLoop = true;
+	      if (ionEne<1.0*eV || ionEnePlus1<1.0*eV)
+		skipLoop = true;
+	      if (ionEnePlus1 > Rgroup*ionEne)
+		skipLoop = true;
+	      
+	      if (!skipLoop)
+		{
+		  G4double newIon = (oscStre*ionEne+
+				     oscStrePlus1*ionEnePlus1)/
+		    (oscStre+oscStrePlus1);
+		  (*theTableC)[i]->SetIonisationEnergy(newIon);
+		  G4double newStre = oscStre+oscStrePlus1;
+		  (*theTableC)[i]->SetOscillatorStrength(newStre);
+		  G4double newHartree = (oscStre*(*theTableC)[i]->GetHartreeFactor()+
+					 oscStrePlus1*(*theTableC)[i+1]->GetHartreeFactor())/
+		    (oscStre+oscStrePlus1);
+		  (*theTableC)[i]->SetHartreeFactor(newHartree);
+		  if ((*theTableC)[i]->GetParentZ() != (*theTableC)[i+1]->GetParentZ())
+		    (*theTableC)[i]->SetParentZ(0.);		  
+		  (*theTableC)[i]->SetShellFlag(30);
+		  (*theTableC)[i]->SetParentShellID((*theTableC)[i]->GetShellFlag());
+
+		  if (i<Nost-2)
+		    {
+		      for (size_t ii=i+1;ii<Nost-1;ii++)
+			(*theTableC)[ii] = (*theTableC)[ii+1];		
+		    }
+		  theTableC->erase(theTableC->begin()+theTableC->size()-1); //delete last element
+		  //theTableC->erase(theTableC->end()); //delete last element
+		  removedLevels++;
+		}		      
+	    }
+	}
+      if (removedLevels)
+	{
+	  Nost -= removedLevels;
+	  loopAgain = true;
+	}
+      if (Rgroup < 2.0 || Nost > 64)
+	{
+	  Rgroup = Rgroup*Rgroup;
+	  loopAgain = true;
+	}
+    }while(loopAgain);
+
+
+   if (verbosityLevel > 1)
+    {
+      G4cout << "Final grouping factor for Compton: " << Rgroup << G4endl;
+    }
+
+    //Last step
+   oscillatorStoreCompton->insert(std::make_pair(material,theTableC));
+  
+  /* //TESTING PURPOSES
+  if (verbosityLevel > 1)
+    {
+      G4cout << "The table contains " << helper->size() << " oscillators " << G4endl;      
+      for (size_t k=0;k<helper->size();k++)
+	{
+	  G4cout << "Oscillator # " << k << G4endl;
+	  G4cout << "Z = " << (*helper)[k].GetParentZ() << G4endl;
+	  G4cout << "Shell Flag = " << (*helper)[k].GetShellFlag() << G4endl;
+	  G4cout << "Compton index = " << (*helper)[k].GetHartreeFactor() << G4endl;
+	  G4cout << "Ionisation energy = " << (*helper)[k].GetIonisationEnergy()/eV << " eV" << G4endl;
+	  G4cout << "Occupation number = " << (*helper)[k].GetOscillatorStrength() << G4endl;
+	  G4cout << "Resonance energy = " << (*helper)[k].GetResonanceEnergy()/eV << " eV" << G4endl;
+	}
+      
+      for (size_t k=0;k<helper->size();k++)
+	{
+	  G4cout << k << " " << (*helper)[k].GetOscillatorStrength() << " " << 
+	    (*helper)[k].GetIonisationEnergy()/eV << " " << (*helper)[k].GetResonanceEnergy()/eV << " " << 
+	    (*helper)[k].GetParentZ() << " " << (*helper)[k].GetShellFlag() << " " << 
+	    (*helper)[k].GetHartreeFactor() << G4endl;	    
+	}
+    } 
+  */
+ 
+
+  //CLEAN UP theHelper and its content 
+  delete helper;
+  if (verbosityLevel > 1)
+    Dump(material);
+
+  return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+
+void G4PenelopeOscillatorManager::ReadElementData()
+{
+  if (verbosityLevel > 0)
+    {
+      G4cout << "G4PenelopeOscillatorManager::ReadElementData()" << G4endl;
+      G4cout << "Going to read Element Data" << G4endl;
+    }
+  char* path = getenv("G4LEDATA");
+  if (!path)
+    {
+      G4String excep = "G4PenelopeOscillatorManager - G4LEDATA environment variable not set!";
+      G4Exception(excep);
+    }
+  G4String pathString(path);
+  G4String pathFile = pathString + "/penelope/pdatconf.p08";
+  std::ifstream file(pathFile);
+
+  if (!file.is_open())
+    {
+      G4String excep = "G4PenelopeOscillatorManager - data file " + pathFile + " not found!";
+      G4Exception(excep);
+    }
+  //Read header (22 lines)
+  G4String theHeader;
+  for (G4int iline=0;iline<22;iline++)
+    getline(file,theHeader);
+  //Done
+  G4int Z=0;
+  G4int shellCode = 0;
+  G4String shellId = "NULL";
+  G4int occupationNumber = 0;
+  G4double ionisationEnergy = 0.0*eV;
+  G4double hartreeProfile = 0.;
+  //Start reading data
+  for (G4int i=0;!file.eof();i++)
+    {
+      file >> Z >> shellCode >> shellId >> occupationNumber >> ionisationEnergy >> hartreeProfile;
+      if (Z>0 && i<2000)
+	{
+	  elementData[0][i] = Z;
+	  elementData[1][i] = shellCode;
+	  elementData[2][i] = occupationNumber;
+	  elementData[3][i] = ionisationEnergy*eV;
+	  elementData[4][i] = hartreeProfile;
+	}
+    }
+  file.close();
+  
+  if (verbosityLevel > 1)
+    {
+      G4cout << "G4PenelopeOscillatorManager::ReadElementData(): Data file read" << G4endl;
+    }
+  fReadElementData = true;
+  return;
+
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+G4double G4PenelopeOscillatorManager::GetMeanExcitationEnergy(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStores and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (excitationEnergy->count(mat))
+    return excitationEnergy->find(mat)->second;
+    
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (excitationEnergy->count(mat))
+    return excitationEnergy->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetMolecularExcitationEnergy() " << G4endl;
+      G4cout << "Impossible to retrieve the excitation energy for  " << mat->GetName() << G4endl;      
+      return 0;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+G4double G4PenelopeOscillatorManager::GetPlasmaEnergySquared(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStores and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (plasmaSquared->count(mat))
+    return plasmaSquared->find(mat)->second;
+    
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (plasmaSquared->count(mat))
+    return plasmaSquared->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetPlasmaEnergySquared() " << G4endl;
+      G4cout << "Impossible to retrieve the plasma energy for  " << mat->GetName() << G4endl;      
+      return 0;
+    }
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
+G4double G4PenelopeOscillatorManager::GetAtomsPerMolecule(const G4Material* mat)
+{
+  // (1) First time, create oscillatorStores and read data
+  CheckForTablesCreated();
+
+  // (2) Check if the material has been already included
+  if (atomsPerMolecule->count(mat))
+    return atomsPerMolecule->find(mat)->second;
+    
+  // (3) If we are here, it means that we have to create the table for the material
+  BuildOscillatorTable(mat);
+
+  // (4) now, the oscillator store should be ok
+  if (atomsPerMolecule->count(mat))
+    return atomsPerMolecule->find(mat)->second;
+  else
+    {
+      G4cout << "G4PenelopeOscillatorManager::GetAtomsPerMolecule() " << G4endl;
+      G4cout << "Impossible to retrieve the number of atoms per molecule for  " 
+	     << mat->GetName() << G4endl;      
+      return 0;
+    }
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeSamplingData.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeSamplingData.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeSamplingData.cc	(revision 1316)
@@ -0,0 +1,205 @@
+//
+// ********************************************************************
+// * 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: G4PenelopeSamplingData.cc,v 1.1 2010/03/17 14:18:50 pandola Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Luciano Pandola
+//
+// History:
+// --------
+// 09 Dec 2009   L Pandola    First implementation
+//
+#include "G4PenelopeSamplingData.hh"
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
+G4PenelopeSamplingData::G4PenelopeSamplingData(G4int nPoints) : 
+  np(nPoints)
+{
+  //create vectors
+  x = new G4DataVector();
+  pac = new G4DataVector();
+  a = new G4DataVector();
+  b = new G4DataVector();
+  ITTL = new std::vector<size_t>;
+  ITTU = new std::vector<size_t>;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
+G4PenelopeSamplingData::~G4PenelopeSamplingData()
+{
+  if (x) delete x;
+  if (pac) delete pac;
+  if (a) delete a;
+  if (b) delete b;
+  if (ITTL) delete ITTL;
+  if (ITTU) delete ITTU;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
+size_t G4PenelopeSamplingData::GetNumberOfStoredPoints()
+{
+  size_t points = x->size();
+
+  //check everything is all right
+  if (pac->size() != points || a->size() != points || 
+      b->size() != points || ITTL->size() != points ||
+      ITTU->size() != points)
+    {
+      G4cout << "G4PenelopeSamplingData::GetNumberOfStoredPoints()" << G4endl;
+      G4cout << "Data vectors look to have different dimensions !" << G4endl;
+      G4Exception();      
+    }
+  return points;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
+void G4PenelopeSamplingData::Clear()
+{
+  if (x) delete x;
+  if (pac) delete pac;
+  if (a) delete a;
+  if (b) delete b;
+  if (ITTL) delete ITTL;
+  if (ITTU) delete ITTU;
+  //create vectors
+  x = new G4DataVector();
+  pac = new G4DataVector();
+  a = new G4DataVector();
+  b = new G4DataVector();
+  ITTL = new std::vector<size_t>;
+  ITTU = new std::vector<size_t>;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
+void G4PenelopeSamplingData::AddPoint(G4double x0,G4double pac0,G4double a0,G4double b0,
+					size_t ITTL0,size_t ITTU0)
+{
+  x->push_back(x0);
+  pac->push_back(pac0);
+  a->push_back(a0);
+  b->push_back(b0);
+  ITTL->push_back(ITTL0);
+  ITTU->push_back(ITTU0);
+
+  //check how many points we do have now
+  size_t nOfPoints = GetNumberOfStoredPoints();
+
+  if (nOfPoints > ((size_t)np))
+    {
+      G4cout << "G4PenelopeSamplingData::AddPoint() " << G4endl;
+      G4cout << "WARNING: Up to now there are " << nOfPoints << " points in the table" << G4endl;
+      G4cout << "while the anticipated (declared) number is " << np << G4endl;
+    }
+    return;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
+void G4PenelopeSamplingData::DumpTable()
+{
+  
+  G4cout << "*************************************************************************" << G4endl;
+  G4cout << GetNumberOfStoredPoints() << " points" << G4endl;
+  G4cout << "*************************************************************************" << G4endl;
+  for (size_t i=0;i<GetNumberOfStoredPoints();i++)
+    {
+      G4cout << i << " " << (*x)[i] << " " << (*pac)[i] << " " << (*a)[i] << " " << 
+	(*b)[i] << " " << (*ITTL)[i] << " " << (*ITTU)[i] << G4endl;
+    }
+  G4cout << "*************************************************************************" << G4endl;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
+G4double G4PenelopeSamplingData::GetX(size_t index)
+{
+  if (index < x->size())
+    return (*x)[index];
+  else
+    return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
+G4double G4PenelopeSamplingData::GetPAC(size_t index)
+{
+  if (index < pac->size())
+    return (*pac)[index];
+  else
+    return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
+G4double G4PenelopeSamplingData::GetA(size_t index)
+{
+  if (index < a->size())
+    return (*a)[index];
+  else
+    return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
+G4double G4PenelopeSamplingData::GetB(size_t index)
+{
+  if (index < b->size())
+    return (*b)[index];
+  else
+    return 0;
+}
+
+//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
+G4double G4PenelopeSamplingData::SampleValue(G4double maxRand)
+{
+  //One passes here a random number in (0,1).
+  //Notice: it possible that is between (0,b) with b<1
+  size_t points = GetNumberOfStoredPoints();
+ 
+  size_t itn = (size_t) (maxRand*(points-1)); 
+  size_t i = (*ITTL)[itn];
+  size_t j = (*ITTU)[itn];
+
+  while ((j-i) > 1)
+    {
+      size_t k = (i+j)/2;
+      if (maxRand > (*pac)[k])
+	i = k;
+      else
+	j = k;
+    }
+
+  //Sampling from the rational inverse cumulative distribution
+  G4double result = 0;
+
+  G4double rr = maxRand - (*pac)[i];
+  if (rr > 1e-16)
+    {
+      G4double d = (*pac)[i+1]-(*pac)[i];
+      result = (*x)[i]+
+	((1.0+(*a)[i]+(*b)[i])*d*rr/
+	 (d*d+((*a)[i]*d+(*b)[i]*rr)*rr))*((*x)[i+1]-(*x)[i]);      
+    }
+  else
+    result = (*x)[i]; 
+  
+  return result;
+}
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4VecpssrKModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4VecpssrKModel.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4VecpssrKModel.cc	(revision 1316)
@@ -0,0 +1,63 @@
+//
+// ********************************************************************
+// * 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: G4VecpssrKModel.cc,v 1.2 2010/06/06 23:52:28 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Haifa Ben Abdelouahed
+//         
+//
+// History:
+// -----------
+//  01 Sep 2009   ALF created
+//
+// -------------------------------------------------------------------
+// Class description:
+// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
+// Further documentation available from http://www.ge.infn.it/geant4/lowE
+// -------------------------------------------------------------------
+
+
+
+#include "G4VecpssrKModel.hh"
+
+
+G4VecpssrKModel::G4VecpssrKModel()
+{ 
+
+}
+
+G4VecpssrKModel::~G4VecpssrKModel()
+{ 
+
+}
+
+/* 
+G4double G4VecpssrKModel::CalculateCrossSection(G4int,G4double,G4double)
+{ 
+
+}
+*/
+
Index: trunk/source/processes/electromagnetic/lowenergy/src/G4VecpssrLiModel.cc
===================================================================
--- trunk/source/processes/electromagnetic/lowenergy/src/G4VecpssrLiModel.cc	(revision 1316)
+++ trunk/source/processes/electromagnetic/lowenergy/src/G4VecpssrLiModel.cc	(revision 1316)
@@ -0,0 +1,75 @@
+//
+// ********************************************************************
+// * 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: G4VecpssrLiModel.cc,v 1.2 2010/06/06 23:52:28 mantero Exp $
+// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
+//
+// Author: Haifa Ben Abdelouahed
+//         
+//
+// History:
+// -----------
+//  01 Sep 2009   ALF created
+//
+// -------------------------------------------------------------------
+// Class description:
+// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
+// Further documentation available from http://www.ge.infn.it/geant4/lowE
+// -------------------------------------------------------------------
+
+
+
+#include "G4VecpssrLiModel.hh"
+
+
+G4VecpssrLiModel::G4VecpssrLiModel()
+{ 
+
+}
+
+G4VecpssrLiModel::~G4VecpssrLiModel()
+{ 
+
+}
+
+ 
+/*G4double G4VecpssrLiModel::CalculateL1CrossSection(G4int ,G4double , G4double )
+{ 
+
+}
+
+G4double G4VecpssrLiModel::CalculateL2CrossSection(G4int ,G4double , G4double )
+ 
+{
+  
+}
+
+
+G4double G4VecpssrLiModel::CalculateL3CrossSection(G4int ,G4double , G4double )
+ 
+{ 
+  
+}
+*/
