TB2J 0.9.0__py3-none-any.whl → 0.9.1rc0__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.
TB2J/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.9.0"
1
+ __version__ = "0.9.0.1"
TB2J/abacus/MAE.py ADDED
@@ -0,0 +1,320 @@
1
+ import numpy as np
2
+ from TB2J.abacus.abacus_wrapper import AbacusWrapper, AbacusParser
3
+ from TB2J.mathutils.rotate_spin import rotate_Matrix_from_z_to_axis
4
+ from TB2J.kpoints import monkhorst_pack
5
+ from TB2J.mathutils.fermi import fermi
6
+ from TB2J.mathutils.kR_convert import R_to_k
7
+ from scipy.linalg import eigh
8
+ from copy import deepcopy
9
+ from scipy.spatial.transform import Rotation
10
+ import matplotlib.pyplot as plt
11
+ from pathlib import Path
12
+ from TB2J.abacus.occupations import Occupations
13
+
14
+ # TODO List:
15
+ # - [x] Add the class AbacusSplitSOCWrapper
16
+ # - [x] Add the function to rotate the XC part
17
+ # - [x] Compute the band energy at arbitrary angle
18
+
19
+
20
+ def get_occupation(evals, kweights, nel, width=0.1):
21
+ occ = Occupations(nel=nel, width=width, wk=kweights, nspin=2)
22
+ return occ.occupy(evals)
23
+
24
+
25
+ def get_density_matrix(evals=None, evecs=None, kweights=None, nel=None, width=0.1):
26
+ occ = get_occupation(evals, kweights, nel, width=width)
27
+ rho = np.einsum("kib, kb, kjb -> kij", evecs, occ, evecs.conj())
28
+ return rho
29
+
30
+
31
+ def spherical_to_cartesian(theta, phi, normalize=True):
32
+ """
33
+ Convert spherical coordinates to cartesian
34
+ """
35
+ x = np.sin(theta) * np.cos(phi)
36
+ y = np.sin(theta) * np.sin(phi)
37
+ z = np.cos(theta)
38
+ vec = np.array([x, y, z])
39
+ if normalize:
40
+ vec = vec / np.linalg.norm(vec)
41
+ return vec
42
+
43
+
44
+ class AbacusSplitSOCWrapper(AbacusWrapper):
45
+ """
46
+ Abacus wrapper with Hamiltonian split to SOC and non-SOC parts
47
+ """
48
+
49
+ def __init__(self, *args, **kwargs):
50
+ HR_soc = kwargs.pop("HR_soc", None)
51
+ # nbasis = HR_soc.shape[1]
52
+ # kwargs["nbasis"] = nbasis
53
+ super().__init__(*args, **kwargs)
54
+ self._HR_copy = deepcopy(self._HR)
55
+ self.HR_soc = HR_soc
56
+ self.soc_lambda = 1.0
57
+ self.nel = 16
58
+ self.width = 0.1
59
+
60
+ @property
61
+ def HR(self):
62
+ return self._HR + self.HR_soc * self.soc_lambda
63
+
64
+ def rotate_HR_xc(self, axis):
65
+ """
66
+ Rotate SOC part of Hamiltonian
67
+ """
68
+ for iR, R in enumerate(self.Rlist):
69
+ self._HR[iR] = rotate_Matrix_from_z_to_axis(self._HR_copy[iR], axis)
70
+
71
+ def rotate_Hk_xc(self, axis):
72
+ """
73
+ Rotate SOC part of Hamiltonian
74
+ """
75
+ for ik in range(len(self._Hk)):
76
+ self._Hk[ik] = rotate_Matrix_from_z_to_axis(self._Hk_copy[ik], axis)
77
+
78
+ def get_density_matrix(self, kpts, kweights=None):
79
+ rho = np.zeros((len(kpts), self.nbasis, self.nbasis), dtype=complex)
80
+ evals, evecs = self.solve_all(kpts)
81
+ occ = get_occupation(evals, kweights, self.nel, width=self.width)
82
+ rho = np.einsum(
83
+ "kib, kb, kjb -> kij", evecs, occ, evecs.conj()
84
+ ) # should multiply S to the the real DM.
85
+ return rho
86
+
87
+ def rotate_DM(self, rho, axis):
88
+ """
89
+ Rotate the density matrix
90
+ """
91
+ for ik in range(len(rho)):
92
+ rho[ik] = rotate_Matrix_from_z_to_axis(rho[ik], axis)
93
+ return rho
94
+
95
+
96
+ class RotateHam:
97
+ def __init__(self, model, kmesh, gamma=True):
98
+ self.model = model
99
+ self.kpts = monkhorst_pack(kmesh, gamma_center=gamma)
100
+ self.kweights = np.ones(len(self.kpts), dtype=float) / len(self.kpts)
101
+
102
+ def get_band_energy2(self):
103
+ for ik, kpt in enumerate(self.kpts):
104
+ Hk, Sk = self.model.gen_ham(kpt)
105
+ evals, evecs = eigh(Hk, Sk)
106
+ rho = np.einsum(
107
+ "ib, b, jb -> ij",
108
+ evecs,
109
+ fermi(evals, self.model.efermi, width=0.05),
110
+ evecs.conj(),
111
+ )
112
+ eband1 = np.sum(evals * fermi(evals, self.model.efermi, width=0.05))
113
+ eband2 = np.trace(Hk @ rho)
114
+ print(eband1, eband2)
115
+
116
+ def get_band_energy(self, dm=False):
117
+ evals, evecs = self.model.solve_all(self.kpts)
118
+ occ = get_occupation(
119
+ evals, self.kweights, self.model.nel, width=self.model.width
120
+ )
121
+ eband = np.sum(evals * occ * self.kweights[:, np.newaxis])
122
+ # * fermi(evals, self.model.efermi, width=0.05)
123
+ if dm:
124
+ density_matrix = self.model.get_density_matrix(evecs)
125
+ return eband, density_matrix
126
+ else:
127
+ return eband
128
+
129
+ def calc_ref(self):
130
+ # calculate the Hk_ref, Sk_ref, Hk_soc_ref, and rho_ref
131
+ self.Sk_ref = R_to_k(self.kpts, self.model.Rlist, self.model.SR)
132
+ self.Hk_xc_ref = R_to_k(self.kpts, self.model.Rlist, self.model._HR_copy)
133
+ self.Hk_soc_ref = R_to_k(self.kpts, self.model.Rlist, self.model.HR_soc)
134
+ self.rho_ref = np.zeros(
135
+ (len(self.kpts), self.model.nbasis, self.model.nbasis), dtype=complex
136
+ )
137
+
138
+ evals = np.zeros((len(self.kpts), self.model.nbasis), dtype=float)
139
+ evecs = np.zeros(
140
+ (len(self.kpts), self.model.nbasis, self.model.nbasis), dtype=complex
141
+ )
142
+
143
+ for ik, kpt in enumerate(self.kpts):
144
+ # evals, evecs = eigh(self.Hk_xc_ref[ik]+self.Hk_soc_ref[ik], self.Sk_ref[ik])
145
+ evals[ik], evecs[ik] = eigh(self.Hk_xc_ref[ik], self.Sk_ref[ik])
146
+ occ = get_occupation(
147
+ evals, self.kweights, self.model.nel, width=self.model.width
148
+ )
149
+ # occ = fermi(evals, self.model.efermi, width=self.model.width)
150
+ self.rho_ref = np.einsum("kib, kb, kjb -> kij", evecs, occ, evecs.conj())
151
+
152
+ def get_band_energy_from_rho(self, axis):
153
+ """
154
+ This is wrong!! Should use second order perturbation theory to get the band energy instead.
155
+ """
156
+ eband = 0.0
157
+ for ik, k in enumerate(self.kpts):
158
+ rho = rotate_Matrix_from_z_to_axis(self.rho_ref[ik], axis)
159
+ Hk_xc = rotate_Matrix_from_z_to_axis(self.Hk_xc_ref[ik], axis)
160
+ Hk_soc = self.Hk_soc_ref[ik]
161
+ Htot = Hk_xc + Hk_soc * self.model.soc_lambda
162
+ # Sk = self.Sk_ref[ik]
163
+ # evals, evecs = eigh(Htot, Sk)
164
+ # rho2= np.einsum("ib, b, jb -> ij", evecs, fermi(evals, self.model.efermi, width=0.05), evecs.conj())
165
+ if ik == 0 and False:
166
+ pass
167
+ # print(f"{evecs[:4,0:4].real=}")
168
+ # print(f"{evals[:4]=}")
169
+ # print(f"{Hk_xc[:4,0:4].real=}")
170
+ # print(f"{Htot[:4,0:4].real=}")
171
+ # print(f"{Sk[:4,0:4].real=}")
172
+ # print(f"{rho[:4,0:4].real=}")
173
+ # print(f"{rho2[:4,0:4].real=}")
174
+ # eband1 = np.sum(evals * fermi(evals, self.model.efermi, width=0.05))
175
+ # eband2 = np.trace(Htot @ rho2).real
176
+ # eband3 = np.trace(Htot @ rho).real
177
+ # print(eband1, eband2, eband3)
178
+ e_soc = np.trace(Hk_soc @ rho) * self.kweights[ik] * self.model.soc_lambda
179
+ eband += e_soc
180
+ return eband
181
+
182
+ def get_band_energy_vs_angles(
183
+ self,
184
+ thetas,
185
+ psis,
186
+ ):
187
+ es = []
188
+ # es2 = []
189
+ # e,rho = self.model.get_band_energy(dm=True)
190
+ # self.calc_ref()
191
+ # thetas = np.linspace(*angle_range, npoints)
192
+ for i, theta, phi in enumerate(zip(thetas, psis)):
193
+ axis = spherical_to_cartesian(theta, phi)
194
+ self.model.rotate_HR_xc(axis)
195
+ # self.get_band_energy2()
196
+ e = self.get_band_energy()
197
+ es.append(e)
198
+ # es2.append(e2)
199
+ return es
200
+
201
+
202
+ def get_model_energy(model, kmesh, gamma=True):
203
+ ham = RotateHam(model, kmesh, gamma=gamma)
204
+ return ham.get_band_energy()
205
+
206
+
207
+ class AbacusSplitSOCParser:
208
+ """
209
+ Abacus parser with Hamiltonian split to SOC and non-SOC parts
210
+ """
211
+
212
+ def __init__(self, outpath_nosoc=None, outpath_soc=None, binary=False):
213
+ self.outpath_nosoc = outpath_nosoc
214
+ self.outpath_soc = outpath_soc
215
+ self.binary = binary
216
+ self.parser_nosoc = AbacusParser(outpath=outpath_nosoc, binary=binary)
217
+ self.parser_soc = AbacusParser(outpath=outpath_soc, binary=binary)
218
+ spin1 = self.parser_nosoc.read_spin()
219
+ spin2 = self.parser_soc.read_spin()
220
+ if spin1 != "noncollinear" or spin2 != "noncollinear":
221
+ raise ValueError("Spin should be noncollinear")
222
+
223
+ def parse(self):
224
+ nbasis, Rlist, HR, SR = self.parser_nosoc.Read_HSR_noncollinear()
225
+ nbasis2, Rlist2, HR2, SR2 = self.parser_soc.Read_HSR_noncollinear()
226
+ # print(HR[0])
227
+ HR_soc = HR2 - HR
228
+ model = AbacusSplitSOCWrapper(HR, SR, Rlist, nbasis, nspin=2, HR_soc=HR_soc)
229
+ model.efermi = self.parser_soc.efermi
230
+ model.basis = self.parser_nosoc.basis
231
+ model.atoms = self.parser_nosoc.atoms
232
+ return model
233
+
234
+
235
+ def abacus_get_MAE(
236
+ path_nosoc, path_soc, kmesh, thetas, psis, gamma=True, outfile="MAE.txt"
237
+ ):
238
+ """Get MAE from Abacus with magnetic force theorem. Two calculations are needed. First we do an calculation with SOC but the soc_lambda is set to 0. Save the density. The next calculatin we start with the density from the first calculation and set the SOC prefactor to 1. With the information from the two calcualtions, we can get the band energy with magnetic moments in the direction, specified in two list, thetas, and phis."""
239
+ parser = AbacusSplitSOCParser(
240
+ outpath_nosoc=path_nosoc, outpath_soc=path_soc, binary=False
241
+ )
242
+ model = parser.parse()
243
+ ham = RotateHam(model, kmesh, gamma=gamma)
244
+ es = []
245
+ for theta, psi in zip(thetas, psis):
246
+ axis = spherical_to_cartesian(theta, psi)
247
+ model.rotate_HR_xc(axis)
248
+ e = ham.get_band_energy()
249
+ es.append(ham.get_band_energy())
250
+ if outfile:
251
+ with open(outfile, "w") as f:
252
+ f.write("theta, psi, energy\n")
253
+ for theta, psi, e in zip(thetas, psis, es):
254
+ f.write(f"{theta}, {psi}, {e}\n")
255
+ return es
256
+
257
+
258
+ def test_AbacusSplitSOCWrapper():
259
+ # path = Path("~/projects/2D_Fe").expanduser()
260
+ path = Path("~/projects/TB2Jflows/examples/2D_Fe/Fe_z").expanduser()
261
+ outpath_nosoc = f"{path}/soc0/OUT.ABACUS"
262
+ outpath_soc = f"{path}/soc1/OUT.ABACUS"
263
+ parser = AbacusSplitSOCParser(
264
+ outpath_nosoc=outpath_nosoc, outpath_soc=outpath_soc, binary=False
265
+ )
266
+ model = parser.parse()
267
+ kmesh = [6, 6, 1]
268
+
269
+ r = RotateHam(model, kmesh)
270
+ # thetas, es = r.get_band_energy_vs_theta(angle_range=(0, np.pi*2), rotation_axis="z", initial_direction=(1,0,0), npoints=21)
271
+ thetas, es, es2 = r.get_band_energy_vs_theta(
272
+ angle_range=(0, np.pi * 2),
273
+ rotation_axis="y",
274
+ initial_direction=(0, 0, 1),
275
+ npoints=11,
276
+ )
277
+ # print the table of thetas and es, es2
278
+ print("theta, e, e2")
279
+ for theta, e, e2 in zip(thetas, es, es2):
280
+ print(f"{theta=}, {e=}, {e2=}")
281
+
282
+ plt.plot(thetas / np.pi, es - es[0], marker="o")
283
+ plt.plot(thetas / np.pi, es2 - es2[0], marker=".")
284
+ plt.savefig("E_along_z_x_z.png")
285
+ plt.show()
286
+
287
+
288
+ def abacus_get_MAE_cli():
289
+ import argparse
290
+
291
+ parser = argparse.ArgumentParser(
292
+ description="Get MAE from Abacus with magnetic force theorem. Two calculations are needed. First we do an calculation with SOC but the soc_lambda is set to 0. Save the density. The next calculatin we start with the density from the first calculation and set the SOC prefactor to 1. With the information from the two calcualtions, we can get the band energy with magnetic moments in the direction, specified in two list, thetas, and phis. "
293
+ )
294
+ parser.add_argument("path_nosoc", type=str, help="Path to the calculation with ")
295
+ parser.add_argument("path_soc", type=str, help="Path to the SOC calculation")
296
+ parser.add_argument("thetas", type=float, nargs="+", help="Thetas")
297
+ parser.add_argument("psis", type=float, nargs="+", help="Phis")
298
+ parser.add_argument("kmesh", type=int, nargs=3, help="K-mesh")
299
+ parser.add_argument(
300
+ "--gamma", action="store_true", help="Use Gamma centered kpoints"
301
+ )
302
+ parser.add_argument(
303
+ "--outfile",
304
+ type=str,
305
+ help="The angles and the energey will be saved in this file.",
306
+ )
307
+ args = parser.parse_args()
308
+ abacus_get_MAE(
309
+ args.path_nosoc,
310
+ args.path_soc,
311
+ args.kmesh,
312
+ args.thetas,
313
+ args.psis,
314
+ gamma=args.gamma,
315
+ outfile=args.outfile,
316
+ )
317
+
318
+
319
+ if __name__ == "__main__":
320
+ abacus_get_MAE_cli()
@@ -16,10 +16,10 @@ from TB2J.abacus.stru_api import read_abacus, read_abacus_out
16
16
 
17
17
  class AbacusWrapper(AbstractTB):
18
18
  def __init__(self, HR, SR, Rlist, nbasis, nspin=1):
19
- self.R2kfactor = -2j * np.pi
19
+ self.R2kfactor = 2j * np.pi
20
20
  self.is_orthogonal = False
21
21
  self._name = "ABACUS"
22
- self.HR = HR
22
+ self._HR = HR
23
23
  self.SR = SR
24
24
  self.Rlist = Rlist
25
25
  self.nbasis = nbasis
@@ -27,6 +27,14 @@ class AbacusWrapper(AbstractTB):
27
27
  self.norb = nbasis * nspin
28
28
  self._build_Rdict()
29
29
 
30
+ @property
31
+ def HR(self):
32
+ return self._HR
33
+
34
+ @HR.setter
35
+ def set_HR(self, HR):
36
+ self._HR = HR
37
+
30
38
  def _build_Rdict(self):
31
39
  if hasattr(self, "Rdict"):
32
40
  pass
@@ -62,6 +70,8 @@ class AbacusWrapper(AbstractTB):
62
70
  S = self.SR[iR] * phase
63
71
  # Sk += S + S.conjugate().T
64
72
  Sk += S
73
+ # Hk = (Hk + Hk.conj().T)/2
74
+ # Sk = (Sk + Sk.conj().T)/2
65
75
  elif convention == 1:
66
76
  # TODO: implement the first convention (the r convention)
67
77
  raise NotImplementedError("convention 1 is not implemented yet.")
@@ -74,6 +84,14 @@ class AbacusWrapper(AbstractTB):
74
84
  Hk, Sk = self.gen_ham(k, convention=convention)
75
85
  return eigh(Hk, Sk)
76
86
 
87
+ def solve_all(self, kpts, convention=2):
88
+ nk = len(kpts)
89
+ evals = np.zeros((nk, self.nbasis), dtype=float)
90
+ evecs = np.zeros((nk, self.nbasis, self.nbasis), dtype=complex)
91
+ for ik, k in enumerate(kpts):
92
+ evals[ik], evecs[ik] = self.solve(k, convention=convention)
93
+ return evals, evecs
94
+
77
95
  def HSE_k(self, kpt, convention=2):
78
96
  H, S = self.gen_ham(tuple(kpt), convention=convention)
79
97
  evals, evecs = eigh(H, S)
@@ -0,0 +1,278 @@
1
+ """
2
+ This file is stolen from the hotbit programm, with some modification.
3
+ """
4
+
5
+ import numpy as np
6
+ from scipy.optimize import brentq
7
+ import sys
8
+
9
+ from ase.dft.dos import DOS
10
+ from scipy import integrate
11
+
12
+ # import numba
13
+
14
+ # from numba import float64, int32
15
+
16
+ MAX_EXP_ARGUMENT = np.log(sys.float_info.max)
17
+
18
+ # @numba.vectorize(nopython=True)
19
+ # def myfermi(e, mu, width, nspin):
20
+ # x = (e - mu) / width
21
+ # if x < -10:
22
+ # ret = 2.0 / nspin
23
+ # elif x > 10:
24
+ # ret = 0.0
25
+ # else:
26
+ # ret = 2.0 / nspin / (math.exp(x) + 1)
27
+ # return ret
28
+
29
+
30
+ def myfermi(e, mu, width, nspin):
31
+ x = (e - mu) / width
32
+ return np.where(x < 10, 2.0 / (nspin * (np.exp(x) + 1.0)), 0.0)
33
+
34
+
35
+ class Occupations(object):
36
+ def __init__(self, nel, width, wk, nspin=1):
37
+ """
38
+ Initialize parameters for occupations.
39
+ :param nel: Number of electrons
40
+ :param width: Fermi-broadening
41
+ :param wk: k-point weights. eg. If only gamma, [1.0]
42
+ :param nspin(optional): number of spin, if spin=1 multiplicity=2 else, multiplicity=1.
43
+ """
44
+ self.nel = nel
45
+ self.width = width
46
+ self.wk = wk
47
+ self.nk = len(wk)
48
+ self.nspin = nspin
49
+
50
+ def get_mu(self):
51
+ """Return the Fermi-level (or chemical potential)."""
52
+ return self.mu
53
+
54
+ def fermi(self, mu):
55
+ """
56
+ Occupy states with given chemical potential.
57
+ Occupations are 0...2; without k-point weights
58
+ """
59
+ return myfermi(self.e, mu, self.width, self.nspin)
60
+
61
+ def root_function(self, mu):
62
+ """This function is exactly zero when mu is right."""
63
+ f = self.fermi(mu)
64
+ return np.einsum("i, ij->", self.wk, f) - self.nel
65
+
66
+ def occupy(self, e, xtol=1e-11):
67
+ """
68
+ Calculate occupation numbers with given Fermi-broadening.
69
+
70
+ @param e: e[ind_k,ind_orb] energy of k-point, state a
71
+ Note added by hexu: With spin=2,e[k,a,sigma], it also work. only the *2 should be removed.
72
+ @param wk: wk[:] weights for k-points
73
+ @param width: The Fermi-broadening
74
+
75
+ Returns: fermi[ind_k, ind_orb]
76
+ """
77
+ self.e = e
78
+ eflat = e.flatten()
79
+ ind = np.argsort(eflat)
80
+ e_sorted = eflat[ind]
81
+ if self.nspin == 1:
82
+ m = 2
83
+ elif self.nspin == 2:
84
+ m = 1
85
+ n_sorted = (self.wk[:, None, None] * np.ones_like(e) * m).flatten()[ind]
86
+
87
+ sum = n_sorted.cumsum()
88
+ if self.nel < sum[0]:
89
+ ifermi = 0
90
+ elif self.nel > sum[-1]:
91
+ raise ("number of electrons larger than number of orbital*spin")
92
+ else:
93
+ ifermi = np.searchsorted(sum, self.nel)
94
+ try:
95
+ if ifermi == 0:
96
+ elo = e_sorted[0]
97
+ else:
98
+ elo = e_sorted[ifermi - 1]
99
+ if ifermi == len(e_sorted) - 1:
100
+ ehi = e_sorted[-1]
101
+ else:
102
+ ehi = e_sorted[ifermi + 1]
103
+ guess = e_sorted[ifermi]
104
+ dmu = np.max((self.width, guess - elo, ehi - guess))
105
+ mu = brentq(self.root_function, guess - dmu, guess + dmu, xtol=xtol)
106
+ # mu = brent(
107
+ # self.root_function,
108
+ # brack=(guess - elo, guess, guess + dmu),
109
+ # tol=xtol)
110
+ except Exception as E:
111
+ # probably a bad guess
112
+ print("Error in finding Fermi level: ", E)
113
+ dmu = self.width
114
+ if self.nel < 1e-3:
115
+ mu = min(e_sorted) - dmu * 20
116
+ elif self.nel - sum[-1] > -1e-3:
117
+ mu = max(e_sorted) + dmu * 20
118
+ else:
119
+ # mu = brent(
120
+ # self.root_function,
121
+ # brack=(e_sorted[0] - dmu * 10,
122
+ # guess,
123
+ # e_sorted[-1] + dmu * 10),
124
+ # tol=xtol)
125
+ mu = brentq(
126
+ self.root_function,
127
+ e_sorted[0] - dmu * 20,
128
+ e_sorted[-1] + dmu * 20,
129
+ xtol=xtol,
130
+ )
131
+
132
+ if np.abs(self.root_function(mu)) > xtol * 1e4:
133
+ # raise RuntimeError(
134
+ # 'Fermi level could not be assigned reliably. Has the system fragmented?'
135
+ # )
136
+ print(
137
+ "Fermi level could not be assigned reliably. Has the system fragmented?"
138
+ )
139
+
140
+ f = self.fermi(mu)
141
+ # rho=(self.eigenvecs*f).dot(self.eigenvecs.transpose())
142
+
143
+ self.mu, self.f = mu, f
144
+ return f
145
+
146
+ def plot(self):
147
+ import pylab as pl
148
+
149
+ for ik in range(self.nk):
150
+ pl.plot(self.e[ik, :], self.f[ik, :])
151
+ pl.scatter(self.e[ik, :], self.f[ik, :])
152
+ pl.title("occupations")
153
+ pl.xlabel("energy (Ha)")
154
+ pl.ylabel("occupation")
155
+ pl.show()
156
+
157
+
158
+ class GaussOccupations(Occupations):
159
+ def get_mu(self):
160
+ return self.mu
161
+
162
+ def delta(self, energy):
163
+ """Return a delta-function centered at 'energy'."""
164
+ x = -(((self.e - energy) / self.width) ** 2)
165
+ return np.exp(x) / (np.sqrt(np.pi) * self.width)
166
+
167
+ def get_dos(self, npts=500):
168
+ eflat = self.e.flatten()
169
+ ind = np.argsort(eflat)
170
+ ##e_sorted = eflat[ind]
171
+ if self.nspin == 1:
172
+ m = 2
173
+ elif self.nspin == 2:
174
+ m = 1
175
+ # n_sorted = (self.wk * np.ones_like(self.e) * m).flatten()[ind]
176
+ dos = np.zeros(npts)
177
+ for w, e_n in zip(self.w_k, self.e_skn[0]):
178
+ for e in e_n:
179
+ dos += w * self.delta(e)
180
+
181
+ def root_function(self, mu):
182
+ pass
183
+
184
+ # @profile
185
+ def occupy(self, e, xtol=1e-8, guess=0.0):
186
+ self.e = e
187
+ dos = myDOS(kweights=self.wk, eigenvalues=e, width=self.width, npts=501)
188
+ edos = dos.get_energies()
189
+ d = dos.get_dos()
190
+ idos = integrate.cumtrapz(d, edos, initial=0) - self.nel
191
+ # f_idos = interpolate.interp1d(edos, idos)
192
+ # ret = optimize.fmin(f_idos, x0=edos[400], xtol=xtol, disp=True)
193
+ ifermi = np.searchsorted(idos, 0.0)
194
+ # self.mu = ret[0]
195
+ self.mu = edos[ifermi]
196
+ self.f = self.fermi(self.mu)
197
+ return self.f
198
+
199
+
200
+ class myDOS(DOS):
201
+ def __init__(
202
+ self, kweights, eigenvalues, nspin=1, width=0.1, window=None, npts=1001
203
+ ):
204
+ """Electronic Density Of States object.
205
+
206
+ calc: calculator object
207
+ Any ASE compliant calculator object.
208
+ width: float
209
+ Width of guassian smearing. Use width=0.0 for linear tetrahedron
210
+ interpolation.
211
+ window: tuple of two float
212
+ Use ``window=(emin, emax)``. If not specified, a window
213
+ big enough to hold all the eigenvalues will be used.
214
+ npts: int
215
+ Number of points.
216
+
217
+ """
218
+ self.npts = npts
219
+ self.width = width
220
+ # self.w_k = calc.get_k_point_weights()
221
+ self.w_k = kweights
222
+ self.nspins = nspin
223
+ # self.e_skn = np.array([[calc.get_eigenvalues(kpt=k, spin=s)
224
+ # for k in range(len(self.w_k))]
225
+ # for s in range(self.nspins)])
226
+ # self.e_skn -= calc.get_fermi_level()
227
+ self.e_skn = np.array([eigenvalues.T]) # eigenvalues: iband, ikpt
228
+
229
+ if window is None:
230
+ emin = None
231
+ emax = None
232
+ else:
233
+ emin, emax = window
234
+
235
+ if emin is None:
236
+ emin = self.e_skn.min() - 10 * self.width
237
+ if emax is None:
238
+ emax = self.e_skn.max() + 10 * self.width
239
+
240
+ self.energies = np.linspace(emin, emax, npts)
241
+
242
+ # if width == 0.0: # To use tetrahedron method
243
+ # bzkpts = calc.get_bz_k_points()
244
+ # size, offset = get_monkhorst_pack_size_and_offset(bzkpts)
245
+ # bz2ibz = calc.get_bz_to_ibz_map()
246
+ # shape = (self.nspins,) + tuple(size) + (-1,)
247
+ # self.e_skn = self.e_skn[:, bz2ibz].reshape(shape)
248
+ # self.cell = calc.atoms.cell
249
+
250
+ def get_idos(self):
251
+ e, d = self.get_dos()
252
+ return np.trapz(d, e)
253
+
254
+ def delta(self, energy):
255
+ """Return a delta-function centered at 'energy'."""
256
+ x = -(((self.energies - energy) / self.width) ** 2)
257
+ return np.exp(x) / (np.sqrt(np.pi) * self.width)
258
+
259
+ def get_dos(self, spin=None):
260
+ """Get array of DOS values.
261
+
262
+ The *spin* argument can be 0 or 1 (spin up or down) - if not
263
+ specified, the total DOS is returned.
264
+ """
265
+
266
+ if spin is None:
267
+ if self.nspins == 2:
268
+ # Spin-polarized calculation, but no spin specified -
269
+ # return the total DOS:
270
+ return self.get_dos(spin=0) + self.get_dos(spin=1)
271
+ else:
272
+ spin = 0
273
+
274
+ dos = np.zeros(self.npts)
275
+ for w, e_n in zip(self.w_k, self.e_skn[spin]):
276
+ for e in e_n:
277
+ dos += w * self.delta(e)
278
+ return dos
@@ -0,0 +1,38 @@
1
+ from scipy.linalg import eigh
2
+ import numpy as np
3
+
4
+
5
+ def gen_random_hermitean_matrix(n):
6
+ A = np.random.rand(n, n) + 1j * np.random.rand(n, n)
7
+ return A + A.conj().T
8
+
9
+
10
+ def gen_overlap_matrix(n):
11
+ A = np.random.rand(n, n) + 1j * np.random.rand(n, n)
12
+ return np.dot(A, A.conj().T)
13
+
14
+
15
+ def fermi_function(x, ef, beta):
16
+ return 1.0 / (np.exp(beta * (x - ef)) + 1)
17
+
18
+
19
+ def test():
20
+ n = 10
21
+ A = gen_random_hermitean_matrix(n)
22
+ S = gen_overlap_matrix(n)
23
+ beta = 0.1
24
+ ef = 0
25
+
26
+ evals, evecs = eigh(A, S)
27
+
28
+ etot = np.sum(evals * fermi_function(evals, ef, beta))
29
+
30
+ rho = np.einsum("ib,b,jb->ij", evecs, fermi_function(evals, ef, beta), evecs.conj())
31
+
32
+ etot2 = np.trace(np.dot(A, rho))
33
+
34
+ print(etot, etot2)
35
+
36
+
37
+ if __name__ == "__main__":
38
+ test()
TB2J/exchange.py CHANGED
@@ -345,7 +345,7 @@ class ExchangeNCL(Exchange):
345
345
  self.norb = self.G.norb
346
346
  self.nbasis = self.G.nbasis
347
347
  # self.rho = np.zeros((self.nbasis, self.nbasis), dtype=complex)
348
- self.rho = self.G.get_density_matrix().real
348
+ self.rho = self.G.get_density_matrix()
349
349
  self.A_ijR_list = defaultdict(lambda: [])
350
350
  self.A_ijR = defaultdict(lambda: np.zeros((4, 4), dtype=complex))
351
351
  self.A_ijR_orb = dict()
TB2J/green.py CHANGED
@@ -7,6 +7,8 @@ import tempfile
7
7
  from pathos.multiprocessing import ProcessPool
8
8
  import sys
9
9
  import pickle
10
+ import warnings
11
+ from TB2J.mathutils.fermi import fermi
10
12
 
11
13
  MAX_EXP_ARGUMENT = np.log(sys.float_info.max)
12
14
 
@@ -26,19 +28,6 @@ def eigen_to_G(evals, evecs, efermi, energy):
26
28
  )
27
29
 
28
30
 
29
- def fermi(e, mu, width=0.01):
30
- """
31
- the fermi function.
32
- .. math::
33
- f=\\frac{1}{\exp((e-\mu)/width)+1}
34
-
35
- :param e,mu,width: e,\mu,width
36
- """
37
-
38
- x = (e - mu) / width
39
- return np.where(x < MAX_EXP_ARGUMENT, 1 / (1.0 + np.exp(x)), 0.0)
40
-
41
-
42
31
  def find_energy_ingap(evals, rbound, gap=4.0):
43
32
  """
44
33
  find a energy inside a gap below rbound (right bound),
@@ -0,0 +1 @@
1
+ from .lowdin import Lowdin
@@ -0,0 +1,22 @@
1
+ import numpy as np
2
+ import warnings
3
+ import sys
4
+
5
+ MAX_EXP_ARGUMENT = np.log(sys.float_info.max)
6
+
7
+
8
+ def fermi(e, mu, width=0.01):
9
+ """
10
+ the fermi function.
11
+ .. math::
12
+ f=\\frac{1}{\exp((e-\mu)/width)+1}
13
+
14
+ :param e,mu,width: e,\mu,width
15
+ """
16
+ x = (e - mu) / width
17
+ # disable overflow warning
18
+ with warnings.catch_warnings():
19
+ warnings.simplefilter("ignore")
20
+ ret = np.where(x < MAX_EXP_ARGUMENT, 1 / (1.0 + np.exp(x)), 0.0)
21
+
22
+ return ret
@@ -0,0 +1,90 @@
1
+ import numpy as np
2
+
3
+
4
+ def HR_to_k(HR, Rlist, kpts):
5
+ # Hk[k,:,:] = sum_R (H[R] exp(i2pi k.R))
6
+ phase = np.exp(2.0j * np.pi * np.tensordot(kpts, Rlist, axes=([1], [1])))
7
+ Hk = np.einsum("rlm, kr -> klm", HR, phase)
8
+ return Hk
9
+
10
+
11
+ def Hk_to_R(Hk, Rlist, kpts, kweights):
12
+ phase = np.exp(-2.0j * np.pi * np.tensordot(kpts, Rlist, axes=([1], [1])))
13
+ HR = np.einsum("klm, kr, k->rlm", Hk, phase, kweights)
14
+ return HR
15
+
16
+
17
+ def k_to_R(kpts, Rlist, Mk, kweights=None):
18
+ """
19
+ Transform k-space wavefunctions to real space.
20
+ params:
21
+ kpts: k-points
22
+ Rlist: list of R vectors
23
+ Mk: matrix of shape [nkpt, n1, n2] in k-space.
24
+
25
+ return:
26
+ MR: matrix of shape [nR, n1, n2], the matrix in R-space.
27
+
28
+ """
29
+ nkpt, n1, n2 = Mk.shape
30
+ if kweights is None:
31
+ kweights = np.ones(nkpt, dtype=float) / nkpt
32
+ phase = np.exp(-2.0j * np.pi * np.tensordot(kpts, Rlist, axes=([1], [1])))
33
+ MR = np.einsum("klm, kr, k -> rlm", Mk, phase, kweights)
34
+ return MR
35
+
36
+ # nkpt, n1, n2 = Mk.shape
37
+ # nR = Rlist.shape[0]
38
+ # MR = np.zeros((nR, n1, n2), dtype=complex)
39
+ # if kweights is None:
40
+ # kweights = np.ones(nkpt, dtype=float)/nkpt
41
+ # for iR, R in enumerate(Rlist):
42
+ # for ik in range(nkpt):
43
+ # MR[iR] += Mk[ik] * np.exp(-2.0j*np.pi * np.dot(kpts[ik], R)) * kweights[ik]
44
+ # return MR
45
+
46
+
47
+ def R_to_k(kpts, Rlist, MR):
48
+ """
49
+ Transform real-space wavefunctions to k-space.
50
+ params:
51
+ kpts: k-points
52
+ Rlist: list of R vectors
53
+ MR: matrix of shape [nR, n1, n2] in R-space.
54
+
55
+ return:
56
+ Mk: matrix of shape [nkpt, n1, n2], the matrix in k-space.
57
+
58
+ """
59
+ phase = np.exp(2.0 * np.pi * 1j * np.tensordot(kpts, Rlist, axes=([1], [1])))
60
+ Mk = np.einsum("rlm, kr -> klm", MR, phase)
61
+
62
+ # nkpt, n1, n2 = Mk.shape
63
+ # nR = Rlist.shape[0]
64
+ # Mk = np.zeros((nkpt, n1, n2), dtype=complex)
65
+ # for iR, R in enumerate(Rlist):
66
+ # for ik in range(nkpt):
67
+ # Mk[ik] += MR[iR] * np.exp(2.0 * np.pi * 1j * np.dot(kpts[ik], R))
68
+ return Mk
69
+
70
+
71
+ def R_to_onek(kpt, Rlist, MR):
72
+ """
73
+ Transform real-space wavefunctions to k-space.
74
+ params:
75
+ kpt: k-point
76
+ Rlist: list of R vectors
77
+ MR: matrix of shape [nR, n1, n2] in R-space.
78
+
79
+ return:
80
+ Mk: matrix of shape [n1, n2], the matrix in k-space.
81
+
82
+ """
83
+ phase = np.exp(2.0j * np.pi * np.dot(Rlist, kpt))
84
+ Mk = np.einsum("rlm, r -> lm", MR, phase)
85
+ return Mk
86
+ # n1, n2 = MR.shape[1:]
87
+ # Mk = np.zeros((n1, n2), dtype=complex)
88
+ # for iR, R in enumerate(Rlist):
89
+ # Mk += MR[iR] * np.exp(2.0j*np.pi * np.dot(kpt, R))
90
+ # return Mk
@@ -0,0 +1,12 @@
1
+ import numpy as np
2
+ from scipy.linalg import inv, eigh
3
+
4
+
5
+ def Lowdin(S):
6
+ """
7
+ Calculate S^(-1/2).
8
+ Which is used in lowind's symmetric orthonormalization.
9
+ psi_prime = S^(-1/2) psi
10
+ """
11
+ eigval, eigvec = eigh(S)
12
+ return eigvec @ np.diag(np.sqrt(1.0 / eigval)) @ (eigvec.T.conj())
@@ -0,0 +1,35 @@
1
+ import numpy as np
2
+ from TB2J.pauli import pauli_block_all, s0, s1, s2, s3, gather_pauli_blocks
3
+
4
+
5
+ def rotate_Matrix_from_z_to_axis(M, axis, normalize=True):
6
+ """
7
+ Given a spinor matrix M, rotate it from z-axis to axis.
8
+ The spinor matrix M is a 2x2 matrix, which can be decomposed as I, x, y, z components using Pauli matrices.
9
+ """
10
+ MI, Mx, My, Mz = pauli_block_all(M)
11
+ axis = axis / np.linalg.norm(axis)
12
+ # M_new = s0* MI + Mz * (axis[0] * s1 + axis[1] * s2 + axis[2] * s3) *2
13
+ M_new = gather_pauli_blocks(MI, Mz * axis[0], Mz * axis[1], Mz * axis[2])
14
+ return M_new
15
+
16
+
17
+ def test_rotate_Matrix_from_z_to_axis():
18
+ M = np.array([[1.1, 0], [0, 0.9]])
19
+ print(pauli_block_all(M))
20
+ Mnew = rotate_Matrix_from_z_to_axis(M, [1, 1, 1])
21
+ print(pauli_block_all(Mnew))
22
+ print(Mnew)
23
+
24
+ M = np.array(
25
+ [
26
+ [-9.90532976e-06 + 0.0j, 0.00000000e00 + 0.0j],
27
+ [0.00000000e00 + 0.0j, -9.88431291e-06 + 0.0j],
28
+ ]
29
+ )
30
+ print(M)
31
+ print(rotate_Matrix_from_z_to_axis(M, [0, 0, 1]))
32
+
33
+
34
+ if __name__ == "__main__":
35
+ test_rotate_Matrix_from_z_to_axis()
TB2J/pauli.py CHANGED
@@ -143,7 +143,24 @@ def pauli_block_all(M):
143
143
  return MI, Mx, My, Mz
144
144
 
145
145
 
146
+ def gather_pauli_blocks(MI, Mx, My, Mz):
147
+ """
148
+ Gather the I, x, y, z component of a matrix.
149
+ """
150
+ return np.kron(MI, s0) + np.kron(Mx, s1) + np.kron(My, s2) + np.kron(Mz, s3)
151
+
152
+
153
+ def test_gather_pauli_blocks():
154
+ M = np.random.rand(4, 4)
155
+ MI, Mx, My, Mz = pauli_block_all(M)
156
+ M2 = gather_pauli_blocks(MI, Mx, My, Mz)
157
+ assert np.allclose(M, M2)
158
+
159
+
146
160
  def op_norm(M):
161
+ """
162
+ Return the operator norm of a matrix.
163
+ """
147
164
  return max(svd(M)[1])
148
165
 
149
166
 
@@ -1,12 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.9.0
3
+ Version: 0.9.1rc0
4
4
  Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
5
- Home-page: UNKNOWN
6
5
  Author: Xu He
7
6
  Author-email: mailhexu@gmail.com
8
7
  License: BSD-2-clause
9
- Platform: UNKNOWN
10
8
  Classifier: Development Status :: 3 - Alpha
11
9
  Classifier: Programming Language :: Python :: 3
12
10
  Classifier: Operating System :: OS Independent
@@ -16,14 +14,13 @@ Classifier: Topic :: Scientific/Engineering :: Physics
16
14
  Classifier: License :: OSI Approved :: BSD License
17
15
  Requires-Python: >=3.6
18
16
  License-File: LICENSE
19
- Requires-Dist: ase (>=3.19)
17
+ Requires-Dist: numpy >1.16.5
18
+ Requires-Dist: scipy
20
19
  Requires-Dist: matplotlib
21
- Requires-Dist: numpy (>1.16.5)
22
- Requires-Dist: packaging (>=20.0)
20
+ Requires-Dist: ase >=3.19
21
+ Requires-Dist: tqdm
23
22
  Requires-Dist: pathos
23
+ Requires-Dist: packaging >=20.0
24
24
  Requires-Dist: pre-commit
25
- Requires-Dist: scipy
26
- Requires-Dist: tqdm
27
25
 
28
26
  TB2J is a Python package aimed to compute automatically the magnetic interactions (superexchange and Dzyaloshinskii-Moriya) between atoms of magnetic crystals from DFT Hamiltonian based on Wannier functions or Linear combination of atomic orbitals. It uses the Green's function method and take the local rigid spin rotation as a perturbation. The package can take the output from Wannier90, which is interfaced with many density functional theory codes or from codes based on localised orbitals. A minimal user input is needed, which allows for an easily integration into a high-throughput workflows.
29
-
@@ -2,19 +2,19 @@ TB2J/Jdownfolder.py,sha256=Nw2ixvn2Uq-o1wficz6rdaYHjfRN3U_kQCvrNJGNb68,6980
2
2
  TB2J/Jtensor.py,sha256=0fhfOcfVQGu75gytEnApKWTJZfg9ksKJ0anJgco5wRQ,3179
3
3
  TB2J/Oiju.py,sha256=cNGv8N5uH_swGq7cnAt2OyiDfqtjLlLrwseGu0E4iaM,3383
4
4
  TB2J/Oiju_epc.py,sha256=oytM3NYW7nWmklrGgNlqwIpI_JYv_hb7ZnR4o9nYNog,6809
5
- TB2J/__init__.py,sha256=H9NWRZb7NbeRRPLP_V1fARmLNXranorVM-OOY-8_2ug,22
5
+ TB2J/__init__.py,sha256=hcEWkag_UvLm1ZSbjsgcTWkGVlR3Bwmzg1QYAwsvf-g,24
6
6
  TB2J/basis.py,sha256=DFo6_QUwjBwisP6zGxvoO0lpGTMDPAOkiL9giNCjOjA,1558
7
7
  TB2J/citation.py,sha256=gcQeyJZaT1Qrtsl8Y3s4neOH3-vvgmIcCvXeV2o3vj0,2891
8
8
  TB2J/contour.py,sha256=aw8LX6wVFCRPhcpkzuI0jGnHisvk4cezvUhkF_6Yx94,2633
9
9
  TB2J/cut_cell.py,sha256=kr9WeQhBQLm8QXL2B3NcsSYmSw-OAtJk3f9wksAOZbs,2952
10
10
  TB2J/density_matrix.py,sha256=D5k8Oe21OCiLVORNYbo4TZOFG0slrQSbj91kJ3TMFjs,1514
11
11
  TB2J/epc.py,sha256=zLbtqZJhDr8DnnGN6YENcXwrMb3Qxu6KB08mLy9Pw20,3474
12
- TB2J/exchange.py,sha256=Xg2fuUZbj-Icpqc65Ictllxvdvct8Ec4KQPAmEyo0oM,29586
12
+ TB2J/exchange.py,sha256=dsXQhlxXaBurxa7z3YkBjqmEFFtfEy1xaHf0VT3eKZE,29581
13
13
  TB2J/exchangeCL2.py,sha256=TIr-d2X56AiGe4qEhyXyZhRuwXvQG6clJMwDmjnTOaE,10985
14
14
  TB2J/exchange_pert.py,sha256=jmFMtQbYa_uczM4VAeS6TijkIHRFIqEzZJswzE9Wfuo,8523
15
15
  TB2J/exchange_qspace.py,sha256=ZL68qBGFUaQ9BsSPsJaaoWOr9RssPiqX34R_9I3nk_8,8436
16
16
  TB2J/gpaw_wrapper.py,sha256=aJ--9Dtyq7jOP1Hkh-Sh1nWcfXm6zKcljOCO0DNCAr0,6890
17
- TB2J/green.py,sha256=X-D8UZcIyz6zh_0W9VgUUv5yXPP3KWJ6C03m6CMWE3o,13377
17
+ TB2J/green.py,sha256=QAJbDaR91QLres5gUPk37iqVsuQdPTt92VtEYLCl240,13170
18
18
  TB2J/greentest.py,sha256=2ISSfhor9ecSEOi_E6b4Cv26wEIQlwlzca0ru8z44_E,1603
19
19
  TB2J/io_merge.py,sha256=t85k3L6IL9X5ys-PWK7CzResb3xJsyqM3LAlKPUe9vM,6825
20
20
  TB2J/kpoints.py,sha256=6XK2KqTncidEq3o9GuO6VEZRPNTRtWeXg9QfcV-9smI,532
@@ -22,7 +22,7 @@ TB2J/manager.py,sha256=4-4x9jJRHpUEqJuhc5HqpXfh2-Ze5G9Wg8gOtn-AqR4,15372
22
22
  TB2J/mathutils.py,sha256=tHA6q3KPDpXLIbZHdDZ2NU5s886VVM_oEG490zQ6Ris,300
23
23
  TB2J/myTB.py,sha256=ok_B4my29bOIghMSZfx0Es6G8FaXaIiLP4gPxTdSj00,17659
24
24
  TB2J/orbmap.py,sha256=RCMJkOPGbfPrcZzcc5ia1ZMKBQWxGcyj8W1ve8BJaEw,6669
25
- TB2J/pauli.py,sha256=_FIF62jq2CkQdWC473a3S2F6NmzCdeCnglO9PjNVmMI,4120
25
+ TB2J/pauli.py,sha256=zOELm7Vgxw6SMaO5l7qVWx1pBKZt25RLnEpnVM3dz_0,4545
26
26
  TB2J/pert.py,sha256=RaCJfewl0doht4cjAnzzGKe-uj2le4aqe0iPKFrq9fo,1192
27
27
  TB2J/plot.py,sha256=AnFIFWE2vlmj7Z6f_7-dX_O1stJN-qbuiurPj43dUCM,4104
28
28
  TB2J/rotate_atoms.py,sha256=Dwptn-wdDW4zYzjYb95yxTzuZOe9WPuLjh3d3-YcSs0,3277
@@ -33,12 +33,15 @@ TB2J/tensor_rotate.py,sha256=4-DfT_Mg5e40fbd74M5W0D5DqmUq-kVOOLDkkkI834A,8083
33
33
  TB2J/utest.py,sha256=z_ahi7tpHQF9WlHNQihcQ7qzfezRJQXQt28eB1X_z64,3897
34
34
  TB2J/utils.py,sha256=_ARYKAeWfP1p5w0mEl-d7KwNfXoqC85TveYl0iCBD3c,9880
35
35
  TB2J/versioninfo.py,sha256=wZwS9QDFRVDe7rf8JyPDDI8UGdTQiO6Pb_sWv8GAegA,337
36
+ TB2J/abacus/MAE.py,sha256=q9aSVDRZFAnZL3gHdNmde7sxj80oe-BRjwDO-ipyfew,12237
36
37
  TB2J/abacus/__init__.py,sha256=5sHiDnF2L-Y80QeET9zOiS83a5T_TQAXvnIhcYB6wNU,56
37
38
  TB2J/abacus/abacus_api.py,sha256=D_NyXW-Pno92d3RVHByx0l1HDPHQAvXsmQVt8cfIGR8,7267
38
- TB2J/abacus/abacus_wrapper.py,sha256=QR3ZW6v-d7dgneKwBO5s9FfCjBp-fkWMEaTO4SlcROA,8461
39
+ TB2J/abacus/abacus_wrapper.py,sha256=PaO7qEE-h1tv2nKsV8h2RZUrmAWjkw8MKapj8Fk9U5s,9006
39
40
  TB2J/abacus/gen_exchange_abacus.py,sha256=lKZqkWMnLQtaSwgn8O5Fzr-pV6tzwoMqfZU_vbET6gU,2973
41
+ TB2J/abacus/occupations.py,sha256=vaMVeZwldgzGDxjA7i3-2-V6akXjpgJwJFWKozJ-l2k,8947
40
42
  TB2J/abacus/orbital_api.py,sha256=l48Hn5z7TA0TH7Is4NDmz74b6B9L2ztYO4dRR37U4mQ,1562
41
43
  TB2J/abacus/stru_api.py,sha256=aBKKlZ2hvAZChVCfNxRdxH51rfHKqZn6kOlazY-yW8k,67888
44
+ TB2J/abacus/test_density_matrix.py,sha256=f0xHOTzIssT-XTvBJrQHU0JVbvBYOE1Mduh-j7qiLO8,774
42
45
  TB2J/abacus/test_read_HRSR.py,sha256=cAT-e79jGjCBXLTJ9UYX0WvalG_yD4Awl79tTOUcwaQ,1254
43
46
  TB2J/abacus/test_read_stru.py,sha256=CpK4zWhlCVAMCmYQmp9Hy-A40OblZQLFpo5JokpNcWQ,785
44
47
  TB2J/external/__init__.py,sha256=yD_ZIMi76H49rj6GAQpiB7UlKa3TgSaMkkLHT6M-8w8,137
@@ -51,6 +54,11 @@ TB2J/io_exchange/io_tomsasd.py,sha256=NqkAC1Fl-CUnFA21eBzSy_S5F_oeQFJysw4UukQbN8
51
54
  TB2J/io_exchange/io_txt.py,sha256=BMr1eSILlKpgtjvDx7uw2VMAkEKSvGEPNxpaT_zev0I,10547
52
55
  TB2J/io_exchange/io_uppasd.py,sha256=bI4iPEgnK4TvCZNvb6x2xYXgjW7pEehCqmcizy2pqFU,3301
53
56
  TB2J/io_exchange/io_vampire.py,sha256=UllC4twf06_q2vBCnAYFzEDGvS8mSefwQXDquBuyc0M,5583
57
+ TB2J/mathutils/__init__.py,sha256=tQLBfHkZqdVfVxPOahy42qMUkFYnFFFhM-uc4QsYFxI,27
58
+ TB2J/mathutils/fermi.py,sha256=tzEicVoxE_5DxPDDZMvi4ynR1_Iqf-Qh0-0zfm-iVBo,480
59
+ TB2J/mathutils/kR_convert.py,sha256=p_9XWJVNanTzTK2rI6KRjTkbSq42la6N448-zJOsMwY,2671
60
+ TB2J/mathutils/lowdin.py,sha256=tHA6q3KPDpXLIbZHdDZ2NU5s886VVM_oEG490zQ6Ris,300
61
+ TB2J/mathutils/rotate_spin.py,sha256=XtfwHGfIqI9nRYZcCd_yQ3Ud1AXVJj9fwqIHloMcaCs,1111
54
62
  TB2J/spinham/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
63
  TB2J/spinham/base_parser.py,sha256=oQRHvFE_BlUtTaTZykKgvicu40oXcbICB-D1aAt-qlA,2196
56
64
  TB2J/spinham/constants.py,sha256=y4-hRyl5EAR42k24Oa5XhAsUQtKVn1MAgyqNf-p3PrM,762
@@ -66,18 +74,18 @@ TB2J/spinham/supercell.py,sha256=y17uUC6r3gQb278FhxIW4CABihfLTvKFj6flyXrCPR8,122
66
74
  TB2J/wannier/__init__.py,sha256=7ojCbM84PYv1X1Tbo4NHI-d3gWmQsZB_xiYqbfxVV1E,80
67
75
  TB2J/wannier/w90_parser.py,sha256=dbd63LuKyv2DVUzqRINGsbDzEsOxsQyE8_Ear_LQIRg,4620
68
76
  TB2J/wannier/w90_tb_parser.py,sha256=qt8pnuprmPp9iIAYwPkPbmEzk6ZPgMq2xognoQp7vwc,4610
69
- TB2J-0.9.0.data/scripts/TB2J_downfold.py,sha256=F9oImXFysejCMP7eIBjbCX2jdHFOCvDW5beF1sG-UM8,1854
70
- TB2J-0.9.0.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
71
- TB2J-0.9.0.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
72
- TB2J-0.9.0.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
73
- TB2J-0.9.0.data/scripts/TB2J_merge.py,sha256=y834SF4rIRn1L1ptkhczvavQpC-8Px6DTmDOOSaq_DE,1854
74
- TB2J-0.9.0.data/scripts/TB2J_rotate.py,sha256=zgiDFuYZNmzKK0rwDmTaYD2OpRlmKA_VGeBx83w2Xwc,873
75
- TB2J-0.9.0.data/scripts/TB2J_rotateDM.py,sha256=kCvF7gotuqAX1VnJ06cwfVm7RrhrdtiV5v7d9P2Pn_E,567
76
- TB2J-0.9.0.data/scripts/abacus2J.py,sha256=M4B07lvTCDczTPTqvnDh_PERzCARAd09TLKv4aIdSQM,4408
77
- TB2J-0.9.0.data/scripts/siesta2J.py,sha256=hBzS7ZgoHM3oXlTCQd-xVA07Ks2FiIwyRpQWUFITRPE,4303
78
- TB2J-0.9.0.data/scripts/wann2J.py,sha256=2t2hWwyELskYCwkGDziCgiIAnfr6odLLJ6cQBJ2RQwQ,5714
79
- TB2J-0.9.0.dist-info/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
80
- TB2J-0.9.0.dist-info/METADATA,sha256=4ooTIlcMyCl-axTuL5PI9qfK4i7k5zFEoHFl-CiYXOc,1462
81
- TB2J-0.9.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
82
- TB2J-0.9.0.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
83
- TB2J-0.9.0.dist-info/RECORD,,
77
+ TB2J-0.9.1rc0.data/scripts/TB2J_downfold.py,sha256=F9oImXFysejCMP7eIBjbCX2jdHFOCvDW5beF1sG-UM8,1854
78
+ TB2J-0.9.1rc0.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
79
+ TB2J-0.9.1rc0.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
80
+ TB2J-0.9.1rc0.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
81
+ TB2J-0.9.1rc0.data/scripts/TB2J_merge.py,sha256=y834SF4rIRn1L1ptkhczvavQpC-8Px6DTmDOOSaq_DE,1854
82
+ TB2J-0.9.1rc0.data/scripts/TB2J_rotate.py,sha256=zgiDFuYZNmzKK0rwDmTaYD2OpRlmKA_VGeBx83w2Xwc,873
83
+ TB2J-0.9.1rc0.data/scripts/TB2J_rotateDM.py,sha256=kCvF7gotuqAX1VnJ06cwfVm7RrhrdtiV5v7d9P2Pn_E,567
84
+ TB2J-0.9.1rc0.data/scripts/abacus2J.py,sha256=M4B07lvTCDczTPTqvnDh_PERzCARAd09TLKv4aIdSQM,4408
85
+ TB2J-0.9.1rc0.data/scripts/siesta2J.py,sha256=hBzS7ZgoHM3oXlTCQd-xVA07Ks2FiIwyRpQWUFITRPE,4303
86
+ TB2J-0.9.1rc0.data/scripts/wann2J.py,sha256=2t2hWwyELskYCwkGDziCgiIAnfr6odLLJ6cQBJ2RQwQ,5714
87
+ TB2J-0.9.1rc0.dist-info/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
88
+ TB2J-0.9.1rc0.dist-info/METADATA,sha256=ymoIhPvH2rmZH5KQRPcDlCBqhctXKTukTDCmdFzZM4w,1421
89
+ TB2J-0.9.1rc0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
90
+ TB2J-0.9.1rc0.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
91
+ TB2J-0.9.1rc0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5