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 ADDED
@@ -0,0 +1,5 @@
1
+ *.o
2
+ *.x
3
+ *.mod
4
+ exchanges.sublime-project
5
+ exchanges.sublime-workspace
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 * 3
51
- self.nLn = self.nL * 3
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=True,
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.es_atom = np.zeros((nangles, self.natoms), dtype=complex)
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
- dE_angle_atom = np.zeros((na, self.natoms), dtype=complex)
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
- # dG2= dG2[::2, ::2] + dG2[1::2, 1::2] + dG2[1::2, ::2] + dG2[::2, 1::2]
185
- dE_atom_orb = dG2[np.ix_(iorb, iorb)] * self.G.kweights[ik]
186
- dE_atom_orb = (
187
- dE_atom_orb[::2, ::2]
188
- + dE_atom_orb[1::2, 1::2]
189
- + dE_atom_orb[1::2, ::2]
190
- + dE_atom_orb[::2, 1::2]
191
- )
192
- dE_atom = np.sum(dE_atom_orb)
193
- mmat = self.mmats[iatom]
194
- dE_atom_orb = mmat.T @ dE_atom_orb @ mmat
195
- dE_angle_atom_orb[(iangle, iatom)] += dE_atom_orb
196
- # dE_atom = np.sum(dG2diag[iorb]) * self.G.kweights[ik]
197
- dE_angle_atom[iangle, iatom] += dE_atom
198
- return dE_angle, dE_angle_atom, dE_angle_atom_orb
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, dE_angle_atom, dE_angle_atom_orb = result
242
+ dE_angle, dE_angle_matrix, dE_angle_atom_orb = result
237
243
  self.es += dE_angle * self.contour.weights[i]
238
- self.es_atom += dE_angle_atom * self.contour.weights[i]
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.es_atom = -np.imag(self.es_atom) / (2 * np.pi)
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), MAE(atom-wise) Unit: meV\n")
274
- for i, (theta, phi, e, es) in enumerate(
275
- zip(self.thetas, self.phis, self.es2, self.es_atom)
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), MAE(atom-wise) Unit: meV\n")
284
- for i, (theta, phi, e, es) in enumerate(
285
- zip(self.thetas, self.phis, self.es, self.es_atom)
286
- ):
287
- f.write(f"{theta%np.pi:.5f} {phi%(2*np.pi):.5f} {e*1e3:.8f} ")
288
- for ea in es:
289
- f.write(f"{ea*1e3:.8f} ")
290
- f.write("\n")
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, eatom) in enumerate(
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, ea in enumerate(eatom):
323
- f.write(f"Atom {iatom:03d}: {ea*1e3:.8f} \n")
324
- f.write("Orbital: ")
325
- eorb = self.es_atom_orb[(i, iatom)]
326
-
327
- # write numpy matrix to file
328
- f.write(
329
- np.array2string(
330
- eorb * 1e3, precision=4, separator=",", suppress_small=True
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
@@ -1 +1,3 @@
1
+ import importlib.metadata
1
2
 
3
+ __version__ = importlib.metadata.version("TB2J")
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
@@ -3,10 +3,7 @@
3
3
  """
4
4
  class for basis set
5
5
  """
6
- from typing import Any
7
- import numpy as np
8
6
  import dataclasses
9
- from TB2J.utils import symbol_number
10
7
 
11
8
 
12
9
  @dataclasses.dataclass
TB2J/contour.py CHANGED
@@ -27,8 +27,9 @@ class Contour:
27
27
  integrate f along the path
28
28
  """
29
29
  ret = 0
30
- for i in range(len(values)):
31
- ret += values[i] * self.weights[i]
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):