Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/xrays/src/G4VXTRenergyLoss.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/xrays/src/G4VXTRenergyLoss.cc (Version 11.3.0) and /processes/electromagnetic/xrays/src/G4VXTRenergyLoss.cc (Version 4.1)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                    <<   3 // * DISCLAIMER                                                       *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th <<   5 // * The following disclaimer summarizes all the specific disclaimers *
  6 // * the Geant4 Collaboration.  It is provided <<   6 // * of contributors to this software. The specific disclaimers,which *
  7 // * conditions of the Geant4 Software License <<   7 // * govern, are listed with their locations in:                      *
  8 // * LICENSE and available at  http://cern.ch/ <<   8 // *   http://cern.ch/geant4/license                                  *
  9 // * include a list of copyright holders.      << 
 10 // *                                                9 // *                                                                  *
 11 // * Neither the authors of this software syst     10 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     11 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     12 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     13 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  <<  14 // * use.                                                             *
 16 // * for the full disclaimer and the limitatio << 
 17 // *                                               15 // *                                                                  *
 18 // * This  code  implementation is the result  <<  16 // * This  code  implementation is the  intellectual property  of the *
 19 // * technical work of the GEANT4 collaboratio <<  17 // * GEANT4 collaboration.                                            *
 20 // * By using,  copying,  modifying or  distri <<  18 // * By copying,  distributing  or modifying the Program (or any work *
 21 // * any work based  on the software)  you  ag <<  19 // * based  on  the Program)  you indicate  your  acceptance of  this *
 22 // * use  in  resulting  scientific  publicati <<  20 // * statement, and all its terms.                                    *
 23 // * acceptance of all terms of the Geant4 Sof << 
 24 // *******************************************     21 // ********************************************************************
 25 //                                                 22 //
 26 // History:                                    <<  23 //
 27 // 2001-2002 R&D by V.Grichine                 <<  24 // $Id: G4VXTRenergyLoss.cc,v 1.5 2002/03/28 07:58:29 gcosmo Exp $
 28 // 19.06.03 V. Grichine, modifications in Buil <<  25 // GEANT4 tag $Name: geant4-04-01 $
 29 //                       in respect of angle:  << 
 30 //                       improved              << 
 31 // 28.07.05, P.Gumplinger add G4ProcessType to << 
 32 // 28.09.07, V.Ivanchenko general cleanup with << 
 33 //                                                 26 //
 34                                                    27 
 35 #include "G4VXTRenergyLoss.hh"                 <<  28 #include "G4Timer.hh"
 36                                                    29 
 37 #include "G4AffineTransform.hh"                <<  30 #include "G4VXTRenergyLoss.hh"
 38 #include "G4DynamicParticle.hh"                <<  31 #include "Randomize.hh"
 39 #include "G4EmProcessSubType.hh"               <<  32 #include "G4Material.hh"
 40 #include "G4Integrator.hh"                     << 
 41 #include "G4MaterialTable.hh"                      33 #include "G4MaterialTable.hh"
 42 #include "G4ParticleMomentum.hh"               <<  34 #include "globals.hh"
 43 #include "G4PhysicalConstants.hh"              <<  35 #include "g4std/complex"
 44 #include "G4PhysicsFreeVector.hh"              <<  36 
                                                   >>  37 #include "G4LogicalVolume.hh"
                                                   >>  38 
                                                   >>  39 #include "G4PhysicsTable.hh"
                                                   >>  40 #include "G4PhysicsVector.hh"
 45 #include "G4PhysicsLinearVector.hh"                41 #include "G4PhysicsLinearVector.hh"
 46 #include "G4PhysicsLogVector.hh"                   42 #include "G4PhysicsLogVector.hh"
 47 #include "G4RotationMatrix.hh"                 <<  43 #include "G4Integrator.hh"
 48 #include "G4SandiaTable.hh"                    <<  44 #include "G4Gamma.hh"
 49 #include "G4SystemOfUnits.hh"                  <<  45 
 50 #include "G4ThreeVector.hh"                    <<  46 // Initialization of local constants
 51 #include "G4Timer.hh"                          <<  47 
 52 #include "G4VDiscreteProcess.hh"               <<  48 G4double G4VXTRenergyLoss::fTheMinEnergyTR   =    1.0*keV  ;
 53 #include "G4VParticleChange.hh"                <<  49 G4double G4VXTRenergyLoss::fTheMaxEnergyTR   =  100.0*keV  ;
 54 #include "G4VSolid.hh"                         <<  50 G4double G4VXTRenergyLoss::fTheMaxAngle    =      1.0e-3   ;
 55 #include "G4PhysicsModelCatalog.hh"            <<  51 G4double G4VXTRenergyLoss::fTheMinAngle    =      5.0e-6   ;
                                                   >>  52 G4int    G4VXTRenergyLoss::fBinTR            =   50        ;
                                                   >>  53 
                                                   >>  54 G4double G4VXTRenergyLoss::fMinProtonTkin = 100.0*GeV  ;
                                                   >>  55 G4double G4VXTRenergyLoss::fMaxProtonTkin = 100.0*TeV  ;
                                                   >>  56 G4int    G4VXTRenergyLoss::fTotBin        =  50        ;
                                                   >>  57 // Proton energy vector initialization
                                                   >>  58 
                                                   >>  59 G4PhysicsLogVector* G4VXTRenergyLoss::
                                                   >>  60 fProtonEnergyVector = new G4PhysicsLogVector(fMinProtonTkin,
                                                   >>  61                                              fMaxProtonTkin,
                                                   >>  62                                                     fTotBin  ) ;
                                                   >>  63 
                                                   >>  64 G4double G4VXTRenergyLoss::fPlasmaCof = 4.0*pi*fine_structure_const*
                                                   >>  65                                        hbarc*hbarc*hbarc/electron_mass_c2 ;
                                                   >>  66 
                                                   >>  67 G4double G4VXTRenergyLoss::fCofTR     = fine_structure_const/pi ;
                                                   >>  68 
                                                   >>  69 
                                                   >>  70 
                                                   >>  71 
 56                                                    72 
 57 //////////////////////////////////////////////     73 ////////////////////////////////////////////////////////////////////////////
                                                   >>  74 //
 58 // Constructor, destructor                         75 // Constructor, destructor
 59 G4VXTRenergyLoss::G4VXTRenergyLoss(G4LogicalVo << 
 60                                    G4Material* << 
 61                                    G4double a, << 
 62                                    const G4Str << 
 63                                    G4ProcessTy << 
 64   : G4VDiscreteProcess(processName, type)      << 
 65   , fGammaCutInKineticEnergy(nullptr)          << 
 66   , fAngleDistrTable(nullptr)                  << 
 67   , fEnergyDistrTable(nullptr)                 << 
 68   , fAngleForEnergyTable(nullptr)              << 
 69   , fPlatePhotoAbsCof(nullptr)                 << 
 70   , fGasPhotoAbsCof(nullptr)                   << 
 71   , fGammaTkinCut(0.0)                         << 
 72 {                                              << 
 73   verboseLevel = 1;                            << 
 74   secID = G4PhysicsModelCatalog::GetModelID("m << 
 75   SetProcessSubType(fTransitionRadiation);     << 
 76                                                << 
 77   fPtrGamma    = nullptr;                      << 
 78   fMinEnergyTR = fMaxEnergyTR = fMaxThetaTR =  << 
 79   fVarAngle = fLambda = fTotalDist = fPlateThi << 
 80   fAlphaPlate = 100.;                          << 
 81   fAlphaGas = 40.;                             << 
 82                                                << 
 83   fTheMinEnergyTR = CLHEP::keV * 1.; //  1.; / << 
 84   fTheMaxEnergyTR = CLHEP::keV * 100.; // 40.; << 
 85                                                << 
 86   fTheMinAngle    = 1.e-8;  //                 << 
 87   fTheMaxAngle    = 4.e-4;                     << 
 88                                                << 
 89   fTotBin = 50;  //  number of bins in log sca << 
 90   fBinTR  = 100; //   number of bins in TR vec << 
 91   fKrange = 229;                               << 
 92   // min/max angle2 in log-vectors             << 
 93                                                << 
 94   fMinThetaTR = 3.0e-9;                        << 
 95   fMaxThetaTR = 1.0e-4;                        << 
 96                                                    76 
 97                                                <<  77 G4VXTRenergyLoss::G4VXTRenergyLoss(G4LogicalVolume *anEnvelope, 
 98   // Proton energy vector initialization       <<  78            G4Material* foilMat,G4Material* gasMat,
 99   fProtonEnergyVector =                        <<  79                                     G4double a, G4double b,
100     new G4PhysicsLogVector(fMinProtonTkin, fMa <<  80                                     G4int n,const G4String& processName) :
101                                                <<  81   G4VContinuousProcess(processName)
102   fXTREnergyVector =                           <<  82 {
103     new G4PhysicsLogVector(fTheMinEnergyTR, fT <<  83   fEnvelope = anEnvelope ;
104                                                <<  84   //  fPlateNumber = fEnvelope->GetNoDaughters() ;
105   fEnvelope = anEnvelope;                      <<  85   fPlateNumber = n ;
106                                                <<  86   G4cout<<"the number of TR radiator plates = "<<fPlateNumber<<G4endl ;
107   fPlateNumber = n;                            << 
108   if(verboseLevel > 0)                         << 
109     G4cout << "### G4VXTRenergyLoss: the numbe << 
110            << fPlateNumber << G4endl;          << 
111   if(fPlateNumber == 0)                            87   if(fPlateNumber == 0)
112   {                                                88   {
113     G4Exception("G4VXTRenergyLoss::G4VXTRenerg <<  89     G4Exception("No plates in X-ray TR radiator") ;
114                 FatalException, "No plates in  << 
115   }                                                90   }
116   // default is XTR dEdx, not flux after radia <<  91   // Mean thicknesses of plates and gas gaps
117   fExitFlux      = false;                      << 
118   // default angle distribution according nume << 
119   fFastAngle     = false; // no angle accordin << 
120   fAngleRadDistr = true;                       << 
121   fCompton       = false;                      << 
122                                                    92 
123   fLambda = DBL_MAX;                           <<  93   fPlateThick = a ;
                                                   >>  94   fGasThick   = b ;
124                                                    95 
125   // Mean thicknesses of plates and gas gaps   <<  96   fTotalDist  = fPlateNumber*(fPlateThick+fGasThick) ;  
126   fPlateThick = a;                             <<  97   G4cout<<"total radiator thickness = "<<fTotalDist/cm<<" cm"<<G4endl ;
127   fGasThick   = b;                             << 
128   fTotalDist  = fPlateNumber * (fPlateThick +  << 
129   if(verboseLevel > 0)                         << 
130     G4cout << "total radiator thickness = " << << 
131            << G4endl;                          << 
132                                                    98 
133   // index of plate material                       99   // index of plate material
134   fMatIndex1 = (G4int)foilMat->GetIndex();     << 100   fMatIndex1 = foilMat->GetIndex()  ;
135   if(verboseLevel > 0)                         << 101   G4cout<<"plate material = "<<foilMat->GetName()<<G4endl ;
136     G4cout << "plate material = " << foilMat-> << 
137                                                   102 
138   // index of gas material                        103   // index of gas material
139   fMatIndex2 = (G4int)gasMat->GetIndex();      << 104   fMatIndex2 = gasMat->GetIndex()  ;
140   if(verboseLevel > 0)                         << 105   G4cout<<"gas material = "<<gasMat->GetName()<<G4endl ;
141     G4cout << "gas material = " << gasMat->Get << 
142                                                   106 
143   // plasma energy squared for plate material     107   // plasma energy squared for plate material
144   fSigma1 = fPlasmaCof * foilMat->GetElectronD << 108 
145   if(verboseLevel > 0)                         << 109   fSigma1 = fPlasmaCof*foilMat->GetElectronDensity()  ;
146     G4cout << "plate plasma energy = " << std: << 110   //  fSigma1 = (20.9*eV)*(20.9*eV) ;
147            << G4endl;                          << 111   G4cout<<"plate plasma energy = "<<sqrt(fSigma1)/eV<<" eV"<<G4endl ;
148                                                   112 
149   // plasma energy squared for gas material       113   // plasma energy squared for gas material
150   fSigma2 = fPlasmaCof * gasMat->GetElectronDe << 114 
151   if(verboseLevel > 0)                         << 115   fSigma2 = fPlasmaCof*gasMat->GetElectronDensity()  ;
152     G4cout << "gas plasma energy = " << std::s << 116   G4cout<<"gas plasma energy = "<<sqrt(fSigma2)/eV<<" eV"<<G4endl ;
153            << G4endl;                          << 
154                                                   117 
155   // Compute cofs for preparation of linear ph    118   // Compute cofs for preparation of linear photo absorption
156   ComputePlatePhotoAbsCof();                   << 
157   ComputeGasPhotoAbsCof();                     << 
158                                                   119 
159   pParticleChange = &fParticleChange;          << 120   ComputePlatePhotoAbsCof() ;
                                                   >> 121   ComputeGasPhotoAbsCof() ;
                                                   >> 122 
160 }                                                 123 }
161                                                   124 
162 //////////////////////////////////////////////    125 ///////////////////////////////////////////////////////////////////////////
                                                   >> 126 
163 G4VXTRenergyLoss::~G4VXTRenergyLoss()             127 G4VXTRenergyLoss::~G4VXTRenergyLoss()
164 {                                                 128 {
165   delete fProtonEnergyVector;                  << 129    G4int i ;
166   delete fXTREnergyVector;                     << 
167   if(fEnergyDistrTable)                        << 
168   {                                            << 
169     fEnergyDistrTable->clearAndDestroy();      << 
170     delete fEnergyDistrTable;                  << 
171   }                                            << 
172   if(fAngleRadDistr)                           << 
173   {                                            << 
174     fAngleDistrTable->clearAndDestroy();       << 
175     delete fAngleDistrTable;                   << 
176   }                                            << 
177   if(fAngleForEnergyTable)                     << 
178   {                                            << 
179     fAngleForEnergyTable->clearAndDestroy();   << 
180     delete fAngleForEnergyTable;               << 
181   }                                            << 
182 }                                              << 
183                                                   130 
184 void G4VXTRenergyLoss::ProcessDescription(std: << 131    if(fEnvelope) delete fEnvelope;
185 {                                              << 132 
186   out << "Base class for 'fast' parameterisati << 133    for(i=0;i<fGasIntervalNumber;i++)
187          "transition\n"                        << 134    {
188          "radiation. Angular distribution is v << 135      delete[] fGasPhotoAbsCof[i] ;
                                                   >> 136    }
                                                   >> 137    delete[] fGasPhotoAbsCof ;
                                                   >> 138 
                                                   >> 139    for(i=0;i<fPlateIntervalNumber;i++)
                                                   >> 140    {
                                                   >> 141      delete[] fPlatePhotoAbsCof[i] ;
                                                   >> 142    }
                                                   >> 143    delete[] fPlatePhotoAbsCof ; 
189 }                                                 144 }
190                                                   145 
191 //////////////////////////////////////////////    146 ///////////////////////////////////////////////////////////////////////////////
                                                   >> 147 //
192 // Returns condition for application of the mo    148 // Returns condition for application of the model depending on particle type
                                                   >> 149 
                                                   >> 150 
193 G4bool G4VXTRenergyLoss::IsApplicable(const G4    151 G4bool G4VXTRenergyLoss::IsApplicable(const G4ParticleDefinition& particle)
194 {                                                 152 {
195   return (particle.GetPDGCharge() != 0.0);     << 153   return  ( particle.GetPDGCharge() != 0.0 ) ; 
196 }                                                 154 }
197                                                   155 
198 ////////////////////////////////////////////// << 156 //////////////////////////////////////////////////////////////////////////////////
199 // Calculate step size for XTR process inside  << 157 //
200 G4double G4VXTRenergyLoss::GetMeanFreePath(con << 158 // GetContinuousStepLimit
201                                            G4F << 159 //
202 {                                              << 
203   G4int iTkin, iPlace;                         << 
204   G4double lambda, sigma, kinEnergy, mass, gam << 
205   G4double charge, chargeSq, massRatio, TkinSc << 
206   G4double E1, E2, W, W1, W2;                  << 
207                                                << 
208   *condition = NotForced;                      << 
209                                                << 
210   if(aTrack.GetVolume()->GetLogicalVolume() != << 
211     lambda = DBL_MAX;                          << 
212   else                                         << 
213   {                                            << 
214     const G4DynamicParticle* aParticle = aTrac << 
215     kinEnergy                          = aPart << 
216     mass  = aParticle->GetDefinition()->GetPDG << 
217     gamma = 1.0 + kinEnergy / mass;            << 
218     if(verboseLevel > 1)                       << 
219     {                                          << 
220       G4cout << " gamma = " << gamma << ";   f << 
221     }                                          << 
222                                                << 
223     if(std::fabs(gamma - fGamma) < 0.05 * gamm << 
224       lambda = fLambda;                        << 
225     else                                       << 
226     {                                          << 
227       charge     = aParticle->GetDefinition()- << 
228       chargeSq   = charge * charge;            << 
229       massRatio  = proton_mass_c2 / mass;      << 
230       TkinScaled = kinEnergy * massRatio;      << 
231                                                << 
232       for(iTkin = 0; iTkin < fTotBin; ++iTkin) << 
233       {                                        << 
234         if(TkinScaled < fProtonEnergyVector->G << 
235           break;                               << 
236       }                                        << 
237       iPlace = iTkin - 1;                      << 
238                                                << 
239       if(iTkin == 0)                           << 
240         lambda = DBL_MAX;  // Tkin is too smal << 
241       else  // general case: Tkin between two  << 
242       {                                        << 
243         if(iTkin == fTotBin)                   << 
244         {                                      << 
245           sigma = (*(*fEnergyDistrTable)(iPlac << 
246         }                                      << 
247         else                                   << 
248         {                                      << 
249           E1    = fProtonEnergyVector->GetLowE << 
250           E2    = fProtonEnergyVector->GetLowE << 
251           W     = 1.0 / (E2 - E1);             << 
252           W1    = (E2 - TkinScaled) * W;       << 
253           W2    = (TkinScaled - E1) * W;       << 
254           sigma = ((*(*fEnergyDistrTable)(iPla << 
255                    (*(*fEnergyDistrTable)(iPla << 
256                   chargeSq;                    << 
257         }                                      << 
258         if(sigma < DBL_MIN)                    << 
259           lambda = DBL_MAX;                    << 
260         else                                   << 
261           lambda = 1. / sigma;                 << 
262         fLambda = lambda;                      << 
263         fGamma  = gamma;                       << 
264         if(verboseLevel > 1)                   << 
265         {                                      << 
266           G4cout << " lambda = " << lambda / m << 
267         }                                      << 
268       }                                        << 
269     }                                          << 
270   }                                            << 
271   return lambda;                               << 
272 }                                              << 
273                                                   160 
274 ////////////////////////////////////////////// << 161 G4double 
275 // Interface for build table from physics list << 162 G4VXTRenergyLoss::GetContinuousStepLimit(const G4Track& aTrack,
276 void G4VXTRenergyLoss::BuildPhysicsTable(const << 163                  G4double  ,
                                                   >> 164                  G4double  ,
                                                   >> 165                                          G4double& )
277 {                                                 166 {
278   if(pd.GetPDGCharge() == 0.)                  << 167   G4double StepLimit = DBL_MAX;
279   {                                            << 
280     G4Exception("G4VXTRenergyLoss::BuildPhysic << 
281                 JustWarning, "XTR initialisati << 
282   }                                            << 
283   BuildEnergyTable();                          << 
284                                                   168 
285   if(fAngleRadDistr)                           << 169   return StepLimit;
286   {                                            << 
287     if(verboseLevel > 0)                       << 
288     {                                          << 
289       G4cout                                   << 
290         << "Build angle for energy distributio << 
291         << G4endl;                             << 
292     }                                          << 
293     BuildAngleForEnergyBank();                 << 
294   }                                            << 
295 }                                                 170 }
296                                                   171 
297 //////////////////////////////////////////////    172 //////////////////////////////////////////////////////////////////////////
                                                   >> 173 //
298 // Build integral energy distribution of XTR p    174 // Build integral energy distribution of XTR photons
299 void G4VXTRenergyLoss::BuildEnergyTable()      << 
300 {                                              << 
301   G4int iTkin, iTR, iPlace;                    << 
302   G4double radiatorCof = 1.0;  // for tuning o << 
303   G4double energySum   = 0.0;                  << 
304                                                << 
305   fEnergyDistrTable = new G4PhysicsTable(fTotB << 
306   if(fAngleRadDistr)                           << 
307     fAngleDistrTable = new G4PhysicsTable(fTot << 
308                                                << 
309   fGammaTkinCut = 0.0;                         << 
310                                                << 
311   // setting of min/max TR energies            << 
312   if(fGammaTkinCut > fTheMinEnergyTR)          << 
313     fMinEnergyTR = fGammaTkinCut;              << 
314   else                                         << 
315     fMinEnergyTR = fTheMinEnergyTR;            << 
316                                                   175 
317   if(fGammaTkinCut > fTheMaxEnergyTR)          << 176 void G4VXTRenergyLoss::BuildTable() 
318     fMaxEnergyTR = 2.0 * fGammaTkinCut;        << 177 {
319   else                                         << 178   G4int iTkin, iTR, iPlace ;
320     fMaxEnergyTR = fTheMaxEnergyTR;            << 179   G4double radiatorCof = 1.0 ;           // for tuning of XTR yield
321                                                   180 
322   G4Integrator<G4VXTRenergyLoss, G4double (G4V << 181   fEnergyDistrTable = new G4PhysicsTable(fTotBin) ;
323     integral;                                  << 
324                                                   182 
325   G4cout.precision(4);                         << 183   fGammaTkinCut = 0.0 ;
326   G4Timer timer;                               << 184   
327   timer.Start();                               << 185   // setting of min/max TR energies 
                                                   >> 186   
                                                   >> 187   if(fGammaTkinCut > fTheMinEnergyTR)  fMinEnergyTR = fGammaTkinCut ;
                                                   >> 188   else                                 fMinEnergyTR = fTheMinEnergyTR ;
                                                   >> 189   
                                                   >> 190   if(fGammaTkinCut > fTheMaxEnergyTR) fMaxEnergyTR = 2.0*fGammaTkinCut ;  
                                                   >> 191   else                                fMaxEnergyTR = fTheMaxEnergyTR ;
328                                                   192 
329   if(verboseLevel > 0)                         << 193   G4cout.precision(4) ;
330   {                                            << 194   G4Timer timer ;
331     G4cout << G4endl;                          << 195   timer.Start() ;
332     G4cout << "Lorentz Factor"                 << 196   
333            << "\t"                             << 197   for( iTkin = 0 ; iTkin < fTotBin ; iTkin++ )      // Lorentz factor loop
334            << "XTR photon number" << G4endl;   << 
335     G4cout << G4endl;                          << 
336   }                                            << 
337   for(iTkin = 0; iTkin < fTotBin; ++iTkin)  // << 
338   {                                               198   {
339     auto energyVector =                        << 199      G4PhysicsLogVector* energyVector = new G4PhysicsLogVector( fMinEnergyTR,
340       new G4PhysicsLogVector(fMinEnergyTR, fMa << 200                                                                 fMaxEnergyTR,
341                                                << 201                                                                 fBinTR         ) ;
342     fGamma =                                   << 
343       1.0 + (fProtonEnergyVector->GetLowEdgeEn << 
344                                                   202 
345     // if(fMaxThetaTR > fTheMaxAngle)     fMax << 203      fGamma = 1.0 + (fProtonEnergyVector->
346     // else if(fMaxThetaTR < fTheMinAngle)     << 204                             GetLowEdgeEnergy(iTkin)/proton_mass_c2) ;
347                                                   205 
348     energySum = 0.0;                           << 206      fMaxThetaTR = 25.0/(fGamma*fGamma) ;  // theta^2
349                                                   207 
350     energyVector->PutValue(fBinTR - 1, energyS << 208      fTheMinAngle = 1.0e-6 ; // was 5.e-6, e-5, e-4
351                                                << 209  
352     for(iTR = fBinTR - 2; iTR >= 0; --iTR)     << 210      if( fMaxThetaTR > fTheMaxAngle )    fMaxThetaTR = fTheMaxAngle ; 
353     {                                          << 211      else
354       // Legendre96 or Legendre10              << 212      {
355                                                << 213        if( fMaxThetaTR < fTheMinAngle )  fMaxThetaTR = fTheMinAngle ;
356       energySum += radiatorCof * fCofTR *      << 214      }
357                                                << 215 
358   // integral.Legendre10(this, &G4VXTRenergyLo << 216      G4PhysicsLinearVector* angleVector = new G4PhysicsLinearVector(        0.0,
359                                                << 217                                                                     fMaxThetaTR,
360                    integral.Legendre96(this, & << 218                                                                     fBinTR      ) ;
361                                                << 219 
362                                        energyV << 220      G4double energySum = 0.0 ;
363                                        energyV << 221      G4double angleSum  = 0.0 ;
364                                                << 222      G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral ;
365       energyVector->PutValue(iTR, energySum /  << 223      energyVector->PutValue(fBinTR-1,energySum) ;
366     }                                          << 224      angleVector->PutValue(fBinTR-1,angleSum)   ;
367     iPlace = iTkin;                            << 225 
368     fEnergyDistrTable->insertAt(iPlace, energy << 226      for( iTR = fBinTR - 2 ; iTR >= 0 ; iTR-- )
369                                                << 227      {
370     if(verboseLevel > 0)                       << 228         energySum += radiatorCof*fCofTR*integral.Legendre10(
371     {                                          << 229          this,&G4VXTRenergyLoss::SpectralXTRdEdx,
372       G4cout << fGamma << "\t" << energySum << << 230                      energyVector->GetLowEdgeEnergy(iTR),
373     }                                          << 231                      energyVector->GetLowEdgeEnergy(iTR+1) ) ; 
374   }                                            << 232 
375   timer.Stop();                                << 233   //    angleSum  += fCofTR*integral.Legendre96(
376   G4cout.precision(6);                         << 234   //       this,&G4VXTRenergyLoss::AngleXTRdEdx,
377   if(verboseLevel > 0)                         << 235   //       angleVector->GetLowEdgeEnergy(iTR),
378   {                                            << 236   //       angleVector->GetLowEdgeEnergy(iTR+1) ) ;
379     G4cout << G4endl;                          << 237 
380     G4cout << "total time for build X-ray TR e << 238         energyVector->PutValue(iTR,energySum/fTotalDist) ;
381            << timer.GetUserElapsed() << " s" < << 239         //  angleVector ->PutValue(iTR,angleSum)   ;
382   }                                            << 240      }
383   fGamma = 0.;                                 << 241      G4cout<<iTkin<<"\t"
384   return;                                      << 242            <<"fGamma = "<<fGamma<<"\t"  //  <<"  fMaxThetaTR = "<<fMaxThetaTR
                                                   >> 243            <<"sumE = "<<energySum      // <<" ; sumA = "<<angleSum
                                                   >> 244            <<G4endl ;
                                                   >> 245      iPlace = iTkin ;
                                                   >> 246      fEnergyDistrTable->insertAt(iPlace,energyVector) ;
                                                   >> 247      //  fAngleDistrTable->insertAt(iPlace,angleVector) ;
                                                   >> 248   }     
                                                   >> 249   timer.Stop() ;
                                                   >> 250   G4cout.precision(6) ;
                                                   >> 251   G4cout<<G4endl ;
                                                   >> 252   G4cout<<"total time for build X-ray TR energy loss tables = "
                                                   >> 253         <<timer.GetUserElapsed()<<" s"<<G4endl ;
                                                   >> 254   return ;
385 }                                                 255 }
386                                                   256 
387 //////////////////////////////////////////////    257 //////////////////////////////////////////////////////////////////////////
388 // Bank of angle distributions for given energ << 258 //
                                                   >> 259 //
389                                                   260 
390 void G4VXTRenergyLoss::BuildAngleForEnergyBank << 261 void G4VXTRenergyLoss::BuildEnergyTable()
391 {                                                 262 {
392                                                << 263   return ;
393   if( ( this->GetProcessName() == "TranspRegXT << 
394         this->GetProcessName() == "TranspRegXT << 
395         this->GetProcessName() == "RegularXTRa << 
396   this->GetProcessName() == "RegularXTRmodel"  << 
397   {                                            << 
398     BuildAngleTable(); // by sum of delta-func << 
399     return;                                    << 
400   }                                            << 
401   G4int i, iTkin, iTR;                         << 
402   G4double angleSum = 0.0;                     << 
403                                                << 
404   fGammaTkinCut = 0.0;                         << 
405                                                << 
406   // setting of min/max TR energies            << 
407   if(fGammaTkinCut > fTheMinEnergyTR)          << 
408     fMinEnergyTR = fGammaTkinCut;              << 
409   else                                         << 
410     fMinEnergyTR = fTheMinEnergyTR;            << 
411                                                << 
412   if(fGammaTkinCut > fTheMaxEnergyTR)          << 
413     fMaxEnergyTR = 2.0 * fGammaTkinCut;        << 
414   else                                         << 
415     fMaxEnergyTR = fTheMaxEnergyTR;            << 
416                                                << 
417   auto energyVector =                          << 
418     new G4PhysicsLogVector(fMinEnergyTR, fMaxE << 
419                                                << 
420   G4Integrator<G4VXTRenergyLoss, G4double (G4V << 
421     integral;                                  << 
422                                                << 
423   G4cout.precision(4);                         << 
424   G4Timer timer;                               << 
425   timer.Start();                               << 
426                                                << 
427   for(iTkin = 0; iTkin < fTotBin; ++iTkin)  // << 
428   {                                            << 
429     fGamma =                                   << 
430       1.0 + (fProtonEnergyVector->GetLowEdgeEn << 
431                                                << 
432     if(fMaxThetaTR > fTheMaxAngle)             << 
433       fMaxThetaTR = fTheMaxAngle;              << 
434     else if(fMaxThetaTR < fTheMinAngle)        << 
435       fMaxThetaTR = fTheMinAngle;              << 
436                                                << 
437     fAngleForEnergyTable = new G4PhysicsTable( << 
438                                                << 
439     for(iTR = 0; iTR < fBinTR; ++iTR)          << 
440     {                                          << 
441       angleSum = 0.0;                          << 
442       fEnergy  = energyVector->GetLowEdgeEnerg << 
443                                                << 
444      // log-vector to increase number of thin  << 
445       auto angleVector = new G4PhysicsLogVecto << 
446                                                << 
447                                                << 
448                                                << 
449       angleVector->PutValue(fBinTR - 1, angleS << 
450                                                << 
451       for(i = fBinTR - 2; i >= 0; --i)         << 
452       {                                        << 
453         // Legendre96 or Legendre10            << 
454                                                << 
455         angleSum +=                            << 
456           integral.Legendre10(this, &G4VXTRene << 
457                               angleVector->Get << 
458                               angleVector->Get << 
459                                                << 
460         angleVector->PutValue(i, angleSum);    << 
461       }                                        << 
462       fAngleForEnergyTable->insertAt(iTR, angl << 
463     }                                          << 
464     fAngleBank.push_back(fAngleForEnergyTable) << 
465   }                                            << 
466   timer.Stop();                                << 
467   G4cout.precision(6);                         << 
468   if(verboseLevel > 0)                         << 
469   {                                            << 
470     G4cout << G4endl;                          << 
471     G4cout << "total time for build X-ray TR a << 
472            << timer.GetUserElapsed() << " s" < << 
473   }                                            << 
474   fGamma = 0.;                                 << 
475   delete energyVector;                         << 
476 }                                                 264 }
477                                                   265 
478 //////////////////////////////////////////////    266 ////////////////////////////////////////////////////////////////////////
479 // Build XTR angular distribution at given ene << 267 //
480 // of transparent regular radiator             << 268 //
                                                   >> 269 
481 void G4VXTRenergyLoss::BuildAngleTable()          270 void G4VXTRenergyLoss::BuildAngleTable()
482 {                                                 271 {
483   G4int iTkin, iTR;                            << 272   return ;
484   G4double energy;                             << 273 } 
485                                                << 
486   fGammaTkinCut = 0.0;                         << 
487                                                   274 
488   // setting of min/max TR energies            << 
489   if(fGammaTkinCut > fTheMinEnergyTR)          << 
490     fMinEnergyTR = fGammaTkinCut;              << 
491   else                                         << 
492     fMinEnergyTR = fTheMinEnergyTR;            << 
493                                                   275 
494   if(fGammaTkinCut > fTheMaxEnergyTR)          << 276 //////////////////////////////////////////////////////////////////////////////
495     fMaxEnergyTR = 2.0 * fGammaTkinCut;        << 277 //
496   else                                         << 278 // The main function which is responsible for the treatment of a particle passage
497     fMaxEnergyTR = fTheMaxEnergyTR;            << 279 // trough G4Envelope
498                                                << 
499   G4cout.precision(4);                         << 
500   G4Timer timer;                               << 
501   timer.Start();                               << 
502   if(verboseLevel > 0)                         << 
503   {                                            << 
504     G4cout << G4endl << "Lorentz Factor" << "\ << 
505            << "XTR photon number" << G4endl << << 
506   }                                            << 
507   for(iTkin = 0; iTkin < fTotBin; ++iTkin)  // << 
508   {                                            << 
509     fGamma =                                   << 
510       1.0 + (fProtonEnergyVector->GetLowEdgeEn << 
511                                                << 
512     // fMaxThetaTR = 25. * 2500.0 / (fGamma *  << 
513                                                << 
514     if(fMaxThetaTR > fTheMaxAngle)             << 
515       fMaxThetaTR = fTheMaxAngle;              << 
516     else                                       << 
517     {                                          << 
518       if(fMaxThetaTR < fTheMinAngle)           << 
519         fMaxThetaTR = fTheMinAngle;            << 
520     }                                          << 
521                                                << 
522     fAngleForEnergyTable = new G4PhysicsTable( << 
523                                                << 
524     for(iTR = 0; iTR < fBinTR; ++iTR)          << 
525     {                                          << 
526       energy = fXTREnergyVector->GetLowEdgeEne << 
527                                                << 
528       G4PhysicsFreeVector* angleVector = GetAn << 
529                                                << 
530       fAngleForEnergyTable->insertAt(iTR, angl << 
531     }                                          << 
532     fAngleBank.push_back(fAngleForEnergyTable) << 
533   }                                            << 
534   timer.Stop();                                << 
535   G4cout.precision(6);                         << 
536   if(verboseLevel > 0)                         << 
537   {                                            << 
538     G4cout << G4endl;                          << 
539     G4cout << "total time for build XTR angle  << 
540            << timer.GetUserElapsed() << " s" < << 
541   }                                            << 
542   fGamma = 0.;                                 << 
543                                                << 
544   return;                                      << 
545 }                                              << 
546                                                   280 
547 ////////////////////////////////////////////// << 281 G4VParticleChange* G4VXTRenergyLoss::AlongStepDoIt( const G4Track& aTrack, 
548 // Vector of angles and angle integral distrib << 282                                         const G4Step&  aStep   )
549 G4PhysicsFreeVector* G4VXTRenergyLoss::GetAngl << 
550 {                                                 283 {
551   G4double theta = 0., result, tmp = 0., cof1, << 284   G4int iTkin, iPlace,   numOfTR, iTR ;
552            angleSum = 0.;                      << 285   G4double energyTR, meanNumOfTR, theta, phi, dirX, dirY, dirZ, rand ;
553   G4int iTheta, k, kMin;                       << 286   G4double W, W1, W2, E1, E2 ;
554                                                << 
555   auto angleVector = new G4PhysicsFreeVector(n << 
556                                                << 
557   cofPHC = 4. * pi * hbarc;                    << 
558   tmp    = (fSigma1 - fSigma2) / cofPHC / ener << 
559   cof1   = fPlateThick * tmp;                  << 
560   cof2   = fGasThick * tmp;                    << 
561                                                   287 
562   cofMin = energy * (fPlateThick + fGasThick)  << 288   aParticleChange.Initialize(aTrack);
563   cofMin += (fPlateThick * fSigma1 + fGasThick << 
564   cofMin /= cofPHC;                            << 
565                                                   289 
566   kMin = G4int(cofMin);                        << 290   if(verboseLevel)
567   if(cofMin > kMin)                            << 
568     kMin++;                                    << 
569                                                << 
570   if(verboseLevel > 2)                         << 
571   {                                               291   {
572     G4cout << "n-1 = " << n - 1                << 292     G4cout<<"Start of G4VXTRenergyLoss::AlongStepDoIt "<<G4endl ;
573            << "; theta = " << std::sqrt(fMaxTh << 293     G4cout<<"name of current material =  "
574            << "; tmp = " << 0. << ";    angleS << 294           <<aTrack.GetVolume()->GetLogicalVolume()->GetMaterial()->GetName()<<G4endl ;
575   }                                               295   }
                                                   >> 296 // if(aStep.GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume() != fEnvelope) 
576                                                   297 
577   for(iTheta = n - 1; iTheta >= 1; --iTheta)   << 298   if( aTrack.GetVolume()->GetLogicalVolume() != fEnvelope ) 
578   {                                               299   {
579     k      = iTheta - 1 + kMin;                << 300     if(verboseLevel)
580     tmp    = pi * fPlateThick * (k + cof2) / ( << 
581     result = (k - cof1) * (k - cof1) * (k + co << 
582     tmp    = std::sin(tmp) * std::sin(tmp) * s << 
583                                                << 
584     if(k == kMin && kMin == G4int(cofMin))     << 
585     {                                             301     {
586       // angleSum += 0.5 * tmp;                << 302       G4cout<<"Go out from G4VXTRenergyLoss::AlongStepDoIt: wrong volume "<<G4endl;
587       angleSum += tmp; // ATLAS TB             << 
588     }                                             303     }
589     else if(iTheta == n - 1)                   << 304     return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
590       ;                                        << 
591     else                                       << 
592     {                                          << 
593       angleSum += tmp;                         << 
594     }                                          << 
595     theta = std::abs(k - cofMin) * cofPHC / en << 
596                                                << 
597     if(verboseLevel > 2)                       << 
598     {                                          << 
599       G4cout << "iTheta = " << iTheta << "; k  << 
600              << "; theta = " << std::sqrt(thet << 
601              << ";    angleSum = " << angleSum << 
602     }                                          << 
603     angleVector->PutValue(iTheta, theta, angle << 
604   }                                            << 
605   if(theta > 0.)                               << 
606   {                                            << 
607     // angleSum += 0.5 * tmp;                  << 
608     angleSum += 0.;  // ATLAS TB               << 
609     theta     = 0.;                            << 
610   }                                            << 
611   if(verboseLevel > 2)                         << 
612   {                                            << 
613     G4cout << "iTheta = " << iTheta << "; thet << 
614            << "; tmp = " << tmp << ";    angle << 
615   }                                               305   }
616   angleVector->PutValue(iTheta, theta, angleSu << 306   G4StepPoint* pPreStepPoint  = aStep.GetPreStepPoint();
617                                                << 307   G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
618   return angleVector;                          << 308   
619 }                                              << 309   const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
620                                                << 310   G4double charge = aParticle->GetDefinition()->GetPDGCharge();
621 ////////////////////////////////////////////// << 311   
622 // Build XTR angular distribution based on the << 312  
623 // radiator                                    << 313   // Now we are ready to Generate TR photons
624 void G4VXTRenergyLoss::BuildGlobalAngleTable() << 
625 {                                              << 
626   G4int iTkin, iTR, iPlace;                    << 
627   G4double radiatorCof = 1.0;  // for tuning o << 
628   G4double angleSum;                           << 
629   fAngleDistrTable = new G4PhysicsTable(fTotBi << 
630                                                << 
631   fGammaTkinCut = 0.0;                         << 
632                                                << 
633   // setting of min/max TR energies            << 
634   if(fGammaTkinCut > fTheMinEnergyTR)          << 
635     fMinEnergyTR = fGammaTkinCut;              << 
636   else                                         << 
637     fMinEnergyTR = fTheMinEnergyTR;            << 
638                                                   314 
639   if(fGammaTkinCut > fTheMaxEnergyTR)          << 315   G4double chargeSq  = charge*charge ;
640     fMaxEnergyTR = 2.0 * fGammaTkinCut;        << 316   G4double kinEnergy = aParticle->GetKineticEnergy() ;
641   else                                         << 317   G4double mass      = aParticle->GetDefinition()->GetPDGMass() ;
642     fMaxEnergyTR = fTheMaxEnergyTR;            << 318   G4double gamma     = 1.0 + kinEnergy/mass ;
643                                                   319 
644   G4cout.precision(4);                         << 320   if(verboseLevel > 0 )
645   G4Timer timer;                               << 
646   timer.Start();                               << 
647   if(verboseLevel > 0)                         << 
648   {                                               321   {
649     G4cout << G4endl;                          << 322     G4cout<<"gamma = "<<gamma<<G4endl ;
650     G4cout << "Lorentz Factor"                 << 
651            << "\t"                             << 
652            << "XTR photon number" << G4endl;   << 
653     G4cout << G4endl;                          << 
654   }                                               323   }
655   for(iTkin = 0; iTkin < fTotBin; ++iTkin)  // << 324   G4double massRatio = proton_mass_c2/mass ;
656   {                                            << 325   G4double TkinScaled = kinEnergy*massRatio ;
657     fGamma =                                   << 
658       1.0 + (fProtonEnergyVector->GetLowEdgeEn << 
659                                                   326 
660     // fMaxThetaTR = 25.0 / (fGamma * fGamma); << 327   G4ThreeVector      startPos  = pPreStepPoint->GetPosition();
661     // fMaxThetaTR = 1.e-4;  // theta^2        << 328   G4double           startTime = pPreStepPoint->GetGlobalTime();
662                                                   329 
663     if(fMaxThetaTR > fTheMaxAngle)             << 330   G4ParticleMomentum direction = aParticle->GetMomentumDirection();
664       fMaxThetaTR = fTheMaxAngle;              << 
665     else                                       << 
666     {                                          << 
667       if(fMaxThetaTR < fTheMinAngle)           << 
668         fMaxThetaTR = fTheMinAngle;            << 
669     }                                          << 
670     auto angleVector =                         << 
671     // G4PhysicsLogVector* angleVector =       << 
672       new G4PhysicsLinearVector(0.0, fMaxTheta << 
673     //  new G4PhysicsLogVector(1.e-8, fMaxThet << 
674                                                << 
675     angleSum = 0.0;                            << 
676                                                   331 
677     G4Integrator<G4VXTRenergyLoss, G4double (G << 332   G4double           distance  = aStep.GetStepLength() ;
678       integral;                                << 
679                                                   333 
680     angleVector->PutValue(fBinTR - 1, angleSum << 
681                                                   334 
682     for(iTR = fBinTR - 2; iTR >= 0; --iTR)     << 335   for(iTkin=0;iTkin<fTotBin;iTkin++)
683     {                                          << 
684       angleSum += radiatorCof * fCofTR *       << 
685                   integral.Legendre96(this, &G << 
686                                       angleVec << 
687                                       angleVec << 
688                                                << 
689       angleVector->PutValue(iTR, angleSum);    << 
690     }                                          << 
691     if(verboseLevel > 1)                       << 
692     {                                          << 
693       G4cout << fGamma << "\t" << angleSum <<  << 
694     }                                          << 
695     iPlace = iTkin;                            << 
696     fAngleDistrTable->insertAt(iPlace, angleVe << 
697   }                                            << 
698   timer.Stop();                                << 
699   G4cout.precision(6);                         << 
700   if(verboseLevel > 0)                         << 
701   {                                               336   {
702     G4cout << G4endl;                          << 337     if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))  break ;    
703     G4cout << "total time for build X-ray TR a << 
704            << timer.GetUserElapsed() << " s" < << 
705   }                                               338   }
706   fGamma = 0.;                                 << 339   iPlace = iTkin - 1 ;
707                                                   340 
708   return;                                      << 341   if(iTkin == 0) // Tkin is too small, neglect of TR photon generation
709 }                                              << 
710                                                << 
711 ////////////////////////////////////////////// << 
712 // The main function which is responsible for  << 
713 // passage through G4Envelope with discrete ge << 
714 G4VParticleChange* G4VXTRenergyLoss::PostStepD << 
715                                                << 
716 {                                              << 
717   G4int iTkin;                                 << 
718   G4double energyTR, theta, theta2, phi, dirX, << 
719                                                << 
720   fParticleChange.Initialize(aTrack);          << 
721                                                << 
722   if(verboseLevel > 1)                         << 
723   {                                               342   {
724     G4cout << "Start of G4VXTRenergyLoss::Post << 343     if(verboseLevel)
725     G4cout << "name of current material =  "   << 
726            << aTrack.GetVolume()->GetLogicalVo << 
727            << G4endl;                          << 
728   }                                            << 
729   if(aTrack.GetVolume()->GetLogicalVolume() != << 
730   {                                            << 
731     if(verboseLevel > 0)                       << 
732     {                                             344     {
733       G4cout << "Go out from G4VXTRenergyLoss: << 345       G4cout<<"Go out from G4VXTRenergyLoss::AlongStepDoIt:iTkin = "<<iTkin<<G4endl;
734              << G4endl;                        << 
735     }                                             346     }
736     return G4VDiscreteProcess::PostStepDoIt(aT << 347     return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
737   }                                            << 348   } 
738   else                                         << 349   else          // general case: Tkin between two vectors of the material
739   {                                               350   {
740     G4StepPoint* pPostStepPoint        = aStep << 351     if(iTkin == fTotBin) 
741     const G4DynamicParticle* aParticle = aTrac << 
742                                                << 
743     // Now we are ready to Generate one TR pho << 
744     G4double kinEnergy = aParticle->GetKinetic << 
745     G4double mass      = aParticle->GetDefinit << 
746     G4double gamma     = 1.0 + kinEnergy / mas << 
747                                                << 
748     if(verboseLevel > 1)                       << 
749     {                                             352     {
750       G4cout << "gamma = " << gamma << G4endl; << 353       meanNumOfTR = (*(*fEnergyDistrTable)(iPlace))(0)*chargeSq*distance ;
                                                   >> 354       numOfTR = RandPoisson::shoot(meanNumOfTR) ;
751     }                                             355     }
752     G4double massRatio           = proton_mass << 356     else
753     G4double TkinScaled          = kinEnergy * << 
754     G4ThreeVector position       = pPostStepPo << 
755     G4ParticleMomentum direction = aParticle-> << 
756     G4double startTime           = pPostStepPo << 
757                                                << 
758     for(iTkin = 0; iTkin < fTotBin; ++iTkin)   << 
759     {                                             357     {
760       if(TkinScaled < fProtonEnergyVector->Get << 358       E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1) ; 
761         break;                                 << 359       E2 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin)     ;
                                                   >> 360        W = 1.0/(E2 - E1) ;
                                                   >> 361       W1 = (E2 - TkinScaled)*W ;
                                                   >> 362       W2 = (TkinScaled - E1)*W ;
                                                   >> 363       meanNumOfTR = ( (*(*fEnergyDistrTable)(iPlace  ))(0)*W1+
                                                   >> 364                       (*(*fEnergyDistrTable)(iPlace+1))(0)*W2 )*chargeSq*distance ;
                                                   >> 365       
                                                   >> 366       if(verboseLevel > 0 )
                                                   >> 367       {
                                                   >> 368         G4cout<<iTkin<<" mean TR number = "<<meanNumOfTR
                                                   >> 369               <<" or mean over energy-angle tables "
                                                   >> 370               <<(((*(*fEnergyDistrTable)(iPlace))(0)+
                                                   >> 371                   (*(*fAngleDistrTable)(iPlace))(0))*W1 + 
                                                   >> 372                  ((*(*fEnergyDistrTable)(iPlace + 1))(0)+
                                                   >> 373                   (*(*fAngleDistrTable)(iPlace + 1))(0))*W2)*chargeSq*0.5
                                                   >> 374               <<G4endl ;
                                                   >> 375       }
                                                   >> 376       numOfTR = RandPoisson::shoot( meanNumOfTR ) ;
762     }                                             377     }
763                                                << 378     if( numOfTR == 0 ) // no change, return 
764     if(iTkin == 0)  // Tkin is too small, negl << 
765     {                                             379     {
766       if(verboseLevel > 0)                     << 380       aParticleChange.SetNumberOfSecondaries(0);
                                                   >> 381       if(verboseLevel)
767       {                                           382       {
768         G4cout << "Go out from G4VXTRenergyLos << 383       G4cout<<"Go out from G4VXTRenergyLoss::AlongStepDoIt: numOfTR = "
769                << G4endl;                      << 384             <<numOfTR<<G4endl ;
770       }                                           385       }
771       return G4VDiscreteProcess::PostStepDoIt( << 386       return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep); 
772     }                                             387     }
773     else  // general case: Tkin between two ve << 388     else
774     {                                             389     {
775       fParticleChange.SetNumberOfSecondaries(1 << 390       if(verboseLevel)
                                                   >> 391       {
                                                   >> 392         G4cout<<"Number of X-ray TR photons = "<<numOfTR<<G4endl ;
                                                   >> 393       }
                                                   >> 394       aParticleChange.SetNumberOfSecondaries(numOfTR);
776                                                   395 
777       energyTR = GetXTRrandomEnergy(TkinScaled << 396       G4double sumEnergyTR = 0.0 ;
778                                                   397 
779       if(verboseLevel > 1)                     << 398       for(iTR=0;iTR<numOfTR;iTR++)
780       {                                           399       {
781         G4cout << "energyTR = " << energyTR /  << 400 
782       }                                        << 401       //    energyPos = ((*(*fEnergyDistrTable)(iPlace))(0)*W1+
783       if(fAngleRadDistr)                       << 402       //          (*(*fEnergyDistrTable)(iPlace + 1))(0)*W2)*G4UniformRand() ;
                                                   >> 403       //  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
                                                   >> 404       //  {
                                                   >> 405       //    if(energyPos >= ((*(*fEnergyDistrTable)(iPlace))(iTransfer)*W1+
                                                   >> 406       //                 (*(*fEnergyDistrTable)(iPlace + 1))(iTransfer)*W2)) break ;
                                                   >> 407       //  }
                                                   >> 408       //   energyTR = ((*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer))*W1+
                                                   >> 409       //     ((*fEnergyDistrTable)(iPlace + 1)->GetLowEdgeEnergy(iTransfer))*W2 ;
                                                   >> 410 
                                                   >> 411       energyTR = GetXTRrandomEnergy(TkinScaled,iTkin) ;
                                                   >> 412 
                                                   >> 413       if(verboseLevel)
784       {                                           414       {
785         theta2 = GetRandomAngle(energyTR, iTki << 415         G4cout<<"energyTR = "<<energyTR/keV<<"keV"<<G4endl ;
786         if(theta2 > 0.)                        << 
787           theta = std::sqrt(theta2);           << 
788         else                                   << 
789           theta = 0.;                          << 
790       }                                           416       }
791       else                                     << 417       sumEnergyTR += energyTR ;
792         theta = std::fabs(G4RandGauss::shoot(0 << 
793                                                   418 
794       if(theta >= 0.1)                         << 419       theta = abs(G4RandGauss::shoot(0.0,pi/gamma)) ;
795         theta = 0.1;                           << 
796                                                   420 
797       phi = twopi * G4UniformRand();           << 421       if( theta >= 0.1 ) theta = 0.1 ;
798                                                   422 
799       dirX = std::sin(theta) * std::cos(phi);  << 423   // G4cout<<" : theta = "<<theta<<endl ;
800       dirY = std::sin(theta) * std::sin(phi);  << 
801       dirZ = std::cos(theta);                  << 
802                                                   424 
803       G4ThreeVector directionTR(dirX, dirY, di << 425         phi = twopi*G4UniformRand() ;
804       directionTR.rotateUz(direction);         << 
805       directionTR.unit();                      << 
806                                                   426 
807       auto aPhotonTR =                         << 427         dirX = sin(theta)*cos(phi)  ;
808         new G4DynamicParticle(G4Gamma::Gamma() << 428         dirY = sin(theta)*sin(phi)  ;
                                                   >> 429         dirZ = cos(theta)           ;
809                                                   430 
810       // A XTR photon is set on the particle t << 431         G4ThreeVector directionTR(dirX,dirY,dirZ) ;
811       // and is moved to the G4Envelope surfac << 432         directionTR.rotateUz(direction) ;
812       // only. The case of fExitFlux=true      << 433         directionTR.unit() ;
813                                                   434 
814       if(fExitFlux)                            << 435         G4DynamicParticle* aPhotonTR = new G4DynamicParticle(G4Gamma::Gamma(),
815       {                                        << 436                                                               directionTR,energyTR) ;
816         const G4RotationMatrix* rotM =         << 
817           pPostStepPoint->GetTouchable()->GetR << 
818         G4ThreeVector transl = pPostStepPoint- << 
819         G4AffineTransform transform = G4Affine << 
820         transform.Invert();                    << 
821         G4ThreeVector localP = transform.Trans << 
822         G4ThreeVector localV = transform.Trans << 
823                                                << 
824         G4double distance =                    << 
825           fEnvelope->GetSolid()->DistanceToOut << 
826         if(verboseLevel > 1)                   << 
827         {                                      << 
828           G4cout << "distance to exit = " << d << 
829         }                                      << 
830         position += distance * directionTR;    << 
831         startTime += distance / c_light;       << 
832       }                                        << 
833       G4Track* aSecondaryTrack = new G4Track(a << 
834       aSecondaryTrack->SetTouchableHandle(     << 
835         aStep.GetPostStepPoint()->GetTouchable << 
836       aSecondaryTrack->SetParentID(aTrack.GetT << 
837                                                   437 
838       fParticleChange.AddSecondary(aSecondaryT << 438   // A XTR photon is set along the particle track and is not moved to 
839       fParticleChange.ProposeEnergy(kinEnergy) << 439   // the G4Envelope surface as in standard X-ray TR models
                                                   >> 440 
                                                   >> 441   rand = G4UniformRand();
                                                   >> 442         G4double delta = rand*distance ;
                                                   >> 443   G4double deltaTime = delta /
                                                   >> 444                        ((pPreStepPoint->GetVelocity()+
                                                   >> 445                          pPostStepPoint->GetVelocity())/2.);
                                                   >> 446 
                                                   >> 447         G4double aSecondaryTime = startTime + deltaTime;
                                                   >> 448 
                                                   >> 449         G4ThreeVector positionTR = startPos + delta*direction ;
                                                   >> 450 
                                                   >> 451 
                                                   >> 452         G4Track* aSecondaryTrack = new G4Track( aPhotonTR, 
                                                   >> 453                                     aSecondaryTime,positionTR ) ;
                                                   >> 454         aSecondaryTrack->SetTouchableHandle(aStep.GetPostStepPoint()
                                                   >> 455                                                   ->GetTouchableHandle());
                                                   >> 456         aSecondaryTrack->SetParentID(aTrack.GetTrackID());
                                                   >> 457 
                                                   >> 458   aParticleChange.AddSecondary(aSecondaryTrack);
                                                   >> 459       }
                                                   >> 460       kinEnergy -= sumEnergyTR ;
                                                   >> 461       aParticleChange.SetEnergyChange(kinEnergy) ;
840     }                                             462     }
841   }                                               463   }
842   return G4VDiscreteProcess::PostStepDoIt(aTra << 464   // return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
                                                   >> 465   return &aParticleChange;
843 }                                                 466 }
844                                                   467 
845 //////////////////////////////////////////////    468 ///////////////////////////////////////////////////////////////////////
                                                   >> 469 //
846 // This function returns the spectral and angl    470 // This function returns the spectral and angle density of TR quanta
847 // in X-ray energy region generated forward wh    471 // in X-ray energy region generated forward when a relativistic
848 // charged particle crosses interface between     472 // charged particle crosses interface between two materials.
849 // The high energy small theta approximation i    473 // The high energy small theta approximation is applied.
850 // (matter1 -> matter2, or 2->1)                  474 // (matter1 -> matter2, or 2->1)
851 // varAngle =2* (1 - std::cos(theta)) or appro << 475 // varAngle =2* (1 - cos(theta)) or approximately = theta*theta
852 G4complex G4VXTRenergyLoss::OneInterfaceXTRdEd << 476 //
853                                                << 477 
854 {                                              << 478 G4complex G4VXTRenergyLoss::OneInterfaceXTRdEdx( G4double energy,
855   G4complex Z1 = GetPlateComplexFZ(energy, gam << 479                                            G4double gamma,
856   G4complex Z2 = GetGasComplexFZ(energy, gamma << 480                                            G4double varAngle ) 
                                                   >> 481 {
                                                   >> 482   G4complex Z1    = GetPlateComplexFZ(energy,gamma,varAngle) ;
                                                   >> 483   G4complex Z2    = GetGasComplexFZ(energy,gamma,varAngle) ;
                                                   >> 484 
                                                   >> 485   G4complex zOut  = (Z1 - Z2)*(Z1 - Z2)
                                                   >> 486                     * (varAngle*energy/hbarc/hbarc) ;  
                                                   >> 487   return    zOut  ;
857                                                   488 
858   G4complex zOut = (Z1 - Z2) * (Z1 - Z2) * (va << 
859   return zOut;                                 << 
860 }                                                 489 }
861                                                   490 
                                                   >> 491 
862 //////////////////////////////////////////////    492 //////////////////////////////////////////////////////////////////////////////
                                                   >> 493 //
863 // For photon energy distribution tables. Inte    494 // For photon energy distribution tables. Integrate first over angle
                                                   >> 495 //
                                                   >> 496 
864 G4double G4VXTRenergyLoss::SpectralAngleXTRdEd    497 G4double G4VXTRenergyLoss::SpectralAngleXTRdEdx(G4double varAngle)
865 {                                                 498 {
866   G4double result = GetStackFactor(fEnergy, fG << 499   G4double result =  GetStackFactor(fEnergy,fGamma,varAngle) ;
867   if(result < 0.0)                             << 500   if(result < 0.0) result = 0.0 ;
868     result = 0.0;                              << 501   return result ;
869   return result;                               << 
870 }                                                 502 }
871                                                   503 
872 //////////////////////////////////////////////    504 /////////////////////////////////////////////////////////////////////////
                                                   >> 505 //
873 // For second integration over energy             506 // For second integration over energy
                                                   >> 507  
874 G4double G4VXTRenergyLoss::SpectralXTRdEdx(G4d    508 G4double G4VXTRenergyLoss::SpectralXTRdEdx(G4double energy)
875 {                                                 509 {
876   G4int i;                                     << 510   fEnergy = energy ;
877   static constexpr G4int iMax = 8;             << 511   G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral ;
878   G4double angleSum           = 0.0;           << 512   return integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
879                                                << 513                              0.0,0.3*fMaxThetaTR) +
880   G4double lim[iMax] = { 0.0, 0.01, 0.02, 0.05 << 514          integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
881                                                << 515                        0.3*fMaxThetaTR,fMaxThetaTR) ;
882   for(i = 0; i < iMax; ++i)                    << 516 } 
883     lim[i] *= fMaxThetaTR;                     << 517  
884                                                << 
885   G4Integrator<G4VXTRenergyLoss, G4double (G4V << 
886     integral;                                  << 
887                                                << 
888   fEnergy = energy;                            << 
889   {                                            << 
890     for(i = 0; i < iMax - 1; ++i)              << 
891     {                                          << 
892       angleSum += integral.Legendre96(         << 
893         this, &G4VXTRenergyLoss::SpectralAngle << 
894     }                                          << 
895   }                                            << 
896   return angleSum;                             << 
897 }                                              << 
898                                                << 
899 //////////////////////////////////////////////    518 //////////////////////////////////////////////////////////////////////////
                                                   >> 519 // 
900 // for photon angle distribution tables           520 // for photon angle distribution tables
                                                   >> 521 //
                                                   >> 522 
901 G4double G4VXTRenergyLoss::AngleSpectralXTRdEd    523 G4double G4VXTRenergyLoss::AngleSpectralXTRdEdx(G4double energy)
902 {                                                 524 {
903   G4double result = GetStackFactor(energy, fGa << 525   G4double result =  GetStackFactor(energy,fGamma,fVarAngle) ;
904   if(result < 0)                               << 526   if(result < 0) result = 0.0 ;
905     result = 0.0;                              << 527   return result ;
906   return result;                               << 528 } 
907 }                                              << 
908                                                   529 
909 //////////////////////////////////////////////    530 ///////////////////////////////////////////////////////////////////////////
910 // The XTR angular distribution based on trans << 531 //
911 G4double G4VXTRenergyLoss::AngleXTRdEdx(G4doub << 532 //
                                                   >> 533 
                                                   >> 534 G4double G4VXTRenergyLoss::AngleXTRdEdx(G4double varAngle) 
912 {                                                 535 {
913   G4double result;                             << 536   fVarAngle = varAngle ;
914   G4double sum = 0., tmp1, tmp2, tmp = 0., cof << 537   G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral ;
915            energy2;                            << 538   return integral.Legendre10(this,&G4VXTRenergyLoss::AngleSpectralXTRdEdx,
916   G4int k, kMax, kMin, i;                      << 539            fMinEnergyTR,fMaxEnergyTR) ;
                                                   >> 540 }
917                                                   541 
918   cofPHC = twopi * hbarc;                      << 
919                                                   542 
920   cof1 = (fPlateThick + fGasThick) * (1. / fGa << 
921   cof2 = fPlateThick * fSigma1 + fGasThick * f << 
922                                                   543 
923   cofMin = std::sqrt(cof1 * cof2);             << 
924   cofMin /= cofPHC;                            << 
925                                                   544 
926   kMin = G4int(cofMin);                        << 
927   if(cofMin > kMin)                            << 
928     kMin++;                                    << 
929                                                   545 
930   kMax = kMin + 9;                             << 
931                                                   546 
932   for(k = kMin; k <= kMax; ++k)                << 
933   {                                            << 
934     tmp1    = cofPHC * k;                      << 
935     tmp2    = std::sqrt(tmp1 * tmp1 - cof1 * c << 
936     energy1 = (tmp1 + tmp2) / cof1;            << 
937     energy2 = (tmp1 - tmp2) / cof1;            << 
938                                                   547 
939     for(i = 0; i < 2; ++i)                     << 
940     {                                          << 
941       if(i == 0)                               << 
942       {                                        << 
943         if(energy1 > fTheMaxEnergyTR || energy << 
944           continue;                            << 
945                                                   548 
946         tmp1 =                                 << 
947           (energy1 * energy1 * (1. / fGamma /  << 
948           fPlateThick / (4 * hbarc * energy1); << 
949         tmp2 = std::sin(tmp1);                 << 
950         tmp  = energy1 * tmp2 * tmp2;          << 
951         tmp2 = fPlateThick / (4. * tmp1);      << 
952         tmp1 =                                 << 
953           hbarc * energy1 /                    << 
954           (energy1 * energy1 * (1. / fGamma /  << 
955         tmp *= (tmp1 - tmp2) * (tmp1 - tmp2);  << 
956         tmp1 = cof1 / (4. * hbarc) - cof2 / (4 << 
957         tmp2 = std::abs(tmp1);                 << 
958                                                << 
959         if(tmp2 > 0.)                          << 
960           tmp /= tmp2;                         << 
961         else                                   << 
962           continue;                            << 
963       }                                        << 
964       else                                     << 
965       {                                        << 
966         if(energy2 > fTheMaxEnergyTR || energy << 
967           continue;                            << 
968                                                   549 
969         tmp1 =                                 << 
970           (energy2 * energy2 * (1. / fGamma /  << 
971           fPlateThick / (4. * hbarc * energy2) << 
972         tmp2 = std::sin(tmp1);                 << 
973         tmp  = energy2 * tmp2 * tmp2;          << 
974         tmp2 = fPlateThick / (4. * tmp1);      << 
975         tmp1 =                                 << 
976           hbarc * energy2 /                    << 
977           (energy2 * energy2 * (1. / fGamma /  << 
978         tmp *= (tmp1 - tmp2) * (tmp1 - tmp2);  << 
979         tmp1 = cof1 / (4. * hbarc) - cof2 / (4 << 
980         tmp2 = std::abs(tmp1);                 << 
981                                                << 
982         if(tmp2 > 0.)                          << 
983           tmp /= tmp2;                         << 
984         else                                   << 
985           continue;                            << 
986       }                                        << 
987       sum += tmp;                              << 
988     }                                          << 
989   }                                            << 
990   result = 4. * pi * fPlateNumber * sum * varA << 
991   result /= hbarc * hbarc;                     << 
992                                                   550 
993   return result;                               << 
994 }                                              << 
995                                                   551 
                                                   >> 552 
                                                   >> 553 
                                                   >> 554 
                                                   >> 555 
                                                   >> 556 //////////////////////////////////////////////////////////////////////
                                                   >> 557 //////////////////////////////////////////////////////////////////////
996 //////////////////////////////////////////////    558 //////////////////////////////////////////////////////////////////////
                                                   >> 559 //
997 // Calculates formation zone for plates. Omega    560 // Calculates formation zone for plates. Omega is energy !!!
998 G4double G4VXTRenergyLoss::GetPlateFormationZo << 561 
999                                                << 562 G4double G4VXTRenergyLoss::GetPlateFormationZone( G4double omega ,
1000 {                                             << 563                                                 G4double gamma ,
1001   G4double cof, lambda;                       << 564                                                 G4double varAngle    ) 
1002   lambda = 1.0 / gamma / gamma + varAngle + f << 565 {
1003   cof    = 2.0 * hbarc / omega / lambda;      << 566   G4double cof, lambda ;
1004   return cof;                                 << 567   lambda = 1.0/gamma/gamma + varAngle + fSigma1/omega/omega ;
                                                   >> 568   cof = 2.0*hbarc/omega/lambda ;
                                                   >> 569   return cof ;
1005 }                                                570 }
1006                                                  571 
1007 /////////////////////////////////////////////    572 //////////////////////////////////////////////////////////////////////
                                                   >> 573 //
1008 // Calculates complex formation zone for plat    574 // Calculates complex formation zone for plates. Omega is energy !!!
1009 G4complex G4VXTRenergyLoss::GetPlateComplexFZ << 575 
1010                                               << 576 G4complex G4VXTRenergyLoss::GetPlateComplexFZ( G4double omega ,
                                                   >> 577                                              G4double gamma ,
                                                   >> 578                                              G4double varAngle    ) 
1011 {                                                579 {
1012   G4double cof, length, delta, real_v, image_ << 580   G4double cof, length,delta, real, image ;
1013                                                  581 
1014   length = 0.5 * GetPlateFormationZone(omega, << 582   length = 0.5*GetPlateFormationZone(omega,gamma,varAngle) ;
1015   delta  = length * GetPlateLinearPhotoAbs(om << 583   delta  = length*GetPlateLinearPhotoAbs(omega) ;
1016   cof    = 1.0 / (1.0 + delta * delta);       << 584   cof    = 1.0/(1.0 + delta*delta) ;
1017                                                  585 
1018   real_v  = length * cof;                     << 586   real   = length*cof ;
1019   image_v = real_v * delta;                   << 587   image  = real*delta ;
1020                                                  588 
1021   G4complex zone(real_v, image_v);            << 589   G4complex zone(real,image); 
1022   return zone;                                << 590   return zone ;
1023 }                                                591 }
1024                                                  592 
1025 /////////////////////////////////////////////    593 ////////////////////////////////////////////////////////////////////////
                                                   >> 594 //
1026 // Computes matrix of Sandia photo absorption    595 // Computes matrix of Sandia photo absorption cross section coefficients for
1027 // plate material                                596 // plate material
1028 void G4VXTRenergyLoss::ComputePlatePhotoAbsCo << 
1029 {                                             << 
1030   const G4MaterialTable* theMaterialTable = G << 
1031   const G4Material* mat                   = ( << 
1032   fPlatePhotoAbsCof                       = m << 
1033                                                  597 
1034   return;                                     << 598 void G4VXTRenergyLoss::ComputePlatePhotoAbsCof() 
                                                   >> 599 {
                                                   >> 600    G4int i, j, numberOfElements ;
                                                   >> 601    static const G4MaterialTable* 
                                                   >> 602    theMaterialTable = G4Material::GetMaterialTable();
                                                   >> 603 
                                                   >> 604    G4SandiaTable thisMaterialSandiaTable(fMatIndex1) ;
                                                   >> 605    numberOfElements = (*theMaterialTable)[fMatIndex1]->GetNumberOfElements() ;
                                                   >> 606    G4int* thisMaterialZ = new G4int[numberOfElements] ;
                                                   >> 607 
                                                   >> 608    for(i=0;i<numberOfElements;i++)
                                                   >> 609    {
                                                   >> 610          thisMaterialZ[i] = (G4int)(*theMaterialTable)[fMatIndex1]->
                                                   >> 611                                       GetElement(i)->GetZ() ;
                                                   >> 612    }
                                                   >> 613    fPlateIntervalNumber = thisMaterialSandiaTable.SandiaIntervals
                                                   >> 614                            (thisMaterialZ,numberOfElements) ;
                                                   >> 615    
                                                   >> 616    fPlateIntervalNumber = thisMaterialSandiaTable.SandiaMixing
                                                   >> 617                            ( thisMaterialZ ,
                                                   >> 618                            (*theMaterialTable)[fMatIndex1]->GetFractionVector() ,
                                                   >> 619                  numberOfElements,fPlateIntervalNumber) ;
                                                   >> 620    
                                                   >> 621    fPlatePhotoAbsCof = new G4double*[fPlateIntervalNumber] ;
                                                   >> 622 
                                                   >> 623    for(i=0;i<fPlateIntervalNumber;i++)
                                                   >> 624    {
                                                   >> 625      fPlatePhotoAbsCof[i] = new G4double[5] ;
                                                   >> 626    }
                                                   >> 627    for(i=0;i<fPlateIntervalNumber;i++)
                                                   >> 628    {
                                                   >> 629       fPlatePhotoAbsCof[i][0] = thisMaterialSandiaTable.
                                                   >> 630                                 GetPhotoAbsorpCof(i+1,0) ; 
                                                   >> 631                               
                                                   >> 632       for(j=1;j<5;j++)
                                                   >> 633       {
                                                   >> 634            fPlatePhotoAbsCof[i][j] = thisMaterialSandiaTable.
                                                   >> 635                                GetPhotoAbsorpCof(i+1,j)*
                                                   >> 636                  (*theMaterialTable)[fMatIndex1]->GetDensity() ;
                                                   >> 637       }
                                                   >> 638    }
                                                   >> 639    delete[] thisMaterialZ ;
                                                   >> 640    return ;
1035 }                                                641 }
1036                                                  642 
1037 /////////////////////////////////////////////    643 //////////////////////////////////////////////////////////////////////
1038 // Returns the value of linear photo absorpti << 644 //
                                                   >> 645 // Returns the value of linear photo absorption coefficient (in reciprocal 
1039 // length) for plate for given energy of X-ra    646 // length) for plate for given energy of X-ray photon omega
1040 G4double G4VXTRenergyLoss::GetPlateLinearPhot << 647 
                                                   >> 648 G4double G4VXTRenergyLoss::GetPlateLinearPhotoAbs(G4double omega) 
1041 {                                                649 {
1042   G4double omega2, omega3, omega4;            << 650   G4int i ;
                                                   >> 651   G4double omega2, omega3, omega4 ; 
                                                   >> 652 
                                                   >> 653   omega2 = omega*omega ;
                                                   >> 654   omega3 = omega2*omega ;
                                                   >> 655   omega4 = omega2*omega2 ;
1043                                                  656 
1044   omega2 = omega * omega;                     << 657   for(i=0;i<fPlateIntervalNumber;i++)
1045   omega3 = omega2 * omega;                    << 658   {
1046   omega4 = omega2 * omega2;                   << 659     if( omega < fPlatePhotoAbsCof[i][0] ) break ;
1047                                               << 660   }
1048   const G4double* SandiaCof = fPlatePhotoAbsC << 661   if( i == 0 )
1049   G4double cross            = SandiaCof[0] /  << 662   { 
1050                    SandiaCof[2] / omega3 + Sa << 663     G4Exception("Invalid (<I1) energy in G4VXTRenergyLoss::GetPlateLinearPhotoAbs");
1051   return cross;                               << 664   }
                                                   >> 665   else i-- ;
                                                   >> 666   
                                                   >> 667   return fPlatePhotoAbsCof[i][1]/omega  + fPlatePhotoAbsCof[i][2]/omega2 + 
                                                   >> 668          fPlatePhotoAbsCof[i][3]/omega3 + fPlatePhotoAbsCof[i][4]/omega4  ;
1052 }                                                669 }
1053                                                  670 
1054 /////////////////////////////////////////////    671 //////////////////////////////////////////////////////////////////////
                                                   >> 672 //
1055 // Calculates formation zone for gas. Omega i    673 // Calculates formation zone for gas. Omega is energy !!!
1056 G4double G4VXTRenergyLoss::GetGasFormationZon << 674 
1057                                               << 675 G4double G4VXTRenergyLoss::GetGasFormationZone( G4double omega ,
1058 {                                             << 676                                               G4double gamma ,
1059   G4double cof, lambda;                       << 677                                               G4double varAngle   ) 
1060   lambda = 1.0 / gamma / gamma + varAngle + f << 678 {
1061   cof    = 2.0 * hbarc / omega / lambda;      << 679   G4double cof, lambda ;
1062   return cof;                                 << 680   lambda = 1.0/gamma/gamma + varAngle + fSigma2/omega/omega ;
                                                   >> 681   cof = 2.0*hbarc/omega/lambda ;
                                                   >> 682   return cof ;
                                                   >> 683 
1063 }                                                684 }
1064                                                  685 
                                                   >> 686 
1065 /////////////////////////////////////////////    687 //////////////////////////////////////////////////////////////////////
                                                   >> 688 //
1066 // Calculates complex formation zone for gas     689 // Calculates complex formation zone for gas gaps. Omega is energy !!!
1067 G4complex G4VXTRenergyLoss::GetGasComplexFZ(G << 690 
1068                                             G << 691 G4complex G4VXTRenergyLoss::GetGasComplexFZ( G4double omega ,
                                                   >> 692                                            G4double gamma ,
                                                   >> 693                                            G4double varAngle    ) 
1069 {                                                694 {
1070   G4double cof, length, delta, real_v, image_ << 695   G4double cof, length,delta, real, image ;
1071                                                  696 
1072   length = 0.5 * GetGasFormationZone(omega, g << 697   length = 0.5*GetGasFormationZone(omega,gamma,varAngle) ;
1073   delta  = length * GetGasLinearPhotoAbs(omeg << 698   delta  = length*GetGasLinearPhotoAbs(omega) ;
1074   cof    = 1.0 / (1.0 + delta * delta);       << 699   cof    = 1.0/(1.0 + delta*delta) ;
1075                                                  700 
1076   real_v  = length * cof;                     << 701   real   = length*cof ;
1077   image_v = real_v * delta;                   << 702   image  = real*delta ;
1078                                                  703 
1079   G4complex zone(real_v, image_v);            << 704   G4complex zone(real,image); 
1080   return zone;                                << 705   return zone ;
1081 }                                                706 }
1082                                                  707 
                                                   >> 708 
                                                   >> 709 
1083 /////////////////////////////////////////////    710 ////////////////////////////////////////////////////////////////////////
                                                   >> 711 //
1084 // Computes matrix of Sandia photo absorption    712 // Computes matrix of Sandia photo absorption cross section coefficients for
1085 // gas material                                  713 // gas material
1086 void G4VXTRenergyLoss::ComputeGasPhotoAbsCof( << 714 
                                                   >> 715 void G4VXTRenergyLoss::ComputeGasPhotoAbsCof() 
1087 {                                                716 {
1088   const G4MaterialTable* theMaterialTable = G << 717    G4int i, j, numberOfElements ;
1089   const G4Material* mat                   = ( << 718    static const G4MaterialTable* 
1090   fGasPhotoAbsCof                         = m << 719    theMaterialTable = G4Material::GetMaterialTable();
1091   return;                                     << 720 
                                                   >> 721    G4SandiaTable thisMaterialSandiaTable(fMatIndex2) ;
                                                   >> 722    numberOfElements = (*theMaterialTable)[fMatIndex2]->GetNumberOfElements() ;
                                                   >> 723    G4int* thisMaterialZ = new G4int[numberOfElements] ;
                                                   >> 724 
                                                   >> 725    for(i=0;i<numberOfElements;i++)
                                                   >> 726    {
                                                   >> 727          thisMaterialZ[i] = (G4int)(*theMaterialTable)[fMatIndex2]->
                                                   >> 728                                       GetElement(i)->GetZ() ;
                                                   >> 729    }
                                                   >> 730    fGasIntervalNumber = thisMaterialSandiaTable.SandiaIntervals
                                                   >> 731                            (thisMaterialZ,numberOfElements) ;
                                                   >> 732    
                                                   >> 733    fGasIntervalNumber = thisMaterialSandiaTable.SandiaMixing
                                                   >> 734                            ( thisMaterialZ ,
                                                   >> 735                            (*theMaterialTable)[fMatIndex2]->GetFractionVector() ,
                                                   >> 736                  numberOfElements,fGasIntervalNumber) ;
                                                   >> 737    
                                                   >> 738    fGasPhotoAbsCof = new G4double*[fGasIntervalNumber] ;
                                                   >> 739 
                                                   >> 740    for(i=0;i<fGasIntervalNumber;i++)
                                                   >> 741    {
                                                   >> 742      fGasPhotoAbsCof[i] = new G4double[5] ;
                                                   >> 743    }
                                                   >> 744    for(i=0;i<fGasIntervalNumber;i++)
                                                   >> 745    {
                                                   >> 746       fGasPhotoAbsCof[i][0] = thisMaterialSandiaTable.
                                                   >> 747                                 GetPhotoAbsorpCof(i+1,0) ; 
                                                   >> 748                               
                                                   >> 749       for(j=1;j<5;j++)
                                                   >> 750       {
                                                   >> 751            fGasPhotoAbsCof[i][j] = thisMaterialSandiaTable.
                                                   >> 752                                GetPhotoAbsorpCof(i+1,j)*
                                                   >> 753                  (*theMaterialTable)[fMatIndex2]->GetDensity() ;
                                                   >> 754       }
                                                   >> 755    }
                                                   >> 756    delete[] thisMaterialZ ;
                                                   >> 757    return ;
1092 }                                                758 }
1093                                                  759 
1094 /////////////////////////////////////////////    760 //////////////////////////////////////////////////////////////////////
1095 // Returns the value of linear photo absorpti << 761 //
                                                   >> 762 // Returns the value of linear photo absorption coefficient (in reciprocal 
1096 // length) for gas                               763 // length) for gas
1097 G4double G4VXTRenergyLoss::GetGasLinearPhotoA << 764 
                                                   >> 765 G4double G4VXTRenergyLoss::GetGasLinearPhotoAbs(G4double omega) 
1098 {                                                766 {
1099   G4double omega2, omega3, omega4;            << 767   G4int i ;
                                                   >> 768   G4double omega2, omega3, omega4 ; 
                                                   >> 769 
                                                   >> 770   omega2 = omega*omega ;
                                                   >> 771   omega3 = omega2*omega ;
                                                   >> 772   omega4 = omega2*omega2 ;
                                                   >> 773 
                                                   >> 774   for(i=0;i<fGasIntervalNumber;i++)
                                                   >> 775   {
                                                   >> 776     if( omega < fGasPhotoAbsCof[i][0] ) break ;
                                                   >> 777   }
                                                   >> 778   if( i == 0 )
                                                   >> 779   { 
                                                   >> 780    G4Exception("Invalid (<I1) energy in G4VXTRenergyLoss::GetGasLinearPhotoAbs");
                                                   >> 781   }
                                                   >> 782   else i-- ;
                                                   >> 783   
                                                   >> 784   return fGasPhotoAbsCof[i][1]/omega  + fGasPhotoAbsCof[i][2]/omega2 + 
                                                   >> 785          fGasPhotoAbsCof[i][3]/omega3 + fGasPhotoAbsCof[i][4]/omega4  ;
1100                                                  786 
1101   omega2 = omega * omega;                     << 
1102   omega3 = omega2 * omega;                    << 
1103   omega4 = omega2 * omega2;                   << 
1104                                               << 
1105   const G4double* SandiaCof = fGasPhotoAbsCof << 
1106   G4double cross            = SandiaCof[0] /  << 
1107                    SandiaCof[2] / omega3 + Sa << 
1108   return cross;                               << 
1109 }                                                787 }
1110                                                  788 
1111 /////////////////////////////////////////////    789 //////////////////////////////////////////////////////////////////////
1112 // Calculates the product of linear cof by fo << 790 //
                                                   >> 791 // Calculates the product of linear cof by formation zone for plate. 
1113 // Omega is energy !!!                           792 // Omega is energy !!!
1114 G4double G4VXTRenergyLoss::GetPlateZmuProduct << 793 
1115                                               << 794 G4double G4VXTRenergyLoss::GetPlateZmuProduct( G4double omega ,
                                                   >> 795                                              G4double gamma ,
                                                   >> 796                                              G4double varAngle   ) 
1116 {                                                797 {
1117   return GetPlateFormationZone(omega, gamma,  << 798   return GetPlateFormationZone(omega,gamma,varAngle)*GetPlateLinearPhotoAbs(omega) ;
1118          GetPlateLinearPhotoAbs(omega);       << 
1119 }                                                799 }
1120 /////////////////////////////////////////////    800 //////////////////////////////////////////////////////////////////////
1121 // Calculates the product of linear cof by fo << 801 //
                                                   >> 802 // Calculates the product of linear cof by formation zone for plate. 
1122 // G4cout and output in file in some energy r    803 // G4cout and output in file in some energy range.
1123 void G4VXTRenergyLoss::GetPlateZmuProduct()   << 804 
                                                   >> 805 void G4VXTRenergyLoss::GetPlateZmuProduct() 
1124 {                                                806 {
1125   std::ofstream outPlate("plateZmu.dat", std: << 807   G4std::ofstream outPlate("plateZmu.dat", G4std::ios::out ) ;
1126   outPlate.setf(std::ios::scientific, std::io << 808   outPlate.setf( G4std::ios::scientific, G4std::ios::floatfield );
1127                                                  809 
1128   G4int i;                                    << 810   G4int i ;
1129   G4double omega, varAngle, gamma;            << 811   G4double omega, varAngle, gamma ;
1130   gamma    = 10000.;                          << 812   gamma = 10000. ;
1131   varAngle = 1 / gamma / gamma;               << 813   varAngle = 1/gamma/gamma ;
1132   if(verboseLevel > 0)                        << 814   G4cout<<"energy, keV"<<"\t"<<"Zmu for plate"<<G4endl ;
1133     G4cout << "energy, keV" << "\t" << "Zmu f << 815   for(i=0;i<100;i++)
1134   for(i = 0; i < 100; ++i)                    << 816   {
1135   {                                           << 817     omega = (1.0 + i)*keV ;
1136     omega = (1.0 + i) * keV;                  << 818     G4cout<<omega/keV<<"\t"<<GetPlateZmuProduct(omega,gamma,varAngle)<<"\t" ;
1137     if(verboseLevel > 1)                      << 819     outPlate<<omega/keV<<"\t\t"<<GetPlateZmuProduct(omega,gamma,varAngle)<<G4endl ;
1138       G4cout << omega / keV << "\t"           << 
1139              << GetPlateZmuProduct(omega, gam << 
1140     if(verboseLevel > 0)                      << 
1141       outPlate << omega / keV << "\t\t"       << 
1142                << GetPlateZmuProduct(omega, g << 
1143   }                                              820   }
1144   return;                                     << 821   return  ;
1145 }                                                822 }
1146                                                  823 
1147 /////////////////////////////////////////////    824 //////////////////////////////////////////////////////////////////////
1148 // Calculates the product of linear cof by fo << 825 //
                                                   >> 826 // Calculates the product of linear cof by formation zone for gas. 
1149 // Omega is energy !!!                           827 // Omega is energy !!!
1150 G4double G4VXTRenergyLoss::GetGasZmuProduct(G << 828 
1151                                             G << 829 G4double G4VXTRenergyLoss::GetGasZmuProduct( G4double omega ,
                                                   >> 830                                              G4double gamma ,
                                                   >> 831                                              G4double varAngle   ) 
1152 {                                                832 {
1153   return GetGasFormationZone(omega, gamma, va << 833   return GetGasFormationZone(omega,gamma,varAngle)*GetGasLinearPhotoAbs(omega) ;
1154          GetGasLinearPhotoAbs(omega);         << 
1155 }                                                834 }
1156                                               << 
1157 /////////////////////////////////////////////    835 //////////////////////////////////////////////////////////////////////
1158 // Calculates the product of linear cof by fo << 836 //
                                                   >> 837 // Calculates the product of linear cof byformation zone for gas. 
1159 // G4cout and output in file in some energy r    838 // G4cout and output in file in some energy range.
1160 void G4VXTRenergyLoss::GetGasZmuProduct()     << 
1161 {                                             << 
1162   std::ofstream outGas("gasZmu.dat", std::ios << 
1163   outGas.setf(std::ios::scientific, std::ios: << 
1164   G4int i;                                    << 
1165   G4double omega, varAngle, gamma;            << 
1166   gamma    = 10000.;                          << 
1167   varAngle = 1 / gamma / gamma;               << 
1168   if(verboseLevel > 0)                        << 
1169     G4cout << "energy, keV" << "\t" << "Zmu f << 
1170   for(i = 0; i < 100; ++i)                    << 
1171   {                                           << 
1172     omega = (1.0 + i) * keV;                  << 
1173     if(verboseLevel > 1)                      << 
1174       G4cout << omega / keV << "\t" << GetGas << 
1175              << "\t";                         << 
1176     if(verboseLevel > 0)                      << 
1177       outGas << omega / keV << "\t\t"         << 
1178              << GetGasZmuProduct(omega, gamma << 
1179   }                                           << 
1180   return;                                     << 
1181 }                                             << 
1182                                                  839 
1183 ///////////////////////////////////////////// << 840 void G4VXTRenergyLoss::GetGasZmuProduct() 
1184 // Computes Compton cross section for plate m << 
1185 G4double G4VXTRenergyLoss::GetPlateCompton(G4 << 
1186 {                                                841 {
1187   G4int i, numberOfElements;                  << 842   G4std::ofstream outGas("gasZmu.dat", G4std::ios::out ) ;
1188   G4double xSection = 0., nowZ, sumZ = 0.;    << 843   outGas.setf( G4std::ios::scientific, G4std::ios::floatfield );
1189                                               << 844   G4int i ;
1190   const G4MaterialTable* theMaterialTable = G << 845   G4double omega, varAngle, gamma ;
1191   numberOfElements = (G4int)(*theMaterialTabl << 846   gamma = 10000. ;
1192                                               << 847   varAngle = 1/gamma/gamma ;
1193   for(i = 0; i < numberOfElements; ++i)       << 848   G4cout<<"energy, keV"<<"\t"<<"Zmu for gas"<<G4endl ;
1194   {                                           << 849   for(i=0;i<100;i++)
1195     nowZ = (*theMaterialTable)[fMatIndex1]->G << 850   {
1196     sumZ += nowZ;                             << 851     omega = (1.0 + i)*keV ;
1197     xSection += GetComptonPerAtom(omega, nowZ << 852     G4cout<<omega/keV<<"\t"<<GetGasZmuProduct(omega,gamma,varAngle)<<"\t" ;
                                                   >> 853     outGas<<omega/keV<<"\t\t"<<GetGasZmuProduct(omega,gamma,varAngle)<<G4endl ;
1198   }                                              854   }
1199   xSection /= sumZ;                           << 855   return  ;
1200   xSection *= (*theMaterialTable)[fMatIndex1] << 
1201   return xSection;                            << 
1202 }                                             << 
1203                                               << 
1204 ///////////////////////////////////////////// << 
1205 // Computes Compton cross section for gas mat << 
1206 G4double G4VXTRenergyLoss::GetGasCompton(G4do << 
1207 {                                             << 
1208   G4double xSection = 0., sumZ = 0.;          << 
1209                                               << 
1210   const G4MaterialTable* theMaterialTable = G << 
1211   G4int numberOfElements = (G4int)(*theMateri << 
1212                                               << 
1213   for (G4int i = 0; i < numberOfElements; ++i << 
1214   {                                           << 
1215     G4double nowZ = (*theMaterialTable)[fMatI << 
1216     sumZ += nowZ;                             << 
1217     xSection += GetComptonPerAtom(omega, nowZ << 
1218   }                                           << 
1219   if (sumZ > 0.0) { xSection /= sumZ; }       << 
1220   xSection *= (*theMaterialTable)[fMatIndex2] << 
1221   return xSection;                            << 
1222 }                                             << 
1223                                               << 
1224 ///////////////////////////////////////////// << 
1225 // Computes Compton cross section per atom wi << 
1226 // the energy GammaEnergy                     << 
1227 G4double G4VXTRenergyLoss::GetComptonPerAtom( << 
1228 {                                             << 
1229   G4double CrossSection = 0.0;                << 
1230   if(Z < 0.9999)                              << 
1231     return CrossSection;                      << 
1232   if(GammaEnergy < 0.1 * keV)                 << 
1233     return CrossSection;                      << 
1234   if(GammaEnergy > (100. * GeV / Z))          << 
1235     return CrossSection;                      << 
1236                                               << 
1237   static constexpr G4double a = 20.0;         << 
1238   static constexpr G4double b = 230.0;        << 
1239   static constexpr G4double c = 440.0;        << 
1240                                               << 
1241   static constexpr G4double d1 = 2.7965e-1 *  << 
1242                             d3 = 6.7527 * bar << 
1243                             e1 = 1.9756e-5 *  << 
1244                             e3 = -7.3913e-2 * << 
1245                             f1 = -3.9178e-7 * << 
1246                             f3 = 6.0480e-5 *  << 
1247                                               << 
1248   G4double p1Z = Z * (d1 + e1 * Z + f1 * Z *  << 
1249   G4double p2Z = Z * (d2 + e2 * Z + f2 * Z *  << 
1250   G4double p3Z = Z * (d3 + e3 * Z + f3 * Z *  << 
1251   G4double p4Z = Z * (d4 + e4 * Z + f4 * Z *  << 
1252                                               << 
1253   G4double T0 = 15.0 * keV;                   << 
1254   if(Z < 1.5)                                 << 
1255     T0 = 40.0 * keV;                          << 
1256                                               << 
1257   G4double X = std::max(GammaEnergy, T0) / el << 
1258   CrossSection =                              << 
1259     p1Z * std::log(1. + 2. * X) / X +         << 
1260     (p2Z + p3Z * X + p4Z * X * X) / (1. + a * << 
1261                                               << 
1262   //  modification for low energy. (special c << 
1263   if(GammaEnergy < T0)                        << 
1264   {                                           << 
1265     G4double dT0 = 1. * keV;                  << 
1266     X            = (T0 + dT0) / electron_mass << 
1267     G4double sigma =                          << 
1268       p1Z * std::log(1. + 2. * X) / X +       << 
1269       (p2Z + p3Z * X + p4Z * X * X) / (1. + a << 
1270     G4double c1 = -T0 * (sigma - CrossSection << 
1271     G4double c2 = 0.150;                      << 
1272     if(Z > 1.5)                               << 
1273       c2 = 0.375 - 0.0556 * std::log(Z);      << 
1274     G4double y = std::log(GammaEnergy / T0);  << 
1275     CrossSection *= std::exp(-y * (c1 + c2 *  << 
1276   }                                           << 
1277   return CrossSection;                        << 
1278 }                                                856 }
1279                                                  857 
1280 /////////////////////////////////////////////    858 ///////////////////////////////////////////////////////////////////////
                                                   >> 859 //
1281 // This function returns the spectral and ang    860 // This function returns the spectral and angle density of TR quanta
1282 // in X-ray energy region generated forward w    861 // in X-ray energy region generated forward when a relativistic
1283 // charged particle crosses interface between    862 // charged particle crosses interface between two materials.
1284 // The high energy small theta approximation     863 // The high energy small theta approximation is applied.
1285 // (matter1 -> matter2, or 2->1)                 864 // (matter1 -> matter2, or 2->1)
1286 // varAngle =2* (1 - std::cos(theta)) or appr << 865 // varAngle =2* (1 - cos(theta)) or approximately = theta*theta
1287 G4double G4VXTRenergyLoss::OneBoundaryXTRNden << 866 //
1288                                               << 867 
1289                                               << 868 G4double
1290 {                                             << 869 G4VXTRenergyLoss::OneBoundaryXTRNdensity( G4double energy,G4double gamma,
1291   G4double formationLength1, formationLength2 << 870                                          G4double varAngle ) const
1292   formationLength1 =                          << 871 {
1293     1.0 / (1.0 / (gamma * gamma) + fSigma1 /  << 872   G4double  formationLength1, formationLength2 ;
1294   formationLength2 =                          << 873   formationLength1 = 1.0/
1295     1.0 / (1.0 / (gamma * gamma) + fSigma2 /  << 874   (1.0/(gamma*gamma)
1296   return (varAngle / energy) * (formationLeng << 875   + fSigma1/(energy*energy)
1297          (formationLength1 - formationLength2 << 876   + varAngle) ;
1298 }                                             << 877   formationLength2 = 1.0/
                                                   >> 878   (1.0/(gamma*gamma)
                                                   >> 879   + fSigma2/(energy*energy)
                                                   >> 880   + varAngle) ;
                                                   >> 881   return (varAngle/energy)*(formationLength1 - formationLength2)
                                                   >> 882               *(formationLength1 - formationLength2)  ;
1299                                                  883 
1300 G4double G4VXTRenergyLoss::GetStackFactor(G4d << 
1301                                           G4d << 
1302 {                                             << 
1303   // return stack factor corresponding to one << 
1304   return std::real(OneInterfaceXTRdEdx(energy << 
1305 }                                                884 }
1306                                                  885 
                                                   >> 886 
1307 /////////////////////////////////////////////    887 //////////////////////////////////////////////////////////////////////////////
                                                   >> 888 //
1308 // For photon energy distribution tables. Int    889 // For photon energy distribution tables. Integrate first over angle
                                                   >> 890 //
                                                   >> 891 
1309 G4double G4VXTRenergyLoss::XTRNSpectralAngleD    892 G4double G4VXTRenergyLoss::XTRNSpectralAngleDensity(G4double varAngle)
1310 {                                                893 {
1311   return OneBoundaryXTRNdensity(fEnergy, fGam << 894   return OneBoundaryXTRNdensity(fEnergy,fGamma,varAngle)*
1312          GetStackFactor(fEnergy, fGamma, varA << 895          GetStackFactor(fEnergy,fGamma,varAngle)             ;
1313 }                                                896 }
1314                                                  897 
1315 /////////////////////////////////////////////    898 /////////////////////////////////////////////////////////////////////////
                                                   >> 899 //
1316 // For second integration over energy            900 // For second integration over energy
                                                   >> 901  
1317 G4double G4VXTRenergyLoss::XTRNSpectralDensit    902 G4double G4VXTRenergyLoss::XTRNSpectralDensity(G4double energy)
1318 {                                                903 {
1319   fEnergy = energy;                           << 904   fEnergy = energy ;
1320   G4Integrator<G4VXTRenergyLoss, G4double (G4 << 905   G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral ;
1321     integral;                                 << 906   return integral.Legendre96(this,&G4VXTRenergyLoss::XTRNSpectralAngleDensity,
1322   return integral.Legendre96(this, &G4VXTRene << 907                              0.0,0.2*fMaxThetaTR) +
1323                              0.0, 0.2 * fMaxT << 908          integral.Legendre10(this,&G4VXTRenergyLoss::XTRNSpectralAngleDensity,
1324          integral.Legendre10(this, &G4VXTRene << 909                        0.2*fMaxThetaTR,fMaxThetaTR) ;
1325                              0.2 * fMaxThetaT << 910 } 
1326 }                                             << 911  
1327                                               << 
1328 /////////////////////////////////////////////    912 //////////////////////////////////////////////////////////////////////////
                                                   >> 913 // 
1329 // for photon angle distribution tables          914 // for photon angle distribution tables
                                                   >> 915 //
                                                   >> 916 
1330 G4double G4VXTRenergyLoss::XTRNAngleSpectralD    917 G4double G4VXTRenergyLoss::XTRNAngleSpectralDensity(G4double energy)
1331 {                                                918 {
1332   return OneBoundaryXTRNdensity(energy, fGamm << 919   return OneBoundaryXTRNdensity(energy,fGamma,fVarAngle)*
1333          GetStackFactor(energy, fGamma, fVarA << 920          GetStackFactor(energy,fGamma,fVarAngle)             ;
1334 }                                             << 921 } 
1335                                                  922 
1336 /////////////////////////////////////////////    923 ///////////////////////////////////////////////////////////////////////////
1337 G4double G4VXTRenergyLoss::XTRNAngleDensity(G << 924 //
                                                   >> 925 //
                                                   >> 926 
                                                   >> 927 G4double G4VXTRenergyLoss::XTRNAngleDensity(G4double varAngle) 
1338 {                                                928 {
1339   fVarAngle = varAngle;                       << 929   fVarAngle = varAngle ;
1340   G4Integrator<G4VXTRenergyLoss, G4double (G4 << 930   G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral ;
1341     integral;                                 << 931   return integral.Legendre96(this,&G4VXTRenergyLoss::XTRNAngleSpectralDensity,
1342   return integral.Legendre96(this, &G4VXTRene << 932            fMinEnergyTR,fMaxEnergyTR) ;
1343                              fMinEnergyTR, fM << 
1344 }                                                933 }
1345                                                  934 
1346 /////////////////////////////////////////////    935 //////////////////////////////////////////////////////////////////////////////
1347 // Check number of photons for a range of Lor << 936 //
                                                   >> 937 // Check number of photons for a range of Lorentz factors from both energy 
1348 // and angular tables                            938 // and angular tables
                                                   >> 939 
1349 void G4VXTRenergyLoss::GetNumberOfPhotons()      940 void G4VXTRenergyLoss::GetNumberOfPhotons()
1350 {                                                941 {
1351   G4int iTkin;                                << 942   G4int iTkin ;
1352   G4double gamma, numberE;                    << 943   G4double gamma, numberE ;
1353                                                  944 
1354   std::ofstream outEn("numberE.dat", std::ios << 945   G4std::ofstream outEn("numberE.dat", G4std::ios::out ) ;
1355   outEn.setf(std::ios::scientific, std::ios:: << 946   outEn.setf( G4std::ios::scientific, G4std::ios::floatfield );
1356                                                  947 
1357   std::ofstream outAng("numberAng.dat", std:: << 948   G4std::ofstream outAng("numberAng.dat", G4std::ios::out ) ;
1358   outAng.setf(std::ios::scientific, std::ios: << 949   outAng.setf( G4std::ios::scientific, G4std::ios::floatfield );
1359                                                  950 
1360   for(iTkin = 0; iTkin < fTotBin; ++iTkin)  / << 951   for(iTkin=0;iTkin<fTotBin;iTkin++)      // Lorentz factor loop
1361   {                                           << 952   {
1362     gamma =                                   << 953      gamma = 1.0 + (fProtonEnergyVector->
1363       1.0 + (fProtonEnergyVector->GetLowEdgeE << 954                             GetLowEdgeEnergy(iTkin)/proton_mass_c2) ;
1364     numberE = (*(*fEnergyDistrTable)(iTkin))( << 955      numberE = (*(*fEnergyDistrTable)(iTkin))(0) ;
1365     if(verboseLevel > 1)                      << 956      //  numberA = (*(*fAngleDistrTable)(iTkin))(0) ;
1366       G4cout << gamma << "\t\t" << numberE << << 957      G4cout<<gamma<<"\t\t"<<numberE<<"\t"    //  <<numberA
1367     if(verboseLevel > 0)                      << 958            <<G4endl ; 
1368       outEn << gamma << "\t\t" << numberE <<  << 959      outEn<<gamma<<"\t\t"<<numberE<<G4endl ; 
                                                   >> 960      //  outAng<<gamma<<"\t\t"<<numberA<<G4endl ; 
1369   }                                              961   }
1370   return;                                     << 962   return ;
1371 }                                             << 963 }  
1372                                                  964 
1373 /////////////////////////////////////////////    965 /////////////////////////////////////////////////////////////////////////
1374 // Returns random energy of a X-ray TR photon << 966 //
                                                   >> 967 // Returns randon energy of a X-ray TR photon for given scaled kinetic energy
1375 // of a charged particle                         968 // of a charged particle
1376 G4double G4VXTRenergyLoss::GetXTRrandomEnergy << 969 
                                                   >> 970 G4double G4VXTRenergyLoss::GetXTRrandomEnergy( G4double scaledTkin, G4int iTkin )
1377 {                                                971 {
1378   G4int iTransfer, iPlace;                    << 972   G4int iTransfer, iPlace  ;
1379   G4double transfer = 0.0, position, E1, E2,  << 973   G4double transfer = 0.0, position, E1, E2, W1, W2, W ;
                                                   >> 974 
                                                   >> 975   iPlace = iTkin - 1 ;
1380                                                  976 
1381   iPlace = iTkin - 1;                         << 977   //  G4cout<<"iPlace = "<<iPlace<<endl ;
1382                                                  978 
1383   if(iTkin == fTotBin)  // relativistic plato << 979   if(iTkin == fTotBin) // relativistic plato, try from left
1384   {                                              980   {
1385     position = (*(*fEnergyDistrTable)(iPlace) << 981       position = (*(*fEnergyDistrTable)(iPlace))(0)*G4UniformRand() ;
1386                                                  982 
1387     for(iTransfer = 0;; ++iTransfer)          << 983       for(iTransfer=0;;iTransfer++)
1388     {                                         << 984       {
1389       if(position >= (*(*fEnergyDistrTable)(i << 985         if(position >= (*(*fEnergyDistrTable)(iPlace))(iTransfer)) break ;
1390         break;                                << 986       }
1391     }                                         << 987       transfer = GetXTRenergy(iPlace,position,iTransfer);
1392     transfer = GetXTRenergy(iPlace, position, << 
1393   }                                              988   }
1394   else                                           989   else
1395   {                                              990   {
1396     E1 = fProtonEnergyVector->GetLowEdgeEnerg << 991     E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1) ; 
1397     E2 = fProtonEnergyVector->GetLowEdgeEnerg << 992     E2 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin)     ;
1398     W  = 1.0 / (E2 - E1);                     << 993     W  = 1.0/(E2 - E1) ;
1399     W1 = (E2 - scaledTkin) * W;               << 994     W1 = (E2 - scaledTkin)*W ;
1400     W2 = (scaledTkin - E1) * W;               << 995     W2 = (scaledTkin - E1)*W ;
1401                                               << 996 
1402     position = ((*(*fEnergyDistrTable)(iPlace << 997     position =( (*(*fEnergyDistrTable)(iPlace))(0)*W1 + 
1403                 (*(*fEnergyDistrTable)(iPlace << 998                     (*(*fEnergyDistrTable)(iPlace+1))(0)*W2 )*G4UniformRand() ;
1404                G4UniformRand();               << 999 
1405                                               << 1000         // G4cout<<position<<"\t" ;
1406     for(iTransfer = 0;; ++iTransfer)          << 1001 
1407     {                                         << 1002     for(iTransfer=0;;iTransfer++)
1408       if(position >= ((*(*fEnergyDistrTable)( << 1003     {
1409                       (*(*fEnergyDistrTable)( << 1004           if( position >=
1410         break;                                << 1005           ( (*(*fEnergyDistrTable)(iPlace))(iTransfer)*W1 + 
1411     }                                         << 1006             (*(*fEnergyDistrTable)(iPlace+1))(iTransfer)*W2) ) break ;
1412     transfer = GetXTRenergy(iPlace, position, << 1007     }
1413   }                                           << 1008     transfer = GetXTRenergy(iPlace,position,iTransfer);
1414   if(transfer < 0.0)                          << 1009     
1415     transfer = 0.0;                           << 1010   } 
1416   return transfer;                            << 1011   //  G4cout<<"XTR transfer = "<<transfer/keV<<" keV"<<endl ; 
                                                   >> 1012   if(transfer < 0.0 ) transfer = 0.0 ;
                                                   >> 1013   return transfer ;
1417 }                                                1014 }
1418                                                  1015 
1419 /////////////////////////////////////////////    1016 ////////////////////////////////////////////////////////////////////////
                                                   >> 1017 //
1420 // Returns approximate position of X-ray phot    1018 // Returns approximate position of X-ray photon energy during random sampling
1421 // over integral energy distribution             1019 // over integral energy distribution
1422 G4double G4VXTRenergyLoss::GetXTRenergy(G4int << 1020 
                                                   >> 1021 G4double G4VXTRenergyLoss::GetXTRenergy( G4int    iPlace, 
                                                   >> 1022                                        G4double position, 
                                                   >> 1023                                        G4int    iTransfer )
1423 {                                                1024 {
1424   G4double x1, x2, y1, y2, result;            << 1025   G4double x1, x2, y1, y2, result ;
1425                                                  1026 
1426   if(iTransfer == 0)                             1027   if(iTransfer == 0)
1427   {                                              1028   {
1428     result = (*fEnergyDistrTable)(iPlace)->Ge << 1029     result = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
1429   }                                           << 1030   }  
1430   else                                           1031   else
1431   {                                              1032   {
1432     y1 = (*(*fEnergyDistrTable)(iPlace))(iTra << 1033     y1 = (*(*fEnergyDistrTable)(iPlace))(iTransfer-1) ;
1433     y2 = (*(*fEnergyDistrTable)(iPlace))(iTra << 1034     y2 = (*(*fEnergyDistrTable)(iPlace))(iTransfer) ;
1434                                                  1035 
1435     x1 = (*fEnergyDistrTable)(iPlace)->GetLow << 1036     x1 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
1436     x2 = (*fEnergyDistrTable)(iPlace)->GetLow << 1037     x2 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
1437                                                  1038 
1438     if(x1 == x2)                              << 1039     if ( x1 == x2 )    result = x2 ;
1439       result = x2;                            << 
1440     else                                         1040     else
1441     {                                            1041     {
1442       if(y1 == y2)                            << 1042       if ( y1 == y2  ) result = x1 + (x2 - x1)*G4UniformRand() ;
1443         result = x1 + (x2 - x1) * G4UniformRa << 
1444       else                                       1043       else
1445       {                                          1044       {
1446         result = x1 + (x2 - x1) * G4UniformRa << 1045         result = x1 + (position - y1)*(x2 - x1)/(y2 - y1) ;
1447       }                                          1046       }
1448     }                                            1047     }
1449   }                                              1048   }
1450   return result;                              << 1049   return result ;
1451 }                                             << 
1452                                               << 
1453 ///////////////////////////////////////////// << 
1454 //  Get XTR photon angle at given energy and  << 
1455                                               << 
1456 G4double G4VXTRenergyLoss::GetRandomAngle(G4d << 
1457 {                                             << 
1458   G4int iTR, iAngle;                          << 
1459   G4double position, angle;                   << 
1460                                               << 
1461   if(iTkin == fTotBin)                        << 
1462     --iTkin;                                  << 
1463                                               << 
1464   fAngleForEnergyTable = fAngleBank[iTkin];   << 
1465                                               << 
1466   for(iTR = 0; iTR < fBinTR; ++iTR)           << 
1467   {                                           << 
1468     if(energyXTR < fXTREnergyVector->GetLowEd << 
1469       break;                                  << 
1470   }                                           << 
1471   if(iTR == fBinTR)                           << 
1472     --iTR;                                    << 
1473                                               << 
1474   position = (*(*fAngleForEnergyTable)(iTR))( << 
1475   // position = (*(*fAngleForEnergyTable)(iTR << 
1476                                               << 
1477   for(iAngle = 0;; ++iAngle)                  << 
1478   // for(iAngle = 1;; ++iAngle) // ATLAS TB   << 
1479   {                                           << 
1480     if(position >= (*(*fAngleForEnergyTable)( << 
1481       break;                                  << 
1482   }                                           << 
1483   angle = GetAngleXTR(iTR, position, iAngle); << 
1484   return angle;                               << 
1485 }                                                1050 }
1486                                                  1051 
1487 ///////////////////////////////////////////// << 
1488 // Returns approximate position of X-ray phot << 
1489 // random sampling over integral energy distr << 
1490                                                  1052 
1491 G4double G4VXTRenergyLoss::GetAngleXTR(G4int  << 
1492                                        G4int  << 
1493 {                                             << 
1494   G4double x1, x2, y1, y2, result;            << 
1495                                                  1053 
1496   if( iTransfer == 0 )                        << 1054 //
1497   // if( iTransfer == 1 ) // ATLAS TB         << 1055 //
1498   {                                           << 1056 ///////////////////////////////////////////////////////////////////////
1499     result = (*fAngleForEnergyTable)(iPlace)- << 
1500   }                                           << 
1501   else                                        << 
1502   {                                           << 
1503     y1 = (*(*fAngleForEnergyTable)(iPlace))(i << 
1504     y2 = (*(*fAngleForEnergyTable)(iPlace))(i << 
1505                                               << 
1506     x1 = (*fAngleForEnergyTable)(iPlace)->Get << 
1507     x2 = (*fAngleForEnergyTable)(iPlace)->Get << 
1508                                                  1057 
1509     if(x1 == x2) result = x2;                 << 
1510     else                                      << 
1511     {                                         << 
1512       if( y1 == y2 )  result = x1 + (x2 - x1) << 
1513       else                                    << 
1514       {                                       << 
1515         result = x1 + (position - y1) * (x2 - << 
1516         // result = x1 + 0.1*(position - y1)  << 
1517         // result = x1 + 0.05*(position - y1) << 
1518       }                                       << 
1519     }                                         << 
1520   }                                           << 
1521   return result;                              << 
1522 }                                             << 
1523                                                  1058