Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4DNAUeharaScreenedRutherfordElasticModel.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
28#include "G4SystemOfUnits.hh"
30#include "G4Exp.hh"
31
32//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
33
34using namespace std;
35
36// #define UEHARA_VERBOSE
37
38//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
39
42 const G4String& nam) : G4VEmModel(nam)
43{
44 // Energy limits of the models
45 intermediateEnergyLimit = 200. * eV;
46 iLowEnergyLimit = 9.*eV;
47 iHighEnergyLimit = 1.*MeV;
48
49 verboseLevel = 0;
50 // Verbosity scale:
51 // 0 = nothing
52 // 1 = warning for energy non-conservation
53 // 2 = details of energy budget
54 // 3 = calculation of cross sections, file openings, sampling of atoms
55 // 4 = entering in methods
56
57 fasterCode = false;
58}
59
60//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
61
62void
64Initialise(const G4ParticleDefinition* particle,
65 const G4DataVector& /*cuts*/)
66{
67 if(isInitialised) { return; }
68 if (verboseLevel > 3)
69 {
70 }
71
72 if(particle->GetParticleName() != "e-")
73 {
74 G4Exception("*** WARNING: the G4DNAUeharaScreenedRutherfordElasticModel is "
75 "not intented to be used with another particle than the electron",
76 "",FatalException,"") ;
77 }
78
79
80 if( verboseLevel>1 )
81 {
82 G4cout << "G4DNAUeharaScreenedRutherfordElasticModel::Initialise()"
83 << G4endl;
84 G4cout << "Energy range: "
85 << LowEnergyLimit() / eV << " eV - "
86 << HighEnergyLimit() / MeV << " MeV"
87 << G4endl;
88 }
89 // Constants for final state by Brenner & Zaider
90 // Note: the instantiation must be placed after if (isInitialised)
91
92 betaCoeff=
93 {
94 7.51525,
95 -0.41912,
96 7.2017E-3,
97 -4.646E-5,
98 1.02897E-7};
99
100 deltaCoeff=
101 {
102 2.9612,
103 -0.26376,
104 4.307E-3,
105 -2.6895E-5,
106 5.83505E-8};
107
108 gamma035_10Coeff=
109 {
110 -1.7013,
111 -1.48284,
112 0.6331,
113 -0.10911,
114 8.358E-3,
115 -2.388E-4};
116
117 gamma10_100Coeff =
118 {
119 -3.32517,
120 0.10996,
121 -4.5255E-3,
122 5.8372E-5,
123 -2.4659E-7};
124
125 gamma100_200Coeff=
126 {
127 2.4775E-2,
128 -2.96264E-5,
129 -1.20655E-7};
130
131 // Initialize water density pointer
132 fpWaterDensity =
134 GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
135
137 isInitialised = true;
138}
139
140//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
141
144CrossSectionPerVolume(const G4Material* material,
145 const G4ParticleDefinition* /*particleDefinition*/,
146 G4double ekin,
147 G4double,
148 G4double)
149{
150#ifdef UEHARA_VERBOSE
151 if (verboseLevel > 3)
152 {
153 G4cout
154 << "Calling CrossSectionPerVolume() of G4DNAUeharaScreenedRutherfordElasticModel"
155 << G4endl;
156 }
157#endif
158
159 // Calculate total cross section for model
160
161 G4double sigma = 0.;
162 if(ekin < iLowEnergyLimit || ekin > iHighEnergyLimit) { return sigma; }
163
164 G4double waterDensity = (*fpWaterDensity)[material->GetIndex()];
165
166 G4double z = 7.42; // FROM PMB 37 (1992) 1841-1858 p1842
167 G4double n = ScreeningFactor(ekin,z);
168 G4double crossSection = RutherfordCrossSection(ekin, z);
169 sigma = pi * crossSection / (n * (n + 1.));
170
171#ifdef UEHARA_VERBOSE
172 if (verboseLevel > 2)
173 {
174 G4cout << "__________________________________" << G4endl;
175 G4cout << "=== G4DNAUeharaScreenedRutherfordElasticModel - XS INFO START"
176 << G4endl;
177 G4cout << "=== Kinetic energy(eV)=" << ekin/eV
178 << " particle : " << particleDefinition->GetParticleName() << G4endl;
179 G4cout << "=== Cross section per water molecule (cm^2)=" << sigma/cm/cm
180 << G4endl;
181 G4cout << "=== Cross section per water molecule (cm^-1)="
182 << sigma*waterDensity/(1./cm) << G4endl;
183 G4cout << "=== G4DNAUeharaScreenedRutherfordElasticModel - XS INFO END"
184 << G4endl;
185 }
186#endif
187
188 return sigma*waterDensity;
189}
190
191//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
192
194G4DNAUeharaScreenedRutherfordElasticModel::RutherfordCrossSection(G4double k,
195 G4double z)
196{
197 //
198 // e^4 / K + m_e c^2 \^2
199 // sigma_Ruth(K) = Z (Z+1) -------------------- | --------------------- |
200 // (4 pi epsilon_0)^2 \ K * (K + 2 m_e c^2) /
201 //
202 // Where K is the electron non-relativistic kinetic energy
203 //
204 // NIM 155, pp. 145-156, 1978
205
206 G4double length = (e_squared * (k + electron_mass_c2))
207 / (4 * pi * epsilon0 * k * (k + 2 * electron_mass_c2));
208 G4double cross = z * (z + 1) * length * length;
209
210 return cross;
211}
212
213//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
214
215G4double G4DNAUeharaScreenedRutherfordElasticModel::ScreeningFactor(G4double k,
216 G4double z)
217{
218 // From Phys Med Biol 37 (1992) 1841-1858
219 // Z=7.42 for water
220
221 const G4double constK(1.7E-5);
222
223 G4double beta2;
224 beta2 = 1. - 1. / ((1. + k / electron_mass_c2) * (1. + k / electron_mass_c2));
225
226 G4double etaC;
227 if (k < 50 * keV)
228 etaC = 1.198;
229 else
230 etaC = 1.13 + 3.76 * (z * z / (137 * 137 * beta2));
231
232 G4double numerator = etaC * constK * std::pow(z, 2. / 3.);
233
234 k /= electron_mass_c2;
235
236 G4double denominator = k * (2 + k);
237
238 G4double value = 0.;
239 if (denominator > 0.)
240 value = numerator / denominator; // form 3
241
242 return value;
243}
244
245//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
246
247void
249SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
250 const G4MaterialCutsCouple* /*couple*/,
251 const G4DynamicParticle* aDynamicElectron,
252 G4double,
253 G4double)
254{
255#ifdef UEHARA_VERBOSE
256 if (verboseLevel > 3)
257 {
258 G4cout
259 << "Calling SampleSecondaries() of G4DNAUeharaScreenedRutherfordElasticModel"
260 << G4endl;
261 }
262#endif
263
264 G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
265 if(electronEnergy0 < iLowEnergyLimit || electronEnergy0 > iHighEnergyLimit)
266 return;
267
268 G4double cosTheta = 0.;
269
270 if (electronEnergy0<intermediateEnergyLimit)
271 {
272#ifdef UEHARA_VERBOSE
273 if (verboseLevel > 3)
274 G4cout << "---> Using Brenner & Zaider model" << G4endl;
275#endif
276 cosTheta = BrennerZaiderRandomizeCosTheta(electronEnergy0);
277 }
278 else //if (electronEnergy0>=intermediateEnergyLimit)
279 {
280#ifdef UEHARA_VERBOSE
281 if (verboseLevel > 3)
282 G4cout << "---> Using Screened Rutherford model" << G4endl;
283#endif
284 G4double z = 7.42; // FROM PMB 37 (1992) 1841-1858 p1842
285 cosTheta = ScreenedRutherfordRandomizeCosTheta(electronEnergy0,z);
286 }
287
288 G4double phi = 2. * pi * G4UniformRand();
289
290 G4ThreeVector zVers = aDynamicElectron->GetMomentumDirection();
291 G4ThreeVector xVers = zVers.orthogonal();
292 G4ThreeVector yVers = zVers.cross(xVers);
293
294 G4double xDir = std::sqrt(1. - cosTheta*cosTheta);
295 G4double yDir = xDir;
296 xDir *= std::cos(phi);
297 yDir *= std::sin(phi);
298
299 G4ThreeVector zPrimeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
300
302
304}
305
306//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
307
309G4DNAUeharaScreenedRutherfordElasticModel::
310BrennerZaiderRandomizeCosTheta(G4double k)
311{
312 // d sigma_el 1 beta(K)
313 // ------------ (K) ~ --------------------------------- + ---------------------------------
314 // d Omega (1 + 2 gamma(K) - cos(theta))^2 (1 + 2 delta(K) + cos(theta))^2
315 //
316 // Maximum is < 1/(4 gamma(K)^2) + beta(K)/((2+2delta(K))^2)
317 //
318 // Phys. Med. Biol. 29 N.4 (1983) 443-447
319
320 // gamma(K), beta(K) and delta(K) are polynomials with coefficients for energy measured in eV
321
322 k /= eV;
323
324 G4double beta = G4Exp(CalculatePolynomial(k, betaCoeff));
325 G4double delta = G4Exp(CalculatePolynomial(k, deltaCoeff));
326 G4double gamma;
327
328 if (k > 100.)
329 {
330 gamma = CalculatePolynomial(k, gamma100_200Coeff);
331 // Only in this case it is not the exponent of the polynomial
332 } else
333 {
334 if (k > 10)
335 {
336 gamma = G4Exp(CalculatePolynomial(k, gamma10_100Coeff));
337 }
338 else
339 {
340 gamma = G4Exp(CalculatePolynomial(k, gamma035_10Coeff));
341 }
342 }
343
344 // ***** Original method
345
346 if (fasterCode == false)
347 {
348 G4double oneOverMax = 1.
349 / (1. / (4. * gamma * gamma)
350 + beta / ((2. + 2. * delta) * (2. + 2. * delta)));
351
352 G4double cosTheta = 0.;
353 G4double leftDenominator = 0.;
354 G4double rightDenominator = 0.;
355 G4double fCosTheta = 0.;
356
357 do
358 {
359 cosTheta = 2. * G4UniformRand()- 1.;
360
361 leftDenominator = (1. + 2.*gamma - cosTheta);
362 rightDenominator = (1. + 2.*delta + cosTheta);
363 if ( (leftDenominator * rightDenominator) != 0. )
364 {
365 fCosTheta = oneOverMax * (1./(leftDenominator*leftDenominator)
366 + beta/(rightDenominator*rightDenominator));
367 }
368 }
369 while (fCosTheta < G4UniformRand());
370
371 return cosTheta;
372 }
373
374 // ***** Alternative method using cumulative probability
375
376 else // if (fasterCode)
377 {
378
379 //
380 // modified by Shogo OKADA @ KEK, JP, 2016.2.27(Sat.)
381 //
382 // An integral of differential cross-section formula shown above this member function
383 // (integral variable: cos(theta), integral interval: [-1, x]) is as follows:
384 //
385 // 1.0 + x beta * (1 + x)
386 // I = --------------------- + ---------------------- (1)
387 // (a - x) * (a + 1.0) (b + x) * (b - 1.0)
388 //
389 // where a = 1.0 + 2.0 * gamma(K), b = 1.0 + 2.0 * delta(K)
390 //
391 // Then, a cumulative probability (cp) is as follows:
392 //
393 // cp 1.0 + x beta * (1 + x)
394 // ---- = --------------------- + ---------------------- (2)
395 // S (a - x) * (a + 1.0) (b + x) * (b - 1.0)
396 //
397 // where 1/S is the integral of differnetical cross-section (1) on interval [-1, 1]
398 //
399 // 1 2.0 2.0 * beta
400 // --- = ----------------------- + ----------------------- (3)
401 // S (a - 1.0) * (a + 1.0) (b + 1.0) * (b - 1.0)
402 //
403 // x is calculated from the quadratic equation derived from (2) and (3):
404 //
405 // A * x^2 + B * x + C = 0
406 //
407 // where A, B, anc C are coefficients of the equation:
408 // A = S * {(b - 1.0) - beta * (a + 1.0)} + cp * (a + 1.0) * (b - 1.0),
409 // B = S * {(b - 1.0) * (b + 1.0) + beta * (a - 1.0) * (a + 1.0)} - cp * (a + 1.0) * (b - 1.0) * (a - b)
410 // C = S * {b * (b - 1.0) + beta * a * (a + 1.0)} - cp * (a + 1.0) * (b - 1.0) * ab
411 //
412
413 // sampling cumulative probability
414 G4double cp = G4UniformRand();
415
416 G4double a = 1.0 + 2.0 * gamma;
417 G4double b = 1.0 + 2.0 * delta;
418 G4double a1 = a - 1.0;
419 G4double a2 = a + 1.0;
420 G4double b1 = b - 1.0;
421 G4double b2 = b + 1.0;
422 G4double c1 = a - b;
423 G4double c2 = a * b;
424
425 G4double S = 2.0 / (a1 * a2) + 2.0 * beta / (b1 * b2); S = 1.0 / S;
426
427 // coefficients for the quadratic equation
428 G4double A = S * (b1 - beta * a2) + cp * a2 * b1;
429 G4double B = S * (b1 * b2 + beta * a1 * a2) - cp * a2 * b1 * c1;
430 G4double C = S * (b * b1 + beta * a * a2) - cp * a2 * b1 * c2;
431
432 // calculate cos(theta)
433 return (-1.0 * B + std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
434
435 /*
436 G4double cosTheta = -1;
437 G4double cumul = 0;
438 G4double value = 0;
439 G4double leftDenominator = 0.;
440 G4double rightDenominator = 0.;
441
442 // Number of integration steps in the -1,1 range
443 G4int iMax=200;
444
445 G4double random = G4UniformRand();
446
447 // Cumulate differential cross section
448 for (G4int i=0; i<iMax; i++)
449 {
450 cosTheta = -1 + i*2./(iMax-1);
451 leftDenominator = (1. + 2.*gamma - cosTheta);
452 rightDenominator = (1. + 2.*delta + cosTheta);
453 if ( (leftDenominator * rightDenominator) != 0. )
454 {
455 cumul = cumul + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator));
456 }
457 }
458
459 // Select cosTheta
460 for (G4int i=0; i<iMax; i++)
461 {
462 cosTheta = -1 + i*2./(iMax-1);
463 leftDenominator = (1. + 2.*gamma - cosTheta);
464 rightDenominator = (1. + 2.*delta + cosTheta);
465 if (cumul !=0 && (leftDenominator * rightDenominator) != 0.)
466 value = value + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator)) / cumul;
467 if (random < value) break;
468 }
469
470 return cosTheta;
471 */
472 }
473
474 //return 0.;
475
476}
477
478//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
479
481G4DNAUeharaScreenedRutherfordElasticModel::
482CalculatePolynomial(G4double k,
483 std::vector<G4double>& vec)
484{
485 // Sum_{i=0}^{size-1} vector_i k^i
486 //
487 // Phys. Med. Biol. 29 N.4 (1983) 443-447
488
489 G4double result = 0.;
490 size_t size = vec.size();
491
492 while (size > 0)
493 {
494 size--;
495
496 result *= k;
497 result += vec[size];
498 }
499
500 return result;
501}
502
503//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
504
506G4DNAUeharaScreenedRutherfordElasticModel::
507ScreenedRutherfordRandomizeCosTheta(G4double k,
508 G4double z)
509{
510
511 // d sigma_el sigma_Ruth(K)
512 // ------------ (K) ~ -----------------------------
513 // d Omega (1 + 2 n(K) - cos(theta))^2
514 //
515 // We extract cos(theta) distributed as (1 + 2 n(K) - cos(theta))^-2
516 //
517 // Maximum is for theta=0: 1/(4 n(K)^2) (When n(K) is positive, that is always
518 // satisfied within the validity of the process)
519 //
520 // Phys. Med. Biol. 45 (2000) 3171-3194
521
522 // ***** Original method
523
524 if (fasterCode == false)
525 {
526 G4double n = ScreeningFactor(k, z);
527
528 G4double oneOverMax = (4. * n * n);
529
530 G4double cosTheta = 0.;
531 G4double fCosTheta;
532
533 do
534 {
535 cosTheta = 2. * G4UniformRand()- 1.;
536 fCosTheta = (1 + 2.*n - cosTheta);
537 if (fCosTheta !=0.) fCosTheta = oneOverMax / (fCosTheta*fCosTheta);
538 }
539 while (fCosTheta < G4UniformRand());
540
541 return cosTheta;
542 }
543
544 // ***** Alternative method using cumulative probability
545 else // if (fasterCode)
546 {
547
548 //
549 // modified by Shogo OKADA @ KEK, JP, 2016.2.27(Sat.)
550 //
551 // The cumulative probability (cp) is calculated by integrating
552 // the differential cross-section fomula with cos(theta):
553 //
554 // n(K) * (1.0 + cos(theta))
555 // cp = ---------------------------------
556 // 1.0 + 2.0 * n(K) - cos(theta)
557 //
558 // Then, cos(theta) is as follows:
559 //
560 // cp * (1.0 + 2.0 * n(K)) - n(K)
561 // cos(theta) = --------------------------------
562 // n(k) + cp
563 //
564 // where, K is kinetic energy, n(K) is screeing factor, and cp is cumulative probability
565 //
566
567 G4double n = ScreeningFactor(k, z);
568 G4double cp = G4UniformRand();
569 G4double numerator = cp * (1.0 + 2.0 * n) - n;
570 G4double denominator = n + cp;
571 return numerator / denominator;
572
573 /*
574 G4double cosTheta = -1;
575 G4double cumul = 0;
576 G4double value = 0;
577 G4double n = ScreeningFactor(k, z);
578 G4double fCosTheta;
579
580 // Number of integration steps in the -1,1 range
581 G4int iMax=200;
582
583 G4double random = G4UniformRand();
584
585 // Cumulate differential cross section
586 for (G4int i=0; i<iMax; i++)
587 {
588 cosTheta = -1 + i*2./(iMax-1);
589 fCosTheta = (1 + 2.*n - cosTheta);
590 if (fCosTheta !=0.) cumul = cumul + 1./(fCosTheta*fCosTheta);
591 }
592
593 // Select cosTheta
594 for (G4int i=0; i<iMax; i++)
595 {
596 cosTheta = -1 + i*2./(iMax-1);
597 fCosTheta = (1 + 2.*n - cosTheta);
598 if (cumul !=0.) value = value + (1./(fCosTheta*fCosTheta)) / cumul;
599 if (random < value) break;
600 }
601 return cosTheta;
602 */
603 }
604
605 //return 0.;
606}
G4double S(G4double temp)
G4double B(G4double temperature)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
double G4double
Definition: G4Types.hh:83
const G4double A[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
Hep3Vector orthogonal() const
Hep3Vector cross(const Hep3Vector &) const
static G4DNAMolecularMaterial * Instance()
G4DNAUeharaScreenedRutherfordElasticModel(const G4ParticleDefinition *p=0, const G4String &nam="DNAUeharaScreenedRutherfordElasticModel")
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax) override
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
size_t GetIndex() const
Definition: G4Material.hh:255
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
Definition: G4Material.cc:691
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
const G4String & GetParticleName() const
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:124
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:641
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:634