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.
- TB2J/.gitignore +5 -0
- TB2J/Jdownfolder.py +43 -19
- TB2J/MAEGreen.py +78 -60
- TB2J/__init__.py +3 -1
- TB2J/anisotropy.py +2 -2
- TB2J/basis.py +0 -3
- TB2J/contour.py +3 -2
- TB2J/exchange.py +335 -48
- TB2J/exchangeCL2.py +289 -51
- TB2J/exchange_params.py +25 -1
- TB2J/gpaw_wrapper.py +0 -3
- TB2J/green.py +58 -33
- TB2J/interfaces/wannier90_interface.py +4 -4
- TB2J/io_exchange/io_espins.py +276 -0
- TB2J/io_exchange/io_exchange.py +53 -12
- TB2J/io_exchange/io_txt.py +9 -8
- TB2J/io_exchange/io_uppasd.py +0 -1
- TB2J/io_exchange/io_vampire.py +3 -1
- TB2J/magnon/magnon3.py +76 -28
- TB2J/magnon/plot_magnon_dos_cli.py +115 -3
- TB2J/myTB.py +11 -11
- TB2J/pauli.py +32 -2
- TB2J/plot.py +8 -7
- TB2J/rotate_atoms.py +10 -7
- TB2J/scripts/TB2J_downfold.py +97 -0
- TB2J/scripts/TB2J_eigen.py +49 -0
- TB2J/scripts/TB2J_magnon.py +117 -0
- TB2J/scripts/TB2J_magnon2.py +78 -0
- TB2J/scripts/TB2J_magnon_dos.py +5 -0
- TB2J/scripts/TB2J_merge.py +49 -0
- TB2J/scripts/TB2J_plot_magnon_bands.py +22 -0
- TB2J/scripts/TB2J_rotate.py +29 -0
- TB2J/scripts/TB2J_rotateDM.py +21 -0
- TB2J/scripts/__init__.py +0 -0
- TB2J/scripts/abacus2J.py +61 -0
- TB2J/scripts/siesta2J.py +78 -0
- TB2J/scripts/wann2J.py +101 -0
- TB2J/spinham/hamiltonian.py +0 -1
- TB2J/symmetrize_J.py +2 -2
- TB2J/tensor_rotate.py +1 -2
- TB2J/versioninfo.py +3 -0
- TB2J/wannier/w90_tb_parser.py +0 -2
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/METADATA +7 -7
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/RECORD +48 -33
- tb2j-0.9.12.17.dist-info/entry_points.txt +15 -0
- tb2j-0.9.10.1.dist-info/entry_points.txt +0 -16
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/WHEEL +0 -0
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/licenses/LICENSE +0 -0
- {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")
|
TB2J/io_exchange/io_exchange.py
CHANGED
|
@@ -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
|
-
|
|
444
|
-
|
|
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(
|
|
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 = {}
|
TB2J/io_exchange/io_txt.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import numpy as np
|
|
2
1
|
import os
|
|
3
|
-
|
|
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
|
-
|
|
187
|
-
|
|
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
|
TB2J/io_exchange/io_uppasd.py
CHANGED
TB2J/io_exchange/io_vampire.py
CHANGED
|
@@ -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:
|