TB2J 0.8.2.8__tar.gz → 0.9.0.1__tar.gz
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-0.8.2.8 → TB2J-0.9.0.1}/PKG-INFO +9 -4
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/README.md +2 -0
- TB2J-0.9.0.1/TB2J/__init__.py +1 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/abacus_wrapper.py +1 -2
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchange.py +3 -3
- TB2J-0.9.0.1/TB2J/io_merge.py +184 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/myTB.py +0 -2
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/rotate_atoms.py +22 -20
- TB2J-0.9.0.1/TB2J/rotate_siestaDM.py +36 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/sisl_wrapper.py +0 -1
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/PKG-INFO +9 -4
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/SOURCES.txt +2 -2
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_merge.py +9 -2
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_rotate.py +6 -1
- TB2J-0.9.0.1/scripts/TB2J_rotateDM.py +21 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/setup.py +2 -1
- TB2J-0.8.2.8/TB2J/__init__.py +0 -1
- TB2J-0.8.2.8/TB2J/io_merge.py +0 -435
- TB2J-0.8.2.8/TB2J/spinham/h_matrix.py +0 -68
- TB2J-0.8.2.8/TB2J/spinham/obtain_J.py +0 -79
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/LICENSE +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Jdownfolder.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Jtensor.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Oiju.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Oiju_epc.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/__init__.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/abacus_api.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/gen_exchange_abacus.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/orbital_api.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/stru_api.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/test_read_HRSR.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/test_read_stru.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/basis.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/citation.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/contour.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/density_matrix.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/epc.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchangeCL2.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchange_pert.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchange_qspace.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/external/__init__.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/external/p_tqdm.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/gpaw_wrapper.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/green.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/greentest.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/__init__.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_exchange.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_multibinit.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_tomsasd.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_txt.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_uppasd.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_vampire.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/kpoints.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/manager.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/mathutils.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/orbmap.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/pauli.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/pert.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/plot.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/__init__.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/base_parser.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/constants.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/hamiltonian.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/hamiltonian_terms.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/plot.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/qsolver.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/spin_api.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/spin_xml.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/supercell.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/tensor_rotate.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/utest.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/utils.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/versioninfo.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/wannier/__init__.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/wannier/w90_parser.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/wannier/w90_tb_parser.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/dependency_links.txt +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/requires.txt +5 -5
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/top_level.txt +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_downfold.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_eigen.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_magnon.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_magnon_dos.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/abacus2J.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/siesta2J.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/wann2J.py +0 -0
- {TB2J-0.8.2.8 → TB2J-0.9.0.1}/setup.cfg +0 -0
@@ -1,12 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: TB2J
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.9.0.1
|
4
4
|
Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
|
5
|
-
Home-page: UNKNOWN
|
6
5
|
Author: Xu He
|
7
6
|
Author-email: mailhexu@gmail.com
|
8
7
|
License: BSD-2-clause
|
9
|
-
Platform: UNKNOWN
|
10
8
|
Classifier: Development Status :: 3 - Alpha
|
11
9
|
Classifier: Programming Language :: Python :: 3
|
12
10
|
Classifier: Operating System :: OS Independent
|
@@ -16,6 +14,13 @@ Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
14
|
Classifier: License :: OSI Approved :: BSD License
|
17
15
|
Requires-Python: >=3.6
|
18
16
|
License-File: LICENSE
|
17
|
+
Requires-Dist: numpy>1.16.5
|
18
|
+
Requires-Dist: scipy
|
19
|
+
Requires-Dist: matplotlib
|
20
|
+
Requires-Dist: ase>=3.19
|
21
|
+
Requires-Dist: tqdm
|
22
|
+
Requires-Dist: pathos
|
23
|
+
Requires-Dist: packaging>=20.0
|
24
|
+
Requires-Dist: pre-commit
|
19
25
|
|
20
26
|
TB2J is a Python package aimed to compute automatically the magnetic interactions (superexchange and Dzyaloshinskii-Moriya) between atoms of magnetic crystals from DFT Hamiltonian based on Wannier functions or Linear combination of atomic orbitals. It uses the Green's function method and take the local rigid spin rotation as a perturbation. The package can take the output from Wannier90, which is interfaced with many density functional theory codes or from codes based on localised orbitals. A minimal user input is needed, which allows for an easily integration into a high-throughput workflows.
|
21
|
-
|
@@ -7,6 +7,8 @@
|
|
7
7
|
|
8
8
|
TB2J is a open source python package for calculating the magnetic interaction parameters in Heisenberg models from DFT. It use the magnetic force theorem and take the local rigid spin rotation as a perturbation in the Green's function method.
|
9
9
|
|
10
|
+
The TB2J project is initialized in the PhyTheMa and Nanomat teams in the University of Liege.
|
11
|
+
|
10
12
|
The features include:
|
11
13
|
- Calculates parameters in Heisenberg model, including isotropic exchange, anisotropic exchange, Dyzanoshinskii-Moriya interaction.
|
12
14
|
- Can use the input from many DFT codes with Wannier90, e.g. Abinit, Quantum Espresso, Siesta, VASP, etc.
|
@@ -0,0 +1 @@
|
|
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.
|
22
|
-
self._name = "Abacus"
|
21
|
+
self._name = "ABACUS"
|
23
22
|
self.HR = HR
|
24
23
|
self.SR = SR
|
25
24
|
self.Rlist = Rlist
|
@@ -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()
|
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()
|
@@ -0,0 +1,184 @@
|
|
1
|
+
import os
|
2
|
+
import copy
|
3
|
+
import warnings
|
4
|
+
import numpy as np
|
5
|
+
from itertools import combinations_with_replacement, product
|
6
|
+
from TB2J.io_exchange import SpinIO
|
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])
|
11
|
+
|
12
|
+
def get_Jani_coefficients(a, R=np.eye(3)):
|
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])
|
24
|
+
|
25
|
+
return coefficients, u, v
|
26
|
+
|
27
|
+
def get_projections(a, b, tol=1e-2):
|
28
|
+
|
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
|
41
|
+
|
42
|
+
return projections
|
43
|
+
|
44
|
+
class SpinIO_merge(SpinIO):
|
45
|
+
def __init__(self, *args, **kwargs):
|
46
|
+
super(SpinIO_merge, self).__init__(*args, **kwargs)
|
47
|
+
self.projv = None
|
48
|
+
|
49
|
+
def _set_projection_vectors(self):
|
50
|
+
|
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]
|
58
|
+
|
59
|
+
self.projv = projv
|
60
|
+
|
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()
|
65
|
+
|
66
|
+
return obj
|
67
|
+
|
68
|
+
def read_pickle(path):
|
69
|
+
p1 = os.path.join(path, 'TB2J_results', 'TB2J.pickle')
|
70
|
+
p2 = os.path.join(path, 'TB2J.pickle')
|
71
|
+
if os.path.exists(p1) and os.path.exists(p2):
|
72
|
+
print(f" WARNING!: Both file {p1} and {p2} exist. Use default {p1}.")
|
73
|
+
if os.path.exists(p1):
|
74
|
+
ret = SpinIO_merge.load_pickle(os.path.join(path, 'TB2J_results'))
|
75
|
+
elif os.path.exists(p2):
|
76
|
+
ret = SpinIO_merge.load_pickle(path)
|
77
|
+
else:
|
78
|
+
raise FileNotFoundError(f"Cannot find either file {p1} or {p2}")
|
79
|
+
return ret
|
80
|
+
|
81
|
+
class Merger():
|
82
|
+
def __init__(self, *paths, main_path=None):
|
83
|
+
self.dat = [read_pickle(path) for path in paths]
|
84
|
+
|
85
|
+
if main_path is None:
|
86
|
+
self.main_dat = copy.deepcopy(self.dat[-1])
|
87
|
+
else:
|
88
|
+
self.main_dat = read_pickle(main_path)
|
89
|
+
self.dat.append(copy.deepcopy(self.main_dat))
|
90
|
+
|
91
|
+
self._set_projv()
|
92
|
+
|
93
|
+
def _set_projv(self):
|
94
|
+
|
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
|
98
|
+
)
|
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
|
123
|
+
|
124
|
+
def merge_Jani(self):
|
125
|
+
Jani_dict = {}
|
126
|
+
proju = self.proju; projv = self.projv; coeff_matrix = self.coeff_matrix;
|
127
|
+
for key in self.main_dat.Jani_dict.keys():
|
128
|
+
try:
|
129
|
+
R, i, j = key
|
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()
|
134
|
+
except KeyError as err:
|
135
|
+
raise KeyError(
|
136
|
+
"Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
|
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
|
145
|
+
|
146
|
+
def merge_Jiso(self):
|
147
|
+
Jdict={}
|
148
|
+
for key in self.main_dat.exchange_Jdict.keys():
|
149
|
+
try:
|
150
|
+
J = np.mean([obj.exchange_Jdict[key] for obj in self.dat])
|
151
|
+
except KeyError as err:
|
152
|
+
raise KeyError(
|
153
|
+
"Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
|
154
|
+
% err)
|
155
|
+
Jdict[key] = J
|
156
|
+
self.main_dat.exchange_Jdict = Jdict
|
157
|
+
|
158
|
+
|
159
|
+
def merge_DMI(self):
|
160
|
+
dmi_ddict = {}
|
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():
|
164
|
+
try:
|
165
|
+
R, i, j = key
|
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()
|
169
|
+
except KeyError as err:
|
170
|
+
raise KeyError(
|
171
|
+
"Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
|
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
|
176
|
+
|
177
|
+
def merge(*paths, main_path=None, save=True, write_path='TB2J_results'):
|
178
|
+
m = Merger(*paths, main_path=main_path)
|
179
|
+
m.merge_Jiso()
|
180
|
+
m.merge_DMI()
|
181
|
+
m.merge_Jani()
|
182
|
+
if save:
|
183
|
+
m.main_dat.write_all(path=write_path)
|
184
|
+
return m.dat
|
@@ -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
|
|
@@ -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
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
109
|
+
rotated = rotate_atom_xyz(atoms, noncollinear=noncollinear)
|
105
110
|
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
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.")
|
@@ -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)
|
@@ -1,12 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: TB2J
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.9.0.1
|
4
4
|
Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
|
5
|
-
Home-page: UNKNOWN
|
6
5
|
Author: Xu He
|
7
6
|
Author-email: mailhexu@gmail.com
|
8
7
|
License: BSD-2-clause
|
9
|
-
Platform: UNKNOWN
|
10
8
|
Classifier: Development Status :: 3 - Alpha
|
11
9
|
Classifier: Programming Language :: Python :: 3
|
12
10
|
Classifier: Operating System :: OS Independent
|
@@ -16,6 +14,13 @@ Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
14
|
Classifier: License :: OSI Approved :: BSD License
|
17
15
|
Requires-Python: >=3.6
|
18
16
|
License-File: LICENSE
|
17
|
+
Requires-Dist: numpy>1.16.5
|
18
|
+
Requires-Dist: scipy
|
19
|
+
Requires-Dist: matplotlib
|
20
|
+
Requires-Dist: ase>=3.19
|
21
|
+
Requires-Dist: tqdm
|
22
|
+
Requires-Dist: pathos
|
23
|
+
Requires-Dist: packaging>=20.0
|
24
|
+
Requires-Dist: pre-commit
|
19
25
|
|
20
26
|
TB2J is a Python package aimed to compute automatically the magnetic interactions (superexchange and Dzyaloshinskii-Moriya) between atoms of magnetic crystals from DFT Hamiltonian based on Wannier functions or Linear combination of atomic orbitals. It uses the Green's function method and take the local rigid spin rotation as a perturbation. The package can take the output from Wannier90, which is interfaced with many density functional theory codes or from codes based on localised orbitals. A minimal user input is needed, which allows for an easily integration into a high-throughput workflows.
|
21
|
-
|
@@ -28,6 +28,7 @@ TB2J/pauli.py
|
|
28
28
|
TB2J/pert.py
|
29
29
|
TB2J/plot.py
|
30
30
|
TB2J/rotate_atoms.py
|
31
|
+
TB2J/rotate_siestaDM.py
|
31
32
|
TB2J/sisl_wrapper.py
|
32
33
|
TB2J/tensor_rotate.py
|
33
34
|
TB2J/utest.py
|
@@ -58,10 +59,8 @@ TB2J/io_exchange/io_vampire.py
|
|
58
59
|
TB2J/spinham/__init__.py
|
59
60
|
TB2J/spinham/base_parser.py
|
60
61
|
TB2J/spinham/constants.py
|
61
|
-
TB2J/spinham/h_matrix.py
|
62
62
|
TB2J/spinham/hamiltonian.py
|
63
63
|
TB2J/spinham/hamiltonian_terms.py
|
64
|
-
TB2J/spinham/obtain_J.py
|
65
64
|
TB2J/spinham/plot.py
|
66
65
|
TB2J/spinham/qsolver.py
|
67
66
|
TB2J/spinham/spin_api.py
|
@@ -76,6 +75,7 @@ scripts/TB2J_magnon.py
|
|
76
75
|
scripts/TB2J_magnon_dos.py
|
77
76
|
scripts/TB2J_merge.py
|
78
77
|
scripts/TB2J_rotate.py
|
78
|
+
scripts/TB2J_rotateDM.py
|
79
79
|
scripts/abacus2J.py
|
80
80
|
scripts/siesta2J.py
|
81
81
|
scripts/wann2J.py
|
@@ -2,7 +2,7 @@
|
|
2
2
|
import argparse
|
3
3
|
import os
|
4
4
|
import sys
|
5
|
-
from TB2J.io_merge import merge
|
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
|
+
#!/usr/bin/env python3
|
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,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
2
|
from setuptools import setup, find_packages
|
3
3
|
|
4
|
-
__version__ = "0.
|
4
|
+
__version__ = "0.9.0.1"
|
5
5
|
|
6
6
|
long_description = """TB2J is a Python package aimed to compute automatically the magnetic interactions (superexchange and Dzyaloshinskii-Moriya) between atoms of magnetic crystals from DFT Hamiltonian based on Wannier functions or Linear combination of atomic orbitals. It uses the Green's function method and take the local rigid spin rotation as a perturbation. The package can take the output from Wannier90, which is interfaced with many density functional theory codes or from codes based on localised orbitals. A minimal user input is needed, which allows for an easily integration into a high-throughput workflows. """
|
7
7
|
|
@@ -19,6 +19,7 @@ setup(
|
|
19
19
|
"scripts/siesta2J.py",
|
20
20
|
"scripts/abacus2J.py",
|
21
21
|
"scripts/TB2J_rotate.py",
|
22
|
+
"scripts/TB2J_rotateDM.py",
|
22
23
|
"scripts/TB2J_merge.py",
|
23
24
|
"scripts/TB2J_magnon.py",
|
24
25
|
"scripts/TB2J_magnon_dos.py",
|
TB2J-0.8.2.8/TB2J/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.8.2.8"
|