TB2J 0.9.9rc6__py3-none-any.whl → 0.9.9rc8__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/Jdownfolder.py +11 -9
- TB2J/MAEGreen.py +96 -22
- TB2J/anisotropy.py +104 -30
- TB2J/interfaces/siesta_interface.py +2 -1
- TB2J/io_exchange/io_exchange.py +17 -5
- TB2J/mathutils/fibonacci_sphere.py +74 -0
- TB2J/mycfr.py +4 -0
- TB2J/orbital_magmom.py +36 -0
- TB2J/thetaphi.py +16 -0
- {TB2J-0.9.9rc6.dist-info → tb2j-0.9.9rc8.dist-info}/METADATA +16 -7
- {TB2J-0.9.9rc6.dist-info → tb2j-0.9.9rc8.dist-info}/RECORD +25 -22
- {TB2J-0.9.9rc6.dist-info → tb2j-0.9.9rc8.dist-info}/WHEEL +1 -1
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_downfold.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_eigen.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_magnon.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_magnon_dos.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_merge.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_rotate.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/TB2J_rotateDM.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/abacus2J.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/siesta2J.py +0 -0
- {TB2J-0.9.9rc6.data → tb2j-0.9.9rc8.data}/scripts/wann2J.py +0 -0
- {TB2J-0.9.9rc6.dist-info → tb2j-0.9.9rc8.dist-info}/entry_points.txt +0 -0
- {TB2J-0.9.9rc6.dist-info → tb2j-0.9.9rc8.dist-info/licenses}/LICENSE +0 -0
- {TB2J-0.9.9rc6.dist-info → tb2j-0.9.9rc8.dist-info}/top_level.txt +0 -0
TB2J/Jdownfolder.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import os
|
2
2
|
from collections import defaultdict
|
3
|
+
|
3
4
|
import numpy as np
|
4
5
|
from ase.dft.kpoints import monkhorst_pack
|
6
|
+
|
5
7
|
from TB2J.io_exchange import SpinIO
|
6
8
|
from TB2J.Jtensor import decompose_J_tensor
|
7
9
|
|
@@ -73,8 +75,8 @@ class JDownfolder:
|
|
73
75
|
class PWFDownfolder:
|
74
76
|
def __init__(self, JR, Rlist, iM, iL, qmesh, atoms=None, iso_only=False, **kwargs):
|
75
77
|
from lawaf.interfaces.magnon.magnon_downfolder import (
|
76
|
-
MagnonWrapper,
|
77
78
|
MagnonDownfolder,
|
79
|
+
MagnonWrapper,
|
78
80
|
)
|
79
81
|
|
80
82
|
model = MagnonWrapper(JR, Rlist, atoms)
|
@@ -92,13 +94,13 @@ class PWFDownfolder:
|
|
92
94
|
# anchors={(0, 0, 0): (-1, -2, -3, -4)},
|
93
95
|
# anchors={(0, 0, 0): ()},
|
94
96
|
# use_proj=True,
|
95
|
-
enhance_Amn=
|
97
|
+
enhance_Amn=0.0,
|
96
98
|
)
|
97
99
|
params.update(kwargs)
|
98
100
|
wann.set_parameters(**params)
|
99
101
|
print("begin downfold")
|
100
102
|
ewf = wann.downfold()
|
101
|
-
ewf.save_hr_pickle("downfolded_JR.pickle")
|
103
|
+
# ewf.save_hr_pickle("downfolded_JR.pickle")
|
102
104
|
|
103
105
|
# Plot the band structure.
|
104
106
|
wann.plot_band_fitting(
|
@@ -135,7 +137,7 @@ class JDownfolder_pickle:
|
|
135
137
|
qmesh=[7, 7, 7],
|
136
138
|
iso_only=False,
|
137
139
|
method="pwf",
|
138
|
-
**kwargs
|
140
|
+
**kwargs,
|
139
141
|
):
|
140
142
|
self.exc = SpinIO.load_pickle(path=inpath, fname="TB2J.pickle")
|
141
143
|
|
@@ -193,7 +195,7 @@ class JDownfolder_pickle:
|
|
193
195
|
qmesh=self.qmesh,
|
194
196
|
atoms=self.atoms,
|
195
197
|
iso_only=self.iso_only,
|
196
|
-
**kwargs
|
198
|
+
**kwargs,
|
197
199
|
)
|
198
200
|
Jd, Rlist = d.get_JR()
|
199
201
|
return Jd, Rlist
|
@@ -274,10 +276,10 @@ class JDownfolder_pickle:
|
|
274
276
|
def test():
|
275
277
|
# pass
|
276
278
|
# inpath = "/home/hexu/projects/NiCl2/vasp_inputs/TB2J_results"
|
277
|
-
|
278
|
-
inpath = "/home/hexu/projects/TB2J_projects/NiCl2/TB2J_NiCl/TB2J_results"
|
279
|
-
|
280
|
-
|
279
|
+
inpath = "/home/hexu/projects/TB2J_example/CrI3/TB2J_results"
|
280
|
+
# inpath = "/home/hexu/projects/TB2J_projects/NiCl2/TB2J_NiCl/TB2J_results"
|
281
|
+
_fname = os.path.join(inpath, "TB2J.pickle")
|
282
|
+
_p = JDownfolder_pickle(
|
281
283
|
inpath=inpath, metals=["Ni"], ligands=["Cl"], outpath="TB2J_results_downfolded"
|
282
284
|
)
|
283
285
|
|
TB2J/MAEGreen.py
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
import gc
|
1
2
|
from pathlib import Path
|
2
3
|
|
4
|
+
import matplotlib.pyplot as plt
|
3
5
|
import numpy as np
|
4
6
|
import tqdm
|
5
7
|
from HamiltonIO.abacus.abacus_wrapper import AbacusSplitSOCParser
|
6
8
|
from HamiltonIO.model.occupations import GaussOccupations
|
7
9
|
from typing_extensions import DefaultDict
|
8
10
|
|
11
|
+
from TB2J.anisotropy import Anisotropy
|
9
12
|
from TB2J.exchange import ExchangeNCL
|
10
13
|
from TB2J.external import p_map
|
14
|
+
from TB2J.mathutils.fibonacci_sphere import fibonacci_semisphere
|
11
15
|
|
12
16
|
# from HamiltonIO.model.rotate_spin import rotate_Matrix_from_z_to_axis, rotate_Matrix_from_z_to_sperical
|
13
17
|
# from TB2J.abacus.abacus_wrapper import AbacusWrapper, AbacusParser
|
@@ -23,12 +27,21 @@ def get_occupation(evals, kweights, nel, width=0.1):
|
|
23
27
|
|
24
28
|
class MAEGreen(ExchangeNCL):
|
25
29
|
def __init__(self, angles=None, **kwargs):
|
30
|
+
"""
|
31
|
+
angles are defined as theta, phi pairs, where theta is the angle between the z-axis and the magnetization direction, and phi is the angle between the x-axis and the projection of the magnetization direction on the x-y plane.
|
32
|
+
"""
|
26
33
|
super().__init__(**kwargs)
|
27
34
|
self.natoms = len(self.atoms)
|
28
35
|
if angles is None or angles == "axis":
|
29
36
|
self.set_angles_axis()
|
30
37
|
elif angles == "scan":
|
31
38
|
self.set_angles_scan()
|
39
|
+
elif angles == "fib":
|
40
|
+
self.set_angles_fib()
|
41
|
+
elif angles == "random":
|
42
|
+
self.set_angles_random()
|
43
|
+
elif angles == "miller":
|
44
|
+
self.set_angles_miller()
|
32
45
|
else:
|
33
46
|
self.thetas = angles[0]
|
34
47
|
self.phis = angles[1]
|
@@ -39,9 +52,32 @@ class MAEGreen(ExchangeNCL):
|
|
39
52
|
self.es_atom_orb = DefaultDict(lambda: 0)
|
40
53
|
|
41
54
|
def set_angles_axis(self):
|
42
|
-
"""theta and phi are defined as the x, y, z, axis."""
|
43
|
-
self.thetas = [0, np.pi / 2, np.pi / 2, np.pi / 2, np.pi]
|
44
|
-
self.phis = [0, 0, np.pi / 2, np.pi / 4, 0]
|
55
|
+
"""theta and phi are defined as the x, y, z, xy, yz, xz, xyz, x-yz, -xyz, -x-yz axis."""
|
56
|
+
self.thetas = [0, np.pi / 2, np.pi / 2, np.pi / 2, np.pi, 0, np.pi / 2, 0, 0, 0]
|
57
|
+
self.phis = [0, 0, np.pi / 2, np.pi / 4, 0, 0, 0, np.pi]
|
58
|
+
|
59
|
+
def set_angles_miller(self, nmax=2):
|
60
|
+
"""theta and angles corresponding to the miller index. remove duplicates.
|
61
|
+
e.g. 002 and 001 are the same.
|
62
|
+
"""
|
63
|
+
thetas = []
|
64
|
+
phis = []
|
65
|
+
for k in range(0, nmax + 1):
|
66
|
+
for j in range(-nmax, nmax + 1):
|
67
|
+
for i in range(-nmax, nmax + 1):
|
68
|
+
if i == 0 and j == 0 and k == 0:
|
69
|
+
continue
|
70
|
+
thetas.append(np.arccos(k / np.sqrt(i**2 + j**2 + k**2)))
|
71
|
+
if i == 0 and j == 0:
|
72
|
+
phis.append(0)
|
73
|
+
else:
|
74
|
+
phis.append(np.arctan2(j, i))
|
75
|
+
self.thetas = thetas
|
76
|
+
self.phis = phis
|
77
|
+
self.angle_pairs = list(zip(thetas, phis))
|
78
|
+
# remove duplicates of angles using sets.
|
79
|
+
self.angle_pairs = list(set(self.angle_pairs))
|
80
|
+
self.thetas, self.phis = zip(*self.angle_pairs)
|
45
81
|
|
46
82
|
def set_angles_scan(self, step=15):
|
47
83
|
self.thetas = []
|
@@ -51,6 +87,21 @@ class MAEGreen(ExchangeNCL):
|
|
51
87
|
self.thetas.append(i * np.pi / 180)
|
52
88
|
self.phis.append(j * np.pi / 180)
|
53
89
|
|
90
|
+
def set_angles_random(self, n=16):
|
91
|
+
# n random pairs of theta, phi
|
92
|
+
self.thetas = np.random.random(n) * np.pi
|
93
|
+
self.phis = np.random.random(n) * 2 * np.pi
|
94
|
+
|
95
|
+
def set_angles_fib(self, n=35):
|
96
|
+
self.thetas, self.phis = fibonacci_semisphere(n)
|
97
|
+
# thetas and phis are np.array
|
98
|
+
# add (theta, phi): (pi/2, pi/2) and (pi/2, pi/4)
|
99
|
+
# self.thetas += [np.pi / 2, np.pi / 2]
|
100
|
+
# self.phis += [np.pi / 2, np.pi / 4]
|
101
|
+
for i in range(8):
|
102
|
+
self.thetas = np.concatenate([self.thetas, [np.pi / 2]])
|
103
|
+
self.phis = np.concatenate([self.phis, [np.pi * i / 8]])
|
104
|
+
|
54
105
|
def get_band_energy_vs_angles_from_eigen(
|
55
106
|
self,
|
56
107
|
thetas,
|
@@ -79,16 +130,12 @@ class MAEGreen(ExchangeNCL):
|
|
79
130
|
|
80
131
|
def get_perturbed(self, e, thetas, phis):
|
81
132
|
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
|
-
|
86
|
-
|
87
|
-
|
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.""")
|
133
|
+
# maxsoc = self.tbmodel.get_max_Hsoc_abs()
|
134
|
+
# maxH0 = self.tbmodel.get_max_H0_spin_abs()
|
135
|
+
# if maxsoc > maxH0 * 0.01:
|
136
|
+
# print(f"""Warning: The SOC of the Hamiltonian has a maximum of {maxsoc} eV,
|
137
|
+
# comparing to the maximum of {maxH0} eV of the spin part of the Hamiltonian.
|
138
|
+
# The SOC is too strong, the perturbation theory may not be valid.""")
|
92
139
|
|
93
140
|
G0K = self.G.get_Gk_all(e)
|
94
141
|
Hsoc_k = self.tbmodel.get_Hk_soc(self.G.kpts)
|
@@ -104,12 +151,12 @@ class MAEGreen(ExchangeNCL):
|
|
104
151
|
GdH = G0K[ik] @ dHi
|
105
152
|
# dE += np.trace(GdH @ G0K[i].T.conj() @ dHi) * self.kweights[i]
|
106
153
|
# diagonal of second order perturbation.
|
107
|
-
dG2diag = np.diag(GdH @ GdH)
|
154
|
+
# dG2diag = np.diag(GdH @ GdH)
|
108
155
|
# dG2 = np.einsum("ij,ji->ij", GdH, GdH)
|
109
156
|
dG2 = GdH * GdH.T
|
110
157
|
dG2sum = np.sum(dG2)
|
111
158
|
# print(f"dG2sum-sum: {dG2sum}")
|
112
|
-
dG2sum = np.sum(dG2diag)
|
159
|
+
# dG2sum = np.sum(dG2diag)
|
113
160
|
|
114
161
|
# dG2sum = np.trace(GdH @ GdH)
|
115
162
|
# print(f"dG2sum-Tr: {dG2sum}")
|
@@ -130,13 +177,11 @@ class MAEGreen(ExchangeNCL):
|
|
130
177
|
+ dE_atom_orb[1::2, ::2]
|
131
178
|
+ dE_atom_orb[::2, 1::2]
|
132
179
|
)
|
180
|
+
dE_atom = np.sum(dE_atom_orb)
|
133
181
|
mmat = self.mmats[iatom]
|
134
182
|
dE_atom_orb = mmat.T @ dE_atom_orb @ mmat
|
135
|
-
|
136
183
|
dE_angle_atom_orb[(iangle, iatom)] += dE_atom_orb
|
137
|
-
|
138
|
-
dE_atom = np.sum(dG2diag[iorb]) * self.G.kweights[ik]
|
139
|
-
# dE_atom = np.sum(dE_atom_orb)
|
184
|
+
# dE_atom = np.sum(dG2diag[iorb]) * self.G.kweights[ik]
|
140
185
|
dE_angle_atom[iangle, iatom] += dE_atom
|
141
186
|
return dE_angle, dE_angle_atom, dE_angle_atom_orb
|
142
187
|
|
@@ -189,10 +234,25 @@ class MAEGreen(ExchangeNCL):
|
|
189
234
|
for key, value in self.es_atom_orb.items():
|
190
235
|
self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
|
191
236
|
|
192
|
-
def
|
237
|
+
def fit_anisotropy_tensor(self):
|
238
|
+
self.ani = Anisotropy.fit_from_data(self.thetas, self.phis, self.es)
|
239
|
+
return self.ani
|
240
|
+
|
241
|
+
def output(
|
242
|
+
self,
|
243
|
+
output_path="TB2J_anisotropy",
|
244
|
+
with_eigen=True,
|
245
|
+
figure3d="MAE_3d.png",
|
246
|
+
figure_contourf="MAE_contourf.png",
|
247
|
+
):
|
193
248
|
Path(output_path).mkdir(exist_ok=True)
|
194
249
|
fname = f"{output_path}/MAE.dat"
|
195
250
|
fname_orb = f"{output_path}/MAE_orb.dat"
|
251
|
+
fname_tensor = f"{output_path}/MAE_tensor.dat"
|
252
|
+
if figure3d is not None:
|
253
|
+
fname_fig3d = f"{output_path}/{figure3d}"
|
254
|
+
if figure_contourf is not None:
|
255
|
+
fname_figcontourf = f"{output_path}/{figure_contourf}"
|
196
256
|
|
197
257
|
# ouput with eigenvalues.
|
198
258
|
if with_eigen:
|
@@ -208,15 +268,29 @@ class MAEGreen(ExchangeNCL):
|
|
208
268
|
f.write("\n")
|
209
269
|
|
210
270
|
with open(fname, "w") as f:
|
211
|
-
f.write("# theta, phi, MAE(total), MAE(atom-wise) Unit: meV\n")
|
271
|
+
f.write("# theta (rad), phi(rad), MAE(total), MAE(atom-wise) Unit: meV\n")
|
212
272
|
for i, (theta, phi, e, es) in enumerate(
|
213
273
|
zip(self.thetas, self.phis, self.es, self.es_atom)
|
214
274
|
):
|
215
|
-
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f} ")
|
275
|
+
f.write(f"{theta%np.pi:.5f} {phi%(2*np.pi):.5f} {e*1e3:.8f} ")
|
216
276
|
for ea in es:
|
217
277
|
f.write(f"{ea*1e3:.8f} ")
|
218
278
|
f.write("\n")
|
219
279
|
|
280
|
+
self.ani = self.fit_anisotropy_tensor()
|
281
|
+
with open(fname_tensor, "w") as f:
|
282
|
+
f.write("# Anisotropy tensor in meV\n")
|
283
|
+
f.write(f"{self.ani.tensor_strings(include_isotropic=False)}\n")
|
284
|
+
|
285
|
+
if figure3d is not None:
|
286
|
+
self.ani.plot_3d(figname=fname_fig3d, show=False)
|
287
|
+
|
288
|
+
if figure_contourf is not None:
|
289
|
+
self.ani.plot_contourf(figname=fname_figcontourf, show=False)
|
290
|
+
|
291
|
+
plt.close()
|
292
|
+
gc.collect()
|
293
|
+
|
220
294
|
with open(fname_orb, "w") as f:
|
221
295
|
f.write("=" * 80 + "\n")
|
222
296
|
f.write("Orbitals for each atom: \n")
|
TB2J/anisotropy.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
import random
|
2
|
-
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from pathlib import Path
|
4
|
+
|
3
5
|
import matplotlib.pyplot as plt
|
6
|
+
import numpy as np
|
7
|
+
from numpy.linalg import matrix_rank
|
4
8
|
from scipy.interpolate import LinearNDInterpolator
|
5
9
|
from scipy.optimize import curve_fit
|
6
|
-
from numpy.linalg import matrix_rank
|
7
|
-
from dataclasses import dataclass
|
8
|
-
from pathlib import Path
|
9
10
|
|
10
11
|
|
11
12
|
@dataclass
|
@@ -18,8 +19,9 @@ class Anisotropy:
|
|
18
19
|
@classmethod
|
19
20
|
def from_T6(cls, T6):
|
20
21
|
T = T6_to_T(T6)
|
21
|
-
|
22
|
-
|
22
|
+
isotropic_part = np.trace(T) / 3
|
23
|
+
T -= isotropic_part * np.eye(3)
|
24
|
+
direction, amplitude = anisotropy_tensor_to_vector(T)
|
23
25
|
return cls(
|
24
26
|
direction=direction, amplitude=amplitude, isotropic_part=isotropic_part, T=T
|
25
27
|
)
|
@@ -33,9 +35,9 @@ class Anisotropy:
|
|
33
35
|
|
34
36
|
@classmethod
|
35
37
|
def from_tensor(cls, T):
|
36
|
-
isotropic_part = np.trace(T) / 3
|
38
|
+
isotropic_part = np.trace(T) / 3 * np.eye(3)
|
37
39
|
T -= np.trace(T) / 3 * np.eye(3)
|
38
|
-
direction, amplitude =
|
40
|
+
direction, amplitude = anisotropy_tensor_to_vector(T)
|
39
41
|
return cls(
|
40
42
|
T=T, direction=direction, amplitude=amplitude, isotropic_part=isotropic_part
|
41
43
|
)
|
@@ -44,13 +46,14 @@ class Anisotropy:
|
|
44
46
|
if self.isotropic_part is None:
|
45
47
|
self.isotropic_part = 0
|
46
48
|
if self.T is None:
|
47
|
-
self.T =
|
48
|
-
self.direction, self.amplitude
|
49
|
-
|
49
|
+
self.T = (
|
50
|
+
anisotropy_vector_to_tensor(self.direction, self.amplitude)
|
51
|
+
+ self.isotropic_part
|
52
|
+
)
|
50
53
|
elif self.direction is None or self.amplitude is None:
|
51
|
-
self.isotropic_part = np.trace(self.T) / 3
|
52
|
-
# print(f'
|
53
|
-
self.direction, self.amplitude =
|
54
|
+
self.isotropic_part = np.trace(self.T) / 3 * np.eye(3)
|
55
|
+
# print(f'anisotropic tensor = {self.anisotropic_part}')
|
56
|
+
self.direction, self.amplitude = anisotropy_tensor_to_vector(
|
54
57
|
self.anisotropic_part
|
55
58
|
)
|
56
59
|
self.isotropic_part = np.trace(self.T) / 3
|
@@ -113,7 +116,6 @@ class Anisotropy:
|
|
113
116
|
E = -self.amplitude * (S @ self.direction) ** 2
|
114
117
|
if include_isotropic:
|
115
118
|
E = E + self.isotropic_part
|
116
|
-
print(f"E shape = {E.shape}")
|
117
119
|
return E
|
118
120
|
|
119
121
|
def energy_tensor_form(self, S=None, angle=None, include_isotropic=False):
|
@@ -126,7 +128,7 @@ class Anisotropy:
|
|
126
128
|
return -S.T @ self.anisotropic_part @ S
|
127
129
|
|
128
130
|
@classmethod
|
129
|
-
def fit_from_data(cls, thetas, phis, values, test=False):
|
131
|
+
def fit_from_data(cls, thetas, phis, values, test=False, units="rad"):
|
130
132
|
"""
|
131
133
|
Fit the anisotropic tensor to the data
|
132
134
|
parameters:
|
@@ -137,14 +139,16 @@ class Anisotropy:
|
|
137
139
|
the anisotropic object fitted from the data
|
138
140
|
"""
|
139
141
|
angles = np.vstack([thetas, phis])
|
142
|
+
if units.lower().startswith("deg"):
|
143
|
+
angles = np.deg2rad(angles)
|
140
144
|
params, cov = curve_fit(anisotropy_energy, angles, values)
|
141
145
|
fitted_values = anisotropy_energy(angles, *params)
|
142
146
|
|
143
147
|
delta = fitted_values - values
|
144
148
|
|
145
149
|
# print(f'Max value = {np.max(values)}, Min value = {np.min(values)}')
|
146
|
-
if np.abs(delta).max() > 1e-
|
147
|
-
print(
|
150
|
+
if np.abs(delta).max() > 1e-4:
|
151
|
+
print("Warning: The fitting is not consistent with the data.")
|
148
152
|
print(f"Max-min = {np.max(values) - np.min(values)}")
|
149
153
|
print(f"delta = {np.max(np.abs(delta))}")
|
150
154
|
T = T6_to_T(params)
|
@@ -157,7 +161,7 @@ class Anisotropy:
|
|
157
161
|
angle=[thetas[i], phis[i]], include_isotropic=True
|
158
162
|
)
|
159
163
|
values2.append(E)
|
160
|
-
delta2 = np.array(values2) - values
|
164
|
+
# delta2 = np.array(values2) - values
|
161
165
|
# print(delta2)
|
162
166
|
|
163
167
|
ax = plot_3D_scatter(angles, values - np.min(values), color="r")
|
@@ -183,7 +187,7 @@ class Anisotropy:
|
|
183
187
|
delta = fitted_values - values
|
184
188
|
print(f"Max value = {np.max(values)}, Min value = {np.min(values)}")
|
185
189
|
print(f"Max-min = {np.max(values) - np.min(values)}")
|
186
|
-
|
190
|
+
print(f"delta = {delta}")
|
187
191
|
theta_a, phi_a, amplitude, isotropic_part = params
|
188
192
|
direction = sphere_to_cartesian([theta_a, phi_a])
|
189
193
|
return cls.from_direction_amplitude(
|
@@ -208,6 +212,25 @@ class Anisotropy:
|
|
208
212
|
else:
|
209
213
|
raise ValueError(f"Unknown method {method}")
|
210
214
|
|
215
|
+
@classmethod
|
216
|
+
def fit_from_xyz_data_file(cls, fname, method="tensor"):
|
217
|
+
"""
|
218
|
+
Fit the anisotropic tensor to the data with x y z val form
|
219
|
+
parameters:
|
220
|
+
fname: the file name of the data
|
221
|
+
Return:
|
222
|
+
anisotropy: the anisotropic object
|
223
|
+
"""
|
224
|
+
data = np.loadtxt(fname)
|
225
|
+
xyz, value = data[:, 0:3], data[:, 3]
|
226
|
+
theta, phi = np.array([cartesian_to_sphere(t) for t in xyz]).T
|
227
|
+
if method == "tensor":
|
228
|
+
return cls.fit_from_data(theta, phi, value)
|
229
|
+
elif method == "vector":
|
230
|
+
return cls.fit_from_data_vector_form(theta, phi, value)
|
231
|
+
else:
|
232
|
+
raise ValueError(f"Unknown method {method}")
|
233
|
+
|
211
234
|
def plot_3d(self, ax=None, figname=None, show=True, surface=True):
|
212
235
|
"""
|
213
236
|
plot the anisotropic energy in all directions in 3D
|
@@ -297,6 +320,55 @@ class Anisotropy:
|
|
297
320
|
if show:
|
298
321
|
plt.show()
|
299
322
|
|
323
|
+
def plot_contourf(self, ax=None, figname=None, show=False):
|
324
|
+
if ax is None:
|
325
|
+
fig, ax = plt.subplots()
|
326
|
+
X, Y = np.meshgrid(np.arange(0, 180, 1), np.arange(-180, 180, 1))
|
327
|
+
Z = np.zeros(X.shape)
|
328
|
+
ntheta, nphi = X.shape
|
329
|
+
for i in range(ntheta):
|
330
|
+
for j in range(nphi):
|
331
|
+
E = self.energy_tensor_form(angle=[X[i, j], Y[i, j]])
|
332
|
+
Z[i, j] = E
|
333
|
+
# find the X, Y for min and max of Z
|
334
|
+
X_max, Y_max = np.unravel_index(np.argmax(Z), Z.shape)
|
335
|
+
X_min, Y_min = np.unravel_index(np.argmin(Z), Z.shape)
|
336
|
+
X_max, Y_max = X[X_max, Y_max], Y[X_max, Y_max]
|
337
|
+
X_min, Y_min = X[X_min, Y_min], Y[X_min, Y_min]
|
338
|
+
c = ax.contourf(X, Y, Z, cmap="viridis", levels=200)
|
339
|
+
# print(X_max, Y_max, X_min, Y_min)
|
340
|
+
# ax.scatter(X_max, Y_max, color="r", marker="o")
|
341
|
+
# ax.scatter(X_min, Y_min, color="b", marker="o")
|
342
|
+
ax.set_xlabel("$\theta$ (degree)")
|
343
|
+
ax.set_ylabel("$\phi$ degree")
|
344
|
+
# ax.scatter(X_max, Y_max, color="r", marker="o")
|
345
|
+
# ax.scatter(X_min, Y_min, color="r", marker="o")
|
346
|
+
|
347
|
+
# colorbar
|
348
|
+
_cbar = plt.colorbar(c, ax=ax)
|
349
|
+
|
350
|
+
if figname is not None:
|
351
|
+
plt.savefig(figname)
|
352
|
+
plt.close()
|
353
|
+
if show:
|
354
|
+
print(f"Max = {X_max}, {Y_max}, Min = {X_min}, {Y_min}")
|
355
|
+
plt.show()
|
356
|
+
return ax
|
357
|
+
|
358
|
+
def tensor_strings(self, include_isotropic=False, multiplier=1):
|
359
|
+
"""
|
360
|
+
convert the energy tensor to strings for easy printing
|
361
|
+
parameters:
|
362
|
+
include_isotropic: if include the isotropic part
|
363
|
+
multiplier: the multiplier for the tensor. Use for scaling the tensor by units.
|
364
|
+
"""
|
365
|
+
if include_isotropic:
|
366
|
+
T = self.T
|
367
|
+
else:
|
368
|
+
T = self.T
|
369
|
+
strings = np.array2string(T * multiplier, precision=5, separator=" ")
|
370
|
+
return strings
|
371
|
+
|
300
372
|
|
301
373
|
def plot_3D_scatter(angles, values, ax=None, **kwargs):
|
302
374
|
if ax is None:
|
@@ -389,7 +461,7 @@ def sphere_to_cartesian(angles, r=1):
|
|
389
461
|
return np.array([x, y, z])
|
390
462
|
|
391
463
|
|
392
|
-
def cartesian_to_sphere(xyz):
|
464
|
+
def cartesian_to_sphere(xyz, unit="deg"):
|
393
465
|
"""
|
394
466
|
Transform the cartesian coordinates to the spherical coordinates
|
395
467
|
parameters:
|
@@ -401,8 +473,13 @@ def cartesian_to_sphere(xyz):
|
|
401
473
|
r = np.linalg.norm(xyz)
|
402
474
|
theta = np.arccos(z / r)
|
403
475
|
phi = np.arctan2(y, x)
|
404
|
-
|
405
|
-
|
476
|
+
if unit.lower().startswith("deg"):
|
477
|
+
theta = theta * 180 / np.pi
|
478
|
+
phi = phi * 180 / np.pi
|
479
|
+
elif unit.lower.startswith("rad"):
|
480
|
+
pass
|
481
|
+
else:
|
482
|
+
raise ValueError("unit must be 'deg' or 'rad'")
|
406
483
|
return np.array([theta, phi])
|
407
484
|
|
408
485
|
|
@@ -470,7 +547,7 @@ def fit_anisotropy(thetas, phis, values):
|
|
470
547
|
params, cov = curve_fit(anisotropy_energy, angles, values)
|
471
548
|
# check if the fitting is consistent with the data
|
472
549
|
T = T6_to_T(params)
|
473
|
-
direction, amp =
|
550
|
+
direction, amp = anisotropy_tensor_to_vector(T)
|
474
551
|
return direction, amp
|
475
552
|
|
476
553
|
|
@@ -518,7 +595,7 @@ def anisotropy_vector_to_tensor(direction, amplitude):
|
|
518
595
|
return T
|
519
596
|
|
520
597
|
|
521
|
-
def
|
598
|
+
def anisotropy_tensor_to_vector(T):
|
522
599
|
"""
|
523
600
|
Transform the anisotropic tensor to the anisotropic vector
|
524
601
|
parameters:
|
@@ -553,7 +630,7 @@ def test_anisotorpy_vector_to_tensor():
|
|
553
630
|
assert np.abs(diff) < 1e-10
|
554
631
|
|
555
632
|
# test if the inverse transformation get the direction and amplitude back
|
556
|
-
dir2, amp2 =
|
633
|
+
dir2, amp2 = anisotropy_tensor_to_vector(T)
|
557
634
|
|
558
635
|
# set the first element of the direction to be positive
|
559
636
|
if direction[0] * dir2[0] < 0:
|
@@ -569,7 +646,7 @@ def test_anisotropy_tensor_to_vector():
|
|
569
646
|
T = np.random.rand(3, 3)
|
570
647
|
T = T + T.T
|
571
648
|
T = T - np.trace(T) / 3
|
572
|
-
direction, amplitude =
|
649
|
+
direction, amplitude = anisotropy_tensor_to_vector(T)
|
573
650
|
T2 = anisotropy_vector_to_tensor(direction, amplitude)
|
574
651
|
print(f"T = {T}")
|
575
652
|
print(f"T2 = {T2}")
|
@@ -597,9 +674,6 @@ def test_fit_anisotropy():
|
|
597
674
|
f"theta = {theta[i]}, phi = {phi[i]}, value = {value[i]}, fitted value = {fitted_values[i]}, delta = {delta[i]}"
|
598
675
|
)
|
599
676
|
|
600
|
-
easy_axis = easy_axis_from_tensor(T6)
|
601
|
-
print(f"easy_axis = {easy_axis}")
|
602
|
-
|
603
677
|
|
604
678
|
def view_anisotropy_strain():
|
605
679
|
strains1 = [(x, 0.0) for x in np.arange(0.000, 0.021, 0.002)]
|
@@ -156,6 +156,7 @@ Warning: The DMI component parallel to the spin orientation, the Jani which has
|
|
156
156
|
atoms=model.atoms,
|
157
157
|
basis=basis,
|
158
158
|
efermi=None,
|
159
|
+
angles="miller",
|
159
160
|
# magnetic_elements=magnetic_elements,
|
160
161
|
# include_orbs=include_orbs,
|
161
162
|
**exargs,
|
@@ -163,7 +164,7 @@ Warning: The DMI component parallel to the spin orientation, the Jani which has
|
|
163
164
|
# thetas = [0, np.pi / 2, np.pi, 3 * np.pi / 2]
|
164
165
|
# phis = [0, 0, 0, 0]
|
165
166
|
# MAE.set_angles(thetas=thetas, phis=phis)
|
166
|
-
MAE.run(output_path=f"{output_path}_anisotropy", with_eigen=
|
167
|
+
MAE.run(output_path=f"{output_path}_anisotropy", with_eigen=False)
|
167
168
|
print(
|
168
169
|
f"MAE calculation finished. The results are in {output_path} directory."
|
169
170
|
)
|
TB2J/io_exchange/io_exchange.py
CHANGED
@@ -13,6 +13,11 @@ import pickle
|
|
13
13
|
from collections.abc import Iterable
|
14
14
|
from datetime import datetime
|
15
15
|
|
16
|
+
import matplotlib
|
17
|
+
|
18
|
+
matplotlib.use("Agg")
|
19
|
+
import gc
|
20
|
+
|
16
21
|
import matplotlib.pyplot as plt
|
17
22
|
import numpy as np
|
18
23
|
|
@@ -320,7 +325,11 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
320
325
|
i = self.i_spin(i)
|
321
326
|
j = self.i_spin(j)
|
322
327
|
if iso_only:
|
323
|
-
|
328
|
+
J = self.get_Jiso(i, j, R)
|
329
|
+
if J is not None:
|
330
|
+
Jtensor = np.eye(3) * self.get_J(i, j, R)
|
331
|
+
else:
|
332
|
+
Jtensor = np.eye(3) * 0
|
324
333
|
else:
|
325
334
|
Jtensor = combine_J_tensor(
|
326
335
|
Jiso=self.get_J(i, j, R),
|
@@ -329,7 +338,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
329
338
|
)
|
330
339
|
return Jtensor
|
331
340
|
|
332
|
-
def get_full_Jtensor_for_one_R(self, R):
|
341
|
+
def get_full_Jtensor_for_one_R(self, R, iso_only=False):
|
333
342
|
"""
|
334
343
|
Return the full exchange tensor of all i and j for cell R.
|
335
344
|
param R (tuple of integers): cell index R
|
@@ -340,15 +349,17 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
340
349
|
Jmat = np.zeros((n3, n3), dtype=float)
|
341
350
|
for i in range(self.nspin):
|
342
351
|
for j in range(self.nspin):
|
343
|
-
Jmat[i * 3 : i * 3 + 3, j * 3 : j * 3 + 3] = self.get_J_tensor(
|
352
|
+
Jmat[i * 3 : i * 3 + 3, j * 3 : j * 3 + 3] = self.get_J_tensor(
|
353
|
+
i, j, R, iso_only=iso_only
|
354
|
+
)
|
344
355
|
return Jmat
|
345
356
|
|
346
|
-
def get_full_Jtensor_for_Rlist(self, asr=False, iso_only=
|
357
|
+
def get_full_Jtensor_for_Rlist(self, asr=False, iso_only=True):
|
347
358
|
n3 = self.nspin * 3
|
348
359
|
nR = len(self.Rlist)
|
349
360
|
Jmat = np.zeros((nR, n3, n3), dtype=float)
|
350
361
|
for iR, R in enumerate(self.Rlist):
|
351
|
-
Jmat[iR] = self.get_full_Jtensor_for_one_R(R)
|
362
|
+
Jmat[iR] = self.get_full_Jtensor_for_one_R(R, iso_only=iso_only)
|
352
363
|
if asr:
|
353
364
|
iR0 = np.argmin(np.linalg.norm(self.Rlist, axis=1))
|
354
365
|
assert np.linalg.norm(self.Rlist[iR0]) == 0
|
@@ -544,6 +555,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
|
|
544
555
|
plt.show()
|
545
556
|
plt.clf()
|
546
557
|
plt.close()
|
558
|
+
gc.collect() # This is to fix the tk error if multiprocess is used.
|
547
559
|
return fig, axes
|
548
560
|
|
549
561
|
def write_tom_format(self, path):
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
scan the spheres in the space of (theta, phi), so that the points are uniformly distributed on a sphere.
|
4
|
+
The algorithm is based on fibonacci spiral sampling method.
|
5
|
+
Reference:
|
6
|
+
https://extremelearning.com.au/how-to-evenly-distribute-points-on-a-sphere-more-effectively-than-the-canonical-fibonacci-lattice/
|
7
|
+
|
8
|
+
But note that the convention of theta and phi are different from the one in the reference.
|
9
|
+
Here, cos(theta) = z, and phi is the azimuthal angle in the x-y plane.
|
10
|
+
In the reference, theta is the azimuthal angle in the x-y plane, and phi is the polar angle.
|
11
|
+
"""
|
12
|
+
|
13
|
+
import numpy as np
|
14
|
+
from numpy import pi
|
15
|
+
|
16
|
+
|
17
|
+
def fibonacci_sphere(samples=100):
|
18
|
+
"""
|
19
|
+
Fibonacci Sphere Sampling Method
|
20
|
+
Parameters:
|
21
|
+
samples (int): number of points to sample on the sphere
|
22
|
+
Returns:
|
23
|
+
theta and phi: numpy arrays with shape (samples,) containing the angles of the sampled points.
|
24
|
+
"""
|
25
|
+
# Initialize the golden ratio and angles
|
26
|
+
goldenRatio = (1 + np.sqrt(5)) / 2
|
27
|
+
phi = np.arange(samples) * (2 * pi / goldenRatio)
|
28
|
+
theta = np.arccos(1 - 2 * np.arange(samples) / samples)
|
29
|
+
return theta, phi
|
30
|
+
|
31
|
+
|
32
|
+
def fibonacci_semisphere(samples=100):
|
33
|
+
"""
|
34
|
+
Fibonacci Sphere Sampling Method for the upper hemisphere of a sphere.
|
35
|
+
|
36
|
+
Parameters:
|
37
|
+
samples (int): number of points to sample on the sphere
|
38
|
+
|
39
|
+
Returns:
|
40
|
+
theta and phi: numpy arrays with shape (samples,) containing the angles of the sampled points.
|
41
|
+
"""
|
42
|
+
# Initialize the golden ratio and angles
|
43
|
+
goldenRatio = (1 + np.sqrt(5)) / 2
|
44
|
+
phi = np.arange(samples) * (2 * pi / goldenRatio)
|
45
|
+
theta = np.arccos(np.linspace(0, 1, samples))
|
46
|
+
return theta, phi
|
47
|
+
|
48
|
+
|
49
|
+
def test_fibonacci_sphere():
|
50
|
+
import matplotlib.pyplot as plt
|
51
|
+
|
52
|
+
# Generate points on the sphere
|
53
|
+
samples = 20000
|
54
|
+
theta, phi = fibonacci_sphere(samples)
|
55
|
+
# theta, phi = fibonacci_semisphere(samples)
|
56
|
+
|
57
|
+
# Convert spherical coordinates to Cartesian coordinates
|
58
|
+
x = np.cos(phi) * np.sin(theta)
|
59
|
+
y = np.sin(phi) * np.sin(theta)
|
60
|
+
z = np.cos(theta)
|
61
|
+
|
62
|
+
fig = plt.figure()
|
63
|
+
ax = fig.add_subplot(111, projection="3d")
|
64
|
+
ax.scatter(x, y, z, s=13.5)
|
65
|
+
# ax.plot(x, y, z)
|
66
|
+
|
67
|
+
# Set aspect to 'equal' for equal scaling in all directions
|
68
|
+
ax.set_aspect("equal")
|
69
|
+
|
70
|
+
plt.show()
|
71
|
+
|
72
|
+
|
73
|
+
if __name__ == "__main__":
|
74
|
+
test_fibonacci_sphere()
|
TB2J/mycfr.py
CHANGED
@@ -64,6 +64,10 @@ class CFR:
|
|
64
64
|
# zp = 1j / eigp * kb * self.T
|
65
65
|
# Rp = 0.25 * np.diag(eigv)**2 * zp **2
|
66
66
|
|
67
|
+
# print the poles and the weights
|
68
|
+
for i in range(len(self.poles)):
|
69
|
+
print("Pole: ", self.poles[i], "Weight: ", self.weights[i])
|
70
|
+
|
67
71
|
# add a point to the poles: 1e10j
|
68
72
|
self.path = np.concatenate((self.path, [self.Rinf * 1j]))
|
69
73
|
# self.path = np.concatenate((self.path, [0.0]))
|
TB2J/orbital_magmom.py
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
"""
|
2
|
+
utilities to handel orbital magnetic moments
|
3
|
+
"""
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
|
7
|
+
|
8
|
+
def complex_spherical_harmonic_to_real_spherical_harmonic(l=1):
|
9
|
+
"""
|
10
|
+
matrix to convert the complex spherical harmonics to real spherical harmonics
|
11
|
+
"""
|
12
|
+
MCR = np.zeros((2 * l + 1, 2 * l + 1), dtype=np.complex128)
|
13
|
+
MCR[0 + l, 0 + l] = 1.0
|
14
|
+
for m in range(1, l + 1):
|
15
|
+
mi = m + l
|
16
|
+
mpi = -m + l
|
17
|
+
MCR[mi, mi] = (-1) ** m / 2
|
18
|
+
MCR[mi, mpi] = 1.0 / 2
|
19
|
+
MCR[mpi, mi] = -1j * (-1) ** m / 2
|
20
|
+
MCR[mpi, mpi] = 1j / 2
|
21
|
+
|
22
|
+
return MCR
|
23
|
+
|
24
|
+
|
25
|
+
def test_complex_spherical_harmonic_to_real_spherical_harmonic():
|
26
|
+
"""
|
27
|
+
test the conversion matrix
|
28
|
+
"""
|
29
|
+
l = 3
|
30
|
+
MCR = complex_spherical_harmonic_to_real_spherical_harmonic(l)
|
31
|
+
# print(MCR*np.sqrt(2))
|
32
|
+
print(MCR * 2)
|
33
|
+
|
34
|
+
|
35
|
+
if __name__ == "__main__":
|
36
|
+
test_complex_spherical_harmonic_to_real_spherical_harmonic()
|
TB2J/thetaphi.py
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
import numpy as np
|
2
|
+
|
3
|
+
|
4
|
+
def theta_phi_even_spaced(n):
|
5
|
+
"""
|
6
|
+
Return n evenly spaced theta and phi values in the ranges [0, pi] and [0, 2*pi] respectively.
|
7
|
+
"""
|
8
|
+
phis = []
|
9
|
+
thetas = []
|
10
|
+
for i in range(n):
|
11
|
+
phi = 2 * np.pi * i / n
|
12
|
+
phis.append(phi)
|
13
|
+
r = np.sin(np.pi * i / n)
|
14
|
+
theta = np.arccos(1 - 2 * r)
|
15
|
+
thetas.append(theta)
|
16
|
+
return thetas, phis
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: TB2J
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.9rc8
|
4
4
|
Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
|
5
5
|
Author: Xu He
|
6
6
|
Author-email: mailhexu@gmail.com
|
@@ -14,15 +14,24 @@ Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
14
|
Classifier: License :: OSI Approved :: BSD License
|
15
15
|
Requires-Python: >=3.6
|
16
16
|
License-File: LICENSE
|
17
|
-
Requires-Dist: numpy
|
17
|
+
Requires-Dist: numpy<2.0
|
18
18
|
Requires-Dist: scipy
|
19
19
|
Requires-Dist: matplotlib
|
20
|
-
Requires-Dist: ase
|
20
|
+
Requires-Dist: ase>=3.19
|
21
21
|
Requires-Dist: tqdm
|
22
22
|
Requires-Dist: pathos
|
23
|
-
Requires-Dist: packaging
|
24
|
-
Requires-Dist: HamiltonIO
|
23
|
+
Requires-Dist: packaging>=20.0
|
24
|
+
Requires-Dist: HamiltonIO>=0.1.9
|
25
25
|
Requires-Dist: pre-commit
|
26
|
-
Requires-Dist: sympair
|
26
|
+
Requires-Dist: sympair>0.1.0
|
27
|
+
Dynamic: author
|
28
|
+
Dynamic: author-email
|
29
|
+
Dynamic: classifier
|
30
|
+
Dynamic: description
|
31
|
+
Dynamic: license
|
32
|
+
Dynamic: license-file
|
33
|
+
Dynamic: requires-dist
|
34
|
+
Dynamic: requires-python
|
35
|
+
Dynamic: summary
|
27
36
|
|
28
37
|
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.
|
@@ -1,11 +1,11 @@
|
|
1
|
-
TB2J/Jdownfolder.py,sha256=
|
1
|
+
TB2J/Jdownfolder.py,sha256=xs0gmcKwOA3ejXqk3JPPgnYVu8CvkK8cteuvHuu1oSk,9603
|
2
2
|
TB2J/Jtensor.py,sha256=t6OsqrSlYW6Im4H7ykVAW8Al_pFXN4C5yj2UEsV6r7g,3181
|
3
3
|
TB2J/MAE.py,sha256=fM8U-Dgp9HcQOEeC_kyZV1oVrygBvcux9BraUXVouvY,10994
|
4
|
-
TB2J/MAEGreen.py,sha256=
|
4
|
+
TB2J/MAEGreen.py,sha256=pCX12GDNaOz8XgMlui8NjAERM43Ux3HyOKfiD80czXI,15306
|
5
5
|
TB2J/Oiju.py,sha256=cNGv8N5uH_swGq7cnAt2OyiDfqtjLlLrwseGu0E4iaM,3383
|
6
6
|
TB2J/Oiju_epc.py,sha256=oytM3NYW7nWmklrGgNlqwIpI_JYv_hb7ZnR4o9nYNog,6809
|
7
7
|
TB2J/__init__.py,sha256=hcEWkag_UvLm1ZSbjsgcTWkGVlR3Bwmzg1QYAwsvf-g,24
|
8
|
-
TB2J/anisotropy.py,sha256=
|
8
|
+
TB2J/anisotropy.py,sha256=0zmvXkmDmakbBOwGYLa3IIkv5cE99SHLAQJsGoZz7JQ,25463
|
9
9
|
TB2J/basis.py,sha256=DFo6_QUwjBwisP6zGxvoO0lpGTMDPAOkiL9giNCjOjA,1558
|
10
10
|
TB2J/citation.py,sha256=gcQeyJZaT1Qrtsl8Y3s4neOH3-vvgmIcCvXeV2o3vj0,2891
|
11
11
|
TB2J/contour.py,sha256=zLHQZZ3hhgLkLFPATCraLOJyLJKLC0fba_L_5sRz23o,3246
|
@@ -22,7 +22,8 @@ TB2J/greentest.py,sha256=2ISSfhor9ecSEOi_E6b4Cv26wEIQlwlzca0ru8z44_E,1603
|
|
22
22
|
TB2J/io_merge.py,sha256=E1_GfAB2HGpW-ipaO2lqU9SvaslwkiLxssn4DqJpMT8,6899
|
23
23
|
TB2J/kpoints.py,sha256=9L7tBarFBHoIhpuc9zuwA6HdnlgH834SQrPek4yRoWk,3191
|
24
24
|
TB2J/myTB.py,sha256=ok_B4my29bOIghMSZfx0Es6G8FaXaIiLP4gPxTdSj00,17659
|
25
|
-
TB2J/mycfr.py,sha256=
|
25
|
+
TB2J/mycfr.py,sha256=ZF1PEE2khlKd_4gPyMkoNXepX3XqwWAL2kDbRJNVX-Y,3908
|
26
|
+
TB2J/orbital_magmom.py,sha256=JTwO9ZDgRRQndqR9aFIua4eTvwLMoGsTiY_HaIPMZ2I,889
|
26
27
|
TB2J/orbmap.py,sha256=XLQjKMxCy2eADaM5eb2F_zG08V7lzpXJxp5uEtTeVYI,7194
|
27
28
|
TB2J/pauli.py,sha256=ESpAhk6LG5ugzuW1YFUTqiDxcg-pQ7wNnzR2FtUnvKM,5295
|
28
29
|
TB2J/pert.py,sha256=RaCJfewl0doht4cjAnzzGKe-uj2le4aqe0iPKFrq9fo,1192
|
@@ -32,6 +33,7 @@ TB2J/rotate_siestaDM.py,sha256=eR97rspdrRaK9YTwQwUKfobI0S9UnEcbEZ2f5IgR7Tk,1070
|
|
32
33
|
TB2J/sisl_wrapper.py,sha256=A5x1-tt8efUSPeGY5wM5m6-pJYQFXTCzQHVqD6RBa2g,14792
|
33
34
|
TB2J/symmetrize_J.py,sha256=IypvLL0JxExq-cmqc4o0nLL8psE7OC9ijj9YMcsqJeA,4487
|
34
35
|
TB2J/tensor_rotate.py,sha256=4-DfT_Mg5e40fbd74M5W0D5DqmUq-kVOOLDkkkI834A,8083
|
36
|
+
TB2J/thetaphi.py,sha256=Z7N3EOSM7rjHd7b9HxMYLPQO__uR0VwEiV9b471Yudc,399
|
35
37
|
TB2J/utest.py,sha256=z_ahi7tpHQF9WlHNQihcQ7qzfezRJQXQt28eB1X_z64,3897
|
36
38
|
TB2J/utils.py,sha256=DHkc7BK0KUGesfoAv1OxMgIw_iZzcFXh--3ybsFSd_c,12535
|
37
39
|
TB2J/versioninfo.py,sha256=atoCpy6lEcGTCC3xahrxEJjoHgoYVtL41Q_3Ryvp76I,338
|
@@ -41,7 +43,7 @@ TB2J/interfaces/__init__.py,sha256=4tiLoXQ73Nlyi9L4j8jJXOYzXluVNPxQZkwfkQZEGHg,3
|
|
41
43
|
TB2J/interfaces/gpaw_interface.py,sha256=GCDlJ-hRWfChvWwsgBDYSmVqO4sH9HAuGZTV9GqgN6c,1504
|
42
44
|
TB2J/interfaces/lawaf_interface.py,sha256=PieLnmppdafOYsgeHznqOou1g9L1sam5jOm3KaObdqo,4408
|
43
45
|
TB2J/interfaces/manager.py,sha256=PQMLEfMCT5GnDWSl2nI4JOgRPm_fysyR-6Y6l97xWcw,860
|
44
|
-
TB2J/interfaces/siesta_interface.py,sha256=
|
46
|
+
TB2J/interfaces/siesta_interface.py,sha256=olvo2xdBOSNk3zn67nuKrxbW--EKPoWwEzKRBwJbrVY,7366
|
45
47
|
TB2J/interfaces/wannier90_interface.py,sha256=qzRgXUBb7t1Aiegrl_RV51BB8csdtVM0EP0Z4pjmTcs,4467
|
46
48
|
TB2J/interfaces/abacus/__init__.py,sha256=leas71oCvM_HxrF4gnO5A_VKcJmDAgsI1BUctLU3OBw,177
|
47
49
|
TB2J/interfaces/abacus/abacus_api.py,sha256=lNV4LNkLcKw7Zux4MQYM9wnh3eFTlcSqbf4Pb7pqhrk,7243
|
@@ -53,7 +55,7 @@ TB2J/interfaces/abacus/test_density_matrix.py,sha256=bMWWJYtDS57SpPZ-eZXZ9Hr_UK4
|
|
53
55
|
TB2J/interfaces/abacus/test_read_HRSR.py,sha256=W1oO_yigT50Yb5_u-KB_IfTpM7kArGkBuMSMs0H4CTs,1235
|
54
56
|
TB2J/interfaces/abacus/test_read_stru.py,sha256=hoKPHVco8vwzC7Gao4bOPCdAPhh29x-9DTJJqRr7AYM,788
|
55
57
|
TB2J/io_exchange/__init__.py,sha256=KfGHum7B8E4G_KKfillqw0lErtoyKEuFUUttHLs-mg4,32
|
56
|
-
TB2J/io_exchange/io_exchange.py,sha256=
|
58
|
+
TB2J/io_exchange/io_exchange.py,sha256=gaT0fXD3EzPsMgE_VX9gvcf7nEGY3KVYN8xxTAPzxc0,20120
|
57
59
|
TB2J/io_exchange/io_multibinit.py,sha256=8PDmWxzGuv-GwJosj2ZTmiyNY_duFVWJ4ekCuSqGdd8,6739
|
58
60
|
TB2J/io_exchange/io_tomsasd.py,sha256=NqkAC1Fl-CUnFA21eBzSy_S5F_oeQFJysw4UukQbN8o,4173
|
59
61
|
TB2J/io_exchange/io_txt.py,sha256=BMr1eSILlKpgtjvDx7uw2VMAkEKSvGEPNxpaT_zev0I,10547
|
@@ -61,6 +63,7 @@ TB2J/io_exchange/io_uppasd.py,sha256=bI4iPEgnK4TvCZNvb6x2xYXgjW7pEehCqmcizy2pqFU
|
|
61
63
|
TB2J/io_exchange/io_vampire.py,sha256=UllC4twf06_q2vBCnAYFzEDGvS8mSefwQXDquBuyc0M,5583
|
62
64
|
TB2J/mathutils/__init__.py,sha256=tQLBfHkZqdVfVxPOahy42qMUkFYnFFFhM-uc4QsYFxI,27
|
63
65
|
TB2J/mathutils/fermi.py,sha256=72tZ5CptGmYaBUD0xLWltuH7LBXcrMUwODyW6-WqlzI,638
|
66
|
+
TB2J/mathutils/fibonacci_sphere.py,sha256=l0USn25ZCAWF6l4UleyWaeLthsj9TThV9iWmfi6DbaM,2344
|
64
67
|
TB2J/mathutils/kR_convert.py,sha256=p_9XWJVNanTzTK2rI6KRjTkbSq42la6N448-zJOsMwY,2671
|
65
68
|
TB2J/mathutils/lowdin.py,sha256=RYbm9OcnFnjcZFdC5YcNUsI9cOJmoDLsWSSCaP0GqKQ,499
|
66
69
|
TB2J/mathutils/rotate_spin.py,sha256=lbGzve_36FyNjanXqdxYDb102kA4_5OycRlBcm-tH-g,8360
|
@@ -77,19 +80,19 @@ TB2J/spinham/supercell.py,sha256=y17uUC6r3gQb278FhxIW4CABihfLTvKFj6flyXrCPR8,122
|
|
77
80
|
TB2J/wannier/__init__.py,sha256=7ojCbM84PYv1X1Tbo4NHI-d3gWmQsZB_xiYqbfxVV1E,80
|
78
81
|
TB2J/wannier/w90_parser.py,sha256=dbd63LuKyv2DVUzqRINGsbDzEsOxsQyE8_Ear_LQIRg,4620
|
79
82
|
TB2J/wannier/w90_tb_parser.py,sha256=qt8pnuprmPp9iIAYwPkPbmEzk6ZPgMq2xognoQp7vwc,4610
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
83
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_downfold.py,sha256=i4BVqnpDdgrX_amookVWeLGefGBn-qeAutWiwuY9SfQ,2099
|
84
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
|
85
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
|
86
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
|
87
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_merge.py,sha256=y834SF4rIRn1L1ptkhczvavQpC-8Px6DTmDOOSaq_DE,1854
|
88
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_rotate.py,sha256=zgiDFuYZNmzKK0rwDmTaYD2OpRlmKA_VGeBx83w2Xwc,873
|
89
|
+
tb2j-0.9.9rc8.data/scripts/TB2J_rotateDM.py,sha256=kCvF7gotuqAX1VnJ06cwfVm7RrhrdtiV5v7d9P2Pn_E,567
|
90
|
+
tb2j-0.9.9rc8.data/scripts/abacus2J.py,sha256=0HLXoJhAkiZ-ZM1cs26lncccxE8-TzC8JiDTba1h1uM,4163
|
91
|
+
tb2j-0.9.9rc8.data/scripts/siesta2J.py,sha256=gp31LioqpPkDmMY0y_5gXIjOBPNnf080P37pRo0yjw8,4886
|
92
|
+
tb2j-0.9.9rc8.data/scripts/wann2J.py,sha256=pTFDf6h72I_LN_NX5UivyCoJPgwvyAyHW175nSAJvLo,2987
|
93
|
+
tb2j-0.9.9rc8.dist-info/licenses/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
|
94
|
+
tb2j-0.9.9rc8.dist-info/METADATA,sha256=4DDVWc-iAm87VSn60YFm-O15MZY-OpcT0ay_lw_0580,1660
|
95
|
+
tb2j-0.9.9rc8.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91
|
96
|
+
tb2j-0.9.9rc8.dist-info/entry_points.txt,sha256=Hdz1WC9waUzyFVmowKnbbZ6j-J4adHh_Ko6JpxGYAtE,131
|
97
|
+
tb2j-0.9.9rc8.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
|
98
|
+
tb2j-0.9.9rc8.dist-info/RECORD,,
|
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
|