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.3.p3)


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