TB2J 0.9.12.9__py3-none-any.whl → 0.9.12.22__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/MAE.py +8 -1
- TB2J/MAEGreen.py +78 -61
- TB2J/contour.py +3 -2
- TB2J/exchange.py +346 -51
- TB2J/exchangeCL2.py +285 -47
- TB2J/exchange_params.py +48 -0
- TB2J/green.py +73 -36
- TB2J/interfaces/abacus/gen_exchange_abacus.py +2 -1
- TB2J/interfaces/wannier90_interface.py +4 -4
- TB2J/io_exchange/__init__.py +19 -1
- TB2J/io_exchange/edit.py +594 -0
- TB2J/io_exchange/io_espins.py +276 -0
- TB2J/io_exchange/io_exchange.py +248 -76
- TB2J/io_exchange/io_tomsasd.py +4 -3
- TB2J/io_exchange/io_txt.py +72 -7
- TB2J/io_exchange/io_vampire.py +4 -2
- TB2J/io_merge.py +60 -40
- TB2J/magnon/magnon3.py +27 -2
- TB2J/mathutils/rotate_spin.py +7 -7
- TB2J/myTB.py +11 -11
- TB2J/mycfr.py +11 -11
- TB2J/pauli.py +32 -2
- TB2J/plot.py +26 -0
- TB2J/rotate_atoms.py +9 -6
- TB2J/scripts/TB2J_edit.py +403 -0
- TB2J/scripts/TB2J_plot_exchange.py +48 -0
- TB2J/spinham/hamiltonian.py +156 -13
- TB2J/spinham/hamiltonian_terms.py +40 -1
- TB2J/spinham/spin_xml.py +40 -8
- TB2J/symmetrize_J.py +140 -9
- TB2J/tests/test_cli_remove_sublattice.py +33 -0
- TB2J/tests/test_cli_toggle_exchange.py +50 -0
- {tb2j-0.9.12.9.dist-info → tb2j-0.9.12.22.dist-info}/METADATA +10 -7
- {tb2j-0.9.12.9.dist-info → tb2j-0.9.12.22.dist-info}/RECORD +38 -34
- {tb2j-0.9.12.9.dist-info → tb2j-0.9.12.22.dist-info}/WHEEL +1 -1
- {tb2j-0.9.12.9.dist-info → tb2j-0.9.12.22.dist-info}/entry_points.txt +2 -0
- TB2J/interfaces/abacus/test_read_HRSR.py +0 -43
- TB2J/interfaces/abacus/test_read_stru.py +0 -32
- {tb2j-0.9.12.9.dist-info → tb2j-0.9.12.22.dist-info}/licenses/LICENSE +0 -0
- {tb2j-0.9.12.9.dist-info → tb2j-0.9.12.22.dist-info}/top_level.txt +0 -0
TB2J/MAE.py
CHANGED
|
@@ -136,7 +136,14 @@ class MAEGreen(MAE):
|
|
|
136
136
|
# occ.occupy(evals)
|
|
137
137
|
efermi = occ.efermi(evals)
|
|
138
138
|
print(f"{efermi=}")
|
|
139
|
-
self.G = TBGreen(
|
|
139
|
+
self.G = TBGreen(
|
|
140
|
+
model,
|
|
141
|
+
kmesh,
|
|
142
|
+
efermi=efermi,
|
|
143
|
+
gamma=gamma,
|
|
144
|
+
smearing_width=self.width,
|
|
145
|
+
**kwargs,
|
|
146
|
+
)
|
|
140
147
|
self.emin = -52
|
|
141
148
|
self.emax = 0
|
|
142
149
|
self.nz = 100
|
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,7 +153,7 @@ 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
158
|
dE_angle_atom_orb = DefaultDict(lambda: 0)
|
|
159
159
|
for iangle, (theta, phi) in enumerate(zip(thetas, phis)):
|
|
@@ -178,23 +178,30 @@ class MAEGreen(ExchangeNCL):
|
|
|
178
178
|
# dE_angle[iangle] += np.trace(GdH@GdH) * self.G.kweights[ik]
|
|
179
179
|
# dE_angle[iangle] += np.trace(GdH@G0K[ik].T.conj()@dHi ) * self.G.kweights[ik]
|
|
180
180
|
dE_angle[iangle] += dG2sum * self.G.kweights[ik]
|
|
181
|
+
|
|
182
|
+
# Calculate atom-atom matrix interactions
|
|
181
183
|
for iatom in range(self.natoms):
|
|
182
184
|
iorb = self.iorb(iatom)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
|
198
205
|
|
|
199
206
|
def get_perturbed_R(self, e, thetas, phis):
|
|
200
207
|
self.tbmodel.set_so_strength(0.0)
|
|
@@ -232,16 +239,16 @@ class MAEGreen(ExchangeNCL):
|
|
|
232
239
|
npole = len(self.contour.path)
|
|
233
240
|
results = map(func, tqdm.tqdm(self.contour.path, total=npole))
|
|
234
241
|
for i, result in enumerate(results):
|
|
235
|
-
dE_angle,
|
|
242
|
+
dE_angle, dE_angle_matrix, dE_angle_atom_orb = result
|
|
236
243
|
self.es += dE_angle * self.contour.weights[i]
|
|
237
|
-
self.
|
|
244
|
+
self.es_matrix += dE_angle_matrix * self.contour.weights[i]
|
|
238
245
|
for key, value in dE_angle_atom_orb.items():
|
|
239
246
|
self.es_atom_orb[key] += (
|
|
240
247
|
dE_angle_atom_orb[key] * self.contour.weights[i]
|
|
241
248
|
)
|
|
242
249
|
|
|
243
250
|
self.es = -np.imag(self.es) / (2 * np.pi)
|
|
244
|
-
self.
|
|
251
|
+
self.es_matrix = -np.imag(self.es_matrix) / (2 * np.pi)
|
|
245
252
|
for key, value in self.es_atom_orb.items():
|
|
246
253
|
self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
|
|
247
254
|
|
|
@@ -259,6 +266,7 @@ class MAEGreen(ExchangeNCL):
|
|
|
259
266
|
Path(output_path).mkdir(exist_ok=True)
|
|
260
267
|
fname = f"{output_path}/MAE.dat"
|
|
261
268
|
fname_orb = f"{output_path}/MAE_orb.dat"
|
|
269
|
+
fname_matrix = f"{output_path}/MAE_matrix.dat"
|
|
262
270
|
# fname_tensor = f"{output_path}/MAE_tensor.dat"
|
|
263
271
|
# if figure3d is not None:
|
|
264
272
|
# fname_fig3d = f"{output_path}/{figure3d}"
|
|
@@ -269,24 +277,32 @@ class MAEGreen(ExchangeNCL):
|
|
|
269
277
|
if with_eigen:
|
|
270
278
|
fname_eigen = f"{output_path}/MAE_eigen.dat"
|
|
271
279
|
with open(fname_eigen, "w") as f:
|
|
272
|
-
f.write("# theta, phi, MAE(total)
|
|
273
|
-
for i, (theta, phi, e
|
|
274
|
-
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)
|
|
275
283
|
):
|
|
276
|
-
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f}
|
|
277
|
-
for ea in es:
|
|
278
|
-
f.write(f"{ea*1e3:.8f} ")
|
|
279
|
-
f.write("\n")
|
|
284
|
+
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f}\n")
|
|
280
285
|
|
|
281
286
|
with open(fname, "w") as f:
|
|
282
|
-
f.write("# theta (rad), phi(rad), MAE(total)
|
|
283
|
-
for i, (theta, phi, e
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
|
290
306
|
|
|
291
307
|
# self.ani = self.fit_anisotropy_tensor()
|
|
292
308
|
# with open(fname_tensor, "w") as f:
|
|
@@ -312,34 +328,37 @@ class MAEGreen(ExchangeNCL):
|
|
|
312
328
|
for orb in self.orbital_names[iatom]:
|
|
313
329
|
f.write(f"{orb} ")
|
|
314
330
|
f.write("\n")
|
|
315
|
-
for i, (theta, phi, e
|
|
316
|
-
zip(self.thetas, self.phis, self.es, self.es_atom)
|
|
317
|
-
):
|
|
331
|
+
for i, (theta, phi, e) in enumerate(zip(self.thetas, self.phis, self.es)):
|
|
318
332
|
f.write("-" * 60 + "\n")
|
|
319
333
|
f.write(f"Angle {i:03d}: theta={theta:.5f} phi={phi:.5f} \n ")
|
|
320
334
|
f.write(f"E: {e*1e3:.8f} \n")
|
|
321
|
-
for iatom
|
|
322
|
-
f.write(f"Atom {iatom:03d}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
eorb_diff = eorb - self.es_atom_orb[(0, iatom)]
|
|
334
|
-
f.write("Diference to the first angle: ")
|
|
335
|
-
f.write(
|
|
336
|
-
np.array2string(
|
|
337
|
-
eorb_diff * 1e3,
|
|
338
|
-
precision=4,
|
|
339
|
-
separator=",",
|
|
340
|
-
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
|
+
)
|
|
341
347
|
)
|
|
342
|
-
|
|
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")
|
|
343
362
|
f.write("\n")
|
|
344
363
|
|
|
345
364
|
def run(self, output_path="TB2J_anisotropy", with_eigen=False):
|
|
@@ -355,7 +374,6 @@ def abacus_get_MAE(
|
|
|
355
374
|
phis,
|
|
356
375
|
gamma=True,
|
|
357
376
|
output_path="TB2J_anisotropy",
|
|
358
|
-
magnetic_elements=None,
|
|
359
377
|
nel=None,
|
|
360
378
|
width=0.1,
|
|
361
379
|
with_eigen=False,
|
|
@@ -376,7 +394,6 @@ def abacus_get_MAE(
|
|
|
376
394
|
efermi=None,
|
|
377
395
|
basis=model.basis,
|
|
378
396
|
angles=[thetas, phis],
|
|
379
|
-
magnetic_elements=magnetic_elements,
|
|
380
397
|
**kwargs,
|
|
381
398
|
)
|
|
382
399
|
mae.run(output_path=output_path, with_eigen=with_eigen)
|
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):
|