Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4LivermorePolarizedComptonModel.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/G4LivermorePolarizedComptonModel.cc (Version 11.3.0) and /processes/electromagnetic/lowenergy/src/G4LivermorePolarizedComptonModel.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: G4LivermorePolarizedComptonModel.cc 95950 2016-03-03 10:42:48Z gcosmo $
 26 //                                                 27 //
 27 // Authors: G.Depaola & F.Longo                    28 // Authors: G.Depaola & F.Longo
 28 //                                                 29 //
 29 // History:                                        30 // History:
 30 // -------                                     <<  31 // --------
 31 //                                             << 
 32 // 05 Apr 2021   J Allison added quantum entan << 
 33 // If the photons have been "tagged" as "quant << 
 34 // G4eplusAnnihilation for annihilation into 2 << 
 35 // here if - and only if - both photons suffer << 
 36 // predictions from Pryce and Ward, Nature No  << 
 37 // Physical Review 73 (1948) p.440. Experiment << 
 38 // entanglement in the MeV regime and its appl << 
 39 // D. Watts, J. Allison et al., Nature Communi << 
 40 // https://doi.org/10.1038/s41467-021-22907-5. << 
 41 //                                             << 
 42 // 02 May 2009   S Incerti as V. Ivanchenko pr     32 // 02 May 2009   S Incerti as V. Ivanchenko proposed in G4LivermoreComptonModel.cc
 43 //                                                 33 //
 44 // Cleanup initialisation and generation of se     34 // Cleanup initialisation and generation of secondaries:
 45 //                  - apply internal high-ener     35 //                  - apply internal high-energy limit only in constructor 
 46 //                  - do not apply low-energy      36 //                  - do not apply low-energy limit (default is 0)
 47 //                  - remove GetMeanFreePath m     37 //                  - remove GetMeanFreePath method and table
 48 //                  - added protection against     38 //                  - added protection against numerical problem in energy sampling 
 49 //                  - use G4ElementSelector        39 //                  - use G4ElementSelector
 50                                                    40 
 51 #include "G4LivermorePolarizedComptonModel.hh"     41 #include "G4LivermorePolarizedComptonModel.hh"
 52 #include "G4PhysicalConstants.hh"                  42 #include "G4PhysicalConstants.hh"
 53 #include "G4SystemOfUnits.hh"                      43 #include "G4SystemOfUnits.hh"
 54 #include "G4AutoLock.hh"                       << 
 55 #include "G4Electron.hh"                           44 #include "G4Electron.hh"
 56 #include "G4ParticleChangeForGamma.hh"             45 #include "G4ParticleChangeForGamma.hh"
 57 #include "G4LossTableManager.hh"                   46 #include "G4LossTableManager.hh"
 58 #include "G4VAtomDeexcitation.hh"                  47 #include "G4VAtomDeexcitation.hh"
 59 #include "G4AtomicShell.hh"                        48 #include "G4AtomicShell.hh"
 60 #include "G4Gamma.hh"                              49 #include "G4Gamma.hh"
 61 #include "G4ShellData.hh"                          50 #include "G4ShellData.hh"
 62 #include "G4DopplerProfile.hh"                     51 #include "G4DopplerProfile.hh"
 63 #include "G4Log.hh"                                52 #include "G4Log.hh"
 64 #include "G4Exp.hh"                                53 #include "G4Exp.hh"
 65 #include "G4Pow.hh"                            << 
 66 #include "G4LogLogInterpolation.hh"                54 #include "G4LogLogInterpolation.hh"
 67 #include "G4PhysicsModelCatalog.hh"            << 
 68 #include "G4EntanglementAuxInfo.hh"            << 
 69 #include "G4eplusAnnihilationEntanglementClipB << 
 70                                                    55 
 71 //....oooOO0OOooo........oooOO0OOooo........oo     56 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 72                                                    57 
 73 using namespace std;                               58 using namespace std;
 74 namespace { G4Mutex LivermorePolarizedComptonM << 
 75                                                    59 
                                                   >>  60 G4int G4LivermorePolarizedComptonModel::maxZ = 99;
                                                   >>  61 G4LPhysicsFreeVector* G4LivermorePolarizedComptonModel::data[] = {0};
                                                   >>  62 G4ShellData*       G4LivermorePolarizedComptonModel::shellData = 0;
                                                   >>  63 G4DopplerProfile*  G4LivermorePolarizedComptonModel::profileData = 0; 
                                                   >>  64 G4CompositeEMDataSet* G4LivermorePolarizedComptonModel::scatterFunctionData = 0;
 76                                                    65 
 77 G4PhysicsFreeVector* G4LivermorePolarizedCompt <<  66 //static const G4double ln10 = G4Log(10.);
 78 G4ShellData*       G4LivermorePolarizedCompton << 
 79 G4DopplerProfile*  G4LivermorePolarizedCompton << 
 80 G4CompositeEMDataSet* G4LivermorePolarizedComp << 
 81                                                    67 
 82 //....oooOO0OOooo........oooOO0OOooo........oo     68 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 83                                                    69 
 84 G4LivermorePolarizedComptonModel::G4LivermoreP     70 G4LivermorePolarizedComptonModel::G4LivermorePolarizedComptonModel(const G4ParticleDefinition*, const G4String& nam)
 85   :G4VEmModel(nam),isInitialised(false)            71   :G4VEmModel(nam),isInitialised(false)
 86 {                                                  72 { 
 87   verboseLevel= 1;                                 73   verboseLevel= 1;
 88   // Verbosity scale:                              74   // Verbosity scale:
 89   // 0 = nothing                                   75   // 0 = nothing 
 90   // 1 = warning for energy non-conservation       76   // 1 = warning for energy non-conservation 
 91   // 2 = details of energy budget                  77   // 2 = details of energy budget
 92   // 3 = calculation of cross sections, file o     78   // 3 = calculation of cross sections, file openings, sampling of atoms
 93   // 4 = entering in methods                       79   // 4 = entering in methods
 94                                                    80 
 95   if( verboseLevel>1 )                             81   if( verboseLevel>1 )  
 96     G4cout << "Livermore Polarized Compton is      82     G4cout << "Livermore Polarized Compton is constructed " << G4endl;
 97                                                    83         
 98   //Mark this model as "applicable" for atomic     84   //Mark this model as "applicable" for atomic deexcitation
 99   SetDeexcitationFlag(true);                       85   SetDeexcitationFlag(true);
100                                                    86   
101   fParticleChange = nullptr;                   <<  87   fParticleChange = 0;
102   fAtomDeexcitation = nullptr;                 <<  88   fAtomDeexcitation = 0;
103   fEntanglementModelID = G4PhysicsModelCatalog << 
104 }                                                  89 }
105                                                    90 
106 //....oooOO0OOooo........oooOO0OOooo........oo     91 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
107                                                    92 
108 G4LivermorePolarizedComptonModel::~G4Livermore     93 G4LivermorePolarizedComptonModel::~G4LivermorePolarizedComptonModel()
109 {                                                  94 {  
110   if(IsMaster()) {                                 95   if(IsMaster()) {
111     delete shellData;                              96     delete shellData;
112     shellData = nullptr;                       <<  97     shellData = 0;
113     delete profileData;                            98     delete profileData;
114     profileData = nullptr;                     <<  99     profileData = 0;
115     delete scatterFunctionData;                   100     delete scatterFunctionData;
116     scatterFunctionData = nullptr;             << 101     scatterFunctionData = 0;
117     for(G4int i=0; i<maxZ; ++i) {                 102     for(G4int i=0; i<maxZ; ++i) {
118       if(data[i]) {                               103       if(data[i]) { 
119   delete data[i];                                 104   delete data[i];
120   data[i] = nullptr;                           << 105   data[i] = 0;
121       }                                           106       }
122     }                                             107     }
123   }                                               108   }
124 }                                                 109 }
125                                                   110 
126 //....oooOO0OOooo........oooOO0OOooo........oo    111 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
127                                                   112 
128 void G4LivermorePolarizedComptonModel::Initial    113 void G4LivermorePolarizedComptonModel::Initialise(const G4ParticleDefinition* particle,
129                                        const G    114                                        const G4DataVector& cuts)
130 {                                                 115 {
131   if (verboseLevel > 1)                           116   if (verboseLevel > 1)
132     G4cout << "Calling G4LivermorePolarizedCom    117     G4cout << "Calling G4LivermorePolarizedComptonModel::Initialise()" << G4endl;
133                                                   118 
134   // Initialise element selector                  119   // Initialise element selector 
                                                   >> 120 
135   if(IsMaster()) {                                121   if(IsMaster()) {
                                                   >> 122     
136     // Access to elements                         123     // Access to elements 
137     const char* path = G4FindDataDir("G4LEDATA << 124 
                                                   >> 125     char* path = getenv("G4LEDATA");
138                                                   126 
139     G4ProductionCutsTable* theCoupleTable =       127     G4ProductionCutsTable* theCoupleTable = 
140       G4ProductionCutsTable::GetProductionCuts    128       G4ProductionCutsTable::GetProductionCutsTable();
141                                                   129 
142     G4int numOfCouples = (G4int)theCoupleTable << 130     G4int numOfCouples = theCoupleTable->GetTableSize();
143                                                   131     
144     for(G4int i=0; i<numOfCouples; ++i) {         132     for(G4int i=0; i<numOfCouples; ++i) {
145       const G4Material* material =                133       const G4Material* material = 
146         theCoupleTable->GetMaterialCutsCouple( << 134   theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
147       const G4ElementVector* theElementVector     135       const G4ElementVector* theElementVector = material->GetElementVector();
148       std::size_t nelm = material->GetNumberOf << 136       G4int nelm = material->GetNumberOfElements();
149                                                   137       
150       for (std::size_t j=0; j<nelm; ++j) {     << 138       for (G4int j=0; j<nelm; ++j) {
151         G4int Z = G4lrint((*theElementVector)[ << 139   G4int Z = G4lrint((*theElementVector)[j]->GetZ());
152         if(Z < 1)        { Z = 1; }            << 140   if(Z < 1)        { Z = 1; }
153         else if(Z > maxZ){ Z = maxZ; }         << 141   else if(Z > maxZ){ Z = maxZ; }
154                                                << 142   
155         if( (!data[Z]) ) { ReadData(Z, path);  << 143   if( (!data[Z]) ) { ReadData(Z, path); }
156       }                                           144       }
157     }                                             145     }
158                                                   146     
159     // For Doppler broadening                     147     // For Doppler broadening
160     if(!shellData) {                              148     if(!shellData) {
161       shellData = new G4ShellData();              149       shellData = new G4ShellData(); 
162       shellData->SetOccupancyData();              150       shellData->SetOccupancyData();
163       G4String file = "/doppler/shell-doppler"    151       G4String file = "/doppler/shell-doppler";
164       shellData->LoadData(file);                  152       shellData->LoadData(file);
165     }                                             153     }
166     if(!profileData) { profileData = new G4Dop    154     if(!profileData) { profileData = new G4DopplerProfile(); }
167                                                   155 
168     // Scattering Function                        156     // Scattering Function 
                                                   >> 157     
169     if(!scatterFunctionData)                      158     if(!scatterFunctionData)
170       {                                           159       {
171                                                   160   
172   G4VDataSetAlgorithm* scatterInterpolation =     161   G4VDataSetAlgorithm* scatterInterpolation = new G4LogLogInterpolation;
173   G4String scatterFile = "comp/ce-sf-";           162   G4String scatterFile = "comp/ce-sf-";
174   scatterFunctionData = new G4CompositeEMDataS    163   scatterFunctionData = new G4CompositeEMDataSet(scatterInterpolation, 1., 1.);
175   scatterFunctionData->LoadData(scatterFile);     164   scatterFunctionData->LoadData(scatterFile);
176       }                                           165       }
177                                                   166     
178     InitialiseElementSelectors(particle, cuts)    167     InitialiseElementSelectors(particle, cuts);
179   }                                               168   }
180                                                   169  
181   if (verboseLevel > 2) {                         170   if (verboseLevel > 2) {
182     G4cout << "Loaded cross section files" <<     171     G4cout << "Loaded cross section files" << G4endl;
183   }                                               172   }
184                                                   173   
185   if( verboseLevel>1 ) {                          174   if( verboseLevel>1 ) { 
186     G4cout << "G4LivermoreComptonModel is init    175     G4cout << "G4LivermoreComptonModel is initialized " << G4endl
187      << "Energy range: "                          176      << "Energy range: "
188      << LowEnergyLimit() / eV << " eV - "         177      << LowEnergyLimit() / eV << " eV - "
189      << HighEnergyLimit() / GeV << " GeV"         178      << HighEnergyLimit() / GeV << " GeV"
190      << G4endl;                                   179      << G4endl;
191   }                                               180   }
192   //                                              181   //  
193   if(isInitialised) { return; }                   182   if(isInitialised) { return; }
194                                                   183   
195   fParticleChange = GetParticleChangeForGamma(    184   fParticleChange = GetParticleChangeForGamma();
196   fAtomDeexcitation  = G4LossTableManager::Ins    185   fAtomDeexcitation  = G4LossTableManager::Instance()->AtomDeexcitation();
197   isInitialised = true;                           186   isInitialised = true;
198 }                                                 187 }
199                                                   188 
200                                                   189 
201 void G4LivermorePolarizedComptonModel::Initial    190 void G4LivermorePolarizedComptonModel::InitialiseLocal(const G4ParticleDefinition*,
202                 G4VEmModel* masterModel)          191                 G4VEmModel* masterModel)
203 {                                                 192 {
204   SetElementSelectors(masterModel->GetElementS    193   SetElementSelectors(masterModel->GetElementSelectors());
205 }                                                 194 }
206                                                   195 
207 //....oooOO0OOooo........oooOO0OOooo........oo    196 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
208                                                   197 
209 void G4LivermorePolarizedComptonModel::ReadDat << 198 void G4LivermorePolarizedComptonModel::ReadData(size_t Z, const char* path)
210 {                                                 199 {
211   if (verboseLevel > 1)                           200   if (verboseLevel > 1) 
212     {                                             201     {
213       G4cout << "G4LivermorePolarizedComptonMo    202       G4cout << "G4LivermorePolarizedComptonModel::ReadData()" 
214        << G4endl;                                 203        << G4endl;
215     }                                             204     }
216   if(data[Z]) { return; }                         205   if(data[Z]) { return; }  
217   const char* datadir = path;                     206   const char* datadir = path;
218   if(!datadir)                                    207   if(!datadir) 
219     {                                             208     {
220       datadir = G4FindDataDir("G4LEDATA");     << 209       datadir = getenv("G4LEDATA");
221       if(!datadir)                                210       if(!datadir) 
222   {                                               211   {
223     G4Exception("G4LivermorePolarizedComptonMo    212     G4Exception("G4LivermorePolarizedComptonModel::ReadData()",
224           "em0006",FatalException,                213           "em0006",FatalException,
225           "Environment variable G4LEDATA not d    214           "Environment variable G4LEDATA not defined");
226     return;                                       215     return;
227   }                                               216   }
228     }                                             217     }
229                                                   218   
230   data[Z] = new G4PhysicsFreeVector();         << 219   data[Z] = new G4LPhysicsFreeVector();
231                                                << 220   
                                                   >> 221   // Activation of spline interpolation
                                                   >> 222   data[Z]->SetSpline(false);
                                                   >> 223   
232   std::ostringstream ost;                         224   std::ostringstream ost;
233   ost << datadir << "/livermore/comp/ce-cs-" <    225   ost << datadir << "/livermore/comp/ce-cs-" << Z <<".dat";
234   std::ifstream fin(ost.str().c_str());           226   std::ifstream fin(ost.str().c_str());
235                                                   227   
236   if( !fin.is_open())                             228   if( !fin.is_open()) 
237     {                                             229     {
238       G4ExceptionDescription ed;                  230       G4ExceptionDescription ed;
239       ed << "G4LivermorePolarizedComptonModel     231       ed << "G4LivermorePolarizedComptonModel data file <" << ost.str().c_str()
240    << "> is not opened!" << G4endl;               232    << "> is not opened!" << G4endl;
241       G4Exception("G4LivermoreComptonModel::Re    233       G4Exception("G4LivermoreComptonModel::ReadData()",
242       "em0003",FatalException,                    234       "em0003",FatalException,
243       ed,"G4LEDATA version should be G4EMLOW8. << 235       ed,"G4LEDATA version should be G4EMLOW6.34 or later");
244       return;                                     236       return;
245     } else {                                      237     } else {
246     if(verboseLevel > 3) {                        238     if(verboseLevel > 3) {
247       G4cout << "File " << ost.str()              239       G4cout << "File " << ost.str() 
248        << " is opened by G4LivermorePolarizedC    240        << " is opened by G4LivermorePolarizedComptonModel" << G4endl;
249     }                                             241     }   
250     data[Z]->Retrieve(fin, true);                 242     data[Z]->Retrieve(fin, true);
251     data[Z]->ScaleVector(MeV, MeV*barn);          243     data[Z]->ScaleVector(MeV, MeV*barn);
252   }                                               244   }   
253   fin.close();                                    245   fin.close();
254 }                                                 246 }
255                                                   247 
                                                   >> 248 
                                                   >> 249 
                                                   >> 250 
256 //....oooOO0OOooo........oooOO0OOooo........oo    251 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
257                                                   252 
258 G4double G4LivermorePolarizedComptonModel::Com    253 G4double G4LivermorePolarizedComptonModel::ComputeCrossSectionPerAtom(
259                                        const G    254                                        const G4ParticleDefinition*,
260                                              G    255                                              G4double GammaEnergy,
261                                              G    256                                              G4double Z, G4double,
262                                              G    257                                              G4double, G4double)
263 {                                                 258 {
264   if (verboseLevel > 3)                           259   if (verboseLevel > 3)
265     G4cout << "Calling ComputeCrossSectionPerA    260     G4cout << "Calling ComputeCrossSectionPerAtom() of G4LivermorePolarizedComptonModel" << G4endl;
266                                                   261 
267   G4double cs = 0.0;                              262   G4double cs = 0.0; 
268                                                   263   
269   if (GammaEnergy < LowEnergyLimit())             264   if (GammaEnergy < LowEnergyLimit()) 
270     return 0.0;                                   265     return 0.0;
271                                                   266 
272   G4int intZ = G4lrint(Z);                        267   G4int intZ = G4lrint(Z);
273   if(intZ < 1 || intZ > maxZ) { return cs; }      268   if(intZ < 1 || intZ > maxZ) { return cs; } 
274                                                   269   
275   G4PhysicsFreeVector* pv = data[intZ];        << 270   G4LPhysicsFreeVector* pv = data[intZ];
276                                                   271   
277   // if element was not initialised               272   // if element was not initialised
278   // do initialisation safely for MT mode         273   // do initialisation safely for MT mode
279   if(!pv)                                         274   if(!pv) 
280     {                                             275     {
281       InitialiseForElement(0, intZ);              276       InitialiseForElement(0, intZ);
282       pv = data[intZ];                            277       pv = data[intZ];
283       if(!pv) { return cs; }                      278       if(!pv) { return cs; }
284     }                                             279     }
285                                                   280   
286   G4int n = G4int(pv->GetVectorLength() - 1);  << 281   G4int n = pv->GetVectorLength() - 1;   
287   G4double e1 = pv->Energy(0);                    282   G4double e1 = pv->Energy(0);
288   G4double e2 = pv->Energy(n);                    283   G4double e2 = pv->Energy(n);
289                                                   284   
290   if(GammaEnergy <= e1)      { cs = GammaEnerg    285   if(GammaEnergy <= e1)      { cs = GammaEnergy/(e1*e1)*pv->Value(e1); }
291   else if(GammaEnergy <= e2) { cs = pv->Value(    286   else if(GammaEnergy <= e2) { cs = pv->Value(GammaEnergy)/GammaEnergy; }
292   else if(GammaEnergy > e2)  { cs = pv->Value(    287   else if(GammaEnergy > e2)  { cs = pv->Value(e2)/GammaEnergy; }
293                                                   288   
294   return cs;                                      289   return cs;
295                                                   290 
296 }                                                 291 }
297                                                   292 
298 //....oooOO0OOooo........oooOO0OOooo........oo    293 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
299                                                   294 
300 void G4LivermorePolarizedComptonModel::SampleS    295 void G4LivermorePolarizedComptonModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
301                 const G4MaterialCutsCouple* co    296                 const G4MaterialCutsCouple* couple,
302                 const G4DynamicParticle* aDyna    297                 const G4DynamicParticle* aDynamicGamma,
303                 G4double,                         298                 G4double,
304                 G4double)                         299                 G4double)
305 {                                                 300 {
306   // The scattered gamma energy is sampled acc    301   // The scattered gamma energy is sampled according to Klein - Nishina formula.
307   // The random number techniques of Butcher &    302   // The random number techniques of Butcher & Messel are used (Nuc Phys 20(1960),15).
308   // GEANT4 internal units                        303   // GEANT4 internal units
309   //                                              304   //
310   // Note : Effects due to binding of atomic e    305   // Note : Effects due to binding of atomic electrons are negliged.
311                                                   306 
312   if (verboseLevel > 3)                           307   if (verboseLevel > 3)
313     G4cout << "Calling SampleSecondaries() of     308     G4cout << "Calling SampleSecondaries() of G4LivermorePolarizedComptonModel" << G4endl;
314                                                   309 
315   G4double gammaEnergy0 = aDynamicGamma->GetKi    310   G4double gammaEnergy0 = aDynamicGamma->GetKineticEnergy();
316                                                   311  
317   // do nothing below the threshold               312   // do nothing below the threshold
318   // should never get here because the XS is z    313   // should never get here because the XS is zero below the limit
319   if (gammaEnergy0 < LowEnergyLimit())            314   if (gammaEnergy0 < LowEnergyLimit())     
320     return ;                                      315     return ; 
321                                                   316 
                                                   >> 317 
322   G4ThreeVector gammaPolarization0 = aDynamicG    318   G4ThreeVector gammaPolarization0 = aDynamicGamma->GetPolarization();
323                                                   319 
324   // Protection: a polarisation parallel to th    320   // Protection: a polarisation parallel to the
325   // direction causes problems;                   321   // direction causes problems;
326   // in that case find a random polarization      322   // in that case find a random polarization
                                                   >> 323 
327   G4ThreeVector gammaDirection0 = aDynamicGamm    324   G4ThreeVector gammaDirection0 = aDynamicGamma->GetMomentumDirection();
328                                                   325 
329   // Make sure that the polarization vector is    326   // Make sure that the polarization vector is perpendicular to the
330   // gamma direction. If not                      327   // gamma direction. If not
                                                   >> 328 
331   if(!(gammaPolarization0.isOrthogonal(gammaDi    329   if(!(gammaPolarization0.isOrthogonal(gammaDirection0, 1e-6))||(gammaPolarization0.mag()==0))
332     { // only for testing now                     330     { // only for testing now
333       gammaPolarization0 = GetRandomPolarizati    331       gammaPolarization0 = GetRandomPolarization(gammaDirection0);
334     }                                             332     }
335   else                                            333   else
336     {                                             334     {
337       if ( gammaPolarization0.howOrthogonal(ga    335       if ( gammaPolarization0.howOrthogonal(gammaDirection0) != 0)
338   {                                               336   {
339     gammaPolarization0 = GetPerpendicularPolar    337     gammaPolarization0 = GetPerpendicularPolarization(gammaDirection0, gammaPolarization0);
340   }                                               338   }
341     }                                             339     }
                                                   >> 340 
342   // End of Protection                            341   // End of Protection
343                                                   342 
344   G4double E0_m = gammaEnergy0 / electron_mass    343   G4double E0_m = gammaEnergy0 / electron_mass_c2 ;
345                                                   344 
346   // Select randomly one element in the curren    345   // Select randomly one element in the current material
347   //G4int Z = crossSectionHandler->SelectRando    346   //G4int Z = crossSectionHandler->SelectRandomAtom(couple,gammaEnergy0);
348   const G4ParticleDefinition* particle =  aDyn    347   const G4ParticleDefinition* particle =  aDynamicGamma->GetDefinition();
349   const G4Element* elm = SelectRandomAtom(coup    348   const G4Element* elm = SelectRandomAtom(couple,particle,gammaEnergy0);
350   G4int Z = (G4int)elm->GetZ();                   349   G4int Z = (G4int)elm->GetZ();
351                                                   350 
352   // Sample the energy and the polarization of    351   // Sample the energy and the polarization of the scattered photon
                                                   >> 352 
353   G4double epsilon, epsilonSq, onecost, sinThe    353   G4double epsilon, epsilonSq, onecost, sinThetaSqr, greject ;
354                                                   354 
355   G4double epsilon0Local = 1./(1. + 2*E0_m);      355   G4double epsilon0Local = 1./(1. + 2*E0_m);
356   G4double epsilon0Sq = epsilon0Local*epsilon0    356   G4double epsilon0Sq = epsilon0Local*epsilon0Local;
357   G4double alpha1   = - G4Log(epsilon0Local);  << 357   G4double alpha1   = - std::log(epsilon0Local);
358   G4double alpha2 = 0.5*(1.- epsilon0Sq);         358   G4double alpha2 = 0.5*(1.- epsilon0Sq);
359                                                   359 
360   G4double wlGamma = h_Planck*c_light/gammaEne    360   G4double wlGamma = h_Planck*c_light/gammaEnergy0;
361   G4double gammaEnergy1;                          361   G4double gammaEnergy1;
362   G4ThreeVector gammaDirection1;                  362   G4ThreeVector gammaDirection1;
363                                                   363 
364   do {                                            364   do {
365     if ( alpha1/(alpha1+alpha2) > G4UniformRan    365     if ( alpha1/(alpha1+alpha2) > G4UniformRand() )
366       {                                           366       {
367   epsilon   = G4Exp(-alpha1*G4UniformRand());     367   epsilon   = G4Exp(-alpha1*G4UniformRand());  
368   epsilonSq = epsilon*epsilon;                    368   epsilonSq = epsilon*epsilon; 
369       }                                           369       }
370     else                                          370     else 
371       {                                           371       {
372   epsilonSq = epsilon0Sq + (1.- epsilon0Sq)*G4    372   epsilonSq = epsilon0Sq + (1.- epsilon0Sq)*G4UniformRand();
373   epsilon   = std::sqrt(epsilonSq);               373   epsilon   = std::sqrt(epsilonSq);
374       }                                           374       }
375                                                   375 
376     onecost = (1.- epsilon)/(epsilon*E0_m);       376     onecost = (1.- epsilon)/(epsilon*E0_m);
377     sinThetaSqr   = onecost*(2.-onecost);         377     sinThetaSqr   = onecost*(2.-onecost);
378                                                   378 
379     // Protection                                 379     // Protection
380     if (sinThetaSqr > 1.)                         380     if (sinThetaSqr > 1.)
381       {                                           381       {
382   G4cout                                          382   G4cout
383     << " -- Warning -- G4LivermorePolarizedCom    383     << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
384     << "sin(theta)**2 = "                         384     << "sin(theta)**2 = "
385     << sinThetaSqr                                385     << sinThetaSqr
386     << "; set to 1"                               386     << "; set to 1"
387     << G4endl;                                    387     << G4endl;
388   sinThetaSqr = 1.;                               388   sinThetaSqr = 1.;
389       }                                           389       }
390     if (sinThetaSqr < 0.)                         390     if (sinThetaSqr < 0.)
391       {                                           391       {
392   G4cout                                          392   G4cout
393     << " -- Warning -- G4LivermorePolarizedCom    393     << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
394     << "sin(theta)**2 = "                         394     << "sin(theta)**2 = "
395     << sinThetaSqr                                395     << sinThetaSqr
396     << "; set to 0"                               396     << "; set to 0"
397     << G4endl;                                    397     << G4endl;
398   sinThetaSqr = 0.;                               398   sinThetaSqr = 0.;
399       }                                           399       }
400     // End protection                             400     // End protection
401                                                   401 
402     G4double x =  std::sqrt(onecost/2.) / (wlG    402     G4double x =  std::sqrt(onecost/2.) / (wlGamma/cm);;
403     G4double scatteringFunction = scatterFunct    403     G4double scatteringFunction = scatterFunctionData->FindValue(x,Z-1);
404     greject = (1. - epsilon*sinThetaSqr/(1.+ e    404     greject = (1. - epsilon*sinThetaSqr/(1.+ epsilonSq))*scatteringFunction;
405                                                   405 
406   } while(greject < G4UniformRand()*Z);           406   } while(greject < G4UniformRand()*Z);
407                                                   407 
408                                                   408 
409   // *****************************************    409   // ****************************************************
410   //    Phi determination                         410   //    Phi determination
411   // *****************************************    411   // ****************************************************
                                                   >> 412 
412   G4double phi = SetPhi(epsilon,sinThetaSqr);     413   G4double phi = SetPhi(epsilon,sinThetaSqr);
413                                                   414 
414   //                                              415   //
415   // scattered gamma angles. ( Z - axis along     416   // scattered gamma angles. ( Z - axis along the parent gamma)
416   //                                              417   //
                                                   >> 418 
417   G4double cosTheta = 1. - onecost;               419   G4double cosTheta = 1. - onecost;
418                                                   420 
419   // Protection                                   421   // Protection
                                                   >> 422 
420   if (cosTheta > 1.)                              423   if (cosTheta > 1.)
421     {                                             424     {
422       G4cout                                      425       G4cout
423   << " -- Warning -- G4LivermorePolarizedCompt    426   << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
424   << "cosTheta = "                                427   << "cosTheta = "
425   << cosTheta                                     428   << cosTheta
426   << "; set to 1"                                 429   << "; set to 1"
427   << G4endl;                                      430   << G4endl;
428       cosTheta = 1.;                              431       cosTheta = 1.;
429     }                                             432     }
430   if (cosTheta < -1.)                             433   if (cosTheta < -1.)
431     {                                             434     {
432       G4cout                                      435       G4cout 
433   << " -- Warning -- G4LivermorePolarizedCompt    436   << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
434   << "cosTheta = "                                437   << "cosTheta = " 
435   << cosTheta                                     438   << cosTheta
436   << "; set to -1"                                439   << "; set to -1"
437   << G4endl;                                      440   << G4endl;
438       cosTheta = -1.;                             441       cosTheta = -1.;
439     }                                             442     }
440   // End protection                               443   // End protection      
441                                                << 444   
                                                   >> 445   
442   G4double sinTheta = std::sqrt (sinThetaSqr);    446   G4double sinTheta = std::sqrt (sinThetaSqr);
443                                                   447   
444   // Protection                                   448   // Protection
445   if (sinTheta > 1.)                              449   if (sinTheta > 1.)
446     {                                             450     {
447       G4cout                                      451       G4cout 
448   << " -- Warning -- G4LivermorePolarizedCompt    452   << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
449   << "sinTheta = "                                453   << "sinTheta = " 
450   << sinTheta                                     454   << sinTheta
451   << "; set to 1"                                 455   << "; set to 1"
452   << G4endl;                                      456   << G4endl;
453       sinTheta = 1.;                              457       sinTheta = 1.;
454     }                                             458     }
455   if (sinTheta < -1.)                             459   if (sinTheta < -1.)
456     {                                             460     {
457       G4cout                                      461       G4cout 
458   << " -- Warning -- G4LivermorePolarizedCompt    462   << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
459   << "sinTheta = "                                463   << "sinTheta = " 
460   << sinTheta                                     464   << sinTheta
461   << "; set to -1"                                465   << "; set to -1" 
462   << G4endl;                                      466   << G4endl;
463       sinTheta = -1.;                             467       sinTheta = -1.;
464     }                                             468     }
465   // End protection                               469   // End protection
466                                                   470   
467   // Check for entanglement and re-sample phi  << 
468                                                << 
469   const auto* auxInfo                          << 
470   = fParticleChange->GetCurrentTrack()->GetAux << 
471   if (auxInfo) {                               << 
472     const auto* entanglementAuxInfo = dynamic_ << 
473     if (entanglementAuxInfo) {                 << 
474       auto* clipBoard = dynamic_cast<G4eplusAn << 
475       (entanglementAuxInfo->GetEntanglementCli << 
476       if (clipBoard) {                         << 
477         // This is an entangled photon from ep << 
478         // If this is the first scatter of the << 
479         // phi on the clipboard.               << 
480         // If this is the first scatter of the << 
481         // phi of the first scatter of the fir << 
482         // theta of the second photon, to samp << 
483         if (clipBoard->IsTrack1Measurement())  << 
484           // Check we have the relevant track. << 
485           // necessary but I want to be sure t << 
486           // entangled system are properly pai << 
487           // Note: the tracking manager pops t << 
488           // will rely on that.  (If not, the  << 
489           // more complicated to ensure we mat << 
490           // So our track 1 is clipboard track << 
491           if (clipBoard->GetTrackB() == fParti << 
492             // This is the first scatter of th << 
493             //            // Debug             << 
494             //            auto* track1 = fPart << 
495             //            G4cout               << 
496             //            << "This is the firs << 
497             //            << "\nTrack: " << tr << 
498             //            << ", Parent: " << t << 
499             //            << ", Name: " << cli << 
500             //            << G4endl;           << 
501             //            // End debug         << 
502             clipBoard->ResetTrack1Measurement( << 
503             // Store cos(theta),phi of first p << 
504             clipBoard->SetComptonCosTheta1(cos << 
505             clipBoard->SetComptonPhi1(phi);    << 
506           }                                    << 
507         } else if (clipBoard->IsTrack2Measurem << 
508           // Check we have the relevant track. << 
509           // Remember our track 2 is clipboard << 
510           if (clipBoard->GetTrackA() == fParti << 
511             // This is the first scatter of th << 
512             //            // Debug             << 
513             //            auto* track2 = fPart << 
514             //            G4cout               << 
515             //            << "This is the firs << 
516             //            << "\nTrack: " << tr << 
517             //            << ", Parent: " << t << 
518             //            << ", Name: " << cli << 
519             //            << G4endl;           << 
520             //            // End debug         << 
521             clipBoard->ResetTrack2Measurement( << 
522                                                << 
523             // Get cos(theta),phi of first pho << 
524             const G4double& cosTheta1 = clipBo << 
525             const G4double& phi1 = clipBoard-> << 
526             // For clarity make aliases for th << 
527             const G4double& cosTheta2 = cosThe << 
528             G4double& phi2 = phi;              << 
529             //            G4cout << "cosTheta1 << 
530             //            G4cout << "cosTheta2 << 
531                                                << 
532             // Re-sample phi                   << 
533             // Draw the difference of azimutha << 
534             // A + B * cos(2*deltaPhi), or rat << 
535             // C = A / (A + |B|) and D = B / ( << 
536             const G4double sin2Theta1 = 1.-cos << 
537             const G4double sin2Theta2 = 1.-cos << 
538                                                << 
539             // Pryce and Ward, Nature No 4065  << 
540             auto* g4Pow = G4Pow::GetInstance() << 
541             const G4double A =                 << 
542             ((g4Pow->powN(1.-cosTheta1,3))+2.) << 
543             ((g4Pow->powN(2.-cosTheta1,3)*g4Po << 
544             const G4double B = -(sin2Theta1*si << 
545             ((g4Pow->powN(2.-cosTheta1,2)*g4Po << 
546                                                << 
547             //    // Snyder et al, Physical Re << 
548             //    // (This is an alternative f << 
549             //    const G4double& k0 = gammaEn << 
550             //    const G4double k1 = k0/(2.-c << 
551             //    const G4double k2 = k0/(2.-c << 
552             //    const G4double gamma1 = k1/k << 
553             //    const G4double gamma2 = k2/k << 
554             //    const G4double A1 = gamma1*g << 
555             //    const G4double B1 = 2.*sin2T << 
556             //    // That's A1 + B1*sin2(delta << 
557             //    const G4double A = A1 + 0.5* << 
558             //    const G4double B = -0.5*B1;  << 
559                                                << 
560             const G4double maxValue = A + std: << 
561             const G4double C = A / maxValue;   << 
562             const G4double D = B / maxValue;   << 
563             //    G4cout << "A,B,C,D: " << A < << 
564                                                << 
565             // Sample delta phi                << 
566             G4double deltaPhi;                 << 
567             const G4int maxCount = 999999;     << 
568             G4int iCount = 0;                  << 
569             for (; iCount < maxCount; ++iCount << 
570               deltaPhi = twopi * G4UniformRand << 
571               if (G4UniformRand() < C + D * co << 
572             }                                  << 
573             if (iCount >= maxCount ) {         << 
574               G4cout << "G4LivermorePolarizedC << 
575               << "Re-sampled delta phi not fou << 
576               << " tries - carrying on anyway. << 
577             }                                  << 
578                                                << 
579             // Thus, the desired second photon << 
580             phi2 = deltaPhi - phi1 + halfpi;   << 
581             // The minus sign is in above stat << 
582             // annihilation photons are in opp << 
583             // are measured in the opposite di << 
584             // halfpi is added for the followi << 
585             // In this function phi is relativ << 
586             // SystemOfRefChange below. We kno << 
587             // the polarisations of the two an << 
588             // to each other, i.e., halfpi dif << 
589             // Furthermore, only sin(phi) and  << 
590             // need to place any range constra << 
591             //            if (phi2 > pi) {     << 
592             //              phi2 -= twopi;     << 
593             //            }                    << 
594             //            if (phi2 < -pi) {    << 
595             //              phi2 += twopi;     << 
596             //            }                    << 
597           }                                    << 
598         }                                      << 
599       }                                        << 
600     }                                          << 
601   }                                            << 
602                                                << 
603   // End of entanglement                       << 
604                                                   471       
605   G4double dirx = sinTheta*std::cos(phi);         472   G4double dirx = sinTheta*std::cos(phi);
606   G4double diry = sinTheta*std::sin(phi);         473   G4double diry = sinTheta*std::sin(phi);
607   G4double dirz = cosTheta ;                      474   G4double dirz = cosTheta ;
608                                                << 475   
                                                   >> 476 
609   // oneCosT , eom                                477   // oneCosT , eom
610                                                   478 
611   // Doppler broadening -  Method based on:       479   // Doppler broadening -  Method based on:
612   // Y. Namito, S. Ban and H. Hirayama,           480   // Y. Namito, S. Ban and H. Hirayama, 
613   // "Implementation of the Doppler Broadening    481   // "Implementation of the Doppler Broadening of a Compton-Scattered Photon Into the EGS4 Code" 
614   // NIM A 349, pp. 489-494, 1994                 482   // NIM A 349, pp. 489-494, 1994
615                                                   483   
616   // Maximum number of sampling iterations        484   // Maximum number of sampling iterations
                                                   >> 485 
617   static G4int maxDopplerIterations = 1000;       486   static G4int maxDopplerIterations = 1000;
618   G4double bindingE = 0.;                         487   G4double bindingE = 0.;
619   G4double photonEoriginal = epsilon * gammaEn    488   G4double photonEoriginal = epsilon * gammaEnergy0;
620   G4double photonE = -1.;                         489   G4double photonE = -1.;
621   G4int iteration = 0;                            490   G4int iteration = 0;
622   G4double eMax = gammaEnergy0;                   491   G4double eMax = gammaEnergy0;
623                                                   492 
624   G4int shellIdx = 0;                             493   G4int shellIdx = 0;
625                                                   494 
626   if (verboseLevel > 3) {                         495   if (verboseLevel > 3) {
627     G4cout << "Started loop to sample broading    496     G4cout << "Started loop to sample broading" << G4endl;
628   }                                               497   }
629                                                   498 
630   do                                              499   do
631     {                                             500     {
632       iteration++;                                501       iteration++;
633       // Select shell based on shell occupancy    502       // Select shell based on shell occupancy
634       shellIdx = shellData->SelectRandomShell(    503       shellIdx = shellData->SelectRandomShell(Z);
635       bindingE = shellData->BindingEnergy(Z,sh    504       bindingE = shellData->BindingEnergy(Z,shellIdx);
636                                                   505       
637       if (verboseLevel > 3) {                     506       if (verboseLevel > 3) {
638   G4cout << "Shell ID= " << shellIdx              507   G4cout << "Shell ID= " << shellIdx 
639          << " Ebind(keV)= " << bindingE/keV <<    508          << " Ebind(keV)= " << bindingE/keV << G4endl;
640       }                                           509       }
641       eMax = gammaEnergy0 - bindingE;             510       eMax = gammaEnergy0 - bindingE;
642                                                   511       
643       // Randomly sample bound electron moment    512       // Randomly sample bound electron momentum (memento: the data set is in Atomic Units)
644       G4double pSample = profileData->RandomSe    513       G4double pSample = profileData->RandomSelectMomentum(Z,shellIdx);
645                                                   514 
646       if (verboseLevel > 3) {                     515       if (verboseLevel > 3) {
647        G4cout << "pSample= " << pSample << G4e    516        G4cout << "pSample= " << pSample << G4endl;
648      }                                            517      }
649       // Rescale from atomic units                518       // Rescale from atomic units
650       G4double pDoppler = pSample * fine_struc    519       G4double pDoppler = pSample * fine_structure_const;
651       G4double pDoppler2 = pDoppler * pDoppler    520       G4double pDoppler2 = pDoppler * pDoppler;
652       G4double var2 = 1. + onecost * E0_m;        521       G4double var2 = 1. + onecost * E0_m;
653       G4double var3 = var2*var2 - pDoppler2;      522       G4double var3 = var2*var2 - pDoppler2;
654       G4double var4 = var2 - pDoppler2 * cosTh    523       G4double var4 = var2 - pDoppler2 * cosTheta;
655       G4double var = var4*var4 - var3 + pDoppl    524       G4double var = var4*var4 - var3 + pDoppler2 * var3;
656       if (var > 0.)                               525       if (var > 0.)
657   {                                               526   {
658     G4double varSqrt = std::sqrt(var);            527     G4double varSqrt = std::sqrt(var);        
659     G4double scale = gammaEnergy0 / var3;         528     G4double scale = gammaEnergy0 / var3;  
660           // Random select either root            529           // Random select either root
661     if (G4UniformRand() < 0.5) photonE = (var4    530     if (G4UniformRand() < 0.5) photonE = (var4 - varSqrt) * scale;               
662     else photonE = (var4 + varSqrt) * scale;      531     else photonE = (var4 + varSqrt) * scale;
663   }                                               532   } 
664       else                                        533       else
665   {                                               534   {
666     photonE = -1.;                                535     photonE = -1.;
667   }                                               536   }
668    } while ( iteration <= maxDopplerIterations    537    } while ( iteration <= maxDopplerIterations && 
669        (photonE < 0. || photonE > eMax || phot    538        (photonE < 0. || photonE > eMax || photonE < eMax*G4UniformRand()) );
                                                   >> 539   //while (iteration <= maxDopplerIterations && photonE > eMax); ???
                                                   >> 540 
670                                                   541 
671   // End of recalculation of photon energy wit    542   // End of recalculation of photon energy with Doppler broadening
672   // Revert to original if maximum number of i    543   // Revert to original if maximum number of iterations threshold has been reached
673   if (iteration >= maxDopplerIterations)          544   if (iteration >= maxDopplerIterations)
674     {                                             545     {
675       photonE = photonEoriginal;                  546       photonE = photonEoriginal;
676       bindingE = 0.;                              547       bindingE = 0.;
677     }                                             548     }
678                                                   549 
679   gammaEnergy1 = photonE;                         550   gammaEnergy1 = photonE;
680                                                   551  
681   //                                              552   //
682   // update G4VParticleChange for the scattere    553   // update G4VParticleChange for the scattered photon 
683   //                                              554   //
                                                   >> 555 
                                                   >> 556 
                                                   >> 557 
                                                   >> 558   //  gammaEnergy1 = epsilon*gammaEnergy0;
                                                   >> 559 
                                                   >> 560 
684   // New polarization                             561   // New polarization
                                                   >> 562 
685   G4ThreeVector gammaPolarization1 = SetNewPol    563   G4ThreeVector gammaPolarization1 = SetNewPolarization(epsilon,
686               sinThetaSqr,                        564               sinThetaSqr,
687               phi,                                565               phi,
688               cosTheta);                          566               cosTheta);
689                                                   567 
690   // Set new direction                            568   // Set new direction
691   G4ThreeVector tmpDirection1( dirx,diry,dirz     569   G4ThreeVector tmpDirection1( dirx,diry,dirz );
692   gammaDirection1 = tmpDirection1;                570   gammaDirection1 = tmpDirection1;
693                                                   571 
694   // Change reference frame.                      572   // Change reference frame.
                                                   >> 573 
695   SystemOfRefChange(gammaDirection0,gammaDirec    574   SystemOfRefChange(gammaDirection0,gammaDirection1,
696         gammaPolarization0,gammaPolarization1)    575         gammaPolarization0,gammaPolarization1);
697                                                   576 
698   if (gammaEnergy1 > 0.)                          577   if (gammaEnergy1 > 0.)
699     {                                             578     {
700       fParticleChange->SetProposedKineticEnerg    579       fParticleChange->SetProposedKineticEnergy( gammaEnergy1 ) ;
701       fParticleChange->ProposeMomentumDirectio    580       fParticleChange->ProposeMomentumDirection( gammaDirection1 );
702       fParticleChange->ProposePolarization( ga    581       fParticleChange->ProposePolarization( gammaPolarization1 );
703     }                                             582     }
704   else                                            583   else
705     {                                             584     {
706       gammaEnergy1 = 0.;                          585       gammaEnergy1 = 0.;
707       fParticleChange->SetProposedKineticEnerg    586       fParticleChange->SetProposedKineticEnergy(0.) ;
708       fParticleChange->ProposeTrackStatus(fSto    587       fParticleChange->ProposeTrackStatus(fStopAndKill);
709     }                                             588     }
710                                                   589 
711   //                                              590   //
712   // kinematic of the scattered electron          591   // kinematic of the scattered electron
713   //                                              592   //
                                                   >> 593 
714   G4double ElecKineEnergy = gammaEnergy0 - gam    594   G4double ElecKineEnergy = gammaEnergy0 - gammaEnergy1 -bindingE;
715                                                   595 
716   // SI -protection against negative final ene    596   // SI -protection against negative final energy: no e- is created
717   // like in G4LivermoreComptonModel.cc           597   // like in G4LivermoreComptonModel.cc
718   if(ElecKineEnergy < 0.0) {                      598   if(ElecKineEnergy < 0.0) {
719     fParticleChange->ProposeLocalEnergyDeposit    599     fParticleChange->ProposeLocalEnergyDeposit(gammaEnergy0 - gammaEnergy1);
720     return;                                       600     return;
721   }                                               601   }
722                                                   602  
                                                   >> 603   // SI - Removed range test
                                                   >> 604   
723   G4double ElecMomentum = std::sqrt(ElecKineEn    605   G4double ElecMomentum = std::sqrt(ElecKineEnergy*(ElecKineEnergy+2.*electron_mass_c2));
724                                                   606 
725   G4ThreeVector ElecDirection((gammaEnergy0 *     607   G4ThreeVector ElecDirection((gammaEnergy0 * gammaDirection0 -
726            gammaEnergy1 * gammaDirection1) * (    608            gammaEnergy1 * gammaDirection1) * (1./ElecMomentum));
727                                                   609 
728   G4DynamicParticle* dp =                      << 610   G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),ElecDirection.unit(),ElecKineEnergy) ;
729     new G4DynamicParticle (G4Electron::Electro << 
730   fvect->push_back(dp);                           611   fvect->push_back(dp);
731                                                   612 
732   // sample deexcitation                          613   // sample deexcitation
733   //                                           << 614   //
                                                   >> 615   
734   if (verboseLevel > 3) {                         616   if (verboseLevel > 3) {
735     G4cout << "Started atomic de-excitation "     617     G4cout << "Started atomic de-excitation " << fAtomDeexcitation << G4endl;
736   }                                               618   }
737                                                   619   
738   if(fAtomDeexcitation && iteration < maxDoppl    620   if(fAtomDeexcitation && iteration < maxDopplerIterations) {
739     G4int index = couple->GetIndex();             621     G4int index = couple->GetIndex();
740     if(fAtomDeexcitation->CheckDeexcitationAct    622     if(fAtomDeexcitation->CheckDeexcitationActiveRegion(index)) {
741       std::size_t nbefore = fvect->size();     << 623       size_t nbefore = fvect->size();
742       G4AtomicShellEnumerator as = G4AtomicShe    624       G4AtomicShellEnumerator as = G4AtomicShellEnumerator(shellIdx);
743       const G4AtomicShell* shell = fAtomDeexci    625       const G4AtomicShell* shell = fAtomDeexcitation->GetAtomicShell(Z, as);
744       fAtomDeexcitation->GenerateParticles(fve    626       fAtomDeexcitation->GenerateParticles(fvect, shell, Z, index);
745       std::size_t nafter = fvect->size();      << 627       size_t nafter = fvect->size();
746       if(nafter > nbefore) {                      628       if(nafter > nbefore) {
747   for (std::size_t i=nbefore; i<nafter; ++i) { << 629   for (size_t i=nbefore; i<nafter; ++i) {
748     //Check if there is enough residual energy    630     //Check if there is enough residual energy 
749     if (bindingE >= ((*fvect)[i])->GetKineticE    631     if (bindingE >= ((*fvect)[i])->GetKineticEnergy())
750             {                                     632             {
751               //Ok, this is a valid secondary:    633               //Ok, this is a valid secondary: keep it
752         bindingE -= ((*fvect)[i])->GetKineticE    634         bindingE -= ((*fvect)[i])->GetKineticEnergy();
753             }                                     635             }
754     else                                          636     else
755             {                                     637             {
756         //Invalid secondary: not enough energy    638         //Invalid secondary: not enough energy to create it!
757         //Keep its energy in the local deposit    639         //Keep its energy in the local deposit
758         delete (*fvect)[i];                       640         delete (*fvect)[i]; 
759               (*fvect)[i]=0;                      641               (*fvect)[i]=0;
760             }                                     642             }
761   }                                               643   } 
762       }                                           644       }
763     }                                             645     }
764   }                                               646   }
765   //This should never happen                      647   //This should never happen
766   if(bindingE < 0.0)                              648   if(bindingE < 0.0) 
767     G4Exception("G4LivermoreComptonModel::Samp    649     G4Exception("G4LivermoreComptonModel::SampleSecondaries()",
768     "em2050",FatalException,"Negative local en    650     "em2050",FatalException,"Negative local energy deposit");   
769                                                   651   
770   fParticleChange->ProposeLocalEnergyDeposit(b    652   fParticleChange->ProposeLocalEnergyDeposit(bindingE);
771                                                   653 
772 }                                                 654 }
773                                                   655 
774 //....oooOO0OOooo........oooOO0OOooo........oo    656 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
775                                                   657 
776 G4double G4LivermorePolarizedComptonModel::Set    658 G4double G4LivermorePolarizedComptonModel::SetPhi(G4double energyRate,
777                G4double sinSqrTh)                 659                G4double sinSqrTh)
778 {                                                 660 {
779   G4double rand1;                                 661   G4double rand1;
780   G4double rand2;                                 662   G4double rand2;
781   G4double phiProbability;                        663   G4double phiProbability;
782   G4double phi;                                   664   G4double phi;
783   G4double a, b;                                  665   G4double a, b;
784                                                   666 
785   do                                              667   do
786     {                                             668     {
787       rand1 = G4UniformRand();                    669       rand1 = G4UniformRand();
788       rand2 = G4UniformRand();                    670       rand2 = G4UniformRand();
789       phiProbability=0.;                          671       phiProbability=0.;
790       phi = twopi*rand1;                          672       phi = twopi*rand1;
791                                                   673       
792       a = 2*sinSqrTh;                             674       a = 2*sinSqrTh;
793       b = energyRate + 1/energyRate;              675       b = energyRate + 1/energyRate;
794                                                   676       
795       phiProbability = 1 - (a/b)*(std::cos(phi    677       phiProbability = 1 - (a/b)*(std::cos(phi)*std::cos(phi));
                                                   >> 678 
                                                   >> 679       
                                                   >> 680  
796     }                                             681     }
797   while ( rand2 > phiProbability );               682   while ( rand2 > phiProbability );
798   return phi;                                     683   return phi;
799 }                                                 684 }
800                                                   685 
801                                                   686 
802 //....oooOO0OOooo........oooOO0OOooo........oo    687 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
803                                                   688 
804 G4ThreeVector G4LivermorePolarizedComptonModel    689 G4ThreeVector G4LivermorePolarizedComptonModel::SetPerpendicularVector(G4ThreeVector& a)
805 {                                                 690 {
806   G4double dx = a.x();                            691   G4double dx = a.x();
807   G4double dy = a.y();                            692   G4double dy = a.y();
808   G4double dz = a.z();                            693   G4double dz = a.z();
809   G4double x = dx < 0.0 ? -dx : dx;               694   G4double x = dx < 0.0 ? -dx : dx;
810   G4double y = dy < 0.0 ? -dy : dy;               695   G4double y = dy < 0.0 ? -dy : dy;
811   G4double z = dz < 0.0 ? -dz : dz;               696   G4double z = dz < 0.0 ? -dz : dz;
812   if (x < y) {                                    697   if (x < y) {
813     return x < z ? G4ThreeVector(-dy,dx,0) : G    698     return x < z ? G4ThreeVector(-dy,dx,0) : G4ThreeVector(0,-dz,dy);
814   }else{                                          699   }else{
815     return y < z ? G4ThreeVector(dz,0,-dx) : G    700     return y < z ? G4ThreeVector(dz,0,-dx) : G4ThreeVector(-dy,dx,0);
816   }                                               701   }
817 }                                                 702 }
818                                                   703 
819 //....oooOO0OOooo........oooOO0OOooo........oo    704 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
820                                                   705 
821 G4ThreeVector G4LivermorePolarizedComptonModel    706 G4ThreeVector G4LivermorePolarizedComptonModel::GetRandomPolarization(G4ThreeVector& direction0)
822 {                                                 707 {
823   G4ThreeVector d0 = direction0.unit();           708   G4ThreeVector d0 = direction0.unit();
824   G4ThreeVector a1 = SetPerpendicularVector(d0    709   G4ThreeVector a1 = SetPerpendicularVector(d0); //different orthogonal
825   G4ThreeVector a0 = a1.unit(); // unit vector    710   G4ThreeVector a0 = a1.unit(); // unit vector
826                                                   711 
827   G4double rand1 = G4UniformRand();               712   G4double rand1 = G4UniformRand();
828                                                   713   
829   G4double angle = twopi*rand1; // random pola    714   G4double angle = twopi*rand1; // random polar angle
830   G4ThreeVector b0 = d0.cross(a0); // cross pr    715   G4ThreeVector b0 = d0.cross(a0); // cross product
831                                                   716   
832   G4ThreeVector c;                                717   G4ThreeVector c;
833                                                   718   
834   c.setX(std::cos(angle)*(a0.x())+std::sin(ang    719   c.setX(std::cos(angle)*(a0.x())+std::sin(angle)*b0.x());
835   c.setY(std::cos(angle)*(a0.y())+std::sin(ang    720   c.setY(std::cos(angle)*(a0.y())+std::sin(angle)*b0.y());
836   c.setZ(std::cos(angle)*(a0.z())+std::sin(ang    721   c.setZ(std::cos(angle)*(a0.z())+std::sin(angle)*b0.z());
837                                                   722   
838   G4ThreeVector c0 = c.unit();                    723   G4ThreeVector c0 = c.unit();
839                                                   724 
840   return c0;                                      725   return c0;
                                                   >> 726   
841 }                                                 727 }
842                                                   728 
843 //....oooOO0OOooo........oooOO0OOooo........oo    729 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
844                                                   730 
845 G4ThreeVector G4LivermorePolarizedComptonModel    731 G4ThreeVector G4LivermorePolarizedComptonModel::GetPerpendicularPolarization
846 (const G4ThreeVector& gammaDirection, const G4    732 (const G4ThreeVector& gammaDirection, const G4ThreeVector& gammaPolarization) const
847 {                                                 733 {
                                                   >> 734 
848   //                                              735   // 
849   // The polarization of a photon is always pe    736   // The polarization of a photon is always perpendicular to its momentum direction.
850   // Therefore this function removes those vec    737   // Therefore this function removes those vector component of gammaPolarization, which
851   // points in direction of gammaDirection        738   // points in direction of gammaDirection
852   //                                              739   //
853   // Mathematically we search the projection o    740   // Mathematically we search the projection of the vector a on the plane E, where n is the
854   // plains normal vector.                        741   // plains normal vector.
855   // The basic equation can be found in each g    742   // The basic equation can be found in each geometry book (e.g. Bronstein):
856   // p = a - (a o n)/(n o n)*n                    743   // p = a - (a o n)/(n o n)*n
857                                                   744   
858   return gammaPolarization - gammaPolarization    745   return gammaPolarization - gammaPolarization.dot(gammaDirection)/gammaDirection.dot(gammaDirection) * gammaDirection;
859 }                                                 746 }
860                                                   747 
861 //....oooOO0OOooo........oooOO0OOooo........oo    748 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
862                                                   749 
863 G4ThreeVector G4LivermorePolarizedComptonModel    750 G4ThreeVector G4LivermorePolarizedComptonModel::SetNewPolarization(G4double epsilon,
864                     G4double sinSqrTh,            751                     G4double sinSqrTh, 
865                     G4double phi,                 752                     G4double phi,
866                     G4double costheta)            753                     G4double costheta) 
867 {                                                 754 {
868   G4double rand1;                                 755   G4double rand1;
869   G4double rand2;                                 756   G4double rand2;
870   G4double cosPhi = std::cos(phi);                757   G4double cosPhi = std::cos(phi);
871   G4double sinPhi = std::sin(phi);                758   G4double sinPhi = std::sin(phi);
872   G4double sinTheta = std::sqrt(sinSqrTh);        759   G4double sinTheta = std::sqrt(sinSqrTh);
873   G4double cosSqrPhi = cosPhi*cosPhi;             760   G4double cosSqrPhi = cosPhi*cosPhi;
874   //  G4double cossqrth = 1.-sinSqrTh;            761   //  G4double cossqrth = 1.-sinSqrTh;
875   //  G4double sinsqrphi = sinPhi*sinPhi;         762   //  G4double sinsqrphi = sinPhi*sinPhi;
876   G4double normalisation = std::sqrt(1. - cosS    763   G4double normalisation = std::sqrt(1. - cosSqrPhi*sinSqrTh);
877                                                   764  
                                                   >> 765 
878   // Determination of Theta                       766   // Determination of Theta 
                                                   >> 767   
                                                   >> 768   // ---- MGP ---- Commented out the following 3 lines to avoid compilation 
                                                   >> 769   // warnings (unused variables)
                                                   >> 770   // G4double thetaProbability;
879   G4double theta;                                 771   G4double theta;
                                                   >> 772   // G4double a, b;
                                                   >> 773   // G4double cosTheta;
                                                   >> 774 
                                                   >> 775   /*
                                                   >> 776 
                                                   >> 777   depaola method
                                                   >> 778   
                                                   >> 779   do
                                                   >> 780   {
                                                   >> 781       rand1 = G4UniformRand();
                                                   >> 782       rand2 = G4UniformRand();
                                                   >> 783       thetaProbability=0.;
                                                   >> 784       theta = twopi*rand1;
                                                   >> 785       a = 4*normalisation*normalisation;
                                                   >> 786       b = (epsilon + 1/epsilon) - 2;
                                                   >> 787       thetaProbability = (b + a*std::cos(theta)*std::cos(theta))/(a+b);
                                                   >> 788       cosTheta = std::cos(theta);
                                                   >> 789     }
                                                   >> 790   while ( rand2 > thetaProbability );
                                                   >> 791   
                                                   >> 792   G4double cosBeta = cosTheta;
                                                   >> 793 
                                                   >> 794   */
                                                   >> 795 
880                                                   796 
881   // Dan Xu method (IEEE TNS, 52, 1160 (2005))    797   // Dan Xu method (IEEE TNS, 52, 1160 (2005))
                                                   >> 798 
882   rand1 = G4UniformRand();                        799   rand1 = G4UniformRand();
883   rand2 = G4UniformRand();                        800   rand2 = G4UniformRand();
884                                                   801 
885   if (rand1<(epsilon+1.0/epsilon-2)/(2.0*(epsi    802   if (rand1<(epsilon+1.0/epsilon-2)/(2.0*(epsilon+1.0/epsilon)-4.0*sinSqrTh*cosSqrPhi))
886     {                                             803     {
887       if (rand2<0.5)                              804       if (rand2<0.5)
888   theta = pi/2.0;                                 805   theta = pi/2.0;
889       else                                        806       else
890   theta = 3.0*pi/2.0;                             807   theta = 3.0*pi/2.0;
891     }                                             808     }
892   else                                            809   else
893     {                                             810     {
894       if (rand2<0.5)                              811       if (rand2<0.5)
895   theta = 0;                                      812   theta = 0;
896       else                                        813       else
897   theta = pi;                                     814   theta = pi;
898     }                                             815     }
899   G4double cosBeta = std::cos(theta);             816   G4double cosBeta = std::cos(theta);
900   G4double sinBeta = std::sqrt(1-cosBeta*cosBe    817   G4double sinBeta = std::sqrt(1-cosBeta*cosBeta);
901                                                   818   
902   G4ThreeVector gammaPolarization1;               819   G4ThreeVector gammaPolarization1;
903                                                   820 
904   G4double xParallel = normalisation*cosBeta;     821   G4double xParallel = normalisation*cosBeta;
905   G4double yParallel = -(sinSqrTh*cosPhi*sinPh    822   G4double yParallel = -(sinSqrTh*cosPhi*sinPhi)*cosBeta/normalisation;
906   G4double zParallel = -(costheta*sinTheta*cos    823   G4double zParallel = -(costheta*sinTheta*cosPhi)*cosBeta/normalisation;
907   G4double xPerpendicular = 0.;                   824   G4double xPerpendicular = 0.;
908   G4double yPerpendicular = (costheta)*sinBeta    825   G4double yPerpendicular = (costheta)*sinBeta/normalisation;
909   G4double zPerpendicular = -(sinTheta*sinPhi)    826   G4double zPerpendicular = -(sinTheta*sinPhi)*sinBeta/normalisation;
910                                                   827 
911   G4double xTotal = (xParallel + xPerpendicula    828   G4double xTotal = (xParallel + xPerpendicular);
912   G4double yTotal = (yParallel + yPerpendicula    829   G4double yTotal = (yParallel + yPerpendicular);
913   G4double zTotal = (zParallel + zPerpendicula    830   G4double zTotal = (zParallel + zPerpendicular);
914                                                   831   
915   gammaPolarization1.setX(xTotal);                832   gammaPolarization1.setX(xTotal);
916   gammaPolarization1.setY(yTotal);                833   gammaPolarization1.setY(yTotal);
917   gammaPolarization1.setZ(zTotal);                834   gammaPolarization1.setZ(zTotal);
918                                                   835   
919   return gammaPolarization1;                      836   return gammaPolarization1;
                                                   >> 837 
920 }                                                 838 }
921                                                   839 
922 //....oooOO0OOooo........oooOO0OOooo........oo    840 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
923                                                   841 
924 void G4LivermorePolarizedComptonModel::SystemO    842 void G4LivermorePolarizedComptonModel::SystemOfRefChange(G4ThreeVector& direction0,
925                 G4ThreeVector& direction1,        843                 G4ThreeVector& direction1,
926                 G4ThreeVector& polarization0,     844                 G4ThreeVector& polarization0,
927                 G4ThreeVector& polarization1)     845                 G4ThreeVector& polarization1)
928 {                                                 846 {
929   // direction0 is the original photon directi    847   // direction0 is the original photon direction ---> z
930   // polarization0 is the original photon pola    848   // polarization0 is the original photon polarization ---> x
931   // need to specify y axis in the real refere    849   // need to specify y axis in the real reference frame ---> y 
932   G4ThreeVector Axis_Z0 = direction0.unit();      850   G4ThreeVector Axis_Z0 = direction0.unit();
933   G4ThreeVector Axis_X0 = polarization0.unit()    851   G4ThreeVector Axis_X0 = polarization0.unit();
934   G4ThreeVector Axis_Y0 = (Axis_Z0.cross(Axis_    852   G4ThreeVector Axis_Y0 = (Axis_Z0.cross(Axis_X0)).unit(); // to be confirmed;
935                                                   853 
936   G4double direction_x = direction1.getX();       854   G4double direction_x = direction1.getX();
937   G4double direction_y = direction1.getY();       855   G4double direction_y = direction1.getY();
938   G4double direction_z = direction1.getZ();       856   G4double direction_z = direction1.getZ();
939                                                   857   
940   direction1 = (direction_x*Axis_X0 + directio    858   direction1 = (direction_x*Axis_X0 + direction_y*Axis_Y0 + direction_z*Axis_Z0).unit();
941   G4double polarization_x = polarization1.getX    859   G4double polarization_x = polarization1.getX();
942   G4double polarization_y = polarization1.getY    860   G4double polarization_y = polarization1.getY();
943   G4double polarization_z = polarization1.getZ    861   G4double polarization_z = polarization1.getZ();
944                                                   862 
945   polarization1 = (polarization_x*Axis_X0 + po    863   polarization1 = (polarization_x*Axis_X0 + polarization_y*Axis_Y0 + polarization_z*Axis_Z0).unit();
946                                                   864 
947 }                                                 865 }
948                                                   866 
949                                                   867 
950 //....oooOO0OOooo........oooOO0OOooo........oo    868 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
951 //....oooOO0OOooo........oooOO0OOooo........oo    869 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
952                                                   870 
                                                   >> 871 #include "G4AutoLock.hh"
                                                   >> 872 namespace { G4Mutex LivermorePolarizedComptonModelMutex = G4MUTEX_INITIALIZER; }
                                                   >> 873 
953 void                                              874 void 
954 G4LivermorePolarizedComptonModel::InitialiseFo    875 G4LivermorePolarizedComptonModel::InitialiseForElement(const G4ParticleDefinition*, 
955                 G4int Z)                          876                 G4int Z)
956 {                                                 877 {
957   G4AutoLock l(&LivermorePolarizedComptonModel    878   G4AutoLock l(&LivermorePolarizedComptonModelMutex);
                                                   >> 879   //  G4cout << "G4LivermoreComptonModel::InitialiseForElement Z= " 
                                                   >> 880   //   << Z << G4endl;
958   if(!data[Z]) { ReadData(Z); }                   881   if(!data[Z]) { ReadData(Z); }
959   l.unlock();                                     882   l.unlock();
960 }                                                 883 }
961                                                   884