Skip to content

Commit 2f5952a

Browse files
authored
Merge pull request #2 from skumblex/dev
Dev
2 parents 8742863 + 7191b15 commit 2f5952a

25 files changed

+618
-372
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
/plots/*.pdf
44
/plots/*
55

6+
tmp/*
7+
68
# Byte-compiled / optimized / DLL files
79
__pycache__
810
*.py[cod]

CHANGELOG

Lines changed: 0 additions & 11 deletions
This file was deleted.

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
**A generiC fRamework fOr Photodisintegration Of LIght elementS**
44

55
![Language: Python3](https://img.shields.io/badge/language-Python3-blue.svg?style=flat-square)
6-
![Version: 1.1](https://img.shields.io/badge/current_version-1.1-blue.svg?style=flat-square)
6+
![Version: 1.2](https://img.shields.io/badge/current_version-1.2-blue.svg?style=flat-square)
77

88
When using this code, please cite the following papers
99

@@ -19,6 +19,14 @@ The remarkable agreement between observations of the primordial light element ab
1919

2020
# Changelog
2121

22+
v1.2
23+
- Speed improvements when running non-thermal nucleosynthesis (by a factor 7)
24+
- Modified the directory structure by moving ./data to ./acropolis/data to transform ACROPOLIS into a proper package, which can be installed via ``python3 setup.py install --user`` (also putting the executables ``decay`` and ``annihilation`` into your ``PATH``)
25+
- Added the decay of neutrons and tritium to the calculation
26+
- Included a new script 'tools/create_sm_cosmo_file.py' which allows to generate the file cosmo_file.dat for sm.tar.gz and can easily be modified by the user
27+
- For AnnihilationModel, it is now possible to freely choose the dark-matter density parameter (default is 0.12)
28+
29+
2230
v1.1
2331
- For the source terms it is now possible to specify arbitrary monochromatic and continuous contributions, meaning that the latter one is no longer limited to only final-state radiation of photons
2432
- By including additional JIT compilation steps, the runtime without database files was drastically increased (by approximately a factor 15)
@@ -33,7 +41,7 @@ v1.0
3341

3442
# Install the dependencies
3543

36-
ACROPOLIS is written in Python3.7 (remember that Python2 is dead) and depends on the following packages (older versions might work, but have not been thoroughly testes)
44+
ACROPOLIS is written in Python3.7 (remember that Python2 is dead) and depends on the following packages (older versions might work, but have not been thoroughly tested)
3745

3846
- NumPy (> 1.19.1)
3947
- SciPy (>1.5.2)
@@ -47,9 +55,19 @@ python3 -m pip install numpy, scipy, numba --user
4755

4856
If these dependencies conflict with those for other programs in your work environment, it is strongly advised to utilise the capabilities of Python's virtual environments.
4957

58+
# Install ACROPOLIS using pip
59+
60+
ACROPOLIS also comes with a ``setup.py`` file, which allows to simply install it via pip. To do this, simply run the following command in the root of the cloned repository
61+
62+
```
63+
python3 -m pip install .
64+
```
65+
66+
Afterwards, the different packages of ACROPOLIS can be imported into our own code, just like any other python package. The above command, also copies the executable ``decay`` and ``annihilation`` into your ``PATH`` and makes sure that all dependencies are fulfilled.
67+
5068
# Use the example models
5169

52-
Within the ACROPOLIS main directory there are two executables, ``decay`` and ``annihilation``, which wrap the scenarios discussed in section 4.1 and section 4.2 from the manual, respectively. Both of these files need to be called with six command-line arguments each, a list of which can be obtained by running the command of choice without any arguments at all. On that note, the following command runs the process of photodisintegration for an unstable mediator with a mass of 10MeV and a lifetime of 1e5s that decays exclusively into photons and has an abundance of 1e-10 relative to photons at a reference temperature of 10MeV
70+
Within the ACROPOLIS main directory there are two executables, ``decay`` and ``annihilation``, which wrap the scenarios discussed in section 4.1 and section 4.2 from the manual, respectively. Both of these files need to be called with six command-line arguments each, a list of which can be obtained by running the command of choice without any arguments at all. On that note, the following command runs the process of photodisintegration for an unstable mediator with a mass of 10MeV and a lifetime of 1e5s that decays exclusively into photons and has an abundance of 1e-10 relative to photons at a reference temperature of 10MeV (**if you installed ACROPOLIS using pip, you can drop the ``./`` at the beginning, since the executables are in your ``PATH``.**)
5371

5472
```
5573
./decay 10 1e5 10 1e-10 0 1

acropolis/cache.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# functools
2+
from functools import wraps
3+
4+
5+
def cached_member(f_uncached):
6+
# Define the cache as a dictionary
7+
cache = {}
8+
cT = {"_": -1.}
9+
10+
# Define the wrapper function
11+
@wraps(f_uncached)
12+
def f_cached(*args):
13+
T = args[-1]
14+
# Drop the first argument 'self'
15+
# ! only for member functions !
16+
pargs = args[1:]
17+
18+
# For each new temperature,
19+
# clear the cache and start over
20+
if T != cT["_"]:
21+
cT["_"] = T
22+
cache.clear()
23+
24+
if pargs not in cache:
25+
cache[pargs] = f_uncached(*args)
26+
27+
return cache[pargs]
28+
29+
return f_cached

acropolis/cascade.py

Lines changed: 38 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# math
22
from math import pi, log, log10, exp, sqrt
3-
# functools
4-
from functools import wraps
53
# numpy
64
import numpy as np
75
# scipy
@@ -13,41 +11,18 @@
1311
import warnings
1412

1513
# db
16-
from .db import import_data_from_db
17-
from .db import in_rate_db, interp_rate_db
14+
from acropolis.db import import_data_from_db
15+
from acropolis.db import in_rate_db, interp_rate_db
16+
# cache
17+
from acropolis.cache import cached_member
1818
# pprint
19-
from .pprint import print_warning, print_error
19+
from acropolis.pprint import print_warning, print_error
2020
# params
21-
from .params import me, me2, alpha, re
22-
from .params import zeta3, pi2
23-
from .params import Emin
24-
from .params import approx_zero, eps, Ephb_T_max, E_EC_cut
25-
from .params import NE_pd, NE_min
26-
27-
28-
def _cached(f_uncached):
29-
# Define the cache as a dictionary
30-
cache = {}
31-
cT = {"_": -1.}
32-
33-
# Define the wrapper function
34-
@wraps(f_uncached)
35-
def f_cached(*args):
36-
T = args[-1]
37-
pargs = args[1:]
38-
39-
# For each new temperature,
40-
# clear the cache and start over
41-
if T != cT["_"]:
42-
cT["_"] = T
43-
cache.clear()
44-
45-
if pargs not in cache:
46-
cache[pargs] = f_uncached(*args)
47-
48-
return cache[pargs]
49-
50-
return f_cached
21+
from acropolis.params import me, me2, alpha, re
22+
from acropolis.params import zeta3, pi2
23+
from acropolis.params import Emin
24+
from acropolis.params import approx_zero, eps, Ephb_T_max, E_EC_cut
25+
from acropolis.params import NE_pd, NE_min
5126

5227

5328
# _ReactionWrapperScaffold ####################################################
@@ -79,8 +54,9 @@ def _JIT_G(Ee, Eph, Ephb):
7954
# ATTENTION: This range is absent in 'astro-ph/9412055'
8055
# Here we adopt the original result from
8156
# 'link.springer.com/content/pdf/10.1007/BF01005624.pdf'
82-
Ee_lim_m = ( Eph + Ephb - (Eph - Ephb)*sqrt( 1. - me2/( Eph*Ephb ) ) )/2.
83-
Ee_lim_p = ( Eph + Ephb + (Eph - Ephb)*sqrt( 1. - me2/( Eph*Ephb ) ) )/2.
57+
dE_sqrt = (Eph - Ephb)*sqrt( 1. - me2/( Eph*Ephb ) )
58+
Ee_lim_m = ( Eph + Ephb - dE_sqrt )/2.
59+
Ee_lim_p = ( Eph + Ephb + dE_sqrt )/2.
8460

8561
if not ( me < Ee_lim_m <= Ee <= Ee_lim_p ):
8662
# CHECKED to never happen, since the intergration
@@ -104,23 +80,23 @@ def _JIT_G(Ee, Eph, Ephb):
10480
# _PhotonReactionWrapper ######################################################
10581

10682
@nb.jit(cache=True)
107-
def _JIT_PH_rate_pair_creation(y, x, T):
83+
def _JIT_ph_rate_pair_creation(y, x, T):
10884
# Define beta as a function of y
10985
b = sqrt(1. - 4.*me2/y)
11086

11187
# Define the kernel for the 2d-integral; y = s, x = epsilon_bar
11288
# f/E^2 s \sigma_DP
113-
return ( 1./(pi**2) )/( exp(x/T) - 1. ) * y * .5*pi*(re**2.)*(1.-b**2.)*( (3.-b**4.)*log( (1.+b)/(1.-b) ) - 2.*b*(2.-b**2.) )
11489
# ATTENTION: There is an error in 'astro-ph/9412055.pdf'
11590
# In the integration for \bar{\epsilon}_\gamma the lower
11691
# limit of integration should be me^2/\epsilon_\gamma
11792
# (the written limit is unitless, which must be wrong)
11893
# This limit is a consequence of the constraint on
11994
# the center-of-mass energy
95+
return ( 1./(pi**2) )/( exp(x/T) - 1. ) * y * .5*pi*(re**2.)*(1.-b**2.)*( (3.-b**4.)*log( (1.+b)/(1.-b) ) - 2.*b*(2.-b**2.) )
12096

12197

12298
@nb.jit(cache=True)
123-
def _JIT_PH_kernel_inverse_compton(y, E, Ep, T):
99+
def _JIT_ph_kernel_inverse_compton(y, E, Ep, T):
124100
# Return the integrand for the 1d-integral in log-space; x = Ephb
125101
x = exp(y)
126102

@@ -130,21 +106,21 @@ def _JIT_PH_kernel_inverse_compton(y, E, Ep, T):
130106
# _ElectronReactionWrapper ####################################################
131107

132108
@nb.jit(cache=True)
133-
def _JIT_EL_rate_inverse_compton(y, x, E, T):
109+
def _JIT_el_rate_inverse_compton(y, x, E, T):
134110
# Return the integrand for the 2d-integral; y = Eph, x = Ephb
135111
return _JIT_F(y, E, x)*x/( (pi**2.)*(exp(x/T) - 1.) )
136112

137113

138114
@nb.jit(cache=True)
139-
def _JIT_EL_kernel_inverse_compton(y, E, Ep, T):
115+
def _JIT_el_kernel_inverse_compton(y, E, Ep, T):
140116
# Define the integrand for the 1d-integral in log-space; x = Ephb
141117
x = exp(y)
142118

143119
return _JIT_F(Ep+x-E, Ep, x)*( x/(pi**2) )/( exp(x/T) - 1. ) * x
144120

145121

146122
@nb.jit(cache=True)
147-
def _JIT_EL_kernel_pair_creation(y, E, Ep, T):
123+
def _JIT_el_kernel_pair_creation(y, E, Ep, T):
148124
# Define the integrand for the 1d-integral in log-space; x = Ephb
149125
x = exp(y)
150126

@@ -184,7 +160,7 @@ def _JIT_dsdE_Z2(Ee, Eph):
184160

185161
@nb.jit(cache=True)
186162
def _JIT_set_spectra(F, i, Fi, cond):
187-
F[:,i] = Fi
163+
F[:, i] = Fi
188164
# In the strongly compressed regime, manually
189165
# set the photon spectrum to zero in order to
190166
# avoid floating-point errors
@@ -329,7 +305,7 @@ def _rate_pair_creation(self, E, T):
329305
# In general, the threshold is E ~ me^2/(22*T)
330306
# However, here we use a slighlty smaller threshold
331307
# in order to guarantee a smooth transition
332-
if E < me2/(30.*T):
308+
if E < me2/(50.*T):
333309
return 0.
334310

335311
# Define the integration limits from the
@@ -340,13 +316,13 @@ def _rate_pair_creation(self, E, T):
340316
# CHECKED!
341317

342318
# Perform the integration in lin space
343-
I_fso_E2 = dblquad(_JIT_PH_rate_pair_creation, llim, ulim, lambda x: 4.*me2, lambda x: 4.*E*x, epsrel=eps, epsabs=0, args=(T,))
319+
I_fso_E2 = dblquad(_JIT_ph_rate_pair_creation, llim, ulim, lambda x: 4.*me2, lambda x: 4.*E*x, epsrel=eps, epsabs=0, args=(T,))
344320

345321
return I_fso_E2[0]/( 8.*E**2. )
346322

347323

348324
def _rate_pair_creation_db(self, E, T):
349-
if E < me2/(30.*T):
325+
if E < me2/(50.*T):
350326
return 0.
351327

352328
E_log, T_log = log10(E), log10(T)
@@ -385,7 +361,7 @@ def _kernel_compton(self, E, Ep, T):
385361

386362

387363
# INVERSE COMPTON SCATTERING ##############################################
388-
@_cached
364+
@cached_member
389365
def _kernel_inverse_compton(self, E, Ep, T):
390366
# Incorporate the non-generic integration limit as
391367
# the algorithm requires Ep > E and not Ep > E + me
@@ -410,7 +386,7 @@ def _kernel_inverse_compton(self, E, Ep, T):
410386
return 0.
411387

412388
# Perform the integration in log space
413-
I_fF_E = quad(_JIT_PH_kernel_inverse_compton, log(llim), log(ulim), epsrel=eps, epsabs=0, args=(E, Ep, T))
389+
I_fF_E = quad(_JIT_ph_kernel_inverse_compton, log(llim), log(ulim), epsrel=eps, epsabs=0, args=(E, Ep, T))
414390

415391
# ATTENTION: Kawasaki considers a combined e^+/e^- spectrum
416392
# Therefore the factor 2 should not be there in our case
@@ -445,7 +421,7 @@ def __init__(self, Y0, eta, db):
445421
# T is the temperature of the background photons
446422

447423
# INVERSE COMPTON SCATTERING ##############################################
448-
@_cached
424+
@cached_member
449425
def _rate_inverse_compton(self, E, T):
450426
# Define the upper limit for the integration over x
451427
ulim = min( E - me2/(4.*E), Ephb_T_max*T )
@@ -459,7 +435,7 @@ def _rate_inverse_compton(self, E, T):
459435
# ATTENTION:
460436
# The integral over \epsilon_\gamma should start at 0.
461437
# In fact, for \epsilon_\gamma > \epsilon_e, we have q < 0.
462-
I_fF_E = dblquad(_JIT_EL_rate_inverse_compton, 0., ulim, lambda x: x, lambda x: 4.*x*E*E/( me2 + 4.*x*E ), epsrel=eps, epsabs=0, args=(E, T))
438+
I_fF_E = dblquad(_JIT_el_rate_inverse_compton, 0., ulim, lambda x: x, lambda x: 4.*x*E*E/( me2 + 4.*x*E ), epsrel=eps, epsabs=0, args=(E, T))
463439

464440
return 2.*pi*(alpha**2.)*I_fF_E[0]/(E**2.)
465441

@@ -483,7 +459,7 @@ def total_rate(self, E, T):
483459
# T is the temperature of the background photons
484460

485461
# INVERSE COMPTON SCATTERING ##############################################
486-
@_cached
462+
@cached_member
487463
def _kernel_inverse_compton(self, E, Ep, T):
488464
# E == Ep leads to a divergence in
489465
# the Bose-Einstein distribution
@@ -492,11 +468,12 @@ def _kernel_inverse_compton(self, E, Ep, T):
492468
return 0.
493469

494470
# Calculate appropriate integration limits
495-
pf = .25*me2/Ep - E # <= 0.
496-
qf = .25*me2*(Ep-E)/Ep # >= 0.
471+
pf = .25*me2/Ep - E # <= 0.
472+
qf = .25*me2*(Ep-E)/Ep # >= 0.
497473

498-
z1 = -pf/2. - sqrt( (pf/2.)**2 - qf ) # smaller
499-
z2 = -pf/2. + sqrt( (pf/2.)**2 - qf ) # larger
474+
sqrt_d = sqrt( (pf/2.)**2. - qf )
475+
z1 = -pf/2. - sqrt_d # smaller
476+
z2 = -pf/2. + sqrt_d # larger
500477

501478
# Define the integration limits from
502479
# the range that is specified in '_JIT_F'
@@ -513,7 +490,7 @@ def _kernel_inverse_compton(self, E, Ep, T):
513490
return 0.
514491

515492
# Perform the integration in log space
516-
I_fF_E = quad(_JIT_EL_kernel_inverse_compton, log(llim), log(ulim), epsrel=eps, epsabs=0, args=(E, Ep, T))
493+
I_fF_E = quad(_JIT_el_kernel_inverse_compton, log(llim), log(ulim), epsrel=eps, epsabs=0, args=(E, Ep, T))
517494

518495
return 2.*pi*(alpha**2.)*I_fF_E[0]/(Ep**2.)
519496

@@ -541,7 +518,7 @@ def _kernel_compton(self, E, Ep, T):
541518

542519

543520
# BETHE_HEITLER PAIR CREATION #############################################
544-
@_cached
521+
@cached_member
545522
def _kernel_bethe_heitler(self, E, Ep, T):
546523
# Incorporate the non-generic integration limit as
547524
# the algorithm requires Ep > E and not Ep > E + me
@@ -553,13 +530,13 @@ def _kernel_bethe_heitler(self, E, Ep, T):
553530

554531

555532
# DOUBLE PHOTON PAIR CREATION #############################################
556-
@_cached
533+
@cached_member
557534
def _kernel_pair_creation(self, E, Ep, T):
558535
# In general, the threshold is Ep >~ me^2/(22*T)
559536
# However, here we use a slighlty smaller threshold
560537
# in acordance with the implementation we use in
561538
# '_PhotonReactionWrapper._rate_pair_creation'
562-
if Ep < me2/(30.*T):
539+
if Ep < me2/(50.*T):
563540
return 0.
564541

565542
dE, E2 = Ep - E, E**2.
@@ -586,7 +563,7 @@ def _kernel_pair_creation(self, E, Ep, T):
586563
return 0.
587564

588565
# Perform the integration in log space
589-
I_fG_E2 = quad(_JIT_EL_kernel_pair_creation, log(llim), log(ulim), epsrel=eps, epsabs=0, args=(E, Ep, T))
566+
I_fG_E2 = quad(_JIT_el_kernel_pair_creation, log(llim), log(ulim), epsrel=eps, epsabs=0, args=(E, Ep, T))
590567

591568
return 0.25*pi*(alpha**2.)*me2*I_fG_E2[0]/(Ep**3.)
592569

acropolis/data/rates.db.gz

3.67 MB
Binary file not shown.

acropolis/data/sm.tar.gz

373 KB
Binary file not shown.

0 commit comments

Comments
 (0)