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 9.2.p4)


  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,v 1.2 2008/12/04 14:09:36 pandola Exp $
                                                   >>  27 // GEANT4 tag $Name: geant4-09-02-patch-04 $
 26 //                                                 28 //
 27 // Author: Luciano Pandola                         29 // Author: Luciano Pandola
 28 //                                                 30 //
 29 // History:                                        31 // History:
 30 // --------                                        32 // --------
 31 // 03 Dec 2009   L Pandola    First implementa <<  33 // 14 Oct 2008   L Pandola    Migration from process to model 
 32 // 25 May 2011   L.Pandola    Renamed (make v2 << 
 33 // 19 Sep 2013   L.Pandola    Migration to MT  << 
 34 //                                                 34 //
 35                                                    35 
 36 #include "G4PenelopeRayleighModel.hh"              36 #include "G4PenelopeRayleighModel.hh"
 37 #include "G4PhysicalConstants.hh"              << 
 38 #include "G4SystemOfUnits.hh"                  << 
 39 #include "G4PenelopeSamplingData.hh"           << 
 40 #include "G4ParticleDefinition.hh"                 37 #include "G4ParticleDefinition.hh"
 41 #include "G4MaterialCutsCouple.hh"                 38 #include "G4MaterialCutsCouple.hh"
 42 #include "G4ProductionCutsTable.hh"                39 #include "G4ProductionCutsTable.hh"
 43 #include "G4DynamicParticle.hh"                    40 #include "G4DynamicParticle.hh"
 44 #include "G4PhysicsTable.hh"                       41 #include "G4PhysicsTable.hh"
 45 #include "G4ElementTable.hh"                       42 #include "G4ElementTable.hh"
 46 #include "G4Element.hh"                            43 #include "G4Element.hh"
 47 #include "G4PhysicsFreeVector.hh"              <<  44 #include "G4PenelopeIntegrator.hh"
 48 #include "G4AutoLock.hh"                       << 
 49 #include "G4Exp.hh"                            << 
 50                                                    45 
 51 //....oooOO0OOooo........oooOO0OOooo........oo << 
 52                                                << 
 53 const G4int G4PenelopeRayleighModel::fMaxZ;    << 
 54 G4PhysicsFreeVector* G4PenelopeRayleighModel:: << 
 55 G4PhysicsFreeVector* G4PenelopeRayleighModel:: << 
 56                                                    46 
 57 //....oooOO0OOooo........oooOO0OOooo........oo     47 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 58                                                    48 
 59 G4PenelopeRayleighModel::G4PenelopeRayleighMod <<  49 
 60              const G4String& nam)              <<  50 G4PenelopeRayleighModel::G4PenelopeRayleighModel(const G4ParticleDefinition*,
 61   :G4VEmModel(nam),fParticleChange(nullptr),fP <<  51                                              const G4String& nam)
 62    fLogFormFactorTable(nullptr),fPMaxTable(nul <<  52   :G4VEmModel(nam),samplingFunction_x(0),samplingFunction_xNoLog(0),
 63    fIsInitialised(false),fLocalTable(false)    <<  53    theMaterial(0),
                                                   >>  54    isInitialised(false)
 64 {                                                  55 {
 65   fIntrinsicLowEnergyLimit = 100.0*eV;             56   fIntrinsicLowEnergyLimit = 100.0*eV;
 66   fIntrinsicHighEnergyLimit = 100.0*GeV;           57   fIntrinsicHighEnergyLimit = 100.0*GeV;
 67   //  SetLowEnergyLimit(fIntrinsicLowEnergyLim <<  58   SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
 68   SetHighEnergyLimit(fIntrinsicHighEnergyLimit     59   SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
 69                                                << 
 70   if (part)                                    << 
 71     SetParticle(part);                         << 
 72                                                << 
 73   //                                               60   //
 74   fVerboseLevel= 0;                            <<  61   verboseLevel= 0;
 75   // Verbosity scale:                              62   // Verbosity scale:
 76   // 0 = nothing                               <<  63   // 0 = nothing 
 77   // 1 = warning for energy non-conservation   <<  64   // 1 = warning for energy non-conservation 
 78   // 2 = details of energy budget                  65   // 2 = details of energy budget
 79   // 3 = calculation of cross sections, file o     66   // 3 = calculation of cross sections, file openings, sampling of atoms
 80   // 4 = entering in methods                       67   // 4 = entering in methods
 81                                                    68 
 82   //build the energy grid. It is the same for  <<  69   PrepareConstants();
 83   G4double logenergy = G4Log(fIntrinsicLowEner << 
 84   G4double logmaxenergy = G4Log(1.5*fIntrinsic << 
 85   //finer grid below 160 keV                   << 
 86   G4double logtransitionenergy = G4Log(160*keV << 
 87   G4double logfactor1 = G4Log(10.)/250.;       << 
 88   G4double logfactor2 = logfactor1*10;         << 
 89   fLogEnergyGridPMax.push_back(logenergy);     << 
 90   do{                                          << 
 91     if (logenergy < logtransitionenergy)       << 
 92       logenergy += logfactor1;                 << 
 93     else                                       << 
 94       logenergy += logfactor2;                 << 
 95     fLogEnergyGridPMax.push_back(logenergy);   << 
 96   }while (logenergy < logmaxenergy);           << 
 97 }                                                  70 }
 98                                                    71 
 99 //....oooOO0OOooo........oooOO0OOooo........oo     72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
100                                                    73 
101 G4PenelopeRayleighModel::~G4PenelopeRayleighMo     74 G4PenelopeRayleighModel::~G4PenelopeRayleighModel()
102 {                                                  75 {
103   if (IsMaster() || fLocalTable)               <<  76   std::map <const G4Material*,G4DataVector*>::iterator i;
104     {                                          <<  77   for(i=SamplingTable.begin(); i != SamplingTable.end(); i++) {
105                                                <<  78     delete (*i).second;
106       for(G4int i=0; i<=fMaxZ; ++i)            <<  79   }
107   {                                            <<  80   if (samplingFunction_x) delete samplingFunction_x;
108     if(fLogAtomicCrossSection[i])              <<  81   if (samplingFunction_xNoLog) delete samplingFunction_xNoLog;
109       {                                        << 
110         delete fLogAtomicCrossSection[i];      << 
111         fLogAtomicCrossSection[i] = nullptr;   << 
112       }                                        << 
113     if(fAtomicFormFactor[i])                   << 
114       {                                        << 
115         delete fAtomicFormFactor[i];           << 
116         fAtomicFormFactor[i] = nullptr;        << 
117       }                                        << 
118   }                                            << 
119       ClearTables();                           << 
120     }                                          << 
121 }                                              << 
122                                                << 
123 //....oooOO0OOooo........oooOO0OOooo........oo << 
124 void G4PenelopeRayleighModel::ClearTables()    << 
125 {                                              << 
126    if (fLogFormFactorTable)                    << 
127      {                                         << 
128        for (auto& item : (*fLogFormFactorTable << 
129    if (item.second) delete item.second;        << 
130        delete fLogFormFactorTable;             << 
131        fLogFormFactorTable = nullptr; //zero e << 
132      }                                         << 
133    if (fPMaxTable)                             << 
134      {                                         << 
135        for (auto& item : (*fPMaxTable))        << 
136    if (item.second) delete item.second;        << 
137        delete fPMaxTable;                      << 
138        fPMaxTable = nullptr; //zero explicitly << 
139      }                                         << 
140    if (fSamplingTable)                         << 
141      {                                         << 
142        for (auto& item : (*fSamplingTable))    << 
143    if (item.second) delete item.second;        << 
144        delete fSamplingTable;                  << 
145        fSamplingTable = nullptr; //zero explic << 
146      }                                         << 
147    return;                                     << 
148 }                                                  82 }
149                                                    83 
150 //....oooOO0OOooo........oooOO0OOooo........oo     84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
151                                                    85 
152 void G4PenelopeRayleighModel::Initialise(const <<  86 void G4PenelopeRayleighModel::Initialise(const G4ParticleDefinition* ,
153            const G4DataVector& )                   87            const G4DataVector& )
154 {                                                  88 {
155   if (fVerboseLevel > 3)                       <<  89   if (verboseLevel > 3)
156     G4cout << "Calling G4PenelopeRayleighModel     90     G4cout << "Calling G4PenelopeRayleighModel::Initialise()" << G4endl;
157                                                    91 
158   SetParticle(part);                           <<  92   if (LowEnergyLimit() < fIntrinsicLowEnergyLimit)
159                                                << 
160   //Only the master model creates/fills/destro << 
161   if (IsMaster() && part == fParticle)         << 
162     {                                              93     {
163       //clear tables depending on materials, n <<  94       G4cout << "G4PenelopeRayleighModel: low energy limit increased from " << 
164       ClearTables();                           <<  95   LowEnergyLimit()/eV << " eV to " << fIntrinsicLowEnergyLimit/eV << " eV" << G4endl;
165                                                <<  96       SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
166       if (fVerboseLevel > 3)                   <<  97     }
167   G4cout << "Calling G4PenelopeRayleighModel:: <<  98   if (HighEnergyLimit() > fIntrinsicHighEnergyLimit)
168                                                <<  99     {
169       //create new tables                      << 100       G4cout << "G4PenelopeRayleighModel: high energy limit decreased from " << 
170       if (!fLogFormFactorTable)                << 101   HighEnergyLimit()/GeV << " GeV to " << fIntrinsicHighEnergyLimit/GeV << " GeV" << G4endl;
171   fLogFormFactorTable = new std::map<const G4M << 102       SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
172       if (!fPMaxTable)                         << 103     }
173   fPMaxTable = new std::map<const G4Material*, << 
174       if (!fSamplingTable)                     << 
175   fSamplingTable = new std::map<const G4Materi << 
176                                                << 
177       G4ProductionCutsTable* theCoupleTable =  << 
178   G4ProductionCutsTable::GetProductionCutsTabl << 
179                                                   104 
180       for (G4int i=0;i<(G4int)theCoupleTable-> << 105   G4cout << "Penelope Rayleigh model is initialized " << G4endl
181   {                                            << 106          << "Energy range: "
182     const G4Material* material =               << 107          << LowEnergyLimit() / keV << " keV - "
183       theCoupleTable->GetMaterialCutsCouple(i) << 108          << HighEnergyLimit() / GeV << " GeV"
184     const G4ElementVector* theElementVector =  << 109          << G4endl;
185                                                   110 
186     for (std::size_t j=0;j<material->GetNumber << 111   if(isInitialised) return;
187       {                                        << 
188         G4int iZ = theElementVector->at(j)->Ge << 
189         //read data files only in the master   << 
190         if (!fLogAtomicCrossSection[iZ])       << 
191     ReadDataFile(iZ);                          << 
192       }                                        << 
193                                                << 
194     //1) If the table has not been built for t << 
195     if (!fLogFormFactorTable->count(material)) << 
196       BuildFormFactorTable(material);          << 
197                                                << 
198     //2) retrieve or build the sampling table  << 
199     if (!(fSamplingTable->count(material)))    << 
200       InitializeSamplingAlgorithm(material);   << 
201                                                << 
202     //3) retrieve or build the pMax data       << 
203     if (!fPMaxTable->count(material))          << 
204       GetPMaxTable(material);                  << 
205   }                                            << 
206                                                   112 
207       if (fVerboseLevel > 1) {                 << 113   if(pParticleChange)
208   G4cout << "Penelope Rayleigh model v2008 is  << 114     fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
209          << "Energy range: "                   << 115   else
210          << LowEnergyLimit() / keV << " keV -  << 116     fParticleChange = new G4ParticleChangeForGamma();
211          << HighEnergyLimit() / GeV << " GeV"  << 117   isInitialised = true;
212          << G4endl;                            << 
213       }                                        << 
214     }                                          << 
215                                                << 
216   if(fIsInitialised) return;                   << 
217   fParticleChange = GetParticleChangeForGamma( << 
218   fIsInitialised = true;                       << 
219 }                                                 118 }
220                                                   119 
221 //....oooOO0OOooo........oooOO0OOooo........oo    120 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
222                                                   121 
223 void G4PenelopeRayleighModel::InitialiseLocal( << 122 G4double G4PenelopeRayleighModel::CrossSectionPerVolume(const G4Material* material,
224                  G4VEmModel *masterModel)      << 123                                            const G4ParticleDefinition* p,
                                                   >> 124                                            G4double ekin,
                                                   >> 125                                            G4double,
                                                   >> 126                                            G4double)
225 {                                                 127 {
226   if (fVerboseLevel > 3)                       << 128   // Penelope model to calculate the Rayleigh scattering inverse mean 
227     G4cout << "Calling  G4PenelopeRayleighMode << 129   // free path. 
228   //                                              130   //
229   //Check that particle matches: one might hav << 131   // The basic method is from
230   //for e+ and e-).                            << 132   //  M. Born, Atomic physics, Ed. Blackie and Sons (1969)
                                                   >> 133   // using numerical approximations developed in
                                                   >> 134   //  J. Baro' et al., Radiat. Phys. Chem. 44 (1994) 531
                                                   >> 135   // Data used for the form factor used in the calculation (numerical integral of 
                                                   >> 136   // dSigma/dOmega) are been derived by fitting the atomic forn factor tables 
                                                   >> 137   // tabulated in 
                                                   >> 138   //  J.H. Hubbel et al., J. Phys. Chem. Ref. Data 4 (1975) 471; erratum ibid. 
                                                   >> 139   //   6 (1977) 615.
                                                   >> 140   // The numerical integration of the differential cross section dSigma/dOmega, 
                                                   >> 141   // which is implemented in the DifferentialCrossSection() method, is performed 
                                                   >> 142   // by 20-point Gaussian method (managed by G4PenelopeIntegrator). 
231   //                                              143   //
232   if (part == fParticle)                       << 
233     {                                          << 
234       //Get the const table pointers from the  << 
235       const G4PenelopeRayleighModel* theModel  << 
236   static_cast<G4PenelopeRayleighModel*> (maste << 
237                                                << 
238       //Copy pointers to the data tables       << 
239       for(G4int i=0; i<=fMaxZ; ++i)            << 
240   {                                            << 
241     fLogAtomicCrossSection[i] = theModel->fLog << 
242     fAtomicFormFactor[i] = theModel->fAtomicFo << 
243   }                                            << 
244       fLogFormFactorTable = theModel->fLogForm << 
245       fPMaxTable = theModel->fPMaxTable;       << 
246       fSamplingTable = theModel->fSamplingTabl << 
247                                                << 
248       //copy the G4DataVector with the grid    << 
249       fLogQSquareGrid = theModel->fLogQSquareG << 
250                                                << 
251       //Same verbosity for all workers, as the << 
252       fVerboseLevel = theModel->fVerboseLevel; << 
253     }                                          << 
254                                                << 
255   return;                                      << 
256 }                                              << 
257                                                << 
258                                                << 
259 //....oooOO0OOooo........oooOO0OOooo........oo << 
260 namespace { G4Mutex  PenelopeRayleighModelMute << 
261 G4double G4PenelopeRayleighModel::ComputeCross << 
262                    G4double energy,            << 
263                    G4double Z,                 << 
264                    G4double,                   << 
265                    G4double,                   << 
266                    G4double)                   << 
267 {                                              << 
268   // Cross section of Rayleigh scattering in P << 
269   // tabulation, Cuellen et al. (1997), with n << 
270   // et al. J. Phys. Chem. Ref. Data 4 (1975)  << 
271                                                << 
272    if (fVerboseLevel > 3)                      << 
273     G4cout << "Calling CrossSectionPerAtom() o << 
274                                                << 
275    G4int iZ = G4int(Z);                        << 
276                                                << 
277    if (!fLogAtomicCrossSection[iZ])            << 
278      {                                         << 
279        //If we are here, it means that Initial << 
280        //not filled up. This can happen in a U << 
281        if (fVerboseLevel > 0)                  << 
282   {                                            << 
283     //Issue a G4Exception (warning) only in ve << 
284     G4ExceptionDescription ed;                 << 
285     ed << "Unable to retrieve the cross sectio << 
286     ed << "This can happen only in Unit Tests  << 
287     G4Exception("G4PenelopeRayleighModel::Comp << 
288           "em2040",JustWarning,ed);            << 
289   }                                            << 
290        //protect file reading via autolock     << 
291        G4AutoLock lock(&PenelopeRayleighModelM << 
292        ReadDataFile(iZ);                       << 
293        lock.unlock();                          << 
294      }                                         << 
295                                                << 
296    G4double cross = 0;                         << 
297    G4PhysicsFreeVector* atom = fLogAtomicCross << 
298    if (!atom)                                  << 
299      {                                         << 
300        G4ExceptionDescription ed;              << 
301        ed << "Unable to find Z=" << iZ << " in << 
302        G4Exception("G4PenelopeRayleighModel::C << 
303        "em2041",FatalException,ed);            << 
304        return 0;                               << 
305      }                                         << 
306    G4double logene = G4Log(energy);            << 
307    G4double logXS = atom->Value(logene);       << 
308    cross = G4Exp(logXS);                       << 
309                                                   144 
310    if (fVerboseLevel > 2)                      << 145   if (verboseLevel > 3)
311      {                                         << 146     G4cout << "Calling CrossSectionPerVolume() of G4PenelopeRayleighModel" << G4endl;
312        G4cout << "Rayleigh cross section at "  << 147   SetupForMaterial(p, material, ekin);
313    " = " << cross/barn << " barn" << G4endl;   << 148   
314      }                                         << 149   //Assign local variable "material" to private member "theMaterial", because 
315    return cross;                               << 150   //this information is necessary to calculate the cross section
316 }                                              << 151   theMaterial = material;
317                                                   152 
318                                                << 153   G4int nElements = material->GetNumberOfElements();
319 //....oooOO0OOooo........oooOO0OOooo........oo << 
320 void G4PenelopeRayleighModel::BuildFormFactorT << 
321 {                                              << 
322   /*                                           << 
323     1) get composition and equivalent molecula << 
324   */                                           << 
325   std::size_t nElements = material->GetNumberO << 
326   const G4ElementVector* elementVector = mater    154   const G4ElementVector* elementVector = material->GetElementVector();
327   const G4double* fractionVector = material->G << 
328                                                   155 
329   std::vector<G4double> *StechiometricFactors  << 156   G4int maxZ=0;
330   for (std::size_t i=0;i<nElements;++i)        << 157   for (G4int i=0; i<nElements; i++) 
331     {                                          << 
332       G4double fraction = fractionVector[i];   << 
333       G4double atomicWeigth = (*elementVector) << 
334       StechiometricFactors->push_back(fraction << 
335     }                                          << 
336   //Find max                                   << 
337   G4double MaxStechiometricFactor = 0.;        << 
338   for (std::size_t i=0;i<nElements;++i)        << 
339     {                                             158     {
340       if ((*StechiometricFactors)[i] > MaxStec << 159       G4int Z = (G4int) (*elementVector)[i]->GetZ();
341         MaxStechiometricFactor = (*Stechiometr << 160       if (Z>maxZ)
                                                   >> 161   maxZ = Z;
342     }                                             162     }
343   if (MaxStechiometricFactor<1e-16)            << 163       
                                                   >> 164   G4double ec=std::min(ekin,0.5*maxZ);
                                                   >> 165   factorE = 849.3315*(ec/electron_mass_c2)*(ec/electron_mass_c2);
                                                   >> 166   G4double cs=0;
                                                   >> 167   //
                                                   >> 168   //Integrate the Differential Cross Section dSigma/dCosTheta between -1 and 1.
                                                   >> 169   //
                                                   >> 170   G4PenelopeIntegrator<G4PenelopeRayleighModel,G4double(G4PenelopeRayleighModel::*)(G4double)> 
                                                   >> 171     theIntegrator;
                                                   >> 172   cs =
                                                   >> 173     theIntegrator.Calculate(this,&G4PenelopeRayleighModel::DifferentialCrossSection,
                                                   >> 174           -1.0,0.90,1e-06);
                                                   >> 175   cs += theIntegrator.Calculate(this,&G4PenelopeRayleighModel::DifferentialCrossSection,
                                                   >> 176         0.90,0.9999999,1e-06);
                                                   >> 177   cs = cs*(ec/ekin)*(ec/ekin)*pi*classic_electr_radius*classic_electr_radius;
                                                   >> 178   //
                                                   >> 179   // Here cs represents the cross section per molecule for materials defined with chemical 
                                                   >> 180   // formulas and the average cross section per atom in compounds (defined with the mass 
                                                   >> 181   // fraction)
                                                   >> 182   //
                                                   >> 183   const G4int* stechiometric = material->GetAtomsVector();
                                                   >> 184   //This is the total density of atoms in the material
                                                   >> 185   G4double atomDensity = material->GetTotNbOfAtomsPerVolume();
                                                   >> 186   G4double moleculeDensity = 0;
                                                   >> 187 
                                                   >> 188   //Default case: the material is a compound. In this case, cs is the average cross section 
                                                   >> 189   // _per_atom_ and one has to multiply for the atom density.
                                                   >> 190   G4double cross = atomDensity*cs;
                                                   >> 191   G4bool isAMolecule = false;
                                                   >> 192   
                                                   >> 193   //Alternative case: the material is a molecule. In this case cs is the cross section 
                                                   >> 194   // _per_molecule_ and one has to multiply for the molecule density
                                                   >> 195   if (stechiometric)
344     {                                             196     {
345       G4ExceptionDescription ed;               << 197       //Calculate the total number of atoms per molecule
346       ed << "Inconsistent data of atomic compo << 198       G4int atomsPerMolecule = 0;
347   material->GetName() << G4endl;               << 199       for (G4int k=0;k<nElements;k++)
348       G4Exception("G4PenelopeRayleighModel::Bu << 200   atomsPerMolecule += stechiometric[k];
349       "em2042",FatalException,ed);             << 201       if (atomsPerMolecule)
                                                   >> 202   {
                                                   >> 203     isAMolecule = true;
                                                   >> 204     if (verboseLevel > 3)
                                                   >> 205       {
                                                   >> 206         G4cout << "Material " << material->GetName() << " is a molecule composed by " << 
                                                   >> 207     atomsPerMolecule << " atoms" << G4endl;
                                                   >> 208       }
                                                   >> 209     moleculeDensity = atomDensity/((G4double) atomsPerMolecule);
                                                   >> 210     cross = cs*moleculeDensity;
                                                   >> 211   }
350     }                                             212     }
351   //Normalize                                  << 
352   for (std::size_t i=0;i<nElements;++i)        << 
353     (*StechiometricFactors)[i] /=  MaxStechiom << 
354                                                << 
355   /*                                           << 
356     CREATE THE FORM FACTOR TABLE               << 
357   */                                           << 
358   G4PhysicsFreeVector* theFFVec = new G4Physic << 
359                                                   213 
360   for (std::size_t k=0;k<fLogQSquareGrid.size( << 214   if (verboseLevel > 2)
361     {                                             215     {
362       G4double ff2 = 0; //squared form factor  << 216       if (isAMolecule)
363       for (std::size_t i=0;i<nElements;++i)    << 
364   {                                               217   {
365     G4int iZ = (*elementVector)[i]->GetZasInt( << 218     G4cout << "Rayleigh cross section at " << ekin/keV << " keV for material " << 
366     G4PhysicsFreeVector* theAtomVec = fAtomicF << 219       material->GetName() << " (molecule) = " << cs/barn << " barn/molecule." << G4endl;
367     G4double f = (*theAtomVec)[k]; //the q-gri << 220     G4cout << "Mean free path: " << (1./cross)/mm << " mm" << G4endl;
368     ff2 += f*f*(*StechiometricFactors)[i];     << 221   }
                                                   >> 222       else
                                                   >> 223   {
                                                   >> 224     G4cout << "Rayleigh cross section at " << ekin/keV << " keV for material " << 
                                                   >> 225       material->GetName() << " (compound) = " << cs/barn << " barn/atom." << G4endl;
                                                   >> 226     G4cout << "Mean free path: " << (1./cross)/mm << " mm" << G4endl;
369   }                                               227   }
370       if (ff2)                                 << 
371   theFFVec->PutValue(k,fLogQSquareGrid[k],G4Lo << 
372     }                                             228     }
373   theFFVec->FillSecondDerivatives(); //vector  << 229   return cross;
374   fLogFormFactorTable->insert(std::make_pair(m << 
375                                                << 
376   delete StechiometricFactors;                 << 
377   return;                                      << 
378 }                                                 230 }
379                                                   231 
380 //....oooOO0OOooo........oooOO0OOooo........oo    232 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
381                                                   233 
382 void G4PenelopeRayleighModel::SampleSecondarie    234 void G4PenelopeRayleighModel::SampleSecondaries(std::vector<G4DynamicParticle*>* ,
383             const G4MaterialCutsCouple* couple << 235                 const G4MaterialCutsCouple* couple,
384             const G4DynamicParticle* aDynamicG << 236                 const G4DynamicParticle* aDynamicGamma,
385             G4double,                          << 237                 G4double,
386             G4double)                          << 238                 G4double)
387 {                                                 239 {
388   // Sampling of the Rayleigh final state (nam << 240   // Penelope model to sample the Rayleigh scattering final state.
389   // from the Penelope2008 model. The scatteri << 241   //
390   // cross section dOmega/d(cosTheta) from Bor << 242   // The angular deflection of the scattered photon is sampled according to the 
391   // anomalous scattering effects. The Form Fa << 243   // differential cross section dSigma/dOmega used for the numerical integration, 
392   // analytical cross section is retrieved via << 244   // and implemented in the DifferentialCrossSection() method. See comments in 
393   // are tabulated for F(Q). Form factor for c << 245   // method CrossSectionPerVolume() for more details on the original references 
394   // the additivity rule. The sampling from th << 246   // of the model.
395   // Transform with Aliasing (RITA) algorithm; << 247   //
396   // for each material and managed by G4Penelo << 
397   // The sampling algorithm (rejection method) << 
398   // increases with energy. For E=100 keV the  << 
399   // hydrogen and uranium, respectively.       << 
400                                                   248 
401   if (fVerboseLevel > 3)                       << 249   if (verboseLevel > 3)
402     G4cout << "Calling SamplingSecondaries() o    250     G4cout << "Calling SamplingSecondaries() of G4PenelopeRayleighModel" << G4endl;
403                                                << 251                                                                                                     
404   G4double photonEnergy0 = aDynamicGamma->GetK    252   G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
405                                                << 253  
406   if (photonEnergy0 <= fIntrinsicLowEnergyLimi << 254   if (photonEnergy0 <= LowEnergyLimit())
407     {                                          << 255   {
408       fParticleChange->ProposeTrackStatus(fSto    256       fParticleChange->ProposeTrackStatus(fStopAndKill);
409       fParticleChange->SetProposedKineticEnerg    257       fParticleChange->SetProposedKineticEnergy(0.);
410       fParticleChange->ProposeLocalEnergyDepos    258       fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
411       return ;                                    259       return ;
412     }                                          << 260   }
413                                                   261 
414   G4ParticleMomentum photonDirection0 = aDynam    262   G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
415                                                << 263    
416   const G4Material* theMat = couple->GetMateri << 264   // Sampling inizialitation (build internal table)
417                                                << 265   theMaterial = couple->GetMaterial();
418   //1) Verify if tables are ready              << 266   InitialiseSampling();
419   //Either Initialize() was not called, or we  << 267 
420   //not invoked                                << 268   G4DataVector* samplingFunction_y = SamplingTable.find(theMaterial)->second;
421   if (!fPMaxTable || !fSamplingTable || !fLogF << 269 
422     {                                          << 270    // Sample the angle of the scattered photon
423       //create a **thread-local** version of t << 271   G4double x2max = 2.0*std::log(41.2148*photonEnergy0/electron_mass_c2);
424       //Unit Tests                             << 272   G4int jm=0;
425       fLocalTable = true;                      << 273   G4int asize = samplingFunction_x->size();
426       if (!fLogFormFactorTable)                << 274   if (x2max < (*samplingFunction_x)[1]) 
427   fLogFormFactorTable = new std::map<const G4M << 275     jm=0;
428       if (!fPMaxTable)                         << 276   else if(x2max>(*samplingFunction_x)[asize-2])
429   fPMaxTable = new std::map<const G4Material*, << 277     jm=asize-2;
430       if (!fSamplingTable)                     << 278   else 
431   fSamplingTable = new std::map<const G4Materi << 279     {
432     }                                          << 280       //spacing in the logTable
433                                                << 281       G4double logScalingFactor = (*samplingFunction_x)[1]-(*samplingFunction_x)[0];
434   if (!fSamplingTable->count(theMat))          << 282       jm=(G4int) ((x2max-(*samplingFunction_x)[0])/logScalingFactor);
435     {                                          << 283     }
436       //If we are here, it means that Initiali << 284 
437       //not filled up. This can happen in a Un << 285   G4double rumax = (*samplingFunction_y)[jm]+((*samplingFunction_y)[jm+1]-(*samplingFunction_y)[jm])*
438       if (fVerboseLevel > 0)                   << 286     (x2max-(*samplingFunction_x)[jm])/((*samplingFunction_x)[jm+1]-(*samplingFunction_x)[jm]); 
439   {                                            << 287   G4double cosTheta=0;
440     //Issue a G4Exception (warning) only in ve << 288   G4double rejectionValue = 0;
441     G4ExceptionDescription ed;                 << 289   do{
442     ed << "Unable to find the fSamplingTable d << 290     G4double ru = rumax + std::log(G4UniformRand());
443       theMat->GetName() << G4endl;             << 291     G4int j=0;
444     ed << "This can happen only in Unit Tests" << 292     G4int ju=jm+1;
445     G4Exception("G4PenelopeRayleighModel::Samp << 293     do{
446           "em2019",JustWarning,ed);            << 294       G4int jt=(j+ju)/2; //bipartition
447   }                                            << 295       if (ru > (*samplingFunction_y)[jt])
448       const G4ElementVector* theElementVector  << 296   j=jt;
449       //protect file reading via autolock      << 297       else
450       G4AutoLock lock(&PenelopeRayleighModelMu << 298   ju=jt;
451       for (std::size_t j=0;j<theMat->GetNumber << 299     }while ((ju-j)>1);
452   {                                            << 300     G4double x2rat = 0;
453     G4int iZ = theElementVector->at(j)->GetZas << 301     G4double denomin = (*samplingFunction_y)[j+1]-(*samplingFunction_y)[j];
454     if (!fLogAtomicCrossSection[iZ])           << 302     if (denomin > 1e-12) 
455       {                                        << 303      {
456         lock.lock();                           << 304        x2rat = (*samplingFunction_x)[j]+(((*samplingFunction_x)[j+1]-(*samplingFunction_x)[j])*
457         ReadDataFile(iZ);                      << 305            (ru-(*samplingFunction_y)[j])/denomin)-x2max;
458         lock.unlock();                         << 306      }
459       }                                        << 307     else
460   }                                            << 308      {
461       lock.lock();                             << 309        x2rat = (*samplingFunction_x)[j]-x2max;
462       //1) If the table has not been built for << 310      }
463       if (!fLogFormFactorTable->count(theMat)) << 311     cosTheta = 1.0-2.0*std::exp(x2rat);
464   BuildFormFactorTable(theMat);                << 312     rejectionValue = 0.5*(1.0+cosTheta*cosTheta);
465                                                << 313    }while (G4UniformRand() > rejectionValue);
466       //2) retrieve or build the sampling tabl << 
467       if (!(fSamplingTable->count(theMat)))    << 
468   InitializeSamplingAlgorithm(theMat);         << 
469                                                << 
470       //3) retrieve or build the pMax data     << 
471       if (!fPMaxTable->count(theMat))          << 
472   GetPMaxTable(theMat);                        << 
473       lock.unlock();                           << 
474     }                                          << 
475                                                << 
476   //Ok, restart the job                        << 
477   G4PenelopeSamplingData* theDataTable = fSamp << 
478   G4PhysicsFreeVector* thePMax = fPMaxTable->f << 
479                                                << 
480   G4double cosTheta = 1.0;                     << 
481                                                << 
482   //OK, ready to go!                           << 
483   G4double qmax = 2.0*photonEnergy0/electron_m << 
484                                                << 
485   if (qmax < 1e-10) //very low momentum transf << 
486     {                                          << 
487       G4bool loopAgain=false;                  << 
488       do                                       << 
489   {                                            << 
490     loopAgain = false;                         << 
491     cosTheta = 1.0-2.0*G4UniformRand();        << 
492     G4double G = 0.5*(1+cosTheta*cosTheta);    << 
493     if (G4UniformRand()>G)                     << 
494       loopAgain = true;                        << 
495   }while(loopAgain);                           << 
496     }                                          << 
497   else //larger momentum transfer              << 
498     {                                          << 
499       std::size_t nData = theDataTable->GetNum << 
500       G4double LastQ2inTheTable = theDataTable << 
501       G4double q2max = std::min(qmax*qmax,Last << 
502                                                << 
503       G4bool loopAgain = false;                << 
504       G4double MaxPValue = thePMax->Value(phot << 
505       G4double xx=0;                           << 
506                                                << 
507       //Sampling by rejection method. The reje << 
508       //G = 0.5*(1+cos^2(theta))               << 
509       //                                       << 
510       do{                                      << 
511   loopAgain = false;                           << 
512   G4double RandomMax = G4UniformRand()*MaxPVal << 
513   xx = theDataTable->SampleValue(RandomMax);   << 
514   //xx is a random value of q^2 in (0,q2max),s << 
515   //F(Q^2) via the RITA algorithm              << 
516   if (xx > q2max)                              << 
517     loopAgain = true;                          << 
518   cosTheta = 1.0-2.0*xx/q2max;                 << 
519   G4double G = 0.5*(1+cosTheta*cosTheta);      << 
520   if (G4UniformRand()>G)                       << 
521     loopAgain = true;                          << 
522       }while(loopAgain);                       << 
523     }                                          << 
524                                                   314 
525   G4double sinTheta = std::sqrt(1-cosTheta*cos    315   G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
526                                                << 316  
527   // Scattered photon angles. ( Z - axis along    317   // Scattered photon angles. ( Z - axis along the parent photon)
528   G4double phi = twopi * G4UniformRand() ;        318   G4double phi = twopi * G4UniformRand() ;
529   G4double dirX = sinTheta*std::cos(phi);         319   G4double dirX = sinTheta*std::cos(phi);
530   G4double dirY = sinTheta*std::sin(phi);         320   G4double dirY = sinTheta*std::sin(phi);
531   G4double dirZ = cosTheta;                       321   G4double dirZ = cosTheta;
532                                                << 322   
533   // Update G4VParticleChange for the scattere << 323   // Update G4VParticleChange for the scattered photon 
534   G4ThreeVector photonDirection1(dirX, dirY, d    324   G4ThreeVector photonDirection1(dirX, dirY, dirZ);
535                                                   325 
536   photonDirection1.rotateUz(photonDirection0);    326   photonDirection1.rotateUz(photonDirection0);
537   fParticleChange->ProposeMomentumDirection(ph    327   fParticleChange->ProposeMomentumDirection(photonDirection1) ;
538   fParticleChange->SetProposedKineticEnergy(ph    328   fParticleChange->SetProposedKineticEnergy(photonEnergy0) ;
539                                                << 329    
540   return;                                         330   return;
541 }                                                 331 }
542                                                   332 
543                                                << 
544 //....oooOO0OOooo........oooOO0OOooo........oo    333 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
545                                                   334 
546 void G4PenelopeRayleighModel::ReadDataFile(con << 335 G4double G4PenelopeRayleighModel::DifferentialCrossSection(G4double cosTheta)
547 {                                                 336 {
548   if (fVerboseLevel > 2)                       << 337   //Differential cross section for Rayleigh scattering
549     {                                          << 338   G4double x2 = factorE*(1-cosTheta);
550       G4cout << "G4PenelopeRayleighModel::Read << 339   G4double gradx = (1+cosTheta*cosTheta)*MolecularFormFactor(x2);
551       G4cout << "Going to read Rayleigh data f << 340   return gradx;
552     }                                          << 341 }
553     const char* path = G4FindDataDir("G4LEDATA << 342 
554     if(!path)                                  << 343 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
555     {                                          << 344 
556       G4String excep = "G4LEDATA environment v << 345 G4double G4PenelopeRayleighModel::MolecularFormFactor(G4double x2)
557       G4Exception("G4PenelopeRayleighModel::Re << 346 {
558       "em0006",FatalException,excep);          << 347   //Squared molecular form factor (additivity rule)
559       return;                                  << 348   const G4int ntot=95;
560     }                                          << 349   G4double RA1[ntot] = {0.0e0, 3.9265e+0, 4.3100e+1, 5.2757e+1, 2.5021e+1,
561                                                << 350           1.2211e+1, 9.3229e+0, 3.2455e+0, 2.4197e+0, 1.5985e+0,
562   /*                                           << 351           3.0926e+1, 1.5315e+1, 7.7061e+0, 3.9493e+0, 2.2042e+0,
563     Read first the cross section file          << 352           1.9453e+1, 1.9354e+1, 8.0374e+0, 8.3779e+1, 5.7370e+1,
564   */                                           << 353           5.2310e+1, 4.7514e+1, 4.3785e+1, 4.2048e+1, 3.6972e+1,
565   std::ostringstream ost;                      << 354           3.3849e+1, 3.1609e+1, 2.8763e+1, 2.7217e+1, 2.4263e+1,
566   if (Z>9)                                     << 355           2.2403e+1, 1.8606e+1, 1.5143e+1, 1.4226e+1, 1.1792e+1,
567     ost << path << "/penelope/rayleigh/pdgra"  << 356           9.7574e+0, 1.2796e+1, 1.2854e+1, 1.2368e+1, 1.0208e+1,
568   else                                         << 357           8.2823e+0, 7.4677e+0, 7.6028e+0, 6.1090e+0, 5.5346e+0,
569     ost << path << "/penelope/rayleigh/pdgra0" << 358           4.2340e+0, 4.0444e+0, 4.2905e+0, 4.7950e+0, 5.1112e+0,
570   std::ifstream file(ost.str().c_str());       << 359           5.2407e+0, 5.2153e+0, 5.1639e+0, 4.8814e+0, 5.8054e+0,
571   if (!file.is_open())                         << 360           6.6724e+0, 6.5104e+0, 6.3364e+0, 6.2889e+0, 6.3028e+0,
572     {                                          << 361           6.3853e+0, 6.3475e+0, 6.5779e+0, 6.8486e+0, 7.0993e+0,
573       G4String excep = "Data file " + G4String << 362           7.6122e+0, 7.9681e+0, 8.3481e+0, 6.3875e+0, 8.0042e+0,
574       G4Exception("G4PenelopeRayleighModel::Re << 363           8.0820e+0, 7.6940e+0, 7.1927e+0, 6.6751e+0, 6.1623e+0,
575       "em0003",FatalException,excep);          << 364           5.8335e+0, 5.5599e+0, 4.6551e+0, 4.4327e+0, 4.7601e+0,
576     }                                          << 365           5.2872e+0, 5.6084e+0, 5.7680e+0, 5.8041e+0, 5.7566e+0,
577   G4int readZ =0;                              << 366           5.6541e+0, 6.3932e+0, 6.9313e+0, 7.0027e+0, 6.8796e+0,
578   std::size_t nPoints= 0;                      << 367           6.4739e+0, 6.2405e+0, 6.0081e+0, 5.5708e+0, 5.3680e+0};
579   file >> readZ >> nPoints;                    << 368 
580   //check the right file is opened.            << 369 
581   if (readZ != Z || nPoints <= 0 || nPoints >= << 370   G4double  RA2[ntot] = {0.0e0, 1.3426e-1, 9.4875e+1,-1.0896e+2,-4.5494e+1,
582     {                                          << 371            -1.9572e+1,-1.2382e+1,-3.6827e+0,-2.4542e+0,-1.4453e+0,
583       G4ExceptionDescription ed;               << 372            1.3401e+2, 7.9717e+1, 6.2164e+1, 4.0300e+1, 3.1682e+1,
584       ed << "Corrupted data file for Z=" << Z  << 373            -1.3639e+1,-1.5950e+1,-5.1523e+0, 1.8351e+2, 1.2205e+2,
585       G4Exception("G4PenelopeRayleighModel::Re << 374            1.0007e+2, 8.5632e+1, 7.9145e+1, 6.3675e+1, 6.2954e+1,
586       "em0005",FatalException,ed);             << 375            5.6601e+1, 5.4171e+1, 4.8752e+1, 3.8062e+1, 3.9933e+1,
587       return;                                  << 376            4.8343e+1, 4.2137e+1, 3.4617e+1, 2.9430e+1, 2.4010e+1,
588     }                                          << 377            1.9744e+1, 4.0009e+1, 5.1614e+1, 5.0456e+1, 3.9088e+1,
589                                                << 378            2.6824e+1, 2.2953e+1, 2.4773e+1, 1.6893e+1, 1.4548e+1,
590   fLogAtomicCrossSection[Z] = new G4PhysicsFre << 379            9.7226e+0, 1.0192e+1, 1.1153e+1, 1.3188e+1, 1.4733e+1,
591   G4double ene=0,f1=0,f2=0,xs=0;               << 380            1.5644e+1, 1.5939e+1, 1.5923e+1, 1.5254e+1, 2.0748e+1,
592   for (std::size_t i=0;i<nPoints;++i)          << 381            2.6901e+1, 2.7032e+1, 2.4938e+1, 2.1528e+1, 2.0362e+1,
593     {                                          << 382            1.9474e+1, 1.8238e+1, 1.7898e+1, 1.9174e+1, 1.9023e+1,
594       file >> ene >> f1 >> f2 >> xs;           << 383            1.8194e+1, 1.8504e+1, 1.8955e+1, 1.4276e+1, 1.7558e+1,
595       //dimensional quantities                 << 384            1.8651e+1, 1.7984e+1, 1.6793e+1, 1.5469e+1, 1.4143e+1,
596       ene *= eV;                               << 385            1.3149e+1, 1.2255e+1, 9.2352e+0, 8.6067e+0, 9.7460e+0,
597       xs *= cm2;                               << 386            1.1749e+1, 1.3281e+1, 1.4326e+1, 1.4920e+1, 1.5157e+1,
598       fLogAtomicCrossSection[Z]->PutValue(i,G4 << 387            1.5131e+1, 1.9489e+1, 2.3649e+1, 2.4686e+1, 2.4760e+1,
599       if (file.eof() && i != (nPoints-1)) //fi << 388            2.1519e+1, 2.0099e+1, 1.8746e+1, 1.5943e+1, 1.4880e+1};
600   {                                            << 389 
601     G4ExceptionDescription ed ;                << 390   G4double RA3[ntot] =  {0.0e0, 2.2648e+0, 1.0579e+3, 8.6177e+2, 2.4422e+2,
602     ed << "Corrupted data file for Z=" << Z << << 391            7.8788e+1, 3.8293e+1, 1.2564e+1, 6.9091e+0, 3.7926e+0,
603     ed << "Found less than " << nPoints << "en << 392            0.0000e+0, 0.0000e+0, 1.6759e-9, 1.3026e+1, 3.0569e+0,
604     G4Exception("G4PenelopeRayleighModel::Read << 393            1.5521e+2, 1.2815e+2, 4.7378e+1, 9.2802e+2, 4.7508e+2,
605           "em0005",FatalException,ed);         << 394            3.6612e+2, 2.7582e+2, 2.1008e+2, 1.5903e+2, 1.2322e+2,
606   }                                            << 395            9.2898e+1, 7.1345e+1, 5.1651e+1, 3.8474e+1, 2.7410e+1,
607     }                                          << 396            1.9126e+1, 1.0889e+1, 5.3479e+0, 8.2223e+0, 5.0837e+0,
608   file.close();                                << 397            2.8905e+0, 2.7457e+0, 6.7082e-1, 0.0000e+0, 0.0000e+0,
609                                                << 398            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
610   /*                                           << 399            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
611     Then read the form factor file             << 400            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
612   */                                           << 401            0.0000e+0, 0.0000e+0, 0.0000e+0, 1.7264e-1, 2.7322e-1,
613   std::ostringstream ost2;                     << 402            3.9444e-1, 4.5648e-1, 6.2286e-1, 7.2468e-1, 8.4296e-1,
614   if (Z>9)                                     << 403            1.1698e+0, 1.2994e+0, 1.4295e+0, 0.0000e+0, 8.1570e-1,
615     ost2 << path << "/penelope/rayleigh/pdaff" << 404            6.9349e-1, 4.9536e-1, 3.1211e-1, 1.5931e-1, 2.9512e-2,
616   else                                         << 405            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
617     ost2 << path << "/penelope/rayleigh/pdaff0 << 406            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
618   file.open(ost2.str().c_str());               << 407            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
619   if (!file.is_open())                         << 408            0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0};
620     {                                          << 409 
621       G4String excep = "Data file " + G4String << 410  G4double RA4[ntot] =  {1.1055e1,6.3519e0,4.7367e+1, 3.9402e+1, 2.2896e+1,
622       G4Exception("G4PenelopeRayleighModel::Re << 411           1.3979e+1, 1.0766e+1, 6.5252e+0, 5.1631e+0, 4.0524e+0,
623       "em0003",FatalException,excep);          << 412           2.7145e+1, 1.8724e+1, 1.4782e+1, 1.1608e+1, 9.7750e+0,
624     }                                          << 413           1.6170e+1, 1.5249e+1, 9.1916e+0, 5.4499e+1, 4.1381e+1,
625   file >> readZ >> nPoints;                    << 414           3.7395e+1, 3.3815e+1, 3.1135e+1, 2.8273e+1, 2.6140e+1,
626   //check the right file is opened.            << 415           2.3948e+1, 2.2406e+1, 2.0484e+1, 1.8453e+1, 1.7386e+1,
627   if (readZ != Z || nPoints <= 0 || nPoints >= << 416           1.7301e+1, 1.5388e+1, 1.3411e+1, 1.2668e+1, 1.1133e+1,
628     {                                          << 417           9.8081e+0, 1.3031e+1, 1.4143e+1, 1.3815e+1, 1.2077e+1,
629       G4ExceptionDescription ed;               << 418           1.0033e+1, 9.2549e+0, 9.5338e+0, 7.9076e+0, 7.3263e+0,
630       ed << "Corrupted data file for Z=" << Z  << 419           5.9996e+0, 6.0087e+0, 6.2660e+0, 6.7914e+0, 7.1501e+0,
631       G4Exception("G4PenelopeRayleighModel::Re << 420           7.3367e+0, 7.3729e+0, 7.3508e+0, 7.1465e+0, 8.2731e+0,
632       "em0005",FatalException,ed);             << 421           9.3745e+0, 9.3508e+0, 8.9897e+0, 8.4566e+0, 8.2690e+0,
633       return;                                  << 422           8.1398e+0, 7.9183e+0, 7.9123e+0, 8.1677e+0, 8.1871e+0,
634     }                                          << 423           8.1766e+0, 8.2881e+0, 8.4227e+0, 7.0273e+0, 8.0002e+0,
635   fAtomicFormFactor[Z] = new G4PhysicsFreeVect << 424           8.1440e+0, 7.9104e+0, 7.5685e+0, 7.1970e+0, 6.8184e+0,
636   G4double q=0,ff=0,incoh=0;                   << 425           6.5469e+0, 6.3056e+0, 5.4844e+0, 5.2832e+0, 5.5889e+0,
637   G4bool fillQGrid = false;                    << 426           6.0919e+0, 6.4340e+0, 6.6426e+0, 6.7428e+0, 6.7636e+0,
638   //fill this vector only the first time.      << 427           6.7281e+0, 7.5729e+0, 8.2808e+0, 8.4400e+0, 8.4220e+0,
639   if (!fLogQSquareGrid.size())                 << 428           7.8662e+0, 7.5993e+0, 7.3353e+0, 6.7829e+0, 6.5520e+0};
640     fillQGrid = true;                          << 429 
641   for (std::size_t i=0;i<nPoints;++i)          << 430   G4double RA5[ntot] = {0.0e0, 4.9828e+0, 5.5674e+1, 3.0902e+1, 1.1496e+1,
642     {                                          << 431           4.8936e+0, 2.5506e+0, 1.2236e+0, 7.4698e-1, 4.7042e-1,
643       file >> q >> ff >> incoh;                << 432           4.7809e+0, 4.6315e+0, 4.3677e+0, 4.9269e+0, 2.6033e+0,
644       //q and ff are dimensionless (q is in un << 433           9.6229e+0, 7.2592e+0, 4.1634e+0, 1.3999e+1, 8.6975e+0,
645       fAtomicFormFactor[Z]->PutValue(i,q,ff);  << 434           6.9630e+0, 5.4681e+0, 4.2653e+0, 3.2848e+0, 2.7354e+0,
646       if (fillQGrid)                           << 435           2.1617e+0, 1.7030e+0, 1.2826e+0, 9.7080e-1, 7.2227e-1,
647   {                                            << 436           5.0874e-1, 3.1402e-1, 1.6360e-1, 3.2918e-1, 2.3570e-1,
648     fLogQSquareGrid.push_back(2.0*G4Log(q));   << 437           1.5868e-1, 1.5146e-1, 9.7662e-2, 7.3151e-2, 6.4206e-2,
649   }                                            << 438           4.8945e-2, 4.3189e-2, 4.4368e-2, 3.3976e-2, 3.0466e-2,
650       if (file.eof() && i != (nPoints-1)) //fi << 439           2.4477e-2, 3.7202e-2, 3.7093e-2, 3.8161e-2, 3.8576e-2,
651   {                                            << 440           3.8403e-2, 3.7806e-2, 3.4958e-2, 3.6029e-2, 4.3087e-2,
652     G4ExceptionDescription ed;                 << 441           4.7069e-2, 4.6452e-2, 4.2486e-2, 4.1517e-2, 4.1691e-2,
653     ed << "Corrupted data file for Z=" << Z << << 442           4.2813e-2, 4.2294e-2, 4.5287e-2, 4.8462e-2, 4.9726e-2,
654     ed << "Found less than " << nPoints << "en << 443           5.5097e-2, 5.6568e-2, 5.8069e-2, 1.2270e-2, 3.8006e-2,
655     G4Exception("G4PenelopeRayleighModel::Read << 444           3.5048e-2, 3.0050e-2, 2.5069e-2, 2.0485e-2, 1.6151e-2,
656           "em0005",FatalException,ed);         << 445           1.4631e-2, 1.4034e-2, 1.1978e-2, 1.1522e-2, 1.2375e-2,
657   }                                            << 446           1.3805e-2, 1.4954e-2, 1.5832e-2, 1.6467e-2, 1.6896e-2,
658     }                                          << 447           1.7166e-2, 1.9954e-2, 2.2497e-2, 2.1942e-2, 2.1965e-2,
659   file.close();                                << 448           2.0005e-2, 1.8927e-2, 1.8167e-2, 1.6314e-2, 1.5522e-2};
660   return;                                      << 449 
661 }                                              << 450   G4double x=std::sqrt(x2);
662                                                << 451   G4double gradx1=0.0;
663 //....oooOO0OOooo........oooOO0OOooo........oo << 452 
664                                                << 453   G4int nElements = theMaterial->GetNumberOfElements();
665 G4double G4PenelopeRayleighModel::GetFSquared( << 454   const G4ElementVector* elementVector = theMaterial->GetElementVector();
666 {                                              << 455   const G4int* stechiometric = theMaterial->GetAtomsVector();
667   G4double f2 = 0;                             << 456   const G4double* vector_of_atoms = theMaterial->GetVecNbOfAtomsPerVolume();
668   //Input value QSquared could be zero: protec << 457   const G4double tot_atoms = theMaterial->GetTotNbOfAtomsPerVolume();
669   //the FPE exception                          << 458   for (G4int i=0;i<nElements;i++)
670   //If Q<1e-10, set Q to 1e-10                 << 459     {
671   G4double logQSquared = (QSquared>1e-10) ? G4 << 460       G4int Z = (G4int) (*elementVector)[i]->GetZ();
672   //last value of the table                    << 461       if (Z>ntot) Z=95;
673   G4double maxlogQ2 = fLogQSquareGrid[fLogQSqu << 462       G4double denomin = 1.+x2*(RA4[Z-1]+x2*RA5[Z-1]);
674                                                << 463       G4double fa=Z*(1+x2*(RA1[Z-1]+x*(RA2[Z-1]+x*RA3[Z-1])))/(denomin*denomin);
675   //now it should  be all right                << 464       if (Z>10 && fa>2.0)
676   G4PhysicsFreeVector* theVec = fLogFormFactor << 465   {
677                                                << 466     G4double k1=0.3125;
678   if (!theVec)                                 << 467     G4double k2=2.426311e-02;
679     {                                          << 468     G4double Pa=(Z-k1)*fine_structure_const;
680       G4ExceptionDescription ed;               << 469     G4double Pg=std::sqrt(1-(Pa*Pa));
681       ed << "Unable to retrieve F squared tabl << 470     G4double Pq=k2*x/Pa;
682       G4Exception("G4PenelopeRayleighModel::Ge << 471     G4double fb=std::sin(2.0*Pg*std::atan(Pq))/(Pg*Pq*std::pow((1+Pq*Pq),Pg));
683       "em2046",FatalException,ed);             << 472     fa=std::max(fa,fb);
684       return 0;                                << 
685     }                                          << 
686   if (logQSquared < -20) // Q < 1e-9           << 
687     {                                          << 
688       G4double logf2 = (*theVec)[0]; //first v << 
689       f2 = G4Exp(logf2);                       << 
690     }                                          << 
691   else if (logQSquared > maxlogQ2)             << 
692     f2 =0;                                     << 
693   else                                         << 
694     {                                          << 
695       //log(Q^2) vs. log(F^2)                  << 
696       G4double logf2 = theVec->Value(logQSquar << 
697       f2 = G4Exp(logf2);                       << 
698                                                << 
699     }                                          << 
700   if (fVerboseLevel > 3)                       << 
701     {                                          << 
702       G4cout << "G4PenelopeRayleighModel::GetF << 
703       G4cout << "Q^2 = " <<  QSquared << " (un << 
704     }                                          << 
705   return f2;                                   << 
706 }                                              << 
707                                                << 
708 //....oooOO0OOooo........oooOO0OOooo........oo << 
709                                                << 
710 void G4PenelopeRayleighModel::InitializeSampli << 
711 {                                              << 
712   G4double q2min = 0;                          << 
713   G4double q2max = 0;                          << 
714   const std::size_t np = 150; //hard-coded in  << 
715   //G4cout << "Init N= " << fLogQSquareGrid.si << 
716   for (std::size_t i=1;i<fLogQSquareGrid.size( << 
717     {                                          << 
718       G4double Q2 = G4Exp(fLogQSquareGrid[i]); << 
719       if (GetFSquared(mat,Q2) >  1e-35)        << 
720   {                                            << 
721     q2max = G4Exp(fLogQSquareGrid[i-1]);       << 
722   }                                            << 
723       //G4cout << "Q2= " << Q2 << " q2max= " < << 
724     }                                          << 
725                                                << 
726   std::size_t nReducedPoints = np/4;           << 
727                                                << 
728   //check for errors                           << 
729   if (np < 16)                                 << 
730     {                                          << 
731       G4Exception("G4PenelopeRayleighModel::In << 
732       "em2047",FatalException,                 << 
733       "Too few points to initialize the sampli << 
734     }                                          << 
735   if (q2min > (q2max-1e-10))                   << 
736     {                                          << 
737       G4cout << "q2min= " << q2min << " q2max= << 
738       G4Exception("G4PenelopeRayleighModel::In << 
739       "em2048",FatalException,                 << 
740       "Too narrow grid to initialize the sampl << 
741     }                                          << 
742                                                << 
743   //This is subroutine RITAI0 of Penelope      << 
744   //Create an object of type G4PenelopeRayleig << 
745                                                << 
746   //temporary vectors --> Then everything is s << 
747   G4DataVector* x = new G4DataVector();        << 
748                                                << 
749   /******************************************* << 
750     Start with a grid of NUNIF points uniforml << 
751   ******************************************** << 
752   std::size_t NUNIF = std::min(std::max(((std: << 
753   const G4int nip = 51; //hard-coded in Penelo << 
754                                                << 
755   G4double dx = (q2max-q2min)/((G4double) NUNI << 
756   x->push_back(q2min);                         << 
757   for (std::size_t i=1;i<NUNIF-1;++i)          << 
758     {                                          << 
759       G4double app = q2min + i*dx;             << 
760       x->push_back(app); //increase            << 
761     }                                          << 
762   x->push_back(q2max);                         << 
763                                                << 
764   if (fVerboseLevel> 3)                        << 
765     G4cout << "Vector x has " << x->size() <<  << 
766                                                << 
767   //Allocate temporary storage vectors         << 
768   G4DataVector* area = new G4DataVector();     << 
769   G4DataVector* a = new G4DataVector();        << 
770   G4DataVector* b = new G4DataVector();        << 
771   G4DataVector* c = new G4DataVector();        << 
772   G4DataVector* err = new G4DataVector();      << 
773                                                << 
774   for (std::size_t i=0;i<NUNIF-1;++i) //build  << 
775     {                                          << 
776       //Temporary vectors for this loop        << 
777       G4DataVector* pdfi = new G4DataVector(); << 
778       G4DataVector* pdfih = new G4DataVector() << 
779       G4DataVector* sumi = new G4DataVector(); << 
780                                                << 
781       G4double dxi = ((*x)[i+1]-(*x)[i])/(G4do << 
782       G4double pdfmax = 0;                     << 
783       for (G4int k=0;k<nip;k++)                << 
784   {                                            << 
785     G4double xik = (*x)[i]+k*dxi;              << 
786     G4double pdfk = std::max(GetFSquared(mat,x << 
787     pdfi->push_back(pdfk);                     << 
788     pdfmax = std::max(pdfmax,pdfk);            << 
789     if (k < (nip-1))                           << 
790       {                                        << 
791         G4double xih = xik + 0.5*dxi;          << 
792         G4double pdfIK = std::max(GetFSquared( << 
793         pdfih->push_back(pdfIK);               << 
794         pdfmax = std::max(pdfmax,pdfIK);       << 
795       }                                        << 
796   }                                            << 
797                                                << 
798       //Simpson's integration                  << 
799       G4double cons = dxi*0.5*(1./3.);         << 
800       sumi->push_back(0.);                     << 
801       for (G4int k=1;k<nip;k++)                << 
802   {                                            << 
803     G4double previous = (*sumi)[k-1];          << 
804     G4double next = previous + cons*((*pdfi)[k << 
805     sumi->push_back(next);                     << 
806   }                                            << 
807                                                << 
808       G4double lastIntegral = (*sumi)[sumi->si << 
809       area->push_back(lastIntegral);           << 
810       //Normalize cumulative function          << 
811       G4double factor = 1.0/lastIntegral;      << 
812       for (std::size_t k=0;k<sumi->size();++k) << 
813   (*sumi)[k] *= factor;                        << 
814                                                << 
815       //When the PDF vanishes at one of the in << 
816       if ((*pdfi)[0] < 1e-35)                  << 
817   (*pdfi)[0] = 1e-5*pdfmax;                    << 
818       if ((*pdfi)[pdfi->size()-1] < 1e-35)     << 
819   (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;       << 
820                                                << 
821       G4double pli = (*pdfi)[0]*factor;        << 
822       G4double pui = (*pdfi)[pdfi->size()-1]*f << 
823       G4double B_temp = 1.0-1.0/(pli*pui*dx*dx << 
824       G4double A_temp = (1.0/(pli*dx))-1.0-B_t << 
825       G4double C_temp = 1.0+A_temp+B_temp;     << 
826       if (C_temp < 1e-35)                      << 
827   {                                            << 
828     a->push_back(0.);                          << 
829     b->push_back(0.);                          << 
830     c->push_back(1.);                          << 
831   }                                               473   }
                                                   >> 474       if (stechiometric && stechiometric[i]!=0)
                                                   >> 475   gradx1 += stechiometric[i]*(fa*fa); //sum on the molecule
832       else                                        476       else
833   {                                            << 477   gradx1 += (vector_of_atoms[i]/tot_atoms)*(fa*fa); //weighted mean
834     a->push_back(A_temp);                      << 
835     b->push_back(B_temp);                      << 
836     c->push_back(C_temp);                      << 
837   }                                            << 
838                                                << 
839       //OK, now get ERR(I), the integral of th << 
840       //and the true pdf, extended over the in << 
841       G4int icase = 1; //loop code             << 
842       G4bool reLoop = false;                   << 
843       err->push_back(0.);                      << 
844       do                                       << 
845   {                                            << 
846     reLoop = false;                            << 
847     (*err)[i] = 0.; //zero variable            << 
848     for (G4int k=0;k<nip;k++)                  << 
849       {                                        << 
850         G4double rr = (*sumi)[k];              << 
851         G4double pap = (*area)[i]*(1.0+((*a)[i << 
852     ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1]-(* << 
853         if (k == 0 || k == nip-1)              << 
854     (*err)[i] += 0.5*std::fabs(pap-(*pdfi)[k]) << 
855         else                                   << 
856     (*err)[i] += std::fabs(pap-(*pdfi)[k]);    << 
857       }                                        << 
858     (*err)[i] *= dxi;                          << 
859                                                << 
860     //If err(I) is too large, the pdf is appro << 
861     if ((*err)[i] > 0.1*(*area)[i] && icase == << 
862       {                                        << 
863         (*b)[i] = 0;                           << 
864         (*a)[i] = 0;                           << 
865         (*c)[i] = 1.;                          << 
866         icase = 2;                             << 
867         reLoop = true;                         << 
868       }                                        << 
869   }while(reLoop);                              << 
870       delete pdfi;                             << 
871       delete pdfih;                            << 
872       delete sumi;                             << 
873     } //end of first loop over i               << 
874                                                << 
875   //Now assign last point                      << 
876   (*x)[x->size()-1] = q2max;                   << 
877   a->push_back(0.);                            << 
878   b->push_back(0.);                            << 
879   c->push_back(0.);                            << 
880   err->push_back(0.);                          << 
881   area->push_back(0.);                         << 
882                                                << 
883   if (x->size() != NUNIF || a->size() != NUNIF << 
884       err->size() != NUNIF || area->size() !=  << 
885     {                                          << 
886       G4ExceptionDescription ed;               << 
887       ed << "Problem in building the Table for << 
888       G4Exception("G4PenelopeRayleighModel::In << 
889       "em2049",FatalException,ed);             << 
890     }                                             478     }
891                                                << 479   return gradx1;
892   /******************************************* << 
893    New grid points are added by halving the su << 
894   This is done up to np=150 points in the grid << 
895   ******************************************** << 
896   do                                           << 
897     {                                          << 
898       G4double maxError = 0.0;                 << 
899       std::size_t iErrMax = 0;                 << 
900       for (std::size_t i=0;i<err->size()-2;++i << 
901   {                                            << 
902     //maxError is the lagest of the interval e << 
903     if ((*err)[i] > maxError)                  << 
904       {                                        << 
905         maxError = (*err)[i];                  << 
906         iErrMax = i;                           << 
907       }                                        << 
908   }                                            << 
909                                                << 
910       //OK, now I have to insert one new point << 
911       G4double newx = 0.5*((*x)[iErrMax]+(*x)[ << 
912                                                << 
913       x->insert(x->begin()+iErrMax+1,newx);    << 
914       //Add place-holders in the other vectors << 
915       area->insert(area->begin()+iErrMax+1,0.) << 
916       a->insert(a->begin()+iErrMax+1,0.);      << 
917       b->insert(b->begin()+iErrMax+1,0.);      << 
918       c->insert(c->begin()+iErrMax+1,0.);      << 
919       err->insert(err->begin()+iErrMax+1,0.);  << 
920                                                << 
921       //Now calculate the other parameters     << 
922       for (std::size_t i=iErrMax;i<=iErrMax+1; << 
923   {                                            << 
924     //Temporary vectors for this loop          << 
925     G4DataVector* pdfi = new G4DataVector();   << 
926     G4DataVector* pdfih = new G4DataVector();  << 
927     G4DataVector* sumi = new G4DataVector();   << 
928                                                << 
929     G4double dxLocal = (*x)[i+1]-(*x)[i];      << 
930     G4double dxi = ((*x)[i+1]-(*x)[i])/(G4doub << 
931     G4double pdfmax = 0;                       << 
932     for (G4int k=0;k<nip;k++)                  << 
933       {                                        << 
934         G4double xik = (*x)[i]+k*dxi;          << 
935         G4double pdfk = std::max(GetFSquared(m << 
936         pdfi->push_back(pdfk);                 << 
937         pdfmax = std::max(pdfmax,pdfk);        << 
938         if (k < (nip-1))                       << 
939     {                                          << 
940       G4double xih = xik + 0.5*dxi;            << 
941       G4double pdfIK = std::max(GetFSquared(ma << 
942       pdfih->push_back(pdfIK);                 << 
943       pdfmax = std::max(pdfmax,pdfIK);         << 
944     }                                          << 
945       }                                        << 
946                                                << 
947     //Simpson's integration                    << 
948     G4double cons = dxi*0.5*(1./3.);           << 
949     sumi->push_back(0.);                       << 
950     for (G4int k=1;k<nip;k++)                  << 
951       {                                        << 
952         G4double previous = (*sumi)[k-1];      << 
953         G4double next = previous + cons*((*pdf << 
954         sumi->push_back(next);                 << 
955       }                                        << 
956     G4double lastIntegral = (*sumi)[sumi->size << 
957     (*area)[i] = lastIntegral;                 << 
958                                                << 
959     //Normalize cumulative function            << 
960     G4double factor = 1.0/lastIntegral;        << 
961     for (std::size_t k=0;k<sumi->size();++k)   << 
962       (*sumi)[k] *= factor;                    << 
963                                                << 
964     //When the PDF vanishes at one of the inte << 
965     if ((*pdfi)[0] < 1e-35)                    << 
966       (*pdfi)[0] = 1e-5*pdfmax;                << 
967     if ((*pdfi)[pdfi->size()-1] < 1e-35)       << 
968       (*pdfi)[pdfi->size()-1] = 1e-5*pdfmax;   << 
969                                                << 
970     G4double pli = (*pdfi)[0]*factor;          << 
971     G4double pui = (*pdfi)[pdfi->size()-1]*fac << 
972     G4double B_temp = 1.0-1.0/(pli*pui*dxLocal << 
973     G4double A_temp = (1.0/(pli*dxLocal))-1.0- << 
974     G4double C_temp = 1.0+A_temp+B_temp;       << 
975     if (C_temp < 1e-35)                        << 
976       {                                        << 
977         (*a)[i]= 0.;                           << 
978         (*b)[i] = 0.;                          << 
979         (*c)[i] = 1;                           << 
980       }                                        << 
981     else                                       << 
982       {                                        << 
983         (*a)[i]= A_temp;                       << 
984         (*b)[i] = B_temp;                      << 
985         (*c)[i] = C_temp;                      << 
986       }                                        << 
987     //OK, now get ERR(I), the integral of the  << 
988     //and the true pdf, extended over the inte << 
989     G4int icase = 1; //loop code               << 
990     G4bool reLoop = false;                     << 
991     do                                         << 
992       {                                        << 
993         reLoop = false;                        << 
994         (*err)[i] = 0.; //zero variable        << 
995         for (G4int k=0;k<nip;k++)              << 
996     {                                          << 
997       G4double rr = (*sumi)[k];                << 
998       G4double pap = (*area)[i]*(1.0+((*a)[i]+ << 
999         ((1.0-(*b)[i]*rr*rr)*(*c)[i]*((*x)[i+1 << 
1000       if (k == 0 || k == nip-1)               << 
1001         (*err)[i] += 0.5*std::fabs(pap-(*pdfi << 
1002       else                                    << 
1003         (*err)[i] += std::fabs(pap-(*pdfi)[k] << 
1004     }                                         << 
1005         (*err)[i] *= dxi;                     << 
1006                                               << 
1007         //If err(I) is too large, the pdf is  << 
1008         if ((*err)[i] > 0.1*(*area)[i] && ica << 
1009     {                                         << 
1010       (*b)[i] = 0;                            << 
1011       (*a)[i] = 0;                            << 
1012       (*c)[i] = 1.;                           << 
1013       icase = 2;                              << 
1014       reLoop = true;                          << 
1015     }                                         << 
1016       }while(reLoop);                         << 
1017     delete pdfi;                              << 
1018     delete pdfih;                             << 
1019     delete sumi;                              << 
1020   }                                           << 
1021     }while(x->size() < np);                   << 
1022                                               << 
1023   if (x->size() != np || a->size() != np ||   << 
1024       err->size() != np || area->size() != np << 
1025     {                                         << 
1026       G4Exception("G4PenelopeRayleighModel::I << 
1027       "em2050",FatalException,                << 
1028       "Problem in building the extended Table << 
1029     }                                         << 
1030                                               << 
1031   /****************************************** << 
1032    Renormalization                            << 
1033   ******************************************* << 
1034   G4double ws = 0;                            << 
1035   for (std::size_t i=0;i<np-1;++i)            << 
1036     ws += (*area)[i];                         << 
1037   ws = 1.0/ws;                                << 
1038   G4double errMax = 0;                        << 
1039   for (std::size_t i=0;i<np-1;++i)            << 
1040     {                                         << 
1041       (*area)[i] *= ws;                       << 
1042       (*err)[i] *= ws;                        << 
1043       errMax = std::max(errMax,(*err)[i]);    << 
1044     }                                         << 
1045                                               << 
1046   //Vector with the normalized cumulative dis << 
1047   G4DataVector* PAC = new G4DataVector();     << 
1048   PAC->push_back(0.);                         << 
1049   for (std::size_t i=0;i<np-1;++i)            << 
1050     {                                         << 
1051       G4double previous = (*PAC)[i];          << 
1052       PAC->push_back(previous+(*area)[i]);    << 
1053     }                                         << 
1054   (*PAC)[PAC->size()-1] = 1.;                 << 
1055                                               << 
1056   /****************************************** << 
1057   Pre-calculated limits for the initial binar << 
1058   ******************************************* << 
1059   std::vector<std::size_t> *ITTL = new std::v << 
1060   std::vector<std::size_t> *ITTU = new std::v << 
1061                                               << 
1062   //Just create place-holders                 << 
1063   for (std::size_t i=0;i<np;++i)              << 
1064     {                                         << 
1065       ITTL->push_back(0);                     << 
1066       ITTU->push_back(0);                     << 
1067     }                                         << 
1068                                               << 
1069   G4double bin = 1.0/(np-1);                  << 
1070   (*ITTL)[0]=0;                               << 
1071   for (std::size_t i=1;i<(np-1);++i)          << 
1072     {                                         << 
1073       G4double ptst = i*bin;                  << 
1074       G4bool found = false;                   << 
1075       for (std::size_t j=(*ITTL)[i-1];j<np && << 
1076   {                                           << 
1077     if ((*PAC)[j] > ptst)                     << 
1078       {                                       << 
1079         (*ITTL)[i] = j-1;                     << 
1080         (*ITTU)[i-1] = j;                     << 
1081         found = true;                         << 
1082       }                                       << 
1083   }                                           << 
1084     }                                         << 
1085   (*ITTU)[ITTU->size()-2] = ITTU->size()-1;   << 
1086   (*ITTU)[ITTU->size()-1] = ITTU->size()-1;   << 
1087   (*ITTL)[ITTL->size()-1] = ITTU->size()-2;   << 
1088                                               << 
1089   if (ITTU->size() != np || ITTU->size() != n << 
1090     {                                         << 
1091       G4Exception("G4PenelopeRayleighModel::I << 
1092       "em2051",FatalException,                << 
1093       "Problem in building the Limit Tables f << 
1094     }                                         << 
1095                                               << 
1096   /****************************************** << 
1097     Copy tables                               << 
1098   ******************************************* << 
1099   G4PenelopeSamplingData* theTable = new G4Pe << 
1100   for (std::size_t i=0;i<np;++i)              << 
1101     {                                         << 
1102       theTable->AddPoint((*x)[i],(*PAC)[i],(* << 
1103     }                                         << 
1104                                               << 
1105   if (fVerboseLevel > 2)                      << 
1106     {                                         << 
1107       G4cout << "**************************** << 
1108   G4endl;                                     << 
1109       G4cout << "Sampling table for Penelope  << 
1110       theTable->DumpTable();                  << 
1111     }                                         << 
1112   fSamplingTable->insert(std::make_pair(mat,t << 
1113                                               << 
1114   //Clean up temporary vectors                << 
1115   delete x;                                   << 
1116   delete a;                                   << 
1117   delete b;                                   << 
1118   delete c;                                   << 
1119   delete err;                                 << 
1120   delete area;                                << 
1121   delete PAC;                                 << 
1122   delete ITTL;                                << 
1123   delete ITTU;                                << 
1124                                               << 
1125   //DONE!                                     << 
1126   return;                                     << 
1127 }                                                480 }
1128                                                  481 
1129 //....oooOO0OOooo........oooOO0OOooo........o    482 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1130                                                  483 
1131 void G4PenelopeRayleighModel::GetPMaxTable(co << 484 void G4PenelopeRayleighModel::InitialiseSampling()
1132 {                                                485 {
1133   if (!fPMaxTable)                            << 486   if (!samplingFunction_x || !samplingFunction_xNoLog)
1134     {                                         << 
1135       G4cout << "G4PenelopeRayleighModel::Bui << 
1136       G4cout << "Going to instanziate the fPM << 
1137       G4cout << "That should _not_ be here! " << 
1138       fPMaxTable = new std::map<const G4Mater << 
1139     }                                         << 
1140   //check if the table is already there       << 
1141   if (fPMaxTable->count(mat))                 << 
1142     return;                                   << 
1143                                               << 
1144   //otherwise build it                        << 
1145   if (!fSamplingTable)                        << 
1146     {                                         << 
1147       G4Exception("G4PenelopeRayleighModel::G << 
1148       "em2052",FatalException,                << 
1149       "SamplingTable is not properly instanti << 
1150       return;                                 << 
1151     }                                         << 
1152                                               << 
1153   //This should not be: the sampling table is << 
1154   if (!fSamplingTable->count(mat))            << 
1155     {                                            487     {
1156        G4ExceptionDescription ed;             << 488       G4cout << "G4PenelopeRayleighModel::InitialiseSampling(), something wrong" << G4endl;
1157        ed << "Sampling table for material " < << 489       G4cout << "It looks like G4PenelopeRayleighModel::PrepareConstants() has not been called" << G4endl;
1158        G4Exception("G4PenelopeRayleighModel:: << 490       G4Exception();
1159                   "em2052",FatalException,    << 
1160                   ed);                        << 
1161        return;                                << 
1162     }                                            491     }
1163                                               << 492   if (!SamplingTable.count(theMaterial)) //material not defined yet
1164   G4PenelopeSamplingData *theTable = fSamplin << 493     { 
1165   std::size_t tablePoints = theTable->GetNumb << 494       G4double XlowInte = 0.;
1166                                               << 495       G4double XhighInte=(*samplingFunction_xNoLog)[0];
1167   std::size_t nOfEnergyPoints = fLogEnergyGri << 496       //material not inizialized yet: initialize it now
1168   G4PhysicsFreeVector* theVec = new G4Physics << 497       G4DataVector* samplingFunction_y = new G4DataVector();
1169                                               << 498       G4PenelopeIntegrator<G4PenelopeRayleighModel,G4double(G4PenelopeRayleighModel::*)(G4double)> 
1170   const std::size_t nip = 51; //hard-coded in << 499   theIntegrator;
1171                                               << 500       G4double sum = theIntegrator.Calculate(this,&G4PenelopeRayleighModel::MolecularFormFactor,
1172   for (std::size_t ie=0;ie<fLogEnergyGridPMax << 501             XlowInte,XhighInte,1e-10); 
1173     {                                         << 502       samplingFunction_y->push_back(sum);
1174       G4double energy = G4Exp(fLogEnergyGridP << 503       for (G4int i=1;i<nPoints;i++)
1175       G4double Qm = 2.0*energy/electron_mass_ << 
1176       G4double Qm2 = Qm*Qm;                   << 
1177       G4double firstQ2 = theTable->GetX(0);   << 
1178       G4double lastQ2 = theTable->GetX(tableP << 
1179       G4double thePMax = 0;                   << 
1180                                               << 
1181       if (Qm2 > firstQ2)                      << 
1182   {                                           << 
1183     if (Qm2 < lastQ2)                         << 
1184       {                                       << 
1185         //bisection to look for the index of  << 
1186         std::size_t lowerBound = 0;           << 
1187         std::size_t upperBound = tablePoints- << 
1188         while (lowerBound <= upperBound)      << 
1189     {                                         << 
1190       std::size_t midBin = (lowerBound + uppe << 
1191       if( Qm2 < theTable->GetX(midBin))       << 
1192         { upperBound = midBin-1; }            << 
1193       else                                    << 
1194         { lowerBound = midBin+1; }            << 
1195     }                                         << 
1196         //upperBound is the output (but also  << 
1197         G4double Q1 = theTable->GetX(upperBou << 
1198         G4double Q2 = Qm2;                    << 
1199         G4double DQ = (Q2-Q1)/((G4double)(nip << 
1200         G4double theA = theTable->GetA(upperB << 
1201         G4double theB = theTable->GetB(upperB << 
1202         G4double thePAC = theTable->GetPAC(up << 
1203         G4DataVector* fun = new G4DataVector( << 
1204         for (std::size_t k=0;k<nip;++k)       << 
1205     {                                         << 
1206       G4double qi = Q1 + k*DQ;                << 
1207       G4double tau = (qi-Q1)/                 << 
1208         (theTable->GetX(upperBound+1)-Q1);    << 
1209       G4double con1 = 2.0*theB*tau;           << 
1210       G4double ci = 1.0+theA+theB;            << 
1211       G4double con2 = ci-theA*tau;            << 
1212       G4double etap = 0;                      << 
1213       if (std::fabs(con1) > 1.0e-16*std::fabs << 
1214         etap = con2*(1.0-std::sqrt(1.0-2.0*ta << 
1215       else                                    << 
1216         etap = tau/con2;                      << 
1217       G4double theFun = (theTable->GetPAC(upp << 
1218         (1.0+(theA+theB*etap)*etap)*(1.0+(the << 
1219         ((1.0-theB*etap*etap)*ci*(theTable->G << 
1220       fun->push_back(theFun);                 << 
1221     }                                         << 
1222         //Now intergrate numerically the fun  << 
1223         G4DataVector* sum = new G4DataVector; << 
1224         G4double CONS = DQ*(1./12.);          << 
1225         G4double HCONS = 0.5*CONS;            << 
1226         sum->push_back(0.);                   << 
1227         G4double secondPoint = (*sum)[0] +    << 
1228     (5.0*(*fun)[0]+8.0*(*fun)[1]-(*fun)[2])*C << 
1229         sum->push_back(secondPoint);          << 
1230         for (std::size_t hh=2;hh<nip-1;++hh)  << 
1231     {                                         << 
1232       G4double previous = (*sum)[hh-1];       << 
1233       G4double next = previous+(13.0*((*fun)[ << 
1234               (*fun)[hh+1]-(*fun)[hh-2])*HCON << 
1235       sum->push_back(next);                   << 
1236     }                                         << 
1237         G4double last = (*sum)[nip-2]+(5.0*(* << 
1238                (*fun)[nip-3])*CONS;           << 
1239         sum->push_back(last);                 << 
1240         thePMax = thePAC + (*sum)[sum->size() << 
1241         delete fun;                           << 
1242         delete sum;                           << 
1243       }                                       << 
1244     else                                      << 
1245       {                                       << 
1246         thePMax = 1.0;                        << 
1247       }                                       << 
1248   }                                           << 
1249       else                                    << 
1250   {                                              504   {
1251     thePMax = theTable->GetPAC(0);            << 505     XlowInte=(*samplingFunction_xNoLog)[i-1];
                                                   >> 506     XhighInte=(*samplingFunction_xNoLog)[i];
                                                   >> 507     sum += theIntegrator.Calculate(this,
                                                   >> 508           &G4PenelopeRayleighModel::MolecularFormFactor,
                                                   >> 509           XlowInte,XhighInte,1e-10);
                                                   >> 510     samplingFunction_y->push_back(sum);
1252   }                                              511   }
1253                                               << 512       for (G4int i=0;i<nPoints;i++) 
1254       //Write number in the table             << 513   (*samplingFunction_y)[i]=std::log((*samplingFunction_y)[i]);
1255       theVec->PutValue(ie,energy,thePMax);    << 514   
                                                   >> 515       //
                                                   >> 516       /*
                                                   >> 517       G4String nnn = theMaterial->GetName()+".ntab";
                                                   >> 518       std::ofstream file(nnn);
                                                   >> 519       for (size_t k=0;k<samplingFunction_x->size();k++)
                                                   >> 520   file << (*samplingFunction_x)[k] << " " << (*samplingFunction_y)[k] << G4endl;
                                                   >> 521       file.close();
                                                   >> 522       */
                                                   >> 523       //
                                                   >> 524       SamplingTable[theMaterial] = samplingFunction_y;
1256   }                                              525   }
1257                                               << 
1258   fPMaxTable->insert(std::make_pair(mat,theVe << 
1259   return;                                     << 
1260 }                                                526 }
1261                                                  527 
1262 //....oooOO0OOooo........oooOO0OOooo........o << 528 void G4PenelopeRayleighModel::PrepareConstants()
1263                                               << 
1264 void G4PenelopeRayleighModel::DumpFormFactorT << 
1265 {                                                529 {
1266   G4cout << "******************************** << 530   if (verboseLevel > 3)
1267   G4cout << "G4PenelopeRayleighModel: Form Fa << 531     G4cout << "Calling G4PenelopeRayleighModel::PrepareConstants()" << G4endl;
1268   //try to use the same format as Penelope-Fo << 532   nPoints=241;
1269   G4cout <<  "Q/(m_e*c)                 F(Q)  << 533   Xlow=1e-04;
1270   G4cout << "******************************** << 534   Xhigh=1e06;
1271   if (!fLogFormFactorTable->count(mat))       << 535   if (samplingFunction_x)
1272     BuildFormFactorTable(mat);                << 536     delete samplingFunction_x;
1273                                               << 537   if (samplingFunction_xNoLog)
1274   G4PhysicsFreeVector* theVec = fLogFormFacto << 538     delete samplingFunction_xNoLog;
1275   for (std::size_t i=0;i<theVec->GetVectorLen << 539  
1276     {                                         << 540   samplingFunction_x = new G4DataVector();
1277       G4double logQ2 = theVec->GetLowEdgeEner << 541   samplingFunction_xNoLog = new G4DataVector();
1278       G4double Q = G4Exp(0.5*logQ2);          << 542  
1279       G4double logF2 = (*theVec)[i];          << 543   G4double scalingFactor = std::pow((Xhigh/Xlow),((1/((G4double)(nPoints-1)))));
1280       G4double F = G4Exp(0.5*logF2);          << 544   G4double logScalingFactor=(1/((G4double)(nPoints-1)))*std::log(Xhigh/Xlow);
1281       G4cout << Q << "              " << F << << 545   //Logarithmic table between log(Xlow) and log(Xhigh)
                                                   >> 546   samplingFunction_x->push_back(std::log(Xlow));
                                                   >> 547   //Table between Xlow and Xhigh with log spacement: needed for InitialiseSampling()
                                                   >> 548   samplingFunction_xNoLog->push_back(Xlow);
                                                   >> 549 
                                                   >> 550   for (G4int i=1;i<nPoints;i++)
                                                   >> 551     {
                                                   >> 552       G4double nextx = (*samplingFunction_x)[i-1]+logScalingFactor;
                                                   >> 553       samplingFunction_x->push_back(nextx);
                                                   >> 554       nextx = (*samplingFunction_xNoLog)[i-1]*scalingFactor;
                                                   >> 555       samplingFunction_xNoLog->push_back(nextx);
1282     }                                            556     }
1283   //DONE                                      << 
1284   return;                                     << 
1285 }                                             << 
1286                                               << 
1287 //....oooOO0OOooo........oooOO0OOooo........o << 
1288                                               << 
1289 void G4PenelopeRayleighModel::SetParticle(con << 
1290 {                                             << 
1291   if(!fParticle) {                            << 
1292     fParticle = p;                            << 
1293   }                                           << 
1294 }                                                557 }
1295                                                  558