TB2J 0.8.2.7__py3-none-any.whl → 0.9.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.
TB2J/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.8.2.7"
1
+ __version__ = "0.9.0"
@@ -18,8 +18,7 @@ class AbacusWrapper(AbstractTB):
18
18
  def __init__(self, HR, SR, Rlist, nbasis, nspin=1):
19
19
  self.R2kfactor = -2j * np.pi
20
20
  self.is_orthogonal = False
21
- self.is_siesta = False
22
- self._name = "Abacus"
21
+ self._name = "ABACUS"
23
22
  self.HR = HR
24
23
  self.SR = SR
25
24
  self.Rlist = Rlist
TB2J/exchange.py CHANGED
@@ -240,7 +240,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
240
240
  self.mmats = {}
241
241
  self.orbital_names = {}
242
242
  self.norb_reduced = {}
243
- if self.backend_name == "SIESTA":
243
+ if self.backend_name.upper() == "SIESTA":
244
244
  syms = self.atoms.get_chemical_symbols()
245
245
  for iatom, orbs in self.labels.items():
246
246
  if (self.include_orbs is not None) and syms[iatom] in self.include_orbs:
@@ -305,7 +305,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
305
305
  """
306
306
  sum up the contribution of all the orbitals with same (n,l,m)
307
307
  """
308
- if self.backend_name == "SIESTA":
308
+ if self.backend_name.upper() == "SIESTA":
309
309
  mmat_i = self.mmats[iatom]
310
310
  mmat_j = self.mmats[jatom]
311
311
  Jorbij = mmat_i.T @ Jorbij @ mmat_j
TB2J/green.py CHANGED
@@ -225,12 +225,22 @@ class TBGreen:
225
225
 
226
226
  def get_density_matrix(self):
227
227
  rho = np.zeros((self.nbasis, self.nbasis), dtype=complex)
228
- for ik, _ in enumerate(self.kpts):
229
- rho += (
230
- (self.get_evecs(ik) * fermi(self.evals[ik], self.efermi))
231
- @ self.get_evecs(ik).T.conj()
232
- * self.kweights[ik]
233
- )
228
+ if self.is_orthogonal:
229
+ for ik, _ in enumerate(self.kpts):
230
+ rho += (
231
+ (self.get_evecs(ik) * fermi(self.evals[ik], self.efermi))
232
+ @ self.get_evecs(ik).T.conj()
233
+ * self.kweights[ik]
234
+ )
235
+ else:
236
+ for ik, _ in enumerate(self.kpts):
237
+ rho += (
238
+ (self.get_evecs(ik) * fermi(self.evals[ik], self.efermi))
239
+ @ self.get_evecs(ik).T.conj()
240
+ @ self.get_Sk(ik)
241
+ * self.kweights[ik]
242
+ )
243
+
234
244
  return rho
235
245
 
236
246
  def get_rho_R(self, Rlist):
TB2J/io_merge.py CHANGED
@@ -1,435 +1,184 @@
1
1
  import os
2
2
  import copy
3
+ import warnings
3
4
  import numpy as np
4
- from scipy.spatial.transform import Rotation
5
+ from itertools import combinations_with_replacement, product
5
6
  from TB2J.io_exchange import SpinIO
6
- from TB2J.tensor_rotate import remove_components
7
- from TB2J.Jtensor import DMI_to_Jtensor, Jtensor_to_DMI
8
- from TB2J.tensor_rotate import Rzx, Rzy, Rzz, Ryz, Rxz
9
7
 
8
+ u0 = np.zeros(3)
9
+ uy = np.array([0.0, 1.0, 0.0])
10
+ uz = np.array([0.0, 0.0, 1.0])
10
11
 
11
- def test_rotation_matrix():
12
- x = [1, 0, 0]
13
- y = [0, 1, 0]
14
- z = [0, 0, 1]
15
- print(Rxz.apply(x))
16
- print(Ryz.apply(y))
17
- print(Rzx.apply(z))
18
- print(Rzy.apply(z))
19
-
20
-
21
- def recover_DMI_from_rotated_structure(Ddict, rotation):
22
- """
23
- Recover the DMI vector from the rotated structure.
24
- D: the dictionary of DMI vector in the rotated structure.
25
- rotation: the rotation operator from the original structure to the rotated structure.
26
- """
27
- for key, val in Ddict.items():
28
- Ddict[key] = rotation.apply(val, inverse=True)
29
- return Ddict
30
-
31
-
32
- def recover_Jani_fom_rotated_structure(Janidict, rotation):
33
- """
34
- Recover the Jani tensor from the rotated structure.
35
- Janidict: the dictionary of Jani tensor in the rotated structure.
36
- rotation: the from the original structure to the rotated structure.
37
- """
38
- R = rotation.as_matrix()
39
- RT = R.T
40
- for key, Jani in Janidict.items():
41
- # Note: E=Si J Sj , Si'= Si RT, Sj' = R Sj,
42
- # Si' J' Sj' = Si RT R J RT R Sj => J' = R J RT
43
- # But here we are doing the opposite rotation back to
44
- # the original axis, so we replace R with RT.
45
- Janidict[key] = RT @ Jani @ R
46
- return Janidict
47
-
48
-
49
- def recover_spinat_from_rotated_structure(spinat, rotation):
50
- """
51
- Recover the spinat from the rotated structure.
52
- spinat: the spinat in the rotated structure.
53
- rotation: the rotation operator from the original structure to the rotated structure.
54
- """
55
- for i, spin in enumerate(spinat):
56
- spinat[i] = rotation.apply(spin, inverse=True)
57
- return spinat
58
-
59
-
60
- # test_rotation_matrix()
61
-
62
- # R_xyz = [Rxz.as_matrix(), Ryz.as_matrix(), np.eye(3, dtype=float)]
63
-
64
-
65
- def rot_merge_DMI(Dx, Dy, Dz):
66
- Dx_z = Rzx.apply(Dx)
67
- Dy_z = Rzy.apply(Dy)
68
- D = (
69
- np.array([0.0, 0.5, 0.5]) * Dx_z
70
- + np.array([0.5, 0.0, 0.5]) * Dy_z
71
- + np.array([0.5, 0.5, 0.0]) * Dz
72
- )
73
- return D
74
-
75
-
76
- def rot_merge_DMI2(Dx, Dy, Dz):
77
- Dx_z = Rzx.apply(Dx)
78
- Dy_z = Rzy.apply(Dy)
79
- D = (
80
- np.array([1, 0, 0]) * Dx_z
81
- + np.array([0, 1, 0]) * Dy_z
82
- + np.array([0, 0, 1]) * Dz
83
- )
84
- return D
12
+ def get_Jani_coefficients(a, R=np.eye(3)):
85
13
 
14
+ if len(a) == 1:
15
+ u = a
16
+ v = a
17
+ else:
18
+ u = a[[0, 0, 1]]
19
+ v = a[[0, 1, 1]]
20
+
21
+ ur = u @ R.T
22
+ vr = v @ R.T
23
+ coefficients = np.hstack([ur*vr, np.roll(ur, -1, axis=-1)*vr + np.roll(vr, -1, axis=-1)*ur])
86
24
 
87
- def merge_DMI(Dx, Dy, Dz):
88
- D = (
89
- np.array([0.0, 0.5, 0.5]) * Dx
90
- + np.array([0.5, 0.0, 0.5]) * Dy
91
- + np.array([0.5, 0.5, 0.0]) * Dz
92
- )
93
- return D
25
+ return coefficients, u, v
94
26
 
27
+ def get_projections(a, b, tol=1e-2):
95
28
 
96
- def merge_DMI2(Dx, Dy, Dz):
97
- D = np.array([1, 0, 0]) * Dx + np.array([0, 1, 0]) * Dy + np.array([0, 0, 1]) * Dz
98
- return D
29
+ projections = np.empty((2, 3))
30
+ if np.linalg.matrix_rank([a, b], tol=tol) == 1:
31
+ if np.linalg.matrix_rank([a, uy], tol=tol) == 1:
32
+ projections[0] = np.cross(a, uz)
33
+ else:
34
+ projections[0] = np.cross(a, uy)
35
+ projections[1] = np.cross(a, projections[0])
36
+ projections /= np.linalg.norm(projections, axis=-1).reshape(-1, 1)
37
+ else:
38
+ projections[0] = np.cross(a, b)
39
+ projections[0] /= np.linalg.norm(projections[0])
40
+ projections[1] = u0
99
41
 
42
+ return projections
100
43
 
101
- def swap_direction(m, idirections):
102
- """
103
- swap two directions of a tensor m.
104
- idirections: the index of the two directions.
105
- """
106
- idirections = list(idirections)
107
- inv = [idirections[1], idirections[0]]
108
- n = np.copy(m)
109
- n[:, idirections] = n[:, inv]
110
- n[idirections, :] = n[inv, :]
111
- return n
44
+ class SpinIO_merge(SpinIO):
45
+ def __init__(self, *args, **kwargs):
46
+ super(SpinIO_merge, self).__init__(*args, **kwargs)
47
+ self.projv = None
112
48
 
49
+ def _set_projection_vectors(self):
113
50
 
114
- def test_swap():
115
- m = np.reshape(np.arange(9), (3, 3))
116
- print(m)
117
- print(swap_direction(m, [0, 1]))
51
+ spinat = self.spinat
52
+ idx = [self.ind_atoms[i] for i in self.index_spin if i >= 0]
53
+ projv = {}
54
+ for i, j in combinations_with_replacement(range(self.nspin), 2):
55
+ a, b = spinat[idx][[i, j]]
56
+ projv[i, j] = get_projections(a, b)
57
+ projv[j, i] = projv[i, j]
118
58
 
59
+ self.projv = projv
119
60
 
120
- def merge_Jani(Janix, Janiy, Janiz):
121
- # This is wrong.
122
- # Jani = (
123
- # np.array([[0, 0, 0], [0, 1, 1], [0, 1, 1]]) * Janix
124
- # + np.array([[1, 0, 1], [0, 0, 0], [1, 0, 1]]) * Janiy
125
- # + np.array([[1, 1, 0], [1, 1, 0], [0, 0, 0]]) * Janiz
126
- # ) / 2.0
127
- wx = np.array([[0, 0, 0], [0, 1, 1], [0, 1, 1]])
128
- wy = np.array([[1, 0, 1], [0, 0, 0], [1, 0, 1]])
129
- wz = np.array([[1, 1, 0], [1, 1, 0], [0, 0, 0]])
130
- Jani = (wx * Janix + wy * Janiy + wz * Janiz) / (wx + wy + wz)
131
- return Jani
61
+ @classmethod
62
+ def load_pickle(cls, path='TB2J_results', fname='TB2J.pickle'):
63
+ obj = super(SpinIO_merge, cls).load_pickle(path=path, fname=fname)
64
+ obj._set_projection_vectors()
132
65
 
66
+ return obj
133
67
 
134
68
  def read_pickle(path):
135
- p1 = os.path.join(path, "TB2J_results", "TB2J.pickle")
136
- p2 = os.path.join(path, "TB2J.pickle")
69
+ p1 = os.path.join(path, 'TB2J_results', 'TB2J.pickle')
70
+ p2 = os.path.join(path, 'TB2J.pickle')
137
71
  if os.path.exists(p1) and os.path.exists(p2):
138
72
  print(f" WARNING!: Both file {p1} and {p2} exist. Use default {p1}.")
139
73
  if os.path.exists(p1):
140
- ret = SpinIO.load_pickle(os.path.join(path, "TB2J_results"))
74
+ ret = SpinIO_merge.load_pickle(os.path.join(path, 'TB2J_results'))
141
75
  elif os.path.exists(p2):
142
- ret = SpinIO.load_pickle(path)
76
+ ret = SpinIO_merge.load_pickle(path)
143
77
  else:
144
78
  raise FileNotFoundError(f"Cannot find either file {p1} or {p2}")
145
79
  return ret
146
80
 
81
+ class Merger():
82
+ def __init__(self, *paths, main_path=None):
83
+ self.dat = [read_pickle(path) for path in paths]
147
84
 
148
- class Merger2:
149
- def __init__(self, paths, method):
150
- self.method = method
151
- if method.lower() == "spin":
152
- self.load_with_rotated_spin(paths)
153
- elif method.lower() == "structure":
154
- self.load_with_rotated_structure(paths)
85
+ if main_path is None:
86
+ self.main_dat = copy.deepcopy(self.dat[-1])
155
87
  else:
156
- raise ValueError("method should be either 'spin' or 'structure'")
157
-
158
- def load_with_rotated_structure(self, paths):
159
- """
160
- Merge TB2J results from multiple calculations.
161
- :param paths: a list of paths to the TB2J results.
162
- :param method: 'structure' or 'spin'
163
- """
164
- self.paths = paths
165
- if len(self.paths) != 3:
166
- raise ValueError(
167
- "The number of paths should be 3, with structure rotated from z to x, y, z"
168
- )
169
- for i, path in enumerate(self.paths):
170
- read_pickle(path)
171
- self.indata = [read_pickle(path) for path in paths]
172
-
173
- self.dat = copy.deepcopy(self.indata[-1])
174
- # self.dat.description += (
175
- # "Merged from TB2J results in paths: \n " + "\n ".join(paths) + "\n"
176
- # )
177
- Rotations = [Rzx, Rzy, Rzz]
178
- for dat, rotation in zip(self.indata, Rotations):
179
- dat.spinat = recover_spinat_from_rotated_structure(dat.spinat, rotation)
180
- dat.dmi_ddict = recover_DMI_from_rotated_structure(dat.dmi_ddict, rotation)
181
- dat.Jani_dict = recover_Jani_fom_rotated_structure(dat.Jani_dict, rotation)
182
-
183
- def load_with_rotated_spin(self, paths):
184
- """
185
- Merge TB2J results from multiple calculations.
186
- :param paths: a list of paths to the TB2J results.
187
- :param method: 'structure' or 'spin'
188
- """
189
- self.paths = paths
190
- self.indata = [read_pickle(path) for path in paths]
191
- self.dat = copy.deepcopy(self.indata[-1])
192
- # self.dat.description += (
193
- # "Merged from TB2J results in paths: \n " + "\n ".join(paths) + "\n"
194
- # )
195
-
196
- def merge_Jani(self):
197
- """
198
- Merge the anisotropic exchange tensor.
199
- """
200
- Jani_dict = {}
201
- for key, Jani in self.dat.Jani_dict.items():
202
- R, i, j = key
203
- weights = np.zeros((3, 3), dtype=float)
204
- Jani_sum = np.zeros((3, 3), dtype=float)
205
- for dat in self.indata:
206
- Si = dat.get_spin_ispin(i)
207
- Sj = dat.get_spin_ispin(j)
208
- # print(f"{Si=}, {Sj=}")
209
- Jani = dat.get_Jani(i, j, R, default=np.zeros((3, 3), dtype=float))
210
- Jani_removed, w = remove_components(
211
- Jani,
212
- Si,
213
- Sj,
214
- remove_indices=[[0, 2], [1, 2], [2, 2], [2, 1], [2, 0]],
215
- )
216
- w = Jani_removed / Jani
217
- Jani_sum += Jani * w # Jani_removed
218
- # print(f"{Jani* w=}")
219
- weights += w
220
- # print(f"{weights=}")
221
- if np.any(weights == 0):
222
- raise RuntimeError(
223
- "The data set to be merged does not give a complete anisotropic J tensor, please add more data"
224
- )
225
- Jani_dict[key] = Jani_sum / weights
226
- self.dat.Jani_dict = Jani_dict
227
-
228
- def merge_DMI(self):
229
- """
230
- merge the DMI vector
231
- """
232
- DMI = {}
233
- for key, D in self.dat.dmi_ddict.items():
234
- R, i, j = key
235
- weights = np.zeros((3, 3), dtype=float)
236
- Dtensor_sum = np.zeros((3, 3), dtype=float)
237
- for dat in self.indata:
238
- Si = dat.get_spin_ispin(i)
239
- Sj = dat.get_spin_ispin(j)
240
- D = dat.get_DMI(i, j, R, default=np.zeros((3,), dtype=float))
241
- Dtensor = DMI_to_Jtensor(D)
242
- Dtensor_removed, w = remove_components(
243
- Dtensor, Si, Sj, remove_indices=[[0, 1], [1, 0]]
244
- )
245
- Dtensor_sum += Dtensor * w # Dtensor_removed
246
- weights += w
247
- if np.any(weights == 0):
248
- raise RuntimeError(
249
- "The data set to be merged does not give a complete DMI vector, please add more data"
250
- )
251
- DMI[key] = Jtensor_to_DMI(Dtensor_sum / weights)
252
- self.dat.dmi_ddict = DMI
88
+ self.main_dat = read_pickle(main_path)
89
+ self.dat.append(copy.deepcopy(self.main_dat))
253
90
 
254
- def merge_Jiso(self):
255
- """
256
- merge the isotropic exchange
257
- """
258
- Jiso = {}
259
- for key, J in self.dat.exchange_Jdict.items():
260
- R, i, j = key
261
- weights = 0.0
262
- Jiso_sum = 0.0
263
- for dat in self.indata:
264
- Si = dat.get_spin_ispin(i)
265
- Sj = dat.get_spin_ispin(j)
266
- J = dat.get_Jiso(i, j, R, default=0.0)
267
- Jiso_sum += J # *np.eye(3, dtype=float)
268
- weights += 1.0
269
- if np.any(weights == 0):
270
- raise RuntimeError(
271
- "The data set to be merged does not give a complete isotropic exchange, please add more data"
272
- )
273
- Jiso[key] = Jiso_sum / weights
274
- self.dat.exchange_Jdict = Jiso
91
+ self._set_projv()
92
+
93
+ def _set_projv(self):
275
94
 
276
- def write(self, path="TB2J_results"):
277
- """
278
- Write the merged TB2J results to a folder.
279
- :param path: the path to the folder to write the results.
280
- """
281
- self.dat.description += (
282
- "Merged from TB2J results in paths: \n " + "\n ".join(self.paths) + "\n"
95
+ cell = self.main_dat.atoms.cell.array
96
+ rotated_cells = np.stack(
97
+ [obj.atoms.cell.array for obj in self.dat], axis=0
283
98
  )
284
- if self.method == "spin":
285
- self.dat.description += (
286
- ", which are from DFT data with various spin orientations. \n"
287
- )
288
- elif self.method == "structure":
289
- self.dat.description += ", which are from DFT data with structure with z axis rotated to x, y, z\n"
290
- self.dat.description += "\n"
291
- self.dat.write_all(path=path)
292
-
293
-
294
- class Merger:
295
- def __init__(self, path_x, path_y, path_z, method="structure"):
296
- assert method in ["structure", "spin"]
297
- self.dat_x = read_pickle(path_x)
298
- self.dat_y = read_pickle(path_y)
299
- self.dat_z = read_pickle(path_z)
300
- self.dat = copy.copy(self.dat_z)
301
- self.paths = [path_x, path_y, path_z]
302
- self.method = method
99
+ R = np.linalg.solve(cell, rotated_cells)
100
+ indices = range(len(self.dat))
101
+
102
+ proju = {}; projv = {}; coeff_matrix = {}; projectors = {};
103
+ for key in self.main_dat.projv.keys():
104
+ vectors = [obj.projv[key] for obj in self.dat]
105
+ coefficients, u, v = zip(*[get_Jani_coefficients(vectors[i], R=R[i]) for i in indices])
106
+ projectors[key] = np.vstack([u[i] @ R[i].T for i in indices])
107
+ coeff_matrix[key] = np.vstack(coefficients)
108
+ proju[key] = np.stack(u)
109
+ projv[key] = np.stack(v)
110
+ if np.linalg.matrix_rank(coeff_matrix[key], tol=1e-2) < 6:
111
+ warnings.warn('''
112
+ WARNING: The matrix of equations to reconstruct the exchange tensors is
113
+ close to being singular. This happens when the magnetic moments between
114
+ different configurations are cloes to being parallel. You need to consider
115
+ more rotated spin configurations, otherwise the results might have a large
116
+ error.'''
117
+ )
118
+
119
+ self.proju = proju
120
+ self.projv = projv
121
+ self.coeff_matrix = coeff_matrix
122
+ self.projectors = projectors
303
123
 
304
124
  def merge_Jani(self):
305
125
  Jani_dict = {}
306
- Janixdict = self.dat_x.Jani_dict
307
- Janiydict = self.dat_y.Jani_dict
308
- Janizdict = self.dat_z.Jani_dict
309
- for key, Janiz in Janizdict.items():
126
+ proju = self.proju; projv = self.projv; coeff_matrix = self.coeff_matrix;
127
+ for key in self.main_dat.Jani_dict.keys():
310
128
  try:
311
129
  R, i, j = key
312
- keyx = R
313
- keyy = R
314
- Janix = Janixdict[(tuple(keyx), i, j)]
315
- Janiy = Janiydict[(tuple(keyy), i, j)]
130
+ u = proju[i, j]
131
+ v = projv[i, j]
132
+ Jani = np.stack([sio.Jani_dict[key] for sio in self.dat])
133
+ projections = np.einsum('nmi,nij,nmj->nm', u, Jani, v).flatten()
316
134
  except KeyError as err:
317
135
  raise KeyError(
318
136
  "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
319
- % err
320
- )
321
- if self.method == "spin":
322
- Jani_dict[key] = merge_Jani(Janix, Janiy, Janiz)
323
- else:
324
- Jani_dict[key] = merge_Jani(
325
- swap_direction(Janix, (0, 2)), swap_direction(Janiy, (1, 2)), Janiz
326
- )
327
- self.dat.Jani_dict = Jani_dict
137
+ % err)
138
+ newJani = np.linalg.lstsq(coeff_matrix[i, j], projections, rcond=1e-2)[0]
139
+ Jani_dict[key] = np.array([
140
+ [newJani[0], newJani[3], newJani[5]],
141
+ [newJani[3], newJani[1], newJani[4]],
142
+ [newJani[5], newJani[4], newJani[2]]
143
+ ])
144
+ self.main_dat.Jani_dict = Jani_dict
328
145
 
329
146
  def merge_Jiso(self):
330
- Jdict = {}
331
- Jxdict = self.dat_x.exchange_Jdict
332
- Jydict = self.dat_y.exchange_Jdict
333
- Jzdict = self.dat_z.exchange_Jdict
334
- for key, J in Jzdict.items():
147
+ Jdict={}
148
+ for key in self.main_dat.exchange_Jdict.keys():
335
149
  try:
336
- Jx = Jxdict[key]
337
- Jy = Jydict[key]
338
- Jz = Jzdict[key]
150
+ J = np.mean([obj.exchange_Jdict[key] for obj in self.dat])
339
151
  except KeyError as err:
340
152
  raise KeyError(
341
- "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
342
- % err
343
- )
344
- Jdict[key] = (Jx + Jy + Jz) / 3.0
345
- self.dat.exchange_Jdict = Jdict
346
-
347
- def merge_DMI(self):
348
- dmi_ddict = {}
349
- if self.dat_x.has_dmi and self.dat_y.has_dmi and self.dat_z.has_dmi:
350
- Dxdict = self.dat_x.dmi_ddict
351
- Dydict = self.dat_y.dmi_ddict
352
- Dzdict = self.dat_z.dmi_ddict
353
- for key, Dz in Dzdict.items():
354
- try:
355
- R, i, j = key
356
- keyx = R
357
- keyy = R
358
- Dx = Dxdict[(tuple(keyx), i, j)]
359
- Dy = Dydict[(tuple(keyy), i, j)]
360
- except KeyError as err:
361
- raise KeyError(
362
153
  "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
363
- % err
364
- )
365
- if self.method == "structure":
366
- dmi_ddict[key] = rot_merge_DMI(Dx, Dy, Dz)
367
- else:
368
- dmi_ddict[key] = merge_DMI(Dx, Dy, Dz)
369
- self.dat.dmi_ddict = dmi_ddict
154
+ % err)
155
+ Jdict[key] = J
156
+ self.main_dat.exchange_Jdict = Jdict
157
+
370
158
 
159
+ def merge_DMI(self):
371
160
  dmi_ddict = {}
372
- try:
373
- Dxdict = self.dat_x.debug_dict["DMI2"]
374
- Dydict = self.dat_y.debug_dict["DMI2"]
375
- Dzdict = self.dat_z.debug_dict["DMI2"]
376
- for key, Dz in Dzdict.items():
161
+ if all(obj.has_dmi for obj in self.dat):
162
+ projectors = self.projectors; proju = self.proju;
163
+ for key in self.main_dat.dmi_ddict.keys():
377
164
  try:
378
165
  R, i, j = key
379
- keyx = R
380
- keyy = R
381
- Dx = Dxdict[(tuple(keyx), i, j)]
382
- Dy = Dydict[(tuple(keyy), i, j)]
166
+ u = proju[i, j]
167
+ DMI = np.stack([sio.dmi_ddict[key] for sio in self.dat])
168
+ projections = np.einsum('nmi,ni->nm', u, DMI).flatten()
383
169
  except KeyError as err:
384
170
  raise KeyError(
385
171
  "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
386
- % err
387
- )
388
- if self.method == "structure":
389
- dmi_ddict[key] = rot_merge_DMI2(Dx, Dy, Dz)
390
- elif self.method == "spin":
391
- dmi_ddict[key] = merge_DMI2(Dx, Dy, Dz)
392
-
393
- self.dat.debug_dict["DMI2"] = dmi_ddict
394
- except:
395
- pass
396
-
397
- def write(self, path="TB2J_results"):
398
- self.dat.description += (
399
- "Merged from TB2J results in paths: \n " + "\n ".join(self.paths) + "\n"
400
- )
401
- if self.method == "spin":
402
- self.dat.description += (
403
- ", which are from DFT data with spin along x, y, z orientation\n"
404
- )
405
- elif self.method == "structure":
406
- self.dat.description += ", which are from DFT data with structure with z axis rotated to x, y, z\n"
407
- self.dat.description += "\n"
408
- self.dat.write_all(path=path)
409
-
410
-
411
- def merge(path_x, path_y, path_z, method, save=True, path="TB2J_results"):
412
- m = Merger(path_x, path_y, path_z, method)
413
- m.merge_Jiso()
414
- m.merge_DMI()
415
- m.merge_Jani()
416
- if save:
417
- m.write(path=path)
418
- return m.dat
419
-
172
+ % err)
173
+ newDMI = np.linalg.lstsq(projectors[i, j], projections, rcond=4e-1)[0]
174
+ dmi_ddict[key] = newDMI
175
+ self.main_dat.dmi_ddict = dmi_ddict
420
176
 
421
- def merge2(paths, method, save=True, path="TB2J_results"):
422
- """
423
- Merge TB2J results from multiple calculations.
424
- :param paths: a list of paths to the TB2J results.
425
- :param method: 'structure' or 'spin'
426
- :param save: whether to save the merged results.
427
- :param path: the path to the folder to write the results.
428
- """
429
- m = Merger2(paths, method)
177
+ def merge(*paths, main_path=None, save=True, write_path='TB2J_results'):
178
+ m = Merger(*paths, main_path=main_path)
430
179
  m.merge_Jiso()
431
180
  m.merge_DMI()
432
181
  m.merge_Jani()
433
182
  if save:
434
- m.write(path=path)
183
+ m.main_dat.write_all(path=write_path)
435
184
  return m.dat
TB2J/myTB.py CHANGED
@@ -16,7 +16,6 @@ class AbstractTB:
16
16
  def __init__(self, R2kfactor, nspin, norb):
17
17
  #: :math:`\alpha` used in :math:`H(k)=\sum_R H(R) \exp( \alpha k \cdot R)`,
18
18
  #: Should be :math:`2\pi i` or :math:`-2\pi i`
19
- self.is_siesta = False
20
19
  self.is_orthogonal = True
21
20
  self.R2kfactor = R2kfactor
22
21
 
@@ -125,7 +124,6 @@ class MyTB(AbstractTB):
125
124
  self.atoms = None
126
125
  self.R2kfactor = 2.0j * np.pi
127
126
  self.k2Rfactor = -2.0j * np.pi
128
- self.is_siesta = False
129
127
  self.is_orthogonal = True
130
128
  self._name = "Wannier"
131
129
 
TB2J/rotate_atoms.py CHANGED
@@ -5,19 +5,24 @@ import numpy as np
5
5
  from TB2J.tensor_rotate import Rxx, Rxy, Rxz, Ryx, Ryy, Ryz, Rzx, Rzy, Rzz
6
6
 
7
7
 
8
- def rotate_atom_xyz(atoms):
8
+ def rotate_atom_xyz(atoms, noncollinear=False):
9
9
  """
10
- given a atoms, return:
11
- - 'z'->'x'
12
- - 'z'->'y'
13
- - 'z'->'z'
10
+ given a atoms, return rotated atoms:
11
+ atoms_1, ..., atoms_n,
12
+ where we considered n diffeerent roation axes.
13
+
14
+ When noncollinear == True, more rotated structures
15
+ will be generated.
14
16
  """
15
- atoms_x = copy.deepcopy(atoms)
16
- atoms_x.rotate(90, "y", rotate_cell=True)
17
- atoms_y = copy.deepcopy(atoms)
18
- atoms_y.rotate(90, "x", rotate_cell=True)
19
- atoms_z = atoms
20
- return atoms_x, atoms_y, atoms_z
17
+
18
+ rotation_axes = [(1, 0, 0), (0, 1, 0)]
19
+ if noncollinear:
20
+ rotation_axes += [(1, 1, 0), (1, 0, 1), (0, 1, 1)]
21
+
22
+ for axis in rotation_axes:
23
+ rotated_atoms = copy.deepcopy(atoms)
24
+ rotated_atoms.rotate(90, axis, rotate_cell=True)
25
+ yield rotated_atoms
21
26
 
22
27
 
23
28
  def rotate_atom_spin_one_rotation(atoms, Rotation):
@@ -96,18 +101,15 @@ def check_ftype(ftype):
96
101
  print("=" * 40)
97
102
 
98
103
 
99
- def rotate_xyz(fname, ftype="xyz"):
104
+ def rotate_xyz(fname, ftype="xyz", noncollinear=False):
100
105
  check_ftype(ftype)
101
106
  atoms = read(fname)
102
107
  atoms.set_pbc(True)
103
108
 
104
- atoms_x, atoms_y, atoms_z = rotate_atom_xyz(atoms)
109
+ rotated = rotate_atom_xyz(atoms, noncollinear=noncollinear)
105
110
 
106
- fname_x = f"atoms_x.{ftype}"
107
- fname_y = f"atoms_y.{ftype}"
108
- fname_z = f"atoms_z.{ftype}"
111
+ for i, rotated_atoms in enumerate(rotated):
112
+ write(f"atoms_{i+1}.{ftype}", rotated_atoms)
113
+ write(f"atoms_0.{ftype}", atoms)
109
114
 
110
- write(fname_x, atoms_x)
111
- write(fname_y, atoms_y)
112
- write(fname_z, atoms_z)
113
- print(f"The output has been written to {fname_x}, {fname_y}, {fname_z}")
115
+ print(f"The output has been written to the atoms_i.{ftype} files. atoms_0.{ftype} contains the reference structure.")
@@ -0,0 +1,36 @@
1
+ import sisl
2
+
3
+ def rotate_siesta_DM(DM, noncollinear=False):
4
+
5
+ angles_list = [ [0.0, 90.0, 0.0], [0.0, 90.0, 90.0] ]
6
+ if noncollinear:
7
+ angles_list += [[0.0, 45.0, 0.0], [0.0, 90.0, 45.0], [0.0, 45.0, 90.0]]
8
+
9
+ for angles in angles_list:
10
+ yield DM.spin_rotate(angles)
11
+
12
+ def read_label(fdf_fname):
13
+
14
+ label = 'siesta'
15
+ with open(fdf_fname, 'r') as File:
16
+ for line in File:
17
+ corrected_line = line.lower().replace('.', '').replace('-', '')
18
+ if 'systemlabel' in corrected_line:
19
+ label = line.split()[1]
20
+ break
21
+
22
+ return label
23
+
24
+ def rotate_DM(fdf_fname, noncollinear=False):
25
+
26
+ fdf = sisl.get_sile(fdf_fname)
27
+ DM = fdf.read_density_matrix()
28
+ label = read_label(fdf_fname)
29
+
30
+ rotated = rotate_siesta_DM(DM, noncollinear=noncollinear)
31
+
32
+ for i, rotated_DM in enumerate(rotated):
33
+ rotated_DM.write(f"{label}_{i+1}.DM")
34
+ DM.write(f"{label}_0.DM")
35
+
36
+ print(f"The output has been written to the {label}_i.DM files. {label}_0.DM contains the reference density matrix.")
TB2J/sisl_wrapper.py CHANGED
@@ -10,7 +10,6 @@ from TB2J.mathutils import Lowdin
10
10
 
11
11
  class SislWrapper(AbstractTB):
12
12
  def __init__(self, sisl_hamiltonian, geom=None, spin=None):
13
- self.is_siesta = False
14
13
  self.is_orthogonal = False
15
14
  self.ham = sisl_hamiltonian
16
15
  # k2Rfactor : H(k) = \int_R H(R) * e^(k2Rfactor * k.R)
@@ -0,0 +1,68 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import aiida
4
+ from aiida_tb2j.data import ExchangeData
5
+
6
+ def plot_dispersion(bands, kpoint_labels, color='blue', title=None):
7
+
8
+ fig, axs = plt.subplots(1, 1, constrained_layout=True)
9
+ fig.set_size_inches(6, 6/1.618)
10
+
11
+ '''
12
+ Plot the bands
13
+ '''
14
+ kpoints = np.arange(len(bands))
15
+ axs.plot(kpoints, bands, color=color, linewidth=1.5)
16
+
17
+ '''
18
+ Plot the symmetry points
19
+ '''
20
+ bmin = bands.min(); bmax = bands.max()
21
+ ymin = bmin - 0.05*np.abs(bmin-bmax); ymax = bmax + 0.05*np.abs(bmax-bmin);
22
+ axs.set_xticks(kpoint_labels[0], kpoint_labels[1], fontsize=10)
23
+ axs.vlines(x=kpoint_labels[0], ymin=ymin, ymax=ymax, color='black', linewidth=0.5)
24
+ axs.set_xlim([0, len(kpoints)])
25
+ axs.set_ylim([ymin, ymax])
26
+
27
+ if title is not None:
28
+ plt.title(title, fontsize=10)
29
+
30
+ plt.show()
31
+
32
+
33
+ if __name__ == "__main__":
34
+
35
+ from argparse import ArgumentParser
36
+
37
+ parser = ArgumentParser()
38
+ parser.add_argument('-f', '--pickle_filename', type=str, help="Path of the 'TB2J.pickle' file.", required=True)
39
+ args = parser.parse_args()
40
+
41
+ '''
42
+ Right now the implementation depends on AiiDA and so we must create and load an AiiDA profile,
43
+ even if we do not store any information on a data base.
44
+ '''
45
+ aiida.load_profile()
46
+ '''
47
+ Create an ExchangeData object with the informations from the TB2J.pickle file
48
+ '''
49
+ exchange = ExchangeData.load_tb2j(pickle_file=args.pickle_filename, isotropic=False, pbc=(True, True, True))
50
+ '''
51
+ Compute the magnon band structure along a high symmetry path generated with
52
+ the ASE package. The informations is stored in an AiiDA BandsData object.
53
+ Here tol is the symmetry tolerance to determine the space group of the system.
54
+ They are in units of eV
55
+ '''
56
+ magnon_data = exchange.get_magnon_bands(npoints=300, tol=1e-1, with_DMI=True, with_Jani=True)
57
+ magnon_bands = 1000*magnon_data.get_bands() # Convert to meV
58
+ raw_labels = [(k, '$\Gamma$') if s == 'GAMMA' else (k, s) for k, s in magnon_data.labels]
59
+ kpoint_labels = list( zip( *raw_labels ) )
60
+ plot_dispersion(magnon_bands, kpoint_labels, color='blue', title='Magnon Bands')
61
+ '''
62
+ We can also obtain the dynamical matrix h instead of the actual magnon bands. The result
63
+ is stored in a numpy array with shape (number of kpoints, 2*natoms, 2*natoms)
64
+ '''
65
+ kpoints = magnon_data.get_kpoints() # The shape of the kpoints must be (nkpoints, 3)
66
+ h_matrix = 1000*exchange._H_matrix(kpoints, with_DMI=True, with_Jani=True) # Convert to meV
67
+ h_dispersion = np.linalg.eigvalsh(h_matrix) # We can also get the eigenvectors with np.linalg.eigh
68
+ plot_dispersion(h_dispersion, kpoint_labels, color='red', title='h matrix dispersion')
@@ -0,0 +1,79 @@
1
+ import numpy as np
2
+ from aiida_tb2j.data import ExchangeData
3
+ from aiida_tb2j.data.exchange import get_rotation_arrays
4
+ from itertools import combinations_with_replacement
5
+
6
+ ux, uy, uz = np.eye(3).reshape((3, 1, 3))
7
+
8
+ def combine_arrays(u, v):
9
+
10
+ return np.concatenate([u*v, np.roll(u, -1, axis=-1)*v, np.roll(v, -1, axis=-1)*u], axis=-1)
11
+
12
+ def get_coefficients(magmoms, indices):
13
+
14
+ i, j = indices
15
+
16
+ U, V = zip(*[get_rotation_arrays(magmoms, u=u) for u in [ux, uy, uz]])
17
+ U = np.stack(U).swapaxes(0, 1)
18
+ V = np.stack(V).swapaxes(0, 1)
19
+
20
+ uc = combine_arrays(U[i], U[j].conj())
21
+ ur = combine_arrays(U[i], U[j])
22
+ uc2 = combine_arrays(U[i].conj(), U[j])
23
+ u = np.concatenate([uc, ur, uc2], axis=1)
24
+
25
+ return u, V
26
+
27
+ def get_C(H0, u, V):
28
+
29
+ n = int(H0.shape[-1]/2)
30
+ upi = np.triu_indices(n)
31
+ dig = np.diag_indices(n)
32
+
33
+ i, j = upi
34
+ AB0 = H0[:, [i, i, i+n], [j, j+n, j+n]]
35
+ AB0 = np.swapaxes(AB0, 0, 2).reshape(len(i), 9)
36
+ J0_flat = np.linalg.solve(u, AB0)
37
+
38
+ J0 = np.empty((n, n, 3, 3), dtype=complex)
39
+ J0[*upi] = J0_flat[:, [0, 6, 5, 3, 1, 7, 8, 4, 2]].reshape(-1, 3, 3)
40
+ J0 += J0.swapaxes(0, 1)
41
+ J0[*dig] = 0.0
42
+
43
+ C = np.array([np.diag(a) for a in np.einsum('imx,ijxy,jmy->mi', V, 2*J0, V)])
44
+
45
+ return C
46
+
47
+ def get_J(H, kpoints, exchange):
48
+
49
+ n = int(H.shape[-1]/2)
50
+ upi = np.triu_indices(n)
51
+ dig = np.diag_indices(n)
52
+ i, j = upi
53
+
54
+ magmoms = exchange.magmoms()[np.unique(exchange.pairs)]
55
+ magmoms /= np.linalg.norm(magmoms, axis=-1).reshape(-1, 1)
56
+ u, V = get_coefficients(magmoms, indices=upi)
57
+
58
+ H0 = np.stack([1000*exchange._H_matrix(kpoints=np.zeros((1, 3)), with_DMI=True, with_Jani=True, u=u) for u in [ux, uy, uz]])[:, 0, :, :]
59
+ C = get_C(H0, u, V)
60
+ H[:, :, :n, :n] += C.reshape(3, 1, n, n)
61
+ H[:, :, n:, n:] += C.reshape(3, 1, n, n)
62
+
63
+ AB = H[:, :, [i, i, i+n], [j, j+n, j+n]]
64
+ AB[:, :, 2, :] = AB[:, ::-1, 2, :]
65
+ AB = np.moveaxis(AB, [2, 3], [1, 0]).reshape(len(i), 9, -1)
66
+
67
+ vectors = exchange.get_vectors()
68
+ exp_summand = np.exp( -2j*np.pi*vectors @ kpoints.T )
69
+ nAB = np.einsum('nik,ndk->nid', AB, exp_summand) / len(kpoints)
70
+
71
+ ii = np.where(i == j)
72
+ i0 = np.where(np.linalg.norm(vectors, axis=-1) == 0.0)
73
+ J = np.linalg.solve(u, nAB).swapaxes(1, 2)
74
+ J = J[:, :, [0, 6, 5, 3, 1, 7, 8, 4, 2]].reshape(len(i), -1, 3, 3)
75
+ J *= -1
76
+ J[ii] *= 2
77
+ J[i0] *= 0
78
+
79
+ return J
@@ -2,7 +2,7 @@
2
2
  import argparse
3
3
  import os
4
4
  import sys
5
- from TB2J.io_merge import merge, merge2
5
+ from TB2J.io_merge import merge
6
6
 
7
7
 
8
8
  def main():
@@ -28,11 +28,18 @@ def main():
28
28
  type=str,
29
29
  default="TB2J_results",
30
30
  )
31
+ parser.add_argument(
32
+ "--main_path",
33
+ help="The path containning the reference structure.",
34
+ type=str,
35
+ default=None
36
+ )
31
37
 
32
38
  args = parser.parse_args()
33
39
  # merge(*(args.directories), args.type.strip().lower(), path=args.output_path)
34
40
  # merge(*(args.directories), method=args.type.strip().lower(), path=args.output_path)
35
- merge2(args.directories, args.type.strip().lower(), path=args.output_path)
41
+ #merge2(args.directories, args.type.strip().lower(), path=args.output_path)
42
+ merge(*args.directories, main_path=args.main_path, write_path=args.output_path)
36
43
 
37
44
 
38
45
  main()
@@ -14,9 +14,14 @@ def main():
14
14
  default="xyz",
15
15
  type=str,
16
16
  )
17
+ parser.add_argument(
18
+ "--noncollinear",
19
+ action="store_true",
20
+ help="If present, six different configurations will be generated. These are required for non-collinear systems."
21
+ )
17
22
 
18
23
  args = parser.parse_args()
19
- rotate_xyz(args.fname, ftype=args.ftype)
24
+ rotate_xyz(args.fname, ftype=args.ftype, noncollinear=args.noncollinear)
20
25
 
21
26
 
22
27
  if __name__ == "__main__":
@@ -0,0 +1,21 @@
1
+ #!python
2
+ import argparse
3
+ from TB2J.rotate_siestaDM import rotate_DM
4
+
5
+ def main():
6
+ parser = argparse.ArgumentParser(description="")
7
+ parser.add_argument(
8
+ "--fdf_fname", help="Name of the *.fdf siesta file."
9
+ )
10
+ parser.add_argument(
11
+ "--noncollinear",
12
+ action="store_true",
13
+ help="If present, six different configurations will be generated. These are required for non-collinear systems."
14
+ )
15
+
16
+ args = parser.parse_args()
17
+ rotate_DM(args.fdf_fname, noncollinear=args.noncollinear)
18
+
19
+
20
+ if __name__ == "__main__":
21
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.8.2.7
3
+ Version: 0.9.0
4
4
  Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
5
5
  Home-page: UNKNOWN
6
6
  Author: Xu He
@@ -2,31 +2,32 @@ 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=SgNb_x-EiSsKRMJsfDX9rLKVaPFJDAj-eBAlhqvvaFM,24
5
+ TB2J/__init__.py,sha256=H9NWRZb7NbeRRPLP_V1fARmLNXranorVM-OOY-8_2ug,22
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=UmZU5h91BPql3ylNALvzMJWTxkfzObZ1OVMxj2Hmp7A,29570
12
+ TB2J/exchange.py,sha256=Xg2fuUZbj-Icpqc65Ictllxvdvct8Ec4KQPAmEyo0oM,29586
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=UCDIkpH2HNVglvZZKnxigOOBMLdRBUpkiOqC13fitQE,13011
17
+ TB2J/green.py,sha256=X-D8UZcIyz6zh_0W9VgUUv5yXPP3KWJ6C03m6CMWE3o,13377
18
18
  TB2J/greentest.py,sha256=2ISSfhor9ecSEOi_E6b4Cv26wEIQlwlzca0ru8z44_E,1603
19
- TB2J/io_merge.py,sha256=2dYrQFHSnb_8fwbQiVod9GyaT-BotawA26eagXWUyMg,15265
19
+ TB2J/io_merge.py,sha256=t85k3L6IL9X5ys-PWK7CzResb3xJsyqM3LAlKPUe9vM,6825
20
20
  TB2J/kpoints.py,sha256=6XK2KqTncidEq3o9GuO6VEZRPNTRtWeXg9QfcV-9smI,532
21
21
  TB2J/manager.py,sha256=4-4x9jJRHpUEqJuhc5HqpXfh2-Ze5G9Wg8gOtn-AqR4,15372
22
22
  TB2J/mathutils.py,sha256=tHA6q3KPDpXLIbZHdDZ2NU5s886VVM_oEG490zQ6Ris,300
23
- TB2J/myTB.py,sha256=cm9Kkyzi686QyoxrR3lm4rsSnE6Imee3-j2xM78XnGI,17721
23
+ TB2J/myTB.py,sha256=ok_B4my29bOIghMSZfx0Es6G8FaXaIiLP4gPxTdSj00,17659
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
- TB2J/rotate_atoms.py,sha256=-fxlQN7LbyQAbGUCUBqDJ5ENR0pT8MLBd-5sLxaX_vI,3031
29
- TB2J/sisl_wrapper.py,sha256=BMYaj7-nVxKhYENEwafsyZHcRm1Z66p5Yr-zsxdiFcY,14823
28
+ TB2J/rotate_atoms.py,sha256=Dwptn-wdDW4zYzjYb95yxTzuZOe9WPuLjh3d3-YcSs0,3277
29
+ TB2J/rotate_siestaDM.py,sha256=eR97rspdrRaK9YTwQwUKfobI0S9UnEcbEZ2f5IgR7Tk,1070
30
+ TB2J/sisl_wrapper.py,sha256=A5x1-tt8efUSPeGY5wM5m6-pJYQFXTCzQHVqD6RBa2g,14792
30
31
  TB2J/supercell.py,sha256=4hgLGPBLRUDhtD-eF29v46ex7fHdkH-OENjS2wGLFww,19588
31
32
  TB2J/tensor_rotate.py,sha256=4-DfT_Mg5e40fbd74M5W0D5DqmUq-kVOOLDkkkI834A,8083
32
33
  TB2J/utest.py,sha256=z_ahi7tpHQF9WlHNQihcQ7qzfezRJQXQt28eB1X_z64,3897
@@ -34,7 +35,7 @@ TB2J/utils.py,sha256=_ARYKAeWfP1p5w0mEl-d7KwNfXoqC85TveYl0iCBD3c,9880
34
35
  TB2J/versioninfo.py,sha256=wZwS9QDFRVDe7rf8JyPDDI8UGdTQiO6Pb_sWv8GAegA,337
35
36
  TB2J/abacus/__init__.py,sha256=5sHiDnF2L-Y80QeET9zOiS83a5T_TQAXvnIhcYB6wNU,56
36
37
  TB2J/abacus/abacus_api.py,sha256=D_NyXW-Pno92d3RVHByx0l1HDPHQAvXsmQVt8cfIGR8,7267
37
- TB2J/abacus/abacus_wrapper.py,sha256=Pqm1MMcD5oQ1Pd4x0EkBh6yRindAps0FIf8LNGOlQok,8492
38
+ TB2J/abacus/abacus_wrapper.py,sha256=QR3ZW6v-d7dgneKwBO5s9FfCjBp-fkWMEaTO4SlcROA,8461
38
39
  TB2J/abacus/gen_exchange_abacus.py,sha256=lKZqkWMnLQtaSwgn8O5Fzr-pV6tzwoMqfZU_vbET6gU,2973
39
40
  TB2J/abacus/orbital_api.py,sha256=l48Hn5z7TA0TH7Is4NDmz74b6B9L2ztYO4dRR37U4mQ,1562
40
41
  TB2J/abacus/stru_api.py,sha256=aBKKlZ2hvAZChVCfNxRdxH51rfHKqZn6kOlazY-yW8k,67888
@@ -53,8 +54,10 @@ TB2J/io_exchange/io_vampire.py,sha256=UllC4twf06_q2vBCnAYFzEDGvS8mSefwQXDquBuyc0
53
54
  TB2J/spinham/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
55
  TB2J/spinham/base_parser.py,sha256=oQRHvFE_BlUtTaTZykKgvicu40oXcbICB-D1aAt-qlA,2196
55
56
  TB2J/spinham/constants.py,sha256=y4-hRyl5EAR42k24Oa5XhAsUQtKVn1MAgyqNf-p3PrM,762
57
+ TB2J/spinham/h_matrix.py,sha256=MfHIz6RViKkEB3Mu-WcwNx5uk7A5sjAlbqVG9wYA4xk,2784
56
58
  TB2J/spinham/hamiltonian.py,sha256=OfsjlGIgFwpXaohopZcgPamSfjm3X46_zc245eyTr_A,16607
57
59
  TB2J/spinham/hamiltonian_terms.py,sha256=7e84tfEjvAfZltUkrSWi1sUEiW_itLKy83lxi5iBpcQ,9714
60
+ TB2J/spinham/obtain_J.py,sha256=sg8tiCRRLEN57Olb3MHIuqkDhAkmu-w87AkM00ylXtA,2401
58
61
  TB2J/spinham/plot.py,sha256=tLLNqFAATVrP1kmSVLPKzn686i-CUyqu4qgOcs-okHI,6599
59
62
  TB2J/spinham/qsolver.py,sha256=Sr9I3aGfVNYn5wzwPx1QonHe6ZZUXBAujWRa7nTA5u4,4986
60
63
  TB2J/spinham/spin_api.py,sha256=oN3AKg1WQl0YzR4f5ealcJOaVoAy8d7HodIwrbXvQeY,2219
@@ -63,17 +66,18 @@ TB2J/spinham/supercell.py,sha256=y17uUC6r3gQb278FhxIW4CABihfLTvKFj6flyXrCPR8,122
63
66
  TB2J/wannier/__init__.py,sha256=7ojCbM84PYv1X1Tbo4NHI-d3gWmQsZB_xiYqbfxVV1E,80
64
67
  TB2J/wannier/w90_parser.py,sha256=dbd63LuKyv2DVUzqRINGsbDzEsOxsQyE8_Ear_LQIRg,4620
65
68
  TB2J/wannier/w90_tb_parser.py,sha256=qt8pnuprmPp9iIAYwPkPbmEzk6ZPgMq2xognoQp7vwc,4610
66
- TB2J-0.8.2.7.data/scripts/TB2J_downfold.py,sha256=F9oImXFysejCMP7eIBjbCX2jdHFOCvDW5beF1sG-UM8,1854
67
- TB2J-0.8.2.7.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
68
- TB2J-0.8.2.7.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
69
- TB2J-0.8.2.7.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
70
- TB2J-0.8.2.7.data/scripts/TB2J_merge.py,sha256=uZKLM__EyCHwxrQvx3Wd73dOEADp_SqfYC8KQvA-N9g,1622
71
- TB2J-0.8.2.7.data/scripts/TB2J_rotate.py,sha256=XPacPb7-DaFafBXFdWuNW_eNbjd5XPdNhBRNYhge_cg,634
72
- TB2J-0.8.2.7.data/scripts/abacus2J.py,sha256=M4B07lvTCDczTPTqvnDh_PERzCARAd09TLKv4aIdSQM,4408
73
- TB2J-0.8.2.7.data/scripts/siesta2J.py,sha256=hBzS7ZgoHM3oXlTCQd-xVA07Ks2FiIwyRpQWUFITRPE,4303
74
- TB2J-0.8.2.7.data/scripts/wann2J.py,sha256=2t2hWwyELskYCwkGDziCgiIAnfr6odLLJ6cQBJ2RQwQ,5714
75
- TB2J-0.8.2.7.dist-info/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
76
- TB2J-0.8.2.7.dist-info/METADATA,sha256=VwLdf9LlN_meROiv7NTa47fBvw1fwVf97mrz4RqWc-c,1464
77
- TB2J-0.8.2.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
78
- TB2J-0.8.2.7.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
79
- TB2J-0.8.2.7.dist-info/RECORD,,
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,,
File without changes
File without changes
File without changes