TB2J 0.9.9rc3__tar.gz → 0.9.9rc5__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.9rc3 → tb2j-0.9.9rc5}/PKG-INFO +1 -1
  2. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/MAE.py +3 -3
  3. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/MAEGreen.py +6 -4
  4. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange.py +9 -14
  5. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange_params.py +11 -4
  6. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/green.py +63 -14
  7. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/siesta_interface.py +1 -0
  8. tb2j-0.9.9rc5/TB2J/kpoints.py +87 -0
  9. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/symmetrize_J.py +34 -9
  10. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/versioninfo.py +2 -1
  11. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/PKG-INFO +1 -1
  12. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/setup.py +1 -1
  13. tb2j-0.9.9rc3/TB2J/kpoints.py +0 -16
  14. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/LICENSE +0 -0
  15. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/README.md +0 -0
  16. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Jdownfolder.py +0 -0
  17. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Jtensor.py +0 -0
  18. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Oiju.py +0 -0
  19. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/Oiju_epc.py +0 -0
  20. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/__init__.py +0 -0
  21. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/anisotropy.py +0 -0
  22. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/basis.py +0 -0
  23. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/citation.py +0 -0
  24. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/contour.py +0 -0
  25. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/density_matrix.py +0 -0
  26. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/epc.py +0 -0
  27. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchangeCL2.py +0 -0
  28. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange_pert.py +0 -0
  29. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/exchange_qspace.py +0 -0
  30. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/external/__init__.py +0 -0
  31. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/external/p_tqdm.py +0 -0
  32. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/gpaw_wrapper.py +0 -0
  33. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/greentest.py +0 -0
  34. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/__init__.py +0 -0
  35. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/__init__.py +0 -0
  36. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/abacus_api.py +0 -0
  37. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/abacus_wrapper.py +0 -0
  38. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/gen_exchange_abacus.py +0 -0
  39. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/orbital_api.py +0 -0
  40. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/stru_api.py +0 -0
  41. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/test_density_matrix.py +0 -0
  42. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/test_read_HRSR.py +0 -0
  43. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/abacus/test_read_stru.py +0 -0
  44. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/gpaw_interface.py +0 -0
  45. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/lawaf_interface.py +0 -0
  46. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/manager.py +0 -0
  47. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/interfaces/wannier90_interface.py +0 -0
  48. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/__init__.py +0 -0
  49. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_exchange.py +0 -0
  50. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_multibinit.py +0 -0
  51. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_tomsasd.py +0 -0
  52. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_txt.py +0 -0
  53. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_uppasd.py +0 -0
  54. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_exchange/io_vampire.py +0 -0
  55. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/io_merge.py +0 -0
  56. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/__init__.py +0 -0
  57. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/fermi.py +0 -0
  58. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/kR_convert.py +0 -0
  59. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/lowdin.py +0 -0
  60. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/mathutils/rotate_spin.py +0 -0
  61. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/myTB.py +0 -0
  62. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/orbmap.py +0 -0
  63. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/pauli.py +0 -0
  64. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/pert.py +0 -0
  65. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/plot.py +0 -0
  66. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/rotate_atoms.py +0 -0
  67. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/rotate_siestaDM.py +0 -0
  68. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/sisl_wrapper.py +0 -0
  69. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/__init__.py +0 -0
  70. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/base_parser.py +0 -0
  71. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/constants.py +0 -0
  72. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/hamiltonian.py +0 -0
  73. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/hamiltonian_terms.py +0 -0
  74. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/plot.py +0 -0
  75. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/qsolver.py +0 -0
  76. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/spin_api.py +0 -0
  77. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/spin_xml.py +0 -0
  78. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/spinham/supercell.py +0 -0
  79. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/tensor_rotate.py +0 -0
  80. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/utest.py +0 -0
  81. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/utils.py +0 -0
  82. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/wannier/__init__.py +0 -0
  83. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/wannier/w90_parser.py +0 -0
  84. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J/wannier/w90_tb_parser.py +0 -0
  85. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/SOURCES.txt +0 -0
  86. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/dependency_links.txt +0 -0
  87. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/entry_points.txt +0 -0
  88. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/requires.txt +0 -0
  89. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/TB2J.egg-info/top_level.txt +0 -0
  90. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_downfold.py +0 -0
  91. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_eigen.py +0 -0
  92. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_magnon.py +0 -0
  93. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_magnon_dos.py +0 -0
  94. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_merge.py +0 -0
  95. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_rotate.py +0 -0
  96. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/TB2J_rotateDM.py +0 -0
  97. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/abacus2J.py +0 -0
  98. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/siesta2J.py +0 -0
  99. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/scripts/wann2J.py +0 -0
  100. {tb2j-0.9.9rc3 → tb2j-0.9.9rc5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.9.9rc3
3
+ Version: 0.9.9rc5
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
@@ -137,9 +137,9 @@ class MAEGreen(MAE):
137
137
  efermi = occ.efermi(evals)
138
138
  print(f"{efermi=}")
139
139
  self.G = TBGreen(model, kmesh, efermi=efermi, gamma=gamma, **kwargs)
140
- self.emin = -12
140
+ self.emin = -52
141
141
  self.emax = 0
142
- self.nz = 50
142
+ self.nz = 100
143
143
  self._prepare_elist()
144
144
 
145
145
  def _prepare_elist(self, method="legendre"):
@@ -186,7 +186,7 @@ class MAEGreen(MAE):
186
186
  for ie, e in enumerate(tqdm.tqdm(self.contour.path)):
187
187
  dE_angle = self.get_perturbed(e, thetas, phis)
188
188
  es += np.imag(dE_angle * self.contour.weights[ie])
189
- return -es / np.pi
189
+ return -es / np.pi / 2
190
190
 
191
191
 
192
192
  def get_model_energy(model, kmesh, gamma=True):
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
  import numpy as np
4
4
  import tqdm
5
5
  from HamiltonIO.abacus.abacus_wrapper import AbacusSplitSOCParser
6
- from HamiltonIO.model.occupations import Occupations
6
+ from HamiltonIO.model.occupations import GaussOccupations
7
7
  from typing_extensions import DefaultDict
8
8
 
9
9
  from TB2J.exchange import ExchangeNCL
@@ -16,7 +16,7 @@ from TB2J.mathutils.rotate_spin import (
16
16
 
17
17
 
18
18
  def get_occupation(evals, kweights, nel, width=0.1):
19
- occ = Occupations(nel=nel, width=width, wk=kweights, nspin=2)
19
+ occ = GaussOccupations(nel=nel, width=width, wk=kweights, nspin=2)
20
20
  return occ.occupy(evals)
21
21
 
22
22
 
@@ -97,6 +97,7 @@ class MAEGreen(ExchangeNCL):
97
97
  dG2 = GdH * GdH.T
98
98
  dG2sum = np.sum(dG2)
99
99
  # print(f"dG2sum-sum: {dG2sum}")
100
+ dG2sum = np.sum(dG2diag)
100
101
 
101
102
  # dG2sum = np.trace(GdH @ GdH)
102
103
  # print(f"dG2sum-Tr: {dG2sum}")
@@ -158,7 +159,7 @@ class MAEGreen(ExchangeNCL):
158
159
  for key, value in self.es_atom_orb.items():
159
160
  self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
160
161
 
161
- def output(self, output_path="TB2J_anisotropy", with_eigen=False):
162
+ def output(self, output_path="TB2J_anisotropy", with_eigen=True):
162
163
  Path(output_path).mkdir(exist_ok=True)
163
164
  fname = f"{output_path}/MAE.dat"
164
165
  fname_orb = f"{output_path}/MAE_orb.dat"
@@ -242,6 +243,7 @@ def abacus_get_MAE(
242
243
  magnetic_elements=None,
243
244
  nel=None,
244
245
  width=0.1,
246
+ with_eigen=False,
245
247
  **kwargs,
246
248
  ):
247
249
  """Get MAE from Abacus with magnetic force theorem. Two calculations are needed. First we do an calculation with SOC but the soc_lambda is set to 0. Save the density. The next calculatin we start with the density from the first calculation and set the SOC prefactor to 1. With the information from the two calcualtions, we can get the band energy with magnetic moments in the direction, specified in two list, thetas, and phis."""
@@ -262,4 +264,4 @@ def abacus_get_MAE(
262
264
  magnetic_elements=magnetic_elements,
263
265
  **kwargs,
264
266
  )
265
- mae.run(output_path=output_path)
267
+ mae.run(output_path=output_path, with_eigen=with_eigen)
@@ -21,12 +21,7 @@ from TB2J.utils import (
21
21
 
22
22
 
23
23
  class Exchange(ExchangeParams):
24
- def __init__(
25
- self,
26
- tbmodels,
27
- atoms,
28
- **params: ExchangeParams,
29
- ):
24
+ def __init__(self, tbmodels, atoms, **params):
30
25
  self.atoms = atoms
31
26
  super().__init__(**params)
32
27
  self._prepare_kmesh(self._kmesh)
@@ -50,8 +45,8 @@ class Exchange(ExchangeParams):
50
45
  os.makedirs(self.orbpath, exist_ok=True)
51
46
 
52
47
  def _adjust_emin(self):
53
- # self.emin = self.G.find_energy_ingap(rbound=self.efermi - 10.0) - self.efermi
54
- self.emin = -22.0
48
+ self.emin = self.G.find_energy_ingap(rbound=self.efermi - 10.0) - self.efermi
49
+ # self.emin = -22.0
55
50
  print(f"A gap is found at {self.emin}, set emin to it.")
56
51
 
57
52
  def set_tbmodels(self, tbmodels):
@@ -62,7 +57,7 @@ class Exchange(ExchangeParams):
62
57
  # del self.G.tbmodel
63
58
  pass
64
59
 
65
- def _prepare_kmesh(self, kmesh):
60
+ def _prepare_kmesh(self, kmesh, ibz=False):
66
61
  for k in kmesh:
67
62
  self.kmesh = list(map(lambda x: x // 2 * 2 + 1, kmesh))
68
63
 
@@ -150,7 +145,7 @@ class Exchange(ExchangeParams):
150
145
  )
151
146
  if not self._is_collinear:
152
147
  for iatom, orb in self.orb_dict.items():
153
- print(f"iatom: {iatom}, orb: {orb}")
148
+ # print(f"iatom: {iatom}, orb: {orb}")
154
149
  nsorb = len(self.orb_dict[iatom])
155
150
  if nsorb % 2 != 0 and False:
156
151
  raise ValueError(
@@ -175,8 +170,8 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
175
170
  self.norb_reduced = {}
176
171
  print(f"self.backend_name: {self.backend_name}")
177
172
  if self.backend_name.upper() in ["SIESTA", "ABACUS", "LCAOHAMILTONIAN"]:
178
- print(f"magntic_elements: {self.magnetic_elements}")
179
- print(f"include_orbs: {self.include_orbs}")
173
+ # print(f"magntic_elements: {self.magnetic_elements}")
174
+ # print(f"include_orbs: {self.include_orbs}")
180
175
  syms = self.atoms.get_chemical_symbols()
181
176
  for iatom, orbs in self.labels.items():
182
177
  if (self.include_orbs is not None) and syms[iatom] in self.include_orbs:
@@ -186,7 +181,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
186
181
  include_only=self.include_orbs[syms[iatom]],
187
182
  )
188
183
  else:
189
- print(f"orbs: {orbs}")
184
+ # print(f"orbs: {orbs}")
190
185
  mmat, reduced_orbs = map_orbs_matrix(
191
186
  orbs, spinor=not (self._is_collinear), include_only=None
192
187
  )
@@ -271,10 +266,10 @@ class ExchangeNCL(Exchange):
271
266
  """
272
267
  self.tbmodel = tbmodels
273
268
  self.backend_name = self.tbmodel.name
274
- print(self.kmesh)
275
269
  self.G = TBGreen(
276
270
  tbmodel=self.tbmodel,
277
271
  kmesh=self.kmesh,
272
+ ibz=self.ibz,
278
273
  gamma=True,
279
274
  efermi=self.efermi,
280
275
  use_cache=self._use_cache,
@@ -31,6 +31,7 @@ class ExchangeParams:
31
31
  output_path: str = "TB2J_results"
32
32
  mae_angles = None
33
33
  orth = False
34
+ ibz = False
34
35
 
35
36
  def __init__(
36
37
  self,
@@ -53,6 +54,7 @@ class ExchangeParams:
53
54
  exclude_orbs=[],
54
55
  mae_angles=None,
55
56
  orth=False,
57
+ ibz=False,
56
58
  ):
57
59
  self.efermi = efermi
58
60
  self.basis = basis
@@ -76,6 +78,7 @@ class ExchangeParams:
76
78
  self.output_path = output_path
77
79
  self.mae_angles = mae_angles
78
80
  self.orth = orth
81
+ self.ibz = ibz
79
82
 
80
83
  def set_params(self, **kwargs):
81
84
  for key, val in kwargs.items():
@@ -92,8 +95,6 @@ class ExchangeParams:
92
95
  include_orbs = {}
93
96
  if isinstance(magnetic_elements, str):
94
97
  magnetic_elements = [magnetic_elements]
95
- print(f"magnetic_elements: {magnetic_elements}")
96
- print(f"include_orbs: {include_orbs}")
97
98
  for element in magnetic_elements:
98
99
  if "_" in element:
99
100
  elem = element.split("_")[0]
@@ -102,8 +103,6 @@ class ExchangeParams:
102
103
  else:
103
104
  include_orbs[element] = None
104
105
 
105
- print(f"magnetic_elements: {magnetic_elements}")
106
- print(f"include_orbs: {include_orbs}")
107
106
  magnetic_elements = list(include_orbs.keys())
108
107
  return magnetic_elements, include_orbs
109
108
 
@@ -214,6 +213,14 @@ def add_exchange_args_to_parser(parser: argparse.ArgumentParser):
214
213
  action="store_true",
215
214
  default=False,
216
215
  )
216
+
217
+ parser.add_argument(
218
+ "--ibz",
219
+ help=" use irreducible k-points in the Brillouin zone. (Note: only for computing total MAE).",
220
+ action="store_true",
221
+ default=False,
222
+ )
223
+
217
224
  return parser
218
225
 
219
226
 
@@ -7,11 +7,11 @@ from collections import defaultdict
7
7
  from shutil import rmtree
8
8
 
9
9
  import numpy as np
10
- from HamiltonIO.model.occupations import Occupations
10
+ from HamiltonIO.model.occupations import GaussOccupations
11
11
  from HamiltonIO.model.occupations import myfermi as fermi
12
12
  from pathos.multiprocessing import ProcessPool
13
13
 
14
- from TB2J.kpoints import monkhorst_pack
14
+ from TB2J.kpoints import ir_kpts, monkhorst_pack
15
15
 
16
16
  # from TB2J.mathutils.fermi import fermi
17
17
 
@@ -40,7 +40,7 @@ def eigen_to_G(evals, evecs, efermi, energy):
40
40
  )
41
41
 
42
42
 
43
- def find_energy_ingap(evals, rbound, gap=4.0):
43
+ def find_energy_ingap(evals, rbound, gap=2.0):
44
44
  """
45
45
  find a energy inside a gap below rbound (right bound),
46
46
  return the energy gap top - 0.5.
@@ -59,9 +59,11 @@ class TBGreen:
59
59
  self,
60
60
  tbmodel,
61
61
  kmesh=None, # [ikpt, 3]
62
+ ibz=False, # if True, will interpolate the Green's function at Ir-kpoints
62
63
  efermi=None, # efermi
63
64
  gamma=False,
64
65
  kpts=None,
66
+ kweights=None,
65
67
  k_sym=False,
66
68
  use_cache=False,
67
69
  cache_path=None,
@@ -81,20 +83,61 @@ class TBGreen:
81
83
  self.cache_path = cache_path
82
84
  if use_cache:
83
85
  self._prepare_cache()
84
- if kpts is not None:
85
- self.kpts = kpts
86
- elif kmesh is not None:
87
- self.kpts = monkhorst_pack(kmesh, gamma_center=gamma)
88
- else:
89
- self.kpts = tbmodel.get_kpts()
90
- self.nkpts = len(self.kpts)
91
- self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
86
+ self.prepare_kpts(
87
+ kmesh=kmesh,
88
+ ibz=ibz,
89
+ gamma=gamma,
90
+ kpts=kpts,
91
+ kweights=kweights,
92
+ tbmodel=tbmodel,
93
+ )
94
+
92
95
  self.norb = tbmodel.norb
93
96
  self.nbasis = tbmodel.nbasis
94
97
  self.k_sym = k_sym
95
98
  self.nproc = nproc
96
99
  self._prepare_eigen()
97
100
 
101
+ def prepare_kpts(
102
+ self, kmesh=None, gamma=True, ibz=False, kpts=None, kweights=None, tbmodel=None
103
+ ):
104
+ """
105
+ Prepare the k-points for the calculation.
106
+
107
+ Parameters:
108
+ - kmesh (tuple): The k-mesh used to generate k-points.
109
+ - gamma (bool): Whether to include the gamma point in the k-points.
110
+ - ibz (bool): Whether to use the irreducible Brillouin zone.
111
+ - kpts (list): List of user-defined k-points.
112
+ - kweights (list): List of weights for each k-point.
113
+
114
+ Returns:
115
+ None
116
+ """
117
+ if kpts is not None:
118
+ self.kpts = kpts
119
+ self.nkpts = len(self.kpts)
120
+ self.kweights = kweights
121
+ elif kmesh is not None:
122
+ if ibz:
123
+ self.kpts, self.kweights = ir_kpts(
124
+ atoms=tbmodel.atoms, mp_grid=kmesh, ir=True, is_time_reversal=False
125
+ )
126
+ self.nkpts = len(self.kpts)
127
+ print(f"Using IBZ of kmesh of {kmesh}")
128
+ print(f"Number of kpts: {self.nkpts}")
129
+ for kpt, weight in zip(self.kpts, self.kweights):
130
+ # format the kpt and weight, use 5 digits
131
+ print(f"{kpt[0]:8.5f} {kpt[1]:8.5f} {kpt[2]:8.5f} {weight:8.5f}")
132
+ else:
133
+ self.kpts = monkhorst_pack(kmesh, gamma_center=gamma)
134
+ self.nkpts = len(self.kpts)
135
+ self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
136
+ else:
137
+ self.kpts = tbmodel.get_kpts()
138
+ self.nkpts = len(self.kpts)
139
+ self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
140
+
98
141
  def _reduce_eigens(self, evals, evecs, emin, emax):
99
142
  ts = np.logical_and(evals >= emin, evals < emax)
100
143
  ts = np.any(ts, axis=0)
@@ -106,7 +149,7 @@ class TBGreen:
106
149
  istart, iend = ts[0], ts[-1] + 1
107
150
  return evals[:, istart:iend], evecs[:, :, istart:iend]
108
151
 
109
- def find_energy_ingap(self, rbound, gap=4.0):
152
+ def find_energy_ingap(self, rbound, gap=2.0):
110
153
  return find_energy_ingap(self.evals, rbound, gap)
111
154
 
112
155
  def _prepare_cache(self):
@@ -165,7 +208,14 @@ class TBGreen:
165
208
  if self.efermi is None:
166
209
  print("Calculating Fermi energy from eigenvalues")
167
210
  print(f"Number of electrons: {self.tbmodel.nel} ")
168
- occ = Occupations(
211
+
212
+ # occ = Occupations(
213
+ # nel=self.tbmodel.nel, width=0.1, wk=self.kweights, nspin=2
214
+ # )
215
+ # self.efermi = occ.efermi(copy.deepcopy(self.evals))
216
+ # print(f"Fermi energy found: {self.efermi}")
217
+
218
+ occ = GaussOccupations(
169
219
  nel=self.tbmodel.nel, width=0.1, wk=self.kweights, nspin=2
170
220
  )
171
221
  self.efermi = occ.efermi(copy.deepcopy(self.evals))
@@ -360,7 +410,6 @@ class TBGreen:
360
410
  for iR, R in enumerate(Rpts):
361
411
  phase = np.exp(self.k2Rfactor * np.dot(R, kpt))
362
412
  GR[R] += Gkw * (phase * self.kweights[ik])
363
-
364
413
  dHRdx = dHdx.get_hamR(R)
365
414
  dGRdx[R] += Gkw @ dHRdx @ Gk
366
415
  # dGRdx[R] += Gk.dot(dHRdx).dot(Gkp)
@@ -74,6 +74,7 @@ def gen_exchange_siesta(fdf_fname, read_H_soc=False, **kwargs):
74
74
  output_path="TB2J_results",
75
75
  orb_decomposition=False,
76
76
  orth=False,
77
+ ibz=False,
77
78
  description="",
78
79
  )
79
80
  exargs.update(kwargs)
@@ -0,0 +1,87 @@
1
+ from collections import Counter
2
+
3
+ import numpy as np
4
+ import spglib
5
+
6
+
7
+ def monkhorst_pack(size, gamma_center=False):
8
+ """Construct a uniform sampling of k-space of given size.
9
+ Modified from ase.dft.kpoints with gamma_center option added"""
10
+ if np.less_equal(size, 0).any():
11
+ raise ValueError("Illegal size: %s" % list(size))
12
+ kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3))
13
+ asize = np.array(size)
14
+ shift = 0.5 * ((asize + 1) % 2) / asize
15
+ mkpts = (kpts + 0.5) / size - 0.5
16
+ if gamma_center:
17
+ mkpts += shift
18
+ return mkpts
19
+
20
+
21
+ def get_ir_kpts(atoms, mesh):
22
+ """
23
+ Gamma-centered IR kpoints. mesh : [nk1,nk2,nk3].
24
+ """
25
+ lattice = atoms.get_cell()
26
+ positions = atoms.get_scaled_positions()
27
+ numbers = atoms.get_atomic_numbers()
28
+
29
+ cell = (lattice, positions, numbers)
30
+ mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
31
+ return grid[np.unique(mapping)] / np.array(mesh, dtype=float)
32
+
33
+
34
+ def ir_kpts(
35
+ atoms, mp_grid, is_shift=[0, 0, 0], verbose=True, ir=True, is_time_reversal=False
36
+ ):
37
+ """
38
+ generate kpoints for structure
39
+ Parameters:
40
+ ------------------
41
+ atoms: ase.Atoms
42
+ structure
43
+ mp_grid: [nk1,nk2,nk3]
44
+ is_shift: shift of k points. default is Gamma centered.
45
+ ir: bool
46
+ Irreducible or not.
47
+ """
48
+ cell = (atoms.get_cell(), atoms.get_scaled_positions(), atoms.get_atomic_numbers())
49
+ # print(spglib.get_spacegroup(cell, symprec=1e-5))
50
+ mesh = mp_grid
51
+ # Gamma centre mesh
52
+ mapping, grid = spglib.get_ir_reciprocal_mesh(
53
+ mesh, cell, is_shift=is_shift, is_time_reversal=is_time_reversal, symprec=1e-4
54
+ )
55
+ if not ir:
56
+ return (np.array(grid).astype(float) + np.asarray(is_shift) / 2.0) / mesh, [
57
+ 1.0 / len(mapping)
58
+ ] * len(mapping)
59
+ # All k-points and mapping to ir-grid points
60
+ # for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
61
+ # print("%3d ->%3d %s" % (i, ir_gp_id, gp.astype(float) / mesh))
62
+ cnt = Counter(mapping)
63
+ ids = list(cnt.keys())
64
+ weight = list(cnt.values())
65
+ weight = np.array(weight) * 1.0 / sum(weight)
66
+ ird_kpts = [
67
+ (grid[id].astype(float) + np.asarray(is_shift) / 2.0) / mesh for id in ids
68
+ ]
69
+
70
+ # Irreducible k-points
71
+ # print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
72
+ # print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))
73
+ return ird_kpts, weight
74
+
75
+
76
+ def test_ir_kpts():
77
+ from ase.build import bulk
78
+
79
+ atoms = bulk("Si")
80
+ mesh = [14, 14, 14]
81
+ kpts = get_ir_kpts(atoms, mesh)
82
+ print(kpts)
83
+ print(len(kpts))
84
+
85
+
86
+ if __name__ == "__main__":
87
+ test_ir_kpts()
@@ -1,12 +1,15 @@
1
- from sympair import SymmetryPairFinder, SymmetryPairGroupDict
2
- import numpy as np
1
+ import copy
3
2
  from pathlib import Path
3
+
4
+ import numpy as np
5
+ from sympair import SymmetryPairFinder
6
+
7
+ from TB2J.io_exchange import SpinIO
4
8
  from TB2J.versioninfo import print_license
5
- import copy
6
9
 
7
10
 
8
11
  class TB2JSymmetrizer:
9
- def __init__(self, exc, symprec=1e-8, verbose=True):
12
+ def __init__(self, exc, symprec=1e-8, verbose=True, Jonly=False):
10
13
  # list of pairs with the index of atoms
11
14
  ijRs = exc.ijR_list_index_atom()
12
15
  finder = SymmetryPairFinder(atoms=exc.atoms, pairs=ijRs, symprec=symprec)
@@ -28,10 +31,11 @@ class TB2JSymmetrizer:
28
31
  print(f"Finding crystal symmetry with symprec of {symprec} Angstrom.")
29
32
  print("Symmetry found:")
30
33
  print(finder.spacegroup)
31
- print(f"-" * 30)
34
+ print("-" * 30)
32
35
  self.pgdict = finder.get_symmetry_pair_group_dict()
33
36
  self.exc = exc
34
37
  self.new_exc = copy.deepcopy(exc)
38
+ self.Jonly = Jonly
35
39
 
36
40
  def print_license(self):
37
41
  print_license()
@@ -41,8 +45,8 @@ class TB2JSymmetrizer:
41
45
  Symmetrize the exchange parameters J.
42
46
  """
43
47
  symJdict = {}
44
- Jdict = self.exc.exchange_Jdict
45
- ngroup = self.pgdict
48
+ # Jdict = self.exc.exchange_Jdict
49
+ # ngroup = self.pgdict
46
50
  for pairgroup in self.pgdict.groups:
47
51
  ijRs = pairgroup.get_all_ijR()
48
52
  ijRs_spin = [self.exc.ijR_index_atom_to_spin(*ijR) for ijR in ijRs]
@@ -51,6 +55,14 @@ class TB2JSymmetrizer:
51
55
  for i, j, R in ijRs_spin:
52
56
  symJdict[(R, i, j)] = Javg
53
57
  self.new_exc.exchange_Jdict = symJdict
58
+ if self.Jonly:
59
+ self.new_exc.has_dmi = False
60
+ self.new_exc.dmi_ddict = None
61
+ self.new_exc.has_bilinear = False
62
+ self.new_exc.Jani_dict = None
63
+ self.has_uniaxial_anisotropy = False
64
+ self.k1 = None
65
+ self.k1dir = None
54
66
 
55
67
  def output(self, path="TB2J_symmetrized"):
56
68
  if path is None:
@@ -72,6 +84,7 @@ def symmetrize_J(
72
84
  fname="TB2J.pickle",
73
85
  symprec=1e-5,
74
86
  output_path="TB2J_symmetrized",
87
+ Jonly=False,
75
88
  ):
76
89
  """
77
90
  symmetrize the exchange parameters
@@ -80,7 +93,7 @@ def symmetrize_J(
80
93
  """
81
94
  if exc is None:
82
95
  exc = SpinIO.load_pickle(path=path, fname=fname)
83
- symmetrizer = TB2JSymmetrizer(exc, symprec=symprec)
96
+ symmetrizer = TB2JSymmetrizer(exc, symprec=symprec, Jonly=Jonly)
84
97
  symmetrizer.run(path=output_path)
85
98
 
86
99
 
@@ -109,11 +122,23 @@ def symmetrize_J_cli():
109
122
  default=1e-5,
110
123
  help="precision for symmetry detection. default is 1e-5 Angstrom",
111
124
  )
125
+
126
+ parser.add_argument(
127
+ "-Jonly",
128
+ action="store_true",
129
+ help="Symmetrize only the exchange parameters. Do not output DMI and anisotropic exchange.",
130
+ )
131
+
112
132
  args = parser.parse_args()
113
133
  if args.inpath is None:
114
134
  parser.print_help()
115
135
  raise ValueError("Please provide the input path to the exchange.")
116
- symmetrize_J(path=args.inpath, output_path=args.outpath, symprec=args.symprec)
136
+ symmetrize_J(
137
+ path=args.inpath,
138
+ output_path=args.outpath,
139
+ symprec=args.symprec,
140
+ Jonly=args.Jonly,
141
+ )
117
142
 
118
143
 
119
144
  if __name__ == "__main__":
@@ -1,6 +1,7 @@
1
- import TB2J
2
1
  from datetime import datetime
3
2
 
3
+ import TB2J
4
+
4
5
 
5
6
  def print_license():
6
7
  print(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.9.9rc3
3
+ Version: 0.9.9rc5
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
@@ -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_rc3"
4
+ __version__ = "0.9.9_rc5"
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
 
@@ -1,16 +0,0 @@
1
- import numpy as np
2
-
3
-
4
- def monkhorst_pack(size, gamma_center=False):
5
- """Construct a uniform sampling of k-space of given size.
6
- Modified from ase.dft.kpoints with gamma_center option added"""
7
- if np.less_equal(size, 0).any():
8
- raise ValueError("Illegal size: %s" % list(size))
9
- kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3))
10
- asize = np.array(size)
11
- shift = 0.5 * ((asize + 1) % 2) / asize
12
- mkpts = (kpts + 0.5) / size - 0.5
13
- if gamma_center:
14
- mkpts += shift
15
-
16
- return mkpts
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
File without changes