Geant4 11.1.1
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 == 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