TB2J 0.9.12.6__py3-none-any.whl → 0.9.12.17__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.
Potentially problematic release.
This version of TB2J might be problematic. Click here for more details.
- TB2J/.gitignore +5 -0
- TB2J/Jdownfolder.py +4 -3
- TB2J/MAEGreen.py +78 -60
- TB2J/__init__.py +2 -0
- TB2J/anisotropy.py +2 -2
- TB2J/basis.py +0 -3
- TB2J/contour.py +3 -2
- TB2J/exchange.py +335 -47
- TB2J/exchangeCL2.py +283 -47
- TB2J/exchange_params.py +24 -0
- TB2J/gpaw_wrapper.py +0 -3
- TB2J/green.py +58 -33
- TB2J/interfaces/wannier90_interface.py +4 -4
- TB2J/io_exchange/io_espins.py +276 -0
- TB2J/io_exchange/io_exchange.py +11 -3
- TB2J/io_exchange/io_uppasd.py +0 -1
- TB2J/io_exchange/io_vampire.py +3 -1
- TB2J/myTB.py +11 -11
- TB2J/pauli.py +32 -2
- TB2J/plot.py +8 -7
- TB2J/rotate_atoms.py +10 -7
- TB2J/spinham/hamiltonian.py +0 -1
- TB2J/symmetrize_J.py +2 -2
- TB2J/tensor_rotate.py +1 -2
- TB2J/wannier/w90_tb_parser.py +0 -2
- {tb2j-0.9.12.6.dist-info → tb2j-0.9.12.17.dist-info}/METADATA +7 -7
- {tb2j-0.9.12.6.dist-info → tb2j-0.9.12.17.dist-info}/RECORD +31 -29
- {tb2j-0.9.12.6.dist-info → tb2j-0.9.12.17.dist-info}/WHEEL +0 -0
- {tb2j-0.9.12.6.dist-info → tb2j-0.9.12.17.dist-info}/entry_points.txt +0 -0
- {tb2j-0.9.12.6.dist-info → tb2j-0.9.12.17.dist-info}/licenses/LICENSE +0 -0
- {tb2j-0.9.12.6.dist-info → tb2j-0.9.12.17.dist-info}/top_level.txt +0 -0
TB2J/.gitignore
ADDED
TB2J/Jdownfolder.py
CHANGED
|
@@ -47,8 +47,8 @@ class JDownfolder:
|
|
|
47
47
|
self.qmesh = qmesh
|
|
48
48
|
self.qpts = monkhorst_pack(qmesh)
|
|
49
49
|
self.nqpt = len(self.qpts)
|
|
50
|
-
self.nMn = self.nM *
|
|
51
|
-
self.nLn = self.nL *
|
|
50
|
+
self.nMn = self.nM * self.nxyz
|
|
51
|
+
self.nLn = self.nL * self.nxyz
|
|
52
52
|
self.iso_only = iso_only
|
|
53
53
|
|
|
54
54
|
def get_JR(self):
|
|
@@ -62,6 +62,7 @@ class JDownfolder:
|
|
|
62
62
|
for iR, R in enumerate(self.Rlist):
|
|
63
63
|
phase = np.exp(-2.0j * np.pi * np.dot(q, R))
|
|
64
64
|
JR_downfolded[iR] += np.real(Jq_downfolded[iq] * phase / self.nqpt)
|
|
65
|
+
return JR_downfolded, self.Rlist
|
|
65
66
|
|
|
66
67
|
def downfold_oneq(self, J):
|
|
67
68
|
JMM = J[np.ix_(self.iMn, self.iMn)]
|
|
@@ -121,7 +122,7 @@ class PWFDownfolder:
|
|
|
121
122
|
marker="o",
|
|
122
123
|
ax=None,
|
|
123
124
|
savefig="downfold_band.png",
|
|
124
|
-
show=
|
|
125
|
+
show=False,
|
|
125
126
|
)
|
|
126
127
|
self.JR_downfolded = ewf.HwannR
|
|
127
128
|
self.Rlist = ewf.Rlist
|
TB2J/MAEGreen.py
CHANGED
|
@@ -51,7 +51,7 @@ class MAEGreen(ExchangeNCL):
|
|
|
51
51
|
|
|
52
52
|
nangles = len(self.thetas)
|
|
53
53
|
self.es = np.zeros(nangles, dtype=complex)
|
|
54
|
-
self.
|
|
54
|
+
self.es_matrix = np.zeros((nangles, self.natoms, self.natoms), dtype=complex)
|
|
55
55
|
self.es_atom_orb = DefaultDict(lambda: 0)
|
|
56
56
|
|
|
57
57
|
def set_angles_xyz(self):
|
|
@@ -153,9 +153,8 @@ class MAEGreen(ExchangeNCL):
|
|
|
153
153
|
Hsoc_k = self.tbmodel.get_Hk_soc(self.G.kpts)
|
|
154
154
|
na = len(thetas)
|
|
155
155
|
dE_angle = np.zeros(na, dtype=complex)
|
|
156
|
-
|
|
156
|
+
dE_angle_matrix = np.zeros((na, self.natoms, self.natoms), dtype=complex)
|
|
157
157
|
# dE_angle_orbitals = np.zeros((na, self.natoms, self.norb, self.norb), dtype=complex)
|
|
158
|
-
# dE_angle_orbitals = DefaultDict(lambda: 0)
|
|
159
158
|
dE_angle_atom_orb = DefaultDict(lambda: 0)
|
|
160
159
|
for iangle, (theta, phi) in enumerate(zip(thetas, phis)):
|
|
161
160
|
for ik, dHk in enumerate(Hsoc_k):
|
|
@@ -179,23 +178,30 @@ class MAEGreen(ExchangeNCL):
|
|
|
179
178
|
# dE_angle[iangle] += np.trace(GdH@GdH) * self.G.kweights[ik]
|
|
180
179
|
# dE_angle[iangle] += np.trace(GdH@G0K[ik].T.conj()@dHi ) * self.G.kweights[ik]
|
|
181
180
|
dE_angle[iangle] += dG2sum * self.G.kweights[ik]
|
|
181
|
+
|
|
182
|
+
# Calculate atom-atom matrix interactions
|
|
182
183
|
for iatom in range(self.natoms):
|
|
183
184
|
iorb = self.iorb(iatom)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
185
|
+
for jatom in range(self.natoms):
|
|
186
|
+
jorb = self.iorb(jatom)
|
|
187
|
+
# Calculate cross terms between atoms i and j
|
|
188
|
+
dE_ij_orb = dG2[np.ix_(iorb, jorb)] * self.G.kweights[ik]
|
|
189
|
+
dE_ij_orb = (
|
|
190
|
+
dE_ij_orb[::2, ::2]
|
|
191
|
+
+ dE_ij_orb[1::2, 1::2]
|
|
192
|
+
+ dE_ij_orb[1::2, ::2]
|
|
193
|
+
+ dE_ij_orb[::2, 1::2]
|
|
194
|
+
)
|
|
195
|
+
dE_ij = np.sum(dE_ij_orb)
|
|
196
|
+
# Transform to local orbital basis
|
|
197
|
+
mmat_i = self.mmats[iatom]
|
|
198
|
+
mmat_j = self.mmats[jatom]
|
|
199
|
+
dE_ij_orb = mmat_i.T @ dE_ij_orb @ mmat_j
|
|
200
|
+
dE_angle_matrix[iangle, iatom, jatom] += dE_ij
|
|
201
|
+
# Store orbital-resolved data for diagonal terms
|
|
202
|
+
if iatom == jatom:
|
|
203
|
+
dE_angle_atom_orb[(iangle, iatom)] += dE_ij_orb
|
|
204
|
+
return dE_angle, dE_angle_matrix, dE_angle_atom_orb
|
|
199
205
|
|
|
200
206
|
def get_perturbed_R(self, e, thetas, phis):
|
|
201
207
|
self.tbmodel.set_so_strength(0.0)
|
|
@@ -233,16 +239,16 @@ class MAEGreen(ExchangeNCL):
|
|
|
233
239
|
npole = len(self.contour.path)
|
|
234
240
|
results = map(func, tqdm.tqdm(self.contour.path, total=npole))
|
|
235
241
|
for i, result in enumerate(results):
|
|
236
|
-
dE_angle,
|
|
242
|
+
dE_angle, dE_angle_matrix, dE_angle_atom_orb = result
|
|
237
243
|
self.es += dE_angle * self.contour.weights[i]
|
|
238
|
-
self.
|
|
244
|
+
self.es_matrix += dE_angle_matrix * self.contour.weights[i]
|
|
239
245
|
for key, value in dE_angle_atom_orb.items():
|
|
240
246
|
self.es_atom_orb[key] += (
|
|
241
247
|
dE_angle_atom_orb[key] * self.contour.weights[i]
|
|
242
248
|
)
|
|
243
249
|
|
|
244
250
|
self.es = -np.imag(self.es) / (2 * np.pi)
|
|
245
|
-
self.
|
|
251
|
+
self.es_matrix = -np.imag(self.es_matrix) / (2 * np.pi)
|
|
246
252
|
for key, value in self.es_atom_orb.items():
|
|
247
253
|
self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
|
|
248
254
|
|
|
@@ -260,6 +266,7 @@ class MAEGreen(ExchangeNCL):
|
|
|
260
266
|
Path(output_path).mkdir(exist_ok=True)
|
|
261
267
|
fname = f"{output_path}/MAE.dat"
|
|
262
268
|
fname_orb = f"{output_path}/MAE_orb.dat"
|
|
269
|
+
fname_matrix = f"{output_path}/MAE_matrix.dat"
|
|
263
270
|
# fname_tensor = f"{output_path}/MAE_tensor.dat"
|
|
264
271
|
# if figure3d is not None:
|
|
265
272
|
# fname_fig3d = f"{output_path}/{figure3d}"
|
|
@@ -270,24 +277,32 @@ class MAEGreen(ExchangeNCL):
|
|
|
270
277
|
if with_eigen:
|
|
271
278
|
fname_eigen = f"{output_path}/MAE_eigen.dat"
|
|
272
279
|
with open(fname_eigen, "w") as f:
|
|
273
|
-
f.write("# theta, phi, MAE(total)
|
|
274
|
-
for i, (theta, phi, e
|
|
275
|
-
zip(self.thetas, self.phis, self.es2
|
|
280
|
+
f.write("# theta, phi, MAE(total) Unit: meV\n")
|
|
281
|
+
for i, (theta, phi, e) in enumerate(
|
|
282
|
+
zip(self.thetas, self.phis, self.es2)
|
|
276
283
|
):
|
|
277
|
-
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f}
|
|
278
|
-
for ea in es:
|
|
279
|
-
f.write(f"{ea*1e3:.8f} ")
|
|
280
|
-
f.write("\n")
|
|
284
|
+
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f}\n")
|
|
281
285
|
|
|
282
286
|
with open(fname, "w") as f:
|
|
283
|
-
f.write("# theta (rad), phi(rad), MAE(total)
|
|
284
|
-
for i, (theta, phi, e
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
287
|
+
f.write("# theta (rad), phi(rad), MAE(total) Unit: meV\n")
|
|
288
|
+
for i, (theta, phi, e) in enumerate(zip(self.thetas, self.phis, self.es)):
|
|
289
|
+
f.write(f"{theta%np.pi:.5f} {phi%(2*np.pi):.5f} {e*1e3:.8f}\n")
|
|
290
|
+
|
|
291
|
+
# Write matrix data to MAE_matrix.dat
|
|
292
|
+
with open(fname_matrix, "w") as fmat:
|
|
293
|
+
fmat.write("# MAE atom-atom interaction matrices\n")
|
|
294
|
+
fmat.write("# Format: angle_index theta phi atom_i atom_j MAE_ij(meV)\n")
|
|
295
|
+
fmat.write("# Units: theta and phi in radians, MAE in meV\n")
|
|
296
|
+
for iangle, (theta, phi) in enumerate(zip(self.thetas, self.phis)):
|
|
297
|
+
for iatom in range(self.natoms):
|
|
298
|
+
for jatom in range(self.natoms):
|
|
299
|
+
mae_ij = (
|
|
300
|
+
self.es_matrix[iangle, iatom, jatom] * 1e3
|
|
301
|
+
) # Convert to meV
|
|
302
|
+
fmat.write(
|
|
303
|
+
f"{iangle:4d} {theta:.5f} {phi:.5f} {iatom:4d} {jatom:4d} {mae_ij:.8f}\n"
|
|
304
|
+
)
|
|
305
|
+
fmat.write("\n") # Empty line between angles for readability
|
|
291
306
|
|
|
292
307
|
# self.ani = self.fit_anisotropy_tensor()
|
|
293
308
|
# with open(fname_tensor, "w") as f:
|
|
@@ -313,34 +328,37 @@ class MAEGreen(ExchangeNCL):
|
|
|
313
328
|
for orb in self.orbital_names[iatom]:
|
|
314
329
|
f.write(f"{orb} ")
|
|
315
330
|
f.write("\n")
|
|
316
|
-
for i, (theta, phi, e
|
|
317
|
-
zip(self.thetas, self.phis, self.es, self.es_atom)
|
|
318
|
-
):
|
|
331
|
+
for i, (theta, phi, e) in enumerate(zip(self.thetas, self.phis, self.es)):
|
|
319
332
|
f.write("-" * 60 + "\n")
|
|
320
333
|
f.write(f"Angle {i:03d}: theta={theta:.5f} phi={phi:.5f} \n ")
|
|
321
334
|
f.write(f"E: {e*1e3:.8f} \n")
|
|
322
|
-
for iatom
|
|
323
|
-
f.write(f"Atom {iatom:03d}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
eorb_diff = eorb - self.es_atom_orb[(0, iatom)]
|
|
335
|
-
f.write("Diference to the first angle: ")
|
|
336
|
-
f.write(
|
|
337
|
-
np.array2string(
|
|
338
|
-
eorb_diff * 1e3,
|
|
339
|
-
precision=4,
|
|
340
|
-
separator=",",
|
|
341
|
-
suppress_small=True,
|
|
335
|
+
for iatom in range(self.natoms):
|
|
336
|
+
f.write(f"Atom {iatom:03d} orbital matrix:\n")
|
|
337
|
+
if (i, iatom) in self.es_atom_orb:
|
|
338
|
+
eorb = self.es_atom_orb[(i, iatom)]
|
|
339
|
+
# write numpy matrix to file
|
|
340
|
+
f.write(
|
|
341
|
+
np.array2string(
|
|
342
|
+
eorb * 1e3,
|
|
343
|
+
precision=4,
|
|
344
|
+
separator=",",
|
|
345
|
+
suppress_small=True,
|
|
346
|
+
)
|
|
342
347
|
)
|
|
343
|
-
|
|
348
|
+
f.write("\n")
|
|
349
|
+
|
|
350
|
+
if (0, iatom) in self.es_atom_orb:
|
|
351
|
+
eorb_diff = eorb - self.es_atom_orb[(0, iatom)]
|
|
352
|
+
f.write("Difference to the first angle: ")
|
|
353
|
+
f.write(
|
|
354
|
+
np.array2string(
|
|
355
|
+
eorb_diff * 1e3,
|
|
356
|
+
precision=4,
|
|
357
|
+
separator=",",
|
|
358
|
+
suppress_small=True,
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
f.write("\n")
|
|
344
362
|
f.write("\n")
|
|
345
363
|
|
|
346
364
|
def run(self, output_path="TB2J_anisotropy", with_eigen=False):
|
TB2J/__init__.py
CHANGED
TB2J/anisotropy.py
CHANGED
|
@@ -339,8 +339,8 @@ class Anisotropy:
|
|
|
339
339
|
# print(X_max, Y_max, X_min, Y_min)
|
|
340
340
|
# ax.scatter(X_max, Y_max, color="r", marker="o")
|
|
341
341
|
# ax.scatter(X_min, Y_min, color="b", marker="o")
|
|
342
|
-
ax.set_xlabel("$\theta$ (degree)")
|
|
343
|
-
ax.set_ylabel("$\phi$ degree")
|
|
342
|
+
ax.set_xlabel(r"$\theta$ (degree)")
|
|
343
|
+
ax.set_ylabel(r"$\phi$ degree")
|
|
344
344
|
# ax.scatter(X_max, Y_max, color="r", marker="o")
|
|
345
345
|
# ax.scatter(X_min, Y_min, color="r", marker="o")
|
|
346
346
|
|
TB2J/basis.py
CHANGED
TB2J/contour.py
CHANGED
|
@@ -27,8 +27,9 @@ class Contour:
|
|
|
27
27
|
integrate f along the path
|
|
28
28
|
"""
|
|
29
29
|
ret = 0
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
ret = np.einsum("i...,i->...", values, self.weights)
|
|
31
|
+
# for i in range(len(values)):
|
|
32
|
+
# ret += values[i] * self.weights[i]
|
|
32
33
|
return ret
|
|
33
34
|
|
|
34
35
|
def build_path_semicircle(self, npoints, endpoint=True):
|