Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/parameterisations/channeling/src/G4VChannelingFastSimCrystalData.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 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 // Author:      Alexei Sytov
 27 // Co-author:   Gianfranco PaternĂ² (modifications & testing)
 28 // On the base of the CRYSTALRAD realization of scattering model:
 29 // A. I. Sytov, V. V. Tikhomirov, and L. Bandiera PRAB 22, 064601 (2019)
 30 
 31 #include "G4VChannelingFastSimCrystalData.hh"
 32 #include "G4SystemOfUnits.hh"
 33 #include "G4PhysicalConstants.hh"
 34 #include "G4Log.hh"
 35 
 36 G4VChannelingFastSimCrystalData::G4VChannelingFastSimCrystalData()
 37 {
 38 
 39 }
 40 
 41 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 42 
 43 G4VChannelingFastSimCrystalData::~G4VChannelingFastSimCrystalData(){;}
 44 
 45 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 46 
 47 void G4VChannelingFastSimCrystalData::SetGeometryParameters
 48                                      (const G4LogicalVolume *crystallogic)
 49 {
 50     G4int crystalID = crystallogic->GetInstanceID();
 51 
 52     //set bending angle if the it exists in the list, otherwise default = 0
 53     (fMapBendingAngle.count(crystalID) > 0)
 54     ? SetBendingAngle(fMapBendingAngle[crystalID],crystallogic)
 55     : SetBendingAngle(0.,crystallogic);
 56 
 57     //set miscut angle if the it exists in the list, otherwise default = 0
 58     (fMapMiscutAngle.count(crystalID) > 0)
 59     ? SetMiscutAngle(fMapMiscutAngle[crystalID],crystallogic)
 60     : SetMiscutAngle(0.,crystallogic);
 61 
 62     //set crystalline undulator parameters if they exist in the list,
 63     //otherwise default = G4ThreeVector(0,0,0).
 64     (fMapCUAmplitudePeriodPhase.count(crystalID) > 0)
 65     ? SetCUParameters(fMapCUAmplitudePeriodPhase[crystalID],crystallogic)
 66     : SetCUParameters(G4ThreeVector(0.,0.,0.),crystallogic);
 67 }
 68 
 69 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 70 
 71 void G4VChannelingFastSimCrystalData::SetBendingAngle(G4double tetab,
 72                   const G4LogicalVolume* crystallogic)
 73 {
 74     G4int crystalID = crystallogic->GetInstanceID();
 75 
 76     //set the bending angle for this logical volume
 77     fMapBendingAngle[crystalID]=tetab;
 78 
 79     G4ThreeVector limboxmin;//minimal limits of the box bounding the logical volume
 80     G4ThreeVector limboxmax;//maximal limits of the box bounding the logical volume
 81     //save the limits of the box bounding the logical volume
 82     crystallogic->GetSolid()->BoundingLimits(limboxmin,limboxmax);
 83 
 84     //bounding box half dimensions
 85     fHalfDimBoundingBox = (limboxmax-limboxmin)/2.;
 86 
 87     G4double lcr = limboxmax.getZ()-limboxmin.getZ();//crystal thickness
 88 
 89     fBendingAngle=std::abs(tetab);
 90     if (fBendingAngle<0.000001)//no bending less then 1 urad
 91     {
 92         if(fBendingAngle>DBL_EPSILON)
 93         {
 94             G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
 95             G4cout << "Warning: bending angle is lower than 1 urad => set to 0" << G4endl;
 96         }
 97 
 98        fBent=0;
 99        fBendingAngle=0.;
100        fBendingR=0.;//just for convenience (infinity in reality)
101        fBending2R=0.;
102        fBendingRsquare=0.;
103        fCurv=0.;
104 
105        fCorrectionZ = 1.;
106     }
107     else
108     {
109        fBent=1;
110        fBendingR=lcr/fBendingAngle;
111        fBending2R=2.*fBendingR;
112        fBendingRsquare=fBendingR*fBendingR;
113        fCurv=1./fBendingR;
114 
115        if (tetab<0.)
116        {
117            G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
118            G4cout << "Warning: bending angle is negative => set to be positive" << G4endl;
119        }
120     }
121 
122 }
123 
124 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
125 
126 void G4VChannelingFastSimCrystalData::SetMiscutAngle(G4double tetam,
127                  const G4LogicalVolume *crystallogic)
128 {
129     G4int crystalID = crystallogic->GetInstanceID();
130 
131     //set the bending angle for this logical volume
132     fMapMiscutAngle[crystalID]=tetam;
133 
134     // fMiscutAngle>0: rotation of xz coordinate planes clockwise in the xz plane
135     fMiscutAngle=tetam;
136     if (std::abs(tetam)>1.*mrad)
137     {
138         G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
139         G4cout << "Warning: miscut angle is higher than 1 mrad => " << G4endl;
140         G4cout << "coordinate transformation routines may be unstable" << G4endl;
141     }
142     fCosMiscutAngle=std::cos(fMiscutAngle);
143     fSinMiscutAngle=std::sin(fMiscutAngle);
144 }
145 
146 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
147 
148 void G4VChannelingFastSimCrystalData::SetCrystallineUndulatorParameters(
149                                        G4double amplitude,
150                                        G4double period,
151                                        G4double phase,
152                                        const G4LogicalVolume *crystallogic)
153 {
154     if (amplitude<DBL_EPSILON||period<DBL_EPSILON)
155     {
156         amplitude = 0.;
157         period=0.;
158         phase=0.;
159         G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
160         G4cout << "Warning: The crystalline undulator parameters are out of range "
161                   "=> the crystalline undulator mode switched off" << G4endl;
162     }
163 
164     SetCUParameters(G4ThreeVector(amplitude,period,phase),crystallogic);
165 }
166 
167 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
168 
169 void G4VChannelingFastSimCrystalData::SetCUParameters(
170                                       const G4ThreeVector &amplitudePeriodPhase,
171                                       const G4LogicalVolume *crystallogic)
172 {
173     G4int crystalID = crystallogic->GetInstanceID();
174 
175     //set the crystalline undulator parameters for this logical volume
176     fMapCUAmplitudePeriodPhase[crystalID]=amplitudePeriodPhase;
177     fCUAmplitude=amplitudePeriodPhase.x();
178     G4double period = amplitudePeriodPhase.y();
179     fCUPhase = amplitudePeriodPhase.z();
180 
181     //if the amplidude of the crystalline undulator is 0 => no undulator
182     if(fCUAmplitude>DBL_EPSILON&&period>DBL_EPSILON)
183     {
184         //crystalline undulator flag
185         fCU = true;
186 
187         fCUK = CLHEP::twopi/period;
188 
189         if(fBendingAngle>DBL_EPSILON)
190         {
191             //bent and periodically bent crystal are not compatible
192             SetBendingAngle(0,crystallogic);
193 
194             G4cout << "Channeling model: volume " << crystallogic->GetName() << G4endl;
195             G4cout << "Warning: crystalline undulator is not compatible with "
196                       "a bent crystal mode => setting bending angle to 0." << G4endl;
197         }
198     }
199     else
200     {
201         fCU = false;
202         fCUAmplitude = 0.;
203         fCUK = 0.;
204         fCUPhase = 0.;
205         fMapCUAmplitudePeriodPhase[crystalID] = G4ThreeVector(0.,0.,0.);
206     }
207 
208     fCUK2 = fCUK*fCUK;
209     fCUAmplitudeK = fCUAmplitude*fCUK;
210 }
211 
212 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
213 
214 void G4VChannelingFastSimCrystalData::SetParticleProperties(G4double etotal,
215                                                          G4double mass,
216                                                          G4double charge,
217                                                          const G4String& particleName)
218 {
219     G4double teta1;
220     fZ2=charge;
221     G4double zz22=fZ2*fZ2;
222     fParticleName=particleName;
223 
224 //     particle momentum and energy
225        G4double t=etotal*etotal-mass*mass; //  economy of operations
226        fPz=std::sqrt(t); //  momentum of particle
227        fPV=t/etotal;    //  pv
228        fBeta=fPz/etotal;   //  velocity/c
229        fTetaL = std::sqrt(std::abs(fZ2)*fVmax2/fPV); //Lindhard angle
230        fChannelingStep = fChangeStep/fTetaL; //standard simulation step
231 
232 //     Energy losses
233        fV2 = fBeta*fBeta; // particle (velocity/c)^2
234        fGamma = etotal/mass; //  Lorentz factor
235        fMe2Gamma = 2*CLHEP::electron_mass_c2*fGamma;
236 //     max ionization losses
237        fTmax = fMe2Gamma*fGamma*fV2/
238                (CLHEP::electron_mass_c2/mass*CLHEP::electron_mass_c2/mass +
239                 1. + fMe2Gamma/mass);
240 //     max ionization losses for electrons
241        if(fParticleName=="e-"){fTmax/=2;}
242 
243        for(G4int i=0; i<fNelements; i++)
244        {
245 
246 //       minimal scattering angle by coulomb scattering on nuclei
247 //       defining by shielding by electrons
248 //       teta1=hdc/(fPz*fRF)*DSQRT(1.13D0+3.76D0*(alpha*fZ1*fZ2/fBeta)**2){ev*cm/(eV*cm)}
249          teta1=fTeta10[i]*std::sqrt(1.13+fK40[i]*zz22/fV2); // /fPz later to speed up
250                                                             //  the calculations
251 
252 //       the coefficient for multiple scattering
253          fBB[i]=teta1*teta1*fPu11[i];
254          fE1XBbb[i]=expint(fBB[i]);
255          fBBDEXP[i]=(1.+fBB[i])*std::exp(fBB[i]);
256 //       necessary for suppression of incoherent scattering
257 //       by the atomic correlations in crystals for single scattering on nucleus
258 //       (screened atomic potential): EXP(-(fPz*teta*fU1)**2)=EXP(-fPzu11*teta**2).GE.ksi
259 //         =>no scattering
260          fPzu11[i]=fPu11[i]*fPz*fPz;
261 
262          teta1=teta1/fPz; //
263          fTeta12[i]=teta1*teta1;
264 //       maximal scattering angle by coulomb scattering on nuclei
265 //       defining by nucleus radius
266 //       tetamax=hc/(fPz*1.D-6*fR0*fAN**(1.D0/3.D0))//  {Mev*fermi/(MeV*fermi)}
267          G4double tetamax=fTetamax0[i]/fPz;
268          fTetamax2[i]=tetamax*tetamax;
269          fTetamax12[i]=fTeta12[i]+fTetamax2[i];
270 
271 //       a coefficient in a formula for scattering (for high speed of simulation)
272 //       fK2=(fZ2)**2*alphahbarc2*4.*pi*fN0*(fZ1/fPV)**2
273          fK2[i]=fK20[i]*zz22/fPV/fPV;
274        }
275 
276 //     fK3=(fZ2)**2*alphahbarc2*pi/electron_mass_c2/(fV2)**2
277        fK3=fK30*zz22/fV2;
278 }
279 
280 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
281 
282 G4double G4VChannelingFastSimCrystalData::GetLindhardAngle(G4double etotal,
283                                                            G4double mass,
284                                                            G4double charge)
285 {
286     G4double pv0 = etotal-mass*mass/etotal;
287        return std::sqrt(2*std::abs(charge)*fVmax/pv0); //Calculate the value of the Lindhard angle
288                                    //(!!! the value for a straight crystal)
289 }
290 
291 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
292 
293 G4double G4VChannelingFastSimCrystalData::GetLindhardAngle()
294 {
295     return fTetaL; //return the Lindhard angle value calculated in SetParticleProperties
296 }
297 
298 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
299 
300 G4double G4VChannelingFastSimCrystalData::GetSimulationStep(G4double tx,G4double ty)
301 {
302     G4double simulationstep;
303     //find angle of particle w.r.t. the plane or axis
304     G4double angle=0.;
305     if (iModel==1)//1D model
306     {
307         angle = std::abs(tx);
308     }
309     else if  (iModel==2)//2D model
310     {
311         angle = std::sqrt(tx*tx+ty*ty);
312     }
313 
314     //compare this angle with the Lindhard angle
315     if (angle<fTetaL)
316     {
317         simulationstep = fChannelingStep;
318     }
319     else
320     {
321       simulationstep = fChangeStep;
322       if (angle > 0.0) { simulationstep /= angle; }
323     }
324 
325     return simulationstep;
326 }
327 
328 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
329 
330 G4double G4VChannelingFastSimCrystalData::GetMaxSimulationStep(G4double etotal,
331                                                                G4double mass,
332                                                                G4double charge)
333 {
334     //standard value of step for channeling particles which is the maximal possible step
335     return fChangeStep/GetLindhardAngle(etotal, mass, charge);
336 }
337 
338 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
339 
340 G4ThreeVector G4VChannelingFastSimCrystalData::CoulombAtomicScattering(
341                                                            G4double effectiveStep,
342                                                            G4double step,
343                                                            G4int ielement)
344 {
345         G4double tx = 0.;//horizontal scattering angle
346         G4double ty = 0.;//vertical scattering angle
347 
348         G4double ksi=0.1;
349 
350 //      calculation of the teta2-minimal possible angle of a single scattering
351         G4double e1=fK2[ielement]*effectiveStep; //for high speed of a program
352 //      (real formula is (4*pi*fN0*wpl(x)*dz*fZ1*zz2*alpha*hdc/fPV)**2)
353         G4double teta122=fTetamax12[ielement]/(ksi*fTetamax12[ielement]/e1+1.);
354         // teta122=fTeta12+teta22=teta1^2+teta2^2
355 
356         G4double teta22;
357         G4double t;
358 //      if the angle of a single scattering is less teta1 - minimal possible
359 //      angle of coulomb scattering defining by the electron shielding than
360 //      multiple scattering by both nuclei and electrons and electrons will not
361 //      occur => minimal possible angle of a single scattering is equal to teta1
362         if (teta122<=fTeta12[ielement]*1.000125)
363         {
364           teta22=0.;
365           teta122=fTeta12[ielement];
366         }
367         else
368         {
369           teta22=teta122-fTeta12[ielement];
370           G4double aa=teta22/fTeta12[ielement];
371           G4double aa1=1.+aa;
372 
373 //        crystal, with scattering suppression
374           G4double tetamsi=e1*(G4Log(aa1)+
375                            (1.-std::exp(-aa*fBB[ielement]))/aa1+
376                            fBBDEXP[ielement]*
377                            (expint(fBB[ielement]*aa1)-fE1XBbb[ielement]));
378 
379 //        sumilation of multiple coulomb scattering by nuclei and electrons
380 //        for high speed of a program, real formula is
381 //        4*pi*fN0*wpl(x)*dz*(fZ1*zz2*alpha*hdc/fPV)**2*
382 //         *(ln(1+a)+(1-exp(-a*b))/(1+a)+(1+b)*exp(b)*(E1XB(b*(1+a))-E1XB(b)))
383 
384           ksi=G4UniformRand();
385           t=std::sqrt(-tetamsi*G4Log(ksi));
386 
387           ksi=G4UniformRand();
388 
389           tx+=t*std::cos(CLHEP::twopi*ksi);
390           ty+=t*std::sin(CLHEP::twopi*ksi);
391 
392         }
393 //      simulation of single coulomb scattering by nuclei (with screened potential)
394         G4double zss=0.;
395         G4double dzss=step;
396 
397 //      (calculation of a distance, at which another single scattering can happen)
398         ksi=G4UniformRand();
399 
400         zss=-G4Log(ksi)*step/(e1*(1./teta122-1./fTetamax12[ielement]));
401         G4double tt;
402 
403 //      At some step several single scattering can occur.
404 //      So,if the distance of the next scattering is less than the step,
405 //      another scattering can occur. If the distance of the next scattering
406 //      is less than the difference between the step and the distance of
407 //      the previous scattering, another scattering can occur. And so on, and so on.
408 //      In the cycle we simulate each of them. The cycle is finished, when
409 //      the remaining part of step is less than a distance of the next single scattering.
410 //********************************************
411 //      if at a step a single scattering occurs
412         while (zss<dzss)
413         {
414 
415 //        simulation by Monte-Carlo of angles of single scattering
416           ksi=G4UniformRand();
417 
418           tt=fTetamax12[ielement]/(1.+ksi*(fTetamax2[ielement]-teta22)/teta122)-
419                   fTeta12[ielement];
420 
421           ksi=G4UniformRand();
422 
423 //        suppression of incoherent scattering by the atomic correlations in crystals
424           t=fPzu11[ielement]*tt;
425           t=std::exp(-t);
426 
427           if (t<ksi) //if scattering takes place
428           {
429             //scattering angle
430             t=std::sqrt(tt);
431             ksi=G4UniformRand();
432 
433             tx+=t*std::cos(CLHEP::twopi*ksi);
434             ty+=t*std::sin(CLHEP::twopi*ksi);
435           }
436 
437           dzss-=zss;
438 //        (calculation of a distance, at which another single scattering can happen)
439           ksi=G4UniformRand();
440 
441           zss=-G4Log(ksi)*step/(e1*(1./teta122-1./fTetamax12[ielement]));
442         }
443 //********************************************
444         return G4ThreeVector(tx,ty,0.);
445 }
446 
447 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
448 
449 G4ThreeVector G4VChannelingFastSimCrystalData::CoulombElectronScattering(
450                                                              G4double eMinIonization,
451                                                              G4double electronDensity,
452                                                              G4double step)
453 {
454 
455     G4double zss=0.;
456     G4double dzss=step;
457     G4double ksi = 0.;
458 
459     G4double tx = 0.;//horizontal scattering angle
460     G4double ty = 0.;//vertical scattering angle
461     G4double eloss = 0.;//energy loss
462 
463     // eMinIonization - minimal energy transfered to electron
464     // a cut to reduce the number of calls of electron scattering
465     // is needed only at low density regions, in many cases does not do anything at all
466     if (eMinIonization<0.5*eV){eMinIonization=0.5*eV;}
467 
468     //  single scattering on electrons routine
469     if ((eMinIonization<fTmax)&&(electronDensity>DBL_EPSILON))
470     {
471 
472 //    (calculation of a distance, at which another single scattering can happen)
473 //    simulation of scattering length (by the same way single scattering by nucleus
474       ksi=G4UniformRand();
475 
476       zss=-1.0*G4Log(ksi)/(fK3*electronDensity)/(1./eMinIonization-1./fTmax);
477 
478 //********************************************
479 //    if at a step a single scattering occur
480       while (zss<dzss)
481       {
482 //      simulation by Monte-Carlo of angles of single scattering
483         ksi=G4UniformRand();
484 
485 //      energy transfered to electron
486         G4double e1=eMinIonization/(1.-ksi*(1.-eMinIonization/fTmax));
487 
488 //      scattering angle
489         G4double t=0;
490         if(fTmax-e1>DBL_EPSILON) //to be sure e1<fTmax
491         {
492             t=std::sqrt(2.*CLHEP::electron_mass_c2*e1*(1-e1/fTmax))/fPz;
493         }
494 
495         // energy losses
496         eloss=e1;
497         ksi=G4UniformRand();
498 
499         tx+=t*std::cos(CLHEP::twopi*ksi);
500         ty+=t*std::sin(CLHEP::twopi*ksi);
501 
502         dzss-=zss;
503 //      (calculation of a distance, at which another single scattering can happen)
504 //      simulation of scattering length
505 //      (by the same way single scattering by nucleus
506         ksi=G4UniformRand();
507 
508         zss=-1.0*G4Log(ksi)/(fK3*electronDensity)/(1./eMinIonization-1./fTmax);
509       }
510 //********************************************
511     }
512     return G4ThreeVector(tx,ty,eloss);
513 }
514 
515 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
516 
517 G4double G4VChannelingFastSimCrystalData::IonizationLosses(G4double dz,
518                                                     G4int ielement)
519 {
520     //amorphous part of ionization losses
521 
522     G4double elosses = 0.;
523     // 1/2 already taken into account in fKD
524 
525     G4double loge = G4Log(fMe2Gamma*fGamma*fV2/fI0[ielement]);
526     G4double delta= 2*(G4Log(fBeta*fGamma)+fLogPlasmaEdI0[ielement]-0.5);
527     if(delta<0){delta=0;}
528     loge-=delta;
529     if(fParticleName=="e-")
530     {
531        loge+=(-G4Log(2.) + 1
532               -(2*fGamma - 1)/fGamma/fGamma*G4Log(2.) +
533                1/8*((fGamma - 1)/fGamma)*((fGamma - 1)/fGamma));
534     }
535     else if(fParticleName=="e+")
536     {
537        loge+=(-fV2/12*(11 + 14/(fGamma + 1) + 10/(fGamma + 1)/(fGamma + 1) +
538                       4/(fGamma + 1)/(fGamma + 1)/(fGamma + 1)));
539     }
540     else
541     {
542         loge-=fV2;
543     }
544     elosses=fZ2*fZ2*fKD[ielement]/fV2*loge*dz;
545 
546     return elosses;}
547 
548 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
549 
550 G4double G4VChannelingFastSimCrystalData::expint(G4double X)
551 {
552 //      ============================================
553 //      Purpose: Compute exponential integral E1(x)
554 //      Input :  x  --- Argument of E1(x)
555 //      Output:  E1 --- E1(x)
556 //      ============================================
557 
558 G4double E1, R, T, T0;
559 G4int M;
560 
561 if (X==0)
562 {
563     E1=1.e300;
564 }
565 else if (X<=1.)
566 {
567    E1=1.;
568    R=1.;
569 
570 
571    for(int K=1; K<=25; K++)
572    {
573        R=-R*K*X/std::pow(K+1.,2.);
574        E1=E1+R;
575        if (std::abs(R)<=std::abs(E1)*1.0e-15) {break;}
576    }
577 
578    E1=-0.5772156649015328-G4Log(X)+X*E1;
579 }
580 else
581 {
582    M=20+std::trunc(80.0/X);
583    T0=0.;
584 
585    for(int K=M; K>=1; K--)
586    {
587       T0=K/(1.0+K/(X+T0));
588    }
589 
590    T=1.0/(X+T0);
591    E1=std::exp(-X)*T;
592 }
593 
594 return E1;
595 }
596