source: trunk/source/processes/electromagnetic/muons/src/G4MuBremsstrahlungModel.cc @ 846

Last change on this file since 846 was 819, checked in by garnier, 16 years ago

import all except CVS

File size: 19.2 KB
Line 
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// $Id: G4MuBremsstrahlungModel.cc,v 1.24 2007/11/08 11:48:28 vnivanch Exp $
27// GEANT4 tag $Name: geant4-09-01-patch-02 $
28//
29// -------------------------------------------------------------------
30//
31// GEANT4 Class file
32//
33//
34// File name:     G4MuBremsstrahlungModel
35//
36// Author:        Vladimir Ivanchenko on base of Laszlo Urban code
37//
38// Creation date: 24.06.2002
39//
40// Modifications:
41//
42// 04-12-02 Change G4DynamicParticle constructor in PostStepDoIt (V.Ivanchenko)
43// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
44// 24-01-03 Fix for compounds (V.Ivanchenko)
45// 27-01-03 Make models region aware (V.Ivanchenko)
46// 13-02-03 Add name (V.Ivanchenko)
47// 10-02-04 Add lowestKinEnergy (V.Ivanchenko)
48// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
49// 03-08-05 Angular correlations according to PRM (V.Ivantchenko)
50// 13-02-06 add ComputeCrossSectionPerAtom (mma)
51// 21-03-06 Fix problem of initialisation in case when cuts are not defined (VI)
52// 07-11-07 Improve sampling of final state (A.Bogdanov)
53//
54
55//
56// Class Description:
57//
58//
59// -------------------------------------------------------------------
60//
61//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
62//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
63
64#include "G4MuBremsstrahlungModel.hh"
65#include "G4Gamma.hh"
66#include "G4MuonMinus.hh"
67#include "G4MuonPlus.hh"
68#include "Randomize.hh"
69#include "G4Material.hh"
70#include "G4Element.hh"
71#include "G4ElementVector.hh"
72#include "G4ProductionCutsTable.hh"
73#include "G4ParticleChangeForLoss.hh"
74
75//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
76
77// static members
78//
79G4double G4MuBremsstrahlungModel::zdat[]={1., 4., 13., 29., 92.};
80G4double G4MuBremsstrahlungModel::adat[]={1.01, 9.01, 26.98, 63.55, 238.03};
81G4double G4MuBremsstrahlungModel::tdat[]={1.e3, 1.e4, 1.e5, 1.e6, 1.e7, 1.e8,
82                                          1.e9, 1.e10};
83
84//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
85
86using namespace std;
87
88G4MuBremsstrahlungModel::G4MuBremsstrahlungModel(const G4ParticleDefinition* p,
89                                                 const G4String& nam)
90  : G4VEmModel(nam),
91    particle(0),
92    lowestKinEnergy(1.0*GeV),
93    minThreshold(1.0*keV),
94    nzdat(5),
95    ntdat(8),
96    NBIN(1000),
97    cutFixed(0.98*keV),
98    ignoreCut(false),
99    samplingTablesAreFilled(false)
100{
101  theGamma = G4Gamma::Gamma();
102  if(p) SetParticle(p);
103}
104
105//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
106
107G4MuBremsstrahlungModel::~G4MuBremsstrahlungModel()
108{
109  size_t n = partialSumSigma.size();
110  if(n > 0) {
111    for(size_t i=0; i<n; i++) {
112      delete partialSumSigma[i];
113    }
114  }
115}
116
117//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
118
119G4double G4MuBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
120                                               const G4MaterialCutsCouple*)
121{
122  return minThreshold;
123}
124
125//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
126
127void G4MuBremsstrahlungModel::SetParticle(const G4ParticleDefinition* p)
128{
129  if(!particle) {
130    particle = p;
131    mass = particle->GetPDGMass();
132  }
133}
134
135//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
136
137void G4MuBremsstrahlungModel::Initialise(const G4ParticleDefinition* p,
138                                         const G4DataVector& cuts)
139{
140  if(p) SetParticle(p);
141
142  highKinEnergy = HighEnergyLimit();
143
144  G4double fixedEnergy = 0.5*highKinEnergy;
145
146  const G4ProductionCutsTable* theCoupleTable=
147        G4ProductionCutsTable::GetProductionCutsTable();
148  if(theCoupleTable) {
149    G4int numOfCouples = theCoupleTable->GetTableSize();
150   
151    G4int nn = partialSumSigma.size();
152    G4int nc = cuts.size();
153    if(nn > 0) {
154      for (G4int ii=0; ii<nn; ii++){
155        G4DataVector* a=partialSumSigma[ii];
156        if ( a )  delete a;   
157      } 
158      partialSumSigma.clear();
159    }
160    if (numOfCouples>0) {
161      for (G4int i=0; i<numOfCouples; i++) {
162        G4double cute = DBL_MAX;
163        if(i < nc) cute = cuts[i];
164        if(cute < cutFixed || ignoreCut) cute = cutFixed;
165        const G4MaterialCutsCouple* couple = 
166          theCoupleTable->GetMaterialCutsCouple(i);
167        const G4Material* material = couple->GetMaterial();
168        G4DataVector* dv = ComputePartialSumSigma(material,fixedEnergy,cute);
169        partialSumSigma.push_back(dv);
170      }
171    }
172  }
173  if(!samplingTablesAreFilled) MakeSamplingTables();
174  if(pParticleChange)
175    fParticleChange = 
176      reinterpret_cast<G4ParticleChangeForLoss*>(pParticleChange);
177  else
178    fParticleChange = new G4ParticleChangeForLoss();
179}
180
181//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
182
183G4double G4MuBremsstrahlungModel::ComputeDEDXPerVolume(
184                                              const G4Material* material,
185                                              const G4ParticleDefinition*,
186                                                    G4double kineticEnergy,
187                                                    G4double cutEnergy)
188{
189  G4double dedx = 0.0;
190  if (kineticEnergy <= lowestKinEnergy || ignoreCut) return dedx;
191
192  G4double tmax = kineticEnergy;
193  G4double cut  = min(cutEnergy,tmax);
194  if(cut < cutFixed) cut = cutFixed;
195
196  const G4ElementVector* theElementVector = material->GetElementVector();
197  const G4double* theAtomicNumDensityVector =
198                                          material->GetAtomicNumDensityVector();
199
200  //  loop for elements in the material
201  for (size_t i=0; i<material->GetNumberOfElements(); i++) {
202
203    G4double Z = (*theElementVector)[i]->GetZ();
204    G4double A = (*theElementVector)[i]->GetA()/(g/mole) ;
205
206    G4double loss = ComputMuBremLoss(Z, A, kineticEnergy, cut);
207
208    dedx += loss*theAtomicNumDensityVector[i];
209  }
210  if(dedx < 0.) dedx = 0.;
211  return dedx;
212}
213
214//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
215
216G4double G4MuBremsstrahlungModel::ComputMuBremLoss(G4double Z, G4double A,
217                                                   G4double tkin, G4double cut)
218{
219  G4double totalEnergy = mass + tkin;
220  G4double ak1 = 0.05;
221  G4int    k2=5;
222  G4double xgi[]={0.03377,0.16940,0.38069,0.61931,0.83060,0.96623};
223  G4double wgi[]={0.08566,0.18038,0.23396,0.23396,0.18038,0.08566};
224  G4double loss = 0.;
225
226  G4double vcut = cut/totalEnergy;
227  G4double vmax = tkin/totalEnergy;
228
229  G4double aaa = 0.;
230  G4double bbb = vcut;
231  if(vcut>vmax) bbb=vmax ;
232  G4int kkk = (G4int)((bbb-aaa)/ak1)+k2 ;
233  G4double hhh=(bbb-aaa)/float(kkk) ;
234
235  G4double aa = aaa;
236  for(G4int l=0; l<kkk; l++)
237  {
238    for(G4int i=0; i<6; i++)
239    {
240      G4double ep = (aa + xgi[i]*hhh)*totalEnergy;
241      loss += ep*wgi[i]*ComputeDMicroscopicCrossSection(tkin, Z, A, ep);
242    }
243    aa += hhh;
244  }
245
246  loss *=hhh*totalEnergy ;
247
248  return loss;
249}
250
251//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
252
253G4double G4MuBremsstrahlungModel::ComputeMicroscopicCrossSection(
254                                           G4double tkin,
255                                           G4double Z,
256                                           G4double A,
257                                           G4double cut)
258{
259  G4double totalEnergy = tkin + mass;
260  G4double ak1 = 2.3;
261  G4int    k2  = 4;
262  G4double xgi[]={0.03377,0.16940,0.38069,0.61931,0.83060,0.96623};
263  G4double wgi[]={0.08566,0.18038,0.23396,0.23396,0.18038,0.08566};
264  G4double cross = 0.;
265
266  if(cut >= tkin) return cross;
267
268  G4double vcut = cut/totalEnergy;
269  G4double vmax = tkin/totalEnergy;
270
271  G4double aaa = log(vcut);
272  G4double bbb = log(vmax);
273  G4int    kkk = (G4int)((bbb-aaa)/ak1)+k2 ;
274  G4double hhh = (bbb-aaa)/float(kkk);
275
276  G4double aa = aaa;
277
278  for(G4int l=0; l<kkk; l++)
279  {
280    for(G4int i=0; i<6; i++)
281    {
282      G4double ep = exp(aa + xgi[i]*hhh)*totalEnergy;
283      cross += ep*wgi[i]*ComputeDMicroscopicCrossSection(tkin, Z, A, ep);
284    }
285    aa += hhh;
286  }
287
288  cross *=hhh;
289
290  return cross;
291}
292
293//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
294
295G4double G4MuBremsstrahlungModel::ComputeDMicroscopicCrossSection(
296                                           G4double tkin,
297                                           G4double Z,
298                                           G4double A,
299                                           G4double gammaEnergy)
300//  differential cross section
301{
302  static const G4double sqrte=sqrt(exp(1.)) ;
303  static const G4double bh=202.4,bh1=446.,btf=183.,btf1=1429. ;
304  static const G4double rmass=mass/electron_mass_c2 ;
305  static const G4double cc=classic_electr_radius/rmass ;
306  static const G4double coeff= 16.*fine_structure_const*cc*cc/3. ;
307
308  G4double dxsection = 0.;
309
310  if( gammaEnergy > tkin) return dxsection ;
311
312  G4double E = tkin + mass ;
313  G4double v = gammaEnergy/E ;
314  G4double delta = 0.5*mass*mass*v/(E-gammaEnergy) ;
315  G4double rab0=delta*sqrte ;
316
317  G4double z13 = exp(-log(Z)/3.) ;
318  G4double dn  = 1.54*exp(0.27*log(A)) ;
319
320  G4double b,b1,dnstar ;
321
322  if(Z<1.5)
323  {
324    b=bh;
325    b1=bh1;
326    dnstar=dn ;
327  }
328  else
329  {
330    b=btf;
331    b1=btf1;
332    dnstar = exp((1.-1./Z)*log(dn)) ;
333  }
334
335  // nucleus contribution logarithm
336  G4double rab1=b*z13;
337  G4double fn=log(rab1/(dnstar*(electron_mass_c2+rab0*rab1))*
338              (mass+delta*(dnstar*sqrte-2.))) ;
339  if(fn <0.) fn = 0. ;
340  // electron contribution logarithm
341  G4double epmax1=E/(1.+0.5*mass*rmass/E) ;
342  G4double fe=0.;
343  if(gammaEnergy<epmax1)
344  {
345    G4double rab2=b1*z13*z13 ;
346    fe=log(rab2*mass/((1.+delta*rmass/(electron_mass_c2*sqrte))*
347                              (electron_mass_c2+rab0*rab2))) ;
348    if(fe<0.) fe=0. ;
349  }
350
351  dxsection = coeff*(1.-v*(1. - 0.75*v))*Z*(fn*Z + fe)/gammaEnergy;
352
353  return dxsection;
354}
355
356//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
357
358G4double G4MuBremsstrahlungModel::ComputeCrossSectionPerAtom(
359                                           const G4ParticleDefinition*,
360                                                 G4double kineticEnergy,
361                                                 G4double Z, G4double A,
362                                                 G4double cutEnergy,
363                                                 G4double)
364{
365  G4double cut  = min(cutEnergy, kineticEnergy);
366  if(cut < cutFixed || ignoreCut) cut = cutFixed;
367  G4double cross =
368    ComputeMicroscopicCrossSection (kineticEnergy, Z, A/(g/mole), cut);
369  return cross;
370}
371
372//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
373
374G4double G4MuBremsstrahlungModel::CrossSectionPerVolume(
375                                               const G4Material* material,
376                                               const G4ParticleDefinition*,
377                                                     G4double kineticEnergy,
378                                                     G4double cutEnergy,
379                                                     G4double maxEnergy)
380{
381  G4double cross = 0.0;
382  if (cutEnergy >= maxEnergy || kineticEnergy <= lowestKinEnergy) return cross;
383 
384  G4double tmax = min(maxEnergy, kineticEnergy);
385  G4double cut  = min(cutEnergy, tmax);
386  if(cut < cutFixed || ignoreCut) cut = cutFixed;
387
388  const G4ElementVector* theElementVector = material->GetElementVector();
389  const G4double* theAtomNumDensityVector =
390                                          material->GetAtomicNumDensityVector();
391
392  for (size_t i=0; i<material->GetNumberOfElements(); i++) {
393
394    G4double Z = (*theElementVector)[i]->GetZ();
395    G4double A = (*theElementVector)[i]->GetA()/(g/mole);
396
397    G4double cr = ComputeMicroscopicCrossSection(kineticEnergy, Z, A, cut);
398
399    if(tmax < kineticEnergy) {
400      cr -= ComputeMicroscopicCrossSection(kineticEnergy, Z, A, tmax);
401    }
402    cross += theAtomNumDensityVector[i] * cr;
403  }
404
405  return cross;
406}
407
408//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
409
410G4DataVector* G4MuBremsstrahlungModel::ComputePartialSumSigma(
411                                       const G4Material* material,
412                                             G4double kineticEnergy,
413                                             G4double cut)
414
415// Build the table of cross section per element. The table is built for MATERIAL
416// This table is used by DoIt to select randomly an element in the material.
417{
418  G4int nElements = material->GetNumberOfElements();
419  const G4ElementVector* theElementVector = material->GetElementVector();
420  const G4double* theAtomNumDensityVector = 
421                                          material->GetAtomicNumDensityVector();
422
423  G4DataVector* dv = new G4DataVector();
424
425  G4double cross = 0.0;
426
427  for (G4int i=0; i<nElements; i++ ) {
428
429    G4double Z = (*theElementVector)[i]->GetZ();
430    G4double A = (*theElementVector)[i]->GetA()/(g/mole) ;
431    cross += theAtomNumDensityVector[i] 
432             * ComputeMicroscopicCrossSection(kineticEnergy, Z, A, cut);
433    dv->push_back(cross);
434  }
435  return dv;
436}
437
438//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
439
440void G4MuBremsstrahlungModel::MakeSamplingTables()
441{
442
443  G4double AtomicNumber,AtomicWeight,KineticEnergy,
444           TotalEnergy,Maxep;
445
446  for (G4int iz=0; iz<nzdat; iz++)
447   {
448     AtomicNumber = zdat[iz];
449     AtomicWeight = adat[iz]*g/mole ;
450
451     for (G4int it=0; it<ntdat; it++)
452     {
453       KineticEnergy = tdat[it];
454       TotalEnergy = KineticEnergy + mass;
455       Maxep = KineticEnergy ;
456
457       G4double CrossSection = 0.0 ;
458
459       // calculate the differential cross section
460       // numerical integration in
461       //  log ...............
462       G4double c = log(Maxep/cutFixed) ;
463       G4double ymin = -5. ;
464       G4double ymax = 0. ;
465       G4double dy = (ymax-ymin)/NBIN ;
466
467       G4double y = ymin - 0.5*dy ;
468       G4double yy = ymin - dy ;
469       G4double x = exp(y);
470       G4double fac = exp(dy);
471       G4double dx = exp(yy)*(fac - 1.0);
472
473       for (G4int i=0 ; i<NBIN; i++)
474       {
475         y += dy ;
476         x *= fac;
477         dx*= fac;
478         G4double ep = cutFixed*exp(c*x) ;
479
480         CrossSection += ep*dx*ComputeDMicroscopicCrossSection(
481                                                 KineticEnergy,AtomicNumber,
482                                                 AtomicWeight,ep) ;
483         ya[i]=y ;
484         proba[iz][it][i] = CrossSection ;
485
486       }
487
488       proba[iz][it][NBIN] = CrossSection ;
489       ya[NBIN] = 0. ;   //   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
490
491       if(CrossSection > 0.)
492       {
493         for(G4int ib=0; ib<=NBIN; ib++)
494         {
495           proba[iz][it][ib] /= CrossSection ;
496         }
497       }
498     }
499   }
500  samplingTablesAreFilled = true;
501}
502
503//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
504
505void G4MuBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
506                                                const G4MaterialCutsCouple* couple,
507                                                const G4DynamicParticle* dp,
508                                                G4double minEnergy,
509                                                G4double maxEnergy)
510{
511  G4double kineticEnergy = dp->GetKineticEnergy();
512  // check against insufficient energy
513  G4double tmax = min(kineticEnergy, maxEnergy);
514  G4double tmin = min(kineticEnergy, minEnergy);
515  if(tmin < cutFixed || ignoreCut) tmin = cutFixed;
516  if(tmin >= tmax) return;
517
518  // ===== the begining of a new code  ======
519  // ===== sampling of energy transfer ======
520
521  G4ParticleMomentum partDirection = dp->GetMomentumDirection();
522
523  // select randomly one element constituing the material
524  const G4Element* anElement = SelectRandomAtom(couple);
525
526  G4double totalEnergy   = kineticEnergy + mass;
527  G4double totalMomentum = sqrt(kineticEnergy*(kineticEnergy + 2.0*mass));
528
529  G4double AtomicNumber = anElement->GetZ();
530  G4double AtomicWeight = anElement->GetA()/(g/mole);
531
532  G4double func1 = tmin*ComputeDMicroscopicCrossSection(
533                                    kineticEnergy,AtomicNumber,
534                                    AtomicWeight,tmin);
535
536  G4double lnepksi, epksi;
537  G4double func2;
538  G4double ksi2;
539
540  do {
541    lnepksi = log(tmin) + G4UniformRand()*log(kineticEnergy/tmin);
542    epksi   = exp(lnepksi);
543    func2   = epksi*ComputeDMicroscopicCrossSection(
544                                kineticEnergy,AtomicNumber,
545                                AtomicWeight,epksi);
546    ksi2 = G4UniformRand();
547
548  } while(func2/func1 < ksi2);
549
550  // ===== the end of a new code =====
551
552  // create G4DynamicParticle object for the Gamma
553  G4double gEnergy = epksi;
554
555  // sample angle
556  G4double gam  = totalEnergy/mass;
557  G4double rmax = gam*min(1.0, totalEnergy/gEnergy - 1.0);
558  rmax *= rmax;
559  G4double x = G4UniformRand()*rmax/(1.0 + rmax);
560
561  G4double theta = sqrt(x/(1.0 - x))/gam;
562  G4double sint  = sin(theta);
563  G4double phi   = twopi * G4UniformRand() ;
564  G4double dirx  = sint*cos(phi), diry = sint*sin(phi), dirz = cos(theta) ;
565
566  G4ThreeVector gDirection(dirx, diry, dirz);
567  gDirection.rotateUz(partDirection);
568
569  partDirection *= totalMomentum;
570  partDirection -= gEnergy*gDirection;
571  partDirection = partDirection.unit();
572
573  // primary change
574  kineticEnergy -= gEnergy;
575  fParticleChange->SetProposedKineticEnergy(kineticEnergy);
576  fParticleChange->SetProposedMomentumDirection(partDirection);
577
578  // save secondary
579  G4DynamicParticle* aGamma = new G4DynamicParticle(theGamma,gDirection,gEnergy);
580  vdp->push_back(aGamma);
581}
582
583//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
584
585const G4Element* G4MuBremsstrahlungModel::SelectRandomAtom(
586           const G4MaterialCutsCouple* couple) const
587{
588  // select randomly 1 element within the material
589
590  const G4Material* material = couple->GetMaterial();
591  G4int nElements = material->GetNumberOfElements();
592  const G4ElementVector* theElementVector = material->GetElementVector();
593  if(1 == nElements) return (*theElementVector)[0];
594  else if(1 > nElements) return 0;
595
596  G4DataVector* dv = partialSumSigma[couple->GetIndex()];
597  G4double rval = G4UniformRand()*((*dv)[nElements-1]);
598  for (G4int i=0; i<nElements; i++) {
599    if (rval <= (*dv)[i]) return (*theElementVector)[i];
600  }
601  return (*theElementVector)[nElements-1];
602}
603
604//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Note: See TracBrowser for help on using the repository browser.