Geant4 Cross Reference

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

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

Diff markup

Differences between /processes/electromagnetic/lowenergy/src/G4PenelopeRayleighModel.cc (Version 11.3.0) and /processes/electromagnetic/lowenergy/src/G4PenelopeRayleighModel.cc (Version 10.1.p2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
                                                   >>  26 // $Id: G4PenelopeRayleighModel.cc 83584 2014-09-02 08:45:37Z gcosmo $
 26 //                                                 27 //
 27 // Author: Luciano Pandola                         28 // Author: Luciano Pandola
 28 //                                                 29 //
 29 // History:                                        30 // History:
 30 // --------                                        31 // --------
 31 // 03 Dec 2009   L Pandola    First implementa     32 // 03 Dec 2009   L Pandola    First implementation
 32 // 25 May 2011   L.Pandola    Renamed (make v2     33 // 25 May 2011   L.Pandola    Renamed (make v2008 as default Penelope)
 33 // 19 Sep 2013   L.Pandola    Migration to MT      34 // 19 Sep 2013   L.Pandola    Migration to MT
 34 //                                                 35 //
 35                                                    36 
 36 #include "G4PenelopeRayleighModel.hh"              37 #include "G4PenelopeRayleighModel.hh"
 37 #include "G4PhysicalConstants.hh"                  38 #include "G4PhysicalConstants.hh"
 38 #include "G4SystemOfUnits.hh"                      39 #include "G4SystemOfUnits.hh"
 39 #include "G4PenelopeSamplingData.hh"               40 #include "G4PenelopeSamplingData.hh"
 40 #include "G4ParticleDefinition.hh"                 41 #include "G4ParticleDefinition.hh"
 41 #include "G4MaterialCutsCouple.hh"                 42 #include "G4MaterialCutsCouple.hh"
 42 #include "G4ProductionCutsTable.hh"                43 #include "G4ProductionCutsTable.hh"
 43 #include "G4DynamicParticle.hh"                    44 #include "G4DynamicParticle.hh"
 44 #include "G4PhysicsTable.hh"                       45 #include "G4PhysicsTable.hh"
 45 #include "G4ElementTable.hh"                       46 #include "G4ElementTable.hh"
 46 #include "G4Element.hh"                            47 #include "G4Element.hh"
 47 #include "G4PhysicsFreeVector.hh"                  48 #include "G4PhysicsFreeVector.hh"
 48 #include "G4AutoLock.hh"                           49 #include "G4AutoLock.hh"
 49 #include "G4Exp.hh"                            << 
 50                                                    50 
 51 //....oooOO0OOooo........oooOO0OOooo........oo << 
 52                                                << 
 53 const G4int G4PenelopeRayleighModel::fMaxZ;    << 
 54 G4PhysicsFreeVector* G4PenelopeRayleighModel:: << 
 55 G4PhysicsFreeVector* G4PenelopeRayleighModel:: << 
 56                                                    51 
 57 //....oooOO0OOooo........oooOO0OOooo........oo     52 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 58                                                    53 
 59 G4PenelopeRayleighModel::G4PenelopeRayleighMod     54 G4PenelopeRayleighModel::G4PenelopeRayleighModel(const G4ParticleDefinition* part,
 60              const G4String& nam)                  55              const G4String& nam)
 61   :G4VEmModel(nam),fParticleChange(nullptr),fP <<  56   :G4VEmModel(nam),fParticleChange(0),fParticle(0),isInitialised(false),
 62    fLogFormFactorTable(nullptr),fPMaxTable(nul <<  57    logAtomicCrossSection(0),atomicFormFactor(0),logFormFactorTable(0),
 63    fIsInitialised(false),fLocalTable(false)    <<  58    pMaxTable(0),samplingTable(0),fLocalTable(false)
 64 {                                                  59 {
 65   fIntrinsicLowEnergyLimit = 100.0*eV;             60   fIntrinsicLowEnergyLimit = 100.0*eV;
 66   fIntrinsicHighEnergyLimit = 100.0*GeV;           61   fIntrinsicHighEnergyLimit = 100.0*GeV;
 67   //  SetLowEnergyLimit(fIntrinsicLowEnergyLim     62   //  SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
 68   SetHighEnergyLimit(fIntrinsicHighEnergyLimit     63   SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
 69                                                    64 
 70   if (part)                                        65   if (part)
 71     SetParticle(part);                             66     SetParticle(part);
 72                                                    67 
 73   //                                               68   //
 74   fVerboseLevel= 0;                            <<  69   verboseLevel= 0;
 75   // Verbosity scale:                              70   // Verbosity scale:
 76   // 0 = nothing                               <<  71   // 0 = nothing 
 77   // 1 = warning for energy non-conservation   <<  72   // 1 = warning for energy non-conservation 
 78   // 2 = details of energy budget                  73   // 2 = details of energy budget
 79   // 3 = calculation of cross sections, file o     74   // 3 = calculation of cross sections, file openings, sampling of atoms
 80   // 4 = entering in methods                   <<  75   // 4 = entering in methods 
 81                                                    76 
 82   //build the energy grid. It is the same for      77   //build the energy grid. It is the same for all materials
 83   G4double logenergy = G4Log(fIntrinsicLowEner <<  78   G4double logenergy = std::log(fIntrinsicLowEnergyLimit/2.);
 84   G4double logmaxenergy = G4Log(1.5*fIntrinsic <<  79   G4double logmaxenergy = std::log(1.5*fIntrinsicHighEnergyLimit);
 85   //finer grid below 160 keV                       80   //finer grid below 160 keV
 86   G4double logtransitionenergy = G4Log(160*keV <<  81   G4double logtransitionenergy = std::log(160*keV); 
 87   G4double logfactor1 = G4Log(10.)/250.;       <<  82   G4double logfactor1 = std::log(10.)/250.;
 88   G4double logfactor2 = logfactor1*10;             83   G4double logfactor2 = logfactor1*10;
 89   fLogEnergyGridPMax.push_back(logenergy);     <<  84   logEnergyGridPMax.push_back(logenergy);
 90   do{                                              85   do{
 91     if (logenergy < logtransitionenergy)           86     if (logenergy < logtransitionenergy)
 92       logenergy += logfactor1;                     87       logenergy += logfactor1;
 93     else                                           88     else
 94       logenergy += logfactor2;                     89       logenergy += logfactor2;
 95     fLogEnergyGridPMax.push_back(logenergy);   <<  90     logEnergyGridPMax.push_back(logenergy);      
 96   }while (logenergy < logmaxenergy);               91   }while (logenergy < logmaxenergy);
 97 }                                                  92 }
 98                                                    93 
 99 //....oooOO0OOooo........oooOO0OOooo........oo     94 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
100                                                    95 
101 G4PenelopeRayleighModel::~G4PenelopeRayleighMo     96 G4PenelopeRayleighModel::~G4PenelopeRayleighModel()
102 {                                                  97 {
103   if (IsMaster() || fLocalTable)                   98   if (IsMaster() || fLocalTable)
104     {                                              99     {
105                                                << 100       std::map <G4int,G4PhysicsFreeVector*>::iterator i;
106       for(G4int i=0; i<=fMaxZ; ++i)            << 101       if (logAtomicCrossSection)
107   {                                               102   {
108     if(fLogAtomicCrossSection[i])              << 103     for (i=logAtomicCrossSection->begin();i != logAtomicCrossSection->end();i++)
109       {                                        << 104       if (i->second) delete i->second;
110         delete fLogAtomicCrossSection[i];      << 105     
111         fLogAtomicCrossSection[i] = nullptr;   << 106     delete logAtomicCrossSection;
112       }                                        << 107     logAtomicCrossSection = 0;
113     if(fAtomicFormFactor[i])                   << 108   }    
114       {                                        << 109       if (atomicFormFactor)
115         delete fAtomicFormFactor[i];           << 110   {   
116         fAtomicFormFactor[i] = nullptr;        << 111     for (i=atomicFormFactor->begin();i != atomicFormFactor->end();i++)
117       }                                        << 112       if (i->second) delete i->second;    
                                                   >> 113     delete atomicFormFactor;
                                                   >> 114     atomicFormFactor = 0;
118   }                                               115   }
                                                   >> 116   
119       ClearTables();                              117       ClearTables();
120     }                                             118     }
121 }                                                 119 }
122                                                   120 
123 //....oooOO0OOooo........oooOO0OOooo........oo    121 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
124 void G4PenelopeRayleighModel::ClearTables()       122 void G4PenelopeRayleighModel::ClearTables()
125 {                                                 123 {
126    if (fLogFormFactorTable)                    << 124   /*
127      {                                         << 125   if (!IsMaster())    
128        for (auto& item : (*fLogFormFactorTable << 126     //Should not be here!
129    if (item.second) delete item.second;        << 127     G4Exception("G4PenelopeRayleighModel::ClearTables()",
130        delete fLogFormFactorTable;             << 128     "em0100",FatalException,"Worker thread in this method");    
131        fLogFormFactorTable = nullptr; //zero e << 129   */
                                                   >> 130 
                                                   >> 131   std::map <const G4Material*,G4PhysicsFreeVector*>::iterator i;  
                                                   >> 132 
                                                   >> 133    if (logFormFactorTable)
                                                   >> 134      {       
                                                   >> 135        for (i=logFormFactorTable->begin(); i != logFormFactorTable->end(); i++)
                                                   >> 136    if (i->second) delete i->second;       
                                                   >> 137        delete logFormFactorTable;
                                                   >> 138        logFormFactorTable = 0; //zero explicitely
132      }                                            139      }
133    if (fPMaxTable)                             << 140 
134      {                                         << 141    if (pMaxTable)
135        for (auto& item : (*fPMaxTable))        << 142      {       
136    if (item.second) delete item.second;        << 143        for (i=pMaxTable->begin(); i != pMaxTable->end(); i++)
137        delete fPMaxTable;                      << 144    if (i->second) delete i->second;       
138        fPMaxTable = nullptr; //zero explicitly << 145        delete pMaxTable;
                                                   >> 146        pMaxTable = 0; //zero explicitely
139      }                                            147      }
140    if (fSamplingTable)                         << 148 
                                                   >> 149    std::map<const G4Material*,G4PenelopeSamplingData*>::iterator ii;
                                                   >> 150    if (samplingTable)
141      {                                            151      {
142        for (auto& item : (*fSamplingTable))    << 152        for (ii=samplingTable->begin(); ii != samplingTable->end(); ii++)
143    if (item.second) delete item.second;        << 153    if (ii->second) delete ii->second;
144        delete fSamplingTable;                  << 154        delete samplingTable;
145        fSamplingTable = nullptr; //zero explic << 155        samplingTable = 0; //zero explicitely
146      }                                         << 156      }     
                                                   >> 157 
147    return;                                        158    return;
148 }                                                 159 }
149                                                   160 
150 //....oooOO0OOooo........oooOO0OOooo........oo    161 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
151                                                   162 
152 void G4PenelopeRayleighModel::Initialise(const    163 void G4PenelopeRayleighModel::Initialise(const G4ParticleDefinition* part,
153            const G4DataVector& )                  164            const G4DataVector& )
154 {                                                 165 {
155   if (fVerboseLevel > 3)                       << 166   if (verboseLevel > 3)
156     G4cout << "Calling G4PenelopeRayleighModel    167     G4cout << "Calling G4PenelopeRayleighModel::Initialise()" << G4endl;
157                                                   168 
158   SetParticle(part);                              169   SetParticle(part);
159                                                   170 
160   //Only the master model creates/fills/destro    171   //Only the master model creates/fills/destroys the tables
161   if (IsMaster() && part == fParticle)         << 172   if (IsMaster() && part == fParticle) 
162     {                                             173     {
163       //clear tables depending on materials, n    174       //clear tables depending on materials, not the atomic ones
164       ClearTables();                              175       ClearTables();
165                                                   176 
166       if (fVerboseLevel > 3)                   << 177       if (verboseLevel > 3)
167   G4cout << "Calling G4PenelopeRayleighModel::    178   G4cout << "Calling G4PenelopeRayleighModel::Initialise() [master]" << G4endl;
                                                   >> 179   
                                                   >> 180       //create new tables
                                                   >> 181       //
                                                   >> 182       // logAtomicCrossSection and atomicFormFactor are created only once,
                                                   >> 183       // since they are never cleared
                                                   >> 184       if (!logAtomicCrossSection)
                                                   >> 185   logAtomicCrossSection = new std::map<G4int,G4PhysicsFreeVector*>;
                                                   >> 186       if (!atomicFormFactor)
                                                   >> 187   atomicFormFactor = new std::map<G4int,G4PhysicsFreeVector*>;
                                                   >> 188       
                                                   >> 189       if (!logFormFactorTable)
                                                   >> 190   logFormFactorTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
                                                   >> 191       if (!pMaxTable)
                                                   >> 192   pMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
                                                   >> 193       if (!samplingTable)
                                                   >> 194   samplingTable = new std::map<const G4Material*,G4PenelopeSamplingData*>;
168                                                   195 
169       //create new tables                      << 
170       if (!fLogFormFactorTable)                << 
171   fLogFormFactorTable = new std::map<const G4M << 
172       if (!fPMaxTable)                         << 
173   fPMaxTable = new std::map<const G4Material*, << 
174       if (!fSamplingTable)                     << 
175   fSamplingTable = new std::map<const G4Materi << 
176                                                   196 
177       G4ProductionCutsTable* theCoupleTable =  << 197       G4ProductionCutsTable* theCoupleTable = 
178   G4ProductionCutsTable::GetProductionCutsTabl    198   G4ProductionCutsTable::GetProductionCutsTable();
179                                                << 199       
180       for (G4int i=0;i<(G4int)theCoupleTable-> << 200       for (size_t i=0;i<theCoupleTable->GetTableSize();i++)
181   {                                               201   {
182     const G4Material* material =               << 202     const G4Material* material = 
183       theCoupleTable->GetMaterialCutsCouple(i)    203       theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
184     const G4ElementVector* theElementVector =     204     const G4ElementVector* theElementVector = material->GetElementVector();
185                                                << 205     
186     for (std::size_t j=0;j<material->GetNumber << 206     for (size_t j=0;j<material->GetNumberOfElements();j++)
187       {                                           207       {
188         G4int iZ = theElementVector->at(j)->Ge << 208         G4int iZ = (G4int) theElementVector->at(j)->GetZ();
189         //read data files only in the master      209         //read data files only in the master
190         if (!fLogAtomicCrossSection[iZ])       << 210         if (!logAtomicCrossSection->count(iZ))
191     ReadDataFile(iZ);                          << 211     ReadDataFile(iZ);       
192       }                                           212       }
193                                                   213 
194     //1) If the table has not been built for t    214     //1) If the table has not been built for the material, do it!
195     if (!fLogFormFactorTable->count(material)) << 215     if (!logFormFactorTable->count(material))
196       BuildFormFactorTable(material);             216       BuildFormFactorTable(material);
197                                                   217 
198     //2) retrieve or build the sampling table     218     //2) retrieve or build the sampling table
199     if (!(fSamplingTable->count(material)))    << 219     if (!(samplingTable->count(material)))
200       InitializeSamplingAlgorithm(material);      220       InitializeSamplingAlgorithm(material);
201                                                   221 
202     //3) retrieve or build the pMax data          222     //3) retrieve or build the pMax data
203     if (!fPMaxTable->count(material))          << 223     if (!pMaxTable->count(material))
204       GetPMaxTable(material);                  << 224       GetPMaxTable(material);   
205   }                                            << 
206                                                   225 
207       if (fVerboseLevel > 1) {                 << 226   }
                                                   >> 227   
                                                   >> 228       if (verboseLevel > 1) {
208   G4cout << "Penelope Rayleigh model v2008 is     229   G4cout << "Penelope Rayleigh model v2008 is initialized " << G4endl
209          << "Energy range: "                      230          << "Energy range: "
210          << LowEnergyLimit() / keV << " keV -     231          << LowEnergyLimit() / keV << " keV - "
211          << HighEnergyLimit() / GeV << " GeV"     232          << HighEnergyLimit() / GeV << " GeV"
212          << G4endl;                               233          << G4endl;
213       }                                           234       }
214     }                                             235     }
215                                                   236 
216   if(fIsInitialised) return;                   << 237   if(isInitialised) return;
217   fParticleChange = GetParticleChangeForGamma(    238   fParticleChange = GetParticleChangeForGamma();
218   fIsInitialised = true;                       << 239   isInitialised = true;
219 }                                                 240 }
220                                                   241 
221 //....oooOO0OOooo........oooOO0OOooo........oo    242 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
222                                                   243 
223 void G4PenelopeRayleighModel::InitialiseLocal(    244 void G4PenelopeRayleighModel::InitialiseLocal(const G4ParticleDefinition* part,
224                  G4VEmModel *masterModel)         245                  G4VEmModel *masterModel)
225 {                                                 246 {
226   if (fVerboseLevel > 3)                       << 247   if (verboseLevel > 3)
227     G4cout << "Calling  G4PenelopeRayleighMode    248     G4cout << "Calling  G4PenelopeRayleighModel::InitialiseLocal()" << G4endl;
                                                   >> 249  
228   //                                              250   //
229   //Check that particle matches: one might hav << 251   //Check that particle matches: one might have multiple master models (e.g. 
230   //for e+ and e-).                               252   //for e+ and e-).
231   //                                              253   //
232   if (part == fParticle)                          254   if (part == fParticle)
233     {                                             255     {
234       //Get the const table pointers from the     256       //Get the const table pointers from the master to the workers
235       const G4PenelopeRayleighModel* theModel  << 257       const G4PenelopeRayleighModel* theModel = 
236   static_cast<G4PenelopeRayleighModel*> (maste    258   static_cast<G4PenelopeRayleighModel*> (masterModel);
237                                                << 259       
238       //Copy pointers to the data tables          260       //Copy pointers to the data tables
239       for(G4int i=0; i<=fMaxZ; ++i)            << 261       logAtomicCrossSection = theModel->logAtomicCrossSection;
240   {                                            << 262       atomicFormFactor = theModel->atomicFormFactor;
241     fLogAtomicCrossSection[i] = theModel->fLog << 263       logFormFactorTable = theModel->logFormFactorTable;
242     fAtomicFormFactor[i] = theModel->fAtomicFo << 264       pMaxTable = theModel->pMaxTable;
243   }                                            << 265       samplingTable = theModel->samplingTable;
244       fLogFormFactorTable = theModel->fLogForm << 266       
245       fPMaxTable = theModel->fPMaxTable;       << 
246       fSamplingTable = theModel->fSamplingTabl << 
247                                                << 
248       //copy the G4DataVector with the grid       267       //copy the G4DataVector with the grid
249       fLogQSquareGrid = theModel->fLogQSquareG << 268       logQSquareGrid = theModel->logQSquareGrid;
250                                                << 269       
251       //Same verbosity for all workers, as the    270       //Same verbosity for all workers, as the master
252       fVerboseLevel = theModel->fVerboseLevel; << 271       verboseLevel = theModel->verboseLevel;
253     }                                             272     }
254                                                   273 
255   return;                                         274   return;
256 }                                                 275 }
257                                                   276 
258                                                   277 
259 //....oooOO0OOooo........oooOO0OOooo........oo    278 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
260 namespace { G4Mutex  PenelopeRayleighModelMute    279 namespace { G4Mutex  PenelopeRayleighModelMutex = G4MUTEX_INITIALIZER; }
261 G4double G4PenelopeRayleighModel::ComputeCross    280 G4double G4PenelopeRayleighModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
262                    G4double energy,               281                    G4double energy,
263                    G4double Z,                    282                    G4double Z,
264                    G4double,                      283                    G4double,
265                    G4double,                      284                    G4double,
266                    G4double)                      285                    G4double)
267 {                                                 286 {
268   // Cross section of Rayleigh scattering in P << 287   // Cross section of Rayleigh scattering in Penelope v2008 is calculated by the EPDL97 
269   // tabulation, Cuellen et al. (1997), with n << 288   // tabulation, Cuellen et al. (1997), with non-relativistic form factors from Hubbel 
270   // et al. J. Phys. Chem. Ref. Data 4 (1975)     289   // et al. J. Phys. Chem. Ref. Data 4 (1975) 471; Erratum ibid. 6 (1977) 615.
271                                                   290 
272    if (fVerboseLevel > 3)                      << 291    if (verboseLevel > 3)
273     G4cout << "Calling CrossSectionPerAtom() o    292     G4cout << "Calling CrossSectionPerAtom() of G4PenelopeRayleighModel" << G4endl;
274                                                << 293  
275    G4int iZ = G4int(Z);                        << 294    G4int iZ = (G4int) Z;
276                                                << 295    
277    if (!fLogAtomicCrossSection[iZ])            << 296    //Either Initialize() was not called, or we are in a slave and InitializeLocal() was 
                                                   >> 297    //not invoked
                                                   >> 298    if (!logAtomicCrossSection)
                                                   >> 299      {
                                                   >> 300        //create a **thread-local** version of the table. Used only for G4EmCalculator and 
                                                   >> 301        //Unit Tests
                                                   >> 302        fLocalTable = true;
                                                   >> 303        logAtomicCrossSection = new std::map<G4int,G4PhysicsFreeVector*>;
                                                   >> 304      }
                                                   >> 305    //now it should be ok
                                                   >> 306    if (!logAtomicCrossSection->count(iZ))
278      {                                            307      {
279        //If we are here, it means that Initial << 308        //If we are here, it means that Initialize() was inkoved, but the MaterialTable was 
280        //not filled up. This can happen in a U    309        //not filled up. This can happen in a UnitTest or via G4EmCalculator
281        if (fVerboseLevel > 0)                  << 310        if (verboseLevel > 0)
282   {                                               311   {
283     //Issue a G4Exception (warning) only in ve    312     //Issue a G4Exception (warning) only in verbose mode
284     G4ExceptionDescription ed;                    313     G4ExceptionDescription ed;
285     ed << "Unable to retrieve the cross sectio    314     ed << "Unable to retrieve the cross section table for Z=" << iZ << G4endl;
286     ed << "This can happen only in Unit Tests     315     ed << "This can happen only in Unit Tests or via G4EmCalculator" << G4endl;
287     G4Exception("G4PenelopeRayleighModel::Comp    316     G4Exception("G4PenelopeRayleighModel::ComputeCrossSectionPerAtom()",
288           "em2040",JustWarning,ed);               317           "em2040",JustWarning,ed);
289   }                                               318   }
290        //protect file reading via autolock        319        //protect file reading via autolock
291        G4AutoLock lock(&PenelopeRayleighModelM    320        G4AutoLock lock(&PenelopeRayleighModelMutex);
292        ReadDataFile(iZ);                          321        ReadDataFile(iZ);
293        lock.unlock();                          << 322        lock.unlock();       
294      }                                            323      }
295                                                   324 
296    G4double cross = 0;                            325    G4double cross = 0;
297    G4PhysicsFreeVector* atom = fLogAtomicCross << 326 
                                                   >> 327    G4PhysicsFreeVector* atom = logAtomicCrossSection->find(iZ)->second;
298    if (!atom)                                     328    if (!atom)
299      {                                            329      {
300        G4ExceptionDescription ed;                 330        G4ExceptionDescription ed;
301        ed << "Unable to find Z=" << iZ << " in    331        ed << "Unable to find Z=" << iZ << " in the atomic cross section table" << G4endl;
302        G4Exception("G4PenelopeRayleighModel::C    332        G4Exception("G4PenelopeRayleighModel::ComputeCrossSectionPerAtom()",
303        "em2041",FatalException,ed);               333        "em2041",FatalException,ed);
304        return 0;                                  334        return 0;
305      }                                            335      }
306    G4double logene = G4Log(energy);            << 336    G4double logene = std::log(energy);
307    G4double logXS = atom->Value(logene);          337    G4double logXS = atom->Value(logene);
308    cross = G4Exp(logXS);                       << 338    cross = std::exp(logXS);
309                                                   339 
310    if (fVerboseLevel > 2)                      << 340    if (verboseLevel > 2)
311      {                                         << 341     G4cout << "Rayleigh cross section at " << energy/keV << " keV for Z=" << Z << 
312        G4cout << "Rayleigh cross section at "  << 342       " = " << cross/barn << " barn" << G4endl;
313    " = " << cross/barn << " barn" << G4endl;   << 343     return cross;
314      }                                         << 
315    return cross;                               << 
316 }                                                 344 }
317                                                   345 
318                                                   346 
319 //....oooOO0OOooo........oooOO0OOooo........oo    347 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
320 void G4PenelopeRayleighModel::BuildFormFactorT    348 void G4PenelopeRayleighModel::BuildFormFactorTable(const G4Material* material)
321 {                                                 349 {
322   /*                                           << 350 
323     1) get composition and equivalent molecula << 351    /*
324   */                                           << 352      1) get composition and equivalent molecular density
325   std::size_t nElements = material->GetNumberO << 353    */
                                                   >> 354   
                                                   >> 355   G4int nElements = material->GetNumberOfElements();
326   const G4ElementVector* elementVector = mater    356   const G4ElementVector* elementVector = material->GetElementVector();
327   const G4double* fractionVector = material->G    357   const G4double* fractionVector = material->GetFractionVector();
328                                                   358 
329   std::vector<G4double> *StechiometricFactors     359   std::vector<G4double> *StechiometricFactors = new std::vector<G4double>;
330   for (std::size_t i=0;i<nElements;++i)        << 360   for (G4int i=0;i<nElements;i++)
331     {                                             361     {
332       G4double fraction = fractionVector[i];      362       G4double fraction = fractionVector[i];
333       G4double atomicWeigth = (*elementVector)    363       G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
334       StechiometricFactors->push_back(fraction    364       StechiometricFactors->push_back(fraction/atomicWeigth);
335     }                                             365     }
336   //Find max                                      366   //Find max
337   G4double MaxStechiometricFactor = 0.;           367   G4double MaxStechiometricFactor = 0.;
338   for (std::size_t i=0;i<nElements;++i)        << 368   for (G4int i=0;i<nElements;i++)
339     {                                             369     {
340       if ((*StechiometricFactors)[i] > MaxStec    370       if ((*StechiometricFactors)[i] > MaxStechiometricFactor)
341         MaxStechiometricFactor = (*Stechiometr    371         MaxStechiometricFactor = (*StechiometricFactors)[i];
342     }                                             372     }
343   if (MaxStechiometricFactor<1e-16)               373   if (MaxStechiometricFactor<1e-16)
344     {                                             374     {
345       G4ExceptionDescription ed;                  375       G4ExceptionDescription ed;
346       ed << "Inconsistent data of atomic compo << 376       ed << "Inconsistent data of atomic composition for " << 
347   material->GetName() << G4endl;                  377   material->GetName() << G4endl;
348       G4Exception("G4PenelopeRayleighModel::Bu    378       G4Exception("G4PenelopeRayleighModel::BuildFormFactorTable()",
349       "em2042",FatalException,ed);                379       "em2042",FatalException,ed);
350     }                                             380     }
351   //Normalize                                     381   //Normalize
352   for (std::size_t i=0;i<nElements;++i)        << 382   for (G4int i=0;i<nElements;i++)
353     (*StechiometricFactors)[i] /=  MaxStechiom    383     (*StechiometricFactors)[i] /=  MaxStechiometricFactor;
354                                                << 384  
                                                   >> 385   // Equivalent atoms per molecule
                                                   >> 386   G4double atomsPerMolecule = 0;
                                                   >> 387   for (G4int i=0;i<nElements;i++)
                                                   >> 388     atomsPerMolecule += (*StechiometricFactors)[i]; 
                                                   >> 389  
355   /*                                              390   /*
356     CREATE THE FORM FACTOR TABLE                  391     CREATE THE FORM FACTOR TABLE
357   */                                              392   */
358   G4PhysicsFreeVector* theFFVec = new G4Physic << 393   G4PhysicsFreeVector* theFFVec = new G4PhysicsFreeVector(logQSquareGrid.size());
                                                   >> 394   theFFVec->SetSpline(true);
359                                                   395 
360   for (std::size_t k=0;k<fLogQSquareGrid.size( << 396   for (size_t k=0;k<logQSquareGrid.size();k++)
361     {                                             397     {
362       G4double ff2 = 0; //squared form factor     398       G4double ff2 = 0; //squared form factor
363       for (std::size_t i=0;i<nElements;++i)    << 399       for (G4int i=0;i<nElements;i++)
364   {                                               400   {
365     G4int iZ = (*elementVector)[i]->GetZasInt( << 401     G4int iZ = (G4int) (*elementVector)[i]->GetZ();
366     G4PhysicsFreeVector* theAtomVec = fAtomicF << 402     G4PhysicsFreeVector* theAtomVec = atomicFormFactor->find(iZ)->second;
367     G4double f = (*theAtomVec)[k]; //the q-gri << 403     G4double f = (*theAtomVec)[k]; //the q-grid is always the same      
368     ff2 += f*f*(*StechiometricFactors)[i];        404     ff2 += f*f*(*StechiometricFactors)[i];
369   }                                               405   }
370       if (ff2)                                    406       if (ff2)
371   theFFVec->PutValue(k,fLogQSquareGrid[k],G4Lo << 407   theFFVec->PutValue(k,logQSquareGrid[k],std::log(ff2)); //NOTICE: THIS IS log(Q^2) vs. log(F^2)
372     }                                             408     }
373   theFFVec->FillSecondDerivatives(); //vector  << 409   logFormFactorTable->insert(std::make_pair(material,theFFVec));
374   fLogFormFactorTable->insert(std::make_pair(m << 
375                                                   410 
376   delete StechiometricFactors;                    411   delete StechiometricFactors;
                                                   >> 412   
377   return;                                         413   return;
378 }                                                 414 }
379                                                   415 
                                                   >> 416 
380 //....oooOO0OOooo........oooOO0OOooo........oo    417 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
381                                                   418 
382 void G4PenelopeRayleighModel::SampleSecondarie    419 void G4PenelopeRayleighModel::SampleSecondaries(std::vector<G4DynamicParticle*>* ,
383             const G4MaterialCutsCouple* couple    420             const G4MaterialCutsCouple* couple,
384             const G4DynamicParticle* aDynamicG    421             const G4DynamicParticle* aDynamicGamma,
385             G4double,                             422             G4double,
386             G4double)                             423             G4double)
387 {                                                 424 {
388   // Sampling of the Rayleigh final state (nam << 425   // Sampling of the Rayleigh final state (namely, scattering angle of the photon) 
389   // from the Penelope2008 model. The scatteri << 426   // from the Penelope2008 model. The scattering angle is sampled from the atomic 
390   // cross section dOmega/d(cosTheta) from Bor << 427   // cross section dOmega/d(cosTheta) from Born ("Atomic Phyisics", 1969), disregarding 
391   // anomalous scattering effects. The Form Fa << 428   // anomalous scattering effects. The Form Factor F(Q) function which appears in the 
392   // analytical cross section is retrieved via << 429   // analytical cross section is retrieved via the method GetFSquared(); atomic data 
393   // are tabulated for F(Q). Form factor for c << 430   // are tabulated for F(Q). Form factor for compounds is calculated according to 
394   // the additivity rule. The sampling from th << 431   // the additivity rule. The sampling from the F(Q) is made via a Rational Inverse 
395   // Transform with Aliasing (RITA) algorithm; << 432   // Transform with Aliasing (RITA) algorithm; RITA parameters are calculated once 
396   // for each material and managed by G4Penelo    433   // for each material and managed by G4PenelopeSamplingData objects.
397   // The sampling algorithm (rejection method) << 434   // The sampling algorithm (rejection method) has efficiency 67% at low energy, and 
398   // increases with energy. For E=100 keV the  << 435   // increases with energy. For E=100 keV the efficiency is 100% and 86% for 
399   // hydrogen and uranium, respectively.          436   // hydrogen and uranium, respectively.
400                                                   437 
401   if (fVerboseLevel > 3)                       << 438   if (verboseLevel > 3)
402     G4cout << "Calling SamplingSecondaries() o    439     G4cout << "Calling SamplingSecondaries() of G4PenelopeRayleighModel" << G4endl;
403                                                   440 
404   G4double photonEnergy0 = aDynamicGamma->GetK    441   G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
405                                                << 442  
406   if (photonEnergy0 <= fIntrinsicLowEnergyLimi    443   if (photonEnergy0 <= fIntrinsicLowEnergyLimit)
407     {                                             444     {
408       fParticleChange->ProposeTrackStatus(fSto    445       fParticleChange->ProposeTrackStatus(fStopAndKill);
409       fParticleChange->SetProposedKineticEnerg    446       fParticleChange->SetProposedKineticEnergy(0.);
410       fParticleChange->ProposeLocalEnergyDepos    447       fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
411       return ;                                    448       return ;
412     }                                             449     }
413                                                   450 
414   G4ParticleMomentum photonDirection0 = aDynam    451   G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
415                                                << 452   
416   const G4Material* theMat = couple->GetMateri    453   const G4Material* theMat = couple->GetMaterial();
417                                                   454 
                                                   >> 455   
418   //1) Verify if tables are ready                 456   //1) Verify if tables are ready
419   //Either Initialize() was not called, or we  << 457   //Either Initialize() was not called, or we are in a slave and InitializeLocal() was 
420   //not invoked                                   458   //not invoked
421   if (!fPMaxTable || !fSamplingTable || !fLogF << 459   if (!pMaxTable || !samplingTable || !logAtomicCrossSection || !atomicFormFactor || 
                                                   >> 460       !logFormFactorTable)
422     {                                             461     {
423       //create a **thread-local** version of t << 462       //create a **thread-local** version of the table. Used only for G4EmCalculator and 
424       //Unit Tests                                463       //Unit Tests
425       fLocalTable = true;                         464       fLocalTable = true;
426       if (!fLogFormFactorTable)                << 465       if (!logAtomicCrossSection)
427   fLogFormFactorTable = new std::map<const G4M << 466   logAtomicCrossSection = new std::map<G4int,G4PhysicsFreeVector*>;
428       if (!fPMaxTable)                         << 467       if (!atomicFormFactor)
429   fPMaxTable = new std::map<const G4Material*, << 468   atomicFormFactor = new std::map<G4int,G4PhysicsFreeVector*>;
430       if (!fSamplingTable)                     << 469       if (!logFormFactorTable)
431   fSamplingTable = new std::map<const G4Materi << 470   logFormFactorTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
432     }                                          << 471       if (!pMaxTable)
433                                                << 472   pMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
434   if (!fSamplingTable->count(theMat))          << 473       if (!samplingTable)
435     {                                          << 474   samplingTable = new std::map<const G4Material*,G4PenelopeSamplingData*>;
436       //If we are here, it means that Initiali << 475     }
437       //not filled up. This can happen in a Un << 476   
438       if (fVerboseLevel > 0)                   << 477   if (!samplingTable->count(theMat))
                                                   >> 478     {
                                                   >> 479       //If we are here, it means that Initialize() was inkoved, but the MaterialTable was 
                                                   >> 480       //not filled up. This can happen in a UnitTest 
                                                   >> 481       if (verboseLevel > 0)
439   {                                               482   {
440     //Issue a G4Exception (warning) only in ve    483     //Issue a G4Exception (warning) only in verbose mode
441     G4ExceptionDescription ed;                    484     G4ExceptionDescription ed;
442     ed << "Unable to find the fSamplingTable d << 485     ed << "Unable to find the samplingTable data for " << 
443       theMat->GetName() << G4endl;                486       theMat->GetName() << G4endl;
444     ed << "This can happen only in Unit Tests" << 487     ed << "This can happen only in Unit Tests" << G4endl;   
445     G4Exception("G4PenelopeRayleighModel::Samp    488     G4Exception("G4PenelopeRayleighModel::SampleSecondaries()",
446           "em2019",JustWarning,ed);               489           "em2019",JustWarning,ed);
447   }                                               490   }
448       const G4ElementVector* theElementVector     491       const G4ElementVector* theElementVector = theMat->GetElementVector();
449       //protect file reading via autolock         492       //protect file reading via autolock
450       G4AutoLock lock(&PenelopeRayleighModelMu    493       G4AutoLock lock(&PenelopeRayleighModelMutex);
451       for (std::size_t j=0;j<theMat->GetNumber << 494       for (size_t j=0;j<theMat->GetNumberOfElements();j++)
452   {                                               495   {
453     G4int iZ = theElementVector->at(j)->GetZas << 496     G4int iZ = (G4int) theElementVector->at(j)->GetZ();   
454     if (!fLogAtomicCrossSection[iZ])           << 497     if (!logAtomicCrossSection->count(iZ))
455       {                                           498       {
456         lock.lock();                              499         lock.lock();
457         ReadDataFile(iZ);                         500         ReadDataFile(iZ);
458         lock.unlock();                         << 501         lock.unlock(); 
459       }                                        << 502       }      
460   }                                               503   }
461       lock.lock();                                504       lock.lock();
462       //1) If the table has not been built for    505       //1) If the table has not been built for the material, do it!
463       if (!fLogFormFactorTable->count(theMat)) << 506       if (!logFormFactorTable->count(theMat))
464   BuildFormFactorTable(theMat);                   507   BuildFormFactorTable(theMat);
465                                                   508 
466       //2) retrieve or build the sampling tabl    509       //2) retrieve or build the sampling table
467       if (!(fSamplingTable->count(theMat)))    << 510       if (!(samplingTable->count(theMat)))
468   InitializeSamplingAlgorithm(theMat);            511   InitializeSamplingAlgorithm(theMat);
469                                                << 512       
470       //3) retrieve or build the pMax data        513       //3) retrieve or build the pMax data
471       if (!fPMaxTable->count(theMat))          << 514       if (!pMaxTable->count(theMat))
472   GetPMaxTable(theMat);                           515   GetPMaxTable(theMat);
473       lock.unlock();                              516       lock.unlock();
474     }                                             517     }
475                                                   518 
476   //Ok, restart the job                           519   //Ok, restart the job
477   G4PenelopeSamplingData* theDataTable = fSamp << 520   
478   G4PhysicsFreeVector* thePMax = fPMaxTable->f << 521   G4PenelopeSamplingData* theDataTable = samplingTable->find(theMat)->second;  
                                                   >> 522   G4PhysicsFreeVector* thePMax = pMaxTable->find(theMat)->second;
479                                                   523 
480   G4double cosTheta = 1.0;                        524   G4double cosTheta = 1.0;
481                                                << 525   
482   //OK, ready to go!                              526   //OK, ready to go!
483   G4double qmax = 2.0*photonEnergy0/electron_m    527   G4double qmax = 2.0*photonEnergy0/electron_mass_c2; //this is non-dimensional now
484                                                   528 
485   if (qmax < 1e-10) //very low momentum transf    529   if (qmax < 1e-10) //very low momentum transfer
486     {                                             530     {
487       G4bool loopAgain=false;                     531       G4bool loopAgain=false;
488       do                                          532       do
489   {                                               533   {
490     loopAgain = false;                            534     loopAgain = false;
491     cosTheta = 1.0-2.0*G4UniformRand();           535     cosTheta = 1.0-2.0*G4UniformRand();
492     G4double G = 0.5*(1+cosTheta*cosTheta);       536     G4double G = 0.5*(1+cosTheta*cosTheta);
493     if (G4UniformRand()>G)                        537     if (G4UniformRand()>G)
494       loopAgain = true;                           538       loopAgain = true;
495   }while(loopAgain);                              539   }while(loopAgain);
496     }                                             540     }
497   else //larger momentum transfer                 541   else //larger momentum transfer
498     {                                             542     {
499       std::size_t nData = theDataTable->GetNum << 543       size_t nData = theDataTable->GetNumberOfStoredPoints();
500       G4double LastQ2inTheTable = theDataTable    544       G4double LastQ2inTheTable = theDataTable->GetX(nData-1);
501       G4double q2max = std::min(qmax*qmax,Last    545       G4double q2max = std::min(qmax*qmax,LastQ2inTheTable);
502                                                   546 
503       G4bool loopAgain = false;                   547       G4bool loopAgain = false;
504       G4double MaxPValue = thePMax->Value(phot    548       G4double MaxPValue = thePMax->Value(photonEnergy0);
505       G4double xx=0;                              549       G4double xx=0;
506                                                << 550       
507       //Sampling by rejection method. The reje << 551       //Sampling by rejection method. The rejection function is 
508       //G = 0.5*(1+cos^2(theta))                  552       //G = 0.5*(1+cos^2(theta))
509       //                                          553       //
510       do{                                         554       do{
511   loopAgain = false;                              555   loopAgain = false;
512   G4double RandomMax = G4UniformRand()*MaxPVal    556   G4double RandomMax = G4UniformRand()*MaxPValue;
513   xx = theDataTable->SampleValue(RandomMax);      557   xx = theDataTable->SampleValue(RandomMax);
514   //xx is a random value of q^2 in (0,q2max),s << 558   //xx is a random value of q^2 in (0,q2max),sampled according to 
515   //F(Q^2) via the RITA algorithm                 559   //F(Q^2) via the RITA algorithm
516   if (xx > q2max)                                 560   if (xx > q2max)
517     loopAgain = true;                             561     loopAgain = true;
518   cosTheta = 1.0-2.0*xx/q2max;                    562   cosTheta = 1.0-2.0*xx/q2max;
519   G4double G = 0.5*(1+cosTheta*cosTheta);         563   G4double G = 0.5*(1+cosTheta*cosTheta);
520   if (G4UniformRand()>G)                          564   if (G4UniformRand()>G)
521     loopAgain = true;                             565     loopAgain = true;
522       }while(loopAgain);                          566       }while(loopAgain);
523     }                                             567     }
524                                                << 568   
525   G4double sinTheta = std::sqrt(1-cosTheta*cos    569   G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
526                                                << 570  
527   // Scattered photon angles. ( Z - axis along    571   // Scattered photon angles. ( Z - axis along the parent photon)
528   G4double phi = twopi * G4UniformRand() ;        572   G4double phi = twopi * G4UniformRand() ;
529   G4double dirX = sinTheta*std::cos(phi);         573   G4double dirX = sinTheta*std::cos(phi);
530   G4double dirY = sinTheta*std::sin(phi);         574   G4double dirY = sinTheta*std::sin(phi);
531   G4double dirZ = cosTheta;                       575   G4double dirZ = cosTheta;
532                                                << 576   
533   // Update G4VParticleChange for the scattere << 577   // Update G4VParticleChange for the scattered photon 
534   G4ThreeVector photonDirection1(dirX, dirY, d    578   G4ThreeVector photonDirection1(dirX, dirY, dirZ);
535                                                   579 
536   photonDirection1.rotateUz(photonDirection0);    580   photonDirection1.rotateUz(photonDirection0);
537   fParticleChange->ProposeMomentumDirection(ph    581   fParticleChange->ProposeMomentumDirection(photonDirection1) ;
538   fParticleChange->SetProposedKineticEnergy(ph    582   fParticleChange->SetProposedKineticEnergy(photonEnergy0) ;
539                                                << 583  
540   return;                                         584   return;
541 }                                                 585 }
542                                                   586 
543                                                   587 
544 //....oooOO0OOooo........oooOO0OOooo........oo    588 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
545                                                   589 
546 void G4PenelopeRayleighModel::ReadDataFile(con    590 void G4PenelopeRayleighModel::ReadDataFile(const G4int Z)
547 {                                                 591 {
548   if (fVerboseLevel > 2)                       << 592 
                                                   >> 593   if (verboseLevel > 2)
549     {                                             594     {
550       G4cout << "G4PenelopeRayleighModel::Read    595       G4cout << "G4PenelopeRayleighModel::ReadDataFile()" << G4endl;
551       G4cout << "Going to read Rayleigh data f    596       G4cout << "Going to read Rayleigh data files for Z=" << Z << G4endl;
552     }                                             597     }
553     const char* path = G4FindDataDir("G4LEDATA << 598 
554     if(!path)                                  << 599   char* path = getenv("G4LEDATA");
                                                   >> 600   if (!path)
555     {                                             601     {
556       G4String excep = "G4LEDATA environment v    602       G4String excep = "G4LEDATA environment variable not set!";
557       G4Exception("G4PenelopeRayleighModel::Re    603       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
558       "em0006",FatalException,excep);             604       "em0006",FatalException,excep);
559       return;                                     605       return;
560     }                                             606     }
561                                                   607 
562   /*                                              608   /*
563     Read first the cross section file             609     Read first the cross section file
564   */                                              610   */
565   std::ostringstream ost;                         611   std::ostringstream ost;
566   if (Z>9)                                        612   if (Z>9)
567     ost << path << "/penelope/rayleigh/pdgra"     613     ost << path << "/penelope/rayleigh/pdgra" << Z << ".p08";
568   else                                            614   else
569     ost << path << "/penelope/rayleigh/pdgra0"    615     ost << path << "/penelope/rayleigh/pdgra0" << Z << ".p08";
570   std::ifstream file(ost.str().c_str());          616   std::ifstream file(ost.str().c_str());
571   if (!file.is_open())                            617   if (!file.is_open())
572     {                                             618     {
573       G4String excep = "Data file " + G4String    619       G4String excep = "Data file " + G4String(ost.str()) + " not found!";
574       G4Exception("G4PenelopeRayleighModel::Re    620       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
575       "em0003",FatalException,excep);             621       "em0003",FatalException,excep);
576     }                                             622     }
577   G4int readZ =0;                                 623   G4int readZ =0;
578   std::size_t nPoints= 0;                      << 624   size_t nPoints= 0;
579   file >> readZ >> nPoints;                       625   file >> readZ >> nPoints;
580   //check the right file is opened.               626   //check the right file is opened.
581   if (readZ != Z || nPoints <= 0 || nPoints >=    627   if (readZ != Z || nPoints <= 0 || nPoints >= 5000)
582     {                                             628     {
583       G4ExceptionDescription ed;                  629       G4ExceptionDescription ed;
584       ed << "Corrupted data file for Z=" << Z     630       ed << "Corrupted data file for Z=" << Z << G4endl;
585       G4Exception("G4PenelopeRayleighModel::Re    631       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
586       "em0005",FatalException,ed);                632       "em0005",FatalException,ed);
587       return;                                     633       return;
588     }                                          << 634     }  
589                                                << 635   G4PhysicsFreeVector* theVec = new G4PhysicsFreeVector((size_t)nPoints);
590   fLogAtomicCrossSection[Z] = new G4PhysicsFre << 
591   G4double ene=0,f1=0,f2=0,xs=0;                  636   G4double ene=0,f1=0,f2=0,xs=0;
592   for (std::size_t i=0;i<nPoints;++i)          << 637   for (size_t i=0;i<nPoints;i++)
593     {                                             638     {
594       file >> ene >> f1 >> f2 >> xs;              639       file >> ene >> f1 >> f2 >> xs;
595       //dimensional quantities                    640       //dimensional quantities
596       ene *= eV;                                  641       ene *= eV;
597       xs *= cm2;                                  642       xs *= cm2;
598       fLogAtomicCrossSection[Z]->PutValue(i,G4 << 643       theVec->PutValue(i,std::log(ene),std::log(xs));
599       if (file.eof() && i != (nPoints-1)) //fi    644       if (file.eof() && i != (nPoints-1)) //file ended too early
600   {                                               645   {
601     G4ExceptionDescription ed ;                << 646     G4ExceptionDescription ed ;   
602     ed << "Corrupted data file for Z=" << Z <<    647     ed << "Corrupted data file for Z=" << Z << G4endl;
603     ed << "Found less than " << nPoints << "en    648     ed << "Found less than " << nPoints << "entries " <<G4endl;
604     G4Exception("G4PenelopeRayleighModel::Read    649     G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
605           "em0005",FatalException,ed);            650           "em0005",FatalException,ed);
606   }                                               651   }
607     }                                             652     }
                                                   >> 653   if (!logAtomicCrossSection)
                                                   >> 654     {
                                                   >> 655       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
                                                   >> 656       "em2044",FatalException,"Unable to allocate the atomic cross section table");
                                                   >> 657       delete theVec;
                                                   >> 658       return;
                                                   >> 659     }
                                                   >> 660   logAtomicCrossSection->insert(std::make_pair(Z,theVec));
608   file.close();                                   661   file.close();
609                                                   662 
610   /*                                              663   /*
611     Then read the form factor file                664     Then read the form factor file
612   */                                              665   */
613   std::ostringstream ost2;                        666   std::ostringstream ost2;
614   if (Z>9)                                        667   if (Z>9)
615     ost2 << path << "/penelope/rayleigh/pdaff"    668     ost2 << path << "/penelope/rayleigh/pdaff" << Z << ".p08";
616   else                                            669   else
617     ost2 << path << "/penelope/rayleigh/pdaff0    670     ost2 << path << "/penelope/rayleigh/pdaff0" << Z << ".p08";
618   file.open(ost2.str().c_str());                  671   file.open(ost2.str().c_str());
619   if (!file.is_open())                            672   if (!file.is_open())
620     {                                             673     {
621       G4String excep = "Data file " + G4String    674       G4String excep = "Data file " + G4String(ost2.str()) + " not found!";
622       G4Exception("G4PenelopeRayleighModel::Re    675       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
623       "em0003",FatalException,excep);             676       "em0003",FatalException,excep);
624     }                                             677     }
625   file >> readZ >> nPoints;                       678   file >> readZ >> nPoints;
626   //check the right file is opened.               679   //check the right file is opened.
627   if (readZ != Z || nPoints <= 0 || nPoints >=    680   if (readZ != Z || nPoints <= 0 || nPoints >= 5000)
628     {                                             681     {
629       G4ExceptionDescription ed;                  682       G4ExceptionDescription ed;
630       ed << "Corrupted data file for Z=" << Z     683       ed << "Corrupted data file for Z=" << Z << G4endl;
631       G4Exception("G4PenelopeRayleighModel::Re    684       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
632       "em0005",FatalException,ed);                685       "em0005",FatalException,ed);
633       return;                                     686       return;
634     }                                          << 687     }  
635   fAtomicFormFactor[Z] = new G4PhysicsFreeVect << 688   G4PhysicsFreeVector* theFFVec = new G4PhysicsFreeVector((size_t)nPoints);
636   G4double q=0,ff=0,incoh=0;                      689   G4double q=0,ff=0,incoh=0;
637   G4bool fillQGrid = false;                       690   G4bool fillQGrid = false;
638   //fill this vector only the first time.         691   //fill this vector only the first time.
639   if (!fLogQSquareGrid.size())                 << 692   if (!logQSquareGrid.size())
640     fillQGrid = true;                             693     fillQGrid = true;
641   for (std::size_t i=0;i<nPoints;++i)          << 694   for (size_t i=0;i<nPoints;i++)
642     {                                             695     {
643       file >> q >> ff >> incoh;                   696       file >> q >> ff >> incoh;
644       //q and ff are dimensionless (q is in un    697       //q and ff are dimensionless (q is in units of (m_e*c)
645       fAtomicFormFactor[Z]->PutValue(i,q,ff);  << 698       theFFVec->PutValue(i,q,ff);
646       if (fillQGrid)                              699       if (fillQGrid)
647   {                                               700   {
648     fLogQSquareGrid.push_back(2.0*G4Log(q));   << 701     logQSquareGrid.push_back(2.0*std::log(q));
649   }                                               702   }
650       if (file.eof() && i != (nPoints-1)) //fi    703       if (file.eof() && i != (nPoints-1)) //file ended too early
651   {                                               704   {
652     G4ExceptionDescription ed;                 << 705     G4ExceptionDescription ed;    
653     ed << "Corrupted data file for Z=" << Z <<    706     ed << "Corrupted data file for Z=" << Z << G4endl;
654     ed << "Found less than " << nPoints << "en    707     ed << "Found less than " << nPoints << "entries " <<G4endl;
655     G4Exception("G4PenelopeRayleighModel::Read    708     G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
656           "em0005",FatalException,ed);            709           "em0005",FatalException,ed);
657   }                                               710   }
658     }                                             711     }
                                                   >> 712   if (!atomicFormFactor)
                                                   >> 713     {
                                                   >> 714       G4Exception("G4PenelopeRayleighModel::ReadDataFile()",
                                                   >> 715       "em2045",FatalException,
                                                   >> 716       "Unable to allocate the atomicFormFactor data table");
                                                   >> 717       delete theFFVec;
                                                   >> 718       return;
                                                   >> 719     }
                                                   >> 720   atomicFormFactor->insert(std::make_pair(Z,theFFVec));
659   file.close();                                   721   file.close();
660   return;                                         722   return;
661 }                                                 723 }
662                                                   724 
663 //....oooOO0OOooo........oooOO0OOooo........oo    725 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
664                                                   726 
665 G4double G4PenelopeRayleighModel::GetFSquared(    727 G4double G4PenelopeRayleighModel::GetFSquared(const G4Material* mat, const G4double QSquared)
666 {                                                 728 {
667   G4double f2 = 0;                                729   G4double f2 = 0;
668   //Input value QSquared could be zero: protec << 730   //Input value QSquared could be zero: protect the log() below against 
669   //the FPE exception                             731   //the FPE exception
670   //If Q<1e-10, set Q to 1e-10                    732   //If Q<1e-10, set Q to 1e-10
671   G4double logQSquared = (QSquared>1e-10) ? G4 << 733   G4double logQSquared = (QSquared>1e-10) ? std::log(QSquared) : -23.;
672   //last value of the table                       734   //last value of the table
673   G4double maxlogQ2 = fLogQSquareGrid[fLogQSqu << 735   G4double maxlogQ2 = logQSquareGrid[logQSquareGrid.size()-1];
674                                                << 736   
                                                   >> 737   
675   //now it should  be all right                   738   //now it should  be all right
676   G4PhysicsFreeVector* theVec = fLogFormFactor << 739   G4PhysicsFreeVector* theVec = logFormFactorTable->find(mat)->second;
677                                                   740 
678   if (!theVec)                                    741   if (!theVec)
679     {                                             742     {
680       G4ExceptionDescription ed;                  743       G4ExceptionDescription ed;
681       ed << "Unable to retrieve F squared tabl    744       ed << "Unable to retrieve F squared table for " << mat->GetName() << G4endl;
682       G4Exception("G4PenelopeRayleighModel::Ge    745       G4Exception("G4PenelopeRayleighModel::GetFSquared()",
683       "em2046",FatalException,ed);                746       "em2046",FatalException,ed);
684       return 0;                                   747       return 0;
685     }                                             748     }
686   if (logQSquared < -20) // Q < 1e-9              749   if (logQSquared < -20) // Q < 1e-9
687     {                                             750     {
688       G4double logf2 = (*theVec)[0]; //first v    751       G4double logf2 = (*theVec)[0]; //first value of the table
689       f2 = G4Exp(logf2);                       << 752       f2 = std::exp(logf2);
690     }                                             753     }
691   else if (logQSquared > maxlogQ2)                754   else if (logQSquared > maxlogQ2)
692     f2 =0;                                        755     f2 =0;
693   else                                            756   else
694     {                                             757     {
695       //log(Q^2) vs. log(F^2)                     758       //log(Q^2) vs. log(F^2)
696       G4double logf2 = theVec->Value(logQSquar    759       G4double logf2 = theVec->Value(logQSquared);
697       f2 = G4Exp(logf2);                       << 760       f2 = std::exp(logf2);
698                                                   761 
699     }                                             762     }
700   if (fVerboseLevel > 3)                       << 763   if (verboseLevel > 3)
701     {                                             764     {
702       G4cout << "G4PenelopeRayleighModel::GetF << 765       G4cout << "G4PenelopeRayleighModel::GetFSquared() in " << mat->GetName() << G4endl;  
703       G4cout << "Q^2 = " <<  QSquared << " (un    766       G4cout << "Q^2 = " <<  QSquared << " (units of 1/(m_e*c); F^2 = " << f2 << G4endl;
704     }                                             767     }
705   return f2;                                      768   return f2;
706 }                                                 769 }
707                                                   770 
708 //....oooOO0OOooo........oooOO0OOooo........oo    771 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
709                                                   772 
710 void G4PenelopeRayleighModel::InitializeSampli    773 void G4PenelopeRayleighModel::InitializeSamplingAlgorithm(const G4Material* mat)
711 {                                                 774 {
                                                   >> 775 
712   G4double q2min = 0;                             776   G4double q2min = 0;
713   G4double q2max = 0;                             777   G4double q2max = 0;
714   const std::size_t np = 150; //hard-coded in  << 778   const size_t np = 150; //hard-coded in Penelope
715   //G4cout << "Init N= " << fLogQSquareGrid.si << 779   //G4cout << "Init N= " << logQSquareGrid.size() << G4endl;
716   for (std::size_t i=1;i<fLogQSquareGrid.size( << 780   for (size_t i=1;i<logQSquareGrid.size();i++)
717     {                                             781     {
718       G4double Q2 = G4Exp(fLogQSquareGrid[i]); << 782       G4double Q2 = std::exp(logQSquareGrid[i]);
719       if (GetFSquared(mat,Q2) >  1e-35)           783       if (GetFSquared(mat,Q2) >  1e-35)
720   {                                               784   {
721     q2max = G4Exp(fLogQSquareGrid[i-1]);       << 785     q2max = std::exp(logQSquareGrid[i-1]);
722   }                                               786   }
723       //G4cout << "Q2= " << Q2 << " q2max= " <    787       //G4cout << "Q2= " << Q2 << " q2max= " << q2max << G4endl;
724     }                                             788     }
725                                                << 789   
726   std::size_t nReducedPoints = np/4;           << 790   size_t nReducedPoints = np/4;
727                                                   791 
728   //check for errors                              792   //check for errors
729   if (np < 16)                                    793   if (np < 16)
730     {                                             794     {
731       G4Exception("G4PenelopeRayleighModel::In    795       G4Exception("G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
732       "em2047",FatalException,                    796       "em2047",FatalException,
733       "Too few points to initialize the sampli    797       "Too few points to initialize the sampling algorithm");
734     }                                             798     }
735   if (q2min > (q2max-1e-10))                      799   if (q2min > (q2max-1e-10))
736     {                                             800     {
737       G4cout << "q2min= " << q2min << " q2max=    801       G4cout << "q2min= " << q2min << " q2max= " << q2max << G4endl;
738       G4Exception("G4PenelopeRayleighModel::In    802       G4Exception("G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
739       "em2048",FatalException,                    803       "em2048",FatalException,
740       "Too narrow grid to initialize the sampl    804       "Too narrow grid to initialize the sampling algorithm");
741     }                                             805     }
742                                                   806 
743   //This is subroutine RITAI0 of Penelope         807   //This is subroutine RITAI0 of Penelope
744   //Create an object of type G4PenelopeRayleig    808   //Create an object of type G4PenelopeRayleighSamplingData --> store in a map::Material*
745                                                   809 
746   //temporary vectors --> Then everything is s    810   //temporary vectors --> Then everything is stored in G4PenelopeSamplingData
747   G4DataVector* x = new G4DataVector();           811   G4DataVector* x = new G4DataVector();
748                                                << 812   
749   /*******************************************    813   /*******************************************************************************
750     Start with a grid of NUNIF points uniforml    814     Start with a grid of NUNIF points uniformly spaced in the interval q2min,q2max
751   ********************************************    815   ********************************************************************************/
752   std::size_t NUNIF = std::min(std::max(((std: << 816   size_t NUNIF = std::min(std::max(((size_t)8),nReducedPoints),np/2);
753   const G4int nip = 51; //hard-coded in Penelo    817   const G4int nip = 51; //hard-coded in Penelope
754                                                   818 
755   G4double dx = (q2max-q2min)/((G4double) NUNI << 819   G4double dx = (q2max-q2min)/((G4double) NUNIF-1);  
756   x->push_back(q2min);                         << 820   x->push_back(q2min); 
757   for (std::size_t i=1;i<NUNIF-1;++i)          << 821   for (size_t i=1;i<NUNIF-1;i++)
758     {                                             822     {
759       G4double app = q2min + i*dx;                823       G4double app = q2min + i*dx;
760       x->push_back(app); //increase            << 824       x->push_back(app); //increase 
761     }                                             825     }
762   x->push_back(q2max);                            826   x->push_back(q2max);
763                                                << 827   
764   if (fVerboseLevel> 3)                        << 828   if (verboseLevel> 3)
765     G4cout << "Vector x has " << x->size() <<     829     G4cout << "Vector x has " << x->size() << " points, while NUNIF = " << NUNIF << G4endl;
766                                                   830 
767   //Allocate temporary storage vectors            831   //Allocate temporary storage vectors
768   G4DataVector* area = new G4DataVector();        832   G4DataVector* area = new G4DataVector();
769   G4DataVector* a = new G4DataVector();           833   G4DataVector* a = new G4DataVector();
770   G4DataVector* b = new G4DataVector();           834   G4DataVector* b = new G4DataVector();
771   G4DataVector* c = new G4DataVector();           835   G4DataVector* c = new G4DataVector();
772   G4DataVector* err = new G4DataVector();         836   G4DataVector* err = new G4DataVector();
773                                                   837 
774   for (std::size_t i=0;i<NUNIF-1;++i) //build  << 838   for (size_t i=0;i<NUNIF-1;i++) //build all points but the last
775     {                                          << 839     {      
776       //Temporary vectors for this loop           840       //Temporary vectors for this loop
777       G4DataVector* pdfi = new G4DataVector();    841       G4DataVector* pdfi = new G4DataVector();
778       G4DataVector* pdfih = new G4DataVector()    842       G4DataVector* pdfih = new G4DataVector();
779       G4DataVector* sumi = new G4DataVector();    843       G4DataVector* sumi = new G4DataVector();
780                                                   844 
781       G4double dxi = ((*x)[i+1]-(*x)[i])/(G4do    845       G4double dxi = ((*x)[i+1]-(*x)[i])/(G4double (nip-1));
782       G4double pdfmax = 0;                        846       G4double pdfmax = 0;
783       for (G4int k=0;k<nip;k++)                   847       for (G4int k=0;k<nip;k++)
784   {                                               848   {
785     G4double xik = (*x)[i]+k*dxi;              << 849     G4double xik = (*x)[i]+k*dxi; 
786     G4double pdfk = std::max(GetFSquared(mat,x    850     G4double pdfk = std::max(GetFSquared(mat,xik),0.);
787     pdfi->push_back(pdfk);                        851     pdfi->push_back(pdfk);
788     pdfmax = std::max(pdfmax,pdfk);            << 852     pdfmax = std::max(pdfmax,pdfk); 
789     if (k < (nip-1))                              853     if (k < (nip-1))
790       {                                           854       {
791         G4double xih = xik + 0.5*dxi;             855         G4double xih = xik + 0.5*dxi;
792         G4double pdfIK = std::max(GetFSquared(    856         G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
793         pdfih->push_back(pdfIK);                  857         pdfih->push_back(pdfIK);
794         pdfmax = std::max(pdfmax,pdfIK);          858         pdfmax = std::max(pdfmax,pdfIK);
795       }                                           859       }
796   }                                               860   }
797                                                << 861     
798       //Simpson's integration                     862       //Simpson's integration
799       G4double cons = dxi*0.5*(1./3.);            863       G4double cons = dxi*0.5*(1./3.);
800       sumi->push_back(0.);                        864       sumi->push_back(0.);
801       for (G4int k=1;k<nip;k++)                   865       for (G4int k=1;k<nip;k++)
802   {                                               866   {
803     G4double previous = (*sumi)[k-1];             867     G4double previous = (*sumi)[k-1];
804     G4double next = previous + cons*((*pdfi)[k    868     G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
805     sumi->push_back(next);                        869     sumi->push_back(next);
806   }                                               870   }
807                                                << 871     
808       G4double lastIntegral = (*sumi)[sumi->si    872       G4double lastIntegral = (*sumi)[sumi->size()-1];
809       area->push_back(lastIntegral);              873       area->push_back(lastIntegral);
810       //Normalize cumulative function             874       //Normalize cumulative function
811       G4double factor = 1.0/lastIntegral;         875       G4double factor = 1.0/lastIntegral;
812       for (std::size_t k=0;k<sumi->size();++k) << 876       for (size_t k=0;k<sumi->size();k++)
813   (*sumi)[k] *= factor;                           877   (*sumi)[k] *= factor;
814                                                << 878       
815       //When the PDF vanishes at one of the in    879       //When the PDF vanishes at one of the interval end points, its value is modified
816       if ((*pdfi)[0] < 1e-35)                  << 880       if ((*pdfi)[0] < 1e-35) 
817   (*pdfi)[0] = 1e-5*pdfmax;                       881   (*pdfi)[0] = 1e-5*pdfmax;
818       if ((*pdfi)[pdfi->size()-1] < 1e-35)        882       if ((*pdfi)[pdfi->size()-1] < 1e-35)
819   (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;          883   (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
820                                                   884 
821       G4double pli = (*pdfi)[0]*factor;           885       G4double pli = (*pdfi)[0]*factor;
822       G4double pui = (*pdfi)[pdfi->size()-1]*f    886       G4double pui = (*pdfi)[pdfi->size()-1]*factor;
823       G4double B_temp = 1.0-1.0/(pli*pui*dx*dx    887       G4double B_temp = 1.0-1.0/(pli*pui*dx*dx);
824       G4double A_temp = (1.0/(pli*dx))-1.0-B_t    888       G4double A_temp = (1.0/(pli*dx))-1.0-B_temp;
825       G4double C_temp = 1.0+A_temp+B_temp;        889       G4double C_temp = 1.0+A_temp+B_temp;
826       if (C_temp < 1e-35)                         890       if (C_temp < 1e-35)
827   {                                               891   {
828     a->push_back(0.);                             892     a->push_back(0.);
829     b->push_back(0.);                             893     b->push_back(0.);
830     c->push_back(1.);                          << 894     c->push_back(1.);   
831   }                                               895   }
832       else                                        896       else
833   {                                               897   {
834     a->push_back(A_temp);                         898     a->push_back(A_temp);
835     b->push_back(B_temp);                         899     b->push_back(B_temp);
836     c->push_back(C_temp);                         900     c->push_back(C_temp);
837   }                                               901   }
838                                                   902 
839       //OK, now get ERR(I), the integral of th << 903       //OK, now get ERR(I), the integral of the absolute difference between the rational interpolation 
840       //and the true pdf, extended over the in    904       //and the true pdf, extended over the interval (X(I),X(I+1))
841       G4int icase = 1; //loop code                905       G4int icase = 1; //loop code
842       G4bool reLoop = false;                      906       G4bool reLoop = false;
843       err->push_back(0.);                         907       err->push_back(0.);
844       do                                          908       do
845   {                                               909   {
846     reLoop = false;                               910     reLoop = false;
847     (*err)[i] = 0.; //zero variable               911     (*err)[i] = 0.; //zero variable
848     for (G4int k=0;k<nip;k++)                     912     for (G4int k=0;k<nip;k++)
849       {                                           913       {
850         G4double rr = (*sumi)[k];                 914         G4double rr = (*sumi)[k];
851         G4double pap = (*area)[i]*(1.0+((*a)[i    915         G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
852     ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*    916     ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
853         if (k == 0 || k == nip-1)                 917         if (k == 0 || k == nip-1)
854     (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k])    918     (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
855         else                                      919         else
856     (*err)[i] += std::fabs(pap-(*pdfi)[k]);       920     (*err)[i] += std::fabs(pap-(*pdfi)[k]);
857       }                                           921       }
858     (*err)[i] *= dxi;                             922     (*err)[i] *= dxi;
859                                                << 923       
860     //If err(I) is too large, the pdf is appro    924     //If err(I) is too large, the pdf is approximated by a uniform distribution
861     if ((*err)[i] > 0.1*(*area)[i] && icase == << 925     if ((*err)[i] > 0.1*(*area)[i] && icase == 1) 
862       {                                           926       {
863         (*b)[i] = 0;                              927         (*b)[i] = 0;
864         (*a)[i] = 0;                              928         (*a)[i] = 0;
865         (*c)[i] = 1.;                             929         (*c)[i] = 1.;
866         icase = 2;                                930         icase = 2;
867         reLoop = true;                            931         reLoop = true;
868       }                                           932       }
869   }while(reLoop);                                 933   }while(reLoop);
                                                   >> 934 
870       delete pdfi;                                935       delete pdfi;
871       delete pdfih;                               936       delete pdfih;
872       delete sumi;                                937       delete sumi;
873     } //end of first loop over i                  938     } //end of first loop over i
874                                                   939 
875   //Now assign last point                         940   //Now assign last point
876   (*x)[x->size()-1] = q2max;                      941   (*x)[x->size()-1] = q2max;
877   a->push_back(0.);                               942   a->push_back(0.);
878   b->push_back(0.);                               943   b->push_back(0.);
879   c->push_back(0.);                               944   c->push_back(0.);
880   err->push_back(0.);                             945   err->push_back(0.);
881   area->push_back(0.);                            946   area->push_back(0.);
882                                                   947 
883   if (x->size() != NUNIF || a->size() != NUNIF << 948   if (x->size() != NUNIF || a->size() != NUNIF || 
884       err->size() != NUNIF || area->size() !=     949       err->size() != NUNIF || area->size() != NUNIF)
885     {                                             950     {
886       G4ExceptionDescription ed;                  951       G4ExceptionDescription ed;
887       ed << "Problem in building the Table for    952       ed << "Problem in building the Table for Sampling: array dimensions do not match" << G4endl;
888       G4Exception("G4PenelopeRayleighModel::In    953       G4Exception("G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
889       "em2049",FatalException,ed);                954       "em2049",FatalException,ed);
890     }                                             955     }
891                                                << 956   
892   /*******************************************    957   /*******************************************************************************
893    New grid points are added by halving the su    958    New grid points are added by halving the sub-intervals with the largest absolute error
894   This is done up to np=150 points in the grid    959   This is done up to np=150 points in the grid
895   ********************************************    960   ********************************************************************************/
896   do                                              961   do
897     {                                             962     {
898       G4double maxError = 0.0;                    963       G4double maxError = 0.0;
899       std::size_t iErrMax = 0;                 << 964       size_t iErrMax = 0;
900       for (std::size_t i=0;i<err->size()-2;++i << 965       for (size_t i=0;i<err->size()-2;i++) 
901   {                                               966   {
902     //maxError is the lagest of the interval e    967     //maxError is the lagest of the interval errors err[i]
903     if ((*err)[i] > maxError)                     968     if ((*err)[i] > maxError)
904       {                                           969       {
905         maxError = (*err)[i];                     970         maxError = (*err)[i];
906         iErrMax = i;                              971         iErrMax = i;
907       }                                           972       }
908   }                                               973   }
909                                                << 974       
910       //OK, now I have to insert one new point    975       //OK, now I have to insert one new point in the position iErrMax
911       G4double newx = 0.5*((*x)[iErrMax]+(*x)[    976       G4double newx = 0.5*((*x)[iErrMax]+(*x)[iErrMax+1]);
912                                                << 977       
913       x->insert(x->begin()+iErrMax+1,newx);       978       x->insert(x->begin()+iErrMax+1,newx);
914       //Add place-holders in the other vectors    979       //Add place-holders in the other vectors
915       area->insert(area->begin()+iErrMax+1,0.)    980       area->insert(area->begin()+iErrMax+1,0.);
916       a->insert(a->begin()+iErrMax+1,0.);         981       a->insert(a->begin()+iErrMax+1,0.);
917       b->insert(b->begin()+iErrMax+1,0.);         982       b->insert(b->begin()+iErrMax+1,0.);
918       c->insert(c->begin()+iErrMax+1,0.);         983       c->insert(c->begin()+iErrMax+1,0.);
919       err->insert(err->begin()+iErrMax+1,0.);     984       err->insert(err->begin()+iErrMax+1,0.);
920                                                << 985         
921       //Now calculate the other parameters        986       //Now calculate the other parameters
922       for (std::size_t i=iErrMax;i<=iErrMax+1; << 987       for (size_t i=iErrMax;i<=iErrMax+1;i++)
923   {                                               988   {
924     //Temporary vectors for this loop             989     //Temporary vectors for this loop
925     G4DataVector* pdfi = new G4DataVector();      990     G4DataVector* pdfi = new G4DataVector();
926     G4DataVector* pdfih = new G4DataVector();     991     G4DataVector* pdfih = new G4DataVector();
927     G4DataVector* sumi = new G4DataVector();      992     G4DataVector* sumi = new G4DataVector();
928                                                << 993     
929     G4double dxLocal = (*x)[i+1]-(*x)[i];         994     G4double dxLocal = (*x)[i+1]-(*x)[i];
930     G4double dxi = ((*x)[i+1]-(*x)[i])/(G4doub    995     G4double dxi = ((*x)[i+1]-(*x)[i])/(G4double (nip-1));
931     G4double pdfmax = 0;                          996     G4double pdfmax = 0;
932     for (G4int k=0;k<nip;k++)                     997     for (G4int k=0;k<nip;k++)
933       {                                           998       {
934         G4double xik = (*x)[i]+k*dxi;             999         G4double xik = (*x)[i]+k*dxi;
935         G4double pdfk = std::max(GetFSquared(m    1000         G4double pdfk = std::max(GetFSquared(mat,xik),0.);
936         pdfi->push_back(pdfk);                    1001         pdfi->push_back(pdfk);
937         pdfmax = std::max(pdfmax,pdfk);        << 1002         pdfmax = std::max(pdfmax,pdfk); 
938         if (k < (nip-1))                          1003         if (k < (nip-1))
939     {                                             1004     {
940       G4double xih = xik + 0.5*dxi;               1005       G4double xih = xik + 0.5*dxi;
941       G4double pdfIK = std::max(GetFSquared(ma    1006       G4double pdfIK = std::max(GetFSquared(mat,xih),0.);
942       pdfih->push_back(pdfIK);                    1007       pdfih->push_back(pdfIK);
943       pdfmax = std::max(pdfmax,pdfIK);            1008       pdfmax = std::max(pdfmax,pdfIK);
944     }                                             1009     }
945       }                                           1010       }
946                                                << 1011     
947     //Simpson's integration                       1012     //Simpson's integration
948     G4double cons = dxi*0.5*(1./3.);              1013     G4double cons = dxi*0.5*(1./3.);
949     sumi->push_back(0.);                          1014     sumi->push_back(0.);
950     for (G4int k=1;k<nip;k++)                     1015     for (G4int k=1;k<nip;k++)
951       {                                           1016       {
952         G4double previous = (*sumi)[k-1];         1017         G4double previous = (*sumi)[k-1];
953         G4double next = previous + cons*((*pdf    1018         G4double next = previous + cons*((*pdfi)[k-1]+4.0*(*pdfih)[k-1]+(*pdfi)[k]);
954         sumi->push_back(next);                    1019         sumi->push_back(next);
955       }                                           1020       }
956     G4double lastIntegral = (*sumi)[sumi->size    1021     G4double lastIntegral = (*sumi)[sumi->size()-1];
957     (*area)[i] = lastIntegral;                    1022     (*area)[i] = lastIntegral;
958                                                << 1023     
959     //Normalize cumulative function               1024     //Normalize cumulative function
960     G4double factor = 1.0/lastIntegral;           1025     G4double factor = 1.0/lastIntegral;
961     for (std::size_t k=0;k<sumi->size();++k)   << 1026     for (size_t k=0;k<sumi->size();k++)
962       (*sumi)[k] *= factor;                       1027       (*sumi)[k] *= factor;
963                                                << 1028     
964     //When the PDF vanishes at one of the inte    1029     //When the PDF vanishes at one of the interval end points, its value is modified
965     if ((*pdfi)[0] < 1e-35)                    << 1030     if ((*pdfi)[0] < 1e-35) 
966       (*pdfi)[0] = 1e-5*pdfmax;                   1031       (*pdfi)[0] = 1e-5*pdfmax;
967     if ((*pdfi)[pdfi->size()-1] < 1e-35)          1032     if ((*pdfi)[pdfi->size()-1] < 1e-35)
968       (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;      1033       (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;
969                                                << 1034     
970     G4double pli = (*pdfi)[0]*factor;             1035     G4double pli = (*pdfi)[0]*factor;
971     G4double pui = (*pdfi)[pdfi->size()-1]*fac    1036     G4double pui = (*pdfi)[pdfi->size()-1]*factor;
972     G4double B_temp = 1.0-1.0/(pli*pui*dxLocal    1037     G4double B_temp = 1.0-1.0/(pli*pui*dxLocal*dxLocal);
973     G4double A_temp = (1.0/(pli*dxLocal))-1.0-    1038     G4double A_temp = (1.0/(pli*dxLocal))-1.0-B_temp;
974     G4double C_temp = 1.0+A_temp+B_temp;          1039     G4double C_temp = 1.0+A_temp+B_temp;
975     if (C_temp < 1e-35)                           1040     if (C_temp < 1e-35)
976       {                                           1041       {
977         (*a)[i]= 0.;                              1042         (*a)[i]= 0.;
978         (*b)[i] = 0.;                             1043         (*b)[i] = 0.;
979         (*c)[i] = 1;                              1044         (*c)[i] = 1;
980       }                                           1045       }
981     else                                          1046     else
982       {                                           1047       {
983         (*a)[i]= A_temp;                          1048         (*a)[i]= A_temp;
984         (*b)[i] = B_temp;                         1049         (*b)[i] = B_temp;
985         (*c)[i] = C_temp;                         1050         (*c)[i] = C_temp;
986       }                                           1051       }
987     //OK, now get ERR(I), the integral of the  << 1052     //OK, now get ERR(I), the integral of the absolute difference between the rational interpolation 
988     //and the true pdf, extended over the inte    1053     //and the true pdf, extended over the interval (X(I),X(I+1))
989     G4int icase = 1; //loop code                  1054     G4int icase = 1; //loop code
990     G4bool reLoop = false;                        1055     G4bool reLoop = false;
991     do                                            1056     do
992       {                                           1057       {
993         reLoop = false;                           1058         reLoop = false;
994         (*err)[i] = 0.; //zero variable           1059         (*err)[i] = 0.; //zero variable
995         for (G4int k=0;k<nip;k++)                 1060         for (G4int k=0;k<nip;k++)
996     {                                             1061     {
997       G4double rr = (*sumi)[k];                << 1062       G4double rr = (*sumi)[k];       
998       G4double pap = (*area)[i]*(1.0+((*a)[i]+    1063       G4double pap = (*area)[i]*(1.0+((*a)[i]+(*b)[i]*rr)*rr)*(1.0+((*a)[i]+(*b)[i]*rr)*rr)/
999         ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1    1064         ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(*x)[i]));
1000       if (k == 0 || k == nip-1)                  1065       if (k == 0 || k == nip-1)
1001         (*err)[i] += 0.5*std::fabs(pap-(*pdfi    1066         (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]);
1002       else                                       1067       else
1003         (*err)[i] += std::fabs(pap-(*pdfi)[k]    1068         (*err)[i] += std::fabs(pap-(*pdfi)[k]);
1004     }                                            1069     }
1005         (*err)[i] *= dxi;                        1070         (*err)[i] *= dxi;
1006                                               << 1071         
1007         //If err(I) is too large, the pdf is     1072         //If err(I) is too large, the pdf is approximated by a uniform distribution
1008         if ((*err)[i] > 0.1*(*area)[i] && ica << 1073         if ((*err)[i] > 0.1*(*area)[i] && icase == 1) 
1009     {                                            1074     {
1010       (*b)[i] = 0;                               1075       (*b)[i] = 0;
1011       (*a)[i] = 0;                               1076       (*a)[i] = 0;
1012       (*c)[i] = 1.;                              1077       (*c)[i] = 1.;
1013       icase = 2;                                 1078       icase = 2;
1014       reLoop = true;                             1079       reLoop = true;
1015     }                                            1080     }
1016       }while(reLoop);                            1081       }while(reLoop);
1017     delete pdfi;                                 1082     delete pdfi;
1018     delete pdfih;                                1083     delete pdfih;
1019     delete sumi;                                 1084     delete sumi;
1020   }                                              1085   }
1021     }while(x->size() < np);                      1086     }while(x->size() < np);
1022                                                  1087 
1023   if (x->size() != np || a->size() != np ||   << 1088   if (x->size() != np || a->size() != np || 
1024       err->size() != np || area->size() != np    1089       err->size() != np || area->size() != np)
1025     {                                            1090     {
1026       G4Exception("G4PenelopeRayleighModel::I    1091       G4Exception("G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
1027       "em2050",FatalException,                   1092       "em2050",FatalException,
1028       "Problem in building the extended Table    1093       "Problem in building the extended Table for Sampling: array dimensions do not match ");
1029     }                                            1094     }
1030                                                  1095 
1031   /******************************************    1096   /*******************************************************************************
1032    Renormalization                               1097    Renormalization
1033   *******************************************    1098   ********************************************************************************/
1034   G4double ws = 0;                               1099   G4double ws = 0;
1035   for (std::size_t i=0;i<np-1;++i)            << 1100   for (size_t i=0;i<np-1;i++)
1036     ws += (*area)[i];                            1101     ws += (*area)[i];
1037   ws = 1.0/ws;                                   1102   ws = 1.0/ws;
1038   G4double errMax = 0;                           1103   G4double errMax = 0;
1039   for (std::size_t i=0;i<np-1;++i)            << 1104   for (size_t i=0;i<np-1;i++)
1040     {                                            1105     {
1041       (*area)[i] *= ws;                          1106       (*area)[i] *= ws;
1042       (*err)[i] *= ws;                           1107       (*err)[i] *= ws;
1043       errMax = std::max(errMax,(*err)[i]);       1108       errMax = std::max(errMax,(*err)[i]);
1044     }                                            1109     }
1045                                                  1110 
1046   //Vector with the normalized cumulative dis    1111   //Vector with the normalized cumulative distribution
1047   G4DataVector* PAC = new G4DataVector();        1112   G4DataVector* PAC = new G4DataVector();
1048   PAC->push_back(0.);                            1113   PAC->push_back(0.);
1049   for (std::size_t i=0;i<np-1;++i)            << 1114   for (size_t i=0;i<np-1;i++)
1050     {                                            1115     {
1051       G4double previous = (*PAC)[i];             1116       G4double previous = (*PAC)[i];
1052       PAC->push_back(previous+(*area)[i]);       1117       PAC->push_back(previous+(*area)[i]);
1053     }                                            1118     }
1054   (*PAC)[PAC->size()-1] = 1.;                    1119   (*PAC)[PAC->size()-1] = 1.;
1055                                               << 1120          
1056   /******************************************    1121   /*******************************************************************************
1057   Pre-calculated limits for the initial binar    1122   Pre-calculated limits for the initial binary search for subsequent sampling
1058   *******************************************    1123   ********************************************************************************/
1059   std::vector<std::size_t> *ITTL = new std::v << 1124 
1060   std::vector<std::size_t> *ITTU = new std::v << 1125   //G4DataVector* ITTL = new G4DataVector();
                                                   >> 1126   std::vector<size_t> *ITTL = new std::vector<size_t>;
                                                   >> 1127   std::vector<size_t> *ITTU = new std::vector<size_t>;
1061                                                  1128 
1062   //Just create place-holders                    1129   //Just create place-holders
1063   for (std::size_t i=0;i<np;++i)              << 1130   for (size_t i=0;i<np;i++)
1064     {                                            1131     {
1065       ITTL->push_back(0);                        1132       ITTL->push_back(0);
1066       ITTU->push_back(0);                        1133       ITTU->push_back(0);
1067     }                                            1134     }
1068                                                  1135 
1069   G4double bin = 1.0/(np-1);                     1136   G4double bin = 1.0/(np-1);
1070   (*ITTL)[0]=0;                                  1137   (*ITTL)[0]=0;
1071   for (std::size_t i=1;i<(np-1);++i)          << 1138   for (size_t i=1;i<(np-1);i++)
1072     {                                            1139     {
1073       G4double ptst = i*bin;                  << 1140       G4double ptst = i*bin; 
1074       G4bool found = false;                      1141       G4bool found = false;
1075       for (std::size_t j=(*ITTL)[i-1];j<np && << 1142       for (size_t j=(*ITTL)[i-1];j<np && !found;j++)
1076   {                                              1143   {
1077     if ((*PAC)[j] > ptst)                        1144     if ((*PAC)[j] > ptst)
1078       {                                          1145       {
1079         (*ITTL)[i] = j-1;                        1146         (*ITTL)[i] = j-1;
1080         (*ITTU)[i-1] = j;                        1147         (*ITTU)[i-1] = j;
1081         found = true;                            1148         found = true;
1082       }                                          1149       }
1083   }                                              1150   }
1084     }                                            1151     }
1085   (*ITTU)[ITTU->size()-2] = ITTU->size()-1;      1152   (*ITTU)[ITTU->size()-2] = ITTU->size()-1;
1086   (*ITTU)[ITTU->size()-1] = ITTU->size()-1;      1153   (*ITTU)[ITTU->size()-1] = ITTU->size()-1;
1087   (*ITTL)[ITTL->size()-1] = ITTU->size()-2;      1154   (*ITTL)[ITTL->size()-1] = ITTU->size()-2;
1088                                                  1155 
1089   if (ITTU->size() != np || ITTU->size() != n    1156   if (ITTU->size() != np || ITTU->size() != np)
1090     {                                            1157     {
1091       G4Exception("G4PenelopeRayleighModel::I    1158       G4Exception("G4PenelopeRayleighModel::InitializeSamplingAlgorithm()",
1092       "em2051",FatalException,                   1159       "em2051",FatalException,
1093       "Problem in building the Limit Tables f    1160       "Problem in building the Limit Tables for Sampling: array dimensions do not match");
1094     }                                            1161     }
1095                                                  1162 
                                                   >> 1163 
1096   /******************************************    1164   /********************************************************************************
1097     Copy tables                                  1165     Copy tables
1098   *******************************************    1166   ********************************************************************************/
1099   G4PenelopeSamplingData* theTable = new G4Pe    1167   G4PenelopeSamplingData* theTable = new G4PenelopeSamplingData(np);
1100   for (std::size_t i=0;i<np;++i)              << 1168   for (size_t i=0;i<np;i++)
1101     {                                            1169     {
1102       theTable->AddPoint((*x)[i],(*PAC)[i],(*    1170       theTable->AddPoint((*x)[i],(*PAC)[i],(*a)[i],(*b)[i],(*ITTL)[i],(*ITTU)[i]);
1103     }                                            1171     }
1104                                                  1172 
1105   if (fVerboseLevel > 2)                      << 1173   if (verboseLevel > 2)
1106     {                                            1174     {
1107       G4cout << "**************************** << 1175       G4cout << "*************************************************************************" << 
1108   G4endl;                                        1176   G4endl;
1109       G4cout << "Sampling table for Penelope     1177       G4cout << "Sampling table for Penelope Rayleigh scattering in " << mat->GetName() << G4endl;
1110       theTable->DumpTable();                     1178       theTable->DumpTable();
1111     }                                         << 1179     } 
1112   fSamplingTable->insert(std::make_pair(mat,t << 1180   samplingTable->insert(std::make_pair(mat,theTable));
1113                                                  1181 
                                                   >> 1182  
1114   //Clean up temporary vectors                   1183   //Clean up temporary vectors
1115   delete x;                                      1184   delete x;
1116   delete a;                                      1185   delete a;
1117   delete b;                                      1186   delete b;
1118   delete c;                                      1187   delete c;
1119   delete err;                                    1188   delete err;
1120   delete area;                                   1189   delete area;
1121   delete PAC;                                    1190   delete PAC;
1122   delete ITTL;                                   1191   delete ITTL;
1123   delete ITTU;                                   1192   delete ITTU;
1124                                                  1193 
1125   //DONE!                                        1194   //DONE!
1126   return;                                        1195   return;
                                                   >> 1196   
1127 }                                                1197 }
1128                                                  1198 
1129 //....oooOO0OOooo........oooOO0OOooo........o    1199 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1130                                                  1200 
1131 void G4PenelopeRayleighModel::GetPMaxTable(co    1201 void G4PenelopeRayleighModel::GetPMaxTable(const G4Material* mat)
1132 {                                                1202 {
1133   if (!fPMaxTable)                            << 1203 
                                                   >> 1204   if (!pMaxTable)
1134     {                                            1205     {
1135       G4cout << "G4PenelopeRayleighModel::Bui    1206       G4cout << "G4PenelopeRayleighModel::BuildPMaxTable" << G4endl;
1136       G4cout << "Going to instanziate the fPM << 1207       G4cout << "Going to instanziate the pMaxTable !" << G4endl;
1137       G4cout << "That should _not_ be here! "    1208       G4cout << "That should _not_ be here! " << G4endl;
1138       fPMaxTable = new std::map<const G4Mater << 1209       pMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
1139     }                                            1210     }
1140   //check if the table is already there          1211   //check if the table is already there
1141   if (fPMaxTable->count(mat))                 << 1212   if (pMaxTable->count(mat))
1142     return;                                      1213     return;
1143                                                  1214 
1144   //otherwise build it                           1215   //otherwise build it
1145   if (!fSamplingTable)                        << 1216   if (!samplingTable)
1146     {                                            1217     {
1147       G4Exception("G4PenelopeRayleighModel::G    1218       G4Exception("G4PenelopeRayleighModel::GetPMaxTable()",
1148       "em2052",FatalException,                   1219       "em2052",FatalException,
1149       "SamplingTable is not properly instanti    1220       "SamplingTable is not properly instantiated");
1150       return;                                    1221       return;
1151     }                                            1222     }
1152                                                  1223 
1153   //This should not be: the sampling table is    1224   //This should not be: the sampling table is built before the p-table
1154   if (!fSamplingTable->count(mat))            << 1225   if (!samplingTable->count(mat))
1155     {                                            1226     {
1156        G4ExceptionDescription ed;                1227        G4ExceptionDescription ed;
1157        ed << "Sampling table for material " <    1228        ed << "Sampling table for material " << mat->GetName() << " not found";
1158        G4Exception("G4PenelopeRayleighModel::    1229        G4Exception("G4PenelopeRayleighModel::GetPMaxTable()",
1159                   "em2052",FatalException,       1230                   "em2052",FatalException,
1160                   ed);                           1231                   ed);
1161        return;                                   1232        return;
1162     }                                            1233     }
1163                                                  1234 
1164   G4PenelopeSamplingData *theTable = fSamplin << 1235   G4PenelopeSamplingData *theTable = samplingTable->find(mat)->second;
1165   std::size_t tablePoints = theTable->GetNumb << 1236   size_t tablePoints = theTable->GetNumberOfStoredPoints();
1166                                                  1237 
1167   std::size_t nOfEnergyPoints = fLogEnergyGri << 1238   size_t nOfEnergyPoints = logEnergyGridPMax.size();
1168   G4PhysicsFreeVector* theVec = new G4Physics    1239   G4PhysicsFreeVector* theVec = new G4PhysicsFreeVector(nOfEnergyPoints);
1169                                                  1240 
1170   const std::size_t nip = 51; //hard-coded in << 1241   const size_t nip = 51; //hard-coded in Penelope
1171                                                  1242 
1172   for (std::size_t ie=0;ie<fLogEnergyGridPMax << 1243   for (size_t ie=0;ie<logEnergyGridPMax.size();ie++)
1173     {                                            1244     {
1174       G4double energy = G4Exp(fLogEnergyGridP << 1245       G4double energy = std::exp(logEnergyGridPMax[ie]);
1175       G4double Qm = 2.0*energy/electron_mass_    1246       G4double Qm = 2.0*energy/electron_mass_c2; //this is non-dimensional now
1176       G4double Qm2 = Qm*Qm;                      1247       G4double Qm2 = Qm*Qm;
1177       G4double firstQ2 = theTable->GetX(0);      1248       G4double firstQ2 = theTable->GetX(0);
1178       G4double lastQ2 = theTable->GetX(tableP    1249       G4double lastQ2 = theTable->GetX(tablePoints-1);
1179       G4double thePMax = 0;                      1250       G4double thePMax = 0;
1180                                               << 1251       
1181       if (Qm2 > firstQ2)                         1252       if (Qm2 > firstQ2)
1182   {                                              1253   {
1183     if (Qm2 < lastQ2)                            1254     if (Qm2 < lastQ2)
1184       {                                          1255       {
1185         //bisection to look for the index of     1256         //bisection to look for the index of Qm
1186         std::size_t lowerBound = 0;           << 1257         size_t lowerBound = 0;
1187         std::size_t upperBound = tablePoints- << 1258         size_t upperBound = tablePoints-1;
1188         while (lowerBound <= upperBound)         1259         while (lowerBound <= upperBound)
1189     {                                            1260     {
1190       std::size_t midBin = (lowerBound + uppe << 1261       size_t midBin = (lowerBound + upperBound)/2;
1191       if( Qm2 < theTable->GetX(midBin))          1262       if( Qm2 < theTable->GetX(midBin))
1192         { upperBound = midBin-1; }               1263         { upperBound = midBin-1; }
1193       else                                       1264       else
1194         { lowerBound = midBin+1; }               1265         { lowerBound = midBin+1; }
1195     }                                            1266     }
1196         //upperBound is the output (but also     1267         //upperBound is the output (but also lowerBounf --> should be the same!)
1197         G4double Q1 = theTable->GetX(upperBou    1268         G4double Q1 = theTable->GetX(upperBound);
1198         G4double Q2 = Qm2;                       1269         G4double Q2 = Qm2;
1199         G4double DQ = (Q2-Q1)/((G4double)(nip    1270         G4double DQ = (Q2-Q1)/((G4double)(nip-1));
1200         G4double theA = theTable->GetA(upperB    1271         G4double theA = theTable->GetA(upperBound);
1201         G4double theB = theTable->GetB(upperB    1272         G4double theB = theTable->GetB(upperBound);
1202         G4double thePAC = theTable->GetPAC(up    1273         G4double thePAC = theTable->GetPAC(upperBound);
1203         G4DataVector* fun = new G4DataVector(    1274         G4DataVector* fun = new G4DataVector();
1204         for (std::size_t k=0;k<nip;++k)       << 1275         for (size_t k=0;k<nip;k++)
1205     {                                            1276     {
1206       G4double qi = Q1 + k*DQ;                   1277       G4double qi = Q1 + k*DQ;
1207       G4double tau = (qi-Q1)/                    1278       G4double tau = (qi-Q1)/
1208         (theTable->GetX(upperBound+1)-Q1);       1279         (theTable->GetX(upperBound+1)-Q1);
1209       G4double con1 = 2.0*theB*tau;           << 1280       G4double con1 = 2.0*theB*tau; 
1210       G4double ci = 1.0+theA+theB;               1281       G4double ci = 1.0+theA+theB;
1211       G4double con2 = ci-theA*tau;               1282       G4double con2 = ci-theA*tau;
1212       G4double etap = 0;                         1283       G4double etap = 0;
1213       if (std::fabs(con1) > 1.0e-16*std::fabs    1284       if (std::fabs(con1) > 1.0e-16*std::fabs(con2))
1214         etap = con2*(1.0-std::sqrt(1.0-2.0*ta    1285         etap = con2*(1.0-std::sqrt(1.0-2.0*tau*con1/(con2*con2)))/con1;
1215       else                                       1286       else
1216         etap = tau/con2;                         1287         etap = tau/con2;
1217       G4double theFun = (theTable->GetPAC(upp    1288       G4double theFun = (theTable->GetPAC(upperBound+1)-thePAC)*
1218         (1.0+(theA+theB*etap)*etap)*(1.0+(the    1289         (1.0+(theA+theB*etap)*etap)*(1.0+(theA+theB*etap)*etap)/
1219         ((1.0-theB*etap*etap)*ci*(theTable->G    1290         ((1.0-theB*etap*etap)*ci*(theTable->GetX(upperBound+1)-Q1));
1220       fun->push_back(theFun);                    1291       fun->push_back(theFun);
1221     }                                            1292     }
1222         //Now intergrate numerically the fun     1293         //Now intergrate numerically the fun Cavalieri-Simpson's method
1223         G4DataVector* sum = new G4DataVector;    1294         G4DataVector* sum = new G4DataVector;
1224         G4double CONS = DQ*(1./12.);             1295         G4double CONS = DQ*(1./12.);
1225         G4double HCONS = 0.5*CONS;               1296         G4double HCONS = 0.5*CONS;
1226         sum->push_back(0.);                      1297         sum->push_back(0.);
1227         G4double secondPoint = (*sum)[0] +    << 1298         G4double secondPoint = (*sum)[0] + 
1228     (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*C    1299     (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*CONS;
1229         sum->push_back(secondPoint);             1300         sum->push_back(secondPoint);
1230         for (std::size_t hh=2;hh<nip-1;++hh)  << 1301         for (size_t hh=2;hh<nip-1;hh++)
1231     {                                            1302     {
1232       G4double previous = (*sum)[hh-1];          1303       G4double previous = (*sum)[hh-1];
1233       G4double next = previous+(13.0*((*fun)[    1304       G4double next = previous+(13.0*((*fun)[hh-1]+(*fun)[hh])-
1234               (*fun)[hh+1]-(*fun)[hh-2])*HCON    1305               (*fun)[hh+1]-(*fun)[hh-2])*HCONS;
1235       sum->push_back(next);                      1306       sum->push_back(next);
1236     }                                            1307     }
1237         G4double last = (*sum)[nip-2]+(5.0*(*    1308         G4double last = (*sum)[nip-2]+(5.0*(*fun)[nip-1]+8.0*(*fun)[nip-2]-
1238                (*fun)[nip-3])*CONS;              1309                (*fun)[nip-3])*CONS;
1239         sum->push_back(last);                 << 1310         sum->push_back(last);  
1240         thePMax = thePAC + (*sum)[sum->size()    1311         thePMax = thePAC + (*sum)[sum->size()-1]; //last point
1241         delete fun;                              1312         delete fun;
1242         delete sum;                              1313         delete sum;
1243       }                                          1314       }
1244     else                                         1315     else
1245       {                                          1316       {
1246         thePMax = 1.0;                           1317         thePMax = 1.0;
1247       }                                       << 1318       }  
1248   }                                              1319   }
1249       else                                       1320       else
1250   {                                              1321   {
1251     thePMax = theTable->GetPAC(0);               1322     thePMax = theTable->GetPAC(0);
1252   }                                              1323   }
1253                                                  1324 
1254       //Write number in the table                1325       //Write number in the table
1255       theVec->PutValue(ie,energy,thePMax);       1326       theVec->PutValue(ie,energy,thePMax);
1256   }                                              1327   }
1257                                               << 1328   
1258   fPMaxTable->insert(std::make_pair(mat,theVe << 1329   pMaxTable->insert(std::make_pair(mat,theVec));
1259   return;                                        1330   return;
                                                   >> 1331 
1260 }                                                1332 }
1261                                                  1333 
1262 //....oooOO0OOooo........oooOO0OOooo........o    1334 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1263                                                  1335 
1264 void G4PenelopeRayleighModel::DumpFormFactorT    1336 void G4PenelopeRayleighModel::DumpFormFactorTable(const G4Material* mat)
1265 {                                                1337 {
1266   G4cout << "********************************    1338   G4cout << "*****************************************************************" << G4endl;
1267   G4cout << "G4PenelopeRayleighModel: Form Fa    1339   G4cout << "G4PenelopeRayleighModel: Form Factor Table for " << mat->GetName() << G4endl;
1268   //try to use the same format as Penelope-Fo    1340   //try to use the same format as Penelope-Fortran, namely Q (/m_e*c) and F
1269   G4cout <<  "Q/(m_e*c)                 F(Q)     1341   G4cout <<  "Q/(m_e*c)                 F(Q)     " << G4endl;
1270   G4cout << "********************************    1342   G4cout << "*****************************************************************" << G4endl;
1271   if (!fLogFormFactorTable->count(mat))       << 1343   if (!logFormFactorTable->count(mat))
1272     BuildFormFactorTable(mat);                   1344     BuildFormFactorTable(mat);
1273                                               << 1345   
1274   G4PhysicsFreeVector* theVec = fLogFormFacto << 1346   G4PhysicsFreeVector* theVec = logFormFactorTable->find(mat)->second;
1275   for (std::size_t i=0;i<theVec->GetVectorLen << 1347   for (size_t i=0;i<theVec->GetVectorLength();i++)
1276     {                                            1348     {
1277       G4double logQ2 = theVec->GetLowEdgeEner    1349       G4double logQ2 = theVec->GetLowEdgeEnergy(i);
1278       G4double Q = G4Exp(0.5*logQ2);          << 1350       G4double Q = std::exp(0.5*logQ2);
1279       G4double logF2 = (*theVec)[i];             1351       G4double logF2 = (*theVec)[i];
1280       G4double F = G4Exp(0.5*logF2);          << 1352       G4double F = std::exp(0.5*logF2);
1281       G4cout << Q << "              " << F <<    1353       G4cout << Q << "              " << F << G4endl;
1282     }                                            1354     }
1283   //DONE                                         1355   //DONE
1284   return;                                        1356   return;
1285 }                                                1357 }
1286                                                  1358 
1287 //....oooOO0OOooo........oooOO0OOooo........o    1359 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
1288                                                  1360 
1289 void G4PenelopeRayleighModel::SetParticle(con    1361 void G4PenelopeRayleighModel::SetParticle(const G4ParticleDefinition* p)
1290 {                                                1362 {
1291   if(!fParticle) {                               1363   if(!fParticle) {
1292     fParticle = p;                            << 1364     fParticle = p;  
1293   }                                              1365   }
1294 }                                                1366 }
1295                                                  1367