TB2J 0.9.9rc3__tar.gz → 0.9.9rc5__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.9rc3 → tb2j-0.9.9rc5}/PKG-INFO +1 -1
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/MAE.py +3 -3
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/MAEGreen.py +6 -4
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange.py +9 -14
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange_params.py +11 -4
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/green.py +63 -14
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/siesta_interface.py +1 -0
- tb2j-0.9.9rc5/TB2J/kpoints.py +87 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/symmetrize_J.py +34 -9
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/versioninfo.py +2 -1
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/PKG-INFO +1 -1
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/setup.py +1 -1
- tb2j-0.9.9rc3/TB2J/kpoints.py +0 -16
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/LICENSE +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/README.md +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Jdownfolder.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Jtensor.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Oiju.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Oiju_epc.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/anisotropy.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/basis.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/citation.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/contour.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/density_matrix.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/epc.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchangeCL2.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange_pert.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange_qspace.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/external/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/external/p_tqdm.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/gpaw_wrapper.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/greentest.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/abacus_api.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/abacus_wrapper.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/gen_exchange_abacus.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/orbital_api.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/stru_api.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/test_density_matrix.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/test_read_HRSR.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/test_read_stru.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/gpaw_interface.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/lawaf_interface.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/manager.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/wannier90_interface.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_exchange.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_multibinit.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_tomsasd.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_txt.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_uppasd.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_vampire.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_merge.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/fermi.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/kR_convert.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/lowdin.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/rotate_spin.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/myTB.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/orbmap.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/pauli.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/pert.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/plot.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/rotate_atoms.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/rotate_siestaDM.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/sisl_wrapper.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/base_parser.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/constants.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/hamiltonian.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/hamiltonian_terms.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/plot.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/qsolver.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/spin_api.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/spin_xml.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/supercell.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/tensor_rotate.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/utest.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/utils.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/wannier/__init__.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/wannier/w90_parser.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/wannier/w90_tb_parser.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/SOURCES.txt +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/dependency_links.txt +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/entry_points.txt +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/requires.txt +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/top_level.txt +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_downfold.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_eigen.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_magnon.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_magnon_dos.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_merge.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_rotate.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_rotateDM.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/abacus2J.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/siesta2J.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/wann2J.py +0 -0
- {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/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,7 +3,7 @@ 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
|
@@ -16,7 +16,7 @@ from TB2J.mathutils.rotate_spin import (
|
|
16
16
|
|
17
17
|
|
18
18
|
def get_occupation(evals, kweights, nel, width=0.1):
|
19
|
-
occ =
|
19
|
+
occ = GaussOccupations(nel=nel, width=width, wk=kweights, nspin=2)
|
20
20
|
return occ.occupy(evals)
|
21
21
|
|
22
22
|
|
@@ -97,6 +97,7 @@ class MAEGreen(ExchangeNCL):
|
|
97
97
|
dG2 = GdH * GdH.T
|
98
98
|
dG2sum = np.sum(dG2)
|
99
99
|
# print(f"dG2sum-sum: {dG2sum}")
|
100
|
+
dG2sum = np.sum(dG2diag)
|
100
101
|
|
101
102
|
# dG2sum = np.trace(GdH @ GdH)
|
102
103
|
# print(f"dG2sum-Tr: {dG2sum}")
|
@@ -158,7 +159,7 @@ class MAEGreen(ExchangeNCL):
|
|
158
159
|
for key, value in self.es_atom_orb.items():
|
159
160
|
self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
|
160
161
|
|
161
|
-
def output(self, output_path="TB2J_anisotropy", with_eigen=
|
162
|
+
def output(self, output_path="TB2J_anisotropy", with_eigen=True):
|
162
163
|
Path(output_path).mkdir(exist_ok=True)
|
163
164
|
fname = f"{output_path}/MAE.dat"
|
164
165
|
fname_orb = f"{output_path}/MAE_orb.dat"
|
@@ -242,6 +243,7 @@ def abacus_get_MAE(
|
|
242
243
|
magnetic_elements=None,
|
243
244
|
nel=None,
|
244
245
|
width=0.1,
|
246
|
+
with_eigen=False,
|
245
247
|
**kwargs,
|
246
248
|
):
|
247
249
|
"""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 +264,4 @@ def abacus_get_MAE(
|
|
262
264
|
magnetic_elements=magnetic_elements,
|
263
265
|
**kwargs,
|
264
266
|
)
|
265
|
-
mae.run(output_path=output_path)
|
267
|
+
mae.run(output_path=output_path, with_eigen=with_eigen)
|
@@ -21,12 +21,7 @@ from TB2J.utils import (
|
|
21
21
|
|
22
22
|
|
23
23
|
class Exchange(ExchangeParams):
|
24
|
-
def __init__(
|
25
|
-
self,
|
26
|
-
tbmodels,
|
27
|
-
atoms,
|
28
|
-
**params: ExchangeParams,
|
29
|
-
):
|
24
|
+
def __init__(self, tbmodels, atoms, **params):
|
30
25
|
self.atoms = atoms
|
31
26
|
super().__init__(**params)
|
32
27
|
self._prepare_kmesh(self._kmesh)
|
@@ -50,8 +45,8 @@ class Exchange(ExchangeParams):
|
|
50
45
|
os.makedirs(self.orbpath, exist_ok=True)
|
51
46
|
|
52
47
|
def _adjust_emin(self):
|
53
|
-
|
54
|
-
self.emin = -22.0
|
48
|
+
self.emin = self.G.find_energy_ingap(rbound=self.efermi - 10.0) - self.efermi
|
49
|
+
# self.emin = -22.0
|
55
50
|
print(f"A gap is found at {self.emin}, set emin to it.")
|
56
51
|
|
57
52
|
def set_tbmodels(self, tbmodels):
|
@@ -62,7 +57,7 @@ class Exchange(ExchangeParams):
|
|
62
57
|
# del self.G.tbmodel
|
63
58
|
pass
|
64
59
|
|
65
|
-
def _prepare_kmesh(self, kmesh):
|
60
|
+
def _prepare_kmesh(self, kmesh, ibz=False):
|
66
61
|
for k in kmesh:
|
67
62
|
self.kmesh = list(map(lambda x: x // 2 * 2 + 1, kmesh))
|
68
63
|
|
@@ -150,7 +145,7 @@ class Exchange(ExchangeParams):
|
|
150
145
|
)
|
151
146
|
if not self._is_collinear:
|
152
147
|
for iatom, orb in self.orb_dict.items():
|
153
|
-
print(f"iatom: {iatom}, orb: {orb}")
|
148
|
+
# print(f"iatom: {iatom}, orb: {orb}")
|
154
149
|
nsorb = len(self.orb_dict[iatom])
|
155
150
|
if nsorb % 2 != 0 and False:
|
156
151
|
raise ValueError(
|
@@ -175,8 +170,8 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
|
|
175
170
|
self.norb_reduced = {}
|
176
171
|
print(f"self.backend_name: {self.backend_name}")
|
177
172
|
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}")
|
173
|
+
# print(f"magntic_elements: {self.magnetic_elements}")
|
174
|
+
# print(f"include_orbs: {self.include_orbs}")
|
180
175
|
syms = self.atoms.get_chemical_symbols()
|
181
176
|
for iatom, orbs in self.labels.items():
|
182
177
|
if (self.include_orbs is not None) and syms[iatom] in self.include_orbs:
|
@@ -186,7 +181,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
|
|
186
181
|
include_only=self.include_orbs[syms[iatom]],
|
187
182
|
)
|
188
183
|
else:
|
189
|
-
print(f"orbs: {orbs}")
|
184
|
+
# print(f"orbs: {orbs}")
|
190
185
|
mmat, reduced_orbs = map_orbs_matrix(
|
191
186
|
orbs, spinor=not (self._is_collinear), include_only=None
|
192
187
|
)
|
@@ -271,10 +266,10 @@ class ExchangeNCL(Exchange):
|
|
271
266
|
"""
|
272
267
|
self.tbmodel = tbmodels
|
273
268
|
self.backend_name = self.tbmodel.name
|
274
|
-
print(self.kmesh)
|
275
269
|
self.G = TBGreen(
|
276
270
|
tbmodel=self.tbmodel,
|
277
271
|
kmesh=self.kmesh,
|
272
|
+
ibz=self.ibz,
|
278
273
|
gamma=True,
|
279
274
|
efermi=self.efermi,
|
280
275
|
use_cache=self._use_cache,
|
@@ -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
|
|
@@ -214,6 +213,14 @@ def add_exchange_args_to_parser(parser: argparse.ArgumentParser):
|
|
214
213
|
action="store_true",
|
215
214
|
default=False,
|
216
215
|
)
|
216
|
+
|
217
|
+
parser.add_argument(
|
218
|
+
"--ibz",
|
219
|
+
help=" use irreducible k-points in the Brillouin zone. (Note: only for computing total MAE).",
|
220
|
+
action="store_true",
|
221
|
+
default=False,
|
222
|
+
)
|
223
|
+
|
217
224
|
return parser
|
218
225
|
|
219
226
|
|
@@ -7,11 +7,11 @@ 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
|
|
@@ -40,7 +40,7 @@ def eigen_to_G(evals, evecs, efermi, energy):
|
|
40
40
|
)
|
41
41
|
|
42
42
|
|
43
|
-
def find_energy_ingap(evals, rbound, gap=
|
43
|
+
def find_energy_ingap(evals, rbound, gap=2.0):
|
44
44
|
"""
|
45
45
|
find a energy inside a gap below rbound (right bound),
|
46
46
|
return the energy gap top - 0.5.
|
@@ -59,9 +59,11 @@ class TBGreen:
|
|
59
59
|
self,
|
60
60
|
tbmodel,
|
61
61
|
kmesh=None, # [ikpt, 3]
|
62
|
+
ibz=False, # if True, will interpolate the Green's function at Ir-kpoints
|
62
63
|
efermi=None, # efermi
|
63
64
|
gamma=False,
|
64
65
|
kpts=None,
|
66
|
+
kweights=None,
|
65
67
|
k_sym=False,
|
66
68
|
use_cache=False,
|
67
69
|
cache_path=None,
|
@@ -81,20 +83,61 @@ class TBGreen:
|
|
81
83
|
self.cache_path = cache_path
|
82
84
|
if use_cache:
|
83
85
|
self._prepare_cache()
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
86
|
+
self.prepare_kpts(
|
87
|
+
kmesh=kmesh,
|
88
|
+
ibz=ibz,
|
89
|
+
gamma=gamma,
|
90
|
+
kpts=kpts,
|
91
|
+
kweights=kweights,
|
92
|
+
tbmodel=tbmodel,
|
93
|
+
)
|
94
|
+
|
92
95
|
self.norb = tbmodel.norb
|
93
96
|
self.nbasis = tbmodel.nbasis
|
94
97
|
self.k_sym = k_sym
|
95
98
|
self.nproc = nproc
|
96
99
|
self._prepare_eigen()
|
97
100
|
|
101
|
+
def prepare_kpts(
|
102
|
+
self, kmesh=None, gamma=True, ibz=False, kpts=None, kweights=None, tbmodel=None
|
103
|
+
):
|
104
|
+
"""
|
105
|
+
Prepare the k-points for the calculation.
|
106
|
+
|
107
|
+
Parameters:
|
108
|
+
- kmesh (tuple): The k-mesh used to generate k-points.
|
109
|
+
- gamma (bool): Whether to include the gamma point in the k-points.
|
110
|
+
- ibz (bool): Whether to use the irreducible Brillouin zone.
|
111
|
+
- kpts (list): List of user-defined k-points.
|
112
|
+
- kweights (list): List of weights for each k-point.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
None
|
116
|
+
"""
|
117
|
+
if kpts is not None:
|
118
|
+
self.kpts = kpts
|
119
|
+
self.nkpts = len(self.kpts)
|
120
|
+
self.kweights = kweights
|
121
|
+
elif kmesh is not None:
|
122
|
+
if ibz:
|
123
|
+
self.kpts, self.kweights = ir_kpts(
|
124
|
+
atoms=tbmodel.atoms, mp_grid=kmesh, ir=True, is_time_reversal=False
|
125
|
+
)
|
126
|
+
self.nkpts = len(self.kpts)
|
127
|
+
print(f"Using IBZ of kmesh of {kmesh}")
|
128
|
+
print(f"Number of kpts: {self.nkpts}")
|
129
|
+
for kpt, weight in zip(self.kpts, self.kweights):
|
130
|
+
# format the kpt and weight, use 5 digits
|
131
|
+
print(f"{kpt[0]:8.5f} {kpt[1]:8.5f} {kpt[2]:8.5f} {weight:8.5f}")
|
132
|
+
else:
|
133
|
+
self.kpts = monkhorst_pack(kmesh, gamma_center=gamma)
|
134
|
+
self.nkpts = len(self.kpts)
|
135
|
+
self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
|
136
|
+
else:
|
137
|
+
self.kpts = tbmodel.get_kpts()
|
138
|
+
self.nkpts = len(self.kpts)
|
139
|
+
self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
|
140
|
+
|
98
141
|
def _reduce_eigens(self, evals, evecs, emin, emax):
|
99
142
|
ts = np.logical_and(evals >= emin, evals < emax)
|
100
143
|
ts = np.any(ts, axis=0)
|
@@ -106,7 +149,7 @@ class TBGreen:
|
|
106
149
|
istart, iend = ts[0], ts[-1] + 1
|
107
150
|
return evals[:, istart:iend], evecs[:, :, istart:iend]
|
108
151
|
|
109
|
-
def find_energy_ingap(self, rbound, gap=
|
152
|
+
def find_energy_ingap(self, rbound, gap=2.0):
|
110
153
|
return find_energy_ingap(self.evals, rbound, gap)
|
111
154
|
|
112
155
|
def _prepare_cache(self):
|
@@ -165,7 +208,14 @@ class TBGreen:
|
|
165
208
|
if self.efermi is None:
|
166
209
|
print("Calculating Fermi energy from eigenvalues")
|
167
210
|
print(f"Number of electrons: {self.tbmodel.nel} ")
|
168
|
-
|
211
|
+
|
212
|
+
# occ = Occupations(
|
213
|
+
# nel=self.tbmodel.nel, width=0.1, wk=self.kweights, nspin=2
|
214
|
+
# )
|
215
|
+
# self.efermi = occ.efermi(copy.deepcopy(self.evals))
|
216
|
+
# print(f"Fermi energy found: {self.efermi}")
|
217
|
+
|
218
|
+
occ = GaussOccupations(
|
169
219
|
nel=self.tbmodel.nel, width=0.1, wk=self.kweights, nspin=2
|
170
220
|
)
|
171
221
|
self.efermi = occ.efermi(copy.deepcopy(self.evals))
|
@@ -360,7 +410,6 @@ class TBGreen:
|
|
360
410
|
for iR, R in enumerate(Rpts):
|
361
411
|
phase = np.exp(self.k2Rfactor * np.dot(R, kpt))
|
362
412
|
GR[R] += Gkw * (phase * self.kweights[ik])
|
363
|
-
|
364
413
|
dHRdx = dHdx.get_hamR(R)
|
365
414
|
dGRdx[R] += Gkw @ dHRdx @ Gk
|
366
415
|
# dGRdx[R] += Gk.dot(dHRdx).dot(Gkp)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
from collections import Counter
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import spglib
|
5
|
+
|
6
|
+
|
7
|
+
def monkhorst_pack(size, gamma_center=False):
|
8
|
+
"""Construct a uniform sampling of k-space of given size.
|
9
|
+
Modified from ase.dft.kpoints with gamma_center option added"""
|
10
|
+
if np.less_equal(size, 0).any():
|
11
|
+
raise ValueError("Illegal size: %s" % list(size))
|
12
|
+
kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3))
|
13
|
+
asize = np.array(size)
|
14
|
+
shift = 0.5 * ((asize + 1) % 2) / asize
|
15
|
+
mkpts = (kpts + 0.5) / size - 0.5
|
16
|
+
if gamma_center:
|
17
|
+
mkpts += shift
|
18
|
+
return mkpts
|
19
|
+
|
20
|
+
|
21
|
+
def get_ir_kpts(atoms, mesh):
|
22
|
+
"""
|
23
|
+
Gamma-centered IR kpoints. mesh : [nk1,nk2,nk3].
|
24
|
+
"""
|
25
|
+
lattice = atoms.get_cell()
|
26
|
+
positions = atoms.get_scaled_positions()
|
27
|
+
numbers = atoms.get_atomic_numbers()
|
28
|
+
|
29
|
+
cell = (lattice, positions, numbers)
|
30
|
+
mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
|
31
|
+
return grid[np.unique(mapping)] / np.array(mesh, dtype=float)
|
32
|
+
|
33
|
+
|
34
|
+
def ir_kpts(
|
35
|
+
atoms, mp_grid, is_shift=[0, 0, 0], verbose=True, ir=True, is_time_reversal=False
|
36
|
+
):
|
37
|
+
"""
|
38
|
+
generate kpoints for structure
|
39
|
+
Parameters:
|
40
|
+
------------------
|
41
|
+
atoms: ase.Atoms
|
42
|
+
structure
|
43
|
+
mp_grid: [nk1,nk2,nk3]
|
44
|
+
is_shift: shift of k points. default is Gamma centered.
|
45
|
+
ir: bool
|
46
|
+
Irreducible or not.
|
47
|
+
"""
|
48
|
+
cell = (atoms.get_cell(), atoms.get_scaled_positions(), atoms.get_atomic_numbers())
|
49
|
+
# print(spglib.get_spacegroup(cell, symprec=1e-5))
|
50
|
+
mesh = mp_grid
|
51
|
+
# Gamma centre mesh
|
52
|
+
mapping, grid = spglib.get_ir_reciprocal_mesh(
|
53
|
+
mesh, cell, is_shift=is_shift, is_time_reversal=is_time_reversal, symprec=1e-4
|
54
|
+
)
|
55
|
+
if not ir:
|
56
|
+
return (np.array(grid).astype(float) + np.asarray(is_shift) / 2.0) / mesh, [
|
57
|
+
1.0 / len(mapping)
|
58
|
+
] * len(mapping)
|
59
|
+
# All k-points and mapping to ir-grid points
|
60
|
+
# for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
|
61
|
+
# print("%3d ->%3d %s" % (i, ir_gp_id, gp.astype(float) / mesh))
|
62
|
+
cnt = Counter(mapping)
|
63
|
+
ids = list(cnt.keys())
|
64
|
+
weight = list(cnt.values())
|
65
|
+
weight = np.array(weight) * 1.0 / sum(weight)
|
66
|
+
ird_kpts = [
|
67
|
+
(grid[id].astype(float) + np.asarray(is_shift) / 2.0) / mesh for id in ids
|
68
|
+
]
|
69
|
+
|
70
|
+
# Irreducible k-points
|
71
|
+
# print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
|
72
|
+
# print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))
|
73
|
+
return ird_kpts, weight
|
74
|
+
|
75
|
+
|
76
|
+
def test_ir_kpts():
|
77
|
+
from ase.build import bulk
|
78
|
+
|
79
|
+
atoms = bulk("Si")
|
80
|
+
mesh = [14, 14, 14]
|
81
|
+
kpts = get_ir_kpts(atoms, mesh)
|
82
|
+
print(kpts)
|
83
|
+
print(len(kpts))
|
84
|
+
|
85
|
+
|
86
|
+
if __name__ == "__main__":
|
87
|
+
test_ir_kpts()
|
@@ -1,12 +1,15 @@
|
|
1
|
-
|
2
|
-
import numpy as np
|
1
|
+
import copy
|
3
2
|
from pathlib import Path
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from sympair import SymmetryPairFinder
|
6
|
+
|
7
|
+
from TB2J.io_exchange import SpinIO
|
4
8
|
from TB2J.versioninfo import print_license
|
5
|
-
import copy
|
6
9
|
|
7
10
|
|
8
11
|
class TB2JSymmetrizer:
|
9
|
-
def __init__(self, exc, symprec=1e-8, verbose=True):
|
12
|
+
def __init__(self, exc, symprec=1e-8, verbose=True, Jonly=False):
|
10
13
|
# list of pairs with the index of atoms
|
11
14
|
ijRs = exc.ijR_list_index_atom()
|
12
15
|
finder = SymmetryPairFinder(atoms=exc.atoms, pairs=ijRs, symprec=symprec)
|
@@ -28,10 +31,11 @@ class TB2JSymmetrizer:
|
|
28
31
|
print(f"Finding crystal symmetry with symprec of {symprec} Angstrom.")
|
29
32
|
print("Symmetry found:")
|
30
33
|
print(finder.spacegroup)
|
31
|
-
print(
|
34
|
+
print("-" * 30)
|
32
35
|
self.pgdict = finder.get_symmetry_pair_group_dict()
|
33
36
|
self.exc = exc
|
34
37
|
self.new_exc = copy.deepcopy(exc)
|
38
|
+
self.Jonly = Jonly
|
35
39
|
|
36
40
|
def print_license(self):
|
37
41
|
print_license()
|
@@ -41,8 +45,8 @@ class TB2JSymmetrizer:
|
|
41
45
|
Symmetrize the exchange parameters J.
|
42
46
|
"""
|
43
47
|
symJdict = {}
|
44
|
-
Jdict = self.exc.exchange_Jdict
|
45
|
-
ngroup = self.pgdict
|
48
|
+
# Jdict = self.exc.exchange_Jdict
|
49
|
+
# ngroup = self.pgdict
|
46
50
|
for pairgroup in self.pgdict.groups:
|
47
51
|
ijRs = pairgroup.get_all_ijR()
|
48
52
|
ijRs_spin = [self.exc.ijR_index_atom_to_spin(*ijR) for ijR in ijRs]
|
@@ -51,6 +55,14 @@ class TB2JSymmetrizer:
|
|
51
55
|
for i, j, R in ijRs_spin:
|
52
56
|
symJdict[(R, i, j)] = Javg
|
53
57
|
self.new_exc.exchange_Jdict = symJdict
|
58
|
+
if self.Jonly:
|
59
|
+
self.new_exc.has_dmi = False
|
60
|
+
self.new_exc.dmi_ddict = None
|
61
|
+
self.new_exc.has_bilinear = False
|
62
|
+
self.new_exc.Jani_dict = None
|
63
|
+
self.has_uniaxial_anisotropy = False
|
64
|
+
self.k1 = None
|
65
|
+
self.k1dir = None
|
54
66
|
|
55
67
|
def output(self, path="TB2J_symmetrized"):
|
56
68
|
if path is None:
|
@@ -72,6 +84,7 @@ def symmetrize_J(
|
|
72
84
|
fname="TB2J.pickle",
|
73
85
|
symprec=1e-5,
|
74
86
|
output_path="TB2J_symmetrized",
|
87
|
+
Jonly=False,
|
75
88
|
):
|
76
89
|
"""
|
77
90
|
symmetrize the exchange parameters
|
@@ -80,7 +93,7 @@ def symmetrize_J(
|
|
80
93
|
"""
|
81
94
|
if exc is None:
|
82
95
|
exc = SpinIO.load_pickle(path=path, fname=fname)
|
83
|
-
symmetrizer = TB2JSymmetrizer(exc, symprec=symprec)
|
96
|
+
symmetrizer = TB2JSymmetrizer(exc, symprec=symprec, Jonly=Jonly)
|
84
97
|
symmetrizer.run(path=output_path)
|
85
98
|
|
86
99
|
|
@@ -109,11 +122,23 @@ def symmetrize_J_cli():
|
|
109
122
|
default=1e-5,
|
110
123
|
help="precision for symmetry detection. default is 1e-5 Angstrom",
|
111
124
|
)
|
125
|
+
|
126
|
+
parser.add_argument(
|
127
|
+
"-Jonly",
|
128
|
+
action="store_true",
|
129
|
+
help="Symmetrize only the exchange parameters. Do not output DMI and anisotropic exchange.",
|
130
|
+
)
|
131
|
+
|
112
132
|
args = parser.parse_args()
|
113
133
|
if args.inpath is None:
|
114
134
|
parser.print_help()
|
115
135
|
raise ValueError("Please provide the input path to the exchange.")
|
116
|
-
symmetrize_J(
|
136
|
+
symmetrize_J(
|
137
|
+
path=args.inpath,
|
138
|
+
output_path=args.outpath,
|
139
|
+
symprec=args.symprec,
|
140
|
+
Jonly=args.Jonly,
|
141
|
+
)
|
117
142
|
|
118
143
|
|
119
144
|
if __name__ == "__main__":
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
2
|
from setuptools import find_packages, setup
|
3
3
|
|
4
|
-
__version__ = "0.9.
|
4
|
+
__version__ = "0.9.9_rc5"
|
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
|
|
tb2j-0.9.9rc3/TB2J/kpoints.py
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
|
3
|
-
|
4
|
-
def monkhorst_pack(size, gamma_center=False):
|
5
|
-
"""Construct a uniform sampling of k-space of given size.
|
6
|
-
Modified from ase.dft.kpoints with gamma_center option added"""
|
7
|
-
if np.less_equal(size, 0).any():
|
8
|
-
raise ValueError("Illegal size: %s" % list(size))
|
9
|
-
kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3))
|
10
|
-
asize = np.array(size)
|
11
|
-
shift = 0.5 * ((asize + 1) % 2) / asize
|
12
|
-
mkpts = (kpts + 0.5) / size - 0.5
|
13
|
-
if gamma_center:
|
14
|
-
mkpts += shift
|
15
|
-
|
16
|
-
return mkpts
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|