FT-inversion-tools 0.0.1__tar.gz

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.
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: FT_inversion_tools
3
+ Version: 0.0.1
4
+ Summary: A small package containing tools needed to perform analysis for the FT inversions paper. Packaged for consistency.
5
+ Author-email: "Anthony R. Osborne" <anthony.r.osborne019@pm.me>
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.9
@@ -0,0 +1,15 @@
1
+ [project]
2
+ name = "FT_inversion_tools"
3
+ version = "0.0.1"
4
+ authors = [{name = "Anthony R. Osborne", email = "anthony.r.osborne019@pm.me"},]
5
+ description = "A small package containing tools needed to perform analysis for the FT inversions paper. Packaged for consistency."
6
+ requires-python = ">=3.9"
7
+ classifiers = [
8
+ "Programming Language :: Python :: 3",
9
+ "Operating System :: OS Independent",
10
+ ]
11
+ license = "MIT"
12
+ license-files = ["LICEN[CS]E*"]
13
+ [build-system]
14
+ requires = ["setuptools >= 77.0.3"]
15
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,83 @@
1
+ import os.path
2
+ import numpy as np
3
+ import scipy as sp
4
+ ### Functions for ZT system
5
+ def getZTFilePaths(system=str, direction=str):
6
+ """
7
+ Reads data for the FT system
8
+ """
9
+ default_path = os.path.join('~','ft_inversion_paper', 'ZT_data', system)
10
+ dens_path = os.path.expanduser(os.path.join(default_path, direction, 'static', 'density.y=0,z=0'))
11
+ vks_path = os.path.expanduser(os.path.join(default_path, direction, 'static', 'vks.y=0,z=0'))
12
+ vxc_path = os.path.expanduser(os.path.join(default_path, direction, 'static', 'vxc.y=0,z=0'))
13
+ vh_path = os.path.expanduser(os.path.join(default_path, direction, 'static', 'vh.y=0,z=0'))
14
+ return dens_path, vks_path, vxc_path, vh_path
15
+
16
+ def getZTData(system=str, direction=str):
17
+ """
18
+ Reads data for the FT system
19
+ """
20
+ dens_path, vks_path, vxc_path, vh_path = getZTFilePaths(system, direction)
21
+ x_grid = np.loadtxt(dens_path)[:,0] # 1D grid
22
+ dens = np.loadtxt(dens_path)[:,1]
23
+ vks = np.loadtxt(vks_path)[:,1]
24
+ vxc = np.loadtxt(vxc_path)[:,1]
25
+ vh = np.loadtxt(vh_path)[:,1]
26
+ return x_grid, dens, vks, vxc, vh
27
+
28
+ ### Functions for FT system
29
+ def getFTFilePaths(system=str, temp=str, direction=str):
30
+ """
31
+ Reads data for the FT system
32
+ """
33
+ default_path = os.path.join('~','ft_inversion_paper', 'ft_inversions', system)
34
+ dens_path = os.path.expanduser(os.path.join(default_path, temp, direction, 'static', 'density.y=0,z=0'))
35
+ vks_path = os.path.expanduser(os.path.join(default_path, temp, direction, 'static', 'vks.y=0,z=0'))
36
+ vxc_path = os.path.expanduser(os.path.join(default_path, temp, direction, 'static', 'vxc.y=0,z=0'))
37
+ vh_path = os.path.expanduser(os.path.join(default_path, temp, direction, 'static', 'vh.y=0,z=0'))
38
+ return dens_path, vks_path, vxc_path, vh_path
39
+
40
+ def getFTData(temp=str, system=str, direction=str):
41
+ """
42
+ Reads data for the FT system
43
+ """
44
+ dens_path, vks_path, vxc_path, vh_path = getFTFilePaths(temp, system, direction)
45
+ x_grid = np.loadtxt(dens_path)[:,0] # 1D grid
46
+ dens = np.loadtxt(dens_path)[:,1]
47
+ vks = np.loadtxt(vks_path)[:,1]
48
+ vxc = np.loadtxt(vxc_path)[:,1]
49
+ vh = np.loadtxt(vh_path)[:,1]
50
+ return x_grid, dens, vks, vxc, vh
51
+
52
+
53
+ def shifter(temps, vks_list_FWD, vks_list_INV, vxc_list_INV, Fermi_energy_list):
54
+ shifted_ks = []
55
+ shifted_xc = []
56
+ shifted_fermi = []
57
+ for i in range(len(temps)):
58
+ # print(temps[i])
59
+ timpFWDKS = vks_list_FWD[i]
60
+ timpINVKS = vks_list_INV[i]
61
+ shift = np.mean(timpINVKS- timpFWDKS)
62
+ shifted_ks.append(vks_list_INV[i] + shift)
63
+ shifted_xc.append(vxc_list_INV[i] + shift)
64
+ shifted_fermi.append(Fermi_energy_list[i] + shift)
65
+ return shifted_ks, shifted_xc, shifted_fermi
66
+
67
+ def energy_calculator(temps, vxc_list, dens_list, grid_list):
68
+ Exc_list = []
69
+ for i in range(len(temps)):
70
+ Exc = -sp.integrate.simpson((np.diff(vxc_list[0])) * (dens_list[i][1:]*grid_list[i][1:]), grid_list[i][1:])
71
+ Exc_list.append(Exc)
72
+ return Exc_list
73
+
74
+ def diffs_calculator(temps, vxc_list, dens_list):
75
+ potential_diffs = []
76
+ density_diffs = []
77
+ for i in range(len(temps)):
78
+ xc_diff = vxc_list[i] - vxc_list[0]
79
+ potential_diffs.append(xc_diff)
80
+ dens_diff = dens_list[i] - dens_list[0]
81
+ density_diffs.append(dens_diff)
82
+ return potential_diffs, density_diffs
83
+
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: FT_inversion_tools
3
+ Version: 0.0.1
4
+ Summary: A small package containing tools needed to perform analysis for the FT inversions paper. Packaged for consistency.
5
+ Author-email: "Anthony R. Osborne" <anthony.r.osborne019@pm.me>
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.9
@@ -0,0 +1,7 @@
1
+ pyproject.toml
2
+ src/FTI_analysis_tools.py
3
+ src/ZTA_analysis_tools.py
4
+ src/FT_inversion_tools.egg-info/PKG-INFO
5
+ src/FT_inversion_tools.egg-info/SOURCES.txt
6
+ src/FT_inversion_tools.egg-info/dependency_links.txt
7
+ src/FT_inversion_tools.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ FTI_analysis_tools
2
+ ZTA_analysis_tools
@@ -0,0 +1,268 @@
1
+ import os.path
2
+ import numpy as np
3
+ import scipy as sp
4
+ import pickle
5
+ ## Root finding functions
6
+ def secant_method(function, guess1:float, print_opt:bool, criterion:float=1e-6, error_track:bool=False):
7
+ """
8
+ INPUT:
9
+ function : function, function of which to find the roots
10
+ guess1 : float, lower guess for the root
11
+ criterion : float, convergence criterion for the root finding method
12
+ max_iter : float, maximum number of iterations for the root finding method
13
+ Returns:
14
+ root : float, The root of the function
15
+ Raises:
16
+ Excpetion: Divide by zero warning if guess1 and guess2 are equal
17
+ """
18
+
19
+ x2 = guess1
20
+ x1 = guess1 - 5
21
+
22
+ error = 1
23
+ iteration = 0
24
+
25
+ error = -(function(x2)*(x2 - x1))/(function(x2)-function(x1))
26
+
27
+ if print_opt ==True:
28
+ with open("secant_error.txt", "a") as f:
29
+ print("Iteration, x1, x2, f(x1), f(x2), error", file=f)
30
+
31
+ while (abs(error) > criterion and iteration < 1000):
32
+ if print_opt == True:
33
+ with open("secant_error.txt", "a") as f:
34
+ print(iteration, x1, x2, function(x1), function(x2), error, file=f)
35
+ x1 = x2
36
+ x2 += error
37
+ iteration += 1
38
+ error = -function(x2)*(x2 - x1)/(function(x2)-function(x1))
39
+ if print_opt == True:
40
+ with open("secant_error.txt", "a") as f:
41
+ print(iteration, x1, x2, function(x1), function(x2), error, file=f)
42
+
43
+ if error_track == False:
44
+ return x2, function(x2), iteration, error
45
+ return x2, function(x2)
46
+
47
+ ## Boltzman functions 2+ electron systems
48
+
49
+ def boltzman_weights(energy, chem_pot, tau, part_num):
50
+ """Calculates the Boltzman weights for the interacting densities
51
+ to approximate a thermal interacting density
52
+
53
+ Args:
54
+ energy (ndarray): _description_
55
+ chem_pot (float): _description_
56
+ tau (float): _description_
57
+ part_num (float): _description_
58
+
59
+ Returns:
60
+ occupation: boltzman weight for given temperature
61
+ """
62
+ kb = 1 # Boltzman constant in atomic units
63
+ beta = 1/(kb*tau) # beta
64
+ partition_function = 0
65
+ nstates = len(energy)
66
+ w = np.empty((nstates))
67
+ for i in range(part_num):
68
+ for j in range(nstates):
69
+ w[j] = np.exp(-beta*(energy[j]-(chem_pot*(i))))
70
+ partition_function += w[j]
71
+ w = w/partition_function
72
+ occupation = w
73
+ return occupation
74
+
75
+ def boltz_num_func_func(x, tau, vals, densities, ne, target_ne):
76
+ '''
77
+ Description: Determine the Unshifted particle number
78
+ INPUT:
79
+ mu: Scalar (float)
80
+ chemical potential
81
+ tau: Scalar (float)
82
+ Electronic temperature
83
+ vecs: ndarray
84
+ Eigenvectors
85
+ vals: ndarray
86
+ Eigenvalues
87
+ x: ndarray
88
+ Grid
89
+ OUTPUT
90
+ Ne: Scalar (float)
91
+ The unshifted particle number
92
+ '''
93
+
94
+ def boltz_num_func(mu):
95
+
96
+ nx = len(x)
97
+ nk = vals.shape[0]
98
+
99
+ kb = 1 #3.166811563e-6 # Ha K^-1
100
+ T = tau/kb
101
+
102
+ # obtain boltzman weights
103
+ w = boltzman_weights(vals,mu,T,ne)
104
+ dens = np.zeros(nx)
105
+ for i in range(ne):
106
+ for j in range(nk):
107
+ dens += w[j]*densities[j,:]
108
+ Ne = np.trapezoid(dens,x)
109
+
110
+ return Ne - target_ne
111
+
112
+ return boltz_num_func
113
+ ## Fermi Functions for 1 electron systems
114
+ def fermi_weights(energy, chem_pot, tau):
115
+ F_occs = 1/(1+np.exp((energy-chem_pot)/tau))
116
+ return F_occs
117
+ def fermi_num_func_func(x, tau, vals, densities, ne, target_ne):
118
+ '''
119
+ Description: Determine the Unshifted particle number
120
+ INPUT:
121
+ mu: Scalar (float)
122
+ chemical potential
123
+ tau: Scalar (float)
124
+ Electronic temperature
125
+ vecs: ndarray
126
+ Eigenvectors
127
+ vals: ndarray
128
+ Eigenvalues
129
+ x: ndarray
130
+ Grid
131
+ OUTPUT
132
+ Ne: Scalar (float)
133
+ The unshifted particle number
134
+ '''
135
+
136
+ def fermi_num_func(mu):
137
+
138
+ nx = len(x)
139
+ nk = vals.shape[0]
140
+
141
+ # convert temp in units of Ha into K
142
+ kb = 1 #3.166811563e-6 # Ha K^-1
143
+ T = tau/kb
144
+
145
+ # obtain boltzman weights
146
+ w = fermi_weights(vals,mu,T)
147
+ dens = np.zeros(nx)
148
+ for i in range(ne):
149
+ for j in range(nk):
150
+ # print(w.shape)
151
+ # print(densities.shape)
152
+ dens += w[j]*densities[j,:]
153
+ Ne = np.trapezoid(dens,x)
154
+
155
+ return Ne - target_ne
156
+
157
+ return fermi_num_func
158
+
159
+ ## Shifting function
160
+
161
+ def shifter(vks_FWD, vks_INV, vxc_INV):
162
+ """_summary_
163
+
164
+ Args:
165
+ vks_FWD (ndarray): Kohn-Sham potential from forward calculation
166
+ vks_INV (ndarray): Exact Kohn-Sham potential from inverse calculation
167
+ vxc_INV (ndarray): Exact exchange-correlation potential from inverse calculation
168
+
169
+ Returns:
170
+ _type_: _description_
171
+ """
172
+ # shifted_ks = []
173
+ # shifted_xc = []
174
+ timpFWDKS = vks_FWD
175
+ timpINVKS = vks_INV
176
+ shift = np.mean(timpINVKS- timpFWDKS)
177
+ shifted_ks = (vks_INV + shift)
178
+ shifted_xc = (vxc_INV + shift)
179
+ return shifted_ks, shifted_xc
180
+
181
+
182
+ def energy_calculators(temps, vxc_ZTA_list, vxc_LDAZTA_list, dens_list, grid_list):
183
+ """_summary_
184
+
185
+ Args:
186
+ temps (list): list of temperatures
187
+ vxc_ZTA_list (list): list of exact ZTA vxc arrays
188
+ vxc_LDAZTA_list (list): list of approximate ZTA vxc arrays
189
+ dens_list (list): list of theramlized density arrays
190
+ grid_list (list): list of numerical grids (these should be identical but this set up allows for non identical grids)
191
+
192
+ Returns:
193
+ _type_: _description_
194
+ """
195
+ Exc_ZTA_list = []
196
+ Exc_LDAZTA_list = []
197
+ for i in range(len(temps)):
198
+ Exc_ZTA = -sp.integrate.simpson((np.diff(vxc_ZTA_list[0])) * (dens_list[i][1:]*grid_list[i][1:]), grid_list[i][1:])
199
+ compA = np.diff(vxc_LDAZTA_list[i])
200
+ compB = grid_list[i]
201
+ compC = dens_list[i]
202
+ compD = grid_list[i]
203
+ Exc_LDAZTA = -sp.integrate.simpson((compA)* (compB*compC)[1:],compD[1:])
204
+ Exc_ZTA_list.append(Exc_ZTA)
205
+ Exc_LDAZTA_list.append(Exc_LDAZTA)
206
+ return Exc_ZTA_list, Exc_LDAZTA_list
207
+
208
+ def energy_diffs(temps, Exc_ZTA_list, Exc_LDAZTA_list, print_opt:bool = False):
209
+ """Calculates the difference between the Exact ZTA Exc and the LDAZTA Exc
210
+ This could really be abstracted to work with any functional but I will always default to saying LDA
211
+
212
+ Args:
213
+ temps (list): list of temperatures
214
+ Exc_ZTA_list (list): list of exact ZTA Exc values
215
+ Exc_LDAZTA_list (_type_): list of approximate ZTA Exc values
216
+
217
+ Returns:
218
+ _type_: _description_
219
+ """
220
+ LDA_diffs = []
221
+ for i in range(len(temps)):
222
+ xc_diff = Exc_LDAZTA_list[i] - Exc_ZTA_list[i]
223
+ LDA_diffs.append(xc_diff)
224
+ if print_opt:
225
+ print(f"for tau = {temps[i]}")
226
+ print(f"Exact ZTA E_xc = {Exc_ZTA_list[i]}")
227
+ print(f"LDA ZTA E_xc = {Exc_LDAZTA_list[i]}")
228
+ print(f"Difference due to use of LDA approximation = {LDA_diffs[i]}\n")
229
+ return LDA_diffs
230
+
231
+
232
+ ### Defining reader functions
233
+ def get_octo_FilePaths(molecule=str, temp=str, direction=str):
234
+ """
235
+ Reads data for the FT molecule
236
+ """
237
+ default_preMethod_path = os.path.join('~', 'ft_inversion_paper', 'LDAZTA', molecule, 'LDA')
238
+ dens_path = os.path.expanduser(os.path.join(default_preMethod_path, temp, direction, 'static', 'density.y=0,z=0'))
239
+ vks_path = os.path.expanduser(os.path.join(default_preMethod_path, temp, direction, 'static', 'vks.y=0,z=0'))
240
+ vxc_path = os.path.expanduser(os.path.join(default_preMethod_path, temp, direction, 'static', 'vxc.y=0,z=0'))
241
+ return dens_path, vks_path, vxc_path
242
+ def get_octo_Data(molecule=str, temp=str, direction=str):
243
+ """
244
+ Reads data for the FT molecule
245
+ """
246
+ dens_path, vks_path, vxc_path = get_octo_FilePaths(molecule, temp, direction)
247
+ x_grid = np.loadtxt(dens_path)[:,0] # 1D grid
248
+ dens = np.loadtxt(dens_path)[:,1]
249
+ vks = np.loadtxt(vks_path)[:,1]
250
+ vxc = np.loadtxt(vxc_path)[:,1]
251
+ return x_grid, dens, vks, vxc
252
+
253
+ def get_exact_file_paths(molecule=str):
254
+ default_preMethod_path = os.path.join('~', 'ft_inversion_paper', 'LDAZTA', molecule, 'exact')
255
+ vxc_path = os.path.expanduser(os.path.join(default_preMethod_path, 'xc_potential.pkl' ))
256
+ vs_path = os.path.expanduser(os.path.join(default_preMethod_path, 'ks_potential.pkl' ))
257
+
258
+ return vxc_path, vs_path
259
+
260
+
261
+ def get_exact_data(molecule=str):
262
+ vxc_path, vs_path = get_exact_file_paths(molecule)
263
+ with open(vxc_path, 'rb') as xc_file:
264
+ v_xc = pickle.load(xc_file)
265
+ with open(vs_path, 'rb') as vs_file:
266
+ v_s = pickle.load(vs_file)
267
+
268
+ return v_xc, v_s