Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/coherent_elastic/include/G4NuclNuclDiffuseElastic.hh

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 //
 27 //
 28 //
 29 // G4 Model: optical elastic scattering with 4-momentum balance 
 30 //
 31 // Class Description
 32 // Final state production model for nucleus-nucleus elastic scattering;
 33 // Coulomb amplitude is not considered as correction 
 34 // (as in G4DiffuseElastic)
 35 // Class Description - End
 36 //
 37 //
 38 // 17.03.09 V. Grichine implementation for Coulomb elastic scattering
 39 
 40 
 41 #ifndef G4NuclNuclDiffuseElastic_h
 42 #define G4NuclNuclDiffuseElastic_h 1
 43  
 44 #include <complex>
 45 #include <CLHEP/Units/PhysicalConstants.h>
 46 #include "globals.hh"
 47 #include "G4Integrator.hh"
 48 #include "G4HadronElastic.hh"
 49 #include "G4HadProjectile.hh"
 50 #include "G4Nucleus.hh"
 51 
 52 #include "G4Exp.hh"
 53 #include "G4Log.hh"
 54 #include "G4Pow.hh"
 55 
 56 
 57 class G4ParticleDefinition;
 58 class G4PhysicsTable;
 59 class G4PhysicsLogVector;
 60 
 61 class G4NuclNuclDiffuseElastic : public G4HadronElastic   // G4HadronicInteraction
 62 {
 63 public:
 64 
 65   G4NuclNuclDiffuseElastic();
 66 
 67   // G4NuclNuclDiffuseElastic(const G4ParticleDefinition* aParticle);
 68 
 69   virtual ~G4NuclNuclDiffuseElastic();
 70 
 71   void Initialise();
 72 
 73   void InitialiseOnFly(G4double Z, G4double A);
 74 
 75   void BuildAngleTable();
 76 
 77   virtual G4double SampleInvariantT(const G4ParticleDefinition* p, 
 78             G4double plab,
 79             G4int Z, G4int A);
 80 
 81   void SetPlabLowLimit(G4double value);
 82 
 83   void SetHEModelLowLimit(G4double value);
 84 
 85   void SetQModelLowLimit(G4double value);
 86 
 87   void SetLowestEnergyLimit(G4double value);
 88 
 89   void SetRecoilKinEnergyLimit(G4double value);
 90 
 91   G4double SampleT(const G4ParticleDefinition* aParticle, 
 92                          G4double p, G4double A);
 93 
 94   G4double SampleTableT(const G4ParticleDefinition* aParticle, 
 95                          G4double p, G4double Z, G4double A);
 96 
 97   G4double SampleThetaCMS( const G4ParticleDefinition* aParticle, G4double p, G4double A);
 98 
 99   G4double SampleCoulombMuCMS( const G4ParticleDefinition* aParticle, G4double p);
100 
101   G4double SampleTableThetaCMS(const G4ParticleDefinition* aParticle, G4double p, 
102                                      G4double Z, G4double A);
103 
104   G4double GetScatteringAngle(G4int iMomentum, G4int iAngle, G4double position);
105 
106   G4double SampleThetaLab(const G4HadProjectile* aParticle, 
107                                 G4double tmass, G4double A);
108 
109   G4double GetDiffuseElasticXsc( const G4ParticleDefinition* particle, 
110                                  G4double theta, 
111                G4double momentum, 
112          G4double A         );
113 
114   G4double GetInvElasticXsc( const G4ParticleDefinition* particle, 
115                                  G4double theta, 
116                G4double momentum, 
117          G4double A, G4double Z );
118 
119   G4double GetDiffuseElasticSumXsc( const G4ParticleDefinition* particle, 
120                                  G4double theta, 
121                G4double momentum, 
122          G4double A, G4double Z );
123 
124   G4double GetInvElasticSumXsc( const G4ParticleDefinition* particle, 
125                                  G4double tMand, 
126                G4double momentum, 
127          G4double A, G4double Z );
128 
129   G4double IntegralElasticProb( const G4ParticleDefinition* particle, 
130                                  G4double theta, 
131                G4double momentum, 
132          G4double A            );
133   
134 
135   G4double GetCoulombElasticXsc( const G4ParticleDefinition* particle, 
136                                  G4double theta, 
137                G4double momentum, 
138          G4double Z         );
139 
140   G4double GetRutherfordXsc(     G4double theta       );
141 
142   G4double GetInvCoulombElasticXsc( const G4ParticleDefinition* particle, 
143                                  G4double tMand, 
144                G4double momentum, 
145          G4double A, G4double Z         );
146 
147   G4double GetCoulombTotalXsc( const G4ParticleDefinition* particle,  
148                G4double momentum, G4double Z       );
149 
150   G4double GetCoulombIntegralXsc( const G4ParticleDefinition* particle,  
151                G4double momentum, G4double Z, 
152                                  G4double theta1, G4double theta2         );
153 
154 
155   G4double CalculateParticleBeta( const G4ParticleDefinition* particle, 
156                                   G4double momentum    );
157 
158   G4double CalculateZommerfeld( G4double beta, G4double Z1, G4double Z2 );
159 
160   G4double CalculateAm( G4double momentum, G4double n, G4double Z);
161 
162   G4double CalculateNuclearRad( G4double A);
163 
164   G4double ThetaCMStoThetaLab(const G4DynamicParticle* aParticle, 
165                                 G4double tmass, G4double thetaCMS);
166 
167   G4double ThetaLabToThetaCMS(const G4DynamicParticle* aParticle, 
168                                 G4double tmass, G4double thetaLab);
169 
170   void TestAngleTable(const G4ParticleDefinition* theParticle, G4double partMom,
171           G4double Z, G4double A);
172 
173 
174 
175   G4double BesselJzero(G4double z);
176   G4double BesselJone(G4double z);
177   G4double DampFactor(G4double z);
178   G4double BesselOneByArg(G4double z);
179 
180   G4double GetDiffElasticProb(G4double theta);
181   G4double GetDiffElasticSumProb(G4double theta);
182   G4double GetDiffElasticSumProbA(G4double alpha);
183   G4double GetIntegrandFunction(G4double theta);
184 
185   G4double GetNuclearRadius(){return fNuclearRadius;};
186 
187 
188   // Technical math functions for strong Coulomb contribution
189 
190   G4complex GammaLogarithm(G4complex xx);
191   G4complex GammaLogB2n(G4complex xx);
192 
193   G4double  GetErf(G4double x);
194 
195   G4double GetCosHaPit2(G4double t){return std::cos(CLHEP::halfpi*t*t);};
196   G4double GetSinHaPit2(G4double t){return std::sin(CLHEP::halfpi*t*t);};
197 
198   G4double  GetCint(G4double x);
199   G4double  GetSint(G4double x);
200 
201 
202   G4complex GetErfcComp(G4complex z, G4int nMax);
203   G4complex GetErfcSer(G4complex z, G4int nMax);
204   G4complex GetErfcInt(G4complex z); // , G4int nMax);
205 
206   G4complex GetErfComp(G4complex z, G4int nMax);  // AandS algorithm != Ser, Int
207   G4complex GetErfSer(G4complex z, G4int nMax);
208 
209   G4double GetExpCos(G4double x);
210   G4double GetExpSin(G4double x);
211   G4complex GetErfInt(G4complex z); // , G4int nMax);
212 
213   G4double GetLegendrePol(G4int n, G4double x);
214 
215   G4complex TestErfcComp(G4complex z, G4int nMax);
216   G4complex TestErfcSer(G4complex z, G4int nMax);
217   G4complex TestErfcInt(G4complex z); // , G4int nMax);
218 
219   G4complex CoulombAmplitude(G4double theta);
220   G4double  CoulombAmplitudeMod2(G4double theta);
221 
222   void CalculateCoulombPhaseZero();
223   G4double CalculateCoulombPhase(G4int n);
224   void CalculateRutherfordAnglePar();
225 
226   G4double ProfileNear(G4double theta);
227   G4double ProfileFar(G4double theta);
228   G4double Profile(G4double theta);
229 
230   G4complex PhaseNear(G4double theta);
231   G4complex PhaseFar(G4double theta);
232 
233   G4complex GammaLess(G4double theta);
234   G4complex GammaMore(G4double theta);
235 
236   G4complex AmplitudeNear(G4double theta);
237   G4complex AmplitudeFar(G4double theta);
238 
239   G4complex Amplitude(G4double theta);
240   G4double  AmplitudeMod2(G4double theta);
241 
242   G4complex AmplitudeSim(G4double theta);
243   G4double  AmplitudeSimMod2(G4double theta);
244 
245   G4double  GetRatioSim(G4double theta);
246   G4double  GetRatioGen(G4double theta);
247   
248   G4double  GetFresnelDiffuseXsc(G4double theta);
249   G4double  GetFresnelIntegrandXsc(G4double alpha);
250   
251 
252   G4complex AmplitudeGla(G4double theta);
253   G4double  AmplitudeGlaMod2(G4double theta);
254 
255   G4complex AmplitudeGG(G4double theta);
256   G4double  AmplitudeGGMod2(G4double theta);
257 
258   void      InitParameters(const G4ParticleDefinition* theParticle,  
259             G4double partMom, G4double Z, G4double A);
260  
261   void      InitDynParameters(const G4ParticleDefinition* theParticle,  
262             G4double partMom); 
263 
264   void      InitParametersGla(const G4DynamicParticle* aParticle,  
265             G4double partMom, G4double Z, G4double A);
266 
267   G4double GetHadronNucleonXscNS( G4ParticleDefinition* pParticle, 
268                                                  G4double pTkin, 
269           G4ParticleDefinition* tParticle);
270 
271   G4double CalcMandelstamS( const G4double mp , const G4double mt , 
272           const G4double Plab );
273 
274   G4double GetProfileLambda(){return fProfileLambda;};
275 
276   inline void SetProfileLambda(G4double pl) {fProfileLambda = pl;};
277   inline void SetProfileDelta(G4double pd) {fProfileDelta = pd;};
278   inline void SetProfileAlpha(G4double pa){fProfileAlpha = pa;};
279   inline void SetCofLambda(G4double pa){fCofLambda = pa;};
280 
281   inline void SetCofAlpha(G4double pa){fCofAlpha = pa;};
282   inline void SetCofAlphaMax(G4double pa){fCofAlphaMax = pa;};
283   inline void SetCofAlphaCoulomb(G4double pa){fCofAlphaCoulomb = pa;};
284 
285   inline void SetCofDelta(G4double pa){fCofDelta = pa;};
286   inline void SetCofPhase(G4double pa){fCofPhase = pa;};
287   inline void SetCofFar(G4double pa){fCofFar = pa;};
288   inline void SetEtaRatio(G4double pa){fEtaRatio = pa;};
289   inline void SetMaxL(G4int l){fMaxL = l;};
290   inline void SetNuclearRadiusCof(G4double r){fNuclearRadiusCof = r;};
291 
292   inline G4double GetCofAlphaMax(){return fCofAlphaMax;};
293   inline G4double GetCofAlphaCoulomb(){return fCofAlphaCoulomb;};
294 
295 private:
296 
297   G4ParticleDefinition* theProton;
298   G4ParticleDefinition* theNeutron;
299   G4ParticleDefinition* theDeuteron;
300   G4ParticleDefinition* theAlpha;
301 
302   const G4ParticleDefinition* thePionPlus;
303   const G4ParticleDefinition* thePionMinus;
304 
305   G4double lowEnergyRecoilLimit;  
306   G4double lowEnergyLimitHE;  
307   G4double lowEnergyLimitQ;  
308   G4double lowestEnergyLimit;  
309   G4double plabLowLimit;
310 
311   G4int fEnergyBin;
312   G4int fAngleBin;
313 
314   G4PhysicsLogVector*           fEnergyVector;
315   G4PhysicsTable*               fAngleTable;
316   std::vector<G4PhysicsTable*>  fAngleBank;
317 
318   std::vector<G4double> fElementNumberVector;
319   std::vector<G4String> fElementNameVector;
320 
321   const G4ParticleDefinition* fParticle;
322 
323   G4double fWaveVector;
324   G4double fAtomicWeight;
325   G4double fAtomicNumber;
326 
327   G4double fNuclearRadius1;
328   G4double fNuclearRadius2;
329   G4double fNuclearRadius;
330   G4double fNuclearRadiusSquare;
331   G4double fNuclearRadiusCof;
332 
333   G4double fBeta;
334   G4double fZommerfeld;
335   G4double fRutherfordRatio;
336   G4double fAm;
337   G4bool   fAddCoulomb;
338 
339   G4double fCoulombPhase0;
340   G4double fHalfRutThetaTg;
341   G4double fHalfRutThetaTg2;
342   G4double fRutherfordTheta;
343 
344   G4double fProfileLambda;
345   G4double fProfileDelta;
346   G4double fProfileAlpha;
347 
348   G4double fCofLambda;
349   G4double fCofAlpha;
350   G4double fCofDelta;
351   G4double fCofPhase;
352   G4double fCofFar;
353 
354   G4double fCofAlphaMax;
355   G4double fCofAlphaCoulomb;
356 
357   G4int    fMaxL;
358   G4double fSumSigma;
359   G4double fEtaRatio;
360 
361   G4double fReZ;
362   G4double fCoulombMuC;
363 
364 };
365 
366 
367 inline void G4NuclNuclDiffuseElastic::SetRecoilKinEnergyLimit(G4double value)
368 {
369   lowEnergyRecoilLimit = value;
370 }
371 
372 inline void G4NuclNuclDiffuseElastic::SetPlabLowLimit(G4double value)
373 {
374   plabLowLimit = value;
375 }
376 
377 inline void G4NuclNuclDiffuseElastic::SetHEModelLowLimit(G4double value)
378 {
379   lowEnergyLimitHE = value;
380 }
381 
382 inline void G4NuclNuclDiffuseElastic::SetQModelLowLimit(G4double value)
383 {
384   lowEnergyLimitQ = value;
385 }
386 
387 inline void G4NuclNuclDiffuseElastic::SetLowestEnergyLimit(G4double value)
388 {
389   lowestEnergyLimit = value;
390 }
391 
392 ////////////////////////////////////////////////////////////////////
393 //
394 // damp factor in diffraction x/sh(x), x was already *pi
395 
396 inline G4double G4NuclNuclDiffuseElastic::DampFactor(G4double x)
397 {
398   G4double df;
399   G4double f2 = 2., f3 = 6., f4 = 24.; // first factorials
400 
401   // x *= pi;
402 
403   if( std::fabs(x) < 0.01 )
404   { 
405     df = 1./(1. + x/f2 + x*x/f3 + x*x*x/f4);
406   }
407   else
408   {
409     df = x/std::sinh(x); 
410   }
411   return df;
412 }
413 
414 
415 ////////////////////////////////////////////////////////////////////
416 //
417 // return J1(x)/x with special case for small x
418 
419 inline G4double G4NuclNuclDiffuseElastic::BesselOneByArg(G4double x)
420 {
421   G4double x2, result;
422   
423   if( std::fabs(x) < 0.01 )
424   { 
425    x     *= 0.5;
426    x2     = x*x;
427    result = 2. - x2 + x2*x2/6.;
428   }
429   else
430   {
431     result = BesselJone(x)/x; 
432   }
433   return result;
434 }
435 
436 ////////////////////////////////////////////////////////////////////
437 //
438 // return particle beta
439 
440 inline  G4double 
441 G4NuclNuclDiffuseElastic::CalculateParticleBeta(const G4ParticleDefinition* particle, 
442             G4double momentum)
443 {
444   G4double mass = particle->GetPDGMass();
445   G4double a    = momentum/mass;
446   fBeta         = a/std::sqrt(1+a*a);
447 
448   return fBeta; 
449 }
450 
451 ////////////////////////////////////////////////////////////////////
452 //
453 // return Zommerfeld parameter for Coulomb scattering
454 
455 inline  G4double 
456 G4NuclNuclDiffuseElastic::CalculateZommerfeld(G4double beta, G4double Z1, G4double Z2 )
457 {
458   fZommerfeld = CLHEP::fine_structure_const*Z1*Z2/beta;
459 
460   return fZommerfeld; 
461 }
462 
463 ////////////////////////////////////////////////////////////////////
464 //
465 // return Wentzel correction for Coulomb scattering
466 
467 inline  G4double 
468 G4NuclNuclDiffuseElastic::CalculateAm( G4double momentum, G4double n, G4double Z)
469 {
470   G4double k   = momentum/CLHEP::hbarc;
471   G4double ch  = 1.13 + 3.76*n*n;
472   G4double zn  = 1.77*k*(1.0/G4Pow::GetInstance()->A13(Z))*CLHEP::Bohr_radius;
473   G4double zn2 = zn*zn;
474   fAm          = ch/zn2;
475 
476   return fAm;
477 }
478 
479 ////////////////////////////////////////////////////////////////////
480 //
481 // calculate nuclear radius for different atomic weights using different approximations
482 
483 inline  G4double G4NuclNuclDiffuseElastic::CalculateNuclearRad( G4double A)
484 {
485   G4double r0 = 1.*CLHEP::fermi, radius;
486   // r0 *= 1.12;
487   // r0 *= 1.44;
488   r0 *= fNuclearRadiusCof;
489 
490   /*
491   if( A < 50. )
492   {
493     if( A > 10. ) r0  = 1.16*( 1 - (1.0/G4Pow::GetInstance()->A23(A)) )*CLHEP::fermi;   // 1.08*fermi;
494     else          r0  = 1.1*CLHEP::fermi;
495 
496     radius = r0*G4Pow::GetInstance()->A13(A);
497   }
498   else
499   {
500     r0 = 1.7*CLHEP::fermi;   // 1.7*fermi;
501 
502     radius = r0*G4Pow::GetInstance()->powA(A, 0.27); // 0.27);
503   }
504   */
505   radius = r0*G4Pow::GetInstance()->A13(A);
506 
507   return radius;
508 }
509 
510 ////////////////////////////////////////////////////////////////////
511 //
512 // return Coulomb scattering differential xsc with Wentzel correction. Test function  
513 
514 inline  G4double G4NuclNuclDiffuseElastic::GetCoulombElasticXsc( const G4ParticleDefinition* particle, 
515                                  G4double theta, 
516                G4double momentum, 
517          G4double Z         )
518 {
519   G4double sinHalfTheta  = std::sin(0.5*theta);
520   G4double sinHalfTheta2 = sinHalfTheta*sinHalfTheta;
521   G4double beta          = CalculateParticleBeta( particle, momentum);
522   G4double z             = particle->GetPDGCharge();
523   G4double n             = CalculateZommerfeld( beta, z, Z );
524   G4double am            = CalculateAm( momentum, n, Z);
525   G4double k             = momentum/CLHEP::hbarc;
526   G4double ch            = 0.5*n/k;
527   G4double ch2           = ch*ch;
528   G4double xsc           = ch2/((sinHalfTheta2+am)*(sinHalfTheta2+am));
529 
530   return xsc;
531 }
532 
533 ////////////////////////////////////////////////////////////////////
534 //
535 // return Rutherford scattering differential xsc with Wentzel correction. For Sampling.  
536 
537 inline  G4double G4NuclNuclDiffuseElastic::GetRutherfordXsc(G4double theta)
538 {
539   G4double sinHalfTheta  = std::sin(0.5*theta);
540   G4double sinHalfTheta2 = sinHalfTheta*sinHalfTheta;
541 
542   G4double ch2           = fRutherfordRatio*fRutherfordRatio;
543 
544   G4double xsc           = ch2/(sinHalfTheta2+fAm)/(sinHalfTheta2+fAm);
545 
546   return xsc;
547 }
548 
549 ////////////////////////////////////////////////////////////////////
550 //
551 // return Coulomb scattering total xsc with Wentzel correction  
552 
553 inline  G4double G4NuclNuclDiffuseElastic::GetCoulombTotalXsc( const G4ParticleDefinition* particle,  
554                                            G4double momentum, G4double Z  )
555 {
556   G4double beta          = CalculateParticleBeta( particle, momentum);
557   G4cout<<"beta = "<<beta<<G4endl;
558   G4double z             = particle->GetPDGCharge();
559   G4double n             = CalculateZommerfeld( beta, z, Z );
560   G4cout<<"fZomerfeld = "<<n<<G4endl;
561   G4double am            = CalculateAm( momentum, n, Z);
562   G4cout<<"cof Am = "<<am<<G4endl;
563   G4double k             = momentum/CLHEP::hbarc;
564   G4cout<<"k = "<<k*CLHEP::fermi<<" 1/fermi"<<G4endl;
565   G4cout<<"k*Bohr_radius = "<<k*CLHEP::Bohr_radius<<G4endl;
566   G4double ch            = n/k;
567   G4double ch2           = ch*ch;
568   G4double xsc           = ch2*CLHEP::pi/(am +am*am);
569 
570   return xsc;
571 }
572 
573 ////////////////////////////////////////////////////////////////////
574 //
575 // return Coulomb scattering xsc with Wentzel correction  integrated between
576 // theta1 and < theta2
577 
578 inline  G4double 
579 G4NuclNuclDiffuseElastic::GetCoulombIntegralXsc(const G4ParticleDefinition* particle,  
580             G4double momentum, G4double Z, 
581             G4double theta1, G4double theta2 )
582 {
583   G4double c1 = std::cos(theta1);
584   //G4cout<<"c1 = "<<c1<<G4endl;
585   G4double c2 = std::cos(theta2);
586   // G4cout<<"c2 = "<<c2<<G4endl;
587   G4double beta          = CalculateParticleBeta( particle, momentum);
588   // G4cout<<"beta = "<<beta<<G4endl;
589   G4double z             = particle->GetPDGCharge();
590   G4double n             = CalculateZommerfeld( beta, z, Z );
591   // G4cout<<"fZomerfeld = "<<n<<G4endl;
592   G4double am            = CalculateAm( momentum, n, Z);
593   // G4cout<<"cof Am = "<<am<<G4endl;
594   G4double k             = momentum/CLHEP::hbarc;
595   // G4cout<<"k = "<<k*CLHEP::fermi<<" 1/fermi"<<G4endl;
596   // G4cout<<"k*Bohr_radius = "<<k*CLHEP::Bohr_radius<<G4endl;
597   G4double ch            = n/k;
598   G4double ch2           = ch*ch;
599   am *= 2.;
600   G4double xsc = ch2*CLHEP::twopi*(c1-c2)/((1 - c1 + am)*(1 - c2 + am));
601 
602   return xsc;
603 }
604 
605 ///////////////////////////////////////////////////////////////////
606 //
607 // For the calculation of arg Gamma(z) one needs complex extension 
608 // of ln(Gamma(z)) here is approximate algorithm
609 
610 inline G4complex G4NuclNuclDiffuseElastic::GammaLogB2n(G4complex z)
611 {
612   G4complex z1 = 12.*z;
613   G4complex z2 = z*z;
614   G4complex z3 = z2*z;
615   G4complex z5 = z2*z3;
616   G4complex z7 = z2*z5;
617 
618   z3 *= 360.;
619   z5 *= 1260.;
620   z7 *= 1680.;
621 
622   G4complex result  = (z-0.5)*std::log(z)-z+0.5*G4Log(CLHEP::twopi);
623             result += 1./z1 - 1./z3 +1./z5 -1./z7;
624   return result;
625 }
626 
627 /////////////////////////////////////////////////////////////////
628 //
629 //
630 
631 inline G4double  G4NuclNuclDiffuseElastic::GetErf(G4double x)
632 {
633   G4double t, z, tmp, result;
634 
635   z   = std::fabs(x);
636   t   = 1.0/(1.0+0.5*z);
637 
638   tmp = t*std::exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+
639     t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+
640     t*(-0.82215223+t*0.17087277)))))))));
641 
642   if( x >= 0.) result = 1. - tmp;
643   else         result = 1. + tmp; 
644     
645   return result;
646 }
647 
648 /////////////////////////////////////////////////////////////////
649 //
650 //
651 
652 inline G4complex G4NuclNuclDiffuseElastic::GetErfcComp(G4complex z, G4int nMax)
653 {
654   G4complex erfcz = 1. - GetErfComp( z, nMax);
655   return erfcz;
656 }
657 
658 /////////////////////////////////////////////////////////////////
659 //
660 //
661 
662 inline G4complex G4NuclNuclDiffuseElastic::GetErfcSer(G4complex z, G4int nMax)
663 {
664   G4complex erfcz = 1. - GetErfSer( z, nMax);
665   return erfcz;
666 }
667 
668 /////////////////////////////////////////////////////////////////
669 //
670 //
671 
672 inline G4complex G4NuclNuclDiffuseElastic::GetErfcInt(G4complex z) // , G4int nMax)
673 {
674   G4complex erfcz = 1. - GetErfInt( z); // , nMax);
675   return erfcz;
676 }
677 
678 
679 /////////////////////////////////////////////////////////////////
680 //
681 //
682 
683 inline G4complex G4NuclNuclDiffuseElastic::TestErfcComp(G4complex z, G4int nMax)
684 {
685   G4complex miz = G4complex( z.imag(), -z.real() ); 
686   G4complex erfcz = 1. - GetErfComp( miz, nMax);
687   G4complex w = std::exp(-z*z)*erfcz;
688   return w;
689 }
690 
691 /////////////////////////////////////////////////////////////////
692 //
693 //
694 
695 inline G4complex G4NuclNuclDiffuseElastic::TestErfcSer(G4complex z, G4int nMax)
696 {
697   G4complex miz = G4complex( z.imag(), -z.real() ); 
698   G4complex erfcz = 1. - GetErfSer( miz, nMax);
699   G4complex w = std::exp(-z*z)*erfcz;
700   return w;
701 }
702 
703 /////////////////////////////////////////////////////////////////
704 //
705 //
706 
707 inline G4complex G4NuclNuclDiffuseElastic::TestErfcInt(G4complex z) // , G4int nMax)
708 {
709   G4complex miz = G4complex( z.imag(), -z.real() ); 
710   G4complex erfcz = 1. - GetErfInt( miz); // , nMax);
711   G4complex w = std::exp(-z*z)*erfcz;
712   return w;
713 }
714 
715 /////////////////////////////////////////////////////////////////
716 //
717 //
718 
719 inline G4complex G4NuclNuclDiffuseElastic::GetErfSer(G4complex z, G4int nMax)
720 {
721   G4int n;
722   G4double a =1., b = 1., tmp;
723   G4complex sum = z, d = z;
724 
725   for( n = 1; n <= nMax; n++)
726   {
727     a *= 2.;
728     b *= 2.*n +1.;
729     d *= z*z;
730 
731     tmp = a/b;
732 
733     sum += tmp*d;
734   }
735   sum *= 2.*std::exp(-z*z)/std::sqrt(CLHEP::pi);
736 
737   return sum;
738 }
739 
740 /////////////////////////////////////////////////////////////////////
741 
742 inline  G4double  G4NuclNuclDiffuseElastic::GetExpCos(G4double x)
743 {
744   G4double result;
745 
746   result = G4Exp(x*x-fReZ*fReZ);
747   result *= std::cos(2.*x*fReZ);
748   return result;
749 }
750 
751 /////////////////////////////////////////////////////////////////////
752 
753 inline  G4double  G4NuclNuclDiffuseElastic::GetExpSin(G4double x)
754 {
755   G4double result;
756 
757   result = G4Exp(x*x-fReZ*fReZ);
758   result *= std::sin(2.*x*fReZ);
759   return result;
760 }
761 
762 
763 /////////////////////////////////////////////////////////////////
764 //
765 //
766 
767 inline G4double G4NuclNuclDiffuseElastic::GetCint(G4double x)
768 {
769   G4double out;
770 
771   G4Integrator<G4NuclNuclDiffuseElastic,G4double(G4NuclNuclDiffuseElastic::*)(G4double)> integral;
772 
773   out= integral.Legendre96(this,&G4NuclNuclDiffuseElastic::GetCosHaPit2, 0., x );
774 
775   return out;
776 }
777 
778 /////////////////////////////////////////////////////////////////
779 //
780 //
781 
782 inline G4double G4NuclNuclDiffuseElastic::GetSint(G4double x)
783 {
784   G4Integrator<G4NuclNuclDiffuseElastic,G4double(G4NuclNuclDiffuseElastic::*)(G4double)> integral;
785 
786   G4double out = 
787     integral.Legendre96(this,&G4NuclNuclDiffuseElastic::GetSinHaPit2, 0., x );
788 
789   return out;
790 }
791 
792 
793 /////////////////////////////////////////////////////////////////
794 //
795 //
796 
797 inline  G4complex G4NuclNuclDiffuseElastic::CoulombAmplitude(G4double theta)
798 {
799   G4complex ca;
800   
801   G4double sinHalfTheta  = std::sin(0.5*theta);
802   G4double sinHalfTheta2 = sinHalfTheta*sinHalfTheta; 
803   sinHalfTheta2         += fAm;
804 
805   G4double order         = 2.*fCoulombPhase0 - fZommerfeld*G4Log(sinHalfTheta2);
806   G4complex z            = G4complex(0., order);
807   ca                     = std::exp(z);
808 
809   ca                    *= -fZommerfeld/(2.*fWaveVector*sinHalfTheta2);
810 
811   return ca; 
812 }
813 
814 /////////////////////////////////////////////////////////////////
815 //
816 //
817 
818 inline  G4double G4NuclNuclDiffuseElastic::CoulombAmplitudeMod2(G4double theta)
819 {
820   G4complex ca = CoulombAmplitude(theta);
821   G4double out = ca.real()*ca.real() + ca.imag()*ca.imag();
822 
823   return  out;
824 }
825 
826 /////////////////////////////////////////////////////////////////
827 //
828 //
829 
830 
831 inline  void G4NuclNuclDiffuseElastic::CalculateCoulombPhaseZero()
832 {
833   G4complex z        = G4complex(1,fZommerfeld); 
834   // G4complex gammalog = GammaLogarithm(z);
835   G4complex gammalog = GammaLogB2n(z);
836   fCoulombPhase0     = gammalog.imag();
837 }
838 
839 /////////////////////////////////////////////////////////////////
840 //
841 //
842 
843 
844 inline  G4double G4NuclNuclDiffuseElastic::CalculateCoulombPhase(G4int n)
845 {
846   G4complex z        = G4complex(1. + n, fZommerfeld); 
847   // G4complex gammalog = GammaLogarithm(z);
848   G4complex gammalog = GammaLogB2n(z);
849   return gammalog.imag();
850 }
851 
852 
853 /////////////////////////////////////////////////////////////////
854 //
855 //
856 
857 
858 inline  void G4NuclNuclDiffuseElastic::CalculateRutherfordAnglePar()
859 {
860   fHalfRutThetaTg   = fZommerfeld/fProfileLambda;  // (fWaveVector*fNuclearRadius);
861   fRutherfordTheta  = 2.*std::atan(fHalfRutThetaTg);
862   fHalfRutThetaTg2  = fHalfRutThetaTg*fHalfRutThetaTg;
863   // G4cout<<"fRutherfordTheta = "<<fRutherfordTheta/degree<<" degree"<<G4endl;
864 
865 }
866 
867 /////////////////////////////////////////////////////////////////
868 //
869 //
870 
871 inline   G4double G4NuclNuclDiffuseElastic::ProfileNear(G4double theta)
872 {
873   G4double dTheta = fRutherfordTheta - theta;
874   G4double result = 0., argument = 0.;
875 
876   if(std::abs(dTheta) < 0.001) result = fProfileAlpha*fProfileDelta;
877   else
878   {
879     argument = fProfileDelta*dTheta;
880     result   = CLHEP::pi*argument*G4Exp(fProfileAlpha*argument);
881     result  /= std::sinh(CLHEP::pi*argument);
882     result  -= 1.;
883     result  /= dTheta;
884   }
885   return result;
886 }
887 
888 /////////////////////////////////////////////////////////////////
889 //
890 //
891 
892 inline   G4double G4NuclNuclDiffuseElastic::ProfileFar(G4double theta)
893 {
894   G4double dTheta   = fRutherfordTheta + theta;
895   G4double argument = fProfileDelta*dTheta;
896 
897   G4double result   = CLHEP::pi*argument*G4Exp(fProfileAlpha*argument);
898   result           /= std::sinh(CLHEP::pi*argument);
899   result           /= dTheta;
900 
901   return result;
902 }
903 
904 /////////////////////////////////////////////////////////////////
905 //
906 //
907 
908 inline   G4double G4NuclNuclDiffuseElastic::Profile(G4double theta)
909 {
910   G4double dTheta = fRutherfordTheta - theta;
911   G4double result = 0., argument = 0.;
912 
913   if(std::abs(dTheta) < 0.001) result = 1.;
914   else
915   {
916     argument = fProfileDelta*dTheta;
917     result   = CLHEP::pi*argument;
918     result  /= std::sinh(result);
919   }
920   return result;
921 }
922 
923 /////////////////////////////////////////////////////////////////
924 //
925 //
926 
927 inline   G4complex G4NuclNuclDiffuseElastic::PhaseNear(G4double theta)
928 {
929   G4double twosigma = 2.*fCoulombPhase0; 
930   twosigma -= fZommerfeld*G4Log(fHalfRutThetaTg2/(1.+fHalfRutThetaTg2));
931   twosigma += fRutherfordTheta*fZommerfeld/fHalfRutThetaTg - CLHEP::halfpi;
932   twosigma -= fProfileLambda*theta - 0.25*CLHEP::pi;
933 
934   twosigma *= fCofPhase;
935 
936   G4complex z = G4complex(0., twosigma);
937 
938   return std::exp(z);
939 }
940 
941 /////////////////////////////////////////////////////////////////
942 //
943 //
944 
945 inline   G4complex G4NuclNuclDiffuseElastic::PhaseFar(G4double theta)
946 {
947   G4double twosigma = 2.*fCoulombPhase0; 
948   twosigma -= fZommerfeld*G4Log(fHalfRutThetaTg2/(1.+fHalfRutThetaTg2));
949   twosigma += fRutherfordTheta*fZommerfeld/fHalfRutThetaTg - CLHEP::halfpi;
950   twosigma += fProfileLambda*theta - 0.25*CLHEP::pi;
951 
952   twosigma *= fCofPhase;
953 
954   G4complex z = G4complex(0., twosigma);
955 
956   return std::exp(z);
957 }
958 
959 
960 /////////////////////////////////////////////////////////////////
961 //
962 //
963 
964 inline  G4complex G4NuclNuclDiffuseElastic::AmplitudeFar(G4double theta)
965 {
966   G4double kappa = std::sqrt(0.5*fProfileLambda/std::sin(theta)/CLHEP::pi);
967   G4complex out = G4complex(kappa/fWaveVector,0.);
968   out *= ProfileFar(theta);
969   out *= PhaseFar(theta);
970   return out;
971 }
972 
973 
974 /////////////////////////////////////////////////////////////////
975 //
976 //
977 
978 inline  G4complex G4NuclNuclDiffuseElastic::Amplitude(G4double theta)
979 {
980  
981   G4complex out = AmplitudeNear(theta) + fCofFar*AmplitudeFar(theta);
982   // G4complex out = AmplitudeNear(theta);
983   // G4complex out = AmplitudeFar(theta);
984   return    out;
985 }
986 
987 /////////////////////////////////////////////////////////////////
988 //
989 //
990 
991 inline  G4double  G4NuclNuclDiffuseElastic::AmplitudeMod2(G4double theta)
992 {
993   G4complex out = Amplitude(theta);
994   G4double mod2 = out.real()*out.real() + out.imag()*out.imag();
995   return   mod2;
996 }
997 
998 
999 /////////////////////////////////////////////////////////////////
1000 //
1001 //
1002 
1003 inline G4double G4NuclNuclDiffuseElastic::GetRatioSim(G4double theta)
1004 {
1005   G4double sinThetaR  = 2.*fHalfRutThetaTg/(1. + fHalfRutThetaTg2);
1006   G4double dTheta     = 0.5*(theta - fRutherfordTheta);
1007   G4double sindTheta  = std::sin(dTheta);
1008 
1009   G4double order      = std::sqrt(fProfileLambda/sinThetaR/CLHEP::pi)*2.*sindTheta;
1010   // G4cout<<"order = "<<order<<G4endl;  
1011   G4double cosFresnel = 0.5 - GetCint(order);  
1012   G4double sinFresnel = 0.5 - GetSint(order);  
1013 
1014   G4double out = 0.5*( cosFresnel*cosFresnel + sinFresnel*sinFresnel );
1015 
1016   return out;
1017 }
1018 
1019 /////////////////////////////////////////////////////////////////
1020 //
1021 // The xsc for Fresnel smooth nucleus profile
1022 
1023 inline G4double G4NuclNuclDiffuseElastic::GetFresnelDiffuseXsc(G4double theta)
1024 {
1025   G4double ratio   = GetRatioGen(theta);
1026   G4double ruthXsc = GetRutherfordXsc(theta);
1027   G4double xsc     = ratio*ruthXsc;
1028   return xsc;
1029 }
1030 
1031 /////////////////////////////////////////////////////////////////
1032 //
1033 // The xsc for Fresnel smooth nucleus profile for integration
1034 
1035 inline G4double G4NuclNuclDiffuseElastic::GetFresnelIntegrandXsc(G4double alpha)
1036 {
1037   G4double theta = std::sqrt(alpha);
1038   G4double xsc     = GetFresnelDiffuseXsc(theta);
1039   return xsc;
1040 }
1041 
1042 /////////////////////////////////////////////////////////////////
1043 //
1044 //
1045 
1046 inline  G4double  G4NuclNuclDiffuseElastic::AmplitudeSimMod2(G4double theta)
1047 {
1048   G4complex out = AmplitudeSim(theta);
1049   G4double mod2 = out.real()*out.real() + out.imag()*out.imag();
1050   return   mod2;
1051 }
1052 
1053 
1054 /////////////////////////////////////////////////////////////////
1055 //
1056 //
1057 
1058 inline  G4double  G4NuclNuclDiffuseElastic::AmplitudeGlaMod2(G4double theta)
1059 {
1060   G4complex out = AmplitudeGla(theta);
1061   G4double mod2 = out.real()*out.real() + out.imag()*out.imag();
1062   return   mod2;
1063 }
1064 
1065 /////////////////////////////////////////////////////////////////
1066 //
1067 //
1068 
1069 inline  G4double  G4NuclNuclDiffuseElastic::AmplitudeGGMod2(G4double theta)
1070 {
1071   G4complex out = AmplitudeGG(theta);
1072   G4double mod2 = out.real()*out.real() + out.imag()*out.imag();
1073   return   mod2;
1074 }
1075 
1076 ////////////////////////////////////////////////////////////////////////////////////
1077 //
1078 //
1079 
1080 inline G4double G4NuclNuclDiffuseElastic::CalcMandelstamS( const G4double mp , 
1081                                                        const G4double mt , 
1082                                                        const G4double Plab )
1083 {
1084   G4double Elab = std::sqrt ( mp * mp + Plab * Plab );
1085   G4double sMand  = mp*mp + mt*mt + 2*Elab*mt ;
1086 
1087   return sMand;
1088 }
1089 
1090 
1091 
1092 #endif
1093