Geant4 Cross Reference

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


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 //                                                 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, Penelope v2008
 32 // 24 May 2011   L. Pandola   Renamed (make de     32 // 24 May 2011   L. Pandola   Renamed (make default Penelope)
 33 // 13 Mar 2012   L. Pandola   Updated the inte     33 // 13 Mar 2012   L. Pandola   Updated the interface for the angular generator
 34 // 18 Jul 2012   L. Pandola   Migrate to the n     34 // 18 Jul 2012   L. Pandola   Migrate to the new interface of the angular generator, which
 35 //                            now provides the     35 //                            now provides the G4ThreeVector and takes care of rotation
 36 // 02 Oct 2013   L. Pandola   Migrated to MT       36 // 02 Oct 2013   L. Pandola   Migrated to MT
 37 // 17 Oct 2013   L. Pandola   Partially revert     37 // 17 Oct 2013   L. Pandola   Partially revert the MT migration: the angular generator is
 38 //                             kept as thread-     38 //                             kept as thread-local, and created/managed by the workers.
 39 //                                                 39 //
 40                                                    40 
 41 #include "G4PenelopeBremsstrahlungModel.hh"        41 #include "G4PenelopeBremsstrahlungModel.hh"
 42 #include "G4PhysicalConstants.hh"                  42 #include "G4PhysicalConstants.hh"
 43 #include "G4SystemOfUnits.hh"                      43 #include "G4SystemOfUnits.hh"
 44 #include "G4PenelopeBremsstrahlungFS.hh"           44 #include "G4PenelopeBremsstrahlungFS.hh"
 45 #include "G4PenelopeBremsstrahlungAngular.hh"      45 #include "G4PenelopeBremsstrahlungAngular.hh"
 46 #include "G4ParticleDefinition.hh"                 46 #include "G4ParticleDefinition.hh"
 47 #include "G4MaterialCutsCouple.hh"                 47 #include "G4MaterialCutsCouple.hh"
 48 #include "G4ProductionCutsTable.hh"                48 #include "G4ProductionCutsTable.hh"
 49 #include "G4DynamicParticle.hh"                    49 #include "G4DynamicParticle.hh"
 50 #include "G4Gamma.hh"                              50 #include "G4Gamma.hh"
 51 #include "G4Electron.hh"                           51 #include "G4Electron.hh"
 52 #include "G4Positron.hh"                           52 #include "G4Positron.hh"
 53 #include "G4PenelopeOscillatorManager.hh"          53 #include "G4PenelopeOscillatorManager.hh"
 54 #include "G4PenelopeCrossSection.hh"               54 #include "G4PenelopeCrossSection.hh"
 55 #include "G4PhysicsFreeVector.hh"                  55 #include "G4PhysicsFreeVector.hh"
 56 #include "G4PhysicsLogVector.hh"                   56 #include "G4PhysicsLogVector.hh"
 57 #include "G4PhysicsTable.hh"                       57 #include "G4PhysicsTable.hh"
 58 #include "G4Exp.hh"                                58 #include "G4Exp.hh"
 59                                                    59 
 60 //....oooOO0OOooo........oooOO0OOooo........oo     60 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 61 namespace { G4Mutex  PenelopeBremsstrahlungMod     61 namespace { G4Mutex  PenelopeBremsstrahlungModelMutex = G4MUTEX_INITIALIZER; }
 62                                                    62 
 63 G4PenelopeBremsstrahlungModel::G4PenelopeBrems     63 G4PenelopeBremsstrahlungModel::G4PenelopeBremsstrahlungModel(const G4ParticleDefinition* part,
 64                    const G4String& nam)            64                    const G4String& nam)
 65   :G4VEmModel(nam),fParticleChange(nullptr),fP <<  65   :G4VEmModel(nam),fParticleChange(0),fParticle(0),
 66    fPenelopeFSHelper(nullptr),fPenelopeAngular <<  66    isInitialised(false),energyGrid(0),
 67    fXSTableElectron(nullptr),fXSTablePositron( <<  67    XSTableElectron(0),XSTablePositron(0),fPenelopeFSHelper(0),
 68    fIsInitialised(false),fLocalTable(false)    <<  68    fPenelopeAngular(0),fLocalTable(false)
 69                                                    69 
 70 {                                                  70 {
 71   fIntrinsicLowEnergyLimit = 100.0*eV;             71   fIntrinsicLowEnergyLimit = 100.0*eV;
 72   fIntrinsicHighEnergyLimit = 100.0*GeV;           72   fIntrinsicHighEnergyLimit = 100.0*GeV;
 73   nBins = 200;                                     73   nBins = 200;
 74                                                    74 
 75   if (part)                                        75   if (part)
 76     SetParticle(part);                             76     SetParticle(part);
 77                                                    77 
 78   SetHighEnergyLimit(fIntrinsicHighEnergyLimit     78   SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
 79   //                                               79   //
 80   fOscManager = G4PenelopeOscillatorManager::G <<  80   oscManager = G4PenelopeOscillatorManager::GetOscillatorManager();
 81   //                                               81   //
 82   fVerboseLevel= 0;                            <<  82   verboseLevel= 0;
                                                   >>  83 
 83   // Verbosity scale:                              84   // Verbosity scale:
 84   // 0 = nothing                                   85   // 0 = nothing
 85   // 1 = warning for energy non-conservation       86   // 1 = warning for energy non-conservation
 86   // 2 = details of energy budget                  87   // 2 = details of energy budget
 87   // 3 = calculation of cross sections, file o     88   // 3 = calculation of cross sections, file openings, sampling of atoms
 88   // 4 = entering in methods                       89   // 4 = entering in methods
 89                                                    90 
 90   // Atomic deexcitation model activated by de     91   // Atomic deexcitation model activated by default
 91   SetDeexcitationFlag(true);                       92   SetDeexcitationFlag(true);
 92                                                    93 
 93 }                                                  94 }
 94                                                    95 
 95 //....oooOO0OOooo........oooOO0OOooo........oo     96 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 96                                                    97 
 97 G4PenelopeBremsstrahlungModel::~G4PenelopeBrem     98 G4PenelopeBremsstrahlungModel::~G4PenelopeBremsstrahlungModel()
 98 {                                                  99 {
 99   if (IsMaster() || fLocalTable)                  100   if (IsMaster() || fLocalTable)
100     {                                             101     {
101       ClearTables();                              102       ClearTables();
102       if (fPenelopeFSHelper)                      103       if (fPenelopeFSHelper)
103   delete fPenelopeFSHelper;                       104   delete fPenelopeFSHelper;
104     }                                             105     }
105   // This is thread-local at the moment           106   // This is thread-local at the moment
106   if (fPenelopeAngular)                           107   if (fPenelopeAngular)
107     delete fPenelopeAngular;                      108     delete fPenelopeAngular;
108 }                                                 109 }
109                                                   110 
110 //....oooOO0OOooo........oooOO0OOooo........oo    111 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
111                                                   112 
112 void G4PenelopeBremsstrahlungModel::Initialise    113 void G4PenelopeBremsstrahlungModel::Initialise(const G4ParticleDefinition* part,
113                                              c    114                                              const G4DataVector& theCuts)
114 {                                                 115 {
115   if (fVerboseLevel > 3)                       << 116   if (verboseLevel > 3)
116     G4cout << "Calling G4PenelopeBremsstrahlun    117     G4cout << "Calling G4PenelopeBremsstrahlungModel::Initialise()" << G4endl;
117                                                   118 
118   SetParticle(part);                              119   SetParticle(part);
119                                                   120 
120   if (IsMaster() && part == fParticle)            121   if (IsMaster() && part == fParticle)
121     {                                             122     {
                                                   >> 123 
122       if (!fPenelopeFSHelper)                     124       if (!fPenelopeFSHelper)
123   fPenelopeFSHelper = new G4PenelopeBremsstrah << 125   fPenelopeFSHelper = new G4PenelopeBremsstrahlungFS(verboseLevel);
124       if (!fPenelopeAngular)                      126       if (!fPenelopeAngular)
125   fPenelopeAngular = new G4PenelopeBremsstrahl    127   fPenelopeAngular = new G4PenelopeBremsstrahlungAngular();
126       //Clear and re-build the tables             128       //Clear and re-build the tables
127       ClearTables();                              129       ClearTables();
128                                                   130 
129       //forces the cleaning of tables, in this    131       //forces the cleaning of tables, in this specific case
130       if (fPenelopeAngular)                       132       if (fPenelopeAngular)
131   fPenelopeAngular->Initialize();                 133   fPenelopeAngular->Initialize();
132                                                   134 
133       //Set the number of bins for the tables.    135       //Set the number of bins for the tables. 20 points per decade
134       nBins = (std::size_t) (20*std::log10(Hig << 136       nBins = (size_t) (20*std::log10(HighEnergyLimit()/LowEnergyLimit()));
135       nBins = std::max(nBins,(std::size_t)100) << 137       nBins = std::max(nBins,(size_t)100);
136       fEnergyGrid = new G4PhysicsLogVector(Low << 138       energyGrid = new G4PhysicsLogVector(LowEnergyLimit(),
137                                       HighEner    139                                       HighEnergyLimit(),
138                                       nBins-1)    140                                       nBins-1); //one hidden bin is added
139                                                   141 
140       fXSTableElectron = new                   << 142 
                                                   >> 143       XSTableElectron = new
141   std::map< std::pair<const G4Material*,G4doub    144   std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
142       fXSTablePositron = new                   << 145       XSTablePositron = new
143   std::map< std::pair<const G4Material*,G4doub    146   std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
144                                                   147 
145       G4ProductionCutsTable* theCoupleTable =     148       G4ProductionCutsTable* theCoupleTable =
146   G4ProductionCutsTable::GetProductionCutsTabl    149   G4ProductionCutsTable::GetProductionCutsTable();
147                                                   150 
148       //Build tables for all materials            151       //Build tables for all materials
149       for (G4int i=0;i<(G4int)theCoupleTable-> << 152       for (size_t i=0;i<theCoupleTable->GetTableSize();i++)
150   {                                               153   {
151     const G4Material* theMat =                    154     const G4Material* theMat =
152       theCoupleTable->GetMaterialCutsCouple(i)    155       theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
153     //Forces the building of the helper tables    156     //Forces the building of the helper tables
154     fPenelopeFSHelper->BuildScaledXSTable(theM    157     fPenelopeFSHelper->BuildScaledXSTable(theMat,theCuts.at(i),IsMaster());
155     fPenelopeAngular->PrepareTables(theMat,IsM    158     fPenelopeAngular->PrepareTables(theMat,IsMaster());
156     BuildXSTable(theMat,theCuts.at(i));           159     BuildXSTable(theMat,theCuts.at(i));
157                                                   160 
158   }                                               161   }
159                                                   162 
160       if (fVerboseLevel > 2) {                 << 163 
                                                   >> 164       if (verboseLevel > 2) {
161   G4cout << "Penelope Bremsstrahlung model v20    165   G4cout << "Penelope Bremsstrahlung model v2008 is initialized " << G4endl
162          << "Energy range: "                      166          << "Energy range: "
163          << LowEnergyLimit() / keV << " keV -     167          << LowEnergyLimit() / keV << " keV - "
164          << HighEnergyLimit() / GeV << " GeV."    168          << HighEnergyLimit() / GeV << " GeV."
165          << G4endl;                               169          << G4endl;
166       }                                           170       }
167     }                                             171     }
168                                                   172 
169   if(fIsInitialised) return;                   << 173   if(isInitialised) return;
170   fParticleChange = GetParticleChangeForLoss()    174   fParticleChange = GetParticleChangeForLoss();
171   fIsInitialised = true;                       << 175   isInitialised = true;
172 }                                                 176 }
173                                                   177 
174 //....oooOO0OOooo........oooOO0OOooo........oo << 
175                                                   178 
176 void G4PenelopeBremsstrahlungModel::Initialise    179 void G4PenelopeBremsstrahlungModel::InitialiseLocal(const G4ParticleDefinition* part,
177                 G4VEmModel *masterModel)          180                 G4VEmModel *masterModel)
178 {                                                 181 {
179   if (fVerboseLevel > 3)                       << 182   if (verboseLevel > 3)
180     G4cout << "Calling  G4PenelopeBremsstrahlu    183     G4cout << "Calling  G4PenelopeBremsstrahlungModel::InitialiseLocal()" << G4endl;
                                                   >> 184 
181   //                                              185   //
182   //Check that particle matches: one might hav    186   //Check that particle matches: one might have multiple master models (e.g.
183   //for e+ and e-).                               187   //for e+ and e-).
184   //                                              188   //
185   if (part == fParticle)                          189   if (part == fParticle)
186     {                                             190     {
187       //Get the const table pointers from the     191       //Get the const table pointers from the master to the workers
188       const G4PenelopeBremsstrahlungModel* the    192       const G4PenelopeBremsstrahlungModel* theModel =
189   static_cast<G4PenelopeBremsstrahlungModel*>     193   static_cast<G4PenelopeBremsstrahlungModel*> (masterModel);
190                                                   194 
191       //Copy pointers to the data tables          195       //Copy pointers to the data tables
192       fEnergyGrid = theModel->fEnergyGrid;     << 196       energyGrid = theModel->energyGrid;
193       fXSTableElectron = theModel->fXSTableEle << 197       XSTableElectron = theModel->XSTableElectron;
194       fXSTablePositron = theModel->fXSTablePos << 198       XSTablePositron = theModel->XSTablePositron;
195       fPenelopeFSHelper = theModel->fPenelopeF    199       fPenelopeFSHelper = theModel->fPenelopeFSHelper;
196                                                   200 
                                                   >> 201       //fPenelopeAngular = theModel->fPenelopeAngular;
                                                   >> 202 
197       //created in each thread and initialized    203       //created in each thread and initialized.
198       if (!fPenelopeAngular)                      204       if (!fPenelopeAngular)
199   fPenelopeAngular = new G4PenelopeBremsstrahl    205   fPenelopeAngular = new G4PenelopeBremsstrahlungAngular();
200       //forces the cleaning of tables, in this    206       //forces the cleaning of tables, in this specific case
201       if (fPenelopeAngular)                       207       if (fPenelopeAngular)
202   fPenelopeAngular->Initialize();                 208   fPenelopeAngular->Initialize();
203                                                   209 
204       G4ProductionCutsTable* theCoupleTable =     210       G4ProductionCutsTable* theCoupleTable =
205   G4ProductionCutsTable::GetProductionCutsTabl    211   G4ProductionCutsTable::GetProductionCutsTable();
206       //Build tables for all materials            212       //Build tables for all materials
207       for (G4int i=0;i<(G4int)theCoupleTable-> << 213       for (size_t i=0;i<theCoupleTable->GetTableSize();i++)
208   {                                               214   {
209     const G4Material* theMat =                    215     const G4Material* theMat =
210       theCoupleTable->GetMaterialCutsCouple(i)    216       theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
211     fPenelopeAngular->PrepareTables(theMat,IsM    217     fPenelopeAngular->PrepareTables(theMat,IsMaster());
212   }                                               218   }
213                                                   219 
                                                   >> 220 
214       //copy the data                             221       //copy the data
215       nBins = theModel->nBins;                    222       nBins = theModel->nBins;
216                                                   223 
217       //Same verbosity for all workers, as the    224       //Same verbosity for all workers, as the master
218       fVerboseLevel = theModel->fVerboseLevel; << 225       verboseLevel = theModel->verboseLevel;
219     }                                             226     }
                                                   >> 227 
220   return;                                         228   return;
221 }                                                 229 }
222                                                   230 
223 //....oooOO0OOooo........oooOO0OOooo........oo    231 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
224                                                   232 
225 G4double G4PenelopeBremsstrahlungModel::CrossS    233 G4double G4PenelopeBremsstrahlungModel::CrossSectionPerVolume(const G4Material* material,
226                                            con    234                                            const G4ParticleDefinition* theParticle,
227                                            G4d    235                                            G4double energy,
228                                            G4d    236                                            G4double cutEnergy,
229                                            G4d    237                                            G4double)
230 {                                                 238 {
231   //                                              239   //
232   if (fVerboseLevel > 3)                       << 240   if (verboseLevel > 3)
233     G4cout << "Calling CrossSectionPerVolume()    241     G4cout << "Calling CrossSectionPerVolume() of G4PenelopeBremsstrahlungModel" << G4endl;
234                                                   242 
235   SetupForMaterial(theParticle, material, ener    243   SetupForMaterial(theParticle, material, energy);
                                                   >> 244 
236   G4double crossPerMolecule = 0.;                 245   G4double crossPerMolecule = 0.;
237                                                   246 
238   G4PenelopeCrossSection* theXS = GetCrossSect    247   G4PenelopeCrossSection* theXS = GetCrossSectionTableForCouple(theParticle,material,
239                                                   248                                                                 cutEnergy);
                                                   >> 249 
240   if (theXS)                                      250   if (theXS)
241     crossPerMolecule = theXS->GetHardCrossSect    251     crossPerMolecule = theXS->GetHardCrossSection(energy);
242                                                   252 
243   G4double atomDensity = material->GetTotNbOfA    253   G4double atomDensity = material->GetTotNbOfAtomsPerVolume();
244   G4double atPerMol =  fOscManager->GetAtomsPe << 254   G4double atPerMol =  oscManager->GetAtomsPerMolecule(material);
245                                                   255 
246   if (fVerboseLevel > 3)                       << 256   if (verboseLevel > 3)
247     G4cout << "Material " << material->GetName    257     G4cout << "Material " << material->GetName() << " has " << atPerMol <<
248       "atoms per molecule" << G4endl;             258       "atoms per molecule" << G4endl;
249                                                   259 
250   G4double moleculeDensity = 0.;                  260   G4double moleculeDensity = 0.;
251   if (atPerMol)                                   261   if (atPerMol)
252     moleculeDensity = atomDensity/atPerMol;       262     moleculeDensity = atomDensity/atPerMol;
253                                                   263 
254   G4double crossPerVolume = crossPerMolecule*m    264   G4double crossPerVolume = crossPerMolecule*moleculeDensity;
255                                                   265 
256   if (fVerboseLevel > 2)                       << 266   if (verboseLevel > 2)
257   {                                               267   {
258     G4cout << "G4PenelopeBremsstrahlungModel "    268     G4cout << "G4PenelopeBremsstrahlungModel " << G4endl;
259     G4cout << "Mean free path for gamma emissi    269     G4cout << "Mean free path for gamma emission > " << cutEnergy/keV << " keV at " <<
260       energy/keV << " keV = " << (1./crossPerV    270       energy/keV << " keV = " << (1./crossPerVolume)/mm << " mm" << G4endl;
261   }                                               271   }
262                                                   272 
263   return crossPerVolume;                          273   return crossPerVolume;
264 }                                                 274 }
265                                                   275 
266 //....oooOO0OOooo........oooOO0OOooo........oo    276 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
267                                                   277 
268 //This is a dummy method. Never inkoved by the    278 //This is a dummy method. Never inkoved by the tracking, it just issues
269 //a warning if one tries to get Cross Sections    279 //a warning if one tries to get Cross Sections per Atom via the
270 //G4EmCalculator.                                 280 //G4EmCalculator.
271 G4double G4PenelopeBremsstrahlungModel::Comput    281 G4double G4PenelopeBremsstrahlungModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
272                      G4double,                    282                      G4double,
273                      G4double,                    283                      G4double,
274                      G4double,                    284                      G4double,
275                      G4double,                    285                      G4double,
276                      G4double)                    286                      G4double)
277 {                                                 287 {
278   G4cout << "*** G4PenelopeBremsstrahlungModel    288   G4cout << "*** G4PenelopeBremsstrahlungModel -- WARNING ***" << G4endl;
279   G4cout << "Penelope Bremsstrahlung model v20    289   G4cout << "Penelope Bremsstrahlung model v2008 does not calculate cross section _per atom_ " << G4endl;
280   G4cout << "so the result is always zero. For    290   G4cout << "so the result is always zero. For physics values, please invoke " << G4endl;
281   G4cout << "GetCrossSectionPerVolume() or Get    291   G4cout << "GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" << G4endl;
282   return 0;                                       292   return 0;
283 }                                                 293 }
284                                                   294 
285 //....oooOO0OOooo........oooOO0OOooo........oo    295 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
286                                                   296 
287 G4double G4PenelopeBremsstrahlungModel::Comput    297 G4double G4PenelopeBremsstrahlungModel::ComputeDEDXPerVolume(const G4Material* material,
288                    const G4ParticleDefinition*    298                    const G4ParticleDefinition* theParticle,
289                    G4double kineticEnergy,        299                    G4double kineticEnergy,
290                    G4double cutEnergy)            300                    G4double cutEnergy)
291 {                                                 301 {
292   if (fVerboseLevel > 3)                       << 302   if (verboseLevel > 3)
293     G4cout << "Calling ComputeDEDX() of G4Pene    303     G4cout << "Calling ComputeDEDX() of G4PenelopeBremsstrahlungModel" << G4endl;
294                                                   304 
295   G4PenelopeCrossSection* theXS = GetCrossSect    305   G4PenelopeCrossSection* theXS = GetCrossSectionTableForCouple(theParticle,material,
296                                                   306                                                                 cutEnergy);
297   G4double sPowerPerMolecule = 0.0;               307   G4double sPowerPerMolecule = 0.0;
298   if (theXS)                                      308   if (theXS)
299     sPowerPerMolecule = theXS->GetSoftStopping    309     sPowerPerMolecule = theXS->GetSoftStoppingPower(kineticEnergy);
300                                                   310 
                                                   >> 311 
301   G4double atomDensity = material->GetTotNbOfA    312   G4double atomDensity = material->GetTotNbOfAtomsPerVolume();
302   G4double atPerMol =  fOscManager->GetAtomsPe << 313   G4double atPerMol =  oscManager->GetAtomsPerMolecule(material);
303                                                   314 
304   G4double moleculeDensity = 0.;                  315   G4double moleculeDensity = 0.;
305   if (atPerMol)                                   316   if (atPerMol)
306     moleculeDensity = atomDensity/atPerMol;       317     moleculeDensity = atomDensity/atPerMol;
307                                                   318 
308   G4double sPowerPerVolume = sPowerPerMolecule    319   G4double sPowerPerVolume = sPowerPerMolecule*moleculeDensity;
309                                                   320 
310   if (fVerboseLevel > 2)                       << 321   if (verboseLevel > 2)
311     {                                             322     {
312       G4cout << "G4PenelopeBremsstrahlungModel    323       G4cout << "G4PenelopeBremsstrahlungModel " << G4endl;
313       G4cout << "Stopping power < " << cutEner    324       G4cout << "Stopping power < " << cutEnergy/keV << " keV at " <<
314         kineticEnergy/keV << " keV = " <<         325         kineticEnergy/keV << " keV = " <<
315         sPowerPerVolume/(keV/mm) << " keV/mm"     326         sPowerPerVolume/(keV/mm) << " keV/mm" << G4endl;
316     }                                             327     }
317   return sPowerPerVolume;                         328   return sPowerPerVolume;
318 }                                                 329 }
319                                                   330 
320 //....oooOO0OOooo........oooOO0OOooo........oo    331 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
321                                                   332 
322 void G4PenelopeBremsstrahlungModel::SampleSeco    333 void G4PenelopeBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>*fvect,
323                   const G4MaterialCutsCouple*     334                   const G4MaterialCutsCouple* couple,
324                   const G4DynamicParticle* aDy    335                   const G4DynamicParticle* aDynamicParticle,
325                   G4double cutG,                  336                   G4double cutG,
326                   G4double)                       337                   G4double)
327 {                                                 338 {
328   if (fVerboseLevel > 3)                       << 339   if (verboseLevel > 3)
329     G4cout << "Calling SampleSecondaries() of     340     G4cout << "Calling SampleSecondaries() of G4PenelopeBremsstrahlungModel" << G4endl;
330                                                   341 
331   G4double kineticEnergy = aDynamicParticle->G    342   G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
332   const G4Material* material = couple->GetMate    343   const G4Material* material = couple->GetMaterial();
333                                                   344 
334   if (kineticEnergy <= fIntrinsicLowEnergyLimi    345   if (kineticEnergy <= fIntrinsicLowEnergyLimit)
335    {                                              346    {
336      fParticleChange->SetProposedKineticEnergy    347      fParticleChange->SetProposedKineticEnergy(0.);
337      fParticleChange->ProposeLocalEnergyDeposi    348      fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy);
338      return ;                                     349      return ;
339    }                                              350    }
340                                                   351 
341   G4ParticleMomentum particleDirection0 = aDyn    352   G4ParticleMomentum particleDirection0 = aDynamicParticle->GetMomentumDirection();
342   //This is the momentum                          353   //This is the momentum
343   G4ThreeVector initialMomentum =  aDynamicPar    354   G4ThreeVector initialMomentum =  aDynamicParticle->GetMomentum();
344                                                   355 
345   //Not enough energy to produce a secondary!     356   //Not enough energy to produce a secondary! Return with nothing happened
346   if (kineticEnergy < cutG)                       357   if (kineticEnergy < cutG)
347     return;                                       358     return;
348                                                   359 
349   if (fVerboseLevel > 3)                       << 360   if (verboseLevel > 3)
350     G4cout << "Going to sample gamma energy fo    361     G4cout << "Going to sample gamma energy for: " <<material->GetName() << " " <<
351       "energy = " << kineticEnergy/keV << ", c    362       "energy = " << kineticEnergy/keV << ", cut = " << cutG/keV << G4endl;
352                                                   363 
353    //Sample gamma's energy according to the sp    364    //Sample gamma's energy according to the spectrum
354   G4double gammaEnergy =                          365   G4double gammaEnergy =
355     fPenelopeFSHelper->SampleGammaEnergy(kinet    366     fPenelopeFSHelper->SampleGammaEnergy(kineticEnergy,material,cutG);
356                                                   367 
357   if (fVerboseLevel > 3)                       << 368   if (verboseLevel > 3)
358     G4cout << "Sampled gamma energy: " << gamm    369     G4cout << "Sampled gamma energy: " << gammaEnergy/keV << " keV" << G4endl;
359                                                   370 
360   //Now sample the direction for the Gamma. No    371   //Now sample the direction for the Gamma. Notice that the rotation is already done
361   //Z is unused here, I plug 0. The informatio    372   //Z is unused here, I plug 0. The information is in the material pointer
362    G4ThreeVector gammaDirection1 =                373    G4ThreeVector gammaDirection1 =
363      fPenelopeAngular->SampleDirection(aDynami    374      fPenelopeAngular->SampleDirection(aDynamicParticle,gammaEnergy,0,material);
364                                                   375 
365   if (fVerboseLevel > 3)                       << 376   if (verboseLevel > 3)
366     G4cout << "Sampled cosTheta for e-: " << g    377     G4cout << "Sampled cosTheta for e-: " << gammaDirection1.cosTheta() << G4endl;
367                                                   378 
368   G4double residualPrimaryEnergy = kineticEner    379   G4double residualPrimaryEnergy = kineticEnergy-gammaEnergy;
369   if (residualPrimaryEnergy < 0)                  380   if (residualPrimaryEnergy < 0)
370     {                                             381     {
371       //Ok we have a problem, all energy goes     382       //Ok we have a problem, all energy goes with the gamma
372       gammaEnergy += residualPrimaryEnergy;       383       gammaEnergy += residualPrimaryEnergy;
373       residualPrimaryEnergy = 0.0;                384       residualPrimaryEnergy = 0.0;
374     }                                             385     }
375                                                   386 
376   //Produce final state according to momentum     387   //Produce final state according to momentum conservation
377   G4ThreeVector particleDirection1 = initialMo    388   G4ThreeVector particleDirection1 = initialMomentum - gammaEnergy*gammaDirection1;
378   particleDirection1 = particleDirection1.unit    389   particleDirection1 = particleDirection1.unit(); //normalize
379                                                   390 
380   //Update the primary particle                   391   //Update the primary particle
381   if (residualPrimaryEnergy > 0.)                 392   if (residualPrimaryEnergy > 0.)
382     {                                             393     {
383       fParticleChange->ProposeMomentumDirectio    394       fParticleChange->ProposeMomentumDirection(particleDirection1);
384       fParticleChange->SetProposedKineticEnerg    395       fParticleChange->SetProposedKineticEnergy(residualPrimaryEnergy);
385     }                                             396     }
386   else                                            397   else
387     {                                             398     {
388       fParticleChange->SetProposedKineticEnerg    399       fParticleChange->SetProposedKineticEnergy(0.);
389     }                                             400     }
390                                                   401 
391   //Now produce the photon                        402   //Now produce the photon
392   G4DynamicParticle* theGamma = new G4DynamicP    403   G4DynamicParticle* theGamma = new G4DynamicParticle(G4Gamma::Gamma(),
393                                                   404                                                       gammaDirection1,
394                                                   405                                                       gammaEnergy);
395   fvect->push_back(theGamma);                     406   fvect->push_back(theGamma);
396                                                   407 
397   if (fVerboseLevel > 1)                       << 408   if (verboseLevel > 1)
398     {                                             409     {
399       G4cout << "-----------------------------    410       G4cout << "-----------------------------------------------------------" << G4endl;
400       G4cout << "Energy balance from G4Penelop    411       G4cout << "Energy balance from G4PenelopeBremsstrahlung" << G4endl;
401       G4cout << "Incoming primary energy: " <<    412       G4cout << "Incoming primary energy: " << kineticEnergy/keV << " keV" << G4endl;
402       G4cout << "-----------------------------    413       G4cout << "-----------------------------------------------------------" << G4endl;
403       G4cout << "Outgoing primary energy: " <<    414       G4cout << "Outgoing primary energy: " << residualPrimaryEnergy/keV << " keV" << G4endl;
404       G4cout << "Bremsstrahlung photon " << ga    415       G4cout << "Bremsstrahlung photon " << gammaEnergy/keV << " keV" << G4endl;
405       G4cout << "Total final state: " << (resi    416       G4cout << "Total final state: " << (residualPrimaryEnergy+gammaEnergy)/keV
406              << " keV" << G4endl;                 417              << " keV" << G4endl;
407       G4cout << "-----------------------------    418       G4cout << "-----------------------------------------------------------" << G4endl;
408     }                                             419     }
409                                                   420 
410   if (fVerboseLevel > 0)                       << 421   if (verboseLevel > 0)
411     {                                             422     {
412       G4double energyDiff = std::fabs(residual    423       G4double energyDiff = std::fabs(residualPrimaryEnergy+gammaEnergy-kineticEnergy);
413       if (energyDiff > 0.05*keV)                  424       if (energyDiff > 0.05*keV)
414         G4cout << "Warning from G4PenelopeBrem    425         G4cout << "Warning from G4PenelopeBremsstrahlung: problem with energy conservation: "
415          <<                                       426          <<
416           (residualPrimaryEnergy+gammaEnergy)/    427           (residualPrimaryEnergy+gammaEnergy)/keV <<
417           " keV (final) vs. " <<                  428           " keV (final) vs. " <<
418           kineticEnergy/keV << " keV (initial)    429           kineticEnergy/keV << " keV (initial)" << G4endl;
419     }                                             430     }
420   return;                                         431   return;
421 }                                                 432 }
422                                                   433 
423 //....oooOO0OOooo........oooOO0OOooo........oo    434 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
424                                                   435 
425 void G4PenelopeBremsstrahlungModel::ClearTable    436 void G4PenelopeBremsstrahlungModel::ClearTables()
426 {                                                 437 {
427   if (!IsMaster() && !fLocalTable)                438   if (!IsMaster() && !fLocalTable)
428     //Should not be here!                         439     //Should not be here!
429     G4Exception("G4PenelopeBremsstrahlungModel    440     G4Exception("G4PenelopeBremsstrahlungModel::ClearTables()",
430     "em0100",FatalException,"Worker thread in     441     "em0100",FatalException,"Worker thread in this method");
431                                                   442 
432   if (fXSTableElectron)                        << 443   if (XSTableElectron)
433     {                                             444     {
434       for (auto& item : (*fXSTableElectron))   << 445       for (auto& item : (*XSTableElectron))        
435   delete item.second;                             446   delete item.second;        
436       delete fXSTableElectron;                 << 447       delete XSTableElectron;
437       fXSTableElectron = nullptr;              << 448       XSTableElectron = nullptr;
438     }                                             449     }
439   if (fXSTablePositron)                        << 450   if (XSTablePositron)
440     {                                             451     {
441       for (auto& item : (*fXSTablePositron))   << 452       for (auto& item : (*XSTablePositron))                
442   delete item.second;                             453   delete item.second;    
443       delete fXSTablePositron;                 << 454       delete XSTablePositron;
444       fXSTablePositron = nullptr;              << 455       XSTablePositron = nullptr;
445     }                                             456     }
446   /*                                              457   /*
447   if (fEnergyGrid)                             << 458   if (energyGrid)
448     delete fEnergyGrid;                        << 459     delete energyGrid;
449   */                                              460   */
450   if (fPenelopeFSHelper)                          461   if (fPenelopeFSHelper)
451     fPenelopeFSHelper->ClearTables(IsMaster())    462     fPenelopeFSHelper->ClearTables(IsMaster());
452                                                   463 
453   if (fVerboseLevel > 2)                       << 464   if (verboseLevel > 2)
454     G4cout << "G4PenelopeBremsstrahlungModel:     465     G4cout << "G4PenelopeBremsstrahlungModel: cleared tables" << G4endl;
455                                                   466 
456  return;                                          467  return;
457 }                                                 468 }
458                                                   469 
459 //....oooOO0OOooo........oooOO0OOooo........oo    470 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
460                                                   471 
461 G4double G4PenelopeBremsstrahlungModel::MinEne    472 G4double G4PenelopeBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
462                    const G4MaterialCutsCouple*    473                    const G4MaterialCutsCouple*)
463 {                                                 474 {
464   return fIntrinsicLowEnergyLimit;                475   return fIntrinsicLowEnergyLimit;
465 }                                                 476 }
466                                                   477 
467 //....oooOO0OOooo........oooOO0OOooo........oo    478 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
468                                                   479 
469 void G4PenelopeBremsstrahlungModel::BuildXSTab    480 void G4PenelopeBremsstrahlungModel::BuildXSTable(const G4Material* mat,G4double cut)
470 {                                                 481 {
471   if (!IsMaster() && !fLocalTable)                482   if (!IsMaster() && !fLocalTable)
472     //Should not be here!                         483     //Should not be here!
473     G4Exception("G4PenelopeBremsstrahlungModel    484     G4Exception("G4PenelopeBremsstrahlungModel::BuildXSTable()",
474     "em0100",FatalException,"Worker thread in     485     "em0100",FatalException,"Worker thread in this method");
475                                                   486 
476   //The key of the map                            487   //The key of the map
477   std::pair<const G4Material*,G4double> theKey    488   std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
478                                                   489 
479   //The table already exists                      490   //The table already exists
480   if (fXSTableElectron->count(theKey) && fXSTa << 491   if (XSTableElectron->count(theKey) && XSTablePositron->count(theKey))
481     return;                                       492     return;
482                                                   493 
483   //                                              494   //
484   //This method fills the G4PenelopeCrossSecti    495   //This method fills the G4PenelopeCrossSection containers for electrons or positrons
485   //and for the given material/cut couple.        496   //and for the given material/cut couple.
486   //Equivalent of subroutines EBRaT and PINaT     497   //Equivalent of subroutines EBRaT and PINaT of Penelope
487   //                                              498   //
488   if (fVerboseLevel > 2)                       << 499   if (verboseLevel > 2)
489     {                                             500     {
490       G4cout << "G4PenelopeBremsstrahlungModel    501       G4cout << "G4PenelopeBremsstrahlungModel: going to build cross section table " << G4endl;
491       G4cout << "for e+/e- in " << mat->GetNam    502       G4cout << "for e+/e- in " << mat->GetName() << " for Ecut(gamma)= " <<
492   cut/keV << " keV " << G4endl;                   503   cut/keV << " keV " << G4endl;
493     }                                             504     }
494                                                   505 
495   //Tables have been already created (checked     506   //Tables have been already created (checked by GetCrossSectionTableForCouple)
496   if (fEnergyGrid->GetVectorLength() != nBins) << 507   if (energyGrid->GetVectorLength() != nBins)
497     {                                             508     {
498       G4ExceptionDescription ed;                  509       G4ExceptionDescription ed;
499       ed << "Energy Grid looks not initialized    510       ed << "Energy Grid looks not initialized" << G4endl;
500       ed << nBins << " " << fEnergyGrid->GetVe << 511       ed << nBins << " " << energyGrid->GetVectorLength() << G4endl;
501       G4Exception("G4PenelopeBremsstrahlungMod    512       G4Exception("G4PenelopeBremsstrahlungModel::BuildXSTable()",
502       "em2016",FatalException,ed);                513       "em2016",FatalException,ed);
503     }                                             514     }
504                                                   515 
505   G4PenelopeCrossSection* XSEntry = new G4Pene    516   G4PenelopeCrossSection* XSEntry = new G4PenelopeCrossSection(nBins);
506   G4PenelopeCrossSection* XSEntry2 = new G4Pen    517   G4PenelopeCrossSection* XSEntry2 = new G4PenelopeCrossSection(nBins);
                                                   >> 518 
507   const G4PhysicsTable* table = fPenelopeFSHel    519   const G4PhysicsTable* table = fPenelopeFSHelper->GetScaledXSTable(mat,cut);
508                                                   520 
                                                   >> 521 
509   //loop on the energy grid                       522   //loop on the energy grid
510   for (std::size_t bin=0;bin<nBins;++bin)      << 523   for (size_t bin=0;bin<nBins;bin++)
511     {                                             524     {
512        G4double energy = fEnergyGrid->GetLowEd << 525        G4double energy = energyGrid->GetLowEdgeEnergy(bin);
513        G4double XH0=0, XH1=0, XH2=0;              526        G4double XH0=0, XH1=0, XH2=0;
514        G4double XS0=0, XS1=0, XS2=0;              527        G4double XS0=0, XS1=0, XS2=0;
515                                                   528 
516        //Global xs factor                         529        //Global xs factor
517        G4double fact = fPenelopeFSHelper->GetE    530        G4double fact = fPenelopeFSHelper->GetEffectiveZSquared(mat)*
518    ((energy+electron_mass_c2)*(energy+electron    531    ((energy+electron_mass_c2)*(energy+electron_mass_c2)/
519     (energy*(energy+2.0*electron_mass_c2)));      532     (energy*(energy+2.0*electron_mass_c2)));
520                                                   533 
521        G4double restrictedCut = cut/energy;       534        G4double restrictedCut = cut/energy;
522                                                   535 
523        //Now I need the dSigma/dX profile - in    536        //Now I need the dSigma/dX profile - interpolated on energy - for
524        //the 32-point x grid. Interpolation is    537        //the 32-point x grid. Interpolation is log-log
525        std::size_t nBinsX = fPenelopeFSHelper- << 538        size_t nBinsX = fPenelopeFSHelper->GetNBinsX();
526        G4double* tempData = new G4double[nBins    539        G4double* tempData = new G4double[nBinsX];
527        G4double logene = G4Log(energy);        << 540        G4double logene = std::log(energy);
528        for (std::size_t ix=0;ix<nBinsX;++ix)   << 541        for (size_t ix=0;ix<nBinsX;ix++)
529    {                                              542    {
530      //find dSigma/dx for the given E. X belon    543      //find dSigma/dx for the given E. X belongs to the 32-point grid.
531      G4double val = (*table)[ix]->Value(logene    544      G4double val = (*table)[ix]->Value(logene);
532      tempData[ix] = G4Exp(val); //back to the     545      tempData[ix] = G4Exp(val); //back to the real value!
533    }                                              546    }
534                                                   547 
535        G4double XH0A = 0.;                        548        G4double XH0A = 0.;
536        if (restrictedCut <= 1) //calculate onl    549        if (restrictedCut <= 1) //calculate only if we are above threshold!
537    XH0A = fPenelopeFSHelper->GetMomentumIntegr    550    XH0A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,-1) -
538      fPenelopeFSHelper->GetMomentumIntegral(te    551      fPenelopeFSHelper->GetMomentumIntegral(tempData,restrictedCut,-1);
539        G4double XS1A = fPenelopeFSHelper->GetM    552        G4double XS1A = fPenelopeFSHelper->GetMomentumIntegral(tempData,
540                     restrictedCut,0);             553                     restrictedCut,0);
541        G4double XS2A = fPenelopeFSHelper->GetM    554        G4double XS2A = fPenelopeFSHelper->GetMomentumIntegral(tempData,
542                     restrictedCut,1);             555                     restrictedCut,1);
543        G4double XH1A=0, XH2A=0;                   556        G4double XH1A=0, XH2A=0;
544        if (restrictedCut <=1)                     557        if (restrictedCut <=1)
545    {                                              558    {
546      XH1A = fPenelopeFSHelper->GetMomentumInte    559      XH1A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,0) -
547        XS1A;                                      560        XS1A;
548      XH2A = fPenelopeFSHelper->GetMomentumInte    561      XH2A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,1) -
549        XS2A;                                      562        XS2A;
550    }                                              563    }
551        delete[] tempData;                         564        delete[] tempData;
552                                                   565 
553        XH0 = XH0A*fact;                           566        XH0 = XH0A*fact;
554        XS1 = XS1A*fact*energy;                    567        XS1 = XS1A*fact*energy;
555        XH1 = XH1A*fact*energy;                    568        XH1 = XH1A*fact*energy;
556        XS2 = XS2A*fact*energy*energy;             569        XS2 = XS2A*fact*energy*energy;
557        XH2 = XH2A*fact*energy*energy;             570        XH2 = XH2A*fact*energy*energy;
558                                                   571 
559        XSEntry->AddCrossSectionPoint(bin,energ    572        XSEntry->AddCrossSectionPoint(bin,energy,XH0,XH1,XH2,XS0,XS1,XS2);
560                                                   573 
561        //take care of positrons                   574        //take care of positrons
562        G4double posCorrection = GetPositronXSC    575        G4double posCorrection = GetPositronXSCorrection(mat,energy);
563        XSEntry2->AddCrossSectionPoint(bin,ener    576        XSEntry2->AddCrossSectionPoint(bin,energy,XH0*posCorrection,
564               XH1*posCorrection,                  577               XH1*posCorrection,
565               XH2*posCorrection,                  578               XH2*posCorrection,
566               XS0,                                579               XS0,
567               XS1*posCorrection,                  580               XS1*posCorrection,
568               XS2*posCorrection);                 581               XS2*posCorrection);
569     }                                             582     }
570                                                   583 
571   //Insert in the appropriate table               584   //Insert in the appropriate table
572   fXSTableElectron->insert(std::make_pair(theK << 585   XSTableElectron->insert(std::make_pair(theKey,XSEntry));
573   fXSTablePositron->insert(std::make_pair(theK << 586   XSTablePositron->insert(std::make_pair(theKey,XSEntry2));
574                                                   587 
575   return;                                         588   return;
576 }                                                 589 }
577                                                   590 
578                                                   591 
579 //....oooOO0OOooo........oooOO0OOooo........oo    592 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
580                                                   593 
581 G4PenelopeCrossSection*                           594 G4PenelopeCrossSection*
582 G4PenelopeBremsstrahlungModel::GetCrossSection    595 G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple(const G4ParticleDefinition* part,
583                    const G4Material* mat,         596                    const G4Material* mat,
584                    G4double cut)                  597                    G4double cut)
585 {                                                 598 {
586   if (part != G4Electron::Electron() && part !    599   if (part != G4Electron::Electron() && part != G4Positron::Positron())
587     {                                             600     {
588       G4ExceptionDescription ed;                  601       G4ExceptionDescription ed;
589       ed << "Invalid particle: " << part->GetP    602       ed << "Invalid particle: " << part->GetParticleName() << G4endl;
590       G4Exception("G4PenelopeBremsstrahlungMod    603       G4Exception("G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
591       "em0001",FatalException,ed);                604       "em0001",FatalException,ed);
592       return nullptr;                             605       return nullptr;
593     }                                             606     }
594                                                   607 
595   if (part == G4Electron::Electron())             608   if (part == G4Electron::Electron())
596     {                                             609     {
597       //Either Initialize() was not called, or    610       //Either Initialize() was not called, or we are in a slave and InitializeLocal() was
598       //not invoked                               611       //not invoked
599       if (!fXSTableElectron)                   << 612       if (!XSTableElectron)
600         {                                         613         {
601     //create a **thread-local** version of the    614     //create a **thread-local** version of the table. Used only for G4EmCalculator and
602     //Unit Tests                                  615     //Unit Tests
603           G4String excep = "The Cross Section     616           G4String excep = "The Cross Section Table for e- was not initialized correctly!";
604           G4Exception("G4PenelopeBremsstrahlun    617           G4Exception("G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
605           "em2013",JustWarning,excep);            618           "em2013",JustWarning,excep);
606     fLocalTable = true;                           619     fLocalTable = true;
607     fXSTableElectron = new                     << 620     XSTableElectron = new
608       std::map< std::pair<const G4Material*,G4    621       std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
609     if (!fEnergyGrid)                          << 622     if (!energyGrid)
610       fEnergyGrid = new G4PhysicsLogVector(Low << 623       energyGrid = new G4PhysicsLogVector(LowEnergyLimit(),
611             HighEnergyLimit(),                    624             HighEnergyLimit(),
612             nBins-1); //one hidden bin is adde    625             nBins-1); //one hidden bin is added
613     if (!fPenelopeFSHelper)                       626     if (!fPenelopeFSHelper)
614       fPenelopeFSHelper = new G4PenelopeBremss << 627       fPenelopeFSHelper = new G4PenelopeBremsstrahlungFS(verboseLevel);
615         }                                         628         }
616       std::pair<const G4Material*,G4double> th    629       std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
617       if (fXSTableElectron->count(theKey)) //t << 630       if (XSTableElectron->count(theKey)) //table already built
618         return fXSTableElectron->find(theKey)- << 631         return XSTableElectron->find(theKey)->second;
619       else                                        632       else
620   {                                               633   {
621     //If we are here, it means that Initialize    634     //If we are here, it means that Initialize() was inkoved, but the MaterialTable was
622     //not filled up. This can happen in a Unit    635     //not filled up. This can happen in a UnitTest or via G4EmCalculator
623     if (fVerboseLevel > 0)                     << 636     if (verboseLevel > 0)
624       {                                           637       {
625         //G4Exception (warning) is issued only    638         //G4Exception (warning) is issued only in verbose mode
626         G4ExceptionDescription ed;                639         G4ExceptionDescription ed;
627         ed << "Unable to find e- table for " <    640         ed << "Unable to find e- table for " << mat->GetName() << " at Ecut(gamma)= "
628      << cut/keV << " keV " << G4endl;             641      << cut/keV << " keV " << G4endl;
629         ed << "This can happen only in Unit Te    642         ed << "This can happen only in Unit Tests or via G4EmCalculator" << G4endl;
630         G4Exception("G4PenelopeBremsstrahlungM    643         G4Exception("G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
631         "em2009",JustWarning,ed);                 644         "em2009",JustWarning,ed);
632       }                                           645       }
633     //protect file reading via autolock           646     //protect file reading via autolock
634     G4AutoLock lock(&PenelopeBremsstrahlungMod    647     G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
635           fPenelopeFSHelper->BuildScaledXSTabl    648           fPenelopeFSHelper->BuildScaledXSTable(mat,cut,true); //pretend to be a master
636     BuildXSTable(mat,cut);                        649     BuildXSTable(mat,cut);
637     lock.unlock();                                650     lock.unlock();
638     //now it should be ok                         651     //now it should be ok
639     return fXSTableElectron->find(theKey)->sec << 652     return XSTableElectron->find(theKey)->second;
640   }                                               653   }
                                                   >> 654 
641     }                                             655     }
642   if (part == G4Positron::Positron())             656   if (part == G4Positron::Positron())
643     {                                             657     {
644       //Either Initialize() was not called, or    658       //Either Initialize() was not called, or we are in a slave and InitializeLocal() was
645       //not invoked                               659       //not invoked
646       if (!fXSTablePositron)                   << 660       if (!XSTablePositron)
647         {                                         661         {
648     G4String excep = "The Cross Section Table     662     G4String excep = "The Cross Section Table for e+ was not initialized correctly!";
649           G4Exception("G4PenelopeBremsstrahlun    663           G4Exception("G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
650           "em2013",JustWarning,excep);            664           "em2013",JustWarning,excep);
651     fLocalTable = true;                           665     fLocalTable = true;
652     fXSTablePositron = new                     << 666     XSTablePositron = new
653       std::map< std::pair<const G4Material*,G4    667       std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
654     if (!fEnergyGrid)                          << 668     if (!energyGrid)
655       fEnergyGrid = new G4PhysicsLogVector(Low << 669       energyGrid = new G4PhysicsLogVector(LowEnergyLimit(),
656             HighEnergyLimit(),                    670             HighEnergyLimit(),
657             nBins-1); //one hidden bin is adde    671             nBins-1); //one hidden bin is added
658     if (!fPenelopeFSHelper)                       672     if (!fPenelopeFSHelper)
659             fPenelopeFSHelper = new G4Penelope << 673             fPenelopeFSHelper = new G4PenelopeBremsstrahlungFS(verboseLevel);
660         }                                         674         }
661       std::pair<const G4Material*,G4double> th    675       std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
662       if (fXSTablePositron->count(theKey)) //t << 676       if (XSTablePositron->count(theKey)) //table already built
663         return fXSTablePositron->find(theKey)- << 677         return XSTablePositron->find(theKey)->second;
664       else                                        678       else
665         {                                         679         {
666     //If we are here, it means that Initialize    680     //If we are here, it means that Initialize() was inkoved, but the MaterialTable was
667     //not filled up. This can happen in a Unit    681     //not filled up. This can happen in a UnitTest or via G4EmCalculator
668     if (fVerboseLevel > 0)                     << 682     if (verboseLevel > 0)
669       {                                           683       {
670         //Issue a G4Exception (warning) only i    684         //Issue a G4Exception (warning) only in verbose mode
671         G4ExceptionDescription ed;                685         G4ExceptionDescription ed;
672         ed << "Unable to find e+ table for " <    686         ed << "Unable to find e+ table for " << mat->GetName() << " at Ecut(gamma)= "
673      << cut/keV << " keV " << G4endl;             687      << cut/keV << " keV " << G4endl;
674         ed << "This can happen only in Unit Te    688         ed << "This can happen only in Unit Tests or via G4EmCalculator" << G4endl;
675         G4Exception("G4PenelopeBremsstrahlungM    689         G4Exception("G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
676         "em2009",JustWarning,ed);                 690         "em2009",JustWarning,ed);
677       }                                           691       }
678     //protect file reading via autolock           692     //protect file reading via autolock
679     G4AutoLock lock(&PenelopeBremsstrahlungMod    693     G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
680           fPenelopeFSHelper->BuildScaledXSTabl    694           fPenelopeFSHelper->BuildScaledXSTable(mat,cut,true); //pretend to be a master
681     BuildXSTable(mat,cut);                        695     BuildXSTable(mat,cut);
682     lock.unlock();                                696     lock.unlock();
683     //now it should be ok                         697     //now it should be ok
684     return fXSTablePositron->find(theKey)->sec << 698     return XSTablePositron->find(theKey)->second;
685         }                                         699         }
686     }                                             700     }
687   return nullptr;                                 701   return nullptr;
688 }                                                 702 }
689                                                   703 
                                                   >> 704 
                                                   >> 705 
690 //....oooOO0OOooo........oooOO0OOooo........oo    706 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
691                                                   707 
692 G4double G4PenelopeBremsstrahlungModel::GetPos    708 G4double G4PenelopeBremsstrahlungModel::GetPositronXSCorrection(const G4Material* mat,
693                   G4double energy)                709                   G4double energy)
694 {                                                 710 {
695   //The electron-to-positron correction factor    711   //The electron-to-positron correction factor is set equal to the ratio of the
696   //radiative stopping powers for positrons an    712   //radiative stopping powers for positrons and electrons, which has been calculated
697   //by Kim et al. (1986) (cf. Berger and Seltz    713   //by Kim et al. (1986) (cf. Berger and Seltzer, 1982). Here, it is used an
698   //analytical approximation which reproduces     714   //analytical approximation which reproduces the tabulated values with 0.5%
699   //accuracy                                      715   //accuracy
700   G4double t=G4Log(1.0+1e6*energy/             << 716   G4double t=std::log(1.0+1e6*energy/
701           (electron_mass_c2*fPenelopeFSHelper-    717           (electron_mass_c2*fPenelopeFSHelper->GetEffectiveZSquared(mat)));
702   G4double corr = 1.0-G4Exp(-t*(1.2359e-1-t*(6    718   G4double corr = 1.0-G4Exp(-t*(1.2359e-1-t*(6.1274e-2-t*
703              (3.1516e-2-t*(7.7446e-3-t*(1.0595    719              (3.1516e-2-t*(7.7446e-3-t*(1.0595e-3-t*
704                       (7.0568e-5-t*               720                       (7.0568e-5-t*
705                        1.8080e-6)))))));          721                        1.8080e-6)))))));
706   return corr;                                    722   return corr;
707 }                                                 723 }
708                                                   724 
709 //....oooOO0OOooo........oooOO0OOooo........oo    725 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
710                                                   726 
711 void G4PenelopeBremsstrahlungModel::SetParticl    727 void G4PenelopeBremsstrahlungModel::SetParticle(const G4ParticleDefinition* p)
712 {                                                 728 {
713   if(!fParticle) {                                729   if(!fParticle) {
714     fParticle = p;                                730     fParticle = p;
715   }                                               731   }
716 }                                                 732 }
717                                                   733