TB2J 0.7.7.2__py3-none-any.whl → 0.8.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 +1 -1
- TB2J/abacus/__init__.py +1 -0
- TB2J/abacus/abacus_api.py +191 -0
- TB2J/abacus/abacus_wrapper.py +223 -0
- TB2J/abacus/gen_exchange_abacus.py +102 -0
- TB2J/abacus/orbital_api.py +70 -0
- TB2J/abacus/stru_api.py +2020 -0
- TB2J/abacus/test_read_HRSR.py +44 -0
- TB2J/abacus/test_read_stru.py +30 -0
- TB2J/basis.py +67 -0
- TB2J/exchange.py +3 -14
- TB2J/utils.py +5 -0
- TB2J-0.8.0.data/scripts/abacus2J.py +151 -0
- {TB2J-0.7.7.2.dist-info → TB2J-0.8.0.dist-info}/METADATA +1 -1
- {TB2J-0.7.7.2.dist-info → TB2J-0.8.0.dist-info}/RECORD +26 -16
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/TB2J_downfold.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/TB2J_eigen.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/TB2J_magnon.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/TB2J_magnon_dos.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/TB2J_merge.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/TB2J_rotate.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/siesta2J.py +0 -0
- {TB2J-0.7.7.2.data → TB2J-0.8.0.data}/scripts/wann2J.py +0 -0
- {TB2J-0.7.7.2.dist-info → TB2J-0.8.0.dist-info}/LICENSE +0 -0
- {TB2J-0.7.7.2.dist-info → TB2J-0.8.0.dist-info}/WHEEL +0 -0
- {TB2J-0.7.7.2.dist-info → TB2J-0.8.0.dist-info}/top_level.txt +0 -0
TB2J/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.
|
1
|
+
__version__ = "0.8.0"
|
TB2J/abacus/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
from .abacus_wrapper import AbacusWrapper, AbacusParser
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
import numpy as np
|
3
|
+
from scipy import sparse
|
4
|
+
from scipy.sparse import csr_matrix
|
5
|
+
import re
|
6
|
+
import struct
|
7
|
+
|
8
|
+
|
9
|
+
class XR_matrix:
|
10
|
+
def __init__(self, nspin, XR_fileName):
|
11
|
+
self.nspin = nspin
|
12
|
+
self.XR_fileName = XR_fileName
|
13
|
+
|
14
|
+
def read_file(self):
|
15
|
+
with open(self.XR_fileName, "r") as fread:
|
16
|
+
while True:
|
17
|
+
line = fread.readline().split()
|
18
|
+
if line[0] == "Matrix":
|
19
|
+
break
|
20
|
+
|
21
|
+
self.basis_num = int(line[-1])
|
22
|
+
line = fread.readline()
|
23
|
+
self.R_num = int(line.split()[-1])
|
24
|
+
self.R_direct_coor = np.zeros([self.R_num, 3], dtype=int)
|
25
|
+
if self.nspin != 4:
|
26
|
+
self.XR = np.zeros(
|
27
|
+
[self.R_num, self.basis_num, self.basis_num], dtype=float
|
28
|
+
)
|
29
|
+
else:
|
30
|
+
self.XR = np.zeros(
|
31
|
+
[self.R_num, self.basis_num, self.basis_num], dtype=complex
|
32
|
+
)
|
33
|
+
|
34
|
+
for iR in range(self.R_num):
|
35
|
+
line = fread.readline().split()
|
36
|
+
self.R_direct_coor[iR, 0] = int(line[0])
|
37
|
+
self.R_direct_coor[iR, 1] = int(line[1])
|
38
|
+
self.R_direct_coor[iR, 2] = int(line[2])
|
39
|
+
data_size = int(line[3])
|
40
|
+
|
41
|
+
if self.nspin != 4:
|
42
|
+
data = np.zeros((data_size,), dtype=float)
|
43
|
+
else:
|
44
|
+
data = np.zeros((data_size,), dtype=complex)
|
45
|
+
|
46
|
+
indices = np.zeros((data_size,), dtype=int)
|
47
|
+
indptr = np.zeros((self.basis_num + 1,), dtype=int)
|
48
|
+
|
49
|
+
if data_size != 0:
|
50
|
+
if self.nspin != 4:
|
51
|
+
line = fread.readline().split()
|
52
|
+
if len(line) != data_size:
|
53
|
+
print("size = ", len(line), " data_size = ", data_size)
|
54
|
+
for index in range(data_size):
|
55
|
+
data[index] = float(line[index])
|
56
|
+
else:
|
57
|
+
line = re.findall("[(](.*?)[])]", fread.readline())
|
58
|
+
for index in range(data_size):
|
59
|
+
value = line[index].split(",")
|
60
|
+
data[index] = complex(float(value[0]), float(value[1]))
|
61
|
+
|
62
|
+
line = fread.readline().split()
|
63
|
+
for index in range(data_size):
|
64
|
+
indices[index] = int(line[index])
|
65
|
+
|
66
|
+
line = fread.readline().split()
|
67
|
+
for index in range(self.basis_num + 1):
|
68
|
+
indptr[index] = int(line[index])
|
69
|
+
|
70
|
+
self.XR[iR] = csr_matrix(
|
71
|
+
(data, indices, indptr), shape=(self.basis_num, self.basis_num)
|
72
|
+
).toarray()
|
73
|
+
|
74
|
+
def read_file_binary(self):
|
75
|
+
with open(self.XR_fileName, "rb") as fread:
|
76
|
+
self.basis_num = struct.unpack("i", fread.read(4))[0]
|
77
|
+
self.R_num = struct.unpack("i", fread.read(4))[0]
|
78
|
+
self.R_direct_coor = np.zeros([self.R_num, 3], dtype=int)
|
79
|
+
if self.nspin != 4:
|
80
|
+
self.XR = np.zeros(
|
81
|
+
[self.R_num, self.basis_num, self.basis_num], dtype=float
|
82
|
+
)
|
83
|
+
else:
|
84
|
+
self.XR = np.zeros(
|
85
|
+
[self.R_num, self.basis_num, self.basis_num], dtype=complex
|
86
|
+
)
|
87
|
+
|
88
|
+
for iR in range(self.R_num):
|
89
|
+
self.R_direct_coor[iR, 0] = struct.unpack("i", fread.read(4))[0]
|
90
|
+
self.R_direct_coor[iR, 1] = struct.unpack("i", fread.read(4))[0]
|
91
|
+
self.R_direct_coor[iR, 2] = struct.unpack("i", fread.read(4))[0]
|
92
|
+
data_size = struct.unpack("i", fread.read(4))[0]
|
93
|
+
|
94
|
+
if self.nspin != 4:
|
95
|
+
data = np.zeros((data_size,), dtype=float)
|
96
|
+
else:
|
97
|
+
data = np.zeros((data_size,), dtype=complex)
|
98
|
+
|
99
|
+
indices = np.zeros((data_size,), dtype=int)
|
100
|
+
indptr = np.zeros((self.basis_num + 1,), dtype=int)
|
101
|
+
|
102
|
+
if data_size != 0:
|
103
|
+
if self.nspin != 4:
|
104
|
+
for index in range(data_size):
|
105
|
+
data[index] = struct.unpack("d", fread.read(8))[0]
|
106
|
+
else:
|
107
|
+
for index in range(data_size):
|
108
|
+
real = struct.unpack("d", fread.read(8))[0]
|
109
|
+
imag = struct.unpack("d", fread.read(8))[0]
|
110
|
+
data[index] = complex(real, imag)
|
111
|
+
|
112
|
+
for index in range(data_size):
|
113
|
+
indices[index] = struct.unpack("i", fread.read(4))[0]
|
114
|
+
|
115
|
+
for index in range(self.basis_num + 1):
|
116
|
+
indptr[index] = struct.unpack("i", fread.read(4))[0]
|
117
|
+
|
118
|
+
self.XR[iR] = csr_matrix(
|
119
|
+
(data, indices, indptr), shape=(self.basis_num, self.basis_num)
|
120
|
+
).toarray()
|
121
|
+
|
122
|
+
|
123
|
+
def read_HR_SR(
|
124
|
+
nspin=4,
|
125
|
+
binary=False,
|
126
|
+
HR_fileName="data-HR-sparse_SPIN0.csr",
|
127
|
+
SR_fileName="data-SR-sparse_SPIN0.csr",
|
128
|
+
):
|
129
|
+
"""
|
130
|
+
IN:
|
131
|
+
nspin: int, different spins.
|
132
|
+
binary: bool, whether the HR and SR matrices are binary files.
|
133
|
+
HR_fileName: if nspin=1 or 4, str, HR file name;
|
134
|
+
if nspin=2, list or tuple, size=2, [HR_up_fileName, HR_dn_fileName].
|
135
|
+
SR_fileName: str, SR file name.
|
136
|
+
|
137
|
+
OUT:
|
138
|
+
if nspin = 1 or 4:
|
139
|
+
return basis_num, R_direct_coor, HR, SR
|
140
|
+
elif nspin = 2:
|
141
|
+
return basis_num, R_direct_coor, HR_up, HR_dn, SR
|
142
|
+
|
143
|
+
basis_num: int, number of atomic orbital basis.
|
144
|
+
R_direct_coor: numpy ndarray, shape=[R_num, 3], fractional coordinates (x, y, z) of the R-th primitive cell.
|
145
|
+
HR or HR_up or HR_dn: numpy ndarray, shape=[R_num, basis_num, basis_num], HR matrix and unit is eV.
|
146
|
+
SR: numpy ndarray, shape=[R_num, basis_num, basis_num], SR matrix.
|
147
|
+
"""
|
148
|
+
Ry_to_eV = 13.605698066
|
149
|
+
|
150
|
+
if nspin == 1 or nspin == 4:
|
151
|
+
if not isinstance(HR_fileName, str):
|
152
|
+
raise ValueError("The HR_fileName must be a str for nspin=1 or 4.")
|
153
|
+
|
154
|
+
HR = XR_matrix(nspin, HR_fileName)
|
155
|
+
SR = XR_matrix(nspin, SR_fileName)
|
156
|
+
|
157
|
+
if binary:
|
158
|
+
HR.read_file_binary()
|
159
|
+
SR.read_file_binary()
|
160
|
+
else:
|
161
|
+
HR.read_file()
|
162
|
+
SR.read_file()
|
163
|
+
|
164
|
+
return HR.basis_num, HR.R_direct_coor, HR.XR * Ry_to_eV, SR.XR
|
165
|
+
else:
|
166
|
+
if not isinstance(HR_fileName, (list, tuple)):
|
167
|
+
raise ValueError("The HR_fileName must be a list or a tuple for nspin=2.")
|
168
|
+
|
169
|
+
if len(HR_fileName) != 2:
|
170
|
+
raise ValueError("The size of the HR_fileName must be 2 for nspin=2.")
|
171
|
+
|
172
|
+
HR_up = XR_matrix(nspin, HR_fileName[0])
|
173
|
+
HR_dn = XR_matrix(nspin, HR_fileName[1])
|
174
|
+
SR = XR_matrix(nspin, SR_fileName)
|
175
|
+
|
176
|
+
if binary:
|
177
|
+
HR_up.read_file_binary()
|
178
|
+
HR_dn.read_file_binary()
|
179
|
+
SR.read_file_binary()
|
180
|
+
else:
|
181
|
+
HR_up.read_file()
|
182
|
+
HR_dn.read_file()
|
183
|
+
SR.read_file()
|
184
|
+
|
185
|
+
return (
|
186
|
+
HR_up.basis_num,
|
187
|
+
HR_up.R_direct_coor,
|
188
|
+
HR_up.XR * Ry_to_eV,
|
189
|
+
HR_dn.XR * Ry_to_eV,
|
190
|
+
SR.XR,
|
191
|
+
)
|
@@ -0,0 +1,223 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
"""
|
4
|
+
The abacus wrapper
|
5
|
+
"""
|
6
|
+
from pathlib import Path
|
7
|
+
import numpy as np
|
8
|
+
from scipy.linalg import eigh
|
9
|
+
from TB2J.utils import symbol_number_list
|
10
|
+
from TB2J.myTB import AbstractTB
|
11
|
+
from TB2J.abacus.abacus_api import read_HR_SR
|
12
|
+
from TB2J.abacus.orbital_api import parse_abacus_orbital
|
13
|
+
from TB2J.abacus.stru_api import read_abacus, read_abacus_out
|
14
|
+
|
15
|
+
|
16
|
+
class AbacusWrapper(AbstractTB):
|
17
|
+
def __init__(self, HR, SR, Rlist, nbasis, nspin=1):
|
18
|
+
self.R2kfactor = -2j * np.pi
|
19
|
+
self.is_orthogonal = False
|
20
|
+
self.is_siesta = False
|
21
|
+
self._name = "Abacus"
|
22
|
+
self.HR = HR
|
23
|
+
self.SR = SR
|
24
|
+
self.Rlist = Rlist
|
25
|
+
self.nbasis = nbasis
|
26
|
+
self.nspin = nspin
|
27
|
+
self.norb = nbasis * nspin
|
28
|
+
self._build_Rdict()
|
29
|
+
|
30
|
+
def _build_Rdict(self):
|
31
|
+
if hasattr(self, "Rdict"):
|
32
|
+
pass
|
33
|
+
else:
|
34
|
+
self.Rdict = {}
|
35
|
+
for iR, R in enumerate(self.Rlist):
|
36
|
+
self.Rdict[tuple(R)] = iR
|
37
|
+
|
38
|
+
def get_hamR(self, R):
|
39
|
+
return self.HR[self.Rdict[tuple(R)]]
|
40
|
+
|
41
|
+
def gen_ham(self, k, convention=2):
|
42
|
+
"""
|
43
|
+
generate hamiltonian matrix at k point.
|
44
|
+
H_k( i, j)=\sum_R H_R(i, j)^phase.
|
45
|
+
There are two conventions,
|
46
|
+
first:
|
47
|
+
phase =e^{ik(R+rj-ri)}. often better used for berry phase.
|
48
|
+
second:
|
49
|
+
phase= e^{ikR}. We use the first convention here.
|
50
|
+
|
51
|
+
:param k: kpoint
|
52
|
+
:param convention: 1 or 2.
|
53
|
+
"""
|
54
|
+
Hk = np.zeros((self.nbasis, self.nbasis), dtype="complex")
|
55
|
+
Sk = np.zeros((self.nbasis, self.nbasis), dtype="complex")
|
56
|
+
if convention == 2:
|
57
|
+
for iR, R in enumerate(self.Rlist):
|
58
|
+
phase = np.exp(self.R2kfactor * np.dot(k, R))
|
59
|
+
H = self.HR[iR] * phase
|
60
|
+
# Hk += H + H.conjugate().T
|
61
|
+
Hk += H
|
62
|
+
S = self.SR[iR] * phase
|
63
|
+
# Sk += S + S.conjugate().T
|
64
|
+
Sk += S
|
65
|
+
elif convention == 1:
|
66
|
+
# TODO: implement the first convention (the r convention)
|
67
|
+
raise NotImplementedError("convention 1 is not implemented yet.")
|
68
|
+
pass
|
69
|
+
else:
|
70
|
+
raise ValueError("convention should be either 1 or 2.")
|
71
|
+
return Hk, Sk
|
72
|
+
|
73
|
+
def solve(self, k, convention=2):
|
74
|
+
Hk, Sk = self.gen_ham(k, convention=convention)
|
75
|
+
return eigh(Hk, Sk)
|
76
|
+
|
77
|
+
def HSE_k(self, kpt, convention=2):
|
78
|
+
H, S = self.gen_ham(tuple(kpt), convention=convention)
|
79
|
+
evals, evecs = eigh(H, S)
|
80
|
+
return H, S, evals, evecs
|
81
|
+
|
82
|
+
def HS_and_eigen(self, kpts, convention=2):
|
83
|
+
"""
|
84
|
+
calculate eigens for all kpoints.
|
85
|
+
:param kpts: list of k points.
|
86
|
+
"""
|
87
|
+
nk = len(kpts)
|
88
|
+
hams = np.zeros((nk, self.nbasis, self.nbasis), dtype=complex)
|
89
|
+
evals = np.zeros((nk, self.nbasis), dtype=float)
|
90
|
+
evecs = np.zeros((nk, self.nbasis, self.nbasis), dtype=complex)
|
91
|
+
for ik, k in enumerate(kpts):
|
92
|
+
hams[ik], S, evals[ik], evecs[ik] = self.HSE_k(
|
93
|
+
tuple(k), convention=convention
|
94
|
+
)
|
95
|
+
return hams, None, evals, evecs
|
96
|
+
|
97
|
+
|
98
|
+
class AbacusParser:
|
99
|
+
def __init__(self, spin=None, outpath=None, binary=False):
|
100
|
+
self.outpath = outpath
|
101
|
+
if spin is None:
|
102
|
+
self.spin = self.read_spin()
|
103
|
+
else:
|
104
|
+
self.spin = spin
|
105
|
+
self.binary = binary
|
106
|
+
# read the information
|
107
|
+
self.read_atoms()
|
108
|
+
self.efermi = self.read_efermi()
|
109
|
+
self.read_basis()
|
110
|
+
|
111
|
+
def read_spin(self):
|
112
|
+
with open(str(Path(self.outpath) / "running_scf.log")) as myfile:
|
113
|
+
for line in myfile:
|
114
|
+
if line.strip().startswith("nspin"):
|
115
|
+
nspin = int(line.strip().split()[-1])
|
116
|
+
if nspin == 1:
|
117
|
+
return "non-polarized"
|
118
|
+
elif nspin == 2:
|
119
|
+
return "collinear"
|
120
|
+
elif nspin == 2:
|
121
|
+
return "noncollinear"
|
122
|
+
else:
|
123
|
+
raise ValueError("nspin should be either 1 or 4.")
|
124
|
+
|
125
|
+
def read_atoms(self):
|
126
|
+
self.atoms = read_abacus(str(Path(self.outpath) / "../Stru"))
|
127
|
+
return self.atoms
|
128
|
+
|
129
|
+
def read_basis(self):
|
130
|
+
fname = str(Path(self.outpath) / "Orbital")
|
131
|
+
self.basis = parse_abacus_orbital(fname)
|
132
|
+
return self.basis
|
133
|
+
|
134
|
+
def read_HSR_collinear(self, binary=None):
|
135
|
+
p = Path(self.outpath)
|
136
|
+
SR_filename = p / "data-SR-sparse_SPIN0.csr"
|
137
|
+
HR_filename = [p / "data-HR-sparse_SPIN0.csr", p / "data-HR-sparse_SPIN1.csr"]
|
138
|
+
nbasis, Rlist, HR_up, HR_dn, SR = read_HR_SR(
|
139
|
+
nspin=2,
|
140
|
+
binary=self.binary,
|
141
|
+
HR_fileName=HR_filename,
|
142
|
+
SR_fileName=SR_filename,
|
143
|
+
)
|
144
|
+
return nbasis, Rlist, HR_up, HR_dn, SR
|
145
|
+
|
146
|
+
def Read_HSR_noncollinear(self, binary=None):
|
147
|
+
p = Path(self.outpath)
|
148
|
+
SR_filename = (p / "data-SR-sparse_SPIN0.csr").as_posix()
|
149
|
+
HR_filename = p / "data-HR-sparse_SPIN0.csr".as_posix()
|
150
|
+
self.nbasis, self.Rlist, self.HR, self.SR = read_HR_SR(
|
151
|
+
nspin=4,
|
152
|
+
binary=self.binary,
|
153
|
+
HR_fileName=HR_filename,
|
154
|
+
SR_fileName=SR_filename,
|
155
|
+
)
|
156
|
+
|
157
|
+
def get_models(self):
|
158
|
+
if self.spin == "collinear":
|
159
|
+
nbasis, Rlist, HR_up, HR_dn, SR = self.read_HSR_collinear()
|
160
|
+
model_up = AbacusWrapper(HR_up, SR, Rlist, nbasis, nspin=1)
|
161
|
+
model_dn = AbacusWrapper(HR_dn, SR, Rlist, nbasis, nspin=1)
|
162
|
+
model_up.efermi = self.efermi
|
163
|
+
model_dn.efermi = self.efermi
|
164
|
+
model_up.basis, model_dn.basis = self.get_basis()
|
165
|
+
model_up.atoms = self.atoms
|
166
|
+
model_dn.atoms = self.atoms
|
167
|
+
return model_up, model_dn
|
168
|
+
elif self.spin == "noncollinear":
|
169
|
+
nbasis, Rlist, HR, SR = self.Read_HSR_noncollinear()
|
170
|
+
model = AbacusWrapper(HR, SR, Rlist, nbasis, nspin=2)
|
171
|
+
model.efermi = self.efermi
|
172
|
+
model.basis = self.get_basis()
|
173
|
+
model.atoms = self.atoms
|
174
|
+
return model
|
175
|
+
|
176
|
+
def read_efermi(self):
|
177
|
+
"""
|
178
|
+
Reading the efermi from the scf log file.
|
179
|
+
Search for the line EFERMI = xxxxx eV
|
180
|
+
"""
|
181
|
+
fname = str(Path(self.outpath) / "running_scf.log")
|
182
|
+
efermi = None
|
183
|
+
with open(fname, "r") as myfile:
|
184
|
+
for line in myfile:
|
185
|
+
if "EFERMI" in line:
|
186
|
+
efermi = float(line.split()[2])
|
187
|
+
if efermi is None:
|
188
|
+
raise ValueError(f"EFERMI not found in the {str(fname)} file.")
|
189
|
+
return efermi
|
190
|
+
|
191
|
+
def get_basis(self):
|
192
|
+
slist = symbol_number_list(self.atoms)
|
193
|
+
if self.spin == "collinear":
|
194
|
+
basis_up = []
|
195
|
+
basis_dn = []
|
196
|
+
for b in self.basis:
|
197
|
+
basis_up.append((slist[b.iatom], b.sym, "up"))
|
198
|
+
basis_dn.append((slist[b.iatom], b.sym, "down"))
|
199
|
+
return basis_up, basis_dn
|
200
|
+
elif self.spin == "noncollinear":
|
201
|
+
basis = []
|
202
|
+
for b in self.basis:
|
203
|
+
basis.append((slist[b.iatom], b.sym, "up"))
|
204
|
+
basis.append((slist[b.iatom], b.sym, "down"))
|
205
|
+
return basis
|
206
|
+
|
207
|
+
|
208
|
+
def test_abacus_wrapper():
|
209
|
+
outpath = "/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Fe/1_no_soc/OUT.Fe"
|
210
|
+
parser = AbacusParser(outpath=outpath, spin=None, binary=False)
|
211
|
+
atoms = parser.read_atoms()
|
212
|
+
# atoms=parser.read_atoms_out()
|
213
|
+
# parser.read_HSR_collinear()
|
214
|
+
model_up, model_dn = parser.get_models()
|
215
|
+
H, S, E, V = model_up.HSE_k([0, 0, 0])
|
216
|
+
# print(H.shape)
|
217
|
+
# print(H.diagonal().real)
|
218
|
+
# print(model_up.get_HR0().diagonal().real)
|
219
|
+
print(parser.get_efermi())
|
220
|
+
|
221
|
+
|
222
|
+
if __name__ == "__main__":
|
223
|
+
test_abacus_wrapper()
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
"""
|
4
|
+
The main function to compute exchange interaction from abacus data
|
5
|
+
"""
|
6
|
+
|
7
|
+
import os
|
8
|
+
from pathlib import Path
|
9
|
+
from TB2J.abacus.abacus_wrapper import AbacusParser
|
10
|
+
from TB2J.exchange import ExchangeNCL, ExchangeCL
|
11
|
+
from TB2J.exchangeCL2 import ExchangeCL2
|
12
|
+
|
13
|
+
|
14
|
+
def gen_exchange_abacus(
|
15
|
+
path,
|
16
|
+
suffix="Abacus",
|
17
|
+
binary=False,
|
18
|
+
magnetic_elements=[],
|
19
|
+
include_orbs=[],
|
20
|
+
kmesh=[7, 7, 7],
|
21
|
+
emin=-13.0,
|
22
|
+
emax=0.00,
|
23
|
+
nz=100,
|
24
|
+
exclude_orbs=[],
|
25
|
+
Rcut=None,
|
26
|
+
use_cache=False,
|
27
|
+
np=1,
|
28
|
+
output_path="TB2J_results",
|
29
|
+
orb_decomposition=False,
|
30
|
+
description=None,
|
31
|
+
):
|
32
|
+
outpath = Path(path) / f"OUT.{suffix}"
|
33
|
+
|
34
|
+
if not os.path.exists(outpath):
|
35
|
+
raise ValueError(
|
36
|
+
f"The path {outpath} does not exist. Please check if the path and the suffix is correct"
|
37
|
+
)
|
38
|
+
parser = AbacusParser(outpath=outpath, spin=None, binary=binary)
|
39
|
+
spin = parser.read_spin()
|
40
|
+
if spin == "collinear":
|
41
|
+
tbmodel_up, tbmodel_dn = parser.get_models()
|
42
|
+
efermi = parser.read_efermi()
|
43
|
+
print("Starting to calculate exchange.")
|
44
|
+
description = f""" Input from collinear Abacus data.
|
45
|
+
data directory: {outpath}
|
46
|
+
\n"""
|
47
|
+
exchange = ExchangeCL2(
|
48
|
+
tbmodels=(tbmodel_up, tbmodel_dn),
|
49
|
+
atoms=tbmodel_up.atoms,
|
50
|
+
basis=tbmodel_up.basis,
|
51
|
+
efermi=efermi,
|
52
|
+
magnetic_elements=magnetic_elements,
|
53
|
+
include_orbs=include_orbs,
|
54
|
+
kmesh=kmesh,
|
55
|
+
emin=emin,
|
56
|
+
emax=emax,
|
57
|
+
nz=nz,
|
58
|
+
exclude_orbs=exclude_orbs,
|
59
|
+
Rcut=Rcut,
|
60
|
+
np=np,
|
61
|
+
use_cache=use_cache,
|
62
|
+
output_path=output_path,
|
63
|
+
description=description,
|
64
|
+
)
|
65
|
+
exchange.run(path=output_path)
|
66
|
+
print("\n")
|
67
|
+
print(f"All calculation finsihed. The results are in {output_path} directory.")
|
68
|
+
else:
|
69
|
+
tbmodel = parser.get_models()
|
70
|
+
print("Starting to calculate exchange.")
|
71
|
+
description = f""" Input from collinear Abacus data.
|
72
|
+
data directory: {outpath}
|
73
|
+
\n"""
|
74
|
+
exchange = ExchangeNCL(
|
75
|
+
tbmodels=tbmodel,
|
76
|
+
atoms=tbmodel.atoms,
|
77
|
+
basis=tbmodel.basis,
|
78
|
+
efermi=tbmodel.efermi,
|
79
|
+
magnetic_elements=magnetic_elements,
|
80
|
+
kmesh=kmesh,
|
81
|
+
emin=emin,
|
82
|
+
emax=emax,
|
83
|
+
nz=nz,
|
84
|
+
exclude_orbs=exclude_orbs,
|
85
|
+
Rcut=Rcut,
|
86
|
+
use_cache=use_cache,
|
87
|
+
description=description,
|
88
|
+
)
|
89
|
+
exchange.run()
|
90
|
+
print("\n")
|
91
|
+
print("All calculation finsihed. The results are in TB2J_results directory.")
|
92
|
+
|
93
|
+
|
94
|
+
if __name__ == "__main__":
|
95
|
+
gen_exchange_abacus(
|
96
|
+
path="/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Fe/1_no_soc",
|
97
|
+
label="Fe",
|
98
|
+
magnetic_elements=["Fe"],
|
99
|
+
nz=50,
|
100
|
+
Rcut=8,
|
101
|
+
kmesh=[7, 7, 7],
|
102
|
+
)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/vin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
"""
|
4
|
+
Parser for the abacus orbital file
|
5
|
+
"""
|
6
|
+
from pathlib import Path
|
7
|
+
import numpy as np
|
8
|
+
from dataclasses import dataclass
|
9
|
+
from collections import namedtuple
|
10
|
+
from TB2J.utils import symbol_number, symbol_number_list
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass
|
14
|
+
class AbacusOrbital:
|
15
|
+
"""
|
16
|
+
Orbital class
|
17
|
+
"""
|
18
|
+
|
19
|
+
iatom: int
|
20
|
+
sym: str
|
21
|
+
spin: int
|
22
|
+
element: str
|
23
|
+
l: int
|
24
|
+
m: int
|
25
|
+
z: int
|
26
|
+
|
27
|
+
|
28
|
+
def parse_abacus_orbital(fname):
|
29
|
+
"""
|
30
|
+
parse the abacus orbital file
|
31
|
+
"""
|
32
|
+
orbs = []
|
33
|
+
with open(fname, "r") as myfile:
|
34
|
+
line = myfile.readline()
|
35
|
+
line = myfile.readline()
|
36
|
+
while line.strip() != "":
|
37
|
+
seg = line.split()
|
38
|
+
iatom, element, l, m, z, sym = seg
|
39
|
+
iatom = int(iatom)
|
40
|
+
ispin = 0
|
41
|
+
l = int(l)
|
42
|
+
m = int(m)
|
43
|
+
z = int(z)
|
44
|
+
orbs.append(AbacusOrbital(iatom, sym, ispin, element, l, m, z))
|
45
|
+
line = myfile.readline()
|
46
|
+
return orbs
|
47
|
+
|
48
|
+
|
49
|
+
def bset_to_symnum_type(bset, atoms):
|
50
|
+
"""
|
51
|
+
convert the basis set to symbol number type
|
52
|
+
"""
|
53
|
+
slist = symbol_number_list(atoms)
|
54
|
+
result = []
|
55
|
+
for b in bset:
|
56
|
+
result.append((slist[b.iatom], b.sym, b.spin))
|
57
|
+
return result
|
58
|
+
|
59
|
+
|
60
|
+
def test_parse_abacus_orbital():
|
61
|
+
"""
|
62
|
+
test the parser
|
63
|
+
"""
|
64
|
+
outpath = "/Users/hexu/projects/TB2J_abacus/abacus-tb2j-master/abacus_example/case_Sr2Mn2O6/1_no_soc/OUT.Sr2Mn2O6"
|
65
|
+
orbs = parse_abacus_orbital(Path(outpath) / "Orbital")
|
66
|
+
print(orbs)
|
67
|
+
|
68
|
+
|
69
|
+
if __name__ == "__main__":
|
70
|
+
test_parse_abacus_orbital()
|