TB2J 0.9.10.1__py3-none-any.whl → 0.9.12.17__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.

Potentially problematic release.


This version of TB2J might be problematic. Click here for more details.

Files changed (49) hide show
  1. TB2J/.gitignore +5 -0
  2. TB2J/Jdownfolder.py +43 -19
  3. TB2J/MAEGreen.py +78 -60
  4. TB2J/__init__.py +3 -1
  5. TB2J/anisotropy.py +2 -2
  6. TB2J/basis.py +0 -3
  7. TB2J/contour.py +3 -2
  8. TB2J/exchange.py +335 -48
  9. TB2J/exchangeCL2.py +289 -51
  10. TB2J/exchange_params.py +25 -1
  11. TB2J/gpaw_wrapper.py +0 -3
  12. TB2J/green.py +58 -33
  13. TB2J/interfaces/wannier90_interface.py +4 -4
  14. TB2J/io_exchange/io_espins.py +276 -0
  15. TB2J/io_exchange/io_exchange.py +53 -12
  16. TB2J/io_exchange/io_txt.py +9 -8
  17. TB2J/io_exchange/io_uppasd.py +0 -1
  18. TB2J/io_exchange/io_vampire.py +3 -1
  19. TB2J/magnon/magnon3.py +76 -28
  20. TB2J/magnon/plot_magnon_dos_cli.py +115 -3
  21. TB2J/myTB.py +11 -11
  22. TB2J/pauli.py +32 -2
  23. TB2J/plot.py +8 -7
  24. TB2J/rotate_atoms.py +10 -7
  25. TB2J/scripts/TB2J_downfold.py +97 -0
  26. TB2J/scripts/TB2J_eigen.py +49 -0
  27. TB2J/scripts/TB2J_magnon.py +117 -0
  28. TB2J/scripts/TB2J_magnon2.py +78 -0
  29. TB2J/scripts/TB2J_magnon_dos.py +5 -0
  30. TB2J/scripts/TB2J_merge.py +49 -0
  31. TB2J/scripts/TB2J_plot_magnon_bands.py +22 -0
  32. TB2J/scripts/TB2J_rotate.py +29 -0
  33. TB2J/scripts/TB2J_rotateDM.py +21 -0
  34. TB2J/scripts/__init__.py +0 -0
  35. TB2J/scripts/abacus2J.py +61 -0
  36. TB2J/scripts/siesta2J.py +78 -0
  37. TB2J/scripts/wann2J.py +101 -0
  38. TB2J/spinham/hamiltonian.py +0 -1
  39. TB2J/symmetrize_J.py +2 -2
  40. TB2J/tensor_rotate.py +1 -2
  41. TB2J/versioninfo.py +3 -0
  42. TB2J/wannier/w90_tb_parser.py +0 -2
  43. {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/METADATA +7 -7
  44. {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/RECORD +48 -33
  45. tb2j-0.9.12.17.dist-info/entry_points.txt +15 -0
  46. tb2j-0.9.10.1.dist-info/entry_points.txt +0 -16
  47. {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/WHEEL +0 -0
  48. {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/licenses/LICENSE +0 -0
  49. {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,276 @@
1
+ import os
2
+
3
+ import numpy as np
4
+
5
+
6
+ def _get_shell_index(cls, key):
7
+ """Determine shell index based on distance grouping.
8
+
9
+ Parameters
10
+ ----------
11
+ cls : SpinIO
12
+ SpinIO instance
13
+ key : tuple
14
+ (R, i, j) key for exchange parameter
15
+
16
+ Returns
17
+ -------
18
+ int
19
+ Shell index (1 for nearest neighbors, 2 for next nearest, etc.)
20
+ """
21
+ if not hasattr(cls, "_distance_shells"):
22
+ # Calculate all distances and group into shells
23
+ distances = []
24
+ for k in cls.exchange_Jdict:
25
+ if cls.distance_dict and k in cls.distance_dict:
26
+ distances.append(cls.distance_dict[k][1])
27
+
28
+ if distances:
29
+ # Sort distances and group by rounding to nearest 0.01 Å
30
+ sorted_distances = sorted(set(round(d * 100) for d in distances))
31
+ cls._distance_shells = {}
32
+ for shell_idx, dist_int in enumerate(sorted_distances, 1):
33
+ cls._distance_shells[dist_int / 100] = shell_idx
34
+ else:
35
+ cls._distance_shells = {}
36
+
37
+ if cls.distance_dict and key in cls.distance_dict:
38
+ distance = cls.distance_dict[key][1]
39
+ rounded_dist = round(distance * 100)
40
+ return cls._distance_shells.get(rounded_dist / 100, 1)
41
+
42
+ return 1
43
+
44
+
45
+ def write_espins(cls, path="TB2J_results/ESPInS"):
46
+ """Write ESPInS format input files.
47
+
48
+ Parameters
49
+ ----------
50
+ cls : SpinIO
51
+ SpinIO instance containing exchange parameters
52
+ path : str
53
+ Output directory path
54
+ """
55
+ if not os.path.exists(path):
56
+ os.makedirs(path)
57
+
58
+ write_espins_input(cls, os.path.join(path, "espins.in"))
59
+
60
+
61
+ def write_espins_input(cls, fname):
62
+ """Write the main ESPInS input file.
63
+
64
+ Parameters
65
+ ----------
66
+ cls : SpinIO
67
+ SpinIO instance
68
+ fname : str
69
+ Output filename
70
+ """
71
+ with open(fname, "w") as myfile:
72
+ # Write unit cell
73
+ myfile.write("! ESPInS input file generated by TB2J\n")
74
+ # myfile.write("! Compatible with ESPInS version > 1.0 \n")
75
+ myfile.write("! The unit cell in angstrom\n")
76
+ myfile.write("Begin Unit_Cell_Cart\n")
77
+ cell = cls.atoms.get_cell()
78
+ for i in range(3):
79
+ myfile.write(" " + " ".join(f"{x:12.8f}" for x in cell[i]) + "\n")
80
+ myfile.write("End Unit_Cell_Cart\n\n")
81
+
82
+ # Write atomic positions
83
+ myfile.write("! Atomic positions in reduced coordinates\n")
84
+ myfile.write("Begin Atoms_Frac\n")
85
+ scaled_positions = cls.atoms.get_scaled_positions()
86
+ symbols = cls.atoms.get_chemical_symbols()
87
+
88
+ for i, (symbol, pos) in enumerate(zip(symbols, scaled_positions)):
89
+ if cls.index_spin[i] >= 0: # Only magnetic atoms
90
+ myfile.write(
91
+ f" {symbol:<8} {pos[0]:10.7f} {pos[1]:10.7f} {pos[2]:10.7f} 1.00\n"
92
+ )
93
+ myfile.write("End Atoms_Frac\n\n\n")
94
+
95
+ # Write temperature settings (default values)
96
+ myfile.write("tem_start = 1\n")
97
+ myfile.write("tem_end = 30\n")
98
+ myfile.write("tems_num = 30\n")
99
+ # myfile.write("!! tems_mode = man\n")
100
+ # myfile.write("!! tems = 5.00 10.00 15.00 20.00\n\n")
101
+
102
+ # Write Monte Carlo parameters (default values)
103
+ myfile.write("! Pt = .True.\n")
104
+ myfile.write("! Pt_steps_swap = 40\n\n")
105
+
106
+ myfile.write("steps_warmup = 100000\n")
107
+ myfile.write("steps_mc = 100000\n")
108
+ myfile.write("steps_measure = 2\n\n")
109
+
110
+ myfile.write("initial_sconfig = ferro\n")
111
+ myfile.write("mcarlo_mode = random\n\n")
112
+
113
+ myfile.write("supercell_size = 10 10 1\n\n")
114
+
115
+ # Write Hamiltonian settings
116
+ myfile.write(" ## Hamiltonian\n")
117
+ myfile.write("Ham_bij = .False.\n")
118
+ myfile.write("Ham_jij_matrix = .True.\n")
119
+ myfile.write("! We don't have single ion anisotropy, put it to .False.\n")
120
+ myfile.write("Ham_singleion_matrix = .False.\n\n\n")
121
+
122
+ # Write single ion anisotropy matrix if available
123
+ # if cls.has_uniaxial_anistropy:
124
+ # myfile.write("! Don't put this block\n")
125
+ # myfile.write("!Begin SingleIon_Matrix\n")
126
+ # # Placeholder for single ion anisotropy
127
+ # myfile.write("@Axx=0.000 , Axy=-1.65e-07 , Axz=6e-08 , Ayx=-1.65e-07 , Ayy=7.73e-05 , Ayz=-1.5e-05 , Azx=6e-08 , Azz= 6.8e-05\n")
128
+ # myfile.write("!End SingleIon_Matrix\n\n")
129
+
130
+ # Write exchange parameters
131
+ myfile.write(
132
+ """! f1 is the fractional coordinate of atom i, and f2 is of atom j (rj+Rj). Then jij in eV, sh is index of shell, t1 is index of i, t2 is index of j (counting from 1). \n
133
+ !The convention of the Hamiltonian is H = - sum_<ij> Jij Si Sj, and i, j are ordererd so that there is no double counting (ij and ji). To convert from TB2J exchange.out (which has both ij and ji), multiply Jij by 2. \n
134
+ \n"""
135
+ )
136
+
137
+ if cls.has_exchange:
138
+ myfile.write("Begin Jij_parameters\n")
139
+
140
+ # Create a list of unique exchange parameters sorted by distance
141
+ exchange_list = []
142
+ # written_keys = set()
143
+
144
+ for key, jval in cls.exchange_Jdict.items():
145
+ R, i, j = key
146
+
147
+ # Skip if this is the symmetric counterpart of an already written pair
148
+ # symmetric_key = (tuple(-np.array(R)), j, i)
149
+ # if symmetric_key in written_keys:
150
+ # continue
151
+
152
+ # Get distance for sorting
153
+ distance = (
154
+ cls.distance_dict[key][1]
155
+ if cls.distance_dict and key in cls.distance_dict
156
+ else 0.0
157
+ )
158
+
159
+ exchange_list.append((distance, key, jval))
160
+ # written_keys.add(key)
161
+
162
+ # Sort by distance
163
+ exchange_list.sort(key=lambda x: x[0])
164
+
165
+ for distance, key, jval in exchange_list:
166
+ R, i, j = key
167
+ iatom = cls.iatom(i)
168
+ jatom = cls.iatom(j)
169
+
170
+ # Get fractional coordinates
171
+ pos_i = cls.atoms.get_scaled_positions()[iatom]
172
+ pos_j = cls.atoms.get_scaled_positions()[jatom]
173
+
174
+ # Calculate fractional coordinates for j+R
175
+ pos_jR = pos_j + R
176
+ # Determine shell index based on distance
177
+ shell = _get_shell_index(cls, key)
178
+
179
+ myfile.write(
180
+ f" f1= {pos_i[0]:10.6f}, {pos_i[1]:10.6f}, {pos_i[2]:10.6f}:f2= {pos_jR[0]:10.6f}, {pos_jR[1]:10.6f}, {pos_jR[2]:10.6f}:jij= {jval*2:10.8f}!:sh= {shell}!:t1= {i+1}:t2= {j+1}\n"
181
+ )
182
+
183
+ myfile.write("End Jij_parameters\n\n")
184
+
185
+ # Write exchange matrix if available
186
+ if cls.has_exchange:
187
+ myfile.write(
188
+ "! Each matrix element is corresponding to the previous block. The J tensor include the isotropic, anisotropic exchange and DMI. \n"
189
+ )
190
+ myfile.write("Begin Jij_matrix\n")
191
+
192
+ # Create a list of unique exchange parameters sorted by distance
193
+ exchange_list = []
194
+ # written_keys = set()
195
+
196
+ for key in cls.exchange_Jdict:
197
+ R, i, j = key
198
+
199
+ # Skip if this is the symmetric counterpart of an already written pair
200
+ # symmetric_key = (tuple(-np.array(R)), j, i)
201
+ # if symmetric_key in written_keys:
202
+ # continue
203
+
204
+ # Get distance for sorting
205
+ distance = (
206
+ cls.distance_dict[key][1]
207
+ if cls.distance_dict and key in cls.distance_dict
208
+ else 0.0
209
+ )
210
+
211
+ exchange_list.append((distance, key))
212
+ # written_keys.add(key)
213
+
214
+ # Sort by distance
215
+ exchange_list.sort(key=lambda x: x[0])
216
+
217
+ for distance, key in exchange_list:
218
+ R, i, j = key
219
+ # Get full J tensor
220
+ J_tensor = cls.get_J_tensor(i, j, R, Jiso=True, Jani=True, DMI=True) * 2
221
+
222
+ # Format matrix elements exactly as in the example
223
+ myfile.write(
224
+ f"Jxx={J_tensor[0, 0]:.8f}, Jxy={J_tensor[0, 1]:.8f}, Jxz={J_tensor[0, 2]:.8f}, Jyx={J_tensor[1, 0]:.8f}, Jyy={J_tensor[1, 1]:.8f}, Jyz={J_tensor[1, 2]:.8f}, Jzx={J_tensor[2, 0]:.8f}, Jzy={J_tensor[2, 1]:.8f}, Jzz={J_tensor[2, 2]:.8f}\n"
225
+ )
226
+
227
+ myfile.write("End Jij_matrix\n\n")
228
+
229
+ # Write biquadratic exchange if available
230
+ # if cls.has_biquadratic and cls.biquadratic_Jdict:
231
+ if False:
232
+ myfile.write("! Biquadratic, don't put it. \n")
233
+ myfile.write("Begin Bij_parameters\n")
234
+
235
+ # Create a list of unique biquadratic parameters sorted by distance
236
+ biquadratic_list = []
237
+ written_keys = set()
238
+
239
+ for key, bval in cls.biquadratic_Jdict.items():
240
+ R, i, j = key
241
+
242
+ # Skip if this is the symmetric counterpart of an already written pair
243
+ symmetric_key = (tuple(-np.array(R)), j, i)
244
+ if symmetric_key in written_keys:
245
+ continue
246
+
247
+ # Get distance for sorting
248
+ distance = (
249
+ cls.distance_dict[key][1]
250
+ if cls.distance_dict and key in cls.distance_dict
251
+ else 0.0
252
+ )
253
+
254
+ biquadratic_list.append((distance, key, bval))
255
+ written_keys.add(key)
256
+
257
+ # Sort by distance
258
+ biquadratic_list.sort(key=lambda x: x[0])
259
+
260
+ for distance, key, bval in biquadratic_list:
261
+ R, i, j = key
262
+ iatom = cls.iatom(i)
263
+ jatom = cls.iatom(j)
264
+
265
+ # Get fractional coordinates
266
+ pos_i = cls.atoms.get_scaled_positions()[iatom]
267
+ pos_j = cls.atoms.get_scaled_positions()[jatom]
268
+
269
+ # Calculate fractional coordinates for j+R
270
+ pos_jR = pos_j + np.dot(R, np.linalg.inv(cls.atoms.get_cell()))
271
+
272
+ myfile.write(
273
+ f" f1= {pos_i[0]:10.6f}, {pos_i[1]:10.6f}, {pos_i[2]:10.6f}:f2= {pos_jR[0]:10.6f}, {pos_jR[1]:10.6f}, {pos_jR[2]:10.6f}:bij= {bval:10.6f} !t1= {i+1}:t2= {j+1}\n"
274
+ )
275
+
276
+ myfile.write("End Bij_parameters\n")
@@ -18,12 +18,12 @@ from datetime import datetime
18
18
  import matplotlib.pyplot as plt
19
19
  import numpy as np
20
20
 
21
- from TB2J import __version__
22
21
  from TB2J.io_exchange.io_txt import write_Jq_info
23
22
  from TB2J.Jtensor import combine_J_tensor
24
23
  from TB2J.kpoints import monkhorst_pack
25
24
  from TB2J.spinham.spin_api import SpinModel
26
25
  from TB2J.utils import symbol_number
26
+ from TB2J.versioninfo import __version__
27
27
 
28
28
 
29
29
  class SpinIO(object):
@@ -149,6 +149,7 @@ class SpinIO(object):
149
149
  self.has_biquadratic = not (
150
150
  biquadratic_Jdict == {} or biquadratic_Jdict is None
151
151
  )
152
+
152
153
  self.biquadratic_Jdict = biquadratic_Jdict
153
154
 
154
155
  if NJT_ddict is not None:
@@ -399,6 +400,26 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
399
400
  )
400
401
  return Jmat
401
402
 
403
+ def get_full_Jtensor_for_one_R_ij(self, R, Jiso=True, Jani=True, DMI=True):
404
+ """
405
+ Return the full exchange tensor of all i and j for cell R.
406
+ param R (tuple of integers): cell index R
407
+ returns:
408
+ Jmat: (nspin,nspin,3,3) matrix.
409
+ """
410
+ if Jani or DMI:
411
+ raise ValueError(
412
+ "Jani and DMI are not supported for this method. Use get_full_Jtensor_for_one_R_ij33 instead."
413
+ )
414
+ n = self.nspin
415
+ Jmat = np.zeros((n, n), dtype=float)
416
+ for i in range(self.nspin):
417
+ for j in range(self.nspin):
418
+ J = self.get_Jiso(i, j, R)
419
+ if J is not None:
420
+ Jmat[i, j] = J
421
+ return Jmat
422
+
402
423
  def get_full_Jtensor_for_Rlist(
403
424
  self, asr=False, Jiso=True, Jani=True, DMI=True, order="i3j3"
404
425
  ):
@@ -439,11 +460,29 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
439
460
  if asr:
440
461
  iR0 = np.argmin(np.linalg.norm(self.Rlist, axis=1))
441
462
  assert np.linalg.norm(self.Rlist[iR0]) == 0
463
+ sum_JR = np.sum(np.sum(Jmat, axis=0), axis=0)
464
+ print(sum_JR)
442
465
  for i in range(n3):
443
- sum_JRi = np.sum(np.sum(Jmat, axis=0)[i])
444
- Jmat[iR0][i, i] -= sum_JRi
466
+ Jmat[iR0][i, i] -= sum_JR[i]
467
+ elif order == "ij":
468
+ Jmat = np.zeros((nR, n, n), dtype=float)
469
+ for iR, R in enumerate(self.Rlist):
470
+ Jmat[iR] = self.get_full_Jtensor_for_one_R_ij(
471
+ R, Jiso=Jiso, Jani=Jani, DMI=DMI
472
+ )
473
+ if asr:
474
+ iR0 = np.argmin(np.linalg.norm(self.Rlist, axis=1))
475
+ assert np.linalg.norm(self.Rlist[iR0]) == 0
476
+ # check if Jmat has NaN values
477
+ # sum_JR = np.sum(np.sum(Jmat, axis=0), axis=0)
478
+ # sum over axis 0 and 1
479
+ sum_JR = np.sum(Jmat, axis=(0, 1))
480
+ for i in range(n):
481
+ Jmat[iR0][i, i] -= sum_JR[i]
445
482
  else:
446
- raise ValueError("order must be either 'i3j3' or 'ij33', or 'i3j3_2D'.")
483
+ raise ValueError(
484
+ "order must be either 'i3j3' or 'ij33', or 'i3j3_2D', or 'ij'."
485
+ )
447
486
  return Jmat
448
487
 
449
488
  def write_pickle(self, path="TB2J_results", fname="TB2J.pickle"):
@@ -473,6 +512,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
473
512
 
474
513
  def write_all(self, path="TB2J_results"):
475
514
  self.write_pickle(path=path)
515
+ self.atoms.write(os.path.join(path, "structure.vasp"), vasp5=True)
476
516
  self.write_txt(path=path)
477
517
  if self.Jiso_orb:
478
518
  self.write_txt(
@@ -483,6 +523,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
483
523
  self.write_multibinit(path=os.path.join(path, "Multibinit"))
484
524
  self.write_tom_format(path=os.path.join(path, "TomASD"))
485
525
  self.write_vampire(path=os.path.join(path, "Vampire"))
526
+ self.write_espins(path=os.path.join(path, "ESPInS"))
486
527
 
487
528
  self.plot_all(savefile=os.path.join(path, "JvsR.pdf"))
488
529
  # self.write_Jq(kmesh=[9, 9, 9], path=path)
@@ -492,11 +533,6 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
492
533
 
493
534
  write_txt(self, *args, **kwargs)
494
535
 
495
- # def write_txt_with_orb(self, path):
496
- # from TB2J.io_exchange.io_txt import write_txt
497
- # write_txt_with_orb(
498
- # self, path=path, write_experimental=self.write_experimental)
499
-
500
536
  def write_multibinit(self, path):
501
537
  from TB2J.io_exchange.io_multibinit import write_multibinit
502
538
 
@@ -541,7 +577,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
541
577
  Js.append(val * 1e3)
542
578
  ax.scatter(ds, Js, marker=marker, color=color, **kwargs)
543
579
  ax.axhline(color="gray")
544
- ax.set_xlabel("Distance ($\AA$)")
580
+ ax.set_xlabel(r"Distance ($\AA$)")
545
581
  ax.set_ylabel("J (meV)")
546
582
  if fname is not None:
547
583
  plt.savefig(fname)
@@ -569,7 +605,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
569
605
  ax.axhline(color="gray")
570
606
  ax.legend(loc=1)
571
607
  ax.set_ylabel("D (meV)")
572
- ax.set_xlabel("Distance ($\AA$)")
608
+ ax.set_xlabel(r"Distance ($\AA$)")
573
609
  if fname is not None:
574
610
  plt.savefig(fname)
575
611
  if show:
@@ -601,7 +637,7 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
601
637
  )
602
638
  ax.axhline(color="gray")
603
639
  ax.legend(loc=1, ncol=2)
604
- ax.set_xlabel("Distance ($\AA$)")
640
+ ax.set_xlabel(r"Distance ($\AA$)")
605
641
  ax.set_ylabel("Jani (meV)")
606
642
  if fname is not None:
607
643
  plt.savefig(fname)
@@ -651,6 +687,11 @@ Generation time: {now.strftime("%y/%m/%d %H:%M:%S")}
651
687
 
652
688
  write_uppasd(self, path=path)
653
689
 
690
+ def write_espins(self, path):
691
+ from TB2J.io_exchange.io_espins import write_espins
692
+
693
+ write_espins(self, path=path)
694
+
654
695
 
655
696
  def gen_distance_dict(ind_mag_atoms, atoms, Rlist):
656
697
  distance_dict = {}
@@ -1,8 +1,10 @@
1
- import numpy as np
2
1
  import os
3
- from TB2J.utils import symbol_number
2
+
3
+ import numpy as np
4
4
  from numpy import array_str
5
5
 
6
+ from TB2J.utils import symbol_number
7
+
6
8
 
7
9
  def write_info_section(cls, myfile):
8
10
  myfile.write("=" * 90 + "\n")
@@ -17,7 +19,7 @@ def write_atom_section(cls, myfile):
17
19
  write the atom section
18
20
  including the cell and the atomic positions.
19
21
  """
20
- myfile.write("=" * 90 + "\n")
22
+ myfile.write("\n" + "=" * 90 + "\n")
21
23
  myfile.write("Cell (Angstrom):\n")
22
24
  cell = cls.atoms.get_cell()
23
25
  for c in cell:
@@ -42,7 +44,7 @@ def write_atom_section(cls, myfile):
42
44
  )
43
45
 
44
46
  symnum = symbol_number(cls.atoms)
45
- sns = list(symnum.keys())
47
+ # sns = list(symnum.keys())
46
48
  poses = cls.atoms.get_positions()
47
49
 
48
50
  tchg, tmx, tmy, tmz = 0, 0, 0, 0
@@ -105,7 +107,7 @@ def write_exchange_section(
105
107
  ):
106
108
  symnum = symbol_number(cls.atoms)
107
109
  sns = list(symnum.keys())
108
- poses = cls.atoms.get_positions()
110
+ # poses = cls.atoms.get_positions()
109
111
 
110
112
  myfile.write("=" * 90 + "\n")
111
113
  myfile.write("Exchange: \n")
@@ -183,9 +185,8 @@ def write_exchange_section(
183
185
  DMI2[0], DMI2[1], DMI2[2]
184
186
  )
185
187
  )
186
- pass
187
- except:
188
- pass
188
+ except Exception as e:
189
+ myfile.write(f"[Debug!] DMI2 not available: {e}\n")
189
190
 
190
191
  if cls.Jani_dict is not None:
191
192
  J = cls.Jani_dict[ll] * 1e3
@@ -63,7 +63,6 @@ def write_uppasd_exchange(cls, fname):
63
63
  d = np.dot(np.array(R), cls.atoms.get_cell()) + pos[j] - pos[i]
64
64
  myfile.write(
65
65
  "{i} {j} {Rx} {Ry} {Rz} {Jij}\n".format(
66
- IID=counter,
67
66
  i=i + 1,
68
67
  j=j + 1,
69
68
  Rx=d[0],
@@ -66,7 +66,7 @@ def write_vampire_unitcell_file(cls, fname):
66
66
 
67
67
  def write_vampire_mat_file(cls, fname):
68
68
  mat_tmpl = """#---------------------------------------------------
69
- # Material {id}
69
+ # Material {id}
70
70
  #---------------------------------------------------
71
71
  material[{id}]:material-name={name}
72
72
  material[{id}]:damping-constant={damping}
@@ -75,6 +75,8 @@ material[{id}]:uniaxial-anisotropy-constant={k1}
75
75
  material[{id}]:material-element={name}
76
76
  material[{id}]:initial-spin-direction = {spinat}
77
77
  material[{id}]:uniaxial-anisotropy-direction = {k1dir}
78
+ # The following line is required for vampire 5 and later.
79
+ material[{id}]:unit-cell-category = {id}
78
80
  #---------------------------------------------------
79
81
  """
80
82
  with open(fname, "w") as myfile: