Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4MuonicAtomHelper.cc
Go to the documentation of this file.
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"
39#include "G4SystemOfUnits.hh"
40#include "Randomize.hh"
41
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(),
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
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
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
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
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
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}
G4double Y(G4double density)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
static G4MuonicAtom * ConstructMuonicAtom(const G4String &name, G4int encoding, G4Ions const *baseion)
static G4double GetKShellEnergy(G4double A)
static G4double GetMuonCaptureRate(G4int Z, G4int A)
static G4double GetLinApprox(G4int N, const G4double *const X, const G4double *const Y, G4double Xuser)
static G4double GetMuonDecayRate(G4int Z)
static G4double GetMuonZeff(G4int Z)
G4double GetPDGMagneticMoment() const
G4int GetAtomicNumber() const
G4int GetAtomicMass() const
const G4String & GetParticleName() const
const G4String & GetParticleSubType() const
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
#define N
Definition crc32.c:57