TB2J 0.9.9rc18__py3-none-any.whl → 0.9.9.1__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 (28) hide show
  1. TB2J/MAEGreen.py +11 -18
  2. TB2J/exchange_params.py +1 -6
  3. TB2J/interfaces/siesta_interface.py +7 -14
  4. TB2J/io_exchange/__init__.py +0 -2
  5. TB2J/io_exchange/io_exchange.py +5 -2
  6. TB2J/mathutils/__init__.py +0 -1
  7. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/abacus2J.py +2 -6
  8. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/siesta2J.py +1 -5
  9. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/wann2J.py +2 -6
  10. {tb2j-0.9.9rc18.dist-info → tb2j-0.9.9.1.dist-info}/METADATA +3 -2
  11. {tb2j-0.9.9rc18.dist-info → tb2j-0.9.9.1.dist-info}/RECORD +22 -28
  12. TB2J/magnon/__init__.py +0 -3
  13. TB2J/magnon/io_exchange2.py +0 -688
  14. TB2J/magnon/plot.py +0 -58
  15. TB2J/magnon/structure.py +0 -348
  16. TB2J/mathutils/magnons.py +0 -45
  17. tb2j-0.9.9rc18.data/scripts/TB2J_magnon2.py +0 -77
  18. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_downfold.py +0 -0
  19. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_eigen.py +0 -0
  20. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_magnon.py +0 -0
  21. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_magnon_dos.py +0 -0
  22. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_merge.py +0 -0
  23. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_rotate.py +0 -0
  24. {tb2j-0.9.9rc18.data → tb2j-0.9.9.1.data}/scripts/TB2J_rotateDM.py +0 -0
  25. {tb2j-0.9.9rc18.dist-info → tb2j-0.9.9.1.dist-info}/WHEEL +0 -0
  26. {tb2j-0.9.9rc18.dist-info → tb2j-0.9.9.1.dist-info}/entry_points.txt +0 -0
  27. {tb2j-0.9.9rc18.dist-info → tb2j-0.9.9.1.dist-info}/licenses/LICENSE +0 -0
  28. {tb2j-0.9.9rc18.dist-info → tb2j-0.9.9.1.dist-info}/top_level.txt +0 -0
TB2J/magnon/plot.py DELETED
@@ -1,58 +0,0 @@
1
- import matplotlib.pyplot as plt
2
- import numpy as np
3
-
4
-
5
- class BandsPlot:
6
- _UNITS = "meV"
7
- _NSYSTEMS = 1
8
-
9
- def __init__(self, bands, kpath, **kwargs):
10
- self.bands = bands
11
- self.kpath = kpath
12
- self.bands *= 1000
13
-
14
- plot_options = kwargs
15
- self.linewidth = plot_options.pop("linewidth", 1.5)
16
- self.color = plot_options.pop("color", "blue")
17
- self.fontsize = plot_options.pop("fontsize", 12)
18
- self.ticksize = plot_options.pop("ticksize", 10)
19
- self.plot_options = plot_options
20
-
21
- def plot(self, filename=None):
22
- fig, axs = plt.subplots(1, self._NSYSTEMS, constrained_layout=True)
23
-
24
- kdata = np.arange(self.bands.shape[0])
25
- for band in self.bands.T:
26
- axs.plot(
27
- kdata,
28
- band,
29
- linewidth=self.linewidth,
30
- color=self.color,
31
- **self.plot_options,
32
- )
33
-
34
- bmin, bmax = self.bands.min(), self.bands.max()
35
- ymin, ymax = (
36
- bmin - 0.05 * np.abs(bmin - bmax),
37
- bmax + 0.05 * np.abs(bmax - bmin),
38
- )
39
-
40
- axs.set_ylim([ymin, ymax])
41
- axs.set_xlim([0, kdata[-1]])
42
-
43
- kpoint_labels = list(zip(*self.kpath))
44
- axs.set_xticks(*kpoint_labels, fontsize=self.ticksize)
45
- axs.vlines(
46
- x=kpoint_labels[0],
47
- ymin=ymin,
48
- ymax=ymax,
49
- color="black",
50
- linewidth=self.linewidth / 5,
51
- )
52
-
53
- axs.set_ylabel(f"Energy ({self._UNITS})", fontsize=self.fontsize)
54
-
55
- if filename is None:
56
- plt.show()
57
- else:
58
- fig.save(filename, dpi=300, bbox_inches="tight")
TB2J/magnon/structure.py DELETED
@@ -1,348 +0,0 @@
1
- from warnings import warn
2
-
3
- import numpy as np
4
-
5
- valid_symbols = [
6
- # 0
7
- "Ae",
8
- # 1
9
- "H",
10
- "He",
11
- # 2
12
- "Li",
13
- "Be",
14
- "B",
15
- "C",
16
- "N",
17
- "O",
18
- "F",
19
- "Ne",
20
- # 3
21
- "Na",
22
- "Mg",
23
- "Al",
24
- "Si",
25
- "P",
26
- "S",
27
- "Cl",
28
- "Ar",
29
- # 4
30
- "K",
31
- "Ca",
32
- "Sc",
33
- "Ti",
34
- "V",
35
- "Cr",
36
- "Mn",
37
- "Fe",
38
- "Co",
39
- "Ni",
40
- "Cu",
41
- "Zn",
42
- "Ga",
43
- "Ge",
44
- "As",
45
- "Se",
46
- "Br",
47
- "Kr",
48
- # 5
49
- "Rb",
50
- "Sr",
51
- "Y",
52
- "Zr",
53
- "Nb",
54
- "Mo",
55
- "Tc",
56
- "Ru",
57
- "Rh",
58
- "Pd",
59
- "Ag",
60
- "Cd",
61
- "In",
62
- "Sn",
63
- "Sb",
64
- "Te",
65
- "I",
66
- "Xe",
67
- # 6
68
- "Cs",
69
- "Ba",
70
- "La",
71
- "Ce",
72
- "Pr",
73
- "Nd",
74
- "Pm",
75
- "Sm",
76
- "Eu",
77
- "Gd",
78
- "Tb",
79
- "Dy",
80
- "Ho",
81
- "Er",
82
- "Tm",
83
- "Yb",
84
- "Lu",
85
- "Hf",
86
- "Ta",
87
- "W",
88
- "Re",
89
- "Os",
90
- "Ir",
91
- "Pt",
92
- "Au",
93
- "Hg",
94
- "Tl",
95
- "Pb",
96
- "Bi",
97
- "Po",
98
- "At",
99
- "Rn",
100
- # 7
101
- "Fr",
102
- "Ra",
103
- "Ac",
104
- "Th",
105
- "Pa",
106
- "U",
107
- "Np",
108
- "Pu",
109
- "Am",
110
- "Cm",
111
- "Bk",
112
- "Cf",
113
- "Es",
114
- "Fm",
115
- "Md",
116
- "No",
117
- "Lr",
118
- "Rf",
119
- "Db",
120
- "Sg",
121
- "Bh",
122
- "Hs",
123
- "Mt",
124
- "Ds",
125
- "Rg",
126
- "Cn",
127
- "Nh",
128
- "Fl",
129
- "Mc",
130
- "Lv",
131
- "Ts",
132
- "Og",
133
- ]
134
-
135
-
136
- def get_attribute_array(array, attribute, dtype=float):
137
- try:
138
- the_array = np.array(array, dtype=dtype)
139
- except (IndexError, ValueError, TypeError) as err:
140
- typename = dtype.__name__
141
- raise type(err)(
142
- f"'{attribute}' must be an arraylike object of '{typename}' elements."
143
- )
144
-
145
- return the_array
146
-
147
-
148
- def validate_symbols(value):
149
- try:
150
- values_list = value.split()
151
- except AttributeError:
152
- try:
153
- values_list = list(value)
154
- except (ValueError, TypeError):
155
- raise TypeError("'elements' must be an iterable of 'str' or 'int' entries.")
156
-
157
- if all(isinstance(s, str) for s in values_list):
158
- symbols = values_list
159
- for symbol in symbols:
160
- if symbol not in valid_symbols:
161
- raise ValueError(f"Unrecognized element '{symbol}'.")
162
- elif all(isinstance(i, (int, np.integer)) for i in values_list):
163
- if any(i < 0 for i in values_list):
164
- raise ValueError("Atomic numbers must be positive.")
165
- try:
166
- symbols = [valid_symbols[i] for i in values_list]
167
- except IndexError:
168
- raise ValueError("Atomic number exceeds 118.")
169
- else:
170
- raise ValueError("'elements' must be an iterable of 'str' or 'int' entries.")
171
-
172
- return symbols
173
-
174
-
175
- class BaseMagneticStructure:
176
- def __init__(
177
- self,
178
- atoms=None,
179
- cell=None,
180
- elements=None,
181
- positions=None,
182
- magmoms=None,
183
- pbc=None,
184
- collinear=True,
185
- ):
186
- if atoms is not None:
187
- if any(arg is not None for arg in [cell, elements, positions]):
188
- warn(
189
- "WARNING: 'atoms' overrides the 'cell', 'elements', and 'positions' arguments."
190
- )
191
- cell = atoms.cell.array
192
- elements = atoms.numbers
193
- positions = atoms.get_scaled_positions()
194
- pbc = atoms.pbc if pbc is None else pbc
195
- else:
196
- if cell is None:
197
- cell = np.zeros((3, 3))
198
- if elements is None:
199
- elements = ()
200
- if positions is None:
201
- positions = np.zeros((len(elements), 3))
202
- if pbc is None:
203
- pbc = (True, True, True)
204
- if magmoms is None:
205
- magmoms_shape = positions.shape[0] if collinear else positions.shape
206
- magmoms = np.zeros(magmoms_shape)
207
-
208
- self.cell = cell
209
- self.elements = elements
210
- self.positions = positions
211
- self.collinear = collinear
212
- self.magmoms = magmoms
213
- self.pbc = pbc
214
-
215
- self._Q = None
216
- self._n = np.array([0, 0, 1])
217
-
218
- @property
219
- def cell(self):
220
- return self._cell
221
-
222
- @property
223
- def reciprocal_cell(self):
224
- return 2 * np.pi * np.linalg.inv(self._cell)
225
-
226
- @cell.setter
227
- def cell(self, value):
228
- cell_array = get_attribute_array(value, "cell")
229
- if cell_array.shape != (3, 3):
230
- raise ValueError("'cell' must have a (3, 3) shape.")
231
-
232
- self._cell = cell_array
233
-
234
- @property
235
- def elements(self):
236
- return self._symbols
237
-
238
- @elements.setter
239
- def elements(self, value):
240
- symbols = validate_symbols(value)
241
- self._symbols = symbols
242
-
243
- @property
244
- def numbers(self):
245
- return [valid_symbols.index(symbol) for symbol in self._symbols]
246
-
247
- @property
248
- def positions(self):
249
- return self._positions
250
-
251
- @property
252
- def cartesian_positions(self):
253
- return self._positions @ self._cell
254
-
255
- @positions.setter
256
- def positions(self, value):
257
- natoms = len(self.elements)
258
- posarray = get_attribute_array(value, "positions")
259
- if posarray.shape != (natoms, 3):
260
- raise ValueError(
261
- "'positions' must have a (natoms, 3) shape, where natoms is the length of 'elements'. Make sure to set 'elements' first."
262
- )
263
-
264
- self._positions = posarray
265
-
266
- @property
267
- def magmoms(self):
268
- return self._magmoms
269
-
270
- @magmoms.setter
271
- def magmoms(self, value):
272
- magarray = get_attribute_array(value, "magmoms")
273
- if self.collinear and magarray.shape != (len(self._positions),):
274
- raise ValueError(
275
- "'magmoms' must be a 1dim array with the same length as 'positions'. Make sure to set 'positions' first."
276
- )
277
- elif not self.collinear and magarray.shape != self._positions.shape:
278
- raise ValueError(
279
- "'magmoms' must have the same shape as 'positions'. Make sure to set 'positions' first."
280
- )
281
-
282
- self._magmoms = magarray
283
-
284
- @property
285
- def pbc(self):
286
- return self._pbc
287
-
288
- @pbc.setter
289
- def pbc(self, value):
290
- try:
291
- periodic_boundary_conditions = tuple(bool(b) for b in value)
292
- except (ValueError, TypeError):
293
- raise TypeError("'pbc' must be an iterable of 'bool' entries.")
294
-
295
- if len(periodic_boundary_conditions) != 3:
296
- raise ValueError("'pbc' must be of length 3.")
297
-
298
- self._pbc = periodic_boundary_conditions
299
-
300
- @property
301
- def propagation_vector(self):
302
- return self._Q
303
-
304
- @propagation_vector.setter
305
- def propagation_vector(self, value):
306
- Q = get_attribute_array(value, "propagation_vector")
307
- if Q.shape != (3,):
308
- raise ValueError(
309
- "The 'propagation_vector' must be a vector with 3 numbers."
310
- )
311
-
312
- self._Q = Q
313
-
314
- @property
315
- def normal_vector(self):
316
- return self._n
317
-
318
- @normal_vector.setter
319
- def normal_vector(self, value):
320
- n = get_attribute_array(value, "normal_vector")
321
- if n.shape != (3,):
322
- raise ValueError("The 'normal_vector' must be a vector with 3 numbers.")
323
-
324
- self._n = n
325
-
326
- def to_ase(self):
327
- from ase.atoms import Atoms
328
-
329
- atoms = Atoms(
330
- cell=self.cell,
331
- positions=self.cartesian_positions,
332
- numbers=[valid_symbols.index(symbol) for symbol in self.elements],
333
- pbc=self.pbc,
334
- )
335
-
336
- return atoms
337
-
338
- @classmethod
339
- def from_structure_file(
340
- cls, filename, magmoms=None, collinear=True, pbc=(True, True, True)
341
- ):
342
- from ase.io import read
343
-
344
- atoms = read(filename)
345
- atoms.pbc = pbc
346
- obj = cls(atoms=atoms, magmoms=magmoms, collinear=collinear)
347
-
348
- return obj
TB2J/mathutils/magnons.py DELETED
@@ -1,45 +0,0 @@
1
- import numpy as np
2
-
3
- __all__ = ["generate_grid", "get_rotation_arrays", "round_to_precision", "uz", "I"]
4
-
5
- I = np.eye(3)
6
- uz = np.array([[0.0, 0.0, 1.0]])
7
-
8
-
9
- def generate_grid(kmesh, sort=True):
10
- half_grid = [int(n / 2) for n in kmesh]
11
- grid = np.stack(
12
- np.meshgrid(*[np.arange(-n, n + 1) for n in half_grid]), axis=-1
13
- ).reshape(-1, 3)
14
-
15
- if sort:
16
- idx = np.linalg.norm(grid, axis=-1).argsort()
17
- grid = grid[idx]
18
-
19
- return grid
20
-
21
-
22
- def get_rotation_arrays(magmoms, u=uz):
23
- dim = magmoms.shape[0]
24
- v = magmoms
25
- n = np.cross(u, v)
26
- n /= np.linalg.norm(n, axis=-1).reshape(dim, 1)
27
- z = np.repeat(u, dim, axis=0)
28
- A = np.stack([z, np.cross(n, z), n], axis=1)
29
- B = np.stack([v, np.cross(n, v), n], axis=1)
30
- R = np.einsum("nki,nkj->nij", A, B)
31
-
32
- Rnan = np.isnan(R)
33
- if Rnan.any():
34
- nanidx = np.where(Rnan)[0]
35
- R[nanidx] = I
36
- R[nanidx, 2] = v[nanidx]
37
-
38
- U = R[:, 0] + 1j * R[:, 1]
39
- V = R[:, 2]
40
-
41
- return U, V
42
-
43
-
44
- def round_to_precision(array, precision):
45
- return precision * np.round(array / precision)
@@ -1,77 +0,0 @@
1
- from TB2J.magnon import plot_tb2j_magnon_bands
2
-
3
-
4
- def plot_tb2j_magnon_bands_cli():
5
- """Command line interface for plotting magnon band structures from TB2J data."""
6
- import argparse
7
-
8
- parser = argparse.ArgumentParser(
9
- description="Plot magnon band structure from TB2J data",
10
- formatter_class=argparse.ArgumentDefaultsHelpFormatter,
11
- )
12
-
13
- parser.add_argument(
14
- "-f", "--file", default="TB2J.pickle", help="Path to TB2J pickle file"
15
- )
16
-
17
- parser.add_argument(
18
- "-p",
19
- "--path",
20
- help="High-symmetry k-point path (e.g., 'GXMG' for square lattice)",
21
- )
22
-
23
- parser.add_argument(
24
- "-n",
25
- "--npoints",
26
- type=int,
27
- default=300,
28
- help="Number of k-points for band structure calculation",
29
- )
30
-
31
- parser.add_argument(
32
- "-a",
33
- "--anisotropic",
34
- action="store_true",
35
- help="Include anisotropic interactions",
36
- )
37
-
38
- parser.add_argument(
39
- "-q",
40
- "--quadratic",
41
- action="store_true",
42
- help="Include biquadratic interactions",
43
- )
44
-
45
- parser.add_argument("-o", "--output", help="Output filename for the plot")
46
-
47
- parser.add_argument(
48
- "--no-pbc",
49
- nargs="+",
50
- type=int,
51
- choices=[0, 1, 2],
52
- help="Disable periodic boundary conditions in specified directions (0=x, 1=y, 2=z)",
53
- )
54
-
55
- args = parser.parse_args()
56
-
57
- # Set up periodic boundary conditions
58
- pbc = [True, True, True]
59
- if args.no_pbc:
60
- for direction in args.no_pbc:
61
- pbc[direction] = False
62
- pbc = tuple(pbc)
63
-
64
- # Plot the bands
65
- plot_tb2j_magnon_bands(
66
- pickle_file=args.file,
67
- path=args.path,
68
- npoints=args.npoints,
69
- anisotropic=args.anisotropic,
70
- quadratic=args.quadratic,
71
- pbc=pbc,
72
- filename=args.output,
73
- )
74
-
75
-
76
- if __name__ == "__main__":
77
- plot_tb2j_magnon_bands_cli()