TB2J 0.9.5rc0__py3-none-any.whl → 0.9.6rc0__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.
Files changed (58) hide show
  1. TB2J/MAE.py +107 -24
  2. TB2J/anisotropy.py +672 -0
  3. TB2J/contour.py +8 -0
  4. TB2J/exchange.py +43 -103
  5. TB2J/exchangeCL2.py +11 -13
  6. TB2J/exchange_params.py +213 -0
  7. TB2J/green.py +62 -27
  8. TB2J/interfaces/__init__.py +12 -0
  9. TB2J/interfaces/abacus/__init__.py +4 -0
  10. TB2J/{abacus → interfaces/abacus}/abacus_api.py +3 -3
  11. TB2J/{abacus → interfaces/abacus}/abacus_wrapper.py +11 -8
  12. TB2J/{abacus → interfaces/abacus}/gen_exchange_abacus.py +5 -3
  13. TB2J/{abacus → interfaces/abacus}/orbital_api.py +4 -4
  14. TB2J/{abacus → interfaces/abacus}/stru_api.py +11 -11
  15. TB2J/{abacus → interfaces/abacus}/test_read_HRSR.py +0 -1
  16. TB2J/{abacus → interfaces/abacus}/test_read_stru.py +5 -3
  17. TB2J/interfaces/gpaw_interface.py +54 -0
  18. TB2J/interfaces/lawaf_interface.py +129 -0
  19. TB2J/interfaces/manager.py +23 -0
  20. TB2J/interfaces/siesta_interface.py +174 -0
  21. TB2J/interfaces/wannier90_interface.py +115 -0
  22. TB2J/io_exchange/io_exchange.py +21 -7
  23. TB2J/io_merge.py +2 -1
  24. TB2J/mathutils/fermi.py +11 -6
  25. TB2J/mathutils/lowdin.py +12 -2
  26. TB2J/mathutils/rotate_spin.py +222 -4
  27. TB2J/pauli.py +11 -3
  28. TB2J/symmetrize_J.py +120 -0
  29. TB2J/utils.py +82 -1
  30. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/abacus2J.py +5 -4
  31. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/siesta2J.py +21 -4
  32. TB2J-0.9.6rc0.data/scripts/wann2J.py +96 -0
  33. {TB2J-0.9.5rc0.dist-info → TB2J-0.9.6rc0.dist-info}/METADATA +5 -3
  34. {TB2J-0.9.5rc0.dist-info → TB2J-0.9.6rc0.dist-info}/RECORD +46 -46
  35. {TB2J-0.9.5rc0.dist-info → TB2J-0.9.6rc0.dist-info}/WHEEL +1 -1
  36. TB2J-0.9.6rc0.dist-info/entry_points.txt +3 -0
  37. TB2J/abacus/MAE.py +0 -320
  38. TB2J/abacus/__init__.py +0 -1
  39. TB2J/abacus/occupations.py +0 -278
  40. TB2J/cut_cell.py +0 -82
  41. TB2J/io_exchange/io_pickle.py +0 -0
  42. TB2J/manager.py +0 -445
  43. TB2J/mathutils.py +0 -12
  44. TB2J/patch.py +0 -50
  45. TB2J/spinham/h_matrix.py +0 -68
  46. TB2J/spinham/obtain_J.py +0 -79
  47. TB2J/supercell.py +0 -532
  48. TB2J-0.9.5rc0.data/scripts/wann2J.py +0 -194
  49. TB2J/{abacus → interfaces/abacus}/test_density_matrix.py +1 -1
  50. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_downfold.py +0 -0
  51. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_eigen.py +0 -0
  52. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_magnon.py +0 -0
  53. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_magnon_dos.py +0 -0
  54. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_merge.py +0 -0
  55. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_rotate.py +0 -0
  56. {TB2J-0.9.5rc0.data → TB2J-0.9.6rc0.data}/scripts/TB2J_rotateDM.py +0 -0
  57. {TB2J-0.9.5rc0.dist-info → TB2J-0.9.6rc0.dist-info}/LICENSE +0 -0
  58. {TB2J-0.9.5rc0.dist-info → TB2J-0.9.6rc0.dist-info}/top_level.txt +0 -0
TB2J/exchange.py CHANGED
@@ -1,91 +1,23 @@
1
- from collections import defaultdict, OrderedDict
2
1
  import os
3
- import numpy as np
4
2
  import pickle
5
- from dataclasses import dataclass
6
- import yaml
7
- from TB2J.green import TBGreen
8
- from TB2J.pauli import pauli_block_all, pauli_block_sigma_norm, pauli_mat
9
- from TB2J.utils import symbol_number, kmesh_to_R
10
- from TB2J.io_exchange import SpinIO
3
+ from collections import OrderedDict, defaultdict
4
+
5
+ import numpy as np
11
6
  from tqdm import tqdm
12
- from TB2J.external import p_map
7
+
13
8
  from TB2J.contour import Contour
14
- from TB2J.utils import simpson_nonuniform, trapezoidal_nonuniform, split_symbol_number
9
+ from TB2J.exchange_params import ExchangeParams
10
+ from TB2J.external import p_map
11
+ from TB2J.green import TBGreen
12
+ from TB2J.io_exchange import SpinIO
15
13
  from TB2J.orbmap import map_orbs_matrix
16
- from typing import List, Tuple
17
-
18
-
19
- @dataclass
20
- class ExchangeParams:
21
- """
22
- A class to store the parameters for exchange calculation.
23
- """
24
-
25
- efermi: float
26
- basis: list = None
27
- magnetic_elements: list = None
28
- include_orbs = {}
29
- _kmesh = [4, 4, 4]
30
- emin: float = -15
31
- emax: float = 0.05
32
- nz: int = 100
33
- exclude_orbs = []
34
- ne: int = None
35
- Rcut: float = None
36
- _use_cache: bool = False
37
- np: int = 1
38
- description: str = ""
39
- write_density_matrix: bool = False
40
- orb_decomposition: bool = False
41
- output_path: str = "TB2J_results"
42
- mae_angles = None
43
-
44
- def __init__(
45
- self,
46
- efermi=-10.0,
47
- basis=None,
48
- magnetic_elements=None,
49
- include_orbs=None,
50
- kmesh=[4, 4, 4],
51
- emin=-15,
52
- emax=0.05,
53
- nz=100,
54
- exclude_orbs=[],
55
- ne=None,
56
- Rcut=None,
57
- use_cache=False,
58
- np=1,
59
- description="",
60
- write_density_matrix=False,
61
- orb_decomposition=False,
62
- output_path="TB2J_results",
63
- ):
64
- self.efermi = efermi
65
- self.basis = basis
66
- self.magnetic_elements = magnetic_elements
67
- self.include_orbs = include_orbs
68
- self._kmesh = kmesh
69
- self.emin = emin
70
- self.emax = emax
71
- self.nz = nz
72
- self.exclude_orbs = exclude_orbs
73
- self.ne = ne
74
- self.Rcut = Rcut
75
- self._use_cache = use_cache
76
- self.np = np
77
- self.description = description
78
- self.write_density_matrix = write_density_matrix
79
- self.orb_decomposition = orb_decomposition
80
- self.output_path = output_path
81
-
82
- def set_params(self, **kwargs):
83
- for key, val in kwargs.items():
84
- setattr(self, key, val)
85
-
86
- def save_to_yaml(self, fname):
87
- with open(fname, "w") as myfile:
88
- yaml.dump(self.__dict__, myfile)
14
+ from TB2J.pauli import pauli_block_all, pauli_block_sigma_norm, pauli_mat
15
+ from TB2J.utils import (
16
+ kmesh_to_R,
17
+ simpson_nonuniform,
18
+ symbol_number,
19
+ trapezoidal_nonuniform,
20
+ )
89
21
 
90
22
 
91
23
  class Exchange(ExchangeParams):
@@ -219,9 +151,9 @@ class Exchange(ExchangeParams):
219
151
  raise ValueError(
220
152
  f"""The number of spin-orbitals for atom {iatom} is not even,
221
153
  {nsorb} spin-orbitals are found near this atom.
222
- which means the spin up/down does not have same number of orbitals.
154
+ which means the spin up/down does not have same number of orbitals.
223
155
  This is often because the Wannier functions are wrongly defined,
224
- or badly localized. Please check the Wannier centers in the Wannier90 output file.
156
+ or badly localized. Please check the Wannier centers in the Wannier90 output file.
225
157
  """
226
158
  )
227
159
  self._spin_dict = {}
@@ -331,12 +263,14 @@ class ExchangeNCL(Exchange):
331
263
  self.tbmodel = tbmodels
332
264
  self.backend_name = self.tbmodel.name
333
265
  self.G = TBGreen(
334
- self.tbmodel,
335
- self.kmesh,
336
- self.efermi,
266
+ tbmodel=self.tbmodel,
267
+ kmesh=self.kmesh,
268
+ efermi=self.efermi,
337
269
  use_cache=self._use_cache,
338
- nproc=self.np,
270
+ nproc=self.nproc,
339
271
  )
272
+ if self.efermi is None:
273
+ self.efermi = self.G.efermi
340
274
  self.norb = self.G.norb
341
275
  self.nbasis = self.G.nbasis
342
276
  # self.rho = np.zeros((self.nbasis, self.nbasis), dtype=complex)
@@ -344,7 +278,11 @@ class ExchangeNCL(Exchange):
344
278
  self.A_ijR_list = defaultdict(lambda: [])
345
279
  self.A_ijR = defaultdict(lambda: np.zeros((4, 4), dtype=complex))
346
280
  self.A_ijR_orb = dict()
347
- self.HR0 = self.G.H0
281
+ # self.HR0 = self.tbmodel.get_H0()
282
+ if hasattr(self.tbmodel, "get_H0"):
283
+ self.HR0 = self.tbmodel.get_H0()
284
+ else:
285
+ self.HR0 = self.G.H0
348
286
  self._is_collinear = False
349
287
  self.Pdict = {}
350
288
  if self.write_density_matrix:
@@ -477,7 +415,7 @@ class ExchangeNCL(Exchange):
477
415
  if self.orb_decomposition:
478
416
  for key, val in self.A_ijR_orb.items():
479
417
  R, iatom, jatom = key
480
- Rm = tuple(-x for x in R)
418
+ # Rm = tuple(-x for x in R)
481
419
  # valm = self.A_ijR_orb[(Rm, jatom, iatom)]
482
420
  ni = self.norb_reduced[iatom]
483
421
  nj = self.norb_reduced[jatom]
@@ -695,21 +633,23 @@ class ExchangeNCL(Exchange):
695
633
  TODO: This is only a place holder.
696
634
  """
697
635
  return None
698
- Hso_k = self.model.get_Hso_k(k)
699
- mae_e = np.zeros(len(self.mae_angles), dtype=complex)
700
- # rotate the Hso_k to angles
701
- for ik, k in enumerate(self.G.kpoints):
702
- Gk = Gk_all[ik]
703
- for i_angle, angle in enumerate(self.mae_angles):
704
- # TODO: implementa rotate_H
705
- Hso_k_rot = rotate_H(Hso_k, angle)
706
- mae_e[i_angle] = Gk @ Hso_k @ Gk @ Hso_k
707
- return mae_e
636
+
637
+ # mae_e = np.zeros(len(self.mae_angles), dtype=complex)
638
+ # # rotate the Hso_k to angles
639
+ # for ik, k in enumerate(self.G.kpoints):
640
+ # Hso_k = self.model.get_Hso_k(k)
641
+ # Gk = Gk_all[ik]
642
+ # for i_angle, angle in enumerate(self.mae_angles):
643
+ # # TODO: implementa rotate_H
644
+ # Hso_k_rot = rotate_H(Hso_k, angle)
645
+ # mae_e[i_angle] = Gk @ Hso_k @ Gk @ Hso_k
646
+ # return mae_e
708
647
 
709
648
  def get_mae_rspace(self, GR):
710
649
  """
711
650
  get the MAE from GR
712
651
  """
652
+ raise NotImplementedError("Not yet implemented.")
713
653
 
714
654
  def save_AijR(self, AijRs, fname):
715
655
  result = dict(path=self.contour.path, AijRs=AijRs)
@@ -734,9 +674,9 @@ class ExchangeNCL(Exchange):
734
674
  self.validate()
735
675
 
736
676
  npole = len(self.contour.path)
737
- if self.np > 1:
677
+ if self.nproc > 1:
738
678
  results = p_map(
739
- self.get_quantities_per_e, self.contour.path, num_cpus=self.np
679
+ self.get_quantities_per_e, self.contour.path, num_cpus=self.nproc
740
680
  )
741
681
  else:
742
682
  results = map(
TB2J/exchangeCL2.py CHANGED
@@ -20,18 +20,18 @@ class ExchangeCL2(ExchangeCL):
20
20
  self.tbmodel_up, self.tbmodel_dn = tbmodels
21
21
  self.backend_name = self.tbmodel_up.name
22
22
  self.Gup = TBGreen(
23
- self.tbmodel_up,
24
- self.kmesh,
25
- self.efermi,
23
+ tbmodel=self.tbmodel_up,
24
+ kmesh=self.kmesh,
25
+ efermi=self.efermi,
26
26
  use_cache=self._use_cache,
27
- nproc=self.np,
27
+ nproc=self.nproc,
28
28
  )
29
29
  self.Gdn = TBGreen(
30
- self.tbmodel_dn,
31
- self.kmesh,
32
- self.efermi,
30
+ tbmodel=self.tbmodel_dn,
31
+ kmesh=self.kmesh,
32
+ efermi=self.efermi,
33
33
  use_cache=self._use_cache,
34
- nproc=self.np,
34
+ nproc=self.nproc,
35
35
  )
36
36
  if self.write_density_matrix:
37
37
  self.Gup.write_rho_R(
@@ -247,15 +247,15 @@ class ExchangeCL2(ExchangeCL):
247
247
  print("Green's function Calculation started.")
248
248
 
249
249
  npole = len(self.contour.path)
250
- if self.np == 1:
250
+ if self.nproc == 1:
251
251
  results = map(
252
252
  self.get_quantities_per_e, tqdm(self.contour.path, total=npole)
253
253
  )
254
254
  else:
255
- # pool = ProcessPool(nodes=self.np)
255
+ # pool = ProcessPool(nodes=self.nproc)
256
256
  # results = pool.map(self.get_AijR_rhoR ,self.contour.path)
257
257
  results = p_map(
258
- self.get_quantities_per_e, self.contour.path, num_cpus=self.np
258
+ self.get_quantities_per_e, self.contour.path, num_cpus=self.nproc
259
259
  )
260
260
  for i, result in enumerate(results):
261
261
  Jorb_list = result["Jorb_list"]
@@ -265,8 +265,6 @@ class ExchangeCL2(ExchangeCL):
265
265
  key = (R, iatom, jatom)
266
266
  self.Jorb_list[key].append(Jorb_list[key])
267
267
  self.JJ_list[key].append(JJ_list[key])
268
- if self.np > 1:
269
- pass
270
268
  self.integrate()
271
269
  self.get_rho_atom()
272
270
  self.A_to_Jtensor()
@@ -0,0 +1,213 @@
1
+ import argparse
2
+ from dataclasses import dataclass
3
+
4
+ import yaml
5
+
6
+ __all__ = ["ExchangeParams", "add_exchange_args_to_parser", "parser_argument_to_dict"]
7
+
8
+
9
+ @dataclass
10
+ class ExchangeParams:
11
+ """
12
+ A class to store the parameters for exchange calculation.
13
+ """
14
+
15
+ efermi: float
16
+ basis = []
17
+ magnetic_elements = []
18
+ include_orbs = {}
19
+ _kmesh = [4, 4, 4]
20
+ emin: float = -15
21
+ emax: float = 0.05
22
+ nz: int = 100
23
+ exclude_orbs = []
24
+ ne: int = 0
25
+ Rcut: float = None
26
+ _use_cache: bool = False
27
+ nproc: int = 1
28
+ description: str = ""
29
+ write_density_matrix: bool = False
30
+ orb_decomposition: bool = False
31
+ output_path: str = "TB2J_results"
32
+ mae_angles = None
33
+ orth = False
34
+
35
+ def __init__(
36
+ self,
37
+ efermi=-10.0,
38
+ basis=None,
39
+ magnetic_elements=None,
40
+ include_orbs=None,
41
+ kmesh=[4, 4, 4],
42
+ emin=-15,
43
+ emax=0.05,
44
+ nz=100,
45
+ ne=None,
46
+ Rcut=None,
47
+ use_cache=False,
48
+ nproc=1,
49
+ description="",
50
+ write_density_matrix=False,
51
+ orb_decomposition=False,
52
+ output_path="TB2J_results",
53
+ exclude_orbs=[],
54
+ mae_angles=None,
55
+ orth=False,
56
+ ):
57
+ self.efermi = efermi
58
+ self.basis = basis
59
+ self.magnetic_elements = magnetic_elements
60
+ self.include_orbs = include_orbs
61
+ self._kmesh = kmesh
62
+ self.emin = emin
63
+ self.emax = emax
64
+ self.nz = nz
65
+ self.exclude_orbs = exclude_orbs
66
+ self.ne = ne
67
+ self.Rcut = Rcut
68
+ self._use_cache = use_cache
69
+ self.nproc = nproc
70
+ self.description = description
71
+ self.write_density_matrix = write_density_matrix
72
+ self.orb_decomposition = orb_decomposition
73
+ self.output_path = output_path
74
+ self.mae_angles = mae_angles
75
+ self.orth = orth
76
+
77
+ def set_params(self, **kwargs):
78
+ for key, val in kwargs.items():
79
+ setattr(self, key, val)
80
+
81
+ def save_to_yaml(self, fname):
82
+ with open(fname, "w") as myfile:
83
+ yaml.dump(self.__dict__, myfile)
84
+
85
+
86
+ def add_exchange_args_to_parser(parser: argparse.ArgumentParser):
87
+ parser.add_argument(
88
+ "--elements",
89
+ help="elements to be considered in Heisenberg model",
90
+ default=None,
91
+ type=str,
92
+ nargs="*",
93
+ )
94
+ parser.add_argument(
95
+ "--rcut",
96
+ help="cutoff of spin pair distance. The default is to calculate all commensurate R point to the k mesh.",
97
+ default=None,
98
+ type=float,
99
+ )
100
+ parser.add_argument("--efermi", help="Fermi energy in eV", default=None, type=float)
101
+ parser.add_argument(
102
+ "--ne",
103
+ help="number of electrons in the unit cell. If not given, TB2J will use the fermi energy to compute it.",
104
+ )
105
+ parser.add_argument(
106
+ "--kmesh",
107
+ help="kmesh in the format of kx ky kz",
108
+ type=int,
109
+ nargs="*",
110
+ default=[5, 5, 5],
111
+ )
112
+ parser.add_argument(
113
+ "--emin",
114
+ help="energy minimum below efermi, default -14 eV",
115
+ type=float,
116
+ default=-14.0,
117
+ )
118
+ parser.add_argument(
119
+ "--emax",
120
+ help="energy maximum above efermi, default 0.0 eV",
121
+ type=float,
122
+ default=0.0,
123
+ )
124
+ parser.add_argument(
125
+ "--nz",
126
+ help="number of steps for semicircle contour, default: 100",
127
+ default=100,
128
+ type=int,
129
+ )
130
+ parser.add_argument(
131
+ "--cutoff",
132
+ help="The minimum of J amplitude to write, (in eV), default is 1e-5 eV",
133
+ default=1e-5,
134
+ type=float,
135
+ )
136
+ parser.add_argument(
137
+ "--exclude_orbs",
138
+ help="the indices of wannier functions to be excluded from magnetic site. counting start from 0",
139
+ default=[],
140
+ type=int,
141
+ nargs="+",
142
+ )
143
+
144
+ parser.add_argument(
145
+ "--np",
146
+ "--nproc",
147
+ help="number of cpu cores to use in parallel, default: 1",
148
+ default=1,
149
+ type=int,
150
+ )
151
+
152
+ parser.add_argument(
153
+ "--use_cache",
154
+ help="whether to use disk file for temporary storing wavefunctions and hamiltonian to reduce memory usage. Default: False",
155
+ action="store_true",
156
+ default=False,
157
+ )
158
+
159
+ parser.add_argument(
160
+ "--description",
161
+ help="add description of the calculatiion to the xml file. Essential information, like the xc functional, U values, magnetic state should be given.",
162
+ type=str,
163
+ default="Calculated with TB2J.",
164
+ )
165
+
166
+ parser.add_argument(
167
+ "--orb_decomposition",
168
+ default=False,
169
+ action="store_true",
170
+ help="whether to do orbital decomposition in the non-collinear mode.",
171
+ )
172
+
173
+ parser.add_argument(
174
+ "--output_path",
175
+ help="The path of the output directory, default is TB2J_results",
176
+ type=str,
177
+ default="TB2J_results",
178
+ )
179
+ parser.add_argument(
180
+ "--write_dm",
181
+ help="whether to write density matrix",
182
+ action="store_true",
183
+ default=False,
184
+ )
185
+
186
+ parser.add_argument(
187
+ "--orth",
188
+ help="whether to use lowdin orthogonalization before diagonalization (for testing only)",
189
+ action="store_true",
190
+ default=False,
191
+ )
192
+ return parser
193
+
194
+
195
+ def parser_argument_to_dict(args) -> dict:
196
+ return {
197
+ "efermi": args.efermi,
198
+ "magnetic_elements": args.elements,
199
+ "kmesh": args.kmesh,
200
+ "emin": args.emin,
201
+ "emax": args.emax,
202
+ "nz": args.nz,
203
+ "exclude_orbs": args.exclude_orbs,
204
+ "ne": args.ne,
205
+ "Rcut": args.rcut,
206
+ "use_cache": args.use_cache,
207
+ "nproc": args.np,
208
+ "description": args.description,
209
+ "write_density_matrix": args.write_dm,
210
+ "orb_decomposition": args.orb_decomposition,
211
+ "output_path": args.output_path,
212
+ "orth": args.orth,
213
+ }
TB2J/green.py CHANGED
@@ -1,14 +1,19 @@
1
- import numpy as np
2
- from collections import defaultdict
3
- from ase.dft.kpoints import monkhorst_pack
4
- from shutil import rmtree
1
+ import copy
5
2
  import os
3
+ import pickle
4
+ import sys
6
5
  import tempfile
6
+ from collections import defaultdict
7
+ from shutil import rmtree
8
+
9
+ import numpy as np
10
+ from HamiltonIO.model.occupations import Occupations
11
+ from HamiltonIO.model.occupations import myfermi as fermi
7
12
  from pathos.multiprocessing import ProcessPool
8
- import sys
9
- import pickle
10
- import warnings
11
- from TB2J.mathutils.fermi import fermi
13
+
14
+ from TB2J.kpoints import monkhorst_pack
15
+
16
+ # from TB2J.mathutils.fermi import fermi
12
17
 
13
18
  MAX_EXP_ARGUMENT = np.log(sys.float_info.max)
14
19
 
@@ -22,9 +27,16 @@ def eigen_to_G(evals, evecs, efermi, energy):
22
27
  :returns: Green's function G,
23
28
  :rtype: Matrix with same shape of the Hamiltonian (and eigenvector)
24
29
  """
25
- return (
26
- np.einsum("ij, j-> ij", evecs, 1.0 / (-evals + (energy + efermi)))
27
- @ evecs.conj().T
30
+ # return (
31
+ # np.einsum("ij, j-> ij", evecs, 1.0 / (-evals + (energy + efermi)))
32
+ # @ evecs.conj().T
33
+ # )
34
+ return np.einsum(
35
+ "ib, b, jb-> ij",
36
+ evecs,
37
+ 1.0 / (-evals + (energy + efermi)),
38
+ evecs.conj(),
39
+ optimize=True,
28
40
  )
29
41
 
30
42
 
@@ -46,8 +58,10 @@ class TBGreen:
46
58
  def __init__(
47
59
  self,
48
60
  tbmodel,
49
- kmesh, # [ikpt, 3]
50
- efermi, # efermi
61
+ kmesh=None, # [ikpt, 3]
62
+ efermi=None, # efermi
63
+ gamma=False,
64
+ kpts=None,
51
65
  k_sym=False,
52
66
  use_cache=False,
53
67
  cache_path=None,
@@ -67,12 +81,14 @@ class TBGreen:
67
81
  self.cache_path = cache_path
68
82
  if use_cache:
69
83
  self._prepare_cache()
70
- if kmesh is not None:
71
- self.kpts = monkhorst_pack(size=kmesh)
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)
72
88
  else:
73
89
  self.kpts = tbmodel.get_kpts()
74
90
  self.nkpts = len(self.kpts)
75
- self.kweights = [1.0 / self.nkpts] * self.nkpts
91
+ self.kweights = np.array([1.0 / self.nkpts] * self.nkpts)
76
92
  self.norb = tbmodel.norb
77
93
  self.nbasis = tbmodel.nbasis
78
94
  self.k_sym = k_sym
@@ -145,9 +161,19 @@ class TBGreen:
145
161
  if not saveH:
146
162
  self.H = None
147
163
 
148
- self.evals, self.evecs = self._reduce_eigens(
149
- self.evals, self.evecs, emin=self.efermi - 10.0, emax=self.efermi + 10.1
150
- )
164
+ # get efermi
165
+ if self.efermi is None:
166
+ print("Calculating Fermi energy from eigenvalues")
167
+ print(f"Number of electrons: {self.tbmodel.nel} ")
168
+ occ = Occupations(
169
+ nel=self.tbmodel.nel, width=0.05, wk=self.kweights, nspin=2
170
+ )
171
+ self.efermi = occ.efermi(copy.deepcopy(self.evals))
172
+ print(f"Fermi energy found: {self.efermi}")
173
+
174
+ # self.evals, self.evecs = self._reduce_eigens(
175
+ # self.evals, self.evecs, emin=self.efermi - 15.0, emax=self.efermi + 10.1
176
+ # )
151
177
  if self._use_cache:
152
178
  evecs = self.evecs
153
179
  self.evecs_shape = self.evecs.shape
@@ -216,20 +242,22 @@ class TBGreen:
216
242
  rho = np.zeros((self.nbasis, self.nbasis), dtype=complex)
217
243
  if self.is_orthogonal:
218
244
  for ik, _ in enumerate(self.kpts):
245
+ evecs_k = self.get_evecs(ik)
246
+ # chekc if any of the evecs element is nan
219
247
  rho += (
220
- (self.get_evecs(ik) * fermi(self.evals[ik], self.efermi))
221
- @ self.get_evecs(ik).T.conj()
248
+ (evecs_k * fermi(self.evals[ik], self.efermi, nspin=2))
249
+ @ evecs_k.T.conj()
222
250
  * self.kweights[ik]
223
251
  )
224
252
  else:
225
253
  for ik, _ in enumerate(self.kpts):
226
254
  rho += (
227
- (self.get_evecs(ik) * fermi(self.evals[ik], self.efermi))
255
+ (self.get_evecs(ik) * fermi(self.evals[ik], self.efermi, nspin=2))
228
256
  @ self.get_evecs(ik).T.conj()
229
257
  @ self.get_Sk(ik)
230
258
  * self.kweights[ik]
231
259
  )
232
-
260
+ # check if rho has nan values
233
261
  return rho
234
262
 
235
263
  def get_rho_R(self, Rlist):
@@ -238,7 +266,10 @@ class TBGreen:
238
266
  for ik, kpt in enumerate(self.kpts):
239
267
  evec = self.get_evecs(ik)
240
268
  rhok = np.einsum(
241
- "ib,b, bj-> ij", evec, fermi(self.evals[ik], self.efermi), evec.conj().T
269
+ "ib,b, bj-> ij",
270
+ evec,
271
+ fermi(self.evals[ik], self.efermi, nspin=2),
272
+ evec.conj().T,
242
273
  )
243
274
  for iR, R in enumerate(Rlist):
244
275
  rho_R[iR] += rhok * np.exp(self.k2Rfactor * kpt @ R) * self.kweights[ik]
@@ -252,16 +283,20 @@ class TBGreen:
252
283
  def get_density(self):
253
284
  return np.real(np.diag(self.get_density_matrix()))
254
285
 
255
- def get_Gk(self, ik, energy):
286
+ def get_Gk(self, ik, energy, evals=None, evecs=None):
256
287
  """Green's function G(k) for one energy
257
288
  G(\epsilon)= (\epsilon I- H)^{-1}
258
289
  :param ik: indices for kpoint
259
290
  :returns: Gk
260
291
  :rtype: a matrix of indices (nbasis, nbasis)
261
292
  """
293
+ if evals is None:
294
+ evals = self.get_evalue(ik)
295
+ if evecs is None:
296
+ evecs = self.get_evecs(ik)
262
297
  Gk = eigen_to_G(
263
- evals=self.get_evalue(ik),
264
- evecs=self.get_evecs(ik),
298
+ evals=evals,
299
+ evecs=evecs,
265
300
  efermi=self.efermi,
266
301
  energy=energy,
267
302
  )
@@ -0,0 +1,12 @@
1
+ from .abacus import gen_exchange_abacus
2
+ from .manager import Manager
3
+ from .siesta_interface import gen_exchange_siesta
4
+ from .wannier90_interface import WannierManager, gen_exchange
5
+
6
+ __all__ = [
7
+ "Manager",
8
+ "gen_exchange_siesta",
9
+ "WannierManager",
10
+ "gen_exchange",
11
+ "gen_exchange_abacus",
12
+ ]
@@ -0,0 +1,4 @@
1
+ from .abacus_wrapper import AbacusParser, AbacusWrapper
2
+ from .gen_exchange_abacus import gen_exchange_abacus
3
+
4
+ __all__ = ["AbacusWrapper", "AbacusParser", "gen_exchange_abacus"]
@@ -1,10 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
- import numpy as np
3
- from scipy import sparse
4
- from scipy.sparse import csr_matrix
5
2
  import re
6
3
  import struct
7
4
 
5
+ import numpy as np
6
+ from scipy.sparse import csr_matrix
7
+
8
8
 
9
9
  class XR_matrix:
10
10
  def __init__(self, nspin, XR_fileName):