TB2J 0.8.2.8__py3-none-any.whl → 0.9.0.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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.8.2.8"
1
+ __version__ = "0.9.0.1"
@@ -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
@@ -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/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