Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4MuPairProductionModel.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//
27// -------------------------------------------------------------------
28//
29// GEANT4 Class file
30//
31//
32// File name: G4MuPairProductionModel
33//
34// Author: Vladimir Ivanchenko on base of Laszlo Urban code
35//
36// Creation date: 24.06.2002
37//
38// Modifications:
39//
40// 04-12-02 Change G4DynamicParticle constructor in PostStep (V.Ivanchenko)
41// 23-12-02 Change interface in order to move to cut per region (V.Ivanchenko)
42// 24-01-03 Fix for compounds (V.Ivanchenko)
43// 27-01-03 Make models region aware (V.Ivanchenko)
44// 13-02-03 Add model (V.Ivanchenko)
45// 06-06-03 Fix in cross section calculation for high energy (V.Ivanchenko)
46// 20-10-03 2*xi in ComputeDDMicroscopicCrossSection (R.Kokoulin)
47// 8 integration points in ComputeDMicroscopicCrossSection
48// 12-01-04 Take min cut of e- and e+ not its sum (V.Ivanchenko)
49// 10-02-04 Update parameterisation using R.Kokoulin model (V.Ivanchenko)
50// 28-04-04 For complex materials repeat calculation of max energy for each
51// material (V.Ivanchenko)
52// 01-11-04 Fix bug inside ComputeDMicroscopicCrossSection (R.Kokoulin)
53// 08-04-05 Major optimisation of internal interfaces (V.Ivantchenko)
54// 03-08-05 Add SetParticle method (V.Ivantchenko)
55// 23-10-05 Add protection in sampling of e+e- pair energy needed for
56// low cuts (V.Ivantchenko)
57// 13-02-06 Add ComputeCrossSectionPerAtom (mma)
58// 24-04-07 Add protection in SelectRandomAtom method (V.Ivantchenko)
59// 12-05-06 Updated sampling (use cut) in SelectRandomAtom (A.Bogdanov)
60// 11-10-07 Add ignoreCut flag (V.Ivanchenko)
61
62//
63// Class Description:
64//
65//
66// -------------------------------------------------------------------
67//
68//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
69//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
70
73#include "G4SystemOfUnits.hh"
74#include "G4EmParameters.hh"
75#include "G4Electron.hh"
76#include "G4Positron.hh"
77#include "G4MuonMinus.hh"
78#include "G4MuonPlus.hh"
79#include "Randomize.hh"
80#include "G4Material.hh"
81#include "G4Element.hh"
82#include "G4ElementVector.hh"
85#include "G4ModifiedMephi.hh"
86#include "G4Log.hh"
87#include "G4Exp.hh"
88#include <iostream>
89#include <fstream>
90
91//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
92
93// static members
94//
95static const G4double ak1 = 6.9;
96static const G4double ak2 = 1.0;
97static const G4int nzdat = 5;
98static const G4int zdat[5] = {1, 4, 13, 29, 92};
99
100static const G4double xgi[] =
101{ 0.0198550717512320, 0.1016667612931865, 0.2372337950418355, 0.4082826787521750,
102 0.5917173212478250, 0.7627662049581645, 0.8983332387068135, 0.9801449282487680 };
103
104static const G4double wgi[] =
105{ 0.0506142681451880, 0.1111905172266870, 0.1568533229389435, 0.1813418916891810,
106 0.1813418916891810, 0.1568533229389435, 0.1111905172266870, 0.0506142681451880 };
107
108//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
109
110using namespace std;
111
113 const G4String& nam)
114 : G4VEmModel(nam),
115 particle(nullptr),
116 factorForCross(4.*fine_structure_const*fine_structure_const
117 *classic_electr_radius*classic_electr_radius/(3.*pi)),
118 sqrte(sqrt(G4Exp(1.))),
119 currentZ(0),
120 fParticleChange(nullptr),
121 minPairEnergy(4.*electron_mass_c2),
122 lowestKinEnergy(1.0*GeV),
123 nYBinPerDecade(4),
124 nbiny(1000),
125 nbine(0),
126 ymin(-5.),
127 dy(0.005),
128 fTableToFile(false)
129{
131
134
135 particleMass = lnZ = z13 = z23 = 0.;
136
137 // setup lowest limit dependent on particle mass
138 if(p) {
139 SetParticle(p);
140 lowestKinEnergy = std::max(lowestKinEnergy,p->GetPDGMass()*8.0);
141 }
143 emax = 10.*TeV;
145}
146
147//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
148
150{}
151
152//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
153
156 G4double cut)
157{
158 return std::max(lowestKinEnergy,cut);
159}
160
161//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
162
164 const G4DataVector& cuts)
165{
166 SetParticle(p);
168
169 // for low-energy application this process should not work
170 if(lowestKinEnergy >= HighEnergyLimit()) { return; }
171
172 // define scale of internal table for each thread only once
173 if(0 == nbine) {
174 emin = std::max(lowestKinEnergy, LowEnergyLimit());
175 emax = std::max(HighEnergyLimit(), emin*2);
176 nbine = size_t(nYBinPerDecade*std::log10(emax/emin));
177 if(nbine < 3) { nbine = 3; }
178
180 dy = -ymin/G4double(nbiny);
181 }
182
183 if(IsMaster() && p == particle) {
184 if(!fElementData) {
187 if(dataFile) { dataFile = RetrieveTables(); }
188 if(!dataFile) { MakeSamplingTables(); }
189 if(fTableToFile) { StoreTables(); }
190 }
192 }
193}
194
195//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
196
198 G4VEmModel* masterModel)
199{
202 fElementData = masterModel->GetElementData();
203 }
204}
205
206//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
207
209 const G4Material* material,
211 G4double kineticEnergy,
212 G4double cutEnergy)
213{
214 G4double dedx = 0.0;
215 if (cutEnergy <= minPairEnergy || kineticEnergy <= lowestKinEnergy)
216 { return dedx; }
217
218 const G4ElementVector* theElementVector = material->GetElementVector();
219 const G4double* theAtomicNumDensityVector =
220 material->GetAtomicNumDensityVector();
221
222 // loop for elements in the material
223 for (size_t i=0; i<material->GetNumberOfElements(); ++i) {
224 G4double Z = (*theElementVector)[i]->GetZ();
225 G4double tmax = MaxSecondaryEnergyForElement(kineticEnergy, Z);
226 G4double loss = ComputMuPairLoss(Z, kineticEnergy, cutEnergy, tmax);
227 dedx += loss*theAtomicNumDensityVector[i];
228 }
229 dedx = std::max(dedx, 0.0);
230 return dedx;
231}
232
233//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
234
236 G4double tkin,
237 G4double cutEnergy,
238 G4double tmax)
239{
240 G4double loss = 0.0;
241
242 G4double cut = std::min(cutEnergy,tmax);
243 if(cut <= minPairEnergy) { return loss; }
244
245 // calculate the rectricted loss
246 // numerical integration in log(PairEnergy)
248 G4double bbb = G4Log(cut);
249
250 G4int kkk = (G4int)((bbb-aaa)/ak1+ak2);
251 if (kkk > 8) { kkk = 8; }
252 else if (kkk < 1) { kkk = 1; }
253
254 G4double hhh = (bbb-aaa)/(G4double)kkk;
255 G4double x = aaa;
256
257 for (G4int l=0 ; l<kkk; ++l) {
258 for (G4int ll=0; ll<8; ++ll)
259 {
260 G4double ep = G4Exp(x+xgi[ll]*hhh);
261 loss += wgi[ll]*ep*ep*ComputeDMicroscopicCrossSection(tkin, Z, ep);
262 }
263 x += hhh;
264 }
265 loss *= hhh;
266 loss = std::max(loss, 0.0);
267 return loss;
268}
269
270//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
271
273 G4double tkin,
274 G4double Z,
275 G4double cutEnergy)
276{
277 G4double cross = 0.;
279 G4double cut = std::max(cutEnergy, minPairEnergy);
280 if (tmax <= cut) { return cross; }
281
282 // G4double ak1=6.9 ;
283 // G4double ak2=1.0 ;
284 G4double aaa = G4Log(cut);
285 G4double bbb = G4Log(tmax);
286 G4int kkk = (G4int)((bbb-aaa)/ak1 + ak2);
287 if(kkk > 8) { kkk = 8; }
288 else if (kkk < 1) { kkk = 1; }
289
290 G4double hhh = (bbb-aaa)/G4double(kkk);
291 G4double x = aaa;
292
293 for(G4int l=0; l<kkk; ++l)
294 {
295 for(G4int i=0; i<8; ++i)
296 {
297 G4double ep = G4Exp(x + xgi[i]*hhh);
298 cross += ep*wgi[i]*ComputeDMicroscopicCrossSection(tkin, Z, ep);
299 }
300 x += hhh;
301 }
302
303 cross *= hhh;
304 cross = std::max(cross, 0.0);
305 return cross;
306}
307
308//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
309
311 G4double tkin,
312 G4double Z,
313 G4double pairEnergy)
314// Calculates the differential (D) microscopic cross section
315// using the cross section formula of R.P. Kokoulin (18/01/98)
316// Code modified by R.P. Kokoulin, V.N. Ivanchenko (27/01/04)
317{
318 static const G4double bbbtf= 183. ;
319 static const G4double bbbh = 202.4 ;
320 static const G4double g1tf = 1.95e-5 ;
321 static const G4double g2tf = 5.3e-5 ;
322 static const G4double g1h = 4.4e-5 ;
323 static const G4double g2h = 4.8e-5 ;
324
325 if (pairEnergy <= 4.0 * electron_mass_c2)
326 return 0.0;
327
328 G4double totalEnergy = tkin + particleMass;
329 G4double residEnergy = totalEnergy - pairEnergy;
330
331 if (residEnergy <= 0.75*sqrte*z13*particleMass)
332 return 0.0;
333
334 G4double a0 = 1.0 / (totalEnergy * residEnergy);
335 G4double alf = 4.0 * electron_mass_c2 / pairEnergy;
336 G4double rt = sqrt(1.0 - alf);
337 G4double delta = 6.0 * particleMass * particleMass * a0;
338 G4double tmnexp = alf/(1.0 + rt) + delta*rt;
339
340 if(tmnexp >= 1.0) { return 0.0; }
341
342 G4double tmn = G4Log(tmnexp);
343
344 G4double massratio = particleMass/electron_mass_c2;
345 G4double massratio2 = massratio*massratio;
346 G4double inv_massratio2 = 1.0 / massratio2;
347
348 // zeta calculation
349 G4double bbb,g1,g2;
350 if( Z < 1.5 ) { bbb = bbbh ; g1 = g1h ; g2 = g2h ; }
351 else { bbb = bbbtf; g1 = g1tf; g2 = g2tf; }
352
353 G4double zeta = 0.0;
354 G4double z1exp = totalEnergy / (particleMass + g1*z23*totalEnergy);
355
356 // 35.221047195922 is the root of zeta1(x) = 0.073 * log(x) - 0.26, so the
357 // condition below is the same as zeta1 > 0.0, but without calling log(x)
358 if (z1exp > 35.221047195922)
359 {
360 G4double z2exp = totalEnergy / (particleMass + g2*z13*totalEnergy);
361 zeta = (0.073 * G4Log(z1exp) - 0.26) / (0.058 * G4Log(z2exp) - 0.14);
362 }
363
364 G4double z2 = Z*(Z+zeta);
365 G4double screen0 = 2.*electron_mass_c2*sqrte*bbb/(z13*pairEnergy);
366 G4double beta = 0.5*pairEnergy*pairEnergy*a0;
367 G4double xi0 = 0.5*massratio2*beta;
368
369 // Gaussian integration in ln(1-ro) ( with 8 points)
370 G4double rho[8];
371 G4double rho2[8];
372 G4double xi[8];
373 G4double xi1[8];
374 G4double xii[8];
375
376 for (G4int i = 0; i < 8; ++i)
377 {
378 rho[i] = G4Exp(tmn*xgi[i]) - 1.0; // rho = -asymmetry
379 rho2[i] = rho[i] * rho[i];
380 xi[i] = xi0*(1.0-rho2[i]);
381 xi1[i] = 1.0 + xi[i];
382 xii[i] = 1.0 / xi[i];
383 }
384
385 G4double ye1[8];
386 G4double ym1[8];
387
388 G4double b40 = 4.0 * beta;
389 G4double b62 = 6.0 * beta + 2.0;
390
391 for (G4int i = 0; i < 8; ++i)
392 {
393 G4double yeu = (b40 + 5.0) + (b40 - 1.0) * rho2[i];
394 G4double yed = b62 * G4Log(3.0 + xii[i]) + (2.0 * beta - 1.0) * rho2[i] - b40;
395
396 G4double ymu = b62 * (1.0 + rho2[i]) + 6.0;
397 G4double ymd = (b40 + 3.0) * (1.0 + rho2[i]) * G4Log(3.0 + xi[i]) + 2.0 - 3.0 * rho2[i];
398
399 ye1[i] = 1.0 + yeu / yed;
400 ym1[i] = 1.0 + ymu / ymd;
401 }
402
403 G4double be[8];
404 G4double bm[8];
405
406 for(G4int i = 0; i < 8; ++i)
407 {
408 if(xi[i] <= 1000.0) {
409 be[i] = ((2.0 + rho2[i]) * (1.0 + beta) + xi[i] * (3.0 + rho2[i])) *
410 G4Log(1.0 + xii[i]) + (1.0 - rho2[i] - beta) / xi1[i] - (3.0 + rho2[i]);
411 } else {
412 be[i] = 0.5 * (3.0 - rho2[i] + 2.0 * beta * (1.0 + rho2[i])) * xii[i];
413 }
414
415 if(xi[i] >= 0.001) {
416 G4double a10 = (1.0 + 2.0 * beta) * (1.0 - rho2[i]);
417 bm[i] = ((1.0 + rho2[i]) * (1.0 + 1.5 * beta) - a10 * xii[i]) * G4Log(xi1[i]) +
418 xi[i] * (1.0 - rho2[i] - beta) / xi1[i] + a10;
419 } else {
420 bm[i] = 0.5 * (5.0 - rho2[i] + beta * (3.0 + rho2[i])) * xi[i];
421 }
422 }
423
424 G4double sum = 0.0;
425
426 for (G4int i = 0; i < 8; ++i)
427 {
428 G4double screen = screen0*xi1[i]/(1.0-rho2[i]) ;
429 G4double ale = G4Log(bbb/z13*sqrt(xi1[i]*ye1[i])/(1.+screen*ye1[i])) ;
430 G4double cre = 0.5*G4Log(1.+2.25*z23*xi1[i]*ye1[i]*inv_massratio2) ;
431
432 G4double fe = (ale-cre)*be[i];
433 fe *= (fe > 0.0);
434
435 G4double alm_crm = G4Log(bbb*massratio/(1.5*z23*(1.+screen*ym1[i])));
436 G4double fm = alm_crm*bm[i];
437 fm *= (fm > 0.0) * inv_massratio2;
438
439 sum += wgi[i]*(1.0 + rho[i])*(fe+fm);
440 }
441
442 return -tmn*sum*factorForCross*z2*residEnergy/(totalEnergy*pairEnergy);
443}
444
445//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
446
449 G4double kineticEnergy,
451 G4double cutEnergy,
452 G4double maxEnergy)
453{
454 G4double cross = 0.0;
455 if (kineticEnergy <= lowestKinEnergy) { return cross; }
456
457 G4double maxPairEnergy = MaxSecondaryEnergyForElement(kineticEnergy, Z);
458 G4double tmax = std::min(maxEnergy, maxPairEnergy);
459 G4double cut = std::max(cutEnergy, minPairEnergy);
460 if (cut >= tmax) { return cross; }
461
462 cross = ComputeMicroscopicCrossSection(kineticEnergy, Z, cut);
463 if(tmax < kineticEnergy) {
464 cross -= ComputeMicroscopicCrossSection(kineticEnergy, Z, tmax);
465 }
466 return cross;
467}
468
469//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
470
471void G4MuPairProductionModel::MakeSamplingTables()
472{
474
475 for (G4int iz=0; iz<nzdat; ++iz) {
476
477 G4double Z = zdat[iz];
479 G4double kinEnergy = emin;
480
481 for (size_t it=0; it<=nbine; ++it) {
482
483 pv->PutY(it, G4Log(kinEnergy/MeV));
484 G4double maxPairEnergy = MaxSecondaryEnergyForElement(kinEnergy, Z);
485 /*
486 G4cout << "it= " << it << " E= " << kinEnergy
487 << " " << particle->GetParticleName()
488 << " maxE= " << maxPairEnergy << " minE= " << minPairEnergy
489 << " ymin= " << ymin << G4endl;
490 */
491 G4double coef = G4Log(minPairEnergy/kinEnergy)/ymin;
492 G4double ymax = G4Log(maxPairEnergy/kinEnergy)/coef;
493 G4double fac = (ymax - ymin)/dy;
494 size_t imax = (size_t)fac;
495 fac -= (G4double)imax;
496
497 G4double xSec = 0.0;
498 G4double x = ymin;
499 /*
500 G4cout << "Z= " << currentZ << " z13= " << z13
501 << " mE= " << maxPairEnergy << " ymin= " << ymin
502 << " dy= " << dy << " c= " << coef << G4endl;
503 */
504 // start from zero
505 pv->PutValue(0, it, 0.0);
506 if(0 == it) { pv->PutX(nbiny, 0.0); }
507
508 for (size_t i=0; i<nbiny; ++i) {
509
510 if(0 == it) { pv->PutX(i, x); }
511
512 if(i < imax) {
513 G4double ep = kinEnergy*G4Exp(coef*(x + dy*0.5));
514
515 // not multiplied by interval, because table
516 // will be used only for sampling
517 //G4cout << "i= " << i << " x= " << x << "E= " << kinEnergy
518 // << " Egamma= " << ep << G4endl;
519 xSec += ep*ComputeDMicroscopicCrossSection(kinEnergy, Z, ep);
520
521 // last bin before the kinematic limit
522 } else if(i == imax) {
523 G4double ep = kinEnergy*G4Exp(coef*(x + fac*dy*0.5));
524 xSec += ep*fac*ComputeDMicroscopicCrossSection(kinEnergy, Z, ep);
525 }
526 pv->PutValue(i + 1, it, xSec);
527 x += dy;
528 }
529 kinEnergy *= factore;
530
531 // to avoid precision lost
532 if(it+1 == nbine) { kinEnergy = emax; }
533 }
534 fElementData->InitialiseForElement(zdat[iz], pv);
535 }
536}
537
538//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
539
541 std::vector<G4DynamicParticle*>* vdp,
542 const G4MaterialCutsCouple* couple,
543 const G4DynamicParticle* aDynamicParticle,
544 G4double tmin,
545 G4double tmax)
546{
547 G4double kinEnergy = aDynamicParticle->GetKineticEnergy();
548 //G4cout << "------- G4MuPairProductionModel::SampleSecondaries E(MeV)= "
549 // << kinEnergy << " "
550 // << aDynamicParticle->GetDefinition()->GetParticleName() << G4endl;
551 G4double totalEnergy = kinEnergy + particleMass;
552 G4double totalMomentum =
553 sqrt(kinEnergy*(kinEnergy + 2.0*particleMass));
554
555 G4ThreeVector partDirection = aDynamicParticle->GetMomentumDirection();
556
557 // select randomly one element constituing the material
558 const G4Element* anElement = SelectRandomAtom(couple,particle,kinEnergy);
559
560 // define interval of energy transfer
561 G4double maxPairEnergy = MaxSecondaryEnergyForElement(kinEnergy,
562 anElement->GetZ());
563 G4double maxEnergy = std::min(tmax, maxPairEnergy);
564 G4double minEnergy = std::max(tmin, minPairEnergy);
565
566 if(minEnergy >= maxEnergy) { return; }
567 //G4cout << "emin= " << minEnergy << " emax= " << maxEnergy
568 // << " minPair= " << minPairEnergy << " maxpair= " << maxPairEnergy
569 // << " ymin= " << ymin << " dy= " << dy << G4endl;
570
571 G4double coeff = G4Log(minPairEnergy/kinEnergy)/ymin;
572
573 // compute limits
574 G4double yymin = G4Log(minEnergy/kinEnergy)/coeff;
575 G4double yymax = G4Log(maxEnergy/kinEnergy)/coeff;
576
577 //G4cout << "yymin= " << yymin << " yymax= " << yymax << G4endl;
578
579 // units should not be used, bacause table was built without
580 G4double logTkin = G4Log(kinEnergy/MeV);
581
582 // sample e-e+ energy, pair energy first
583
584 // select sample table via Z
585 G4int iz1(0), iz2(0);
586 for(G4int iz=0; iz<nzdat; ++iz) {
587 if(currentZ == zdat[iz]) {
588 iz1 = iz2 = currentZ;
589 break;
590 } else if(currentZ < zdat[iz]) {
591 iz2 = zdat[iz];
592 if(iz > 0) { iz1 = zdat[iz-1]; }
593 else { iz1 = iz2; }
594 break;
595 }
596 }
597 if(0 == iz1) { iz1 = iz2 = zdat[nzdat-1]; }
598
599 G4double pairEnergy = 0.0;
600 G4int count = 0;
601 //G4cout << "start loop Z1= " << iz1 << " Z2= " << iz2 << G4endl;
602 do {
603 ++count;
604 // sampling using only one random number
605 G4double rand = G4UniformRand();
606
607 G4double x = FindScaledEnergy(iz1, rand, logTkin, yymin, yymax);
608 if(iz1 != iz2) {
609 G4double x2 = FindScaledEnergy(iz2, rand, logTkin, yymin, yymax);
610 G4double lz1= nist->GetLOGZ(iz1);
611 G4double lz2= nist->GetLOGZ(iz2);
612 //G4cout << count << ". x= " << x << " x2= " << x2
613 // << " Z1= " << iz1 << " Z2= " << iz2 << G4endl;
614 x += (x2 - x)*(lnZ - lz1)/(lz2 - lz1);
615 }
616 //G4cout << "x= " << x << " coeff= " << coeff << G4endl;
617 pairEnergy = kinEnergy*G4Exp(x*coeff);
618
619 // Loop checking, 03-Aug-2015, Vladimir Ivanchenko
620 } while((pairEnergy < minEnergy || pairEnergy > maxEnergy) && 10 > count);
621
622 //G4cout << "## pairEnergy(GeV)= " << pairEnergy/GeV
623 // << " Etot(GeV)= " << totalEnergy/GeV << G4endl;
624
625 // sample r=(E+-E-)/pairEnergy ( uniformly .....)
626 G4double rmax =
627 (1.-6.*particleMass*particleMass/(totalEnergy*(totalEnergy-pairEnergy)))
628 *sqrt(1.-minPairEnergy/pairEnergy);
629 G4double r = rmax * (-1.+2.*G4UniformRand()) ;
630
631 // compute energies from pairEnergy,r
632 G4double eEnergy = (1.-r)*pairEnergy*0.5;
633 G4double pEnergy = pairEnergy - eEnergy;
634
635 // Sample angles
636 G4ThreeVector eDirection, pDirection;
637 //
638 GetAngularDistribution()->SamplePairDirections(aDynamicParticle,
639 eEnergy, pEnergy,
640 eDirection, pDirection);
641 // create G4DynamicParticle object for e+e-
642 eEnergy = std::max(eEnergy - CLHEP::electron_mass_c2, 0.0);
643 pEnergy = std::max(pEnergy - CLHEP::electron_mass_c2, 0.0);
644 G4DynamicParticle* aParticle1 =
645 new G4DynamicParticle(theElectron,eDirection,eEnergy);
646 G4DynamicParticle* aParticle2 =
647 new G4DynamicParticle(thePositron,pDirection,pEnergy);
648 // Fill output vector
649 vdp->push_back(aParticle1);
650 vdp->push_back(aParticle2);
651
652 // primary change
653 kinEnergy -= pairEnergy;
654 partDirection *= totalMomentum;
655 partDirection -= (aParticle1->GetMomentum() + aParticle2->GetMomentum());
656 partDirection = partDirection.unit();
657
658 // if energy transfer is higher than threshold (very high by default)
659 // then stop tracking the primary particle and create a new secondary
660 if (pairEnergy > SecondaryThreshold()) {
663 G4DynamicParticle* newdp =
664 new G4DynamicParticle(particle, partDirection, kinEnergy);
665 vdp->push_back(newdp);
666 } else { // continue tracking the primary e-/e+ otherwise
669 }
670 //G4cout << "-- G4MuPairProductionModel::SampleSecondaries done" << G4endl;
671}
672
673//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
674
675void G4MuPairProductionModel::DataCorrupted(G4int Z, G4double logTkin) const
676{
678 ed << "G4ElementData is not properly initialized Z= " << Z
679 << " Ekin(MeV)= " << G4Exp(logTkin)
680 << " IsMasterThread= " << IsMaster()
681 << " Model " << GetName();
682 G4Exception("G4MuPairProductionModel::()","em0033",FatalException,
683 ed,"");
684}
685
686//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
687
688void G4MuPairProductionModel::StoreTables() const
689{
690 for (G4int iz=0; iz<nzdat; ++iz) {
691 G4int Z = zdat[iz];
693 if(!pv) {
694 DataCorrupted(Z, 1.0);
695 return;
696 }
697 std::ostringstream ss;
698 ss << "mupair/" << particle->GetParticleName() << Z << ".dat";
699 std::ofstream outfile(ss.str());
700 pv->Store(outfile);
701 }
702}
703
704//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
705
706G4bool G4MuPairProductionModel::RetrieveTables()
707{
708 char* path = std::getenv("G4LEDATA");
709 G4String dir("");
710 if (path) {
711 std::ostringstream ost;
712 ost << path << "/mupair/";
713 dir = ost.str();
714 } else {
715 dir = "./mupair/";
716 }
717
718 for (G4int iz=0; iz<nzdat; ++iz) {
719 G4double Z = zdat[iz];
721 std::ostringstream ss;
722 ss << dir << particle->GetParticleName() << Z << ".dat";
723 std::ifstream infile(ss.str(), std::ios::in);
724 if(!pv->Retrieve(infile)) {
725 delete pv;
726 return false;
727 }
729 }
730 return true;
731}
732
733//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
734
735
std::vector< G4Element * > G4ElementVector
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:179
const G4double a0
G4fissionEvent * fe
G4double G4Log(G4double x)
Definition: G4Log.hh:226
@ fStopAndKill
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
G4ThreeVector GetMomentum() const
static G4Electron * Electron()
Definition: G4Electron.cc:93
void InitialiseForElement(G4int Z, G4PhysicsVector *v)
G4Physics2DVector * GetElement2DData(G4int Z)
G4double GetZ() const
Definition: G4Element.hh:130
static G4EmParameters * Instance()
G4bool RetrieveMuDataFromFile() const
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:188
size_t GetNumberOfElements() const
Definition: G4Material.hh:184
const G4double * GetAtomicNumDensityVector() const
Definition: G4Material.hh:214
G4double ComputeMicroscopicCrossSection(G4double tkin, G4double Z, G4double cut)
void SetParticle(const G4ParticleDefinition *)
G4ParticleDefinition * thePositron
G4double ComputMuPairLoss(G4double Z, G4double tkin, G4double cut, G4double tmax)
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kineticEnergy, G4double Z, G4double A, G4double cutEnergy, G4double maxEnergy) override
G4MuPairProductionModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="muPairProd")
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
virtual G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy) override
virtual void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) override
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
virtual G4double ComputeDMicroscopicCrossSection(G4double tkin, G4double Z, G4double pairEnergy)
const G4ParticleDefinition * particle
virtual G4double MinPrimaryEnergy(const G4Material *, const G4ParticleDefinition *, G4double) override
G4ParticleChangeForLoss * fParticleChange
G4double MaxSecondaryEnergyForElement(G4double kineticEnergy, G4double Z)
G4ParticleDefinition * theElectron
G4double GetLOGZ(G4int Z) const
static G4NistManager * Instance()
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedMomentumDirection(const G4ThreeVector &dir)
const G4String & GetParticleName() const
G4bool Retrieve(std::ifstream &fIn)
void PutY(std::size_t idy, G4double value)
void Store(std::ofstream &fOut) const
void PutValue(std::size_t idx, std::size_t idy, G4double value)
void PutX(std::size_t idx, G4double value)
static G4Positron * Positron()
Definition: G4Positron.cc:93
virtual void SamplePairDirections(const G4DynamicParticle *dp, G4double elecKinEnergy, G4double posiKinEnergy, G4ThreeVector &dirElectron, G4ThreeVector &dirPositron, G4int Z=0, const G4Material *mat=nullptr)
void SetElementSelectors(std::vector< G4EmElementSelector * > *)
Definition: G4VEmModel.hh:842
G4VEmAngularDistribution * GetAngularDistribution()
Definition: G4VEmModel.hh:611
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:652
std::vector< G4EmElementSelector * > * GetElementSelectors()
Definition: G4VEmModel.hh:834
G4bool IsMaster() const
Definition: G4VEmModel.hh:736
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:645
const G4Element * SelectRandomAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.hh:570
G4ElementData * fElementData
Definition: G4VEmModel.hh:438
void SetAngularDistribution(G4VEmAngularDistribution *)
Definition: G4VEmModel.hh:618
const G4String & GetName() const
Definition: G4VEmModel.hh:827
void InitialiseElementSelectors(const G4ParticleDefinition *, const G4DataVector &)
Definition: G4VEmModel.cc:148
G4double SecondaryThreshold() const
Definition: G4VEmModel.hh:680
G4ElementData * GetElementData()
Definition: G4VEmModel.hh:853
G4ParticleChangeForLoss * GetParticleChangeForLoss()
Definition: G4VEmModel.cc:118
void ProposeTrackStatus(G4TrackStatus status)