vsdm 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vsdm/__init__.py ADDED
@@ -0,0 +1,52 @@
1
+ # __init__.py
2
+
3
+ from . import units
4
+ from . import utilities
5
+ from . import analytic
6
+ from . import gaussians
7
+ from . import portfolio
8
+ from . import basis
9
+ from . import projection
10
+ from . import matrixcalc
11
+ from . import wigner
12
+ from . import ratecalc
13
+
14
+ from .units import *
15
+ from .utilities import *
16
+ from .analytic import *
17
+ from .gaussians import *
18
+ from .portfolio import *
19
+ from .basis import *
20
+ from .projection import *
21
+ from .matrixcalc import *
22
+ # wigner and ratecalc require 'spherical' and 'quaternionic' packages
23
+ from .wigner import *
24
+ from .ratecalc import *
25
+
26
+ __all__ = (units.__all__ + utilities.__all__ + basis.__all__ + wigner.__all__
27
+ + projection.__all__ + matrixcalc.__all__ + ratecalc.__all__
28
+ + gaussians.__all__
29
+ + portfolio.__all__ + analytic.__all__)
30
+
31
+ __version__ = "0.1.0"
32
+
33
+
34
+ """
35
+ Dependencies: the following packages are required:
36
+ math, time, os.path, csv, sys
37
+ numpy
38
+ scipy
39
+ gvar
40
+ vegas
41
+ quaternionic
42
+ spherical
43
+ h5py
44
+
45
+ Note: spherical and quaternionic packages may require specific
46
+ versions of Python. I have tested with Python 3.7 and 3.9.
47
+ Only .wigner and .ratecalc require 'spherical'.
48
+ - If a user does not need to perform rotations with the WignerG matrices,
49
+ can load 'vsdm' with the following lines commented out:
50
+ # from .wigner import *
51
+ # from .ratecalc import *
52
+ """
vsdm/analytic.py ADDED
@@ -0,0 +1,202 @@
1
+ """Analytic results for mcalI matrix calculation.
2
+
3
+ Dimensionless integrals of functions of q and v_min(q), as functions
4
+ of x = (q / q_star)**2, for q_star**2 = 2 * omegaS * mX.
5
+
6
+ Functions:
7
+ _t: integral for rectangular volume, [[v1,v2],[q1,q2]]
8
+ _u: integral where v_min(q) sets lower bound, [v_min(q),v2]
9
+ _b: intermediate function for rectangular integral
10
+ _c, _d, _s: intermediate function for non-rectangular integrals (for _u)
11
+ """
12
+
13
+ __all__ = ['mI_star', 't_ln_vq_int', 'u_ln_vq_int',
14
+ '_b_nk_int', '_c_alpha_int', '_s_n_int']
15
+
16
+ import math
17
+ import numpy as np
18
+ import scipy.special as spf
19
+ # import vegas # numeric integration
20
+ # import gvar # gaussian variables; for vegas
21
+ # import time
22
+ # import quaternionic # For rotations
23
+ # import spherical #For Wigner D matrix
24
+ # import csv # file IO for projectFnlm
25
+ # import os.path
26
+ # import h5py # database format for mathcalI arrays
27
+
28
+ # from .units import *
29
+
30
+ def _b_nk_int(n, k, x):
31
+ # x = q^2 / q_*^2.
32
+ assert k-int(k)==0, "'k' should be integer valued"
33
+ k = int(k)
34
+ assert x!=0, "Range in 'x' should not include x=0, even if basis function includes q=0."
35
+ sum = 0.
36
+ for j in range(k+1):
37
+ comb = math.factorial(k) / (math.factorial(j) * math.factorial(k-j))
38
+ ipower = j - n - k/2 + 1
39
+ if ipower==0:
40
+ summand = math.log(x)
41
+ else:
42
+ summand = (x**ipower)/ipower
43
+ sum += comb*summand
44
+ return 0.5*sum
45
+
46
+ def _c_alpha_int(alpha, x):
47
+ # Updated to 'PRD' format
48
+ if alpha==-2:
49
+ return -0.5*math.log( (1+x)/x ) + 0.5/x - 0.125/x**2
50
+ elif alpha==-1:
51
+ return math.log( (1+x)/x ) - 0.5/x
52
+ elif alpha==0:
53
+ return (-0.25*(math.log(x))**2 + math.log(x) * math.log(1 + x)
54
+ + spf.spence(1 + x))
55
+ elif alpha==1:
56
+ return 0.5*x - math.log(1 + x)
57
+ elif alpha==2:
58
+ return 0.125*x**2 - 0.5*x + 0.5*math.log(1 + x)
59
+ else:
60
+ return x**(alpha)/alpha**2 * (0.5 - spf.hyp2f1(1, alpha, 1 + alpha, -x))
61
+
62
+ def _v_n_int(n, x):
63
+ if n==0:
64
+ return 0.5*math.log(x) + x + 0.25*x**2
65
+ elif n==1:
66
+ return 0.5/x + math.log(x) + 0.5*x
67
+ elif n==2:
68
+ return -0.25/x**2 - 1/x + 0.5*math.log(x)
69
+ else:
70
+ return 0.5*(x**(-n)/(-n)) + x**(-n+1)/(-n+1) + 0.5*x**(-n+2)/(-n+2)
71
+
72
+ def _s_n_int(n, x):
73
+ logfactor = 0.5*math.log(x/(1 + 2*x + x**2))
74
+ return (logfactor*_v_n_int(n, x) + 0.5*_c_alpha_int(-n, x)
75
+ + _c_alpha_int(1-n, x) + 0.5*_c_alpha_int(2-n, x))
76
+
77
+ def t_ln_vq_int(l, n, v12_star, q12_star):
78
+ """Rectangular integral T_{l,n}.
79
+
80
+ With [v1,v2] in units of v_star = q_star/mX, [q1,q2] in units of
81
+ q_star = sqrt(2*mX*omegaS).
82
+
83
+ Always v1 >= 1. Also require q1 > 0.
84
+ """
85
+ assert int(l)-l==0, "'l' must be integer valued"
86
+ l = int(l)
87
+ [v1,v2] = v12_star
88
+ [q1,q2] = q12_star
89
+ x1 = q1**2
90
+ x2 = q2**2
91
+ sum = 0.
92
+ for k in range(l+1):
93
+ term_k = 2**(l-k) * spf.gamma(0.5*(k+1+l)) / spf.gamma(0.5*(k+1-l))
94
+ if k==2:
95
+ termV = math.log(v2/v1) / (2 * math.factorial(l-2))
96
+ termQ = (_b_nk_int(n, 2, x2) - _b_nk_int(n, 2, x1))
97
+ sum += termV*term_k*termQ
98
+ else:
99
+ termV = ((v2**(2-k) - v1**(2-k))
100
+ / ((2-k)*math.factorial(k)*math.factorial(l-k)))
101
+ termQ = (_b_nk_int(n, k, x2) - _b_nk_int(n, k, x1))
102
+ sum += termV*term_k*termQ
103
+ return sum
104
+
105
+ def u_ln_vq_int(l, n, v2_star, q12_star):
106
+ """Non-rectangular integral U_{l,n}, with lower bound v1 = v_min(q).
107
+
108
+ With v2 in units of v_star = q_star/mX, [q1,q2] in units of
109
+ q_star = sqrt(2*mX*omegaS).
110
+ """
111
+ assert int(l)-l==0, "'l' must be integer valued"
112
+ l = int(l)
113
+ v2 = v2_star # only need v2, v1 is irrelevant
114
+ [q1,q2] = q12_star
115
+ x1 = q1**2
116
+ x2 = q2**2
117
+ sum = 0.
118
+ for k in range(l+1):
119
+ term_k = (spf.gamma(0.5*(k+1+l)) / spf.gamma(0.5*(k+1-l))
120
+ * 2**(l-k)/(math.factorial(k) * math.factorial(l-k)))
121
+ if k==2:
122
+ summand = (math.log(2*v2)*_b_nk_int(n, 2, x2) + _s_n_int(n, x2)
123
+ - math.log(2*v2)*_b_nk_int(n, 2, x1) - _s_n_int(n, x1))
124
+ sum += term_k*summand
125
+ else:
126
+ summand = (v2**(2-k)*(_b_nk_int(n, k, x2) - _b_nk_int(n, k, x1))
127
+ - 2**(k-2)*(_b_nk_int(n, 2, x2) - _b_nk_int(n, 2, x1)))
128
+ sum += term_k*summand/(2-k)
129
+ return sum
130
+
131
+ def mI_star(ell, n, v12_star, q12_star):
132
+ """Dimensionless integral related to MathcalI.
133
+
134
+ This is 'I^{(\ell)}_\star' without the prefactor (qBohr/qStar)**(2n)
135
+
136
+ With v12, q12 in units of vStar, qStar.
137
+
138
+ There are 0, 1, 2 or 3 regions that contribute to mcalI:
139
+ qA < (R1) < qB < (R2) < qC < (R3) < qD.
140
+ R2 is rectangular, bounded by v1 < v < v2. -> t_ln_vq_int
141
+ R1 and R3 are not rectangular: vMin(q) < v < v2. -> u_ln_vq_int
142
+ If vmin(q) > v1 for all q1 < q < q2, then mcalI is given by u_ln_vq_int
143
+ """
144
+ [v1,v2] = v12_star
145
+ [q1,q2] = q12_star
146
+ if v1==v2 or q1==q2:
147
+ return 0 # No integration volume
148
+ assert q1 < q2, "Need q12 to be ordered"
149
+ assert v1 < v2, "Need v12 to be ordered"
150
+ include_R2 = True
151
+ if v2 < 1:
152
+ # v2 is below the velocity threshold. mcaI=0
153
+ return 0
154
+ tilq_m,tilq_p = v2 - math.sqrt(v2**2-1), v2 + math.sqrt(v2**2-1)
155
+ if tilq_m > q2 or tilq_p < q1:
156
+ # in this case v2 < vmin(q) for all q in [q1,q2]
157
+ return 0
158
+ # Else: there are some q satisfying vmin(q) < v2 in this interval.
159
+ if v1 < 1:
160
+ # There is no v1 = vmin(q) solution for any real q
161
+ include_R2 = False
162
+ # Else: There are two real solutions to v1 = vmin(q)
163
+ else:
164
+ q_m,q_p = v1 - math.sqrt(v1**2-1), v1 + math.sqrt(v1**2-1)
165
+ if q_m > q2 or q_p < q1:
166
+ # in this case v1 < vmin(q) for all q in [q1,q2]
167
+ include_R2 = False
168
+ if include_R2 is False:
169
+ q_A = np.max([q1, tilq_m])
170
+ q_B = np.min([q2, tilq_p])
171
+ return u_ln_vq_int(ell, n, v2, [q_A, q_B])
172
+ # Else: at least part of the integration volume is set by v1 < v.
173
+ q_a = np.max([q1, tilq_m])
174
+ q_b = np.max([q1, q_m]) # q_m > tilq_m iff v2 > v1
175
+ q_c = np.min([q2, q_p]) # q_p < tilq_p iff v2 > v1
176
+ q_d = np.min([q2, tilq_p])
177
+ includeRegion = [True, True, True]
178
+ if q_a==q_b:
179
+ includeRegion[0] = False
180
+ if q_c==q_d:
181
+ includeRegion[2] = False
182
+ if v1>1:
183
+ assert q_b!=q_c, "If q_b==q_c then there should be no R2 region..."
184
+ mI_0,mI_1,mI_2 = 0, 0, 0
185
+ if includeRegion[0]:
186
+ mI_0 = u_ln_vq_int(ell, n, v2, [q_a, q_b])
187
+ if includeRegion[1]:
188
+ mI_1 = t_ln_vq_int(ell, n, [v1,v2], [q_b, q_c])
189
+ if includeRegion[2]:
190
+ mI_2 = u_ln_vq_int(ell, n, v2, [q_c, q_d])
191
+ return mI_0 + mI_1 + mI_2
192
+ #
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+ #