TB2J 0.8.0__py3-none-any.whl → 0.8.2.1__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 +1 -1
- TB2J/abacus/abacus_wrapper.py +28 -8
- TB2J/abacus/gen_exchange_abacus.py +4 -3
- TB2J/abacus/stru_api.py +3 -2
- TB2J/io_exchange/io_exchange.py +29 -0
- TB2J/io_merge.py +2 -2
- TB2J/manager.py +15 -0
- TB2J/myTB.py +26 -13
- TB2J/sisl_wrapper.py +104 -0
- TB2J/wannier/__init__.py +1 -1
- TB2J/wannier/w90_parser.py +11 -1
- TB2J/wannier/w90_tb_parser.py +129 -0
- {TB2J-0.8.0.dist-info → TB2J-0.8.2.1.dist-info}/METADATA +1 -1
- {TB2J-0.8.0.dist-info → TB2J-0.8.2.1.dist-info}/RECORD +26 -25
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/TB2J_downfold.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/TB2J_eigen.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/TB2J_magnon.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/TB2J_magnon_dos.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/TB2J_merge.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/TB2J_rotate.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/abacus2J.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/siesta2J.py +0 -0
- {TB2J-0.8.0.data → TB2J-0.8.2.1.data}/scripts/wann2J.py +0 -0
- {TB2J-0.8.0.dist-info → TB2J-0.8.2.1.dist-info}/LICENSE +0 -0
- {TB2J-0.8.0.dist-info → TB2J-0.8.2.1.dist-info}/WHEEL +0 -0
- {TB2J-0.8.0.dist-info → TB2J-0.8.2.1.dist-info}/top_level.txt +0 -0
TB2J/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.8.
|
1
|
+
__version__ = "0.8.2.1"
|
TB2J/abacus/abacus_wrapper.py
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
The abacus wrapper
|
5
5
|
"""
|
6
6
|
from pathlib import Path
|
7
|
+
import os
|
7
8
|
import numpy as np
|
8
9
|
from scipy.linalg import eigh
|
9
10
|
from TB2J.utils import symbol_number_list
|
@@ -117,13 +118,20 @@ class AbacusParser:
|
|
117
118
|
return "non-polarized"
|
118
119
|
elif nspin == 2:
|
119
120
|
return "collinear"
|
120
|
-
elif nspin ==
|
121
|
+
elif nspin == 4:
|
121
122
|
return "noncollinear"
|
122
123
|
else:
|
123
124
|
raise ValueError("nspin should be either 1 or 4.")
|
124
125
|
|
125
126
|
def read_atoms(self):
|
126
|
-
|
127
|
+
path1=str(Path(self.outpath) / "../STRU")
|
128
|
+
path2=str(Path(self.outpath) / "../Stru")
|
129
|
+
if os.path.exists(path1):
|
130
|
+
self.atoms = read_abacus(path1)
|
131
|
+
elif os.path.exists(path2):
|
132
|
+
self.atoms = read_abacus(path2)
|
133
|
+
else:
|
134
|
+
raise Exception("The STRU or Stru file cannot be found.")
|
127
135
|
return self.atoms
|
128
136
|
|
129
137
|
def read_basis(self):
|
@@ -145,14 +153,15 @@ class AbacusParser:
|
|
145
153
|
|
146
154
|
def Read_HSR_noncollinear(self, binary=None):
|
147
155
|
p = Path(self.outpath)
|
148
|
-
SR_filename = (p / "data-SR-sparse_SPIN0.csr")
|
149
|
-
HR_filename = p / "data-HR-sparse_SPIN0.csr"
|
150
|
-
|
156
|
+
SR_filename = str(p / "data-SR-sparse_SPIN0.csr")
|
157
|
+
HR_filename = str(p / "data-HR-sparse_SPIN0.csr")
|
158
|
+
nbasis, Rlist, HR, SR = read_HR_SR(
|
151
159
|
nspin=4,
|
152
160
|
binary=self.binary,
|
153
161
|
HR_fileName=HR_filename,
|
154
162
|
SR_fileName=SR_filename,
|
155
163
|
)
|
164
|
+
return nbasis, Rlist, HR, SR
|
156
165
|
|
157
166
|
def get_models(self):
|
158
167
|
if self.spin == "collinear":
|
@@ -205,7 +214,7 @@ class AbacusParser:
|
|
205
214
|
return basis
|
206
215
|
|
207
216
|
|
208
|
-
def
|
217
|
+
def test_abacus_wrapper_collinear():
|
209
218
|
outpath = "/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Fe/1_no_soc/OUT.Fe"
|
210
219
|
parser = AbacusParser(outpath=outpath, spin=None, binary=False)
|
211
220
|
atoms = parser.read_atoms()
|
@@ -216,8 +225,19 @@ def test_abacus_wrapper():
|
|
216
225
|
# print(H.shape)
|
217
226
|
# print(H.diagonal().real)
|
218
227
|
# print(model_up.get_HR0().diagonal().real)
|
219
|
-
print(parser.
|
228
|
+
print(parser.efermi)
|
229
|
+
|
230
|
+
|
231
|
+
def test_abacus_wrapper_ncl():
|
232
|
+
outpath = "/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Fe/2_soc/OUT.Fe"
|
233
|
+
|
234
|
+
parser = AbacusParser(outpath=outpath, spin=None, binary=False)
|
235
|
+
atoms = parser.read_atoms()
|
236
|
+
model = parser.get_models()
|
237
|
+
H, S, E, V = model.HSE_k([0, 0, 0])
|
238
|
+
print(parser.efermi)
|
220
239
|
|
221
240
|
|
222
241
|
if __name__ == "__main__":
|
223
|
-
test_abacus_wrapper()
|
242
|
+
# test_abacus_wrapper()
|
243
|
+
test_abacus_wrapper_ncl()
|
@@ -68,7 +68,7 @@ data directory: {outpath}
|
|
68
68
|
else:
|
69
69
|
tbmodel = parser.get_models()
|
70
70
|
print("Starting to calculate exchange.")
|
71
|
-
description = f""" Input from collinear Abacus data.
|
71
|
+
description = f""" Input from non-collinear Abacus data.
|
72
72
|
data directory: {outpath}
|
73
73
|
\n"""
|
74
74
|
exchange = ExchangeNCL(
|
@@ -83,6 +83,7 @@ data directory: {outpath}
|
|
83
83
|
nz=nz,
|
84
84
|
exclude_orbs=exclude_orbs,
|
85
85
|
Rcut=Rcut,
|
86
|
+
np=np,
|
86
87
|
use_cache=use_cache,
|
87
88
|
description=description,
|
88
89
|
)
|
@@ -93,8 +94,8 @@ data directory: {outpath}
|
|
93
94
|
|
94
95
|
if __name__ == "__main__":
|
95
96
|
gen_exchange_abacus(
|
96
|
-
path="/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Fe/
|
97
|
-
|
97
|
+
path="/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Fe/2_soc",
|
98
|
+
suffix="Fe",
|
98
99
|
magnetic_elements=["Fe"],
|
99
100
|
nz=50,
|
100
101
|
Rcut=8,
|
TB2J/abacus/stru_api.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
"""
|
3
|
-
|
4
|
-
@
|
3
|
+
@author: Zhen-Xiong Shen
|
4
|
+
@email: shenzx@iai.ustc.edu.cn
|
5
|
+
@workplace: Institute of Artificial Intelligence, Hefei Comprehensive National Science Center
|
5
6
|
|
6
7
|
Modified on Wed Aug 01 11:44:51 2022
|
7
8
|
@author: Ji Yu-yang
|
TB2J/io_exchange/io_exchange.py
CHANGED
@@ -19,6 +19,7 @@ from datetime import datetime
|
|
19
19
|
import matplotlib.pyplot as plt
|
20
20
|
from TB2J.spinham.spin_api import SpinModel
|
21
21
|
from TB2J.io_exchange.io_txt import write_Jq_info
|
22
|
+
from TB2J.utils import symbol_number
|
22
23
|
|
23
24
|
|
24
25
|
class SpinIO(object):
|
@@ -212,7 +213,23 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
212
213
|
def get_spin_ispin(self, i):
|
213
214
|
return self.spinat[self.iatom(i)]
|
214
215
|
|
216
|
+
def get_symbol_number_ispin(self, symnum):
|
217
|
+
"""
|
218
|
+
Return the spin index for a given symbol number.
|
219
|
+
"""
|
220
|
+
symdict = symbol_number(self.atoms)
|
221
|
+
return self.index_spin[symdict[symnum]]
|
222
|
+
|
223
|
+
def i_spin(self, i):
|
224
|
+
if isinstance(i, int):
|
225
|
+
return i
|
226
|
+
elif isinstance(i, str):
|
227
|
+
return self.get_symbol_number_ispin(i)
|
228
|
+
else:
|
229
|
+
raise ValueError("i must be either an integer or a string.")
|
230
|
+
|
215
231
|
def get_charge_ispin(self, i):
|
232
|
+
i = self.i_spin(i)
|
216
233
|
return self.charges[self.iatom(i)]
|
217
234
|
|
218
235
|
def get_spin_iatom(self, iatom):
|
@@ -222,6 +239,8 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
222
239
|
return self.charges[iatom]
|
223
240
|
|
224
241
|
def get_J(self, i, j, R, default=None):
|
242
|
+
i = self.i_spin(i)
|
243
|
+
j = self.i_spin(j)
|
225
244
|
key = (
|
226
245
|
tuple(R),
|
227
246
|
i,
|
@@ -233,6 +252,8 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
233
252
|
return default
|
234
253
|
|
235
254
|
def get_Jiso(self, i, j, R, default=None):
|
255
|
+
i = self.i_spin(i)
|
256
|
+
j = self.i_spin(j)
|
236
257
|
key = (
|
237
258
|
tuple(R),
|
238
259
|
i,
|
@@ -244,6 +265,8 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
244
265
|
return default
|
245
266
|
|
246
267
|
def get_DMI(self, i, j, R, default=None):
|
268
|
+
i = self.i_spin(i)
|
269
|
+
j = self.i_spin(j)
|
247
270
|
key = (
|
248
271
|
tuple(R),
|
249
272
|
i,
|
@@ -261,6 +284,8 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
261
284
|
param j: spin index j
|
262
285
|
param R (tuple of integers): cell index R
|
263
286
|
"""
|
287
|
+
i = self.i_spin(i)
|
288
|
+
j = self.i_spin(j)
|
264
289
|
key = (
|
265
290
|
tuple(R),
|
266
291
|
i,
|
@@ -278,6 +303,8 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
278
303
|
param j: spin index j
|
279
304
|
param R (tuple of integers): cell index R
|
280
305
|
"""
|
306
|
+
i = self.i_spin(i)
|
307
|
+
j = self.i_spin(j)
|
281
308
|
if iso_only:
|
282
309
|
Jtensor = np.eye(3) * self.get_J(i, j, R)
|
283
310
|
else:
|
@@ -295,6 +322,8 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
295
322
|
returns:
|
296
323
|
Jmat: (3*nspin,3*nspin) matrix.
|
297
324
|
"""
|
325
|
+
i = self.i_spin(i)
|
326
|
+
j = self.i_spin(j)
|
298
327
|
n3 = self.nspin * 3
|
299
328
|
Jmat = np.zeros((n3, n3), dtype=float)
|
300
329
|
for i in range(self.nspin):
|
TB2J/io_merge.py
CHANGED
@@ -215,9 +215,9 @@ class Merger2:
|
|
215
215
|
)
|
216
216
|
w = Jani_removed / Jani
|
217
217
|
Jani_sum += Jani * w # Jani_removed
|
218
|
-
print(f"{Jani* w=}")
|
218
|
+
#print(f"{Jani* w=}")
|
219
219
|
weights += w
|
220
|
-
print(f"{weights=}")
|
220
|
+
#print(f"{weights=}")
|
221
221
|
if np.any(weights == 0):
|
222
222
|
raise RuntimeError(
|
223
223
|
"The data set to be merged does not give a complete anisotropic J tensor, please add more data"
|
TB2J/manager.py
CHANGED
@@ -284,6 +284,21 @@ def gen_exchange_siesta(
|
|
284
284
|
raise ImportError(
|
285
285
|
f"sisl version is {sisl.__version__}, but should be larger than 0.10.0."
|
286
286
|
)
|
287
|
+
|
288
|
+
include_orbs = {}
|
289
|
+
if isinstance(magnetic_elements, str):
|
290
|
+
magnetic_elements = [magnetic_elements]
|
291
|
+
for element in magnetic_elements:
|
292
|
+
if "_" in element:
|
293
|
+
elem = element.split("_")[0]
|
294
|
+
orb = element.split("_")[1:]
|
295
|
+
include_orbs[elem] = orb
|
296
|
+
else:
|
297
|
+
include_orbs[element] = None
|
298
|
+
magnetic_elements = list(include_orbs.keys())
|
299
|
+
print(magnetic_elements)
|
300
|
+
print(include_orbs)
|
301
|
+
|
287
302
|
fdf = sisl.get_sile(fdf_fname)
|
288
303
|
geom = fdf.read_geometry()
|
289
304
|
H = fdf.read_hamiltonian()
|
TB2J/myTB.py
CHANGED
@@ -9,7 +9,7 @@ from collections import defaultdict
|
|
9
9
|
# from tbmodels import Model
|
10
10
|
from ase.atoms import Atoms
|
11
11
|
from TB2J.utils import auto_assign_basis_name
|
12
|
-
from TB2J.wannier import parse_ham, parse_xyz, parse_atoms
|
12
|
+
from TB2J.wannier import parse_ham, parse_xyz, parse_atoms, parse_tb
|
13
13
|
|
14
14
|
|
15
15
|
class AbstractTB:
|
@@ -84,6 +84,7 @@ class MyTB(AbstractTB):
|
|
84
84
|
self,
|
85
85
|
nbasis,
|
86
86
|
data=None,
|
87
|
+
R_degens=None,
|
87
88
|
positions=None,
|
88
89
|
sparse=False,
|
89
90
|
ndim=3,
|
@@ -93,6 +94,7 @@ class MyTB(AbstractTB):
|
|
93
94
|
"""
|
94
95
|
:param nbasis: number of basis.
|
95
96
|
:param data: a dictionary of {R: matrix}. R is a tuple, matrix is a nbasis*nbasis matrix.
|
97
|
+
:param R_degens: degeneracy of R.
|
96
98
|
:param positions: reduced positions.
|
97
99
|
:param sparse: Bool, whether to use a sparse matrix.
|
98
100
|
:param ndim: number of dimensions.
|
@@ -107,6 +109,10 @@ class MyTB(AbstractTB):
|
|
107
109
|
self._nspin = nspin
|
108
110
|
self._norb = nbasis // nspin
|
109
111
|
self._ndim = ndim
|
112
|
+
if R_degens is not None:
|
113
|
+
self.R_degens = R_degens
|
114
|
+
else:
|
115
|
+
self.R_degens = np.ones(len(self.data.keys()), dtype=int)
|
110
116
|
if positions is None:
|
111
117
|
self._positions = np.zeros((nbasis, self.ndim))
|
112
118
|
else:
|
@@ -121,7 +127,6 @@ class MyTB(AbstractTB):
|
|
121
127
|
self.k2Rfactor = -2.0j * np.pi
|
122
128
|
self.is_siesta = False
|
123
129
|
self.is_orthogonal = True
|
124
|
-
|
125
130
|
self._name = "Wannier"
|
126
131
|
|
127
132
|
def set_atoms(self, atoms):
|
@@ -178,12 +183,17 @@ class MyTB(AbstractTB):
|
|
178
183
|
:param path: path
|
179
184
|
:param prefix: prefix to the wannier files, often wannier90, or wannier90_up, or wannier90_dn for vasp.
|
180
185
|
"""
|
181
|
-
# tbmodel = Model.from_wannier_folder(
|
182
|
-
# folder=path, prefix=prefix)
|
183
|
-
# m = MyTB.from_tbmodel(tbmodel)
|
184
186
|
|
185
|
-
|
186
|
-
|
187
|
+
tb_fname = os.path.join(path, prefix + "_tb.dat")
|
188
|
+
hr_fname = os.path.join(path, prefix + "_hr.dat")
|
189
|
+
if os.path.exists(tb_fname):
|
190
|
+
xcart, nbasis, data, R_degens = parse_tb(fname=tb_fname)
|
191
|
+
else:
|
192
|
+
nbasis, data, R_degens = parse_ham(
|
193
|
+
fname=os.path.join(path, prefix + "_hr.dat")
|
194
|
+
)
|
195
|
+
xcart, _, _ = parse_xyz(fname=os.path.join(path, prefix + "_centres.xyz"))
|
196
|
+
|
187
197
|
if atoms is None:
|
188
198
|
atoms = parse_atoms(os.path.join(path, prefix + ".win"))
|
189
199
|
cell = atoms.get_cell()
|
@@ -200,7 +210,7 @@ class MyTB(AbstractTB):
|
|
200
210
|
data[key][1::2, ::2] = dtmp[norb:, :norb]
|
201
211
|
data[key][1::2, 1::2] = dtmp[norb:, norb:]
|
202
212
|
ind, positions = auto_assign_basis_name(xred, atoms)
|
203
|
-
m = MyTB(nbasis=nbasis, data=data, positions=xred)
|
213
|
+
m = MyTB(nbasis=nbasis, data=data, positions=xred, R_degens=R_degens)
|
204
214
|
nm = m.shift_position(positions)
|
205
215
|
nm.set_atoms(atoms)
|
206
216
|
return nm
|
@@ -243,13 +253,16 @@ class MyTB(AbstractTB):
|
|
243
253
|
"""
|
244
254
|
Hk = np.zeros((self.nbasis, self.nbasis), dtype="complex")
|
245
255
|
if convention == 2:
|
246
|
-
for R, mat in self.data.items():
|
247
|
-
phase = np.exp(self.R2kfactor * np.dot(k, R))
|
256
|
+
for iR, (R, mat) in enumerate(self.data.items()):
|
257
|
+
phase = np.exp(self.R2kfactor * np.dot(k, R)) # /self.R_degens[iR]
|
248
258
|
H = mat * phase
|
249
259
|
Hk += H + H.conjugate().T
|
250
260
|
elif convention == 1:
|
251
|
-
for R, mat in self.data.items():
|
252
|
-
phase =
|
261
|
+
for iR, (R, mat) in enumerate(self.data.items()):
|
262
|
+
phase = (
|
263
|
+
np.exp(self.R2kfactor * np.dot(k, R + self.rjminusri))
|
264
|
+
/ self.R_degens[iR]
|
265
|
+
)
|
253
266
|
H = mat * phase
|
254
267
|
Hk += H + H.conjugate().T
|
255
268
|
else:
|
@@ -369,7 +382,7 @@ class MyTB(AbstractTB):
|
|
369
382
|
newpos = copy.deepcopy(pos)
|
370
383
|
for i in range(self.nbasis):
|
371
384
|
newpos[i] = pos[i] - shift[i]
|
372
|
-
d = MyTB(self.nbasis, ndim=self.ndim, nspin=self.nspin)
|
385
|
+
d = MyTB(self.nbasis, ndim=self.ndim, nspin=self.nspin, R_degens=self.R_degens)
|
373
386
|
d._positions = newpos
|
374
387
|
|
375
388
|
for R, v in self.data.items():
|
TB2J/sisl_wrapper.py
CHANGED
@@ -258,6 +258,110 @@ class SislWrapper(AbstractTB):
|
|
258
258
|
return 0.0
|
259
259
|
|
260
260
|
|
261
|
+
class SislWFSXWrapper(SislWrapper):
|
262
|
+
"""Wrapper for retrieving eigenvalues and eigenvectors from siesta WFSX file
|
263
|
+
|
264
|
+
Parameters
|
265
|
+
----------
|
266
|
+
geom : sisl.Geometry
|
267
|
+
the geometry containing information about atomic positions and orbitals
|
268
|
+
wfsx_sile: sisl.io.siesta.wfsxSileSiesta
|
269
|
+
file reader for WFSX file
|
270
|
+
spin : sisl.physics.Spin
|
271
|
+
spin object carrying information about spin configurations and spin component.
|
272
|
+
ispin : None or int
|
273
|
+
index of spin channel to be considered. Only takes effect for collinear spin calculations (UP: 0, DOWN: 1).
|
274
|
+
(default: None)
|
275
|
+
shift_fermi: None or float
|
276
|
+
energy shift to be applied to all energies. If `None` no shift is applied. (default: None)
|
277
|
+
"""
|
278
|
+
|
279
|
+
def __init__(self, geom, wfsx_sile, spin, ispin=None, shift_fermi=None):
|
280
|
+
# super().__init__(geom, spin=spin, ispin=ispin, shift_fermi=shift_fermi)
|
281
|
+
super().__init__(sisl_hamiltonian, geom=None, spin=None)
|
282
|
+
self.geom = geom
|
283
|
+
self.wfsx_sile = wfsx_sile
|
284
|
+
self.read_all()
|
285
|
+
|
286
|
+
def read_all(self):
|
287
|
+
"""Read all wavefunctions, eigenvalues, and k-points from WFSX file."""
|
288
|
+
evals = []
|
289
|
+
evecs = []
|
290
|
+
wfsx_kpts = []
|
291
|
+
|
292
|
+
def change_gauge(k, evec):
|
293
|
+
"""Change the eigenvector gauge"""
|
294
|
+
phase = np.dot(
|
295
|
+
self.geom.xyz[self.geom.o2a(np.arange(self.geom.no)), :],
|
296
|
+
np.dot(k, self.geom.rcell),
|
297
|
+
)
|
298
|
+
if self.spin.has_noncolinear:
|
299
|
+
# for NC/SOC we have a 2x2 spin-box per orbital
|
300
|
+
phase = np.repeat(phase, 2)
|
301
|
+
# r -> R gauge tranformation.
|
302
|
+
return evec * np.exp(1j * phase).reshape(1, -1)
|
303
|
+
|
304
|
+
# Read wavefunctions and eigenvalues
|
305
|
+
for wfc in self.wfsx_sile.yield_eigenstate(parent=self.geom):
|
306
|
+
wfsx_kpts.append(wfc.info["k"])
|
307
|
+
evals.append(wfc.c)
|
308
|
+
# To get the same eigvecs as eigh returns we need to transpose the
|
309
|
+
# array and change the gauge from 'r' to 'R'
|
310
|
+
evecs.append(change_gauge(wfc.info["k"], wfc.state).T)
|
311
|
+
|
312
|
+
# If any k-point occurs more than once in the WaveFuncKPoints block,
|
313
|
+
# we discard the duplicates
|
314
|
+
is_duplicate = self._is_duplicate(wfsx_kpts)
|
315
|
+
self.wfsx_kpts = wfsx_kpts[~is_duplicate]
|
316
|
+
self.evals = np.array(evals, dtype=float)[~is_duplicate]
|
317
|
+
if self.shift_fermi is not None:
|
318
|
+
self.evals += self.shift_fermi
|
319
|
+
self.evecs = np.array(evecs, dtype=np.complex64, order="C")[~is_duplicate]
|
320
|
+
|
321
|
+
def _is_duplicate(self, array):
|
322
|
+
# TODO: Move into utils
|
323
|
+
# Find all matches (i,j): array[i] == array[j]
|
324
|
+
matches = np.all(np.isclose(array[None, :], array[:, None]), axis=-1)
|
325
|
+
# Remove double counting of matches: (i,j) and (j,i)
|
326
|
+
# Also, remove matches of elements with themselves: (i,i)
|
327
|
+
matches = np.triu(matches, 1)
|
328
|
+
|
329
|
+
# Finally determine elements which are duplicates
|
330
|
+
return np.any(matches, axis=0)
|
331
|
+
|
332
|
+
def find_all(self, kpts):
|
333
|
+
"""Find the correct eigenvectors and eigenvalues and sort them
|
334
|
+
to match the order in kpts.
|
335
|
+
|
336
|
+
Parameters
|
337
|
+
----------
|
338
|
+
kpts : list of float (3,) or (nk, 3)
|
339
|
+
list of k points
|
340
|
+
|
341
|
+
Returns
|
342
|
+
-------
|
343
|
+
evals : list of float (nk, n)
|
344
|
+
list of eigenvalues for every requested k point
|
345
|
+
evecs :
|
346
|
+
list of eiegnvector for every requested k point
|
347
|
+
"""
|
348
|
+
kpts = np.asarray(kpts)
|
349
|
+
sort_idx = np.where(
|
350
|
+
np.all(np.isclose(self.wfsx_kpts[None, :], kpts[:, None]), axis=-1)
|
351
|
+
)[1]
|
352
|
+
if len(sort_idx) < len(kpts):
|
353
|
+
# k-point not found
|
354
|
+
raise ValueError(
|
355
|
+
f"{self.__class__.__name__}._read_all unable to find at least one "
|
356
|
+
"required k point in '{self.wfsx_sile.file}'. Please, ensure that "
|
357
|
+
"all k points listed below are included:\n"
|
358
|
+
+ "\n".join([str(k) for k in kpts])
|
359
|
+
)
|
360
|
+
if not np.all(np.isclose(self.wfsx_kpts[sort_idx], kpts)):
|
361
|
+
# raise ValueError( wfsx_kpts = np.asarray(wfsx_kpts)
|
362
|
+
pass
|
363
|
+
|
364
|
+
|
261
365
|
# def test():
|
262
366
|
# fdf = sisl.get_sile('/home/hexu/projects/learn_siesta/SMO_Wannier/siesta.fdf')
|
263
367
|
# H = fdf.read_hamiltonian(order='nc',dim=2)
|
TB2J/wannier/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
from TB2J.wannier.w90_parser import parse_xyz, parse_ham, parse_atoms
|
1
|
+
from TB2J.wannier.w90_parser import parse_xyz, parse_ham, parse_atoms, parse_tb
|
TB2J/wannier/w90_parser.py
CHANGED
@@ -5,6 +5,7 @@ import numpy as np
|
|
5
5
|
from ase.io import read
|
6
6
|
from ase.atoms import Atoms
|
7
7
|
from ase.units import Angstrom, Bohr
|
8
|
+
from .w90_tb_parser import parse_tb_file
|
8
9
|
|
9
10
|
unit_dict = {"ANG": Angstrom, "BOHR": Bohr}
|
10
11
|
|
@@ -49,6 +50,7 @@ def parse_ham(fname="wannier90_hr.dat", cutoff=None):
|
|
49
50
|
for i in range(3, 3 + nline):
|
50
51
|
d = map(float, lines[i].strip().split())
|
51
52
|
dlist += d
|
53
|
+
R_degens = np.array(dlist, dtype=int)
|
52
54
|
H_mnR = defaultdict(lambda: np.zeros((n_wann, n_wann), dtype=complex))
|
53
55
|
for i in range(3 + nline, 3 + nline + n_wann**2 * n_R):
|
54
56
|
t = lines[i].strip().split()
|
@@ -65,7 +67,7 @@ def parse_ham(fname="wannier90_hr.dat", cutoff=None):
|
|
65
67
|
H_mnR[R][m, n] = val / 2.0
|
66
68
|
else:
|
67
69
|
H_mnR[R][m, n] = val / 2.0
|
68
|
-
return n_wann, H_mnR
|
70
|
+
return n_wann, H_mnR, R_degens
|
69
71
|
|
70
72
|
|
71
73
|
def parse_cell(fname, unit=Angstrom):
|
@@ -138,3 +140,11 @@ def parse_atoms(fname):
|
|
138
140
|
taus = taus * factor
|
139
141
|
atoms = Atoms(symbols=symbols, cell=cell, positions=taus)
|
140
142
|
return atoms
|
143
|
+
|
144
|
+
|
145
|
+
def parse_tb(fname):
|
146
|
+
"""
|
147
|
+
return the wannier center, number of wannier functions and the Hamiltonian from the wannier90 _tb.dat file.
|
148
|
+
"""
|
149
|
+
result = parse_tb_file(fname)
|
150
|
+
return result["centers"], result["n_wann"], result["H"], result["Rdegens"]
|
@@ -0,0 +1,129 @@
|
|
1
|
+
"""
|
2
|
+
parse the tb files in Wannier90
|
3
|
+
"""
|
4
|
+
|
5
|
+
import os
|
6
|
+
import re
|
7
|
+
import numpy as np
|
8
|
+
from typing import List, Tuple, Dict
|
9
|
+
|
10
|
+
|
11
|
+
def ssrline(file):
|
12
|
+
"""
|
13
|
+
Read a line and split it into a list of strings"""
|
14
|
+
line = file.readline().strip()
|
15
|
+
return re.split(r"\s+", line)
|
16
|
+
|
17
|
+
|
18
|
+
def parse_vector(file, vector_type, size):
|
19
|
+
result = np.zeros((size,), dtype=vector_type)
|
20
|
+
for i in range(size):
|
21
|
+
result[i] = np.fromstring(file.readline().strip(), sep=" ")
|
22
|
+
result[i] = result[i].astype(vector_type)
|
23
|
+
return result
|
24
|
+
|
25
|
+
|
26
|
+
def find_Rvectors(Rvectors, R):
|
27
|
+
for i, Rvec in enumerate(Rvectors):
|
28
|
+
if np.all(Rvec == R):
|
29
|
+
return i
|
30
|
+
return -1
|
31
|
+
|
32
|
+
|
33
|
+
def parse_tb_file(filename):
|
34
|
+
with open(filename, "r") as io:
|
35
|
+
header = io.readline().strip()
|
36
|
+
a1 = np.fromstring(io.readline().strip(), sep=" ")
|
37
|
+
a2 = np.fromstring(io.readline().strip(), sep=" ")
|
38
|
+
a3 = np.fromstring(io.readline().strip(), sep=" ")
|
39
|
+
# a1, a2, a3 = np.array(list(map(float, [a1, a2, a3])), dtype=np.float64)
|
40
|
+
# lattice = np.vstack((a1.reshape(-1, 1), a2.reshape(-1, 1), a3.reshape(-1, 1))).T
|
41
|
+
lattice = np.vstack((a1, a2, a3))
|
42
|
+
|
43
|
+
n_wann = int(ssrline(io)[0])
|
44
|
+
n_Rvecs = int(ssrline(io)[0])
|
45
|
+
|
46
|
+
Rdegens = []
|
47
|
+
line = io.readline().strip()
|
48
|
+
while line != "":
|
49
|
+
Rdegens += [int(x) for x in line.split()]
|
50
|
+
line = io.readline().strip()
|
51
|
+
assert len(Rdegens) == n_Rvecs, "Rdegens length does not match n_Rvecs"
|
52
|
+
|
53
|
+
Rvectors = np.zeros((n_Rvecs, 3), dtype=np.int32)
|
54
|
+
# H = np.zeros((n_Rvecs,n_wann, n_wann), dtype=np.complex128)
|
55
|
+
H = {}
|
56
|
+
r_x = np.zeros((n_Rvecs, n_wann, n_wann), dtype=np.complex128)
|
57
|
+
r_y = np.zeros((n_Rvecs, n_wann, n_wann), dtype=np.complex128)
|
58
|
+
r_z = np.zeros((n_Rvecs, n_wann, n_wann), dtype=np.complex128)
|
59
|
+
pos_operator = np.zeros((n_Rvecs, n_wann, n_wann, 3), dtype=np.complex128)
|
60
|
+
|
61
|
+
for iR in range(n_Rvecs):
|
62
|
+
# read Rvectors
|
63
|
+
Rvectors[iR] = np.fromstring(io.readline().strip(), sep=" ")
|
64
|
+
Rvectors[iR] = Rvectors[iR].astype(np.int32)
|
65
|
+
R = tuple(Rvectors[iR])
|
66
|
+
H[R] = np.zeros((n_wann, n_wann), dtype=np.complex128)
|
67
|
+
# read H
|
68
|
+
for n in range(n_wann):
|
69
|
+
for m in range(n_wann):
|
70
|
+
line = ssrline(io)
|
71
|
+
assert (
|
72
|
+
m == int(line[0]) - 1 and n == int(line[1]) - 1
|
73
|
+
), "Unexpected indices"
|
74
|
+
reH, imH = float(line[2]), float(line[3])
|
75
|
+
# H[iR][m, n] = reH + 1j * imH
|
76
|
+
H[R][m, n] = (reH + 1j * imH) / 2.0
|
77
|
+
io.readline() # empty line
|
78
|
+
# set the onsite term to half
|
79
|
+
# np.fill_diagonal(H[(0, 0, 0)], H[(0, 0, 0)].diagonal() / 2.0)
|
80
|
+
# print("onsite H from TB: ", H[(0, 0, 0)].diagonal())
|
81
|
+
|
82
|
+
iR0 = find_Rvectors(Rvectors, [0, 0, 0])
|
83
|
+
for iR in range(n_Rvecs):
|
84
|
+
# read Rvectors
|
85
|
+
line = io.readline().strip()
|
86
|
+
Rvectors[iR] = np.fromstring(line, sep=" ")
|
87
|
+
Rvectors[iR] = Rvectors[iR].astype(np.int32)
|
88
|
+
# read r_x, r_y, r_z
|
89
|
+
for n in range(n_wann):
|
90
|
+
for m in range(n_wann):
|
91
|
+
line = ssrline(io)
|
92
|
+
assert (
|
93
|
+
m == int(line[0]) - 1 and n == int(line[1]) - 1
|
94
|
+
), f"Unexpected indices in line {line}"
|
95
|
+
pos_operator[iR, m, n, 0] = complex(float(line[2]), float(line[3]))
|
96
|
+
pos_operator[iR, m, n, 1] = complex(float(line[4]), float(line[5]))
|
97
|
+
pos_operator[iR, m, n, 2] = complex(float(line[6]), float(line[7]))
|
98
|
+
io.readline()
|
99
|
+
|
100
|
+
# print(
|
101
|
+
# f"Reading tb.dat file: {filename} | Header: {header} | n_wann: {n_wann} | n_Rvecs: {n_Rvecs}"
|
102
|
+
# )
|
103
|
+
|
104
|
+
centers = pos_operator[iR0, :, :, :].diagonal(offset=0, axis1=0, axis2=1).T.real
|
105
|
+
|
106
|
+
return {
|
107
|
+
"n_wann": n_wann,
|
108
|
+
"lattice": lattice,
|
109
|
+
"Rvectors": Rvectors,
|
110
|
+
"Rdegens": Rdegens,
|
111
|
+
"H": H,
|
112
|
+
"pos_operator": pos_operator,
|
113
|
+
"centers": centers,
|
114
|
+
"header": header,
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
def test_parse_tb_file():
|
119
|
+
filename = "cri3_up_tb.dat"
|
120
|
+
result = parse_tb_file(filename)
|
121
|
+
# rvecs=result["Rvectors"]
|
122
|
+
# iR=find_Rvectors(rvecs, [0, 0, 0])
|
123
|
+
# for i in range(30):
|
124
|
+
# print(np.real(result["pos_operator"][iR, i, i, :]))
|
125
|
+
print(result["centers"])
|
126
|
+
|
127
|
+
|
128
|
+
if __name__ == "__main__":
|
129
|
+
test_parse_tb_file()
|
@@ -2,7 +2,7 @@ TB2J/Jdownfolder.py,sha256=Nw2ixvn2Uq-o1wficz6rdaYHjfRN3U_kQCvrNJGNb68,6980
|
|
2
2
|
TB2J/Jtensor.py,sha256=0fhfOcfVQGu75gytEnApKWTJZfg9ksKJ0anJgco5wRQ,3179
|
3
3
|
TB2J/Oiju.py,sha256=yQMfxQGnOSLbuTS22upkEFsJ9UAZk7wFaWynvg1NVdA,3595
|
4
4
|
TB2J/Oiju_epc.py,sha256=sqjLIuWWT-d0uH2O7-6mobsUYQjHP5GyGlmdYqvkXFk,7332
|
5
|
-
TB2J/__init__.py,sha256=
|
5
|
+
TB2J/__init__.py,sha256=Gz3blTF1z7t2vohcgNvCiRBFGzinOatDXOyHy8k81ow,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
|
@@ -16,17 +16,17 @@ TB2J/exchange_qspace.py,sha256=ZL68qBGFUaQ9BsSPsJaaoWOr9RssPiqX34R_9I3nk_8,8436
|
|
16
16
|
TB2J/gpaw_wrapper.py,sha256=aJ--9Dtyq7jOP1Hkh-Sh1nWcfXm6zKcljOCO0DNCAr0,6890
|
17
17
|
TB2J/green.py,sha256=aaXFZn8B60kjsvThoBk0fVi5jm5RJBb-LT4E9XCFo2w,13169
|
18
18
|
TB2J/greentest.py,sha256=2ISSfhor9ecSEOi_E6b4Cv26wEIQlwlzca0ru8z44_E,1603
|
19
|
-
TB2J/io_merge.py,sha256=
|
19
|
+
TB2J/io_merge.py,sha256=H1jovWIvYRw4KABS6mEL5OwGZHm9emJ-QJjQpeJHwRU,15263
|
20
20
|
TB2J/kpoints.py,sha256=6XK2KqTncidEq3o9GuO6VEZRPNTRtWeXg9QfcV-9smI,532
|
21
|
-
TB2J/manager.py,sha256=
|
21
|
+
TB2J/manager.py,sha256=hiryBJ5b2LMmZ34GXc-gbk3WhWHh6Tjy5OXD-lposVo,15846
|
22
22
|
TB2J/mathutils.py,sha256=tHA6q3KPDpXLIbZHdDZ2NU5s886VVM_oEG490zQ6Ris,300
|
23
|
-
TB2J/myTB.py,sha256=
|
23
|
+
TB2J/myTB.py,sha256=cm9Kkyzi686QyoxrR3lm4rsSnE6Imee3-j2xM78XnGI,17721
|
24
24
|
TB2J/orbmap.py,sha256=RCMJkOPGbfPrcZzcc5ia1ZMKBQWxGcyj8W1ve8BJaEw,6669
|
25
25
|
TB2J/pauli.py,sha256=_FIF62jq2CkQdWC473a3S2F6NmzCdeCnglO9PjNVmMI,4120
|
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=-fxlQN7LbyQAbGUCUBqDJ5ENR0pT8MLBd-5sLxaX_vI,3031
|
29
|
-
TB2J/sisl_wrapper.py,sha256=
|
29
|
+
TB2J/sisl_wrapper.py,sha256=szeNB_VrRklcMCfWrwnI1Vsv5wqJ92EwwlrWNrIPHM0,14785
|
30
30
|
TB2J/supercell.py,sha256=4hgLGPBLRUDhtD-eF29v46ex7fHdkH-OENjS2wGLFww,19588
|
31
31
|
TB2J/tensor_rotate.py,sha256=4-DfT_Mg5e40fbd74M5W0D5DqmUq-kVOOLDkkkI834A,8083
|
32
32
|
TB2J/utest.py,sha256=z_ahi7tpHQF9WlHNQihcQ7qzfezRJQXQt28eB1X_z64,3897
|
@@ -34,16 +34,16 @@ TB2J/utils.py,sha256=xIKX6p6ULoESWngDLSJsfQQewxsvIWI5l7Uwj_Y5H7U,9262
|
|
34
34
|
TB2J/versioninfo.py,sha256=wZwS9QDFRVDe7rf8JyPDDI8UGdTQiO6Pb_sWv8GAegA,337
|
35
35
|
TB2J/abacus/__init__.py,sha256=5sHiDnF2L-Y80QeET9zOiS83a5T_TQAXvnIhcYB6wNU,56
|
36
36
|
TB2J/abacus/abacus_api.py,sha256=D_NyXW-Pno92d3RVHByx0l1HDPHQAvXsmQVt8cfIGR8,7267
|
37
|
-
TB2J/abacus/abacus_wrapper.py,sha256
|
38
|
-
TB2J/abacus/gen_exchange_abacus.py,sha256=
|
37
|
+
TB2J/abacus/abacus_wrapper.py,sha256=cvOem5WiWYcYqLRBopPACTMEFOvl2jFu2O9rlNbtoPI,8488
|
38
|
+
TB2J/abacus/gen_exchange_abacus.py,sha256=lKZqkWMnLQtaSwgn8O5Fzr-pV6tzwoMqfZU_vbET6gU,2973
|
39
39
|
TB2J/abacus/orbital_api.py,sha256=l48Hn5z7TA0TH7Is4NDmz74b6B9L2ztYO4dRR37U4mQ,1562
|
40
|
-
TB2J/abacus/stru_api.py,sha256=
|
40
|
+
TB2J/abacus/stru_api.py,sha256=aBKKlZ2hvAZChVCfNxRdxH51rfHKqZn6kOlazY-yW8k,67888
|
41
41
|
TB2J/abacus/test_read_HRSR.py,sha256=cAT-e79jGjCBXLTJ9UYX0WvalG_yD4Awl79tTOUcwaQ,1254
|
42
42
|
TB2J/abacus/test_read_stru.py,sha256=CpK4zWhlCVAMCmYQmp9Hy-A40OblZQLFpo5JokpNcWQ,785
|
43
43
|
TB2J/external/__init__.py,sha256=yD_ZIMi76H49rj6GAQpiB7UlKa3TgSaMkkLHT6M-8w8,137
|
44
44
|
TB2J/external/p_tqdm.py,sha256=ug1jy3-43r8iW7bC37xzPSIe0EjYKH_GUluGzMiQiDw,5831
|
45
45
|
TB2J/io_exchange/__init__.py,sha256=KfGHum7B8E4G_KKfillqw0lErtoyKEuFUUttHLs-mg4,32
|
46
|
-
TB2J/io_exchange/io_exchange.py,sha256=
|
46
|
+
TB2J/io_exchange/io_exchange.py,sha256=eJRQM1-ikuNJTfCAB0tgTFwvMA_TiWkGlevVu5CeeAk,19408
|
47
47
|
TB2J/io_exchange/io_multibinit.py,sha256=8PDmWxzGuv-GwJosj2ZTmiyNY_duFVWJ4ekCuSqGdd8,6739
|
48
48
|
TB2J/io_exchange/io_pickle.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
49
|
TB2J/io_exchange/io_tomsasd.py,sha256=NqkAC1Fl-CUnFA21eBzSy_S5F_oeQFJysw4UukQbN8o,4173
|
@@ -60,19 +60,20 @@ TB2J/spinham/qsolver.py,sha256=Sr9I3aGfVNYn5wzwPx1QonHe6ZZUXBAujWRa7nTA5u4,4986
|
|
60
60
|
TB2J/spinham/spin_api.py,sha256=oN3AKg1WQl0YzR4f5ealcJOaVoAy8d7HodIwrbXvQeY,2219
|
61
61
|
TB2J/spinham/spin_xml.py,sha256=mneeZzkCE5andvIlur_6VK3XzWvoL-PVqSoWKXtDYTM,11033
|
62
62
|
TB2J/spinham/supercell.py,sha256=y17uUC6r3gQb278FhxIW4CABihfLTvKFj6flyXrCPR8,12217
|
63
|
-
TB2J/wannier/__init__.py,sha256=
|
64
|
-
TB2J/wannier/w90_parser.py,sha256=
|
65
|
-
TB2J
|
66
|
-
TB2J-0.8.
|
67
|
-
TB2J-0.8.
|
68
|
-
TB2J-0.8.
|
69
|
-
TB2J-0.8.
|
70
|
-
TB2J-0.8.
|
71
|
-
TB2J-0.8.
|
72
|
-
TB2J-0.8.
|
73
|
-
TB2J-0.8.
|
74
|
-
TB2J-0.8.
|
75
|
-
TB2J-0.8.
|
76
|
-
TB2J-0.8.
|
77
|
-
TB2J-0.8.
|
78
|
-
TB2J-0.8.
|
63
|
+
TB2J/wannier/__init__.py,sha256=7ojCbM84PYv1X1Tbo4NHI-d3gWmQsZB_xiYqbfxVV1E,80
|
64
|
+
TB2J/wannier/w90_parser.py,sha256=vkZljyHu-TBts-5jmjgDNdfsQoD06PJQeBwajwOq9qg,4459
|
65
|
+
TB2J/wannier/w90_tb_parser.py,sha256=qt8pnuprmPp9iIAYwPkPbmEzk6ZPgMq2xognoQp7vwc,4610
|
66
|
+
TB2J-0.8.2.1.data/scripts/TB2J_downfold.py,sha256=F9oImXFysejCMP7eIBjbCX2jdHFOCvDW5beF1sG-UM8,1854
|
67
|
+
TB2J-0.8.2.1.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
|
68
|
+
TB2J-0.8.2.1.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
|
69
|
+
TB2J-0.8.2.1.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
|
70
|
+
TB2J-0.8.2.1.data/scripts/TB2J_merge.py,sha256=uZKLM__EyCHwxrQvx3Wd73dOEADp_SqfYC8KQvA-N9g,1622
|
71
|
+
TB2J-0.8.2.1.data/scripts/TB2J_rotate.py,sha256=XPacPb7-DaFafBXFdWuNW_eNbjd5XPdNhBRNYhge_cg,634
|
72
|
+
TB2J-0.8.2.1.data/scripts/abacus2J.py,sha256=M4B07lvTCDczTPTqvnDh_PERzCARAd09TLKv4aIdSQM,4408
|
73
|
+
TB2J-0.8.2.1.data/scripts/siesta2J.py,sha256=Q_kvdgE34JJKVUMgBCSe07kARge0XULJ9B6z8hQFu6M,4706
|
74
|
+
TB2J-0.8.2.1.data/scripts/wann2J.py,sha256=0g8Y5RbsYgV7iuoRQEeOnpaBy3oNpRfiw1dy6lWD13E,6520
|
75
|
+
TB2J-0.8.2.1.dist-info/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
|
76
|
+
TB2J-0.8.2.1.dist-info/METADATA,sha256=wqoI-chRFjU7XfO3zZTNH8B2L6mJsPefB_JJR_CkE-E,1464
|
77
|
+
TB2J-0.8.2.1.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
78
|
+
TB2J-0.8.2.1.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
|
79
|
+
TB2J-0.8.2.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|