TB2J 0.9.9rc5__tar.gz → 0.9.9rc6__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.
Files changed (100) hide show
  1. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/PKG-INFO +1 -1
  2. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/MAEGreen.py +37 -7
  3. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/contour.py +16 -0
  4. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/exchange.py +23 -15
  5. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/exchangeCL2.py +20 -11
  6. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/exchange_params.py +8 -0
  7. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/green.py +15 -1
  8. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/siesta_interface.py +1 -1
  9. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/kpoints.py +15 -1
  10. tb2j-0.9.9rc6/TB2J/mycfr.py +114 -0
  11. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/orbmap.py +4 -4
  12. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/symmetrize_J.py +4 -2
  13. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J.egg-info/PKG-INFO +1 -1
  14. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J.egg-info/SOURCES.txt +1 -0
  15. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/setup.py +1 -1
  16. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/LICENSE +0 -0
  17. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/README.md +0 -0
  18. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/Jdownfolder.py +0 -0
  19. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/Jtensor.py +0 -0
  20. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/MAE.py +0 -0
  21. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/Oiju.py +0 -0
  22. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/Oiju_epc.py +0 -0
  23. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/__init__.py +0 -0
  24. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/anisotropy.py +0 -0
  25. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/basis.py +0 -0
  26. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/citation.py +0 -0
  27. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/density_matrix.py +0 -0
  28. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/epc.py +0 -0
  29. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/exchange_pert.py +0 -0
  30. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/exchange_qspace.py +0 -0
  31. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/external/__init__.py +0 -0
  32. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/external/p_tqdm.py +0 -0
  33. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/gpaw_wrapper.py +0 -0
  34. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/greentest.py +0 -0
  35. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/__init__.py +0 -0
  36. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/__init__.py +0 -0
  37. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/abacus_api.py +0 -0
  38. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/abacus_wrapper.py +0 -0
  39. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/gen_exchange_abacus.py +0 -0
  40. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/orbital_api.py +0 -0
  41. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/stru_api.py +0 -0
  42. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/test_density_matrix.py +0 -0
  43. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/test_read_HRSR.py +0 -0
  44. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/abacus/test_read_stru.py +0 -0
  45. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/gpaw_interface.py +0 -0
  46. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/lawaf_interface.py +0 -0
  47. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/manager.py +0 -0
  48. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/interfaces/wannier90_interface.py +0 -0
  49. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/__init__.py +0 -0
  50. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_exchange.py +0 -0
  51. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_multibinit.py +0 -0
  52. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_tomsasd.py +0 -0
  53. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_txt.py +0 -0
  54. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_uppasd.py +0 -0
  55. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_exchange/io_vampire.py +0 -0
  56. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/io_merge.py +0 -0
  57. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/mathutils/__init__.py +0 -0
  58. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/mathutils/fermi.py +0 -0
  59. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/mathutils/kR_convert.py +0 -0
  60. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/mathutils/lowdin.py +0 -0
  61. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/mathutils/rotate_spin.py +0 -0
  62. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/myTB.py +0 -0
  63. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/pauli.py +0 -0
  64. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/pert.py +0 -0
  65. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/plot.py +0 -0
  66. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/rotate_atoms.py +0 -0
  67. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/rotate_siestaDM.py +0 -0
  68. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/sisl_wrapper.py +0 -0
  69. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/__init__.py +0 -0
  70. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/base_parser.py +0 -0
  71. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/constants.py +0 -0
  72. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/hamiltonian.py +0 -0
  73. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/hamiltonian_terms.py +0 -0
  74. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/plot.py +0 -0
  75. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/qsolver.py +0 -0
  76. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/spin_api.py +0 -0
  77. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/spin_xml.py +0 -0
  78. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/spinham/supercell.py +0 -0
  79. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/tensor_rotate.py +0 -0
  80. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/utest.py +0 -0
  81. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/utils.py +0 -0
  82. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/versioninfo.py +0 -0
  83. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/wannier/__init__.py +0 -0
  84. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/wannier/w90_parser.py +0 -0
  85. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J/wannier/w90_tb_parser.py +0 -0
  86. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J.egg-info/dependency_links.txt +0 -0
  87. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J.egg-info/entry_points.txt +0 -0
  88. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J.egg-info/requires.txt +0 -0
  89. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/TB2J.egg-info/top_level.txt +0 -0
  90. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_downfold.py +0 -0
  91. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_eigen.py +0 -0
  92. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_magnon.py +0 -0
  93. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_magnon_dos.py +0 -0
  94. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_merge.py +0 -0
  95. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_rotate.py +0 -0
  96. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/TB2J_rotateDM.py +0 -0
  97. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/abacus2J.py +0 -0
  98. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/siesta2J.py +0 -0
  99. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/scripts/wann2J.py +0 -0
  100. {tb2j-0.9.9rc5 → tb2j-0.9.9rc6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.9.9rc5
3
+ Version: 0.9.9rc6
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
@@ -7,6 +7,7 @@ from HamiltonIO.model.occupations import GaussOccupations
7
7
  from typing_extensions import DefaultDict
8
8
 
9
9
  from TB2J.exchange import ExchangeNCL
10
+ from TB2J.external import p_map
10
11
 
11
12
  # from HamiltonIO.model.rotate_spin import rotate_Matrix_from_z_to_axis, rotate_Matrix_from_z_to_sperical
12
13
  # from TB2J.abacus.abacus_wrapper import AbacusWrapper, AbacusParser
@@ -78,6 +79,17 @@ class MAEGreen(ExchangeNCL):
78
79
 
79
80
  def get_perturbed(self, e, thetas, phis):
80
81
  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
+ print(f"""Warning: The SOC of the Hamiltonian has a maximum of {maxsoc} eV,
86
+ comparing to the maximum of {maxH0} eV of the spin part of the Hamiltonian.
87
+ The SOC is too strong, the perturbation theory may not be valid.""")
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.""")
92
+
81
93
  G0K = self.G.get_Gk_all(e)
82
94
  Hsoc_k = self.tbmodel.get_Hk_soc(self.G.kpts)
83
95
  na = len(thetas)
@@ -143,15 +155,33 @@ class MAEGreen(ExchangeNCL):
143
155
  if with_eigen:
144
156
  self.es2 = self.get_band_energy_vs_angles_from_eigen(thetas, phis)
145
157
 
146
- for ie, e in enumerate(tqdm.tqdm(self.contour.path)):
147
- dE_angle, dE_angle_atom, dE_angle_atom_orb = self.get_perturbed(
148
- e, thetas, phis
149
- )
150
- self.es += dE_angle * self.contour.weights[ie]
151
- self.es_atom += dE_angle_atom * self.contour.weights[ie]
158
+ # for ie, e in enumerate(tqdm.tqdm(self.contour.path)):
159
+ # dE_angle, dE_angle_atom, dE_angle_atom_orb = self.get_perturbed(
160
+ # e, thetas, phis
161
+ # )
162
+ # self.es += dE_angle * self.contour.weights[ie]
163
+ # self.es_atom += dE_angle_atom * self.contour.weights[ie]
164
+ # for key, value in dE_angle_atom_orb.items():
165
+ # self.es_atom_orb[key] += (
166
+ # dE_angle_atom_orb[key] * self.contour.weights[ie]
167
+ # )
168
+
169
+ # rewrite the for loop above to use p_map
170
+ def func(e):
171
+ return self.get_perturbed(e, thetas, phis)
172
+
173
+ if self.nproc > 1:
174
+ results = p_map(func, self.contour.path, num_cpus=self.nproc)
175
+ else:
176
+ npole = len(self.contour.path)
177
+ results = map(func, tqdm.tqdm(self.contour.path, total=npole))
178
+ for i, result in enumerate(results):
179
+ dE_angle, dE_angle_atom, dE_angle_atom_orb = result
180
+ self.es += dE_angle * self.contour.weights[i]
181
+ self.es_atom += dE_angle_atom * self.contour.weights[i]
152
182
  for key, value in dE_angle_atom_orb.items():
153
183
  self.es_atom_orb[key] += (
154
- dE_angle_atom_orb[key] * self.contour.weights[ie]
184
+ dE_angle_atom_orb[key] * self.contour.weights[i]
155
185
  )
156
186
 
157
187
  self.es = -np.imag(self.es) / (2 * np.pi)
@@ -1,5 +1,6 @@
1
1
  import numpy as np
2
2
  from scipy.special import roots_legendre
3
+
3
4
  from TB2J.utils import simpson_nonuniform_weight
4
5
 
5
6
 
@@ -15,6 +16,21 @@ class Contour:
15
16
  self._weights = simpson_nonuniform_weight(self.path)
16
17
  return self._weights
17
18
 
19
+ def integrate_func(self, func):
20
+ """
21
+ integrate f along the path
22
+ """
23
+ return np.dot(func(self.path), self.weights)
24
+
25
+ def integrate_values(self, values):
26
+ """
27
+ integrate f along the path
28
+ """
29
+ ret = 0
30
+ for i in range(len(values)):
31
+ ret += values[i] * self.weights[i]
32
+ return ret
33
+
18
34
  def build_path_semicircle(self, npoints, endpoint=True):
19
35
  R = (self.emax - self.emin) / 2.0
20
36
  R0 = (self.emin + self.emax) / 2.0
@@ -10,13 +10,12 @@ from TB2J.exchange_params import ExchangeParams
10
10
  from TB2J.external import p_map
11
11
  from TB2J.green import TBGreen
12
12
  from TB2J.io_exchange import SpinIO
13
+ from TB2J.mycfr import CFR
13
14
  from TB2J.orbmap import map_orbs_matrix
14
15
  from TB2J.pauli import pauli_block_all, pauli_block_sigma_norm
15
16
  from TB2J.utils import (
16
17
  kmesh_to_R,
17
- simpson_nonuniform,
18
18
  symbol_number,
19
- trapezoidal_nonuniform,
20
19
  )
21
20
 
22
21
 
@@ -28,6 +27,7 @@ class Exchange(ExchangeParams):
28
27
  self._prepare_Rlist()
29
28
  self.set_tbmodels(tbmodels)
30
29
  self._adjust_emin()
30
+ # self._prepare_elist(method="CFR")
31
31
  self._prepare_elist(method="legendre")
32
32
  self._prepare_basis()
33
33
  self._prepare_orb_dict()
@@ -45,8 +45,9 @@ class Exchange(ExchangeParams):
45
45
  os.makedirs(self.orbpath, exist_ok=True)
46
46
 
47
47
  def _adjust_emin(self):
48
- self.emin = self.G.find_energy_ingap(rbound=self.efermi - 10.0) - self.efermi
49
- # self.emin = -22.0
48
+ self.emin = self.G.find_energy_ingap(rbound=self.efermi - 15.0) - self.efermi
49
+ # self.emin = self.G.find_energy_ingap(rbound=self.efermi - 15.0) - self.efermi
50
+ # self.emin = -42.0
50
51
  print(f"A gap is found at {self.emin}, set emin to it.")
51
52
 
52
53
  def set_tbmodels(self, tbmodels):
@@ -61,21 +62,24 @@ class Exchange(ExchangeParams):
61
62
  for k in kmesh:
62
63
  self.kmesh = list(map(lambda x: x // 2 * 2 + 1, kmesh))
63
64
 
64
- def _prepare_elist(self, method="legendre"):
65
+ def _prepare_elist(self, method="CFR"):
65
66
  """
66
67
  prepare list of energy for integration.
67
68
  The path has three segments:
68
69
  emin --1-> emin + 1j*height --2-> emax+1j*height --3-> emax
69
70
  """
70
- self.contour = Contour(self.emin, self.emax)
71
71
  # if method.lower() == "rectangle":
72
72
  # self.contour.build_path_rectangle(
73
73
  # height=self.height, nz1=self.nz1, nz2=self.nz2, nz3=self.nz3
74
74
  # )
75
75
  if method.lower() == "semicircle":
76
+ self.contour = Contour(self.emin, self.emax)
76
77
  self.contour.build_path_semicircle(npoints=self.nz, endpoint=True)
77
78
  elif method.lower() == "legendre":
79
+ self.contour = Contour(self.emin, self.emax)
78
80
  self.contour.build_path_legendre(npoints=self.nz, endpoint=True)
81
+ elif method.lower() == "cfr":
82
+ self.contour = CFR(nz=self.nz, T=600)
79
83
  else:
80
84
  raise ValueError(f"The path cannot be of type {method}.")
81
85
 
@@ -114,6 +118,7 @@ class Exchange(ExchangeParams):
114
118
  else:
115
119
  try:
116
120
  atom_sym, orb_sym = base[:2]
121
+ iatom = sdict[atom_sym]
117
122
  except Exception:
118
123
  iatom = base.iatom
119
124
  atom_sym = base.iatom
@@ -168,7 +173,6 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
168
173
  self.mmats = {}
169
174
  self.orbital_names = {}
170
175
  self.norb_reduced = {}
171
- print(f"self.backend_name: {self.backend_name}")
172
176
  if self.backend_name.upper() in ["SIESTA", "ABACUS", "LCAOHAMILTONIAN"]:
173
177
  # print(f"magntic_elements: {self.magnetic_elements}")
174
178
  # print(f"include_orbs: {self.include_orbs}")
@@ -562,20 +566,24 @@ class ExchangeNCL(Exchange):
562
566
  AijRs: a list of AijR,
563
567
  wherer AijR: array of ((nR, n, n, 4,4), dtype=complex)
564
568
  """
565
- if method == "trapezoidal":
566
- integrate = trapezoidal_nonuniform
567
- elif method == "simpson":
568
- integrate = simpson_nonuniform
569
+ # if method == "trapezoidal":
570
+ # integrate = trapezoidal_nonuniform
571
+ # elif method == "simpson":
572
+ # integrate = simpson_nonuniform
573
+ #
569
574
 
570
575
  # self.rho = integrate(self.contour.path, rhoRs)
571
576
  for iR, R in enumerate(self.R_ijatom_dict):
572
577
  for iatom, jatom in self.R_ijatom_dict[R]:
573
578
  f = AijRs[(R, iatom, jatom)]
574
- self.A_ijR[(R, iatom, jatom)] = integrate(self.contour.path, f)
579
+ # self.A_ijR[(R, iatom, jatom)] = integrate(self.contour.path, f)
580
+ self.A_ijR[(R, iatom, jatom)] = self.contour.integrate_values(f)
581
+
575
582
  if self.orb_decomposition:
576
- self.A_ijR_orb[(R, iatom, jatom)] = integrate(
577
- self.contour.path, AijRs_orb[(R, iatom, jatom)]
578
- )
583
+ # self.A_ijR_orb[(R, iatom, jatom)] = integrate(
584
+ # self.contour.path, AijRs_orb[(R, iatom, jatom)]
585
+ # )
586
+ self.contour.integrate_values(AijRs_orb[(R, iatom, jatom)])
579
587
 
580
588
  def get_quantities_per_e(self, e):
581
589
  Gk_all = self.G.get_Gk_all(e)
@@ -1,15 +1,18 @@
1
1
  """
2
2
  Exchange from Green's function
3
3
  """
4
+
4
5
  import os
5
6
  from collections import defaultdict
7
+
6
8
  import numpy as np
7
- from TB2J.green import TBGreen
8
- from TB2J.io_exchange import SpinIO
9
9
  from tqdm import tqdm
10
+
10
11
  from TB2J.external import p_map
12
+ from TB2J.green import TBGreen
13
+ from TB2J.io_exchange import SpinIO
14
+
11
15
  from .exchange import ExchangeCL
12
- from .utils import simpson_nonuniform, trapezoidal_nonuniform
13
16
 
14
17
 
15
18
  class ExchangeCL2(ExchangeCL):
@@ -221,17 +224,23 @@ class ExchangeCL2(ExchangeCL):
221
224
  # shutil.rmtree(path)
222
225
 
223
226
  def integrate(self, method="simpson"):
224
- if method == "trapezoidal":
225
- integrate = trapezoidal_nonuniform
226
- elif method == "simpson":
227
- integrate = simpson_nonuniform
227
+ # if method == "trapezoidal":
228
+ # integrate = trapezoidal_nonuniform
229
+ # elif method == "simpson":
230
+ # integrate = simpson_nonuniform
228
231
  for R, ijpairs in self.R_ijatom_dict.items():
229
232
  for iatom, jatom in ijpairs:
230
- self.Jorb[(R, iatom, jatom)] = integrate(
231
- self.contour.path, self.Jorb_list[(R, iatom, jatom)]
233
+ # self.Jorb[(R, iatom, jatom)] = integrate(
234
+ # self.contour.path, self.Jorb_list[(R, iatom, jatom)]
235
+ # )
236
+ # self.JJ[(R, iatom, jatom)] = integrate(
237
+ # self.contour.path, self.JJ_list[(R, iatom, jatom)]
238
+ # )
239
+ self.Jorb[(R, iatom, jatom)] = self.contour.integrate_values(
240
+ self.Jorb_list[(R, iatom, jatom)]
232
241
  )
233
- self.JJ[(R, iatom, jatom)] = integrate(
234
- self.contour.path, self.JJ_list[(R, iatom, jatom)]
242
+ self.JJ[(R, iatom, jatom)] = self.contour.integrate_values(
243
+ self.JJ_list[(R, iatom, jatom)]
235
244
  )
236
245
 
237
246
  def get_quantities_per_e(self, e):
@@ -115,6 +115,14 @@ def add_exchange_args_to_parser(parser: argparse.ArgumentParser):
115
115
  type=str,
116
116
  nargs="*",
117
117
  )
118
+
119
+ parser.add_argument(
120
+ "--spinor",
121
+ help="whether the Wannier functions are spinor. Default: False",
122
+ action="store_true",
123
+ default=False,
124
+ )
125
+
118
126
  parser.add_argument(
119
127
  "--rcut",
120
128
  help="cutoff of spin pair distance. The default is to calculate all commensurate R point to the k mesh.",
@@ -18,6 +18,17 @@ from TB2J.kpoints import ir_kpts, monkhorst_pack
18
18
  MAX_EXP_ARGUMENT = np.log(sys.float_info.max)
19
19
 
20
20
 
21
+ def eigen_to_G2(H, S, efermi, energy):
22
+ """calculate green's function from eigenvalue/eigenvector for energy(e-ef): G(e-ef).
23
+ :param H: Hamiltonian matrix in eigenbasis
24
+ :param S: Overlap matrix in eigenbasis
25
+ :param efermi: fermi energy
26
+ :param energy: energy level e - efermi
27
+ """
28
+ # G = ((E+Ef) S - H)^-1
29
+ return np.linalg.inv((energy + efermi) * S - H)
30
+
31
+
21
32
  def eigen_to_G(evals, evecs, efermi, energy):
22
33
  """calculate green's function from eigenvalue/eigenvector for energy(e-ef): G(e-ef).
23
34
  :param evals: eigen values
@@ -121,7 +132,10 @@ class TBGreen:
121
132
  elif kmesh is not None:
122
133
  if ibz:
123
134
  self.kpts, self.kweights = ir_kpts(
124
- atoms=tbmodel.atoms, mp_grid=kmesh, ir=True, is_time_reversal=False
135
+ atoms=tbmodel.atoms,
136
+ mp_grid=kmesh,
137
+ ir=True,
138
+ is_time_reversal=False,
125
139
  )
126
140
  self.nkpts = len(self.kpts)
127
141
  print(f"Using IBZ of kmesh of {kmesh}")
@@ -163,7 +163,7 @@ Warning: The DMI component parallel to the spin orientation, the Jani which has
163
163
  # thetas = [0, np.pi / 2, np.pi, 3 * np.pi / 2]
164
164
  # phis = [0, 0, 0, 0]
165
165
  # MAE.set_angles(thetas=thetas, phis=phis)
166
- MAE.run(output_path=f"{output_path}_anisotropy")
166
+ MAE.run(output_path=f"{output_path}_anisotropy", with_eigen=True)
167
167
  print(
168
168
  f"MAE calculation finished. The results are in {output_path} directory."
169
169
  )
@@ -70,7 +70,21 @@ def ir_kpts(
70
70
  # Irreducible k-points
71
71
  # print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
72
72
  # print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))
73
- return ird_kpts, weight
73
+
74
+ new_ir_kpts = []
75
+ new_weight = []
76
+ for ik, k in enumerate(ird_kpts):
77
+ # add k and -k to ird_kpts if -k is not in ird_kpts
78
+ if not any([np.allclose(-1.0 * k, kpt) for kpt in new_ir_kpts]):
79
+ new_ir_kpts.append(k)
80
+ new_ir_kpts.append(-1.0 * k)
81
+ new_weight.append(weight[ik] / 2)
82
+ new_weight.append(weight[ik] / 2)
83
+ else:
84
+ new_ir_kpts.append(k)
85
+ new_weight.append(weight[ik])
86
+ # return ird_kpts, weight
87
+ return np.array(new_ir_kpts), np.array(new_weight)
74
88
 
75
89
 
76
90
  def test_ir_kpts():
@@ -0,0 +1,114 @@
1
+ # -*- coding: utf-8 -*-
2
+ # File: mycfr.py
3
+ # Time: 2017/12/10 19:29:43
4
+ """
5
+ Continued fraction representation.
6
+ """
7
+
8
+ import numpy as np
9
+ from scipy.linalg import eig
10
+
11
+ kb = 8.61733e-5 # Boltzmann constant in eV
12
+
13
+
14
+ class CFR:
15
+ """
16
+ Integration with the continued fraction representation.
17
+ """
18
+
19
+ def __init__(self, nz=50, T=60):
20
+ self.nz = nz
21
+ self.T = 600
22
+ self.beta = 1 / (kb * self.T)
23
+ self.Rinf = 1e10
24
+ if nz <= 0:
25
+ raise ValueError("nz should be larger than 0.")
26
+ else:
27
+ self.prepare_poles()
28
+
29
+ def prepare_poles(self):
30
+ ##b_mat = [1 / (2.0 * np.sqrt((2 * (j + 1) - 1) * (2 * (j + 1) + 1)) / (kb * self.#T)) for j in range(0, self.nz- 1)]
31
+ jmat = np.arange(0, self.nz - 1)
32
+ b_mat = 1 / (2.0 * np.sqrt((2 * (jmat + 1) - 1) * (2 * (jmat + 1) + 1)))
33
+ b_mat = np.diag(b_mat, -1) + np.diag(b_mat, 1)
34
+ self.poles, residules = eig(b_mat)
35
+
36
+ residules = 0.25 * np.abs(residules[0, :]) ** 2 / self.poles**2
37
+ # residules = 0.25 * np.diag(residules) ** 2 / self.poles**2
38
+
39
+ # self.weights = np.where(
40
+ # #np.real(self.poles) > 0, 4.0j / self.beta * residules, 0.0
41
+ # #np.real(self.poles) > 0, 2.0j / self.beta * residules, 2.0j / self.beta * residules
42
+ # np.real(self.poles) > 0, 2.0j / self.beta * residules, 0.0
43
+ # )
44
+
45
+ # self.path = 1j / self.poles * kb * self.T
46
+
47
+ self.path = []
48
+ self.weights = []
49
+ for p, r in zip(self.poles, residules):
50
+ if p > 0:
51
+ self.path.append(1j / p * kb * self.T)
52
+ w = 2.0j / self.beta * r
53
+ self.weights.append(w)
54
+ self.path.append(-1j / p * kb * self.T)
55
+ self.weights.append(w)
56
+
57
+ self.path = np.array(self.path)
58
+ self.weights = np.array(self.weights)
59
+
60
+ # from J. Phys. Soc. Jpn. 88, 114706 (2019)
61
+ # A_mat = -1/2 *np.diag(1, -1) + np.diag(1, 1)
62
+ # B_mat = np.diag([2*i-1 for i in range(1, self.nz)])
63
+ # eigp, eigv = eig(A_mat, B_mat)
64
+ # zp = 1j / eigp * kb * self.T
65
+ # Rp = 0.25 * np.diag(eigv)**2 * zp **2
66
+
67
+ # add a point to the poles: 1e10j
68
+ self.path = np.concatenate((self.path, [self.Rinf * 1j]))
69
+ # self.path = np.concatenate((self.path, [0.0]))
70
+ self.npoles = len(self.poles)
71
+
72
+ # add weights for the point 1e10j
73
+ # self.weights = np.concatenate((self.weights, [-self.Rinf]))
74
+ self.weights = np.concatenate((self.weights, [00.0]))
75
+ # zeros moment is 1j * R * test_gf(1j * R), but the real part of it will be taken. In contrast to the other part, where the imaginary part is taken.
76
+
77
+ def integrate_values(self, gf_vals, imag=False):
78
+ ret = 0
79
+ for i in range(self.npoles + 1):
80
+ ret += self.weights[i] * gf_vals[i]
81
+ ret *= (
82
+ -np.pi / 2
83
+ ) # This is to be compatible with the integration of contour, where /-np.pi is used after the integration. And the factor of 2 is because the Fermi function here is 2-fold degenerate.
84
+ if imag:
85
+ return np.imag(ret)
86
+ return ret
87
+
88
+ def integrate_func(self, gf, ef=0):
89
+ """
90
+ Integration with the continued fraction representation.
91
+
92
+ :param gf: Green's function
93
+ :param ef: Fermi energy
94
+ :return: integration result
95
+ """
96
+ path = self.path
97
+ gf_vals = gf(path, ef=ef)
98
+ return self.integrate_values(gf_vals)
99
+
100
+
101
+ def test_cfr():
102
+ cfr = CFR(nz=100)
103
+
104
+ def test_gf(z, ef=0.1):
105
+ return 1 / (z - 3 + ef)
106
+
107
+ r = cfr.integrate_func(test_gf, ef=2)
108
+ r = -np.imag(r) / np.pi * 2
109
+ print(r)
110
+ return r
111
+
112
+
113
+ if __name__ == "__main__":
114
+ test_cfr()
@@ -28,14 +28,14 @@ def map_orbs_matrix(orblist, spinor=False, include_only=None):
28
28
 
29
29
  norb = len(orblist)
30
30
 
31
- print("orblist: ", orblist)
31
+ # print("orblist: ", orblist)
32
32
  ss = [split_orb_name(orb) for orb in orblist]
33
33
  orbdict = dict(zip(ss, range(norb)))
34
34
 
35
35
  reduced_orbdict = defaultdict(lambda: [])
36
36
 
37
- print(f"Orbital dictionary: {orbdict}")
38
- print("include_only: ", include_only)
37
+ # print(f"Orbital dictionary: {orbdict}")
38
+ # print("include_only: ", include_only)
39
39
 
40
40
  if include_only is None:
41
41
  for key, val in orbdict.items():
@@ -46,7 +46,7 @@ def map_orbs_matrix(orblist, spinor=False, include_only=None):
46
46
  # [:2] for 3d, 4d, 5d, etc. and [:1] for s, p, d, etc
47
47
  reduced_orbdict[key[0]].append(val)
48
48
 
49
- print(f"reduced_orbdict: {reduced_orbdict}")
49
+ # print(f"reduced_orbdict: {reduced_orbdict}")
50
50
  reduced_orbs = tuple(reduced_orbdict.keys())
51
51
  ngroup = len(reduced_orbdict)
52
52
  mmat = np.zeros((norb, ngroup), dtype=int)
@@ -14,6 +14,7 @@ class TB2JSymmetrizer:
14
14
  ijRs = exc.ijR_list_index_atom()
15
15
  finder = SymmetryPairFinder(atoms=exc.atoms, pairs=ijRs, symprec=symprec)
16
16
  self.verbose = verbose
17
+ self.Jonly = Jonly
17
18
 
18
19
  if verbose:
19
20
  print("=" * 30)
@@ -124,9 +125,10 @@ def symmetrize_J_cli():
124
125
  )
125
126
 
126
127
  parser.add_argument(
127
- "-Jonly",
128
+ "--Jonly",
128
129
  action="store_true",
129
- help="Symmetrize only the exchange parameters. Do not output DMI and anisotropic exchange.",
130
+ help="symmetrize only the exchange parameters and discard the DMI and anisotropic exchange",
131
+ default=False,
130
132
  )
131
133
 
132
134
  args = parser.parse_args()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.9.9rc5
3
+ Version: 0.9.9rc6
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
@@ -25,6 +25,7 @@ TB2J/greentest.py
25
25
  TB2J/io_merge.py
26
26
  TB2J/kpoints.py
27
27
  TB2J/myTB.py
28
+ TB2J/mycfr.py
28
29
  TB2J/orbmap.py
29
30
  TB2J/pauli.py
30
31
  TB2J/pert.py
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  from setuptools import find_packages, setup
3
3
 
4
- __version__ = "0.9.9_rc5"
4
+ __version__ = "0.9.9_rc6"
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
 
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