Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/particles/management/src/G4MuonicAtomHelper.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 // G4MuonicAtomHelper class implementation
 27 //
 28 // Author: K.Lynch, 01.07.2016 - First implementation
 29 // Revision:
 30 // - 12.06.2017, K L Genser
 31 // --------------------------------------------------------------------
 32 
 33 #include "G4MuonicAtomHelper.hh"
 34 
 35 #include "G4DecayTable.hh"
 36 #include "G4ParticleTable.hh"
 37 #include "G4PhaseSpaceDecayChannel.hh"
 38 #include "G4PhysicalConstants.hh"
 39 #include "G4SystemOfUnits.hh"
 40 #include "Randomize.hh"
 41 
 42 G4MuonicAtom* G4MuonicAtomHelper::ConstructMuonicAtom(const G4String& name, G4int encoding,
 43                                                       G4Ions const* baseion)
 44 {
 45   // what should static charge be?  for G4Ions, it is Z ... should it
 46   // be Z-1 here (since there will always be a muon attached), or Z?
 47   const G4double charge = baseion->GetPDGCharge();
 48 
 49   static const G4String pType("MuonicAtom");  // put in an include? in an enum?
 50 
 51   G4bool stable = false;
 52   // Get the lifetime
 53   G4int Z = baseion->GetAtomicNumber();
 54   G4int A = baseion->GetAtomicMass();
 55   G4double lambdac = GetMuonCaptureRate(Z, A);
 56   G4double lambdad = GetMuonDecayRate(Z);
 57   G4double lifetime = 1. / (lambdac + lambdad);
 58   G4bool shortlived = false;
 59 
 60   const G4double mass = (G4ParticleTable::GetParticleTable()->FindParticle("mu-"))->GetPDGMass()
 61                         + baseion->GetPDGMass() - GetKShellEnergy(G4double(Z));  // fixme check
 62 
 63   auto decayTable = new G4DecayTable();
 64   // clang-format off
 65   auto muatom = new G4MuonicAtom(name, mass, 0.0, charge,
 66                                  baseion->GetPDGiSpin(),
 67                                  baseion->GetPDGiParity(),
 68                                  baseion->GetPDGiConjugation(),
 69                                  baseion->GetPDGiIsospin(),
 70                                  baseion->GetPDGiIsospin3(),
 71                                  baseion->GetPDGiGParity(),
 72                                  pType,
 73                                  baseion->GetLeptonNumber(),
 74                                  baseion->GetBaryonNumber(),
 75                                  encoding,
 76                                  stable,
 77                                  lifetime,
 78                                  decayTable,
 79                                  shortlived,
 80                                  baseion->GetParticleSubType(),
 81                                  baseion);
 82   // clang-format on
 83 
 84   muatom->SetPDGMagneticMoment(baseion->GetPDGMagneticMoment());
 85 
 86   // by this time both G4MuonicAtom and baseion should exist
 87 
 88   // if we choose DIO this will be the channel we'll use, so we put
 89   // br=1. to force it in that case
 90 
 91   decayTable->Insert(new G4PhaseSpaceDecayChannel(name, 1., 4, "e-", "anti_nu_e", "nu_mu",
 92                                                   baseion->GetParticleName()));
 93 
 94   muatom->SetDIOLifeTime(1. / lambdad);
 95   muatom->SetNCLifeTime(1. / lambdac);
 96   return muatom;
 97 }
 98 
 99 G4double G4MuonicAtomHelper::GetMuonCaptureRate(G4int Z, G4int A)
100 {
101   // Initialize data
102 
103   // Mu- capture data from
104   // T. Suzuki, D. F. Measday, J.P. Roalsvig Phys.Rev. C35 (1987) 2212
105   // weighted average of the two most precise measurements
106 
107   // Data for Hydrogen from Phys. Rev. Lett. 99(2007)032002
108   // Data for Helium from D.F. Measday Phys. Rep. 354(2001)243
109 
110   struct capRate
111   {
112       G4int Z;
113       G4int A;
114       G4double cRate;
115       G4double cRErr;
116   };
117 
118   // this struct has to be sorted by Z when initialized as we exit the
119   // loop once Z is above the stored value; cRErr are not used now but
120   // are included for completeness and future use
121   // clang-format off
122   constexpr capRate capRates [] = {
123     {  1,   1,  0.000725, 0.000017 },
124     {  2,   3,  0.002149, 0.00017 },
125     {  2,   4,  0.000356, 0.000026 },
126     {  3,   6,  0.004647, 0.00012 },
127     {  3,   7,  0.002229, 0.00012 },
128     {  4,   9,  0.006107, 0.00019 },
129     {  5,  10,  0.02757 , 0.00063 },
130     {  5,  11,  0.02188 , 0.00064 },
131     {  6,  12,  0.03807 , 0.00031 },
132     {  6,  13,  0.03474 , 0.00034 },
133     {  7,  14,  0.06885 , 0.00057 },
134     {  8,  16,  0.10242 , 0.00059 },
135     {  8,  18,  0.0880  , 0.0015  },
136     {  9,  19,  0.22905 , 0.00099 },
137     { 10,  20,  0.2288  , 0.0045 },
138     { 11,  23,  0.3773  , 0.0014 },
139     { 12,  24,  0.4823  , 0.0013 },
140     { 13,  27,  0.6985  , 0.0012 },
141     { 14,  28,  0.8656  , 0.0015 },
142     { 15,  31,  1.1681  , 0.0026 },
143     { 16,  32,  1.3510  , 0.0029 },
144     { 17,  35,  1.800   , 0.050 },
145     { 17,  37,  1.250   , 0.050 },
146     { 18,  40,  1.2727  , 0.0650 },
147     { 19,  39,  1.8492  , 0.0050 },
148     { 20,  40,  2.5359  , 0.0070 },
149     { 21,  45,  2.711   , 0.025 },
150     { 22,  48,  2.5908  , 0.0115 },
151     { 23,  51,  3.073   , 0.022 },
152     { 24,  50,  3.825   , 0.050 },
153     { 24,  52,  3.465   , 0.026 },
154     { 24,  53,  3.297   , 0.045 },
155     { 24,  54,  3.057   , 0.042 },
156     { 25,  55,  3.900   , 0.030 },
157     { 26,  56,  4.408   , 0.022 },
158     { 27,  59,  4.945   , 0.025 },
159     { 28,  58,  6.11    , 0.10 },
160     { 28,  60,  5.56    , 0.10 },
161     { 28,  62,  4.72    , 0.10 },
162     { 29,  63,  5.691   , 0.030 },
163     { 30,  66,  5.806   , 0.031 },
164     { 31,  69,  5.700   , 0.060 },
165     { 32,  72,  5.561   , 0.031 },
166     { 33,  75,  6.094   , 0.037 },
167     { 34,  80,  5.687   , 0.030 },
168     { 35,  79,  7.223   , 0.28 },
169     { 35,  81,  7.547   , 0.48 },
170     { 37,  85,  6.89    , 0.14 },
171     { 38,  88,  6.93    , 0.12 },
172     { 39,  89,  7.89    , 0.11 },
173     { 40,  91,  8.620   , 0.053 },
174     { 41,  93, 10.38    , 0.11 },
175     { 42,  96,  9.298   , 0.063 },
176     { 45, 103, 10.010   , 0.045 },
177     { 46, 106, 10.000   , 0.070 },
178     { 47, 107, 10.869   , 0.095 },
179     { 48, 112, 10.624   , 0.094 },
180     { 49, 115, 11.38    , 0.11 },
181     { 50, 119, 10.60    , 0.11 },
182     { 51, 121, 10.40    , 0.12 },
183     { 52, 128,  9.174   , 0.074 },
184     { 53, 127, 11.276   , 0.098 },
185     { 55, 133, 10.98    , 0.25 },
186     { 56, 138, 10.112   , 0.085 },
187     { 57, 139, 10.71    , 0.10 },
188     { 58, 140, 11.501   , 0.087 },
189     { 59, 141, 13.45    , 0.13 },
190     { 60, 144, 12.35    , 0.13 },
191     { 62, 150, 12.22    , 0.17 },
192     { 64, 157, 12.00    , 0.13 },
193     { 65, 159, 12.73    , 0.13 },
194     { 66, 163, 12.29    , 0.18 },
195     { 67, 165, 12.95    , 0.13 },
196     { 68, 167, 13.04    , 0.27 },
197     { 72, 178, 13.03    , 0.21 },
198     { 73, 181, 12.86    , 0.13 },
199     { 74, 184, 12.76    , 0.16 },
200     { 79, 197, 13.35    , 0.10 },
201     { 80, 201, 12.74    , 0.18 },
202     { 81, 205, 13.85    , 0.17 },
203     { 82, 207, 13.295   , 0.071 },
204     { 83, 209, 13.238   , 0.065 },
205     { 90, 232, 12.555   , 0.049 },
206     { 92, 238, 12.592   , 0.035 },
207     { 92, 233, 14.27    , 0.15 },
208     { 92, 235, 13.470   , 0.085 },
209     { 92, 236, 13.90    , 0.40 },
210     { 93, 237, 13.58    , 0.18 },
211     { 94, 239, 13.90    , 0.20 },
212     { 94, 242, 12.86    , 0.19 }
213   };
214   // clang-format on
215 
216   G4double lambda = -1.;
217 
218   std::size_t nCapRates = sizeof(capRates) / sizeof(capRates[0]);
219   for (std::size_t j = 0; j < nCapRates; ++j) {
220     if (capRates[j].Z == Z && capRates[j].A == A) {
221       lambda = capRates[j].cRate / microsecond;
222       break;
223     }
224     // make sure the data is sorted for the next statement to work correctly
225     if (capRates[j].Z > Z) {
226       break;
227     }
228   }
229 
230   if (lambda < 0.) {
231     // ==  Mu capture lifetime (Goulard and Primakoff PRC10(1974)2034.
232 
233     constexpr G4double b0a = -0.03;
234     constexpr G4double b0b = -0.25;
235     constexpr G4double b0c = 3.24;
236     constexpr G4double t1 = 875.e-9;  // -10-> -9  suggested by user
237     G4double r1 = GetMuonZeff(Z);
238     G4double zeff2 = r1 * r1;
239 
240     // ^-4 -> ^-5 suggested by user
241     G4double xmu = zeff2 * 2.663e-5;
242     G4double a2ze = 0.5 * G4double(A) / G4double(Z);
243     G4double r2 = 1.0 - xmu;
244     lambda = t1 * zeff2 * zeff2 * (r2 * r2) * (1.0 - (1.0 - xmu) * .75704)
245              * (a2ze * b0a + 1.0 - (a2ze - 1.0) * b0b
246                 - G4double(2 * (A - Z) + std::abs(a2ze - 1.)) * b0c / G4double(A * 4));
247   }
248 
249   return lambda;
250 }
251 
252 G4double G4MuonicAtomHelper::GetMuonZeff(G4int Z)
253 {
254   // ==  Effective charges from
255   // "Total Nuclear Capture Rates for Negative Muons"
256   // T. Suzuki, D. F. Measday, J.P. Roalsvig Phys.Rev. C35 (1987) 2212
257   // and if not present from
258   // Ford and Wills Nucl Phys 35(1962)295 or interpolated
259 
260   // clang-format off
261   constexpr size_t maxZ = 100;
262   constexpr G4double zeff[maxZ+1] =
263     {  0.,
264        1.00, 1.98, 2.94, 3.89, 4.81, 5.72, 6.61, 7.49, 8.32, 9.14,
265        9.95,10.69,11.48,12.22,12.90,13.64,14.24,14.89,15.53,16.15,
266        16.77,17.38,18.04,18.49,19.06,19.59,20.13,20.66,21.12,21.61,
267        22.02,22.43,22.84,23.24,23.65,24.06,24.47,24.85,25.23,25.61,
268        25.99,26.37,26.69,27.00,27.32,27.63,27.95,28.20,28.42,28.64,
269        28.79,29.03,29.27,29.51,29.75,29.99,30.22,30.36,30.53,30.69,
270        30.85,31.01,31.18,31.34,31.48,31.62,31.76,31.90,32.05,32.19,
271        32.33,32.47,32.61,32.76,32.94,33.11,33.29,33.46,33.64,33.81,
272        34.21,34.18,34.00,34.10,34.21,34.31,34.42,34.52,34.63,34.73,
273        34.84,34.94,35.05,35.16,35.25,35.36,35.46,35.57,35.67,35.78 };
274   // clang-format on
275 
276   if (Z < 0) {
277     Z = 0;
278   }
279   if (Z > G4int(maxZ)) {
280     Z = maxZ;
281   }
282 
283   return zeff[Z];
284 }
285 
286 G4double G4MuonicAtomHelper::GetMuonDecayRate(G4int Z)
287 {
288   // Decay time on K-shell
289   // N.C.Mukhopadhyay Phys. Rep. 30 (1977) 1.
290 
291   // this is the "small Z" approximation formula (2.9)
292   // Lambda(bound)/Lambda(free) = 1-beta(Z*alpha)**2 with beta~=2.5
293   // we assume that Z is Zeff
294 
295   // PDG 2012 muon lifetime value is 2.1969811(22) 10e-6s
296   // which when inverted gives       0.45517005    10e+6/s
297 
298   struct decRate
299   {
300       G4int Z;
301       G4double dRate;
302       G4double dRErr;
303   };
304 
305   // this struct has to be sorted by Z when initialized as we exit the
306   // loop once Z is above the stored value
307 
308   constexpr decRate decRates[] = {{1, 0.4558514, 0.0000151}};
309 
310   G4double lambda = -1.;
311 
312   // size_t nDecRates = sizeof(decRates)/sizeof(decRates[0]);
313   // for (size_t j = 0; j < nDecRates; ++j) {
314   //   if( decRates[j].Z == Z ) {
315   //     lambda = decRates[j].dRate / microsecond;
316   //     break;
317   //   }
318   //   // make sure the data is sorted for the next statement to work
319   //   if (decRates[j].Z > Z) {break;}
320   // }
321 
322   // we'll use the above code once we have more data
323   // since we only have one value we just assign it
324   if (Z == 1) {
325     lambda = decRates[0].dRate / microsecond;
326   }
327 
328   if (lambda < 0.) {
329     constexpr G4double freeMuonDecayRate = 0.45517005 / microsecond;
330     lambda = 1.0;
331     G4double x = GetMuonZeff(Z) * fine_structure_const;
332     lambda -= 2.5 * x * x;
333     lambda *= freeMuonDecayRate;
334   }
335 
336   return lambda;
337 }
338 
339 // From G4MuMinusCaptureCascade
340 G4double G4MuonicAtomHelper::GetKShellEnergy(G4double Z)
341 {
342   // Calculate the Energy of K Mesoatom Level for this Element using
343   // the Energy of Hydrogen Atom taken into account finite size of the
344   // nucleus (V.Ivanchenko)
345   // clang-format off
346   constexpr G4int ListK = 28;
347   constexpr G4double ListZK[ListK] = {
348       1., 2.,  4.,  6.,  8., 11., 14., 17., 18., 21., 24.,
349      26., 29., 32., 38., 40., 41., 44., 49., 53., 55.,
350      60., 65., 70., 75., 81., 85., 92.};
351   constexpr G4double ListKEnergy[ListK] = {
352      0.00275, 0.011, 0.043, 0.098, 0.173, 0.326,
353      0.524, 0.765, 0.853, 1.146, 1.472,
354      1.708, 2.081, 2.475, 3.323, 3.627,
355      3.779, 4.237, 5.016, 5.647, 5.966,
356      6.793, 7.602, 8.421, 9.249, 10.222,
357     10.923,11.984};
358   // clang-format on
359 
360   // Energy with finite size corrections
361   G4double KEnergy = GetLinApprox(ListK, ListZK, ListKEnergy, Z);
362 
363   return KEnergy;
364 }
365 
366 // From G4MuMinusCaptureCascade
367 G4double G4MuonicAtomHelper::GetLinApprox(G4int N, const G4double* const X, const G4double* const Y,
368                                           G4double Xuser)
369 {
370   G4double Yuser;
371   if (Xuser <= X[0])
372     Yuser = Y[0];
373   else if (Xuser >= X[N - 1])
374     Yuser = Y[N - 1];
375   else {
376     G4int i;
377     for (i = 1; i < N; ++i) {
378       if (Xuser <= X[i]) break;
379     }
380 
381     if (Xuser == X[i])
382       Yuser = Y[i];
383     else
384       Yuser = Y[i - 1] + (Y[i] - Y[i - 1]) * (Xuser - X[i - 1]) / (X[i] - X[i - 1]);
385   }
386   return Yuser;
387 }
388