TB2J 0.9.9rc4__tar.gz → 0.9.9rc6__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.9.9rc4 → tb2j-0.9.9rc6}/PKG-INFO +1 -1
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/MAE.py +3 -3
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/MAEGreen.py +43 -11
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/contour.py +16 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/exchange.py +30 -27
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/exchangeCL2.py +20 -11
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/exchange_params.py +19 -4
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/green.py +77 -14
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/siesta_interface.py +2 -1
- tb2j-0.9.9rc6/TB2J/kpoints.py +101 -0
- tb2j-0.9.9rc6/TB2J/mycfr.py +114 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/orbmap.py +4 -4
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/symmetrize_J.py +17 -7
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/versioninfo.py +2 -1
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J.egg-info/PKG-INFO +1 -1
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J.egg-info/SOURCES.txt +1 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/setup.py +1 -1
- tb2j-0.9.9rc4/TB2J/kpoints.py +0 -16
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/LICENSE +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/README.md +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/Jdownfolder.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/Jtensor.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/Oiju.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/Oiju_epc.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/anisotropy.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/basis.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/citation.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/density_matrix.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/epc.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/exchange_pert.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/exchange_qspace.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/external/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/external/p_tqdm.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/gpaw_wrapper.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/greentest.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/abacus_api.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/abacus_wrapper.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/gen_exchange_abacus.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/orbital_api.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/stru_api.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/test_density_matrix.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/test_read_HRSR.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/test_read_stru.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/gpaw_interface.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/lawaf_interface.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/manager.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/interfaces/wannier90_interface.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_exchange.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_multibinit.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_tomsasd.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_txt.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_uppasd.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_vampire.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/io_merge.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/mathutils/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/mathutils/fermi.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/mathutils/kR_convert.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/mathutils/lowdin.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/mathutils/rotate_spin.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/myTB.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/pauli.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/pert.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/plot.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/rotate_atoms.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/rotate_siestaDM.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/sisl_wrapper.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/base_parser.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/constants.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/hamiltonian.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/hamiltonian_terms.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/plot.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/qsolver.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/spin_api.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/spin_xml.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/spinham/supercell.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/tensor_rotate.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/utest.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/utils.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/wannier/__init__.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/wannier/w90_parser.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J/wannier/w90_tb_parser.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J.egg-info/dependency_links.txt +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J.egg-info/entry_points.txt +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J.egg-info/requires.txt +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/TB2J.egg-info/top_level.txt +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_downfold.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_eigen.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_magnon.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_magnon_dos.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_merge.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_rotate.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/TB2J_rotateDM.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/abacus2J.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/siesta2J.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/scripts/wann2J.py +0 -0
- {tb2j-0.9.9rc4 → tb2j-0.9.9rc6}/setup.cfg +0 -0
@@ -137,9 +137,9 @@ class MAEGreen(MAE):
|
|
137
137
|
efermi = occ.efermi(evals)
|
138
138
|
print(f"{efermi=}")
|
139
139
|
self.G = TBGreen(model, kmesh, efermi=efermi, gamma=gamma, **kwargs)
|
140
|
-
self.emin = -
|
140
|
+
self.emin = -52
|
141
141
|
self.emax = 0
|
142
|
-
self.nz =
|
142
|
+
self.nz = 100
|
143
143
|
self._prepare_elist()
|
144
144
|
|
145
145
|
def _prepare_elist(self, method="legendre"):
|
@@ -186,7 +186,7 @@ class MAEGreen(MAE):
|
|
186
186
|
for ie, e in enumerate(tqdm.tqdm(self.contour.path)):
|
187
187
|
dE_angle = self.get_perturbed(e, thetas, phis)
|
188
188
|
es += np.imag(dE_angle * self.contour.weights[ie])
|
189
|
-
return -es / np.pi
|
189
|
+
return -es / np.pi / 2
|
190
190
|
|
191
191
|
|
192
192
|
def get_model_energy(model, kmesh, gamma=True):
|
@@ -3,10 +3,11 @@ from pathlib import Path
|
|
3
3
|
import numpy as np
|
4
4
|
import tqdm
|
5
5
|
from HamiltonIO.abacus.abacus_wrapper import AbacusSplitSOCParser
|
6
|
-
from HamiltonIO.model.occupations import
|
6
|
+
from HamiltonIO.model.occupations import GaussOccupations
|
7
7
|
from typing_extensions import DefaultDict
|
8
8
|
|
9
9
|
from TB2J.exchange import ExchangeNCL
|
10
|
+
from TB2J.external import p_map
|
10
11
|
|
11
12
|
# from HamiltonIO.model.rotate_spin import rotate_Matrix_from_z_to_axis, rotate_Matrix_from_z_to_sperical
|
12
13
|
# from TB2J.abacus.abacus_wrapper import AbacusWrapper, AbacusParser
|
@@ -16,7 +17,7 @@ from TB2J.mathutils.rotate_spin import (
|
|
16
17
|
|
17
18
|
|
18
19
|
def get_occupation(evals, kweights, nel, width=0.1):
|
19
|
-
occ =
|
20
|
+
occ = GaussOccupations(nel=nel, width=width, wk=kweights, nspin=2)
|
20
21
|
return occ.occupy(evals)
|
21
22
|
|
22
23
|
|
@@ -78,6 +79,17 @@ class MAEGreen(ExchangeNCL):
|
|
78
79
|
|
79
80
|
def get_perturbed(self, e, thetas, phis):
|
80
81
|
self.tbmodel.set_so_strength(0.0)
|
82
|
+
maxsoc = self.tbmodel.get_max_Hsoc_abs()
|
83
|
+
maxH0 = self.tbmodel.get_max_H0_spin_abs()
|
84
|
+
if maxsoc > maxH0 * 0.01:
|
85
|
+
print(f"""Warning: The SOC of the Hamiltonian has a maximum of {maxsoc} eV,
|
86
|
+
comparing to the maximum of {maxH0} eV of the spin part of the Hamiltonian.
|
87
|
+
The SOC is too strong, the perturbation theory may not be valid.""")
|
88
|
+
|
89
|
+
print(f"""Warning: The SOC of the Hamiltonian has a maximum of {maxsoc} eV,
|
90
|
+
comparing to the maximum of {maxH0} eV of the spin part of the Hamiltonian.
|
91
|
+
The SOC is too strong, the perturbation theory may not be valid.""")
|
92
|
+
|
81
93
|
G0K = self.G.get_Gk_all(e)
|
82
94
|
Hsoc_k = self.tbmodel.get_Hk_soc(self.G.kpts)
|
83
95
|
na = len(thetas)
|
@@ -97,6 +109,7 @@ class MAEGreen(ExchangeNCL):
|
|
97
109
|
dG2 = GdH * GdH.T
|
98
110
|
dG2sum = np.sum(dG2)
|
99
111
|
# print(f"dG2sum-sum: {dG2sum}")
|
112
|
+
dG2sum = np.sum(dG2diag)
|
100
113
|
|
101
114
|
# dG2sum = np.trace(GdH @ GdH)
|
102
115
|
# print(f"dG2sum-Tr: {dG2sum}")
|
@@ -142,15 +155,33 @@ class MAEGreen(ExchangeNCL):
|
|
142
155
|
if with_eigen:
|
143
156
|
self.es2 = self.get_band_energy_vs_angles_from_eigen(thetas, phis)
|
144
157
|
|
145
|
-
for ie, e in enumerate(tqdm.tqdm(self.contour.path)):
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
158
|
+
# for ie, e in enumerate(tqdm.tqdm(self.contour.path)):
|
159
|
+
# dE_angle, dE_angle_atom, dE_angle_atom_orb = self.get_perturbed(
|
160
|
+
# e, thetas, phis
|
161
|
+
# )
|
162
|
+
# self.es += dE_angle * self.contour.weights[ie]
|
163
|
+
# self.es_atom += dE_angle_atom * self.contour.weights[ie]
|
164
|
+
# for key, value in dE_angle_atom_orb.items():
|
165
|
+
# self.es_atom_orb[key] += (
|
166
|
+
# dE_angle_atom_orb[key] * self.contour.weights[ie]
|
167
|
+
# )
|
168
|
+
|
169
|
+
# rewrite the for loop above to use p_map
|
170
|
+
def func(e):
|
171
|
+
return self.get_perturbed(e, thetas, phis)
|
172
|
+
|
173
|
+
if self.nproc > 1:
|
174
|
+
results = p_map(func, self.contour.path, num_cpus=self.nproc)
|
175
|
+
else:
|
176
|
+
npole = len(self.contour.path)
|
177
|
+
results = map(func, tqdm.tqdm(self.contour.path, total=npole))
|
178
|
+
for i, result in enumerate(results):
|
179
|
+
dE_angle, dE_angle_atom, dE_angle_atom_orb = result
|
180
|
+
self.es += dE_angle * self.contour.weights[i]
|
181
|
+
self.es_atom += dE_angle_atom * self.contour.weights[i]
|
151
182
|
for key, value in dE_angle_atom_orb.items():
|
152
183
|
self.es_atom_orb[key] += (
|
153
|
-
dE_angle_atom_orb[key] * self.contour.weights[
|
184
|
+
dE_angle_atom_orb[key] * self.contour.weights[i]
|
154
185
|
)
|
155
186
|
|
156
187
|
self.es = -np.imag(self.es) / (2 * np.pi)
|
@@ -158,7 +189,7 @@ class MAEGreen(ExchangeNCL):
|
|
158
189
|
for key, value in self.es_atom_orb.items():
|
159
190
|
self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
|
160
191
|
|
161
|
-
def output(self, output_path="TB2J_anisotropy", with_eigen=
|
192
|
+
def output(self, output_path="TB2J_anisotropy", with_eigen=True):
|
162
193
|
Path(output_path).mkdir(exist_ok=True)
|
163
194
|
fname = f"{output_path}/MAE.dat"
|
164
195
|
fname_orb = f"{output_path}/MAE_orb.dat"
|
@@ -242,6 +273,7 @@ def abacus_get_MAE(
|
|
242
273
|
magnetic_elements=None,
|
243
274
|
nel=None,
|
244
275
|
width=0.1,
|
276
|
+
with_eigen=False,
|
245
277
|
**kwargs,
|
246
278
|
):
|
247
279
|
"""Get MAE from Abacus with magnetic force theorem. Two calculations are needed. First we do an calculation with SOC but the soc_lambda is set to 0. Save the density. The next calculatin we start with the density from the first calculation and set the SOC prefactor to 1. With the information from the two calcualtions, we can get the band energy with magnetic moments in the direction, specified in two list, thetas, and phis."""
|
@@ -262,4 +294,4 @@ def abacus_get_MAE(
|
|
262
294
|
magnetic_elements=magnetic_elements,
|
263
295
|
**kwargs,
|
264
296
|
)
|
265
|
-
mae.run(output_path=output_path)
|
297
|
+
mae.run(output_path=output_path, with_eigen=with_eigen)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import numpy as np
|
2
2
|
from scipy.special import roots_legendre
|
3
|
+
|
3
4
|
from TB2J.utils import simpson_nonuniform_weight
|
4
5
|
|
5
6
|
|
@@ -15,6 +16,21 @@ class Contour:
|
|
15
16
|
self._weights = simpson_nonuniform_weight(self.path)
|
16
17
|
return self._weights
|
17
18
|
|
19
|
+
def integrate_func(self, func):
|
20
|
+
"""
|
21
|
+
integrate f along the path
|
22
|
+
"""
|
23
|
+
return np.dot(func(self.path), self.weights)
|
24
|
+
|
25
|
+
def integrate_values(self, values):
|
26
|
+
"""
|
27
|
+
integrate f along the path
|
28
|
+
"""
|
29
|
+
ret = 0
|
30
|
+
for i in range(len(values)):
|
31
|
+
ret += values[i] * self.weights[i]
|
32
|
+
return ret
|
33
|
+
|
18
34
|
def build_path_semicircle(self, npoints, endpoint=True):
|
19
35
|
R = (self.emax - self.emin) / 2.0
|
20
36
|
R0 = (self.emin + self.emax) / 2.0
|
@@ -10,29 +10,24 @@ from TB2J.exchange_params import ExchangeParams
|
|
10
10
|
from TB2J.external import p_map
|
11
11
|
from TB2J.green import TBGreen
|
12
12
|
from TB2J.io_exchange import SpinIO
|
13
|
+
from TB2J.mycfr import CFR
|
13
14
|
from TB2J.orbmap import map_orbs_matrix
|
14
15
|
from TB2J.pauli import pauli_block_all, pauli_block_sigma_norm
|
15
16
|
from TB2J.utils import (
|
16
17
|
kmesh_to_R,
|
17
|
-
simpson_nonuniform,
|
18
18
|
symbol_number,
|
19
|
-
trapezoidal_nonuniform,
|
20
19
|
)
|
21
20
|
|
22
21
|
|
23
22
|
class Exchange(ExchangeParams):
|
24
|
-
def __init__(
|
25
|
-
self,
|
26
|
-
tbmodels,
|
27
|
-
atoms,
|
28
|
-
**params: ExchangeParams,
|
29
|
-
):
|
23
|
+
def __init__(self, tbmodels, atoms, **params):
|
30
24
|
self.atoms = atoms
|
31
25
|
super().__init__(**params)
|
32
26
|
self._prepare_kmesh(self._kmesh)
|
33
27
|
self._prepare_Rlist()
|
34
28
|
self.set_tbmodels(tbmodels)
|
35
29
|
self._adjust_emin()
|
30
|
+
# self._prepare_elist(method="CFR")
|
36
31
|
self._prepare_elist(method="legendre")
|
37
32
|
self._prepare_basis()
|
38
33
|
self._prepare_orb_dict()
|
@@ -50,8 +45,9 @@ class Exchange(ExchangeParams):
|
|
50
45
|
os.makedirs(self.orbpath, exist_ok=True)
|
51
46
|
|
52
47
|
def _adjust_emin(self):
|
53
|
-
|
54
|
-
self.emin = -
|
48
|
+
self.emin = self.G.find_energy_ingap(rbound=self.efermi - 15.0) - self.efermi
|
49
|
+
# self.emin = self.G.find_energy_ingap(rbound=self.efermi - 15.0) - self.efermi
|
50
|
+
# self.emin = -42.0
|
55
51
|
print(f"A gap is found at {self.emin}, set emin to it.")
|
56
52
|
|
57
53
|
def set_tbmodels(self, tbmodels):
|
@@ -62,25 +58,28 @@ class Exchange(ExchangeParams):
|
|
62
58
|
# del self.G.tbmodel
|
63
59
|
pass
|
64
60
|
|
65
|
-
def _prepare_kmesh(self, kmesh):
|
61
|
+
def _prepare_kmesh(self, kmesh, ibz=False):
|
66
62
|
for k in kmesh:
|
67
63
|
self.kmesh = list(map(lambda x: x // 2 * 2 + 1, kmesh))
|
68
64
|
|
69
|
-
def _prepare_elist(self, method="
|
65
|
+
def _prepare_elist(self, method="CFR"):
|
70
66
|
"""
|
71
67
|
prepare list of energy for integration.
|
72
68
|
The path has three segments:
|
73
69
|
emin --1-> emin + 1j*height --2-> emax+1j*height --3-> emax
|
74
70
|
"""
|
75
|
-
self.contour = Contour(self.emin, self.emax)
|
76
71
|
# if method.lower() == "rectangle":
|
77
72
|
# self.contour.build_path_rectangle(
|
78
73
|
# height=self.height, nz1=self.nz1, nz2=self.nz2, nz3=self.nz3
|
79
74
|
# )
|
80
75
|
if method.lower() == "semicircle":
|
76
|
+
self.contour = Contour(self.emin, self.emax)
|
81
77
|
self.contour.build_path_semicircle(npoints=self.nz, endpoint=True)
|
82
78
|
elif method.lower() == "legendre":
|
79
|
+
self.contour = Contour(self.emin, self.emax)
|
83
80
|
self.contour.build_path_legendre(npoints=self.nz, endpoint=True)
|
81
|
+
elif method.lower() == "cfr":
|
82
|
+
self.contour = CFR(nz=self.nz, T=600)
|
84
83
|
else:
|
85
84
|
raise ValueError(f"The path cannot be of type {method}.")
|
86
85
|
|
@@ -119,6 +118,7 @@ class Exchange(ExchangeParams):
|
|
119
118
|
else:
|
120
119
|
try:
|
121
120
|
atom_sym, orb_sym = base[:2]
|
121
|
+
iatom = sdict[atom_sym]
|
122
122
|
except Exception:
|
123
123
|
iatom = base.iatom
|
124
124
|
atom_sym = base.iatom
|
@@ -150,7 +150,7 @@ class Exchange(ExchangeParams):
|
|
150
150
|
)
|
151
151
|
if not self._is_collinear:
|
152
152
|
for iatom, orb in self.orb_dict.items():
|
153
|
-
print(f"iatom: {iatom}, orb: {orb}")
|
153
|
+
# print(f"iatom: {iatom}, orb: {orb}")
|
154
154
|
nsorb = len(self.orb_dict[iatom])
|
155
155
|
if nsorb % 2 != 0 and False:
|
156
156
|
raise ValueError(
|
@@ -173,10 +173,9 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
|
|
173
173
|
self.mmats = {}
|
174
174
|
self.orbital_names = {}
|
175
175
|
self.norb_reduced = {}
|
176
|
-
print(f"self.backend_name: {self.backend_name}")
|
177
176
|
if self.backend_name.upper() in ["SIESTA", "ABACUS", "LCAOHAMILTONIAN"]:
|
178
|
-
print(f"magntic_elements: {self.magnetic_elements}")
|
179
|
-
print(f"include_orbs: {self.include_orbs}")
|
177
|
+
# print(f"magntic_elements: {self.magnetic_elements}")
|
178
|
+
# print(f"include_orbs: {self.include_orbs}")
|
180
179
|
syms = self.atoms.get_chemical_symbols()
|
181
180
|
for iatom, orbs in self.labels.items():
|
182
181
|
if (self.include_orbs is not None) and syms[iatom] in self.include_orbs:
|
@@ -186,7 +185,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
|
|
186
185
|
include_only=self.include_orbs[syms[iatom]],
|
187
186
|
)
|
188
187
|
else:
|
189
|
-
print(f"orbs: {orbs}")
|
188
|
+
# print(f"orbs: {orbs}")
|
190
189
|
mmat, reduced_orbs = map_orbs_matrix(
|
191
190
|
orbs, spinor=not (self._is_collinear), include_only=None
|
192
191
|
)
|
@@ -271,10 +270,10 @@ class ExchangeNCL(Exchange):
|
|
271
270
|
"""
|
272
271
|
self.tbmodel = tbmodels
|
273
272
|
self.backend_name = self.tbmodel.name
|
274
|
-
print(self.kmesh)
|
275
273
|
self.G = TBGreen(
|
276
274
|
tbmodel=self.tbmodel,
|
277
275
|
kmesh=self.kmesh,
|
276
|
+
ibz=self.ibz,
|
278
277
|
gamma=True,
|
279
278
|
efermi=self.efermi,
|
280
279
|
use_cache=self._use_cache,
|
@@ -567,20 +566,24 @@ class ExchangeNCL(Exchange):
|
|
567
566
|
AijRs: a list of AijR,
|
568
567
|
wherer AijR: array of ((nR, n, n, 4,4), dtype=complex)
|
569
568
|
"""
|
570
|
-
if method == "trapezoidal":
|
571
|
-
|
572
|
-
elif method == "simpson":
|
573
|
-
|
569
|
+
# if method == "trapezoidal":
|
570
|
+
# integrate = trapezoidal_nonuniform
|
571
|
+
# elif method == "simpson":
|
572
|
+
# integrate = simpson_nonuniform
|
573
|
+
#
|
574
574
|
|
575
575
|
# self.rho = integrate(self.contour.path, rhoRs)
|
576
576
|
for iR, R in enumerate(self.R_ijatom_dict):
|
577
577
|
for iatom, jatom in self.R_ijatom_dict[R]:
|
578
578
|
f = AijRs[(R, iatom, jatom)]
|
579
|
-
self.A_ijR[(R, iatom, jatom)] = integrate(self.contour.path, f)
|
579
|
+
# self.A_ijR[(R, iatom, jatom)] = integrate(self.contour.path, f)
|
580
|
+
self.A_ijR[(R, iatom, jatom)] = self.contour.integrate_values(f)
|
581
|
+
|
580
582
|
if self.orb_decomposition:
|
581
|
-
self.A_ijR_orb[(R, iatom, jatom)] = integrate(
|
582
|
-
|
583
|
-
)
|
583
|
+
# self.A_ijR_orb[(R, iatom, jatom)] = integrate(
|
584
|
+
# self.contour.path, AijRs_orb[(R, iatom, jatom)]
|
585
|
+
# )
|
586
|
+
self.contour.integrate_values(AijRs_orb[(R, iatom, jatom)])
|
584
587
|
|
585
588
|
def get_quantities_per_e(self, e):
|
586
589
|
Gk_all = self.G.get_Gk_all(e)
|
@@ -1,15 +1,18 @@
|
|
1
1
|
"""
|
2
2
|
Exchange from Green's function
|
3
3
|
"""
|
4
|
+
|
4
5
|
import os
|
5
6
|
from collections import defaultdict
|
7
|
+
|
6
8
|
import numpy as np
|
7
|
-
from TB2J.green import TBGreen
|
8
|
-
from TB2J.io_exchange import SpinIO
|
9
9
|
from tqdm import tqdm
|
10
|
+
|
10
11
|
from TB2J.external import p_map
|
12
|
+
from TB2J.green import TBGreen
|
13
|
+
from TB2J.io_exchange import SpinIO
|
14
|
+
|
11
15
|
from .exchange import ExchangeCL
|
12
|
-
from .utils import simpson_nonuniform, trapezoidal_nonuniform
|
13
16
|
|
14
17
|
|
15
18
|
class ExchangeCL2(ExchangeCL):
|
@@ -221,17 +224,23 @@ class ExchangeCL2(ExchangeCL):
|
|
221
224
|
# shutil.rmtree(path)
|
222
225
|
|
223
226
|
def integrate(self, method="simpson"):
|
224
|
-
if method == "trapezoidal":
|
225
|
-
|
226
|
-
elif method == "simpson":
|
227
|
-
|
227
|
+
# if method == "trapezoidal":
|
228
|
+
# integrate = trapezoidal_nonuniform
|
229
|
+
# elif method == "simpson":
|
230
|
+
# integrate = simpson_nonuniform
|
228
231
|
for R, ijpairs in self.R_ijatom_dict.items():
|
229
232
|
for iatom, jatom in ijpairs:
|
230
|
-
self.Jorb[(R, iatom, jatom)] = integrate(
|
231
|
-
|
233
|
+
# self.Jorb[(R, iatom, jatom)] = integrate(
|
234
|
+
# self.contour.path, self.Jorb_list[(R, iatom, jatom)]
|
235
|
+
# )
|
236
|
+
# self.JJ[(R, iatom, jatom)] = integrate(
|
237
|
+
# self.contour.path, self.JJ_list[(R, iatom, jatom)]
|
238
|
+
# )
|
239
|
+
self.Jorb[(R, iatom, jatom)] = self.contour.integrate_values(
|
240
|
+
self.Jorb_list[(R, iatom, jatom)]
|
232
241
|
)
|
233
|
-
self.JJ[(R, iatom, jatom)] =
|
234
|
-
self.
|
242
|
+
self.JJ[(R, iatom, jatom)] = self.contour.integrate_values(
|
243
|
+
self.JJ_list[(R, iatom, jatom)]
|
235
244
|
)
|
236
245
|
|
237
246
|
def get_quantities_per_e(self, e):
|
@@ -31,6 +31,7 @@ class ExchangeParams:
|
|
31
31
|
output_path: str = "TB2J_results"
|
32
32
|
mae_angles = None
|
33
33
|
orth = False
|
34
|
+
ibz = False
|
34
35
|
|
35
36
|
def __init__(
|
36
37
|
self,
|
@@ -53,6 +54,7 @@ class ExchangeParams:
|
|
53
54
|
exclude_orbs=[],
|
54
55
|
mae_angles=None,
|
55
56
|
orth=False,
|
57
|
+
ibz=False,
|
56
58
|
):
|
57
59
|
self.efermi = efermi
|
58
60
|
self.basis = basis
|
@@ -76,6 +78,7 @@ class ExchangeParams:
|
|
76
78
|
self.output_path = output_path
|
77
79
|
self.mae_angles = mae_angles
|
78
80
|
self.orth = orth
|
81
|
+
self.ibz = ibz
|
79
82
|
|
80
83
|
def set_params(self, **kwargs):
|
81
84
|
for key, val in kwargs.items():
|
@@ -92,8 +95,6 @@ class ExchangeParams:
|
|
92
95
|
include_orbs = {}
|
93
96
|
if isinstance(magnetic_elements, str):
|
94
97
|
magnetic_elements = [magnetic_elements]
|
95
|
-
print(f"magnetic_elements: {magnetic_elements}")
|
96
|
-
print(f"include_orbs: {include_orbs}")
|
97
98
|
for element in magnetic_elements:
|
98
99
|
if "_" in element:
|
99
100
|
elem = element.split("_")[0]
|
@@ -102,8 +103,6 @@ class ExchangeParams:
|
|
102
103
|
else:
|
103
104
|
include_orbs[element] = None
|
104
105
|
|
105
|
-
print(f"magnetic_elements: {magnetic_elements}")
|
106
|
-
print(f"include_orbs: {include_orbs}")
|
107
106
|
magnetic_elements = list(include_orbs.keys())
|
108
107
|
return magnetic_elements, include_orbs
|
109
108
|
|
@@ -116,6 +115,14 @@ def add_exchange_args_to_parser(parser: argparse.ArgumentParser):
|
|
116
115
|
type=str,
|
117
116
|
nargs="*",
|
118
117
|
)
|
118
|
+
|
119
|
+
parser.add_argument(
|
120
|
+
"--spinor",
|
121
|
+
help="whether the Wannier functions are spinor. Default: False",
|
122
|
+
action="store_true",
|
123
|
+
default=False,
|
124
|
+
)
|
125
|
+
|
119
126
|
parser.add_argument(
|
120
127
|
"--rcut",
|
121
128
|
help="cutoff of spin pair distance. The default is to calculate all commensurate R point to the k mesh.",
|
@@ -214,6 +221,14 @@ def add_exchange_args_to_parser(parser: argparse.ArgumentParser):
|
|
214
221
|
action="store_true",
|
215
222
|
default=False,
|
216
223
|
)
|
224
|
+
|
225
|
+
parser.add_argument(
|
226
|
+
"--ibz",
|
227
|
+
help=" use irreducible k-points in the Brillouin zone. (Note: only for computing total MAE).",
|
228
|
+
action="store_true",
|
229
|
+
default=False,
|
230
|
+
)
|
231
|
+
|
217
232
|
return parser
|
218
233
|
|
219
234
|
|
@@ -7,17 +7,28 @@ from collections import defaultdict
|
|
7
7
|
from shutil import rmtree
|
8
8
|
|
9
9
|
import numpy as np
|
10
|
-
from HamiltonIO.model.occupations import
|
10
|
+
from HamiltonIO.model.occupations import GaussOccupations
|
11
11
|
from HamiltonIO.model.occupations import myfermi as fermi
|
12
12
|
from pathos.multiprocessing import ProcessPool
|
13
13
|
|
14
|
-
from TB2J.kpoints import monkhorst_pack
|
14
|
+
from TB2J.kpoints import ir_kpts, monkhorst_pack
|
15
15
|
|
16
16
|
# from TB2J.mathutils.fermi import fermi
|
17
17
|
|
18
18
|
MAX_EXP_ARGUMENT = np.log(sys.float_info.max)
|
19
19
|
|
20
20
|
|
21
|
+
def eigen_to_G2(H, S, efermi, energy):
|
22
|
+
"""calculate green's function from eigenvalue/eigenvector for energy(e-ef): G(e-ef).
|
23
|
+
:param H: Hamiltonian matrix in eigenbasis
|
24
|
+
:param S: Overlap matrix in eigenbasis
|
25
|
+
:param efermi: fermi energy
|
26
|
+
:param energy: energy level e - efermi
|
27
|
+
"""
|
28
|
+
# G = ((E+Ef) S - H)^-1
|
29
|
+
return np.linalg.inv((energy + efermi) * S - H)
|
30
|
+
|
31
|
+
|
21
32
|
def eigen_to_G(evals, evecs, efermi, energy):
|
22
33
|
"""calculate green's function from eigenvalue/eigenvector for energy(e-ef): G(e-ef).
|
23
34
|
:param evals: eigen values
|
@@ -40,7 +51,7 @@ def eigen_to_G(evals, evecs, efermi, energy):
|
|
40
51
|
)
|
41
52
|
|
42
53
|
|
43
|
-
def find_energy_ingap(evals, rbound, gap=
|
54
|
+
def find_energy_ingap(evals, rbound, gap=2.0):
|
44
55
|
"""
|
45
56
|
find a energy inside a gap below rbound (right bound),
|
46
57
|
return the energy gap top - 0.5.
|
@@ -59,9 +70,11 @@ class TBGreen:
|
|
59
70
|
self,
|
60
71
|
tbmodel,
|
61
72
|
kmesh=None, # [ikpt, 3]
|
73
|
+
ibz=False, # if True, will interpolate the Green's function at Ir-kpoints
|
62
74
|
efermi=None, # efermi
|
63
75
|
gamma=False,
|
64
76
|
kpts=None,
|
77
|
+
kweights=None,
|
65
78
|
k_sym=False,
|
66
79
|
use_cache=False,
|
67
80
|
cache_path=None,
|
@@ -81,20 +94,64 @@ class TBGreen:
|
|
81
94
|
self.cache_path = cache_path
|
82
95
|
if use_cache:
|
83
96
|
self._prepare_cache()
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
97
|
+
self.prepare_kpts(
|
98
|
+
kmesh=kmesh,
|
99
|
+
ibz=ibz,
|
100
|
+
gamma=gamma,
|
101
|
+
kpts=kpts,
|
102
|
+
kweights=kweights,
|
103
|
+
tbmodel=tbmodel,
|
104
|
+
)
|
105
|
+
|
92
106
|
self.norb = tbmodel.norb
|
93
107
|
self.nbasis = tbmodel.nbasis
|
94
108
|
self.k_sym = k_sym
|
95
109
|
self.nproc = nproc
|
96
110
|
self._prepare_eigen()
|
97
111
|
|
112
|
+
def prepare_kpts(
|
113
|
+
self, kmesh=None, gamma=True, ibz=False, kpts=None, kweights=None, tbmodel=None
|
114
|
+
):
|
115
|
+
"""
|
116
|
+
Prepare the k-points for the calculation.
|
117
|
+
|
118
|
+
Parameters:
|
119
|
+
- kmesh (tuple): The k-mesh used to generate k-points.
|
120
|
+
- gamma (bool): Whether to include the gamma point in the k-points.
|
121
|
+
- ibz (bool): Whether to use the irreducible Brillouin zone.
|
122
|
+
- kpts (list): List of user-defined k-points.
|
123
|
+
- kweights (list): List of weights for each k-point.
|
124
|
+
|
125
|
+
Returns:
|
126
|
+
None
|
127
|
+
"""
|
128
|
+
if kpts is not None:
|
129
|
+
self.kpts = kpts
|
130
|
+
self.nkpts = len(self.kpts)
|
131
|
+
self.kweights = kweights
|
132
|
+
elif kmesh is not None:
|
133
|
+
if ibz:
|
134
|
+
self.kpts, self.kweights = ir_kpts(
|
135
|
+
atoms=tbmodel.atoms,
|
136
|
+
mp_grid=kmesh,
|
137
|
+
ir=True,
|
138
|
+
is_time_reversal=False,
|
139
|
+
)
|
140
|
+
self.nkpts = len(self.kpts)
|
141
|
+
print(f"Using IBZ of kmesh of {kmesh}")
|
142
|
+
print(f"Number of kpts: {self.nkpts}")
|
143
|
+
for kpt, weight in zip(self.kpts, self.kweights):
|
144
|
+
# format the kpt and weight, use 5 digits
|
145
|
+
print(f"{kpt[0]:8.5f} {kpt[1]:8.5f} {kpt[2]:8.5f} {weight:8.5f}")
|
146
|
+
else:
|
147
|
+
self.kpts = monkhorst_pack(kmesh, gamma_center=gamma)
|
148
|
+
self.nkpts = len(self.kpts)
|
149
|
+
self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
|
150
|
+
else:
|
151
|
+
self.kpts = tbmodel.get_kpts()
|
152
|
+
self.nkpts = len(self.kpts)
|
153
|
+
self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
|
154
|
+
|
98
155
|
def _reduce_eigens(self, evals, evecs, emin, emax):
|
99
156
|
ts = np.logical_and(evals >= emin, evals < emax)
|
100
157
|
ts = np.any(ts, axis=0)
|
@@ -106,7 +163,7 @@ class TBGreen:
|
|
106
163
|
istart, iend = ts[0], ts[-1] + 1
|
107
164
|
return evals[:, istart:iend], evecs[:, :, istart:iend]
|
108
165
|
|
109
|
-
def find_energy_ingap(self, rbound, gap=
|
166
|
+
def find_energy_ingap(self, rbound, gap=2.0):
|
110
167
|
return find_energy_ingap(self.evals, rbound, gap)
|
111
168
|
|
112
169
|
def _prepare_cache(self):
|
@@ -165,7 +222,14 @@ class TBGreen:
|
|
165
222
|
if self.efermi is None:
|
166
223
|
print("Calculating Fermi energy from eigenvalues")
|
167
224
|
print(f"Number of electrons: {self.tbmodel.nel} ")
|
168
|
-
|
225
|
+
|
226
|
+
# occ = Occupations(
|
227
|
+
# nel=self.tbmodel.nel, width=0.1, wk=self.kweights, nspin=2
|
228
|
+
# )
|
229
|
+
# self.efermi = occ.efermi(copy.deepcopy(self.evals))
|
230
|
+
# print(f"Fermi energy found: {self.efermi}")
|
231
|
+
|
232
|
+
occ = GaussOccupations(
|
169
233
|
nel=self.tbmodel.nel, width=0.1, wk=self.kweights, nspin=2
|
170
234
|
)
|
171
235
|
self.efermi = occ.efermi(copy.deepcopy(self.evals))
|
@@ -360,7 +424,6 @@ class TBGreen:
|
|
360
424
|
for iR, R in enumerate(Rpts):
|
361
425
|
phase = np.exp(self.k2Rfactor * np.dot(R, kpt))
|
362
426
|
GR[R] += Gkw * (phase * self.kweights[ik])
|
363
|
-
|
364
427
|
dHRdx = dHdx.get_hamR(R)
|
365
428
|
dGRdx[R] += Gkw @ dHRdx @ Gk
|
366
429
|
# dGRdx[R] += Gk.dot(dHRdx).dot(Gkp)
|
@@ -74,6 +74,7 @@ def gen_exchange_siesta(fdf_fname, read_H_soc=False, **kwargs):
|
|
74
74
|
output_path="TB2J_results",
|
75
75
|
orb_decomposition=False,
|
76
76
|
orth=False,
|
77
|
+
ibz=False,
|
77
78
|
description="",
|
78
79
|
)
|
79
80
|
exargs.update(kwargs)
|
@@ -162,7 +163,7 @@ Warning: The DMI component parallel to the spin orientation, the Jani which has
|
|
162
163
|
# thetas = [0, np.pi / 2, np.pi, 3 * np.pi / 2]
|
163
164
|
# phis = [0, 0, 0, 0]
|
164
165
|
# MAE.set_angles(thetas=thetas, phis=phis)
|
165
|
-
MAE.run(output_path=f"{output_path}_anisotropy")
|
166
|
+
MAE.run(output_path=f"{output_path}_anisotropy", with_eigen=True)
|
166
167
|
print(
|
167
168
|
f"MAE calculation finished. The results are in {output_path} directory."
|
168
169
|
)
|