-
Notifications
You must be signed in to change notification settings - Fork 0
/
absorption.py
143 lines (115 loc) · 3.95 KB
/
absorption.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import operator
import functools
import mpmath
import csv
import halleys_method
ELECTRON_MASS = 0.511 # MeV/c^2
# https://stackoverflow.com/a/7948307
def prod(iterable):
return functools.reduce(operator.mul, iterable, 1)
def product_term(
n,
electron_charge,
positron_charge,
vacuum_permativity,
electron_number_density,
ionisation_potential,
initial_energy,
):
a = (electron_number_density * (positron_charge ** 2) * (electron_charge ** 4)) / \
(8 * mpmath.pi * (vacuum_permativity ** 2))
b = 4 / ionisation_potential
constant_of_integration = mpmath.ei(2 * mpmath.ln(b * initial_energy)) / (a * (b ** 2))
exp_integral_inv = exponential_integral_inverse(a * (b ** 2) * (constant_of_integration - n))
denominator = mpmath.e ** (exp_integral_inv / 2)
energy_proportionality_correction = mpmath.sqrt(ELECTRON_MASS / (2 * (electron_number_density ** 2)))
return 1 - (mpmath.sqrt(b / denominator)) / energy_proportionality_correction
# Calculate the terms from scratch
def product_particle_retention_terms(
distance,
electron_charge,
positron_charge,
vacuum_permativity,
electron_number_density,
ionisation_potential,
initial_energy,
):
print(f"Looping {distance + 1} times")
for n in range(0, distance + 1):
yield product_term(
n,
electron_charge,
positron_charge,
vacuum_permativity,
electron_number_density,
ionisation_potential,
initial_energy
)
def exponential_integral_inverse(p):
initial = None
if p > 3.5:
initial = p * mpmath.ln(p)
elif 0.75 < p <= 3.5:
initial = p + 1
elif -0.5 < p <= 0.75:
initial = 1.45137 + (p * 0.37251)
elif -43.8 < p <= -0.5:
initial = 1 + mpmath.e**(p + mpmath.euler)
else:
return 1
return mpmath.ln(halleys_method.solve_fx(initial, p))
# Returns the particles after annihilation from scratch
def particles_after_annihilation(
initial_particles,
dist,
width,
electron_charge,
positron_charge,
vacuum_permativity,
electron_number_density,
ionisation_potential,
initial_energy,
):
terms = product_particle_retention_terms(
round(dist / mpmath.mpf(width)),
mpmath.mpf(electron_charge),
mpmath.mpf(positron_charge),
mpmath.mpf(vacuum_permativity),
mpmath.mpf(electron_number_density),
mpmath.mpf(ionisation_potential),
mpmath.mpf(initial_energy),
)
term_prod = prod(terms)
print(f"Term prod: {term_prod}")
return mpmath.mpf(initial_particles) * term_prod
def loop_inner(initial_particles, dist, prev_product):
width = mpmath.mpf('1')
electron_charge = mpmath.mpf('-1.602176634e-19')
positron_charge = mpmath.mpf('+1.602176634e-19')
vacuum_permativity = mpmath.mpf("8.85e-12")
electron_number_density = mpmath.mpf("3.333e-23")
ionisation_potential = 75
initial_energy = 4e6
term = product_term(
round(dist / mpmath.mpf(width)),
mpmath.mpf(electron_charge),
mpmath.mpf(positron_charge),
mpmath.mpf(vacuum_permativity),
mpmath.mpf(electron_number_density),
mpmath.mpf(ionisation_potential),
mpmath.mpf(initial_energy),
)
product = term * prev_product
return mpmath.mpf(initial_particles) * product, product
mpmath.mp.dps = 100
previous_product = 1
initial = 10**26
with open('out.csv', 'w') as csvfile:
writer = csv.writer(csvfile, delimiter=';')
for distance in range(0, 10**3 + 1):
print(f"Particles after annihilation, distance = {distance}:")
particles_left, previous_product = loop_inner(initial, distance, previous_product)
mpmath.mp.dps = 26
print(particles_left - initial)
writer.writerow([distance, particles_left - initial])
mpmath.mp.dps = 100