Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4PenelopeBremsstrahlungFS.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/G4PenelopeBremsstrahlungFS.cc (Version 11.3.0) and /processes/electromagnetic/lowenergy/src/G4PenelopeBremsstrahlungFS.cc (Version 11.2.2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 //                                                 26 //
 27 // Author: Luciano Pandola                         27 // Author: Luciano Pandola
 28 //                                                 28 //
 29 // History:                                        29 // History:
 30 // --------                                        30 // --------
 31 // 23 Nov 2010   L Pandola    First complete i     31 // 23 Nov 2010   L Pandola    First complete implementation
 32 // 02 May 2011   L.Pandola    Remove dependenc     32 // 02 May 2011   L.Pandola    Remove dependency on CLHEP::HepMatrix
 33 // 24 May 2011   L.Pandola    Renamed (make v2     33 // 24 May 2011   L.Pandola    Renamed (make v2008 as default Penelope)
 34 // 03 Oct 2013   L.Pandola    Migration to MT      34 // 03 Oct 2013   L.Pandola    Migration to MT
 35 // 30 Oct 2013   L.Pandola    Use G4Cache to a     35 // 30 Oct 2013   L.Pandola    Use G4Cache to avoid new/delete of the
 36 //                             data vector on      36 //                             data vector on the fly in SampleGammaEnergy()
 37 //                                                 37 //
 38                                                    38 
 39 //....oooOO0OOooo........oooOO0OOooo........oo     39 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 40 #include "G4PenelopeBremsstrahlungFS.hh"           40 #include "G4PenelopeBremsstrahlungFS.hh"
 41 #include "G4PhysicsFreeVector.hh"                  41 #include "G4PhysicsFreeVector.hh"
 42 #include "G4PhysicsTable.hh"                       42 #include "G4PhysicsTable.hh"
 43 #include "G4Material.hh"                           43 #include "G4Material.hh"
 44 #include "Randomize.hh"                            44 #include "Randomize.hh"
 45 #include "G4AutoDelete.hh"                         45 #include "G4AutoDelete.hh"
 46 #include "G4Exp.hh"                                46 #include "G4Exp.hh"
 47 #include "G4PhysicalConstants.hh"                  47 #include "G4PhysicalConstants.hh"
 48 #include "G4SystemOfUnits.hh"                      48 #include "G4SystemOfUnits.hh"
 49                                                    49 
 50 //....oooOO0OOooo........oooOO0OOooo........oo     50 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 51                                                    51 
 52 G4PenelopeBremsstrahlungFS::G4PenelopeBremsstr     52 G4PenelopeBremsstrahlungFS::G4PenelopeBremsstrahlungFS(G4int verbosity) :
 53   fReducedXSTable(nullptr),fEffectiveZSq(nullp     53   fReducedXSTable(nullptr),fEffectiveZSq(nullptr),fSamplingTable(nullptr),
 54   fPBcut(nullptr),fVerbosity(verbosity)            54   fPBcut(nullptr),fVerbosity(verbosity)
 55 {                                                  55 {
 56   fCache.Put(0);                                   56   fCache.Put(0);
 57   G4double tempvector[fNBinsX] =                   57   G4double tempvector[fNBinsX] =
 58     {1.0e-12,0.025e0,0.05e0,0.075e0,0.1e0,0.15     58     {1.0e-12,0.025e0,0.05e0,0.075e0,0.1e0,0.15e0,0.2e0,0.25e0,
 59     0.3e0,0.35e0,0.4e0,0.45e0,0.5e0,0.55e0,0.6     59     0.3e0,0.35e0,0.4e0,0.45e0,0.5e0,0.55e0,0.6e0,0.65e0,0.7e0,
 60     0.75e0,0.8e0,0.85e0,0.9e0,0.925e0,0.95e0,0     60     0.75e0,0.8e0,0.85e0,0.9e0,0.925e0,0.95e0,0.97e0,0.99e0,
 61     0.995e0,0.999e0,0.9995e0,0.9999e0,0.99995e     61     0.995e0,0.999e0,0.9995e0,0.9999e0,0.99995e0,0.99999e0,1.0e0};
 62                                                    62 
 63   for (std::size_t ix=0;ix<fNBinsX;++ix)           63   for (std::size_t ix=0;ix<fNBinsX;++ix)
 64     theXGrid[ix] = tempvector[ix];                 64     theXGrid[ix] = tempvector[ix];
 65                                                    65 
 66   for (std::size_t i=0;i<fNBinsE;++i)              66   for (std::size_t i=0;i<fNBinsE;++i)
 67     theEGrid[i] = 0.;                              67     theEGrid[i] = 0.;
 68                                                    68 
 69   fElementData = new std::map<G4int,G4DataVect     69   fElementData = new std::map<G4int,G4DataVector*>;
 70 }                                                  70 }
 71                                                    71 
 72 //....oooOO0OOooo........oooOO0OOooo........oo     72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 73                                                    73 
 74 G4PenelopeBremsstrahlungFS::~G4PenelopeBremsst     74 G4PenelopeBremsstrahlungFS::~G4PenelopeBremsstrahlungFS()
 75 {                                                  75 {
 76   ClearTables();                                   76   ClearTables();
 77                                                    77 
 78   //The G4Physics*Vector pointers contained in     78   //The G4Physics*Vector pointers contained in the fCache are automatically deleted by
 79   //the G4AutoDelete so there is no need to ta     79   //the G4AutoDelete so there is no need to take care of them manually
 80                                                    80 
 81   //Clear manually fElementData                    81   //Clear manually fElementData
 82   if (fElementData)                                82   if (fElementData)
 83     {                                              83     {
 84       for (auto& item : (*fElementData))           84       for (auto& item : (*fElementData)) 
 85   delete item.second;                              85   delete item.second;
 86       delete fElementData;                         86       delete fElementData;
 87       fElementData = nullptr;                      87       fElementData = nullptr;
 88     }                                              88     }
 89 }                                                  89 }
 90                                                    90 
 91 //....oooOO0OOooo........oooOO0OOooo........oo     91 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
 92                                                    92 
 93                                                    93 
 94 void G4PenelopeBremsstrahlungFS::ClearTables(G     94 void G4PenelopeBremsstrahlungFS::ClearTables(G4bool isMaster)
 95 {                                                  95 {
 96   //Just to check                                  96   //Just to check
 97   if (!isMaster)                                   97   if (!isMaster)
 98     G4Exception("G4PenelopeBremsstrahlungFS::C     98     G4Exception("G4PenelopeBremsstrahlungFS::ClearTables()",
 99     "em0100",FatalException,"Worker thread in      99     "em0100",FatalException,"Worker thread in this method");
100                                                   100 
101   if (fReducedXSTable)                            101   if (fReducedXSTable)
102     {                                             102     {
103       for (auto& item : (*fReducedXSTable))       103       for (auto& item : (*fReducedXSTable))
104   {                                               104   {
105     G4PhysicsTable* tab = item.second;            105     G4PhysicsTable* tab = item.second;
106     tab->clearAndDestroy();                       106     tab->clearAndDestroy();
107     delete tab;                                   107     delete tab;
108   }                                               108   }
109       fReducedXSTable->clear();                   109       fReducedXSTable->clear();
110       delete fReducedXSTable;                     110       delete fReducedXSTable;
111       fReducedXSTable = nullptr;                  111       fReducedXSTable = nullptr;
112     }                                             112     }
113                                                   113 
114   if (fSamplingTable)                             114   if (fSamplingTable)
115     {                                             115     {
116       for (auto& item : (*fSamplingTable))        116       for (auto& item : (*fSamplingTable))
117   {                                               117   {
118     G4PhysicsTable* tab = item.second;            118     G4PhysicsTable* tab = item.second;
119     tab->clearAndDestroy();                       119     tab->clearAndDestroy();
120           delete tab;                             120           delete tab;
121   }                                               121   }
122       fSamplingTable->clear();                    122       fSamplingTable->clear();
123       delete fSamplingTable;                      123       delete fSamplingTable;
124       fSamplingTable = nullptr;                   124       fSamplingTable = nullptr;
125     }                                             125     }
126   if (fPBcut)                                     126   if (fPBcut)
127     {                                             127     {
128       /*                                          128       /*
129   std::map< std::pair<const G4Material*,G4doub    129   std::map< std::pair<const G4Material*,G4double> ,G4PhysicsFreeVector*>::iterator kk;
130   for (kk=fPBcut->begin(); kk != fPBcut->end()    130   for (kk=fPBcut->begin(); kk != fPBcut->end(); kk++)
131   delete kk->second;                              131   delete kk->second;
132       */                                          132       */
133       delete fPBcut;                              133       delete fPBcut;
134       fPBcut = nullptr;                           134       fPBcut = nullptr;
135     }                                             135     }
136                                                   136 
137   if (fEffectiveZSq)                              137   if (fEffectiveZSq)
138     {                                             138     {
139       delete fEffectiveZSq;                       139       delete fEffectiveZSq;
140       fEffectiveZSq = nullptr;                    140       fEffectiveZSq = nullptr;
141     }                                             141     }
142                                                   142 
143  return;                                          143  return;
144 }                                                 144 }
145                                                   145 
146 //....oooOO0OOooo........oooOO0OOooo........oo    146 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
147                                                   147 
148 G4double G4PenelopeBremsstrahlungFS::GetEffect    148 G4double G4PenelopeBremsstrahlungFS::GetEffectiveZSquared(const G4Material* material) const
149 {                                                 149 {
150   if (!fEffectiveZSq)                             150   if (!fEffectiveZSq)
151     {                                             151     {
152       G4ExceptionDescription ed;                  152       G4ExceptionDescription ed;
153       ed << "The container for the <Z^2> value    153       ed << "The container for the <Z^2> values is not initialized" << G4endl;
154       G4Exception("G4PenelopeBremsstrahlungFS:    154       G4Exception("G4PenelopeBremsstrahlungFS::GetEffectiveZSquared()",
155       "em2007",FatalException,ed);                155       "em2007",FatalException,ed);
156       return 0;                                   156       return 0;
157     }                                             157     }
158   //found in the table: return it                 158   //found in the table: return it
159   if (fEffectiveZSq->count(material))             159   if (fEffectiveZSq->count(material))
160     return fEffectiveZSq->find(material)->seco    160     return fEffectiveZSq->find(material)->second;
161   else                                            161   else
162     {                                             162     {
163       G4ExceptionDescription ed;                  163       G4ExceptionDescription ed;
164       ed << "The value of  <Z^2> is not proper    164       ed << "The value of  <Z^2> is not properly set for material " <<
165   material->GetName() << G4endl;                  165   material->GetName() << G4endl;
166       //requires running of BuildScaledXSTable    166       //requires running of BuildScaledXSTable()
167       G4Exception("G4PenelopeBremsstrahlungFS:    167       G4Exception("G4PenelopeBremsstrahlungFS::GetEffectiveZSquared()",
168       "em2008",FatalException,ed);                168       "em2008",FatalException,ed);
169     }                                             169     }
170   return 0;                                       170   return 0;
171 }                                                 171 }
172                                                   172 
173 //....oooOO0OOooo........oooOO0OOooo........oo    173 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
174                                                   174 
175 void G4PenelopeBremsstrahlungFS::BuildScaledXS    175 void G4PenelopeBremsstrahlungFS::BuildScaledXSTable(const G4Material* material,
176                 G4double cut,G4bool isMaster)     176                 G4double cut,G4bool isMaster)
177 {                                                 177 {
178   //Corresponds to subroutines EBRaW and EBRaR    178   //Corresponds to subroutines EBRaW and EBRaR of PENELOPE
179   /*                                              179   /*
180     This method generates the table of the sca    180     This method generates the table of the scaled energy-loss cross section from
181     bremsstrahlung emission for the given mate    181     bremsstrahlung emission for the given material. Original data are read from
182     file. The table is normalized according to    182     file. The table is normalized according to the Berger-Seltzer cross section.
183   */                                              183   */
184                                                   184 
185   //Just to check                                 185   //Just to check
186   if (!isMaster)                                  186   if (!isMaster)
187     G4Exception("G4PenelopeBremsstrahlungFS::B    187     G4Exception("G4PenelopeBremsstrahlungFS::BuildScaledXSTable()",
188     "em0100",FatalException,"Worker thread in     188     "em0100",FatalException,"Worker thread in this method");
189                                                   189 
190   if (fVerbosity > 2)                             190   if (fVerbosity > 2)
191     {                                             191     {
192       G4cout << "Entering in G4PenelopeBremsst    192       G4cout << "Entering in G4PenelopeBremsstrahlungFS::BuildScaledXSTable for " <<
193   material->GetName() << G4endl;                  193   material->GetName() << G4endl;
194       G4cout << "Threshold = " << cut/keV << "    194       G4cout << "Threshold = " << cut/keV << " keV, isMaster= " << isMaster <<
195   G4endl;                                         195   G4endl;
196     }                                             196     }
197                                                   197 
198   //This method should be accessed by the mast    198   //This method should be accessed by the master only
199   if (!fSamplingTable)                            199   if (!fSamplingTable)
200     fSamplingTable =                              200     fSamplingTable =
201       new std::map< std::pair<const G4Material    201       new std::map< std::pair<const G4Material*,G4double> , G4PhysicsTable*>;
202   if (!fPBcut)                                    202   if (!fPBcut)
203     fPBcut =                                      203     fPBcut =
204       new std::map< std::pair<const G4Material    204       new std::map< std::pair<const G4Material*,G4double> , G4PhysicsFreeVector* >;
205                                                   205 
206   //check if the container exists (if not, cre    206   //check if the container exists (if not, create it)
207   if (!fReducedXSTable)                           207   if (!fReducedXSTable)
208     fReducedXSTable = new std::map< std::pair<    208     fReducedXSTable = new std::map< std::pair<const G4Material*,G4double> ,
209     G4PhysicsTable*>;                             209     G4PhysicsTable*>;
210   if (!fEffectiveZSq)                             210   if (!fEffectiveZSq)
211     fEffectiveZSq = new std::map<const G4Mater    211     fEffectiveZSq = new std::map<const G4Material*,G4double>;
212                                                   212 
213   //******************************************    213   //*********************************************************************
214   //Determine the equivalent atomic number <Z^    214   //Determine the equivalent atomic number <Z^2>
215   //******************************************    215   //*********************************************************************
216   std::vector<G4double> *StechiometricFactors     216   std::vector<G4double> *StechiometricFactors = new std::vector<G4double>;
217   std::size_t nElements = material->GetNumberO    217   std::size_t nElements = material->GetNumberOfElements();
218   const G4ElementVector* elementVector = mater    218   const G4ElementVector* elementVector = material->GetElementVector();
219   const G4double* fractionVector = material->G    219   const G4double* fractionVector = material->GetFractionVector();
220   for (std::size_t i=0;i<nElements;i++)           220   for (std::size_t i=0;i<nElements;i++)
221     {                                             221     {
222       G4double fraction = fractionVector[i];      222       G4double fraction = fractionVector[i];
223       G4double atomicWeigth = (*elementVector)    223       G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
224       StechiometricFactors->push_back(fraction    224       StechiometricFactors->push_back(fraction/atomicWeigth);
225     }                                             225     }
226   //Find max                                      226   //Find max
227   G4double MaxStechiometricFactor = 0.;           227   G4double MaxStechiometricFactor = 0.;
228   for (std::size_t i=0;i<nElements;i++)           228   for (std::size_t i=0;i<nElements;i++)
229     {                                             229     {
230       if ((*StechiometricFactors)[i] > MaxStec    230       if ((*StechiometricFactors)[i] > MaxStechiometricFactor)
231         MaxStechiometricFactor = (*Stechiometr    231         MaxStechiometricFactor = (*StechiometricFactors)[i];
232     }                                             232     }
233   //Normalize                                     233   //Normalize
234   for (std::size_t i=0;i<nElements;i++)           234   for (std::size_t i=0;i<nElements;i++)
235     (*StechiometricFactors)[i] /=  MaxStechiom    235     (*StechiometricFactors)[i] /=  MaxStechiometricFactor;
236                                                   236 
237   G4double sumz2 = 0;                             237   G4double sumz2 = 0;
238   G4double sums = 0;                              238   G4double sums = 0;
239   for (std::size_t i=0;i<nElements;i++)           239   for (std::size_t i=0;i<nElements;i++)
240     {                                             240     {
241       G4double Z = (*elementVector)[i]->GetZ()    241       G4double Z = (*elementVector)[i]->GetZ();
242       sumz2 += (*StechiometricFactors)[i]*Z*Z;    242       sumz2 += (*StechiometricFactors)[i]*Z*Z;
243       sums  += (*StechiometricFactors)[i];        243       sums  += (*StechiometricFactors)[i];
244     }                                             244     }
245   G4double ZBR2 = sumz2/sums;                     245   G4double ZBR2 = sumz2/sums;
246                                                   246 
247   fEffectiveZSq->insert(std::make_pair(materia    247   fEffectiveZSq->insert(std::make_pair(material,ZBR2));
248                                                   248 
249   //******************************************    249   //*********************************************************************
250   // loop on elements and read data files         250   // loop on elements and read data files
251   //******************************************    251   //*********************************************************************
252   G4DataVector* tempData = new G4DataVector(fN    252   G4DataVector* tempData = new G4DataVector(fNBinsE);
253   G4DataVector* tempMatrix = new G4DataVector(    253   G4DataVector* tempMatrix = new G4DataVector(fNBinsE*fNBinsX,0.);
254                                                   254 
255   for (std::size_t iel=0;iel<nElements;iel++)     255   for (std::size_t iel=0;iel<nElements;iel++)
256     {                                             256     {
257       G4double Z = (*elementVector)[iel]->GetZ    257       G4double Z = (*elementVector)[iel]->GetZ();
258       G4int iZ = (G4int) Z;                       258       G4int iZ = (G4int) Z;
259       G4double wgt = (*StechiometricFactors)[i    259       G4double wgt = (*StechiometricFactors)[iel]*Z*Z/ZBR2;
260                                                   260      
261       //the element is not already loaded         261       //the element is not already loaded
262       if (!fElementData->count(iZ))               262       if (!fElementData->count(iZ))
263   {                                               263   {
264     ReadDataFile(iZ);                             264     ReadDataFile(iZ);
265     if (!fElementData->count(iZ))                 265     if (!fElementData->count(iZ))
266       {                                           266       {
267         G4ExceptionDescription ed;                267         G4ExceptionDescription ed;
268         ed << "Error in G4PenelopeBremsstrahlu    268         ed << "Error in G4PenelopeBremsstrahlungFS::BuildScaledXSTable" << G4endl;
269         ed << "Unable to retrieve data for ele    269         ed << "Unable to retrieve data for element " << iZ << G4endl;
270         G4Exception("G4PenelopeBremsstrahlungF    270         G4Exception("G4PenelopeBremsstrahlungFS::BuildScaledXSTable()",
271         "em2009",FatalException,ed);              271         "em2009",FatalException,ed);
272       }                                           272       }
273   }                                               273   }
274                                                   274 
275       G4DataVector* atomData = fElementData->f    275       G4DataVector* atomData = fElementData->find(iZ)->second;
276                                                   276 
277       for (std::size_t ie=0;ie<fNBinsE;++ie)      277       for (std::size_t ie=0;ie<fNBinsE;++ie)
278   {                                               278   {
279     (*tempData)[ie] += wgt*(*atomData)[ie*(fNB    279     (*tempData)[ie] += wgt*(*atomData)[ie*(fNBinsX+1)+fNBinsX]; //last column contains total XS
280     for (std::size_t ix=0;ix<fNBinsX;++ix)        280     for (std::size_t ix=0;ix<fNBinsX;++ix)
281       (*tempMatrix)[ie*fNBinsX+ix] += wgt*(*at    281       (*tempMatrix)[ie*fNBinsX+ix] += wgt*(*atomData)[ie*(fNBinsX+1)+ix];
282   }                                               282   }
283     }                                             283     }
284                                                   284 
285   //******************************************    285   //*********************************************************************
286   // the total energy loss spectrum is re-norm    286   // the total energy loss spectrum is re-normalized to reproduce the total
287   // scaled cross section of Berger and Seltze    287   // scaled cross section of Berger and Seltzer
288   //******************************************    288   //*********************************************************************
289   for (std::size_t ie=0;ie<fNBinsE;++ie)          289   for (std::size_t ie=0;ie<fNBinsE;++ie)
290     {                                             290     {
291       //for each energy, calculate integral of    291       //for each energy, calculate integral of dSigma/dx over dx
292       G4double* tempData2 = new G4double[fNBin    292       G4double* tempData2 = new G4double[fNBinsX];
293       for (std::size_t ix=0;ix<fNBinsX;++ix)      293       for (std::size_t ix=0;ix<fNBinsX;++ix)
294   tempData2[ix] = (*tempMatrix)[ie*fNBinsX+ix]    294   tempData2[ix] = (*tempMatrix)[ie*fNBinsX+ix];
295       G4double rsum = GetMomentumIntegral(temp    295       G4double rsum = GetMomentumIntegral(tempData2,1.0,0);
296       delete[] tempData2;                         296       delete[] tempData2;
297       G4double fact = millibarn*(theEGrid[ie]+    297       G4double fact = millibarn*(theEGrid[ie]+electron_mass_c2)*(1./fine_structure_const)/
298   (classic_electr_radius*classic_electr_radius    298   (classic_electr_radius*classic_electr_radius*(theEGrid[ie]+2.0*electron_mass_c2));
299       G4double fnorm = (*tempData)[ie]/(rsum*f    299       G4double fnorm = (*tempData)[ie]/(rsum*fact);
300       G4double TST = 100.*std::fabs(fnorm-1.0)    300       G4double TST = 100.*std::fabs(fnorm-1.0);
301       if (TST > 1.0)                              301       if (TST > 1.0)
302   {                                               302   {
303     G4ExceptionDescription ed;                    303     G4ExceptionDescription ed;
304     ed << "G4PenelopeBremsstrahlungFS. Corrupt    304     ed << "G4PenelopeBremsstrahlungFS. Corrupted data files?" << G4endl;
305     G4cout << "TST= " << TST << "; fnorm = " <    305     G4cout << "TST= " << TST << "; fnorm = " << fnorm << G4endl;
306     G4cout << "rsum = " << rsum << G4endl;        306     G4cout << "rsum = " << rsum << G4endl;
307     G4cout << "fact = " << fact << G4endl;        307     G4cout << "fact = " << fact << G4endl;
308     G4cout << ie << " " << theEGrid[ie]/keV <<    308     G4cout << ie << " " << theEGrid[ie]/keV << " " << (*tempData)[ie]/barn << G4endl;
309     G4Exception("G4PenelopeBremsstrahlungFS::B    309     G4Exception("G4PenelopeBremsstrahlungFS::BuildScaledXSTable()",
310           "em2010",FatalException,ed);            310           "em2010",FatalException,ed);
311   }                                               311   }
312       for (std::size_t ix=0;ix<fNBinsX;++ix)      312       for (std::size_t ix=0;ix<fNBinsX;++ix)
313   (*tempMatrix)[ie*fNBinsX+ix] *= fnorm;          313   (*tempMatrix)[ie*fNBinsX+ix] *= fnorm;
314     }                                             314     }
315                                                   315 
316   //******************************************    316   //*********************************************************************
317   // create and fill the tables                   317   // create and fill the tables
318   //******************************************    318   //*********************************************************************
319   G4PhysicsTable* thePhysicsTable = new G4Phys    319   G4PhysicsTable* thePhysicsTable = new G4PhysicsTable();
320   // the table will contain 32 G4PhysicsFreeVe    320   // the table will contain 32 G4PhysicsFreeVectors with different
321   // values of x. Each of the G4PhysicsFreeVec    321   // values of x. Each of the G4PhysicsFreeVectors has a profile of
322   // log(XS) vs. log(E)                           322   // log(XS) vs. log(E)
323                                                   323 
324   //reserve space of the vectors. Everything i    324   //reserve space of the vectors. Everything is log-log
325   //I add one extra "fake" point at low energy    325   //I add one extra "fake" point at low energy, since the Penelope
326   //table starts at 1 keV                         326   //table starts at 1 keV
327   for (std::size_t i=0;i<fNBinsX;++i)             327   for (std::size_t i=0;i<fNBinsX;++i)
328     thePhysicsTable->push_back(new G4PhysicsFr    328     thePhysicsTable->push_back(new G4PhysicsFreeVector(fNBinsE+1));
329                                                   329 
330   for (std::size_t ix=0;ix<fNBinsX;++ix)          330   for (std::size_t ix=0;ix<fNBinsX;++ix)
331     {                                             331     {
332       G4PhysicsFreeVector* theVec =               332       G4PhysicsFreeVector* theVec =
333   (G4PhysicsFreeVector*) ((*thePhysicsTable)[i    333   (G4PhysicsFreeVector*) ((*thePhysicsTable)[ix]);
334       for (std::size_t ie=0;ie<fNBinsE;++ie)      334       for (std::size_t ie=0;ie<fNBinsE;++ie)
335   {                                               335   {
336     G4double logene = G4Log(theEGrid[ie]);        336     G4double logene = G4Log(theEGrid[ie]);
337     G4double aValue = (*tempMatrix)[ie*fNBinsX    337     G4double aValue = (*tempMatrix)[ie*fNBinsX+ix];
338     if (aValue < 1e-20*millibarn) //protection    338     if (aValue < 1e-20*millibarn) //protection against log(0)
339       aValue = 1e-20*millibarn;                   339       aValue = 1e-20*millibarn;
340     theVec->PutValues(ie+1,logene,G4Log(aValue    340     theVec->PutValues(ie+1,logene,G4Log(aValue));
341   }                                               341   }
342       //Add fake point at 1 eV using an extrap    342       //Add fake point at 1 eV using an extrapolation with the derivative
343       //at the first valid point (Penelope app    343       //at the first valid point (Penelope approach)
344       G4double derivative = ((*theVec)[2]-(*th    344       G4double derivative = ((*theVec)[2]-(*theVec)[1])/(theVec->Energy(2) - theVec->Energy(1));
345       G4double log1eV = G4Log(1*eV);              345       G4double log1eV = G4Log(1*eV);
346       G4double val1eV = (*theVec)[1]+derivativ    346       G4double val1eV = (*theVec)[1]+derivative*(log1eV-theVec->Energy(1));
347       //fake point at very low energy             347       //fake point at very low energy
348       theVec->PutValues(0,log1eV,val1eV);         348       theVec->PutValues(0,log1eV,val1eV);
349     }                                             349     }
350   std::pair<const G4Material*,G4double> theKey    350   std::pair<const G4Material*,G4double> theKey = std::make_pair(material,cut);
351   fReducedXSTable->insert(std::make_pair(theKe    351   fReducedXSTable->insert(std::make_pair(theKey,thePhysicsTable));
352                                                   352 
353   delete StechiometricFactors;                    353   delete StechiometricFactors;
354   delete tempData;                                354   delete tempData;
355   delete tempMatrix;                              355   delete tempMatrix;
356                                                   356 
357   //Do here also the initialization of the ene    357   //Do here also the initialization of the energy sampling
358   if (!(fSamplingTable->count(theKey)))           358   if (!(fSamplingTable->count(theKey)))
359     InitializeEnergySampling(material,cut);       359     InitializeEnergySampling(material,cut);
360                                                   360 
361   return;                                         361   return;
362 }                                                 362 }
363                                                   363 
364 //....oooOO0OOooo........oooOO0OOooo........oo    364 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
365                                                   365 
366 void G4PenelopeBremsstrahlungFS::ReadDataFile(    366 void G4PenelopeBremsstrahlungFS::ReadDataFile(G4int Z)
367 {                                                 367 {
368   const char* path = G4FindDataDir("G4LEDATA")    368   const char* path = G4FindDataDir("G4LEDATA");
369   if (!path)                                      369   if (!path)
370     {                                             370     {
371       G4String excep = "G4PenelopeBremsstrahlu    371       G4String excep = "G4PenelopeBremsstrahlungFS - G4LEDATA environment variable not set!";
372       G4Exception("G4PenelopeBremsstrahlungFS:    372       G4Exception("G4PenelopeBremsstrahlungFS::ReadDataFile()",
373       "em0006",FatalException,excep);             373       "em0006",FatalException,excep);
374       return;                                     374       return;
375     }                                             375     }
376   /*                                              376   /*
377     Read the cross section file                   377     Read the cross section file
378   */                                              378   */
379   std::ostringstream ost;                         379   std::ostringstream ost;
380   if (Z>9)                                        380   if (Z>9)
381     ost << path << "/penelope/bremsstrahlung/p    381     ost << path << "/penelope/bremsstrahlung/pdebr" << Z << ".p08";
382   else                                            382   else
383     ost << path << "/penelope/bremsstrahlung/p    383     ost << path << "/penelope/bremsstrahlung/pdebr0" << Z << ".p08";
384   std::ifstream file(ost.str().c_str());          384   std::ifstream file(ost.str().c_str());
385   if (!file.is_open())                            385   if (!file.is_open())
386     {                                             386     {
387       G4String excep = "G4PenelopeBremsstrahlu    387       G4String excep = "G4PenelopeBremsstrahlungFS - data file " +
388   G4String(ost.str()) + " not found!";            388   G4String(ost.str()) + " not found!";
389       G4Exception("G4PenelopeBremsstrahlungFS:    389       G4Exception("G4PenelopeBremsstrahlungFS::ReadDataFile()",
390       "em0003",FatalException,excep);             390       "em0003",FatalException,excep);
391       return;                                     391       return;
392     }                                             392     }
393                                                   393 
394   G4int readZ =0;                                 394   G4int readZ =0;
395   file >> readZ;                                  395   file >> readZ;
396                                                   396 
397   //check the right file is opened.               397   //check the right file is opened.
398   if (readZ != Z)                                 398   if (readZ != Z)
399     {                                             399     {
400       G4ExceptionDescription ed;                  400       G4ExceptionDescription ed;
401       ed << "Corrupted data file for Z=" << Z     401       ed << "Corrupted data file for Z=" << Z << G4endl;
402       G4Exception("G4PenelopeBremsstrahlungFS:    402       G4Exception("G4PenelopeBremsstrahlungFS::ReadDataFile()",
403       "em0005",FatalException,ed);                403       "em0005",FatalException,ed);
404       return;                                     404       return;
405     }                                             405     }
406                                                   406 
407   G4DataVector* theMatrix = new G4DataVector(f    407   G4DataVector* theMatrix = new G4DataVector(fNBinsE*(fNBinsX+1),0.); //initialized with zeros
408                                                   408 
409   for (std::size_t ie=0;ie<fNBinsE;++ie)          409   for (std::size_t ie=0;ie<fNBinsE;++ie)
410     {                                             410     {
411       G4double myDouble = 0;                      411       G4double myDouble = 0;
412       file >> myDouble; //energy (eV)             412       file >> myDouble; //energy (eV)
413       if (!theEGrid[ie]) //fill only the first    413       if (!theEGrid[ie]) //fill only the first time
414   theEGrid[ie] = myDouble*eV;                     414   theEGrid[ie] = myDouble*eV;
415       //                                          415       //
416       for (std::size_t ix=0;ix<fNBinsX;++ix)      416       for (std::size_t ix=0;ix<fNBinsX;++ix)
417   {                                               417   {
418     file >> myDouble;                             418     file >> myDouble;
419     (*theMatrix)[ie*(fNBinsX+1)+ix] = myDouble    419     (*theMatrix)[ie*(fNBinsX+1)+ix] = myDouble*millibarn;
420   }                                               420   }
421       file >> myDouble; //total cross section     421       file >> myDouble; //total cross section
422       (*theMatrix)[ie*(fNBinsX+1)+fNBinsX] = m    422       (*theMatrix)[ie*(fNBinsX+1)+fNBinsX] = myDouble*millibarn;
423     }                                             423     }
424                                                   424 
425   if (fElementData)                               425   if (fElementData)
426     fElementData->insert(std::make_pair(Z,theM    426     fElementData->insert(std::make_pair(Z,theMatrix));
427   else                                            427   else
428     delete theMatrix;                             428     delete theMatrix;
429   file.close();                                   429   file.close();
430   return;                                         430   return;
431 }                                                 431 }
432                                                   432 
433 //....oooOO0OOooo........oooOO0OOooo........oo    433 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
434                                                   434 
435 G4double G4PenelopeBremsstrahlungFS::GetMoment    435 G4double G4PenelopeBremsstrahlungFS::GetMomentumIntegral(G4double* y,
436                  G4double xup,G4int momOrder)     436                  G4double xup,G4int momOrder) const
437 //x is always the gridX                           437 //x is always the gridX
438 {                                                 438 {
439   //Corresponds to the function RLMOM of Penel    439   //Corresponds to the function RLMOM of Penelope
440   //This method performs the calculation of th    440   //This method performs the calculation of the integral of (x^momOrder)*y over the interval
441   //from x[0] to xup, obtained by linear inter    441   //from x[0] to xup, obtained by linear interpolation on a table of y.
442   //The independent variable is assumed to tak    442   //The independent variable is assumed to take positive values only.
443   //                                              443   //
444   std::size_t size = fNBinsX;                     444   std::size_t size = fNBinsX;
445   const G4double eps = 1e-35;                     445   const G4double eps = 1e-35;
446                                                   446 
447   //Check that the call is valid                  447   //Check that the call is valid
448   if (momOrder<-1 || size<2 || theXGrid[0]<0)     448   if (momOrder<-1 || size<2 || theXGrid[0]<0)
449     {                                             449     {
450       G4Exception("G4PenelopeBremsstrahlungFS:    450       G4Exception("G4PenelopeBremsstrahlungFS::GetMomentumIntegral()",
451       "em2011",FatalException,"Invalid call");    451       "em2011",FatalException,"Invalid call");
452     }                                             452     }
453                                                   453 
454   for (std::size_t i=1;i<size;++i)                454   for (std::size_t i=1;i<size;++i)
455     {                                             455     {
456       if (theXGrid[i]<0 || theXGrid[i]<theXGri    456       if (theXGrid[i]<0 || theXGrid[i]<theXGrid[i-1])
457   {                                               457   {
458     G4ExceptionDescription ed;                    458     G4ExceptionDescription ed;
459     ed << "Invalid call for bin " << i << G4en    459     ed << "Invalid call for bin " << i << G4endl;
460     G4Exception("G4PenelopeBremsstrahlungFS::G    460     G4Exception("G4PenelopeBremsstrahlungFS::GetMomentumIntegral()",
461       "em2012",FatalException,ed);                461       "em2012",FatalException,ed);
462   }                                               462   }
463     }                                             463     }
464                                                   464 
465   //Compute the integral                          465   //Compute the integral
466   G4double result = 0;                            466   G4double result = 0;
467   if (xup < theXGrid[0])                          467   if (xup < theXGrid[0])
468     return result;                                468     return result;
469   G4bool loopAgain = true;                        469   G4bool loopAgain = true;
470   G4double xt = std::min(xup,theXGrid[size-1])    470   G4double xt = std::min(xup,theXGrid[size-1]);
471   G4double xtc = 0;                               471   G4double xtc = 0;
472   for (std::size_t i=0;i<size-1;++i)              472   for (std::size_t i=0;i<size-1;++i)
473     {                                             473     {
474       G4double x1 = std::max(theXGrid[i],eps);    474       G4double x1 = std::max(theXGrid[i],eps);
475       G4double y1 = y[i];                         475       G4double y1 = y[i];
476       G4double x2 = std::max(theXGrid[i+1],eps    476       G4double x2 = std::max(theXGrid[i+1],eps);
477       G4double y2 = y[i+1];                       477       G4double y2 = y[i+1];
478       if (xt < x2)                                478       if (xt < x2)
479   {                                               479   {
480     xtc = xt;                                     480     xtc = xt;
481     loopAgain = false;                            481     loopAgain = false;
482   }                                               482   }
483       else                                        483       else
484   xtc = x2;                                       484   xtc = x2;
485       G4double dx = x2-x1;                        485       G4double dx = x2-x1;
486       G4double dy = y2-y1;                        486       G4double dy = y2-y1;
487       G4double ds = 0;                            487       G4double ds = 0;
488       if (std::fabs(dx)>1e-14*std::fabs(dy))      488       if (std::fabs(dx)>1e-14*std::fabs(dy))
489   {                                               489   {
490     G4double b=dy/dx;                             490     G4double b=dy/dx;
491     G4double a=y1-b*x1;                           491     G4double a=y1-b*x1;
492     if (momOrder == -1)                           492     if (momOrder == -1)
493       ds = a*G4Log(xtc/x1)+b*(xtc-x1);            493       ds = a*G4Log(xtc/x1)+b*(xtc-x1);
494     else if (momOrder == 0) //speed it up, not    494     else if (momOrder == 0) //speed it up, not using pow()
495       ds = a*(xtc-x1) + 0.5*b*(xtc*xtc-x1*x1);    495       ds = a*(xtc-x1) + 0.5*b*(xtc*xtc-x1*x1);
496     else                                          496     else
497       ds = a*(std::pow(xtc,momOrder+1)-std::po    497       ds = a*(std::pow(xtc,momOrder+1)-std::pow(x1,momOrder+1))/((G4double) (momOrder + 1))
498         + b*(std::pow(xtc,momOrder+2)-std::pow    498         + b*(std::pow(xtc,momOrder+2)-std::pow(x1,momOrder+2))/((G4double) (momOrder + 2));
499   }                                               499   }
500       else                                        500       else
501   ds = 0.5*(y1+y2)*(xtc-x1)*std::pow(xtc,momOr    501   ds = 0.5*(y1+y2)*(xtc-x1)*std::pow(xtc,momOrder);
502       result += ds;                               502       result += ds;
503       if (!loopAgain)                             503       if (!loopAgain)
504   return result;                                  504   return result;
505     }                                             505     }
506   return result;                                  506   return result;
507 }                                                 507 }
508                                                   508 
509 //....oooOO0OOooo........oooOO0OOooo........oo    509 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
510                                                   510 
511 const G4PhysicsTable* G4PenelopeBremsstrahlung    511 const G4PhysicsTable* G4PenelopeBremsstrahlungFS::GetScaledXSTable(const G4Material* mat,
512                    const G4double cut) const      512                    const G4double cut) const
513 {                                                 513 {
514   //check if it already contains the entry        514   //check if it already contains the entry
515   std::pair<const G4Material*,G4double> theKey    515   std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
516                                                   516 
517   if (!(fReducedXSTable->count(theKey)))          517   if (!(fReducedXSTable->count(theKey)))
518     {                                             518     {
519       G4Exception("G4PenelopeBremsstrahlungFS:    519       G4Exception("G4PenelopeBremsstrahlungFS::GetScaledXSTable()",
520       "em2013",FatalException,"Unable to retri    520       "em2013",FatalException,"Unable to retrieve the cross section table");
521     }                                             521     }
522                                                   522 
523   return fReducedXSTable->find(theKey)->second    523   return fReducedXSTable->find(theKey)->second;
524 }                                                 524 }
525                                                   525 
526 //....oooOO0OOooo........oooOO0OOooo........oo    526 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
527                                                   527 
528 void G4PenelopeBremsstrahlungFS::InitializeEne    528 void G4PenelopeBremsstrahlungFS::InitializeEnergySampling(const G4Material* material,
529                   G4double cut)                   529                   G4double cut)
530 {                                                 530 {
531   if (fVerbosity > 2)                             531   if (fVerbosity > 2)
532     G4cout << "Entering in G4PenelopeBremsstra    532     G4cout << "Entering in G4PenelopeBremsstrahlungFS::InitializeEnergySampling() for " <<
533       material->GetName() << G4endl;              533       material->GetName() << G4endl;
534                                                   534 
535   //This method should be accessed by the mast    535   //This method should be accessed by the master only
536   std::pair<const G4Material*,G4double> theKey    536   std::pair<const G4Material*,G4double> theKey = std::make_pair(material,cut);
537                                                   537 
538   G4PhysicsTable* thePhysicsTable = new G4Phys    538   G4PhysicsTable* thePhysicsTable = new G4PhysicsTable();
539   // the table will contain 57 G4PhysicsFreeVe    539   // the table will contain 57 G4PhysicsFreeVectors with different
540   // values of E.                                 540   // values of E.
541   G4PhysicsFreeVector* thePBvec = new G4Physic    541   G4PhysicsFreeVector* thePBvec = new G4PhysicsFreeVector(fNBinsE);
542                                                   542 
543   //I reserve space of the vectors.               543   //I reserve space of the vectors.
544   for (std::size_t i=0;i<fNBinsE;++i)             544   for (std::size_t i=0;i<fNBinsE;++i)
545     thePhysicsTable->push_back(new G4PhysicsFr    545     thePhysicsTable->push_back(new G4PhysicsFreeVector(fNBinsX));
546                                                   546 
547   //Retrieve the table. Must already exist at     547   //Retrieve the table. Must already exist at this point, because this
548   //method is invoked by GetScaledXSTable()       548   //method is invoked by GetScaledXSTable()
549   if (!(fReducedXSTable->count(theKey)))          549   if (!(fReducedXSTable->count(theKey)))
550     G4Exception("G4PenelopeBremsstrahlungFS::I    550     G4Exception("G4PenelopeBremsstrahlungFS::InitializeEnergySampling()",
551     "em2013",FatalException,"Unable to retriev    551     "em2013",FatalException,"Unable to retrieve the cross section table");
552   G4PhysicsTable* theTableReduced = fReducedXS    552   G4PhysicsTable* theTableReduced = fReducedXSTable->find(theKey)->second;
553                                                   553 
554   for (std::size_t ie=0;ie<fNBinsE;++ie)          554   for (std::size_t ie=0;ie<fNBinsE;++ie)
555     {                                             555     {
556       G4PhysicsFreeVector* theVec =               556       G4PhysicsFreeVector* theVec =
557   (G4PhysicsFreeVector*) ((*thePhysicsTable)[i    557   (G4PhysicsFreeVector*) ((*thePhysicsTable)[ie]);
558       //Fill the table                            558       //Fill the table
559       G4double value = 0; //first value           559       G4double value = 0; //first value
560       theVec->PutValues(0,theXGrid[0],value);     560       theVec->PutValues(0,theXGrid[0],value);
561       for (std::size_t ix=1;ix<fNBinsX;++ix)      561       for (std::size_t ix=1;ix<fNBinsX;++ix)
562   {                                               562   {
563     //Here calculate the cumulative distributi    563     //Here calculate the cumulative distribution
564     // int_{0}^{x} dSigma(x',E)/dx' (1/x') dx'    564     // int_{0}^{x} dSigma(x',E)/dx' (1/x') dx'
565     G4PhysicsFreeVector* v1 = (G4PhysicsFreeVe    565     G4PhysicsFreeVector* v1 = (G4PhysicsFreeVector*) (*theTableReduced)[ix-1];
566     G4PhysicsFreeVector* v2 = (G4PhysicsFreeVe    566     G4PhysicsFreeVector* v2 = (G4PhysicsFreeVector*) (*theTableReduced)[ix];
567                                                   567 
568     G4double x1=std::max(theXGrid[ix-1],1.0e-3    568     G4double x1=std::max(theXGrid[ix-1],1.0e-35);
569     //Remember: the table fReducedXSTable has     569     //Remember: the table fReducedXSTable has a fake first point in energy
570     //so, it contains one more bin than fNBins    570     //so, it contains one more bin than fNBinsE.
571     G4double y1=G4Exp((*v1)[ie+1]);               571     G4double y1=G4Exp((*v1)[ie+1]);
572     G4double x2=std::max(theXGrid[ix],1.0e-35)    572     G4double x2=std::max(theXGrid[ix],1.0e-35);
573     G4double y2=G4Exp((*v2)[ie+1]);               573     G4double y2=G4Exp((*v2)[ie+1]);
574     G4double B = (y2-y1)/(x2-x1);                 574     G4double B = (y2-y1)/(x2-x1);
575     G4double A = y1-B*x1;                         575     G4double A = y1-B*x1;
576     G4double dS = A*G4Log(x2/x1)+B*(x2-x1);       576     G4double dS = A*G4Log(x2/x1)+B*(x2-x1);
577     value += dS;                                  577     value += dS;
578     theVec->PutValues(ix,theXGrid[ix],value);     578     theVec->PutValues(ix,theXGrid[ix],value);
579   }                                               579   }
580       //fill the PB vector                        580       //fill the PB vector
581       G4double xc = cut/theEGrid[ie];             581       G4double xc = cut/theEGrid[ie];
582       //Fill a temp data vector                   582       //Fill a temp data vector
583       G4double* tempData = new G4double[fNBins    583       G4double* tempData = new G4double[fNBinsX];
584       for (std::size_t ix=0;ix<fNBinsX;++ix)      584       for (std::size_t ix=0;ix<fNBinsX;++ix)
585   {                                               585   {
586     G4PhysicsFreeVector* vv = (G4PhysicsFreeVe    586     G4PhysicsFreeVector* vv = (G4PhysicsFreeVector*) (*theTableReduced)[ix];
587     tempData[ix] = G4Exp((*vv)[ie+1]);            587     tempData[ix] = G4Exp((*vv)[ie+1]);
588   }                                               588   }
589       G4double pbval = (xc<=1) ?                  589       G4double pbval = (xc<=1) ?
590   GetMomentumIntegral(tempData,xc,-1) :           590   GetMomentumIntegral(tempData,xc,-1) :
591   GetMomentumIntegral(tempData,1.0,-1);           591   GetMomentumIntegral(tempData,1.0,-1);
592       thePBvec->PutValues(ie,theEGrid[ie],pbva    592       thePBvec->PutValues(ie,theEGrid[ie],pbval);
593       delete[] tempData;                          593       delete[] tempData;
594     }                                             594     }
595                                                   595 
596   fSamplingTable->insert(std::make_pair(theKey    596   fSamplingTable->insert(std::make_pair(theKey,thePhysicsTable));
597   fPBcut->insert(std::make_pair(theKey,thePBve    597   fPBcut->insert(std::make_pair(theKey,thePBvec));
598   return;                                         598   return;
599 }                                                 599 }
600                                                   600 
601 //....oooOO0OOooo........oooOO0OOooo........oo    601 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
602                                                   602 
603 G4double G4PenelopeBremsstrahlungFS::SampleGam    603 G4double G4PenelopeBremsstrahlungFS::SampleGammaEnergy(G4double energy,const G4Material* mat,
604                    const G4double cut) const      604                    const G4double cut) const
605 {                                                 605 {
606   std::pair<const G4Material*,G4double> theKey    606   std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
607   if (!(fSamplingTable->count(theKey)) || !(fP    607   if (!(fSamplingTable->count(theKey)) || !(fPBcut->count(theKey)))
608     {                                             608     {
609       G4ExceptionDescription ed;                  609       G4ExceptionDescription ed;
610       ed << "Unable to retrieve the SamplingTa    610       ed << "Unable to retrieve the SamplingTable: " <<
611   fSamplingTable->count(theKey) << " " <<         611   fSamplingTable->count(theKey) << " " <<
612   fPBcut->count(theKey) << G4endl;                612   fPBcut->count(theKey) << G4endl;
613       G4Exception("G4PenelopeBremsstrahlungFS:    613       G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
614       "em2014",FatalException,ed);                614       "em2014",FatalException,ed);
615     }                                             615     }
616   const G4PhysicsTable* theTableInte = fSampli    616   const G4PhysicsTable* theTableInte = fSamplingTable->find(theKey)->second;
617   const G4PhysicsTable* theTableRed = fReduced    617   const G4PhysicsTable* theTableRed = fReducedXSTable->find(theKey)->second;
618                                                   618 
619   //Find the energy bin using bi-partition        619   //Find the energy bin using bi-partition
620   std::size_t eBin = 0;                           620   std::size_t eBin = 0;
621   G4bool firstOrLastBin = false;                  621   G4bool firstOrLastBin = false;
622                                                   622 
623   if (energy < theEGrid[0]) //below first bin     623   if (energy < theEGrid[0]) //below first bin
624     {                                             624     {
625       eBin = 0;                                   625       eBin = 0;
626       firstOrLastBin = true;                      626       firstOrLastBin = true;
627     }                                             627     }
628   else if (energy > theEGrid[fNBinsE-1]) //aft    628   else if (energy > theEGrid[fNBinsE-1]) //after last bin
629     {                                             629     {
630       eBin = fNBinsE-1;                           630       eBin = fNBinsE-1;
631       firstOrLastBin = true;                      631       firstOrLastBin = true;
632     }                                             632     }
633   else                                            633   else
634     {                                             634     {
635       std::size_t i=0;                            635       std::size_t i=0;
636       std::size_t j=fNBinsE-1;                    636       std::size_t j=fNBinsE-1;
637       while ((j-i)>1)                             637       while ((j-i)>1)
638   {                                               638   {
639     std::size_t k = (i+j)/2;                      639     std::size_t k = (i+j)/2;
640     if (energy > theEGrid[k])                     640     if (energy > theEGrid[k])
641       i = k;                                      641       i = k;
642     else                                          642     else
643       j = k;                                      643       j = k;
644   }                                               644   }
645       eBin = i;                                   645       eBin = i;
646     }                                             646     }
647                                                   647 
648   //Get the appropriate physics vector            648   //Get the appropriate physics vector
649   const G4PhysicsFreeVector* theVec1 = (G4Phys    649   const G4PhysicsFreeVector* theVec1 = (G4PhysicsFreeVector*) (*theTableInte)[eBin];
650                                                   650 
651   //Use a "temporary" vector which contains th    651   //Use a "temporary" vector which contains the linear interpolation of the x spectra
652   //in energy. The temporary vector is thread-    652   //in energy. The temporary vector is thread-local, so that there is no conflict.
653   //This is achieved via G4Cache. The theTempV    653   //This is achieved via G4Cache. The theTempVect is allocated only once per thread
654   //(member variable), but it is overwritten a    654   //(member variable), but it is overwritten at every call of this method
655   //(because the interpolation factors change!    655   //(because the interpolation factors change!)
656   G4PhysicsFreeVector* theTempVec = fCache.Get    656   G4PhysicsFreeVector* theTempVec = fCache.Get();
657   if (!theTempVec) //First time this thread ge    657   if (!theTempVec) //First time this thread gets the cache
658     {                                             658     {
659       theTempVec = new G4PhysicsFreeVector(fNB    659       theTempVec = new G4PhysicsFreeVector(fNBinsX);   
660       fCache.Put(theTempVec);                     660       fCache.Put(theTempVec);
661       // The G4AutoDelete takes care here to c    661       // The G4AutoDelete takes care here to clean up the vectors
662       G4AutoDelete::Register(theTempVec);         662       G4AutoDelete::Register(theTempVec);
663       if (fVerbosity > 4)                         663       if (fVerbosity > 4)
664   G4cout << "Creating new instance of G4Physic    664   G4cout << "Creating new instance of G4PhysicsFreeVector() on the worker" << G4endl;
665     }                                             665     }
666                                                   666 
667   //theTempVect is allocated only once (member    667   //theTempVect is allocated only once (member variable), but it is overwritten at
668   //every call of this method (because the int    668   //every call of this method (because the interpolation factors change!)
669   if (!firstOrLastBin)                            669   if (!firstOrLastBin)
670     {                                             670     {
671       const G4PhysicsFreeVector* theVec2 = (G4    671       const G4PhysicsFreeVector* theVec2 = (G4PhysicsFreeVector*) (*theTableInte)[eBin+1];
672       for (std::size_t iloop=0;iloop<fNBinsX;+    672       for (std::size_t iloop=0;iloop<fNBinsX;++iloop)
673   {                                               673   {
674     G4double val = (*theVec1)[iloop]+(((*theVe    674     G4double val = (*theVec1)[iloop]+(((*theVec2)[iloop]-(*theVec1)[iloop]))*
675       (energy-theEGrid[eBin])/(theEGrid[eBin+1    675       (energy-theEGrid[eBin])/(theEGrid[eBin+1]-theEGrid[eBin]);
676     theTempVec->PutValues(iloop,theXGrid[iloop    676     theTempVec->PutValues(iloop,theXGrid[iloop],val);
677   }                                               677   }
678     }                                             678     }
679   else //first or last bin, no interpolation      679   else //first or last bin, no interpolation
680     {                                             680     {
681       for (std::size_t iloop=0;iloop<fNBinsX;+    681       for (std::size_t iloop=0;iloop<fNBinsX;++iloop)
682   theTempVec->PutValues(iloop,theXGrid[iloop],    682   theTempVec->PutValues(iloop,theXGrid[iloop],(*theVec1)[iloop]);
683     }                                             683     }
684                                                   684 
685   //Start the game                                685   //Start the game
686   G4double pbcut = (*(fPBcut->find(theKey)->se    686   G4double pbcut = (*(fPBcut->find(theKey)->second))[eBin];
687                                                   687 
688   if (!firstOrLastBin) //linear interpolation     688   if (!firstOrLastBin) //linear interpolation on pbcut as well
689     {                                             689     {
690       pbcut = (*(fPBcut->find(theKey)->second)    690       pbcut = (*(fPBcut->find(theKey)->second))[eBin] +
691   ((*(fPBcut->find(theKey)->second))[eBin+1]-(    691   ((*(fPBcut->find(theKey)->second))[eBin+1]-(*(fPBcut->find(theKey)->second))[eBin])*
692   (energy-theEGrid[eBin])/(theEGrid[eBin+1]-th    692   (energy-theEGrid[eBin])/(theEGrid[eBin+1]-theEGrid[eBin]);
693     }                                             693     }
694                                                   694 
695   G4double pCumulative = (*theTempVec)[fNBinsX    695   G4double pCumulative = (*theTempVec)[fNBinsX-1]; //last value
696                                                   696 
697   G4double eGamma = 0;                            697   G4double eGamma = 0;
698   G4int nIterations = 0;                          698   G4int nIterations = 0;
699   do                                              699   do
700     {                                             700     {
701       G4double pt = pbcut + G4UniformRand()*(p    701       G4double pt = pbcut + G4UniformRand()*(pCumulative - pbcut);
702       nIterations++;                              702       nIterations++;
703                                                   703 
704       //find where it is                          704       //find where it is
705       std::size_t ibin = 0;                       705       std::size_t ibin = 0;
706       if (pt < (*theTempVec)[0])                  706       if (pt < (*theTempVec)[0])
707   ibin = 0;                                       707   ibin = 0;
708       else if (pt > (*theTempVec)[fNBinsX-1])     708       else if (pt > (*theTempVec)[fNBinsX-1])
709   {                                               709   {
710     //We observed problems due to numerical ro    710     //We observed problems due to numerical rounding here (STT).
711     //delta here is a tiny positive number        711     //delta here is a tiny positive number
712     G4double delta = pt-(*theTempVec)[fNBinsX-    712     G4double delta = pt-(*theTempVec)[fNBinsX-1];
713     if (delta < pt*1e-10) // very small! Numer    713     if (delta < pt*1e-10) // very small! Numerical rounding only
714       {                                           714       {
715         ibin = fNBinsX-2;                         715         ibin = fNBinsX-2;
716         G4ExceptionDescription ed;                716         G4ExceptionDescription ed;
717         ed << "Found that (pt > (*theTempVec)[    717         ed << "Found that (pt > (*theTempVec)[fNBinsX-1]) with pt = " << pt <<
718     " , (*theTempVec)[fNBinsX-1] = " << (*theT    718     " , (*theTempVec)[fNBinsX-1] = " << (*theTempVec)[fNBinsX-1] << " and delta = " <<
719     (pt-(*theTempVec)[fNBinsX-1]) << G4endl;      719     (pt-(*theTempVec)[fNBinsX-1]) << G4endl;
720         ed << "Possible symptom of problem wit    720         ed << "Possible symptom of problem with numerical precision" << G4endl;
721         G4Exception("G4PenelopeBremsstrahlungF    721         G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
722         "em2015",JustWarning,ed);                 722         "em2015",JustWarning,ed);
723       }                                           723       }
724     else //real problem                           724     else //real problem
725       {                                           725       {
726         G4ExceptionDescription ed;                726         G4ExceptionDescription ed;
727         ed << "Crash at (pt > (*theTempVec)[fN    727         ed << "Crash at (pt > (*theTempVec)[fNBinsX-1]) with pt = " << pt <<
728     " , (*theTempVec)[fNBinsX-1]=" << (*theTem    728     " , (*theTempVec)[fNBinsX-1]=" << (*theTempVec)[fNBinsX-1] << " and fNBinsX = " <<
729     fNBinsX << G4endl;                            729     fNBinsX << G4endl;
730         ed << "Material: " << mat->GetName() <    730         ed << "Material: " << mat->GetName() << ", energy = " << energy/keV << " keV" <<
731     G4endl;                                       731     G4endl;
732         G4Exception("G4PenelopeBremsstrahlungF    732         G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
733         "em2015",FatalException,ed);              733         "em2015",FatalException,ed);
734       }                                           734       }
735   }                                               735   }
736       else                                        736       else
737   {                                               737   {
738     std::size_t i=0;                              738     std::size_t i=0;
739     std::size_t j=fNBinsX-1;                      739     std::size_t j=fNBinsX-1;
740     while ((j-i)>1)                               740     while ((j-i)>1)
741       {                                           741       {
742         std::size_t k = (i+j)/2;                  742         std::size_t k = (i+j)/2;
743         if (pt > (*theTempVec)[k])                743         if (pt > (*theTempVec)[k])
744     i = k;                                        744     i = k;
745         else                                      745         else
746     j = k;                                        746     j = k;
747       }                                           747       }
748     ibin = i;                                     748     ibin = i;
749   }                                               749   }
750                                                   750 
751       G4double w1 = theXGrid[ibin];               751       G4double w1 = theXGrid[ibin];
752       G4double w2 = theXGrid[ibin+1];             752       G4double w2 = theXGrid[ibin+1];
753                                                   753 
754       const G4PhysicsFreeVector* v1 = (G4Physi    754       const G4PhysicsFreeVector* v1 = (G4PhysicsFreeVector*) (*theTableRed)[ibin];
755       const G4PhysicsFreeVector* v2 = (G4Physi    755       const G4PhysicsFreeVector* v2 = (G4PhysicsFreeVector*) (*theTableRed)[ibin+1];
756       //Remember: the table fReducedXSTable ha    756       //Remember: the table fReducedXSTable has a fake first point in energy
757       //so, it contains one more bin than fNBi    757       //so, it contains one more bin than fNBinsE.
758       G4double pdf1 = G4Exp((*v1)[eBin+1]);       758       G4double pdf1 = G4Exp((*v1)[eBin+1]);
759       G4double pdf2 = G4Exp((*v2)[eBin+1]);       759       G4double pdf2 = G4Exp((*v2)[eBin+1]);
760       G4double deltaW = w2-w1;                    760       G4double deltaW = w2-w1;
761       G4double dpdfb = pdf2-pdf1;                 761       G4double dpdfb = pdf2-pdf1;
762       G4double B = dpdfb/deltaW;                  762       G4double B = dpdfb/deltaW;
763       G4double A = pdf1-B*w1;                     763       G4double A = pdf1-B*w1;
764       //I already made an interpolation in ene    764       //I already made an interpolation in energy, so I can use the actual value for the
765       //calculation of the wbcut, instead of t    765       //calculation of the wbcut, instead of the grid values (except for the last bin)
766       G4double wbcut  = (cut < energy) ? cut/e    766       G4double wbcut  = (cut < energy) ? cut/energy : 1.0;
767       if (firstOrLastBin) //this is an particu    767       if (firstOrLastBin) //this is an particular case: no interpolation available
768   wbcut  = (cut < theEGrid[eBin]) ? cut/theEGr    768   wbcut  = (cut < theEGrid[eBin]) ? cut/theEGrid[eBin] : 1.0;
769                                                   769 
770       if (w1 < wbcut)                             770       if (w1 < wbcut)
771   w1 = wbcut;                                     771   w1 = wbcut;
772       if (w2 < w1)                                772       if (w2 < w1)
773   {                                               773   {
774     //This configuration can happen if initial    774     //This configuration can happen if initially wbcut > w2 > w1. Due to the previous
775     //statement, (w1 = wbcut), it becomes wbcu    775     //statement, (w1 = wbcut), it becomes wbcut = w1 > w2. In this case, it is not a
776     //real problem. It becomes a problem if w2    776     //real problem. It becomes a problem if w2 < w1 before the w1 = wbcut statement. Issue
777     //a warning only in this specific case.       777     //a warning only in this specific case.
778     if (w2 > wbcut)                               778     if (w2 > wbcut)
779       {                                           779       {
780         G4ExceptionDescription ed;                780         G4ExceptionDescription ed;
781         ed << "Warning in G4PenelopeBremsstrah    781         ed << "Warning in G4PenelopeBremsstrahlungFS::SampleX()" << G4endl;
782         ed << "Conflicting end-point values: w    782         ed << "Conflicting end-point values: w1=" << w1 << "; w2 = " << w2 << G4endl;
783         ed << "wbcut = " << wbcut << " energy=    783         ed << "wbcut = " << wbcut << " energy= " << energy/keV << " keV" << G4endl;
784         ed << "cut = " << cut/keV << " keV" <<    784         ed << "cut = " << cut/keV << " keV" << G4endl;
785         G4Exception("G4PenelopeBremsstrahlungF    785         G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()","em2015",
786         JustWarning,ed);                          786         JustWarning,ed);
787       }                                           787       }
788     return w1*energy;                             788     return w1*energy;
789   }                                               789   }
790                                                   790 
791       G4double pmax = std::max(A+B*w1,A+B*w2);    791       G4double pmax = std::max(A+B*w1,A+B*w2);
792       G4bool loopAgain = false;                   792       G4bool loopAgain = false;
793       do                                          793       do
794   {                                               794   {
795     loopAgain = false;                            795     loopAgain = false;
796     eGamma = w1* std::pow((w2/w1),G4UniformRan    796     eGamma = w1* std::pow((w2/w1),G4UniformRand());
797     if  (G4UniformRand()*pmax > (A+B*eGamma))     797     if  (G4UniformRand()*pmax > (A+B*eGamma))
798       loopAgain = true;                           798       loopAgain = true;
799   }while(loopAgain);                              799   }while(loopAgain);
800       eGamma *= energy;                           800       eGamma *= energy;
801       if (nIterations > 100) //protection agai    801       if (nIterations > 100) //protection against infinite loops
802   return eGamma;                                  802   return eGamma;
803     }while(eGamma < cut); //repeat if sampled     803     }while(eGamma < cut); //repeat if sampled sub-cut!
804                                                   804 
805   return eGamma;                                  805   return eGamma;
806 }                                                 806 }
807                                                   807