Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4MuonDecayChannelWithSpin.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// G4MuonDecayChannelWithSpin class implementation
27//
28// References:
29// - Florian Scheck "Muon Physics", in Physics Reports
30// (Review Section of Physics Letters) 44, No. 4 (1978)
31// 187-248. North-Holland Publishing Company, Amsterdam at page 210 cc.
32// - W.E. Fisher and F. Scheck, Nucl. Phys. B83 (1974) 25.
33
34// Authors: P.Gumplinger and T.MacPhail, 17 August 2004
35// --------------------------------------------------------------------
36
38
39#include "G4DecayProducts.hh"
40#include "G4LorentzVector.hh"
42#include "G4SystemOfUnits.hh"
43#include "Randomize.hh"
44
46 G4double theBR)
47 : G4MuonDecayChannel(theParentName, theBR)
48{}
49
52{
53 if (this != &right) {
56 rbranch = right.rbranch;
57
58 // copy parent name
59 delete parent_name;
60 parent_name = new G4String(*right.parent_name);
61
62 // clear daughters_name array
64
65 // recreate array
67 if (numberOfDaughters > 0) {
69 // copy daughters name
70 for (G4int index = 0; index < numberOfDaughters; ++index) {
71 daughters_name[index] = new G4String(*right.daughters_name[index]);
72 }
73 }
74 }
75 return *this;
76}
77
79{
80 // This version assumes V-A coupling with 1st order radiative correctons,
81 // the standard model Michel parameter values, but
82 // gives incorrect energy spectrum for neutrinos
83
84#ifdef G4VERBOSE
85 if (GetVerboseLevel() > 1) G4cout << "G4MuonDecayChannelWithSpin::DecayIt ";
86#endif
87
90
91 // parent mass
92 G4double parentmass = G4MT_parent->GetPDGMass();
93
94 G4double EMMU = parentmass;
95
96 // daughters'mass
97 G4double daughtermass[3];
98 // G4double sumofdaughtermass = 0.0;
99 for (G4int index = 0; index < 3; ++index) {
100 daughtermass[index] = G4MT_daughters[index]->GetPDGMass();
101 // sumofdaughtermass += daughtermass[index];
102 }
103
104 G4double EMASS = daughtermass[0];
105
106 // create parent G4DynamicParticle at rest
107 G4ThreeVector dummy;
108 auto parentparticle = new G4DynamicParticle(G4MT_parent, dummy, 0.0);
109 // create G4Decayproducts
110 auto products = new G4DecayProducts(*parentparticle);
111 delete parentparticle;
112
113 // calculate electron energy
114
115 G4double michel_rho = 0.75; // Standard Model Michel rho
116 G4double michel_delta = 0.75; // Standard Model Michel delta
117 G4double michel_xsi = 1.00; // Standard Model Michel xsi
118 G4double michel_eta = 0.00; // Standard Model eta
119
120 G4double rndm, x, ctheta;
121
122 G4double FG;
123 G4double FG_max = 2.00;
124
125 G4double W_mue = (EMMU * EMMU + EMASS * EMASS) / (2. * EMMU);
126 G4double x0 = EMASS / W_mue;
127
128 G4double x0_squared = x0 * x0;
129
130 // ***************************************************
131 // x0 <= x <= 1. and -1 <= y <= 1
132 //
133 // F(x,y) = f(x)*g(x,y); g(x,y) = 1.+g(x)*y
134 // ***************************************************
135
136 // ***** sampling F(x,y) directly (brute force) *****
137
138 const std::size_t MAX_LOOP = 10000;
139 for (std::size_t loop_count = 0; loop_count < MAX_LOOP; ++loop_count) {
140 // Sample the positron energy by sampling from F
141
142 rndm = G4UniformRand();
143
144 x = x0 + rndm * (1. - x0);
145
146 G4double x_squared = x * x;
147
148 G4double F_IS, F_AS, G_IS, G_AS;
149
150 F_IS = 1. / 6. * (-2. * x_squared + 3. * x - x0_squared);
151 F_AS = 1. / 6. * std::sqrt(x_squared - x0_squared) * (2. * x - 2. + std::sqrt(1. - x0_squared));
152
153 G_IS = 2. / 9. * (michel_rho - 0.75) * (4. * x_squared - 3. * x - x0_squared);
154 G_IS = G_IS + michel_eta * (1. - x) * x0;
155
156 G_AS = 3. * (michel_xsi - 1.) * (1. - x);
157 G_AS =
158 G_AS + 2. * (michel_xsi * michel_delta - 0.75) * (4. * x - 4. + std::sqrt(1. - x0_squared));
159 G_AS = 1. / 9. * std::sqrt(x_squared - x0_squared) * G_AS;
160
161 F_IS = F_IS + G_IS;
162 F_AS = F_AS + G_AS;
163
164 // *** Radiative Corrections ***
165
166 const G4double omega = std::log(EMMU / EMASS);
167 G4double R_IS = F_c(x, x0, omega);
168
169 G4double F = 6. * F_IS + R_IS / std::sqrt(x_squared - x0_squared);
170
171 // *** Radiative Corrections ***
172
173 G4double R_AS = F_theta(x, x0, omega);
174
175 rndm = G4UniformRand();
176
177 ctheta = 2. * rndm - 1.;
178
179 G4double G = 6. * F_AS - R_AS / std::sqrt(x_squared - x0_squared);
180
181 FG = std::sqrt(x_squared - x0_squared) * F * (1. + (G / F) * ctheta);
182
183 if (FG > FG_max) {
184 G4Exception("G4MuonDecayChannelWithSpin::DecayIt()", "PART113", JustWarning,
185 "Problem in Muon Decay: FG > FG_max");
186 FG_max = FG;
187 }
188
189 rndm = G4UniformRand();
190
191 if (FG >= rndm * FG_max) break;
192 }
193
194 G4double energy = x * W_mue;
195
196 rndm = G4UniformRand();
197
198 G4double phi = twopi * rndm;
199
200 if (energy < EMASS) energy = EMASS;
201
202 // Calculate daughter momentum
203 G4double daughtermomentum[3];
204
205 daughtermomentum[0] = std::sqrt(energy * energy - EMASS * EMASS);
206
207 G4double stheta = std::sqrt(1. - ctheta * ctheta);
208 G4double cphi = std::cos(phi);
209 G4double sphi = std::sin(phi);
210
211 // Coordinates of the decay positron with respect to the muon spin
212 G4double px = stheta * cphi;
213 G4double py = stheta * sphi;
214 G4double pz = ctheta;
215
216 G4ThreeVector direction0(px, py, pz);
217
218 direction0.rotateUz(parent_polarization);
219
220 auto daughterparticle0 =
221 new G4DynamicParticle(G4MT_daughters[0], daughtermomentum[0] * direction0);
222
223 products->PushProducts(daughterparticle0);
224
225 // daughter 1 ,2 (neutrinos)
226 // create neutrinos in the C.M frame of two neutrinos
227 G4double energy2 = parentmass - energy;
228 G4double vmass = std::sqrt((energy2 - daughtermomentum[0]) * (energy2 + daughtermomentum[0]));
229 G4double beta = -1.0 * daughtermomentum[0] / energy2;
230 G4double costhetan = 2. * G4UniformRand() - 1.0;
231 G4double sinthetan = std::sqrt((1.0 - costhetan) * (1.0 + costhetan));
232 G4double phin = twopi * G4UniformRand() * rad;
233 G4double sinphin = std::sin(phin);
234 G4double cosphin = std::cos(phin);
235
236 G4ThreeVector direction1(sinthetan * cosphin, sinthetan * sinphin, costhetan);
237 auto daughterparticle1 = new G4DynamicParticle(G4MT_daughters[1], direction1 * (vmass / 2.));
238 auto daughterparticle2 =
239 new G4DynamicParticle(G4MT_daughters[2], direction1 * (-1.0 * vmass / 2.));
240
241 // boost to the muon rest frame
243 p4 = daughterparticle1->Get4Momentum();
244 p4.boost(direction0.x() * beta, direction0.y() * beta, direction0.z() * beta);
245 daughterparticle1->Set4Momentum(p4);
246 p4 = daughterparticle2->Get4Momentum();
247 p4.boost(direction0.x() * beta, direction0.y() * beta, direction0.z() * beta);
248 daughterparticle2->Set4Momentum(p4);
249 products->PushProducts(daughterparticle1);
250 products->PushProducts(daughterparticle2);
251 daughtermomentum[1] = daughterparticle1->GetTotalMomentum();
252 daughtermomentum[2] = daughterparticle2->GetTotalMomentum();
253
254 // output message
255#ifdef G4VERBOSE
256 if (GetVerboseLevel() > 1) {
257 G4cout << "G4MuonDecayChannelWithSpin::DecayIt ";
258 G4cout << " create decay products in rest frame " << G4endl;
259 G4double TT = daughterparticle0->GetTotalEnergy() + daughterparticle1->GetTotalEnergy()
260 + daughterparticle2->GetTotalEnergy();
261 G4cout << "e " << daughterparticle0->GetTotalEnergy() / MeV << G4endl;
262 G4cout << "nu1" << daughterparticle1->GetTotalEnergy() / MeV << G4endl;
263 G4cout << "nu2" << daughterparticle2->GetTotalEnergy() / MeV << G4endl;
264 G4cout << "total" << (TT - parentmass) / keV << G4endl;
265 if (GetVerboseLevel() > 2) {
266 products->DumpInfo();
267 }
268 }
269#endif
270
271 return products;
272}
273
274G4double G4MuonDecayChannelWithSpin::R_c(G4double x, G4double omega)
275{
276 auto n_max = (G4int)(100. * x);
277
278 if (n_max < 10) n_max = 10;
279
280 G4double L2 = 0.0;
281
282 for (G4int n = 1; n <= n_max; ++n) {
283 L2 += std::pow(x, n) / (n * n);
284 }
285
286 G4double r_c;
287
288 r_c = 2. * L2 - (pi * pi / 3.) - 2.;
289 r_c = r_c + omega * (1.5 + 2. * std::log((1. - x) / x));
290 r_c = r_c - std::log(x) * (2. * std::log(x) - 1.);
291 r_c = r_c + (3. * std::log(x) - 1. - 1. / x) * std::log(1. - x);
292
293 return r_c;
294}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
double z() const
double x() const
double y() const
Hep3Vector & rotateUz(const Hep3Vector &)
HepLorentzVector & boost(double, double, double)
G4DecayProducts * DecayIt(G4double) override
G4MuonDecayChannelWithSpin(const G4String &theParentName, G4double theBR)
G4MuonDecayChannelWithSpin & operator=(const G4MuonDecayChannelWithSpin &)
G4ParticleDefinition ** G4MT_daughters
G4String ** daughters_name
G4int GetVerboseLevel() const
G4ParticleDefinition * G4MT_parent
G4ThreeVector parent_polarization