TB2J 0.8.2.8__tar.gz → 0.9.0.1__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 (87) hide show
  1. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/PKG-INFO +9 -4
  2. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/README.md +2 -0
  3. TB2J-0.9.0.1/TB2J/__init__.py +1 -0
  4. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/abacus_wrapper.py +1 -2
  5. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchange.py +3 -3
  6. TB2J-0.9.0.1/TB2J/io_merge.py +184 -0
  7. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/myTB.py +0 -2
  8. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/rotate_atoms.py +22 -20
  9. TB2J-0.9.0.1/TB2J/rotate_siestaDM.py +36 -0
  10. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/sisl_wrapper.py +0 -1
  11. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/PKG-INFO +9 -4
  12. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/SOURCES.txt +2 -2
  13. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_merge.py +9 -2
  14. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_rotate.py +6 -1
  15. TB2J-0.9.0.1/scripts/TB2J_rotateDM.py +21 -0
  16. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/setup.py +2 -1
  17. TB2J-0.8.2.8/TB2J/__init__.py +0 -1
  18. TB2J-0.8.2.8/TB2J/io_merge.py +0 -435
  19. TB2J-0.8.2.8/TB2J/spinham/h_matrix.py +0 -68
  20. TB2J-0.8.2.8/TB2J/spinham/obtain_J.py +0 -79
  21. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/LICENSE +0 -0
  22. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Jdownfolder.py +0 -0
  23. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Jtensor.py +0 -0
  24. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Oiju.py +0 -0
  25. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/Oiju_epc.py +0 -0
  26. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/__init__.py +0 -0
  27. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/abacus_api.py +0 -0
  28. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/gen_exchange_abacus.py +0 -0
  29. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/orbital_api.py +0 -0
  30. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/stru_api.py +0 -0
  31. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/test_read_HRSR.py +0 -0
  32. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/abacus/test_read_stru.py +0 -0
  33. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/basis.py +0 -0
  34. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/citation.py +0 -0
  35. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/contour.py +0 -0
  36. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/density_matrix.py +0 -0
  37. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/epc.py +0 -0
  38. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchangeCL2.py +0 -0
  39. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchange_pert.py +0 -0
  40. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/exchange_qspace.py +0 -0
  41. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/external/__init__.py +0 -0
  42. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/external/p_tqdm.py +0 -0
  43. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/gpaw_wrapper.py +0 -0
  44. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/green.py +0 -0
  45. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/greentest.py +0 -0
  46. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/__init__.py +0 -0
  47. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_exchange.py +0 -0
  48. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_multibinit.py +0 -0
  49. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_tomsasd.py +0 -0
  50. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_txt.py +0 -0
  51. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_uppasd.py +0 -0
  52. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/io_exchange/io_vampire.py +0 -0
  53. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/kpoints.py +0 -0
  54. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/manager.py +0 -0
  55. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/mathutils.py +0 -0
  56. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/orbmap.py +0 -0
  57. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/pauli.py +0 -0
  58. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/pert.py +0 -0
  59. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/plot.py +0 -0
  60. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/__init__.py +0 -0
  61. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/base_parser.py +0 -0
  62. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/constants.py +0 -0
  63. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/hamiltonian.py +0 -0
  64. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/hamiltonian_terms.py +0 -0
  65. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/plot.py +0 -0
  66. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/qsolver.py +0 -0
  67. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/spin_api.py +0 -0
  68. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/spin_xml.py +0 -0
  69. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/spinham/supercell.py +0 -0
  70. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/tensor_rotate.py +0 -0
  71. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/utest.py +0 -0
  72. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/utils.py +0 -0
  73. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/versioninfo.py +0 -0
  74. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/wannier/__init__.py +0 -0
  75. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/wannier/w90_parser.py +0 -0
  76. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J/wannier/w90_tb_parser.py +0 -0
  77. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/dependency_links.txt +0 -0
  78. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/requires.txt +5 -5
  79. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/TB2J.egg-info/top_level.txt +0 -0
  80. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_downfold.py +0 -0
  81. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_eigen.py +0 -0
  82. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_magnon.py +0 -0
  83. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/TB2J_magnon_dos.py +0 -0
  84. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/abacus2J.py +0 -0
  85. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/siesta2J.py +0 -0
  86. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/scripts/wann2J.py +0 -0
  87. {TB2J-0.8.2.8 → TB2J-0.9.0.1}/setup.cfg +0 -0
@@ -1,12 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.8.2.8
3
+ Version: 0.9.0.1
4
4
  Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
5
- Home-page: UNKNOWN
6
5
  Author: Xu He
7
6
  Author-email: mailhexu@gmail.com
8
7
  License: BSD-2-clause
9
- Platform: UNKNOWN
10
8
  Classifier: Development Status :: 3 - Alpha
11
9
  Classifier: Programming Language :: Python :: 3
12
10
  Classifier: Operating System :: OS Independent
@@ -16,6 +14,13 @@ Classifier: Topic :: Scientific/Engineering :: Physics
16
14
  Classifier: License :: OSI Approved :: BSD License
17
15
  Requires-Python: >=3.6
18
16
  License-File: LICENSE
17
+ Requires-Dist: numpy>1.16.5
18
+ Requires-Dist: scipy
19
+ Requires-Dist: matplotlib
20
+ Requires-Dist: ase>=3.19
21
+ Requires-Dist: tqdm
22
+ Requires-Dist: pathos
23
+ Requires-Dist: packaging>=20.0
24
+ Requires-Dist: pre-commit
19
25
 
20
26
  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.
21
-
@@ -7,6 +7,8 @@
7
7
 
8
8
  TB2J is a open source python package for calculating the magnetic interaction parameters in Heisenberg models from DFT. It use the magnetic force theorem and take the local rigid spin rotation as a perturbation in the Green's function method.
9
9
 
10
+ The TB2J project is initialized in the PhyTheMa and Nanomat teams in the University of Liege.
11
+
10
12
  The features include:
11
13
  - Calculates parameters in Heisenberg model, including isotropic exchange, anisotropic exchange, Dyzanoshinskii-Moriya interaction.
12
14
  - Can use the input from many DFT codes with Wannier90, e.g. Abinit, Quantum Espresso, Siesta, VASP, etc.
@@ -0,0 +1 @@
1
+ __version__ = "0.9.0.1"
@@ -18,8 +18,7 @@ class AbacusWrapper(AbstractTB):
18
18
  def __init__(self, HR, SR, Rlist, nbasis, nspin=1):
19
19
  self.R2kfactor = -2j * np.pi
20
20
  self.is_orthogonal = False
21
- self.is_siesta = False
22
- self._name = "Abacus"
21
+ self._name = "ABACUS"
23
22
  self.HR = HR
24
23
  self.SR = SR
25
24
  self.Rlist = Rlist
@@ -240,7 +240,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
240
240
  self.mmats = {}
241
241
  self.orbital_names = {}
242
242
  self.norb_reduced = {}
243
- if self.backend_name == "SIESTA":
243
+ if self.backend_name.upper() == "SIESTA":
244
244
  syms = self.atoms.get_chemical_symbols()
245
245
  for iatom, orbs in self.labels.items():
246
246
  if (self.include_orbs is not None) and syms[iatom] in self.include_orbs:
@@ -305,7 +305,7 @@ or badly localized. Please check the Wannier centers in the Wannier90 output fil
305
305
  """
306
306
  sum up the contribution of all the orbitals with same (n,l,m)
307
307
  """
308
- if self.backend_name == "SIESTA":
308
+ if self.backend_name.upper() == "SIESTA":
309
309
  mmat_i = self.mmats[iatom]
310
310
  mmat_j = self.mmats[jatom]
311
311
  Jorbij = mmat_i.T @ Jorbij @ mmat_j
@@ -345,7 +345,7 @@ class ExchangeNCL(Exchange):
345
345
  self.norb = self.G.norb
346
346
  self.nbasis = self.G.nbasis
347
347
  # self.rho = np.zeros((self.nbasis, self.nbasis), dtype=complex)
348
- self.rho = self.G.get_density_matrix().real
348
+ self.rho = self.G.get_density_matrix()
349
349
  self.A_ijR_list = defaultdict(lambda: [])
350
350
  self.A_ijR = defaultdict(lambda: np.zeros((4, 4), dtype=complex))
351
351
  self.A_ijR_orb = dict()
@@ -0,0 +1,184 @@
1
+ import os
2
+ import copy
3
+ import warnings
4
+ import numpy as np
5
+ from itertools import combinations_with_replacement, product
6
+ from TB2J.io_exchange import SpinIO
7
+
8
+ u0 = np.zeros(3)
9
+ uy = np.array([0.0, 1.0, 0.0])
10
+ uz = np.array([0.0, 0.0, 1.0])
11
+
12
+ def get_Jani_coefficients(a, R=np.eye(3)):
13
+
14
+ if len(a) == 1:
15
+ u = a
16
+ v = a
17
+ else:
18
+ u = a[[0, 0, 1]]
19
+ v = a[[0, 1, 1]]
20
+
21
+ ur = u @ R.T
22
+ vr = v @ R.T
23
+ coefficients = np.hstack([ur*vr, np.roll(ur, -1, axis=-1)*vr + np.roll(vr, -1, axis=-1)*ur])
24
+
25
+ return coefficients, u, v
26
+
27
+ def get_projections(a, b, tol=1e-2):
28
+
29
+ projections = np.empty((2, 3))
30
+ if np.linalg.matrix_rank([a, b], tol=tol) == 1:
31
+ if np.linalg.matrix_rank([a, uy], tol=tol) == 1:
32
+ projections[0] = np.cross(a, uz)
33
+ else:
34
+ projections[0] = np.cross(a, uy)
35
+ projections[1] = np.cross(a, projections[0])
36
+ projections /= np.linalg.norm(projections, axis=-1).reshape(-1, 1)
37
+ else:
38
+ projections[0] = np.cross(a, b)
39
+ projections[0] /= np.linalg.norm(projections[0])
40
+ projections[1] = u0
41
+
42
+ return projections
43
+
44
+ class SpinIO_merge(SpinIO):
45
+ def __init__(self, *args, **kwargs):
46
+ super(SpinIO_merge, self).__init__(*args, **kwargs)
47
+ self.projv = None
48
+
49
+ def _set_projection_vectors(self):
50
+
51
+ spinat = self.spinat
52
+ idx = [self.ind_atoms[i] for i in self.index_spin if i >= 0]
53
+ projv = {}
54
+ for i, j in combinations_with_replacement(range(self.nspin), 2):
55
+ a, b = spinat[idx][[i, j]]
56
+ projv[i, j] = get_projections(a, b)
57
+ projv[j, i] = projv[i, j]
58
+
59
+ self.projv = projv
60
+
61
+ @classmethod
62
+ def load_pickle(cls, path='TB2J_results', fname='TB2J.pickle'):
63
+ obj = super(SpinIO_merge, cls).load_pickle(path=path, fname=fname)
64
+ obj._set_projection_vectors()
65
+
66
+ return obj
67
+
68
+ def read_pickle(path):
69
+ p1 = os.path.join(path, 'TB2J_results', 'TB2J.pickle')
70
+ p2 = os.path.join(path, 'TB2J.pickle')
71
+ if os.path.exists(p1) and os.path.exists(p2):
72
+ print(f" WARNING!: Both file {p1} and {p2} exist. Use default {p1}.")
73
+ if os.path.exists(p1):
74
+ ret = SpinIO_merge.load_pickle(os.path.join(path, 'TB2J_results'))
75
+ elif os.path.exists(p2):
76
+ ret = SpinIO_merge.load_pickle(path)
77
+ else:
78
+ raise FileNotFoundError(f"Cannot find either file {p1} or {p2}")
79
+ return ret
80
+
81
+ class Merger():
82
+ def __init__(self, *paths, main_path=None):
83
+ self.dat = [read_pickle(path) for path in paths]
84
+
85
+ if main_path is None:
86
+ self.main_dat = copy.deepcopy(self.dat[-1])
87
+ else:
88
+ self.main_dat = read_pickle(main_path)
89
+ self.dat.append(copy.deepcopy(self.main_dat))
90
+
91
+ self._set_projv()
92
+
93
+ def _set_projv(self):
94
+
95
+ cell = self.main_dat.atoms.cell.array
96
+ rotated_cells = np.stack(
97
+ [obj.atoms.cell.array for obj in self.dat], axis=0
98
+ )
99
+ R = np.linalg.solve(cell, rotated_cells)
100
+ indices = range(len(self.dat))
101
+
102
+ proju = {}; projv = {}; coeff_matrix = {}; projectors = {};
103
+ for key in self.main_dat.projv.keys():
104
+ vectors = [obj.projv[key] for obj in self.dat]
105
+ coefficients, u, v = zip(*[get_Jani_coefficients(vectors[i], R=R[i]) for i in indices])
106
+ projectors[key] = np.vstack([u[i] @ R[i].T for i in indices])
107
+ coeff_matrix[key] = np.vstack(coefficients)
108
+ proju[key] = np.stack(u)
109
+ projv[key] = np.stack(v)
110
+ if np.linalg.matrix_rank(coeff_matrix[key], tol=1e-2) < 6:
111
+ warnings.warn('''
112
+ WARNING: The matrix of equations to reconstruct the exchange tensors is
113
+ close to being singular. This happens when the magnetic moments between
114
+ different configurations are cloes to being parallel. You need to consider
115
+ more rotated spin configurations, otherwise the results might have a large
116
+ error.'''
117
+ )
118
+
119
+ self.proju = proju
120
+ self.projv = projv
121
+ self.coeff_matrix = coeff_matrix
122
+ self.projectors = projectors
123
+
124
+ def merge_Jani(self):
125
+ Jani_dict = {}
126
+ proju = self.proju; projv = self.projv; coeff_matrix = self.coeff_matrix;
127
+ for key in self.main_dat.Jani_dict.keys():
128
+ try:
129
+ R, i, j = key
130
+ u = proju[i, j]
131
+ v = projv[i, j]
132
+ Jani = np.stack([sio.Jani_dict[key] for sio in self.dat])
133
+ projections = np.einsum('nmi,nij,nmj->nm', u, Jani, v).flatten()
134
+ except KeyError as err:
135
+ raise KeyError(
136
+ "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
137
+ % err)
138
+ newJani = np.linalg.lstsq(coeff_matrix[i, j], projections, rcond=1e-2)[0]
139
+ Jani_dict[key] = np.array([
140
+ [newJani[0], newJani[3], newJani[5]],
141
+ [newJani[3], newJani[1], newJani[4]],
142
+ [newJani[5], newJani[4], newJani[2]]
143
+ ])
144
+ self.main_dat.Jani_dict = Jani_dict
145
+
146
+ def merge_Jiso(self):
147
+ Jdict={}
148
+ for key in self.main_dat.exchange_Jdict.keys():
149
+ try:
150
+ J = np.mean([obj.exchange_Jdict[key] for obj in self.dat])
151
+ except KeyError as err:
152
+ raise KeyError(
153
+ "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
154
+ % err)
155
+ Jdict[key] = J
156
+ self.main_dat.exchange_Jdict = Jdict
157
+
158
+
159
+ def merge_DMI(self):
160
+ dmi_ddict = {}
161
+ if all(obj.has_dmi for obj in self.dat):
162
+ projectors = self.projectors; proju = self.proju;
163
+ for key in self.main_dat.dmi_ddict.keys():
164
+ try:
165
+ R, i, j = key
166
+ u = proju[i, j]
167
+ DMI = np.stack([sio.dmi_ddict[key] for sio in self.dat])
168
+ projections = np.einsum('nmi,ni->nm', u, DMI).flatten()
169
+ except KeyError as err:
170
+ raise KeyError(
171
+ "Can not find key: %s, Please make sure the three calculations use the same k-mesh and same Rcut."
172
+ % err)
173
+ newDMI = np.linalg.lstsq(projectors[i, j], projections, rcond=4e-1)[0]
174
+ dmi_ddict[key] = newDMI
175
+ self.main_dat.dmi_ddict = dmi_ddict
176
+
177
+ def merge(*paths, main_path=None, save=True, write_path='TB2J_results'):
178
+ m = Merger(*paths, main_path=main_path)
179
+ m.merge_Jiso()
180
+ m.merge_DMI()
181
+ m.merge_Jani()
182
+ if save:
183
+ m.main_dat.write_all(path=write_path)
184
+ return m.dat
@@ -16,7 +16,6 @@ class AbstractTB:
16
16
  def __init__(self, R2kfactor, nspin, norb):
17
17
  #: :math:`\alpha` used in :math:`H(k)=\sum_R H(R) \exp( \alpha k \cdot R)`,
18
18
  #: Should be :math:`2\pi i` or :math:`-2\pi i`
19
- self.is_siesta = False
20
19
  self.is_orthogonal = True
21
20
  self.R2kfactor = R2kfactor
22
21
 
@@ -125,7 +124,6 @@ class MyTB(AbstractTB):
125
124
  self.atoms = None
126
125
  self.R2kfactor = 2.0j * np.pi
127
126
  self.k2Rfactor = -2.0j * np.pi
128
- self.is_siesta = False
129
127
  self.is_orthogonal = True
130
128
  self._name = "Wannier"
131
129
 
@@ -5,19 +5,24 @@ import numpy as np
5
5
  from TB2J.tensor_rotate import Rxx, Rxy, Rxz, Ryx, Ryy, Ryz, Rzx, Rzy, Rzz
6
6
 
7
7
 
8
- def rotate_atom_xyz(atoms):
8
+ def rotate_atom_xyz(atoms, noncollinear=False):
9
9
  """
10
- given a atoms, return:
11
- - 'z'->'x'
12
- - 'z'->'y'
13
- - 'z'->'z'
10
+ given a atoms, return rotated atoms:
11
+ atoms_1, ..., atoms_n,
12
+ where we considered n diffeerent roation axes.
13
+
14
+ When noncollinear == True, more rotated structures
15
+ will be generated.
14
16
  """
15
- atoms_x = copy.deepcopy(atoms)
16
- atoms_x.rotate(90, "y", rotate_cell=True)
17
- atoms_y = copy.deepcopy(atoms)
18
- atoms_y.rotate(90, "x", rotate_cell=True)
19
- atoms_z = atoms
20
- return atoms_x, atoms_y, atoms_z
17
+
18
+ rotation_axes = [(1, 0, 0), (0, 1, 0)]
19
+ if noncollinear:
20
+ rotation_axes += [(1, 1, 0), (1, 0, 1), (0, 1, 1)]
21
+
22
+ for axis in rotation_axes:
23
+ rotated_atoms = copy.deepcopy(atoms)
24
+ rotated_atoms.rotate(90, axis, rotate_cell=True)
25
+ yield rotated_atoms
21
26
 
22
27
 
23
28
  def rotate_atom_spin_one_rotation(atoms, Rotation):
@@ -96,18 +101,15 @@ def check_ftype(ftype):
96
101
  print("=" * 40)
97
102
 
98
103
 
99
- def rotate_xyz(fname, ftype="xyz"):
104
+ def rotate_xyz(fname, ftype="xyz", noncollinear=False):
100
105
  check_ftype(ftype)
101
106
  atoms = read(fname)
102
107
  atoms.set_pbc(True)
103
108
 
104
- atoms_x, atoms_y, atoms_z = rotate_atom_xyz(atoms)
109
+ rotated = rotate_atom_xyz(atoms, noncollinear=noncollinear)
105
110
 
106
- fname_x = f"atoms_x.{ftype}"
107
- fname_y = f"atoms_y.{ftype}"
108
- fname_z = f"atoms_z.{ftype}"
111
+ for i, rotated_atoms in enumerate(rotated):
112
+ write(f"atoms_{i+1}.{ftype}", rotated_atoms)
113
+ write(f"atoms_0.{ftype}", atoms)
109
114
 
110
- write(fname_x, atoms_x)
111
- write(fname_y, atoms_y)
112
- write(fname_z, atoms_z)
113
- print(f"The output has been written to {fname_x}, {fname_y}, {fname_z}")
115
+ print(f"The output has been written to the atoms_i.{ftype} files. atoms_0.{ftype} contains the reference structure.")
@@ -0,0 +1,36 @@
1
+ import sisl
2
+
3
+ def rotate_siesta_DM(DM, noncollinear=False):
4
+
5
+ angles_list = [ [0.0, 90.0, 0.0], [0.0, 90.0, 90.0] ]
6
+ if noncollinear:
7
+ angles_list += [[0.0, 45.0, 0.0], [0.0, 90.0, 45.0], [0.0, 45.0, 90.0]]
8
+
9
+ for angles in angles_list:
10
+ yield DM.spin_rotate(angles)
11
+
12
+ def read_label(fdf_fname):
13
+
14
+ label = 'siesta'
15
+ with open(fdf_fname, 'r') as File:
16
+ for line in File:
17
+ corrected_line = line.lower().replace('.', '').replace('-', '')
18
+ if 'systemlabel' in corrected_line:
19
+ label = line.split()[1]
20
+ break
21
+
22
+ return label
23
+
24
+ def rotate_DM(fdf_fname, noncollinear=False):
25
+
26
+ fdf = sisl.get_sile(fdf_fname)
27
+ DM = fdf.read_density_matrix()
28
+ label = read_label(fdf_fname)
29
+
30
+ rotated = rotate_siesta_DM(DM, noncollinear=noncollinear)
31
+
32
+ for i, rotated_DM in enumerate(rotated):
33
+ rotated_DM.write(f"{label}_{i+1}.DM")
34
+ DM.write(f"{label}_0.DM")
35
+
36
+ print(f"The output has been written to the {label}_i.DM files. {label}_0.DM contains the reference density matrix.")
@@ -10,7 +10,6 @@ from TB2J.mathutils import Lowdin
10
10
 
11
11
  class SislWrapper(AbstractTB):
12
12
  def __init__(self, sisl_hamiltonian, geom=None, spin=None):
13
- self.is_siesta = False
14
13
  self.is_orthogonal = False
15
14
  self.ham = sisl_hamiltonian
16
15
  # k2Rfactor : H(k) = \int_R H(R) * e^(k2Rfactor * k.R)
@@ -1,12 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.8.2.8
3
+ Version: 0.9.0.1
4
4
  Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
5
- Home-page: UNKNOWN
6
5
  Author: Xu He
7
6
  Author-email: mailhexu@gmail.com
8
7
  License: BSD-2-clause
9
- Platform: UNKNOWN
10
8
  Classifier: Development Status :: 3 - Alpha
11
9
  Classifier: Programming Language :: Python :: 3
12
10
  Classifier: Operating System :: OS Independent
@@ -16,6 +14,13 @@ Classifier: Topic :: Scientific/Engineering :: Physics
16
14
  Classifier: License :: OSI Approved :: BSD License
17
15
  Requires-Python: >=3.6
18
16
  License-File: LICENSE
17
+ Requires-Dist: numpy>1.16.5
18
+ Requires-Dist: scipy
19
+ Requires-Dist: matplotlib
20
+ Requires-Dist: ase>=3.19
21
+ Requires-Dist: tqdm
22
+ Requires-Dist: pathos
23
+ Requires-Dist: packaging>=20.0
24
+ Requires-Dist: pre-commit
19
25
 
20
26
  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.
21
-
@@ -28,6 +28,7 @@ TB2J/pauli.py
28
28
  TB2J/pert.py
29
29
  TB2J/plot.py
30
30
  TB2J/rotate_atoms.py
31
+ TB2J/rotate_siestaDM.py
31
32
  TB2J/sisl_wrapper.py
32
33
  TB2J/tensor_rotate.py
33
34
  TB2J/utest.py
@@ -58,10 +59,8 @@ TB2J/io_exchange/io_vampire.py
58
59
  TB2J/spinham/__init__.py
59
60
  TB2J/spinham/base_parser.py
60
61
  TB2J/spinham/constants.py
61
- TB2J/spinham/h_matrix.py
62
62
  TB2J/spinham/hamiltonian.py
63
63
  TB2J/spinham/hamiltonian_terms.py
64
- TB2J/spinham/obtain_J.py
65
64
  TB2J/spinham/plot.py
66
65
  TB2J/spinham/qsolver.py
67
66
  TB2J/spinham/spin_api.py
@@ -76,6 +75,7 @@ scripts/TB2J_magnon.py
76
75
  scripts/TB2J_magnon_dos.py
77
76
  scripts/TB2J_merge.py
78
77
  scripts/TB2J_rotate.py
78
+ scripts/TB2J_rotateDM.py
79
79
  scripts/abacus2J.py
80
80
  scripts/siesta2J.py
81
81
  scripts/wann2J.py
@@ -2,7 +2,7 @@
2
2
  import argparse
3
3
  import os
4
4
  import sys
5
- from TB2J.io_merge import merge, merge2
5
+ from TB2J.io_merge import merge
6
6
 
7
7
 
8
8
  def main():
@@ -28,11 +28,18 @@ def main():
28
28
  type=str,
29
29
  default="TB2J_results",
30
30
  )
31
+ parser.add_argument(
32
+ "--main_path",
33
+ help="The path containning the reference structure.",
34
+ type=str,
35
+ default=None
36
+ )
31
37
 
32
38
  args = parser.parse_args()
33
39
  # merge(*(args.directories), args.type.strip().lower(), path=args.output_path)
34
40
  # merge(*(args.directories), method=args.type.strip().lower(), path=args.output_path)
35
- merge2(args.directories, args.type.strip().lower(), path=args.output_path)
41
+ #merge2(args.directories, args.type.strip().lower(), path=args.output_path)
42
+ merge(*args.directories, main_path=args.main_path, write_path=args.output_path)
36
43
 
37
44
 
38
45
  main()
@@ -14,9 +14,14 @@ def main():
14
14
  default="xyz",
15
15
  type=str,
16
16
  )
17
+ parser.add_argument(
18
+ "--noncollinear",
19
+ action="store_true",
20
+ help="If present, six different configurations will be generated. These are required for non-collinear systems."
21
+ )
17
22
 
18
23
  args = parser.parse_args()
19
- rotate_xyz(args.fname, ftype=args.ftype)
24
+ rotate_xyz(args.fname, ftype=args.ftype, noncollinear=args.noncollinear)
20
25
 
21
26
 
22
27
  if __name__ == "__main__":
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ from TB2J.rotate_siestaDM import rotate_DM
4
+
5
+ def main():
6
+ parser = argparse.ArgumentParser(description="")
7
+ parser.add_argument(
8
+ "--fdf_fname", help="Name of the *.fdf siesta file."
9
+ )
10
+ parser.add_argument(
11
+ "--noncollinear",
12
+ action="store_true",
13
+ help="If present, six different configurations will be generated. These are required for non-collinear systems."
14
+ )
15
+
16
+ args = parser.parse_args()
17
+ rotate_DM(args.fdf_fname, noncollinear=args.noncollinear)
18
+
19
+
20
+ if __name__ == "__main__":
21
+ main()
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  from setuptools import setup, find_packages
3
3
 
4
- __version__ = "0.8.2.8"
4
+ __version__ = "0.9.0.1"
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
 
@@ -19,6 +19,7 @@ setup(
19
19
  "scripts/siesta2J.py",
20
20
  "scripts/abacus2J.py",
21
21
  "scripts/TB2J_rotate.py",
22
+ "scripts/TB2J_rotateDM.py",
22
23
  "scripts/TB2J_merge.py",
23
24
  "scripts/TB2J_magnon.py",
24
25
  "scripts/TB2J_magnon_dos.py",
@@ -1 +0,0 @@
1
- __version__ = "0.8.2.8"