TB2J 0.9.9.9__py3-none-any.whl → 0.9.9.12__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/Jtensor.py +5 -6
- TB2J/MAEGreen.py +8 -0
- TB2J/__init__.py +1 -1
- TB2J/exchange.py +1 -1
- TB2J/interfaces/abacus/stru_api.py +3 -1
- TB2J/interfaces/siesta_interface.py +2 -1
- TB2J/io_exchange/io_exchange.py +65 -23
- TB2J/io_exchange/io_vampire.py +6 -3
- TB2J/io_merge.py +15 -1
- TB2J/magnon/__init__.py +2 -2
- TB2J/magnon/magnon3.py +566 -56
- TB2J/magnon/magnon_band.py +185 -0
- TB2J/magnon/magnon_math.py +1 -0
- TB2J/magnon/plot.py +60 -21
- TB2J/mathutils/auto_kpath.py +151 -0
- tb2j-0.9.9.12.data/scripts/TB2J_plot_magnon_bands.py +7 -0
- {tb2j-0.9.9.9.dist-info → tb2j-0.9.9.12.dist-info}/METADATA +4 -2
- {tb2j-0.9.9.9.dist-info → tb2j-0.9.9.12.dist-info}/RECORD +33 -30
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_downfold.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_eigen.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_magnon.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_magnon2.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_magnon_dos.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_merge.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_rotate.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/TB2J_rotateDM.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/abacus2J.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/siesta2J.py +0 -0
- {tb2j-0.9.9.9.data → tb2j-0.9.9.12.data}/scripts/wann2J.py +0 -0
- {tb2j-0.9.9.9.dist-info → tb2j-0.9.9.12.dist-info}/WHEEL +0 -0
- {tb2j-0.9.9.9.dist-info → tb2j-0.9.9.12.dist-info}/entry_points.txt +0 -0
- {tb2j-0.9.9.9.dist-info → tb2j-0.9.9.12.dist-info}/licenses/LICENSE +0 -0
- {tb2j-0.9.9.9.dist-info → tb2j-0.9.9.12.dist-info}/top_level.txt +0 -0
TB2J/Jtensor.py
CHANGED
@@ -71,22 +71,21 @@ def decompose_J_tensor(Jtensor):
|
|
71
71
|
return Jiso, D, Jani
|
72
72
|
|
73
73
|
|
74
|
-
def combine_J_tensor(Jiso=
|
74
|
+
def combine_J_tensor(Jiso=None, D=None, Jani=None, dtype=float):
|
75
75
|
"""Combine isotropic exchange, DMI, and anisotropic exchange into tensor form
|
76
|
-
|
77
76
|
:param Jiso: scalar, isotropice exchange
|
78
77
|
:param D: vector, DMI.
|
79
78
|
:param Jani: 3x3 matrix anisotropic exchange
|
80
79
|
:returns: A 3x3 matrix, the exchange paraemter in tensor form.
|
81
80
|
"""
|
82
|
-
Jtensor = np.zeros((3, 3), dtype=
|
81
|
+
Jtensor = np.zeros((3, 3), dtype=dtype)
|
83
82
|
if Jiso is not None:
|
84
|
-
Jtensor += np.eye(3, dtype=
|
83
|
+
Jtensor += np.eye(3, dtype=dtype) * Jiso
|
85
84
|
if Jani is not None:
|
86
|
-
Jtensor += np.array(Jani, dtype=
|
85
|
+
Jtensor += np.array(Jani, dtype=dtype)
|
87
86
|
if D is not None:
|
88
87
|
Jtensor += np.array(
|
89
|
-
[[0, D[2], -D[1]], [-D[2], 0, D[0]], [D[1], -D[0], 0]], dtype=
|
88
|
+
[[0, D[2], -D[1]], [-D[2], 0, D[0]], [D[1], -D[0], 0]], dtype=dtype
|
90
89
|
)
|
91
90
|
return Jtensor
|
92
91
|
|
TB2J/MAEGreen.py
CHANGED
@@ -43,6 +43,8 @@ class MAEGreen(ExchangeNCL):
|
|
43
43
|
self.set_angles_random()
|
44
44
|
elif angles == "miller":
|
45
45
|
self.set_angles_miller()
|
46
|
+
elif angles == "ztox":
|
47
|
+
self.set_angels_ztox()
|
46
48
|
else:
|
47
49
|
self.thetas = angles[0]
|
48
50
|
self.phis = angles[1]
|
@@ -92,6 +94,12 @@ class MAEGreen(ExchangeNCL):
|
|
92
94
|
self.thetas.append(i * np.pi / 180)
|
93
95
|
self.phis.append(j * np.pi / 180)
|
94
96
|
|
97
|
+
def set_angels_ztox(self, n=16):
|
98
|
+
"""Set angles for a scan from z to x"""
|
99
|
+
self.thetas = np.linspace(0, np.pi, n)
|
100
|
+
self.phis = np.zeros(n)
|
101
|
+
|
102
|
+
|
95
103
|
def set_angles_random(self, n=16):
|
96
104
|
# n random pairs of theta, phi
|
97
105
|
self.thetas = np.random.random(n) * np.pi
|
TB2J/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.9.9.
|
1
|
+
__version__ = "0.9.9.12"
|
TB2J/exchange.py
CHANGED
@@ -48,7 +48,7 @@ class Exchange(ExchangeParams):
|
|
48
48
|
self.emin = self.G.find_energy_ingap(rbound=self.efermi - 15.0) - self.efermi
|
49
49
|
# self.emin = self.G.find_energy_ingap(rbound=self.efermi - 15.0) - self.efermi
|
50
50
|
# self.emin = -42.0
|
51
|
-
print(f"A gap is found at {self.emin}, set emin to it.")
|
51
|
+
#print(f"A gap is found at {self.emin}, set emin to it.")
|
52
52
|
|
53
53
|
def set_tbmodels(self, tbmodels):
|
54
54
|
pass
|
@@ -7,11 +7,13 @@
|
|
7
7
|
Modified on Wed Aug 01 11:44:51 2022
|
8
8
|
@author: Ji Yu-yang
|
9
9
|
"""
|
10
|
+
import warnings
|
11
|
+
warnings.simplefilter(action='ignore', category=FutureWarning)
|
12
|
+
|
10
13
|
|
11
14
|
import os
|
12
15
|
import re
|
13
16
|
import shutil
|
14
|
-
import warnings
|
15
17
|
from pathlib import Path
|
16
18
|
|
17
19
|
import numpy as np
|
@@ -157,7 +157,7 @@ Warning: The DMI component parallel to the spin orientation, the Jani which has
|
|
157
157
|
atoms=model.atoms,
|
158
158
|
basis=basis,
|
159
159
|
efermi=None,
|
160
|
-
angles="
|
160
|
+
angles="xyz",
|
161
161
|
# magnetic_elements=magnetic_elements,
|
162
162
|
# include_orbs=include_orbs,
|
163
163
|
**exargs,
|
@@ -165,6 +165,7 @@ Warning: The DMI component parallel to the spin orientation, the Jani which has
|
|
165
165
|
# thetas = [0, np.pi / 2, np.pi, 3 * np.pi / 2]
|
166
166
|
# phis = [0, 0, 0, 0]
|
167
167
|
# MAE.set_angles(thetas=thetas, phis=phis)
|
168
|
+
#MAE.set_xyz_angles()
|
168
169
|
MAE.run(output_path=f"{output_path}_anisotropy", with_eigen=False)
|
169
170
|
# print(
|
170
171
|
# f"MAE calculation finished. The results are in {output_path} directory."
|
TB2J/io_exchange/io_exchange.py
CHANGED
@@ -54,6 +54,7 @@ class SpinIO(object):
|
|
54
54
|
gyro_ratio=None,
|
55
55
|
write_experimental=True,
|
56
56
|
description=None,
|
57
|
+
standardize_Jani=False,
|
57
58
|
):
|
58
59
|
"""
|
59
60
|
:param atoms: Ase atoms structure.
|
@@ -190,6 +191,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
190
191
|
def _build_Rlist(self):
|
191
192
|
Rset = set()
|
192
193
|
ispin_set = set()
|
194
|
+
Rset.add((0, 0, 0)) # always add the zero vector
|
193
195
|
for R, i, j in self.exchange_Jdict:
|
194
196
|
Rset.add(R)
|
195
197
|
ispin_set.add(i)
|
@@ -236,6 +238,23 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
236
238
|
i = self.i_spin(i)
|
237
239
|
return self.charges[self.iatom(i)]
|
238
240
|
|
241
|
+
def get_magnetic_moments(self):
|
242
|
+
"""Get magnetic moments for magnetic atoms only.
|
243
|
+
|
244
|
+
Returns
|
245
|
+
-------
|
246
|
+
np.ndarray
|
247
|
+
Array of shape (n_magnetic_atoms, 3) containing the magnetic moments.
|
248
|
+
For collinear calculations, only the z component is meaningful.
|
249
|
+
"""
|
250
|
+
mag_atoms = [i for i, idx in enumerate(self.index_spin) if idx >= 0]
|
251
|
+
if self.spinat.ndim == 1: # Handle collinear case with only z-component
|
252
|
+
moments = np.zeros((len(mag_atoms), 3))
|
253
|
+
moments[:, 2] = self.spinat[mag_atoms]
|
254
|
+
return moments
|
255
|
+
else: # Full 3D magnetic moments
|
256
|
+
return self.spinat[mag_atoms]
|
257
|
+
|
239
258
|
def get_spin_iatom(self, iatom):
|
240
259
|
return self.spinat[iatom]
|
241
260
|
|
@@ -289,7 +308,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
289
308
|
j,
|
290
309
|
)
|
291
310
|
if self.dmi_ddict is not None and key in self.dmi_ddict:
|
292
|
-
return
|
311
|
+
return self.dmi_ddict[(tuple(R), i, j)]
|
293
312
|
else:
|
294
313
|
return default
|
295
314
|
|
@@ -308,11 +327,11 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
308
327
|
j,
|
309
328
|
)
|
310
329
|
if self.Jani_dict is not None and key in self.Jani_dict:
|
311
|
-
return
|
330
|
+
return self.Jani_dict[(tuple(R), i, j)]
|
312
331
|
else:
|
313
332
|
return default
|
314
333
|
|
315
|
-
def get_J_tensor(self, i, j, R,
|
334
|
+
def get_J_tensor(self, i, j, R, Jiso=True, Jani=False, DMI=False):
|
316
335
|
"""
|
317
336
|
Return the full exchange tensor for atom i and j, and cell R.
|
318
337
|
param i : spin index i
|
@@ -321,21 +340,35 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
321
340
|
"""
|
322
341
|
i = self.i_spin(i)
|
323
342
|
j = self.i_spin(j)
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
343
|
+
J=D=Ja = None
|
344
|
+
if Jiso:
|
345
|
+
J= self.get_Jiso(i, j, R)
|
346
|
+
if DMI:
|
347
|
+
D = self.get_DMI(i, j, R)
|
348
|
+
if D is not None:
|
349
|
+
D*=1
|
350
|
+
if Jani:
|
351
|
+
Ja = self.get_Jani(i, j, R)
|
352
|
+
if Ja is not None:
|
353
|
+
Ja*=1
|
354
|
+
Jtensor = combine_J_tensor(Jiso=J, D=D, Jani=Ja)
|
355
|
+
|
356
|
+
|
357
|
+
# if iso_only:
|
358
|
+
# J = self.get_Jiso(i, j, R)
|
359
|
+
# if J is not None:
|
360
|
+
# Jtensor = np.eye(3) * self.get_J(i, j, R)
|
361
|
+
# else:
|
362
|
+
# Jtensor = np.eye(3) * 0
|
363
|
+
# else:
|
364
|
+
# Jtensor = combine_J_tensor(
|
365
|
+
# Jiso=self.get_J(i, j, R),
|
366
|
+
# D=self.get_DMI(i, j, R),
|
367
|
+
# Jani=self.get_Jani(i, j, R),
|
368
|
+
# )
|
336
369
|
return Jtensor
|
337
370
|
|
338
|
-
def get_full_Jtensor_for_one_R_i3j3(self, R,
|
371
|
+
def get_full_Jtensor_for_one_R_i3j3(self, R, Jiso=True, Jani=True, DMI=True):
|
339
372
|
"""
|
340
373
|
Return the full exchange tensor of all i and j for cell R.
|
341
374
|
param R (tuple of integers): cell index R
|
@@ -347,11 +380,11 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
347
380
|
for i in range(self.nspin):
|
348
381
|
for j in range(self.nspin):
|
349
382
|
Jmat[i * 3 : i * 3 + 3, j * 3 : j * 3 + 3] = self.get_J_tensor(
|
350
|
-
i, j, R,
|
383
|
+
i, j, R, Jiso=Jiso, Jani=Jani, DMI=DMI
|
351
384
|
)
|
352
385
|
return Jmat
|
353
386
|
|
354
|
-
def get_full_Jtensor_for_one_R_ij33(self, R,
|
387
|
+
def get_full_Jtensor_for_one_R_ij33(self, R, Jiso=True, Jani=True, DMI=True):
|
355
388
|
"""
|
356
389
|
Return the full exchange tensor of all i and j for cell R.
|
357
390
|
param R (tuple of integers): cell index R
|
@@ -362,27 +395,36 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
362
395
|
Jmat = np.zeros((n, n, 3, 3), dtype=float)
|
363
396
|
for i in range(self.nspin):
|
364
397
|
for j in range(self.nspin):
|
365
|
-
Jmat[i, j, :, :] = self.get_J_tensor(
|
398
|
+
Jmat[i, j, :, :] = self.get_J_tensor(
|
399
|
+
i, j, R, Jiso=Jiso, Jani=Jani, DMI=DMI
|
400
|
+
)
|
366
401
|
return Jmat
|
367
402
|
|
368
|
-
def get_full_Jtensor_for_Rlist(
|
403
|
+
def get_full_Jtensor_for_Rlist(
|
404
|
+
self, asr=False, Jiso=True, Jani=True, DMI=True, order="i3j3"
|
405
|
+
):
|
369
406
|
n = self.nspin
|
370
407
|
n3 = n * 3
|
371
408
|
nR = len(self.Rlist)
|
372
409
|
if order == "i3j3":
|
373
410
|
Jmat = np.zeros((nR, n3, n3), dtype=float)
|
374
411
|
for iR, R in enumerate(self.Rlist):
|
375
|
-
Jmat[iR] = self.get_full_Jtensor_for_one_R_i3j3(
|
412
|
+
Jmat[iR] = self.get_full_Jtensor_for_one_R_i3j3(
|
413
|
+
R, Jiso=Jiso, Jani=Jani, DMI=DMI
|
414
|
+
)
|
376
415
|
if asr:
|
377
416
|
iR0 = np.argmin(np.linalg.norm(self.Rlist, axis=1))
|
378
417
|
assert np.linalg.norm(self.Rlist[iR0]) == 0
|
379
418
|
for i in range(n3):
|
380
419
|
sum_JRi = np.sum(np.sum(Jmat, axis=0)[i])
|
381
|
-
Jmat[iR0][i, i] -= sum_JRi
|
420
|
+
Jmat[iR0][i, :, i, :] -= sum_JRi
|
382
421
|
|
383
422
|
elif order == "ij33":
|
384
423
|
Jmat = np.zeros((nR, n, n, 3, 3), dtype=float)
|
385
|
-
|
424
|
+
for iR, R in enumerate(self.Rlist):
|
425
|
+
Jmat[iR] = self.get_full_Jtensor_for_one_R_ij33(
|
426
|
+
R, Jiso=Jiso, Jani=Jani, DMI=DMI
|
427
|
+
)
|
386
428
|
if asr:
|
387
429
|
iR0 = np.argmin(np.linalg.norm(self.Rlist, axis=1))
|
388
430
|
assert np.linalg.norm(self.Rlist[iR0]) == 0
|
TB2J/io_exchange/io_vampire.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
import numpy as np
|
2
1
|
import os
|
2
|
+
|
3
|
+
import numpy as np
|
3
4
|
from ase.units import J
|
4
5
|
|
5
6
|
|
@@ -51,10 +52,12 @@ def write_vampire_unitcell_file(cls, fname):
|
|
51
52
|
R, ispin, jspin = key
|
52
53
|
Jtensor = cls.get_J_tensor(ispin, jspin, R)
|
53
54
|
counter += 1 # starts at 0
|
54
|
-
myfile.write(
|
55
|
+
myfile.write(
|
56
|
+
f"{counter:5d} {ispin:3d} {jspin:3d} {R[0]:3d} {R[1]:3d} {R[2]:3d} "
|
57
|
+
)
|
55
58
|
for i in range(3):
|
56
59
|
for j in range(3):
|
57
|
-
val =np.real(Jtensor[i,j]*2.0/J)
|
60
|
+
val = np.real(Jtensor[i, j] * 2.0 / J)
|
58
61
|
if np.abs(val) < 1e-30:
|
59
62
|
val = 0.0
|
60
63
|
myfile.write(f"{val:<012.5e} ")
|
TB2J/io_merge.py
CHANGED
@@ -92,7 +92,6 @@ class Merger():
|
|
92
92
|
self._set_projv()
|
93
93
|
|
94
94
|
def _set_projv(self):
|
95
|
-
|
96
95
|
cell = self.main_dat.atoms.cell.array
|
97
96
|
rotated_cells = np.stack(
|
98
97
|
[obj.atoms.cell.array for obj in self.dat], axis=0
|
@@ -175,11 +174,26 @@ class Merger():
|
|
175
174
|
dmi_ddict[key] = newDMI
|
176
175
|
self.main_dat.dmi_ddict = dmi_ddict
|
177
176
|
|
177
|
+
def standardize(self):
|
178
|
+
# make sure that the Jani has the trace of zero
|
179
|
+
Jdict=self.main_dat.exchange_Jdict
|
180
|
+
Jani_dict=self.main_dat.Jani_dict
|
181
|
+
for key in self.main_dat.Jani_dict.keys():
|
182
|
+
Jani = self.main_dat.Jani_dict[key]
|
183
|
+
shift = np.trace(Jani)/3.0
|
184
|
+
Jani_dict[key] -= shift * np.eye(3)
|
185
|
+
Jdict[key] += shift
|
186
|
+
self.main_dat.Jani_dict = Jani_dict
|
187
|
+
self.main_dat.exchange_Jdict = Jdict
|
188
|
+
|
189
|
+
|
178
190
|
def merge(*paths, main_path=None, save=True, write_path='TB2J_results'):
|
179
191
|
m = Merger(*paths, main_path=main_path)
|
180
192
|
m.merge_Jiso()
|
181
193
|
m.merge_DMI()
|
182
194
|
m.merge_Jani()
|
195
|
+
m.standardize()
|
196
|
+
|
183
197
|
if save:
|
184
198
|
m.main_dat.write_all(path=write_path)
|
185
199
|
return m.dat
|
TB2J/magnon/__init__.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
from .io_exchange2 import ExchangeIO, plot_tb2j_magnon_bands
|
1
|
+
# from .io_exchange2 import ExchangeIO, plot_tb2j_magnon_bands
|
2
2
|
|
3
|
-
__all__ = ["ExchangeIO", "plot_tb2j_magnon_bands"]
|
3
|
+
# __all__ = ["ExchangeIO", "plot_tb2j_magnon_bands"]
|