Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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)
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 // if (fasterCode)
377
378 //
379 // modified by Shogo OKADA @ KEK, JP, 2016.2.27(Sat.)
380 //
381 // An integral of differential cross-section formula shown above this member function
382 // (integral variable: cos(theta), integral interval: [-1, x]) is as follows:
383 //
384 // 1.0 + x beta * (1 + x)
385 // I = --------------------- + ---------------------- (1)
386 // (a - x) * (a + 1.0) (b + x) * (b - 1.0)
387 //
388 // where a = 1.0 + 2.0 * gamma(K), b = 1.0 + 2.0 * delta(K)
389 //
390 // Then, a cumulative probability (cp) is as follows:
391 //
392 // cp 1.0 + x beta * (1 + x)
393 // ---- = --------------------- + ---------------------- (2)
394 // S (a - x) * (a + 1.0) (b + x) * (b - 1.0)
395 //
396 // where 1/S is the integral of differnetical cross-section (1) on interval [-1, 1]
397 //
398 // 1 2.0 2.0 * beta
399 // --- = ----------------------- + ----------------------- (3)
400 // S (a - 1.0) * (a + 1.0) (b + 1.0) * (b - 1.0)
401 //
402 // x is calculated from the quadratic equation derived from (2) and (3):
403 //
404 // A * x^2 + B * x + C = 0
405 //
406 // where A, B, anc C are coefficients of the equation:
407 // A = S * {(b - 1.0) - beta * (a + 1.0)} + cp * (a + 1.0) * (b - 1.0),
408 // B = S * {(b - 1.0) * (b + 1.0) + beta * (a - 1.0) * (a + 1.0)} - cp * (a + 1.0) * (b - 1.0) * (a - b)
409 // C = S * {b * (b - 1.0) + beta * a * (a + 1.0)} - cp * (a + 1.0) * (b - 1.0) * ab
410 //
411
412 // sampling cumulative probability
413 G4double cp = G4UniformRand();
414
415 G4double a = 1.0 + 2.0 * gamma;
416 G4double b = 1.0 + 2.0 * delta;
417 G4double a1 = a - 1.0;
418 G4double a2 = a + 1.0;
419 G4double b1 = b - 1.0;
420 G4double b2 = b + 1.0;
421 G4double c1 = a - b;
422 G4double c2 = a * b;
423
424 G4double S = 2.0 / (a1 * a2) + 2.0 * beta / (b1 * b2); S = 1.0 / S;
425
426 // coefficients for the quadratic equation
427 G4double A = S * (b1 - beta * a2) + cp * a2 * b1;
428 G4double B = S * (b1 * b2 + beta * a1 * a2) - cp * a2 * b1 * c1;
429 G4double C = S * (b * b1 + beta * a * a2) - cp * a2 * b1 * c2;
430
431 // calculate cos(theta)
432 return (-1.0 * B + std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
433
434 /*
435 G4double cosTheta = -1;
436 G4double cumul = 0;
437 G4double value = 0;
438 G4double leftDenominator = 0.;
439 G4double rightDenominator = 0.;
440
441 // Number of integration steps in the -1,1 range
442 G4int iMax=200;
443
444 G4double random = G4UniformRand();
445
446 // Cumulate differential cross section
447 for (G4int i=0; i<iMax; i++)
448 {
449 cosTheta = -1 + i*2./(iMax-1);
450 leftDenominator = (1. + 2.*gamma - cosTheta);
451 rightDenominator = (1. + 2.*delta + cosTheta);
452 if ( (leftDenominator * rightDenominator) != 0. )
453 {
454 cumul = cumul + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator));
455 }
456 }
457
458 // Select cosTheta
459 for (G4int i=0; i<iMax; i++)
460 {
461 cosTheta = -1 + i*2./(iMax-1);
462 leftDenominator = (1. + 2.*gamma - cosTheta);
463 rightDenominator = (1. + 2.*delta + cosTheta);
464 if (cumul !=0 && (leftDenominator * rightDenominator) != 0.)
465 value = value + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator)) / cumul;
466 if (random < value) break;
467 }
468
469 return cosTheta;
470 */
471
472
473 //return 0.;
474
475}
476
477//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
478
480G4DNAUeharaScreenedRutherfordElasticModel::
481CalculatePolynomial(G4double k,
482 std::vector<G4double>& vec)
483{
484 // Sum_{i=0}^{size-1} vector_i k^i
485 //
486 // Phys. Med. Biol. 29 N.4 (1983) 443-447
487
488 G4double result = 0.;
489 size_t size = vec.size();
490
491 while (size > 0)
492 {
493 size--;
494
495 result *= k;
496 result += vec[size];
497 }
498
499 return result;
500}
501
502//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
503
505G4DNAUeharaScreenedRutherfordElasticModel::
506ScreenedRutherfordRandomizeCosTheta(G4double k,
507 G4double z)
508{
509
510 // d sigma_el sigma_Ruth(K)
511 // ------------ (K) ~ -----------------------------
512 // d Omega (1 + 2 n(K) - cos(theta))^2
513 //
514 // We extract cos(theta) distributed as (1 + 2 n(K) - cos(theta))^-2
515 //
516 // Maximum is for theta=0: 1/(4 n(K)^2) (When n(K) is positive, that is always
517 // satisfied within the validity of the process)
518 //
519 // Phys. Med. Biol. 45 (2000) 3171-3194
520
521 // ***** Original method
522
523 if (!fasterCode)
524 {
525 G4double n = ScreeningFactor(k, z);
526
527 G4double oneOverMax = (4. * n * n);
528
529 G4double cosTheta = 0.;
530 G4double fCosTheta;
531
532 do
533 {
534 cosTheta = 2. * G4UniformRand()- 1.;
535 fCosTheta = (1 + 2.*n - cosTheta);
536 if (fCosTheta !=0.) fCosTheta = oneOverMax / (fCosTheta*fCosTheta);
537 }
538 while (fCosTheta < G4UniformRand());
539
540 return cosTheta;
541 }
542
543 // ***** Alternative method using cumulative probability
544 // if (fasterCode)
545
546 //
547 // modified by Shogo OKADA @ KEK, JP, 2016.2.27(Sat.)
548 //
549 // The cumulative probability (cp) is calculated by integrating
550 // the differential cross-section fomula with cos(theta):
551 //
552 // n(K) * (1.0 + cos(theta))
553 // cp = ---------------------------------
554 // 1.0 + 2.0 * n(K) - cos(theta)
555 //
556 // Then, cos(theta) is as follows:
557 //
558 // cp * (1.0 + 2.0 * n(K)) - n(K)
559 // cos(theta) = --------------------------------
560 // n(k) + cp
561 //
562 // where, K is kinetic energy, n(K) is screeing factor, and cp is cumulative probability
563 //
564
565 G4double n = ScreeningFactor(k, z);
566 G4double cp = G4UniformRand();
567 G4double numerator = cp * (1.0 + 2.0 * n) - n;
568 G4double denominator = n + cp;
569 return numerator / denominator;
570
571 /*
572 G4double cosTheta = -1;
573 G4double cumul = 0;
574 G4double value = 0;
575 G4double n = ScreeningFactor(k, z);
576 G4double fCosTheta;
577
578 // Number of integration steps in the -1,1 range
579 G4int iMax=200;
580
581 G4double random = G4UniformRand();
582
583 // Cumulate differential cross section
584 for (G4int i=0; i<iMax; i++)
585 {
586 cosTheta = -1 + i*2./(iMax-1);
587 fCosTheta = (1 + 2.*n - cosTheta);
588 if (fCosTheta !=0.) cumul = cumul + 1./(fCosTheta*fCosTheta);
589 }
590
591 // Select cosTheta
592 for (G4int i=0; i<iMax; i++)
593 {
594 cosTheta = -1 + i*2./(iMax-1);
595 fCosTheta = (1 + 2.*n - cosTheta);
596 if (cumul !=0.) value = value + (1./(fCosTheta*fCosTheta)) / cumul;
597 if (random < value) break;
598 }
599 return cosTheta;
600 */
601
602
603 //return 0.;
604}
G4double C(G4double temp)
G4double S(G4double temp)
G4double B(G4double temperature)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
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:67
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=nullptr, 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
std::size_t GetIndex() const
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
const G4String & GetParticleName() const
G4ParticleChangeForGamma * GetParticleChangeForGamma()
G4double LowEnergyLimit() const
G4double HighEnergyLimit() const