TB2Jflows 0.1__py3-none-any.whl → 0.1.0__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.
- TB2Jflows/ase_siesta.py +5 -7
- TB2Jflows/auto_siesta_TB2J.py +0 -2
- TB2Jflows/find_pp.py +67 -0
- TB2Jflows/mysiesta.py +521 -0
- TB2Jflows/siesta_basis.py +50 -0
- tb2jflows-0.1.0.dist-info/METADATA +77 -0
- tb2jflows-0.1.0.dist-info/RECORD +11 -0
- {tb2jflows-0.1.dist-info → tb2jflows-0.1.0.dist-info}/WHEEL +1 -2
- tb2jflows-0.1.dist-info/METADATA +0 -31
- tb2jflows-0.1.dist-info/RECORD +0 -9
- tb2jflows-0.1.dist-info/top_level.txt +0 -1
- {tb2jflows-0.1.dist-info → tb2jflows-0.1.0.dist-info}/licenses/LICENSE +0 -0
TB2Jflows/ase_siesta.py
CHANGED
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
import ase
|
|
7
7
|
from ase.io.jsonio import decode, encode
|
|
8
|
-
from pyDFTutils.siesta import MySiesta
|
|
8
|
+
#from pyDFTutils.siesta import MySiesta
|
|
9
9
|
from TB2J.interfaces import gen_exchange_siesta
|
|
10
10
|
from TB2J.io_merge import merge
|
|
11
11
|
from TB2J.rotate_atoms import rotate_atom_spin, rotate_atom_xyz
|
|
@@ -24,7 +24,6 @@ class SiestaFlow:
|
|
|
24
24
|
restart=True,
|
|
25
25
|
metadata={},
|
|
26
26
|
fdf_arguments={},
|
|
27
|
-
relax_arguments={},
|
|
28
27
|
split_soc=False,
|
|
29
28
|
**kwargs,
|
|
30
29
|
):
|
|
@@ -51,7 +50,6 @@ class SiestaFlow:
|
|
|
51
50
|
self.root_path = root_path
|
|
52
51
|
self.restart = restart
|
|
53
52
|
self.kwargs = kwargs
|
|
54
|
-
self.relax_args = relax_arguments
|
|
55
53
|
|
|
56
54
|
# paths
|
|
57
55
|
self.metadata_path = os.path.join(self.root_path, "metadata.json")
|
|
@@ -358,9 +356,9 @@ class SiestaFlow:
|
|
|
358
356
|
write_path=os.path.join(self.root_path, "TB2J_results_merged"),
|
|
359
357
|
)
|
|
360
358
|
|
|
361
|
-
def runall_collinear(self, atoms, relax=True, scf=True, TB2J=True,
|
|
359
|
+
def runall_collinear(self, atoms, relax=True, scf=True, TB2J=True, **kwargs):
|
|
362
360
|
if relax:
|
|
363
|
-
atoms = self.relax(atoms
|
|
361
|
+
atoms = self.relax(atoms)
|
|
364
362
|
if scf:
|
|
365
363
|
self.scf_calculation_collinear(atoms, label="siesta")
|
|
366
364
|
if TB2J:
|
|
@@ -370,7 +368,7 @@ class SiestaFlow:
|
|
|
370
368
|
self, atoms, relax=True, scf=True, TB2J=True, rotate_type="structure", **kwargs
|
|
371
369
|
):
|
|
372
370
|
if relax:
|
|
373
|
-
atoms = self.relax(atoms
|
|
371
|
+
atoms = self.relax(atoms)
|
|
374
372
|
if scf:
|
|
375
373
|
self.scf_calculation_with_rotations(
|
|
376
374
|
atoms, rotate_type=rotate_type, label="siesta"
|
|
@@ -381,7 +379,7 @@ class SiestaFlow:
|
|
|
381
379
|
|
|
382
380
|
def runall_split_soc(self, atoms, relax=True, scf=True, TB2J=True, **kwargs):
|
|
383
381
|
if relax:
|
|
384
|
-
atoms = self.relax(atoms
|
|
382
|
+
atoms = self.relax(atoms)
|
|
385
383
|
if scf:
|
|
386
384
|
self.scf_calculatoin_split_soc(atoms, label="siesta")
|
|
387
385
|
if TB2J:
|
TB2Jflows/auto_siesta_TB2J.py
CHANGED
|
@@ -52,7 +52,6 @@ def auto_siesta_TB2J(
|
|
|
52
52
|
TB2J=True,
|
|
53
53
|
rotate_type="structure",
|
|
54
54
|
fincore=True,
|
|
55
|
-
relax_arguments={},
|
|
56
55
|
siesta_kwargs={},
|
|
57
56
|
TB2J_kwargs={},
|
|
58
57
|
fdf_kwargs={},
|
|
@@ -100,7 +99,6 @@ def auto_siesta_TB2J(
|
|
|
100
99
|
fincore=fincore,
|
|
101
100
|
Udict=Udict,
|
|
102
101
|
split_soc=split_soc,
|
|
103
|
-
relax_arguments = relax_arguments,
|
|
104
102
|
**siesta_kwargs,
|
|
105
103
|
)
|
|
106
104
|
flow.write_metadata()
|
TB2Jflows/find_pp.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from ase.data import chemical_symbols, atomic_numbers
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PPFinder():
|
|
6
|
+
def __init__(self):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
def get_pp_path(self, element, xc, label, rel):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
class DojoFinder():
|
|
13
|
+
def __init__(self, path=None):
|
|
14
|
+
if path is None:
|
|
15
|
+
self.path = os.environ['DOJO_PATH']
|
|
16
|
+
else:
|
|
17
|
+
self.path = path
|
|
18
|
+
|
|
19
|
+
def get_pp_path(self,
|
|
20
|
+
xc : str,
|
|
21
|
+
typ='NC',
|
|
22
|
+
rel='sr',
|
|
23
|
+
version='04',
|
|
24
|
+
accuracy='standard',
|
|
25
|
+
fmt='psml'):
|
|
26
|
+
typ=typ.lower()
|
|
27
|
+
xc=xc.lower()
|
|
28
|
+
if xc=="lda":
|
|
29
|
+
xc="pw"
|
|
30
|
+
dirname = os.path.join(self.path, f"{typ}-{rel}-{version}_{xc}_{accuracy}_{fmt}")
|
|
31
|
+
if not os.path.exists(dirname):
|
|
32
|
+
raise FileNotFoundError(f"File Not found: {dirname}")
|
|
33
|
+
return dirname
|
|
34
|
+
|
|
35
|
+
def get_pp_fname(self,
|
|
36
|
+
element,
|
|
37
|
+
xc : str,
|
|
38
|
+
typ='NC',
|
|
39
|
+
rel='sr',
|
|
40
|
+
version='04',
|
|
41
|
+
accuracy='standard',
|
|
42
|
+
fincore=False,
|
|
43
|
+
fmt='psml'):
|
|
44
|
+
if 57<atomic_numbers[element]<=70:
|
|
45
|
+
if fincore:
|
|
46
|
+
fname = os.path.join(self.get_pp_path(xc=xc, typ=typ, rel=rel,
|
|
47
|
+
version=version, accuracy=accuracy, fmt=fmt), f"fincore/{element}.{fmt}")
|
|
48
|
+
else:
|
|
49
|
+
fname = os.path.join(self.get_pp_path(xc=xc, typ=typ, rel=rel,
|
|
50
|
+
version=version, accuracy=accuracy, fmt=fmt), f"withf/{element}.{fmt}")
|
|
51
|
+
|
|
52
|
+
else:
|
|
53
|
+
fname = os.path.join(self.get_pp_path(xc=xc, typ=typ, rel=rel,
|
|
54
|
+
version=version, accuracy=accuracy, fmt=fmt), f"{element}.{fmt}")
|
|
55
|
+
if not os.path.exists(fname):
|
|
56
|
+
raise FileNotFoundError(f"File Not found: {fname}")
|
|
57
|
+
return fname
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test():
|
|
62
|
+
finder=DojoFinder(path=os.path.expanduser('~/projects/pp/dojo'))
|
|
63
|
+
fname=finder.get_pp_path(element='Sr', xc='pbesol')
|
|
64
|
+
fname=finder.get_pp_path(element='Srg', xc='pbe')
|
|
65
|
+
|
|
66
|
+
if __name__=='__main__':
|
|
67
|
+
test()
|
TB2Jflows/mysiesta.py
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import math
|
|
3
|
+
import numpy as np
|
|
4
|
+
from ase import Atoms
|
|
5
|
+
from ase.calculators.siesta import Siesta
|
|
6
|
+
from ase.calculators.calculator import FileIOCalculator, ReadError
|
|
7
|
+
from ase.calculators.siesta.parameters import format_fdf
|
|
8
|
+
from ase.calculators.siesta.parameters import Species, PAOBasisBlock
|
|
9
|
+
from ase.io import write
|
|
10
|
+
import copy
|
|
11
|
+
|
|
12
|
+
import shutil
|
|
13
|
+
from os.path import join, isfile, islink
|
|
14
|
+
import numpy as np
|
|
15
|
+
from ase.units import Ry, eV, Bohr
|
|
16
|
+
from ase.data import atomic_numbers
|
|
17
|
+
#from ase.io.siesta import read_siesta_xv
|
|
18
|
+
#from ase.calculators.siesta.import_functions import \
|
|
19
|
+
# get_valence_charge, read_vca_synth_block
|
|
20
|
+
from ase.calculators.calculator import FileIOCalculator, ReadError
|
|
21
|
+
from ase.calculators.calculator import Parameters, all_changes
|
|
22
|
+
from ase.calculators.siesta.parameters import PAOBasisBlock, Species
|
|
23
|
+
from ase.calculators.siesta.parameters import format_fdf
|
|
24
|
+
#from pyDFTutils.siesta.pdos import gen_pdos_figure, plot_layer_pdos
|
|
25
|
+
|
|
26
|
+
from .siesta_basis import get_basis, fincore_basis, withf_basis
|
|
27
|
+
from .findpp import DojoFinder
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
synthetic_atoms_dict_fincore={
|
|
31
|
+
"Yb":((6,5,5,5), (2,6,1,0))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
def read_siesta_xv(fd):
|
|
35
|
+
vectors = []
|
|
36
|
+
for i in range(3):
|
|
37
|
+
data = next(fd).split()
|
|
38
|
+
vectors.append([float(data[j]) * Bohr for j in range(3)])
|
|
39
|
+
|
|
40
|
+
# Read number of atoms (line 4)
|
|
41
|
+
natoms = int(next(fd).split()[0])
|
|
42
|
+
|
|
43
|
+
# Read remaining lines
|
|
44
|
+
speciesnumber, atomnumbers, xyz, V = [], [], [], []
|
|
45
|
+
for line in fd:
|
|
46
|
+
if len(line) > 5: # Ignore blank lines
|
|
47
|
+
data = line.split()
|
|
48
|
+
speciesnumber.append(int(data[0]))
|
|
49
|
+
atomnumbers.append(int(data[1])%200)
|
|
50
|
+
xyz.append([float(data[2 + j]) * Bohr for j in range(3)])
|
|
51
|
+
V.append([float(data[5 + j]) * Bohr for j in range(3)])
|
|
52
|
+
|
|
53
|
+
vectors = np.array(vectors)
|
|
54
|
+
atomnumbers = np.array(atomnumbers)
|
|
55
|
+
xyz = np.array(xyz)
|
|
56
|
+
atoms = Atoms(numbers=atomnumbers, positions=xyz, cell=vectors,
|
|
57
|
+
pbc=True)
|
|
58
|
+
assert natoms == len(atoms)
|
|
59
|
+
return atoms
|
|
60
|
+
|
|
61
|
+
def read_xv(fname):
|
|
62
|
+
with open(fname) as myfile:
|
|
63
|
+
atoms=read_siesta_xv(myfile)
|
|
64
|
+
return atoms
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_species(atoms, xc, rel='sr', accuracy='standard'):
|
|
68
|
+
finder = DojoFinder()
|
|
69
|
+
elems = list(dict.fromkeys(atoms.get_chemical_symbols()).keys())
|
|
70
|
+
elem_dict = dict(zip(elems, range(1, len(elems) + 1)))
|
|
71
|
+
pseudo_path = finder.get_pp_path(xc=xc)
|
|
72
|
+
species = [
|
|
73
|
+
Species(symbol=elem,
|
|
74
|
+
pseudopotential=finder.get_pp_fname(
|
|
75
|
+
elem, xc=xc, rel=rel, accuracy=accuracy, fincore=fincore),
|
|
76
|
+
ghost=False) for elem in elem_dict.keys()
|
|
77
|
+
]
|
|
78
|
+
return pseudo_path, species
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def cart2sph(vec):
|
|
82
|
+
x, y, z = vec
|
|
83
|
+
r = np.linalg.norm(vec) # r
|
|
84
|
+
if r < 1e-10:
|
|
85
|
+
theta, phi = 0.0, 0.0
|
|
86
|
+
else:
|
|
87
|
+
# note that there are many conventions, here is the ISO convention.
|
|
88
|
+
phi = math.atan2(y, x) * 180/math.pi # phi
|
|
89
|
+
theta = math.acos(z/r) * 180/math.pi # theta
|
|
90
|
+
return r, theta, phi
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class MySiesta(Siesta):
|
|
94
|
+
def __init__(self,
|
|
95
|
+
atoms=None,
|
|
96
|
+
command=None,
|
|
97
|
+
xc='LDA',
|
|
98
|
+
spin='non-polarized',
|
|
99
|
+
basis_set='DZP',
|
|
100
|
+
species=None,
|
|
101
|
+
ghosts=[],
|
|
102
|
+
synthetic_atoms={},
|
|
103
|
+
input_basis_set={},
|
|
104
|
+
pseudo_path=None,
|
|
105
|
+
input_pp={},
|
|
106
|
+
pp_accuracy='standard',
|
|
107
|
+
fincore=False,
|
|
108
|
+
**kwargs):
|
|
109
|
+
# non-perturnbative polarized orbital.
|
|
110
|
+
self.npt_elems = set()
|
|
111
|
+
self.synthetic_atoms=synthetic_atoms
|
|
112
|
+
|
|
113
|
+
if fincore:
|
|
114
|
+
input_basis_set.update(fincore_basis)
|
|
115
|
+
else:
|
|
116
|
+
input_basis_set.update(withf_basis)
|
|
117
|
+
|
|
118
|
+
if atoms is not None:
|
|
119
|
+
finder = DojoFinder()
|
|
120
|
+
elems = list(dict.fromkeys(atoms.get_chemical_symbols()).keys())
|
|
121
|
+
self.elem_dict = dict(zip(elems, range(1, len(elems) + 1)))
|
|
122
|
+
symbols = atoms.get_chemical_symbols()
|
|
123
|
+
|
|
124
|
+
# ghosts
|
|
125
|
+
ghost_symbols = [symbols[i] for i in ghosts]
|
|
126
|
+
ghost_elems = list(dict.fromkeys(ghost_symbols).keys())
|
|
127
|
+
tags = [1 if i in ghosts else 0 for i in range(len(atoms))]
|
|
128
|
+
atoms.set_tags(tags)
|
|
129
|
+
|
|
130
|
+
if pseudo_path is None:
|
|
131
|
+
pseudo_path = finder.get_pp_path(xc=xc, accuracy=pp_accuracy)
|
|
132
|
+
|
|
133
|
+
if spin == 'spin-orbit':
|
|
134
|
+
rel = 'fr'
|
|
135
|
+
else:
|
|
136
|
+
rel = 'sr'
|
|
137
|
+
species = []
|
|
138
|
+
for elem, index in self.elem_dict.items():
|
|
139
|
+
if elem not in input_basis_set:
|
|
140
|
+
bselem = basis_set
|
|
141
|
+
if elem in ['Li', 'Be', 'Na', 'Mg', 'Sm']:
|
|
142
|
+
self.npt_elems.add(f"{elem}.{index}")
|
|
143
|
+
else:
|
|
144
|
+
bselem = PAOBasisBlock(input_basis_set[elem])
|
|
145
|
+
if elem not in input_pp:
|
|
146
|
+
pseudopotential = finder.get_pp_fname(
|
|
147
|
+
elem, xc=xc, rel=rel, accuracy=pp_accuracy, fincore=fincore)
|
|
148
|
+
else:
|
|
149
|
+
pseudopotential = os.path.join(
|
|
150
|
+
pseudo_path, input_pp[elem])
|
|
151
|
+
|
|
152
|
+
if elem in self.synthetic_atoms:
|
|
153
|
+
excess_charge = 0
|
|
154
|
+
else:
|
|
155
|
+
excess_charge = None
|
|
156
|
+
|
|
157
|
+
species.append(Species(symbol=elem,
|
|
158
|
+
pseudopotential=pseudopotential,
|
|
159
|
+
basis_set=bselem,
|
|
160
|
+
ghost=False,
|
|
161
|
+
excess_charge=excess_charge))
|
|
162
|
+
for elem in ghost_elems:
|
|
163
|
+
species.append(
|
|
164
|
+
Species(symbol=elem,
|
|
165
|
+
pseudopotential=finder.get_pp_fname(
|
|
166
|
+
elem, xc=xc, rel=rel, accuracy=pp_accuracy,
|
|
167
|
+
fincore=fincore),
|
|
168
|
+
tag=1,
|
|
169
|
+
ghost=True))
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
Siesta.__init__(self,
|
|
173
|
+
xc=xc,
|
|
174
|
+
spin=spin,
|
|
175
|
+
atoms=atoms,
|
|
176
|
+
pseudo_path=pseudo_path,
|
|
177
|
+
species=species,
|
|
178
|
+
**kwargs)
|
|
179
|
+
self.set_npt_elements()
|
|
180
|
+
self.set_synthetic_atoms()
|
|
181
|
+
|
|
182
|
+
def _write_species(self, fd, atoms):
|
|
183
|
+
"""Write input related the different species.
|
|
184
|
+
|
|
185
|
+
Parameters:
|
|
186
|
+
- f: An open file object.
|
|
187
|
+
- atoms: An atoms object.
|
|
188
|
+
"""
|
|
189
|
+
species, species_numbers = self.species(atoms)
|
|
190
|
+
|
|
191
|
+
if self['pseudo_path'] is not None:
|
|
192
|
+
pseudo_path = self['pseudo_path']
|
|
193
|
+
elif 'SIESTA_PP_PATH' in os.environ:
|
|
194
|
+
pseudo_path = os.environ['SIESTA_PP_PATH']
|
|
195
|
+
else:
|
|
196
|
+
mess = "Please set the environment variable 'SIESTA_PP_PATH'"
|
|
197
|
+
raise Exception(mess)
|
|
198
|
+
|
|
199
|
+
fd.write(format_fdf('NumberOfSpecies', len(species)))
|
|
200
|
+
fd.write(format_fdf('NumberOfAtoms', len(atoms)))
|
|
201
|
+
|
|
202
|
+
pao_basis = []
|
|
203
|
+
chemical_labels = []
|
|
204
|
+
basis_sizes = []
|
|
205
|
+
synth_blocks = []
|
|
206
|
+
for species_number, spec in enumerate(species):
|
|
207
|
+
species_number += 1
|
|
208
|
+
symbol = spec['symbol']
|
|
209
|
+
atomic_number = atomic_numbers[symbol]
|
|
210
|
+
|
|
211
|
+
if spec['pseudopotential'] is None:
|
|
212
|
+
if self.pseudo_qualifier() == '':
|
|
213
|
+
label = symbol
|
|
214
|
+
pseudopotential = label + '.psf'
|
|
215
|
+
else:
|
|
216
|
+
label = '.'.join([symbol, self.pseudo_qualifier()])
|
|
217
|
+
pseudopotential = label + '.psf'
|
|
218
|
+
else:
|
|
219
|
+
pseudopotential = spec['pseudopotential']
|
|
220
|
+
label = os.path.basename(pseudopotential)
|
|
221
|
+
label = '.'.join(label.split('.')[:-1])
|
|
222
|
+
|
|
223
|
+
if not os.path.isabs(pseudopotential):
|
|
224
|
+
pseudopotential = join(pseudo_path, pseudopotential)
|
|
225
|
+
|
|
226
|
+
if not os.path.exists(pseudopotential):
|
|
227
|
+
mess = "Pseudopotential '%s' not found" % pseudopotential
|
|
228
|
+
raise RuntimeError(mess)
|
|
229
|
+
|
|
230
|
+
name = os.path.basename(pseudopotential)
|
|
231
|
+
name = name.split('.')
|
|
232
|
+
name.insert(-1, str(species_number))
|
|
233
|
+
if spec['ghost']:
|
|
234
|
+
name.insert(-1, 'ghost')
|
|
235
|
+
atomic_number = -atomic_number
|
|
236
|
+
|
|
237
|
+
name = '.'.join(name)
|
|
238
|
+
pseudo_targetpath = self.getpath(name)
|
|
239
|
+
|
|
240
|
+
if join(os.getcwd(), name) != pseudopotential:
|
|
241
|
+
if islink(pseudo_targetpath) or isfile(pseudo_targetpath):
|
|
242
|
+
os.remove(pseudo_targetpath)
|
|
243
|
+
symlink_pseudos = self['symlink_pseudos']
|
|
244
|
+
|
|
245
|
+
symlink_pseudos = False
|
|
246
|
+
|
|
247
|
+
if symlink_pseudos is None:
|
|
248
|
+
symlink_pseudos = not os.name == 'nt'
|
|
249
|
+
|
|
250
|
+
if symlink_pseudos:
|
|
251
|
+
os.symlink(pseudopotential, pseudo_targetpath)
|
|
252
|
+
else:
|
|
253
|
+
shutil.copy(pseudopotential, pseudo_targetpath)
|
|
254
|
+
if not spec['excess_charge'] is None:
|
|
255
|
+
atomic_number += 200
|
|
256
|
+
n_atoms = sum(np.array(species_numbers) == species_number)
|
|
257
|
+
|
|
258
|
+
if spec['excess_charge'] != 0:
|
|
259
|
+
paec = float(spec['excess_charge']) / n_atoms
|
|
260
|
+
vc = get_valence_charge(pseudopotential)
|
|
261
|
+
fraction = float(vc + paec) / vc
|
|
262
|
+
pseudo_head = name[:-4]
|
|
263
|
+
fractional_command = os.environ['SIESTA_UTIL_FRACTIONAL']
|
|
264
|
+
cmd = '%s %s %.7f' % (fractional_command,
|
|
265
|
+
pseudo_head,
|
|
266
|
+
fraction)
|
|
267
|
+
os.system(cmd)
|
|
268
|
+
|
|
269
|
+
pseudo_head += '-Fraction-%.5f' % fraction
|
|
270
|
+
synth_pseudo = pseudo_head + '.psf'
|
|
271
|
+
synth_block_filename = pseudo_head + '.synth'
|
|
272
|
+
os.remove(name)
|
|
273
|
+
shutil.copyfile(synth_pseudo, name)
|
|
274
|
+
synth_block = read_vca_synth_block(
|
|
275
|
+
synth_block_filename,
|
|
276
|
+
species_number=species_number)
|
|
277
|
+
synth_blocks.append(synth_block)
|
|
278
|
+
else:
|
|
279
|
+
synth_block = self.synthetic_atoms[symbol]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
if len(synth_blocks) > 0:
|
|
284
|
+
fd.write(format_fdf('SyntheticAtoms', list(synth_blocks)))
|
|
285
|
+
|
|
286
|
+
label = '.'.join(np.array(name.split('.'))[:-1])
|
|
287
|
+
string = ' %d %d %s' % (species_number, atomic_number, label)
|
|
288
|
+
chemical_labels.append(string)
|
|
289
|
+
if isinstance(spec['basis_set'], PAOBasisBlock):
|
|
290
|
+
pao_basis.append(spec['basis_set'].script(label))
|
|
291
|
+
else:
|
|
292
|
+
basis_sizes.append((" " + label, spec['basis_set']))
|
|
293
|
+
fd.write((format_fdf('ChemicalSpecieslabel', chemical_labels)))
|
|
294
|
+
fd.write('\n')
|
|
295
|
+
fd.write((format_fdf('PAO.Basis', pao_basis)))
|
|
296
|
+
fd.write((format_fdf('PAO.BasisSizes', basis_sizes)))
|
|
297
|
+
fd.write('\n')
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def set_npt_elements(self):
|
|
301
|
+
if len(self.npt_elems) > 0:
|
|
302
|
+
npt_text = []
|
|
303
|
+
for name in self.npt_elems:
|
|
304
|
+
npt_text.append(
|
|
305
|
+
f"{name} non-perturbative ")
|
|
306
|
+
# npt_text += "%endblock PAO.PolarizationScheme\n"
|
|
307
|
+
self['fdf_arguments'].update({"PAO.PolarizationScheme": npt_text})
|
|
308
|
+
|
|
309
|
+
def set_synthetic_atoms(self):
|
|
310
|
+
print("setting syn")
|
|
311
|
+
nsyn=len(self.synthetic_atoms)
|
|
312
|
+
if nsyn> 0:
|
|
313
|
+
syntext = []
|
|
314
|
+
#syntext.append(f"{nsyn}")
|
|
315
|
+
for name, content in self.synthetic_atoms.items():
|
|
316
|
+
syntext.append(
|
|
317
|
+
f"{self.elem_dict[name]}")
|
|
318
|
+
syntext.append(
|
|
319
|
+
" ".join([str(x) for x in content[0]]))
|
|
320
|
+
syntext.append(
|
|
321
|
+
" ".join([str(x) for x in content[1]]))
|
|
322
|
+
self['fdf_arguments'].update({"SyntheticAtoms": syntext})
|
|
323
|
+
|
|
324
|
+
#print("setting syn:", syntext)
|
|
325
|
+
|
|
326
|
+
def set_fdf_arguments(self, fdf_arguments):
|
|
327
|
+
self['fdf_arguments'].update(fdf_arguments)
|
|
328
|
+
|
|
329
|
+
def set_mixer(self,
|
|
330
|
+
method='pulay',
|
|
331
|
+
weight=0.05,
|
|
332
|
+
history=10,
|
|
333
|
+
restart=25,
|
|
334
|
+
restart_save=4,
|
|
335
|
+
linear_after=0,
|
|
336
|
+
linear_after_weight=0.1):
|
|
337
|
+
pass
|
|
338
|
+
|
|
339
|
+
def update_fdf_arguments(self, fdf_arguments):
|
|
340
|
+
fdf = self['fdf_arguments'].update(fdf_arguments)
|
|
341
|
+
|
|
342
|
+
def add_Hubbard_U(self,
|
|
343
|
+
specy,
|
|
344
|
+
n=3,
|
|
345
|
+
l=2,
|
|
346
|
+
U=0,
|
|
347
|
+
J=0,
|
|
348
|
+
rc=0.0,
|
|
349
|
+
Fermi_cut=0.0,
|
|
350
|
+
scale_factor='0.95'):
|
|
351
|
+
if not 'Udict' in self.__dict__:
|
|
352
|
+
self.Udict = dict()
|
|
353
|
+
idx=self.elem_dict[specy]
|
|
354
|
+
specy_label=f"{specy}.{idx}"
|
|
355
|
+
self.Udict[specy_label] = {
|
|
356
|
+
'n': n,
|
|
357
|
+
'l': l,
|
|
358
|
+
'U': U,
|
|
359
|
+
'J': J,
|
|
360
|
+
'rc': rc,
|
|
361
|
+
'Fermi_cut': Fermi_cut,
|
|
362
|
+
'scale_factor': scale_factor
|
|
363
|
+
}
|
|
364
|
+
self.set_Hubbard_U(self.Udict)
|
|
365
|
+
|
|
366
|
+
def set_Hubbard_U(self, Udict):
|
|
367
|
+
"""
|
|
368
|
+
Udict: {'Fe': {'n':n, 'l':l, 'U':U, 'J', J, 'rc':rc, 'Fermi_cut':Fermi_cut }}
|
|
369
|
+
"""
|
|
370
|
+
Ublock = []
|
|
371
|
+
for key, val in Udict.items():
|
|
372
|
+
Ublock.append(' %s %s ' % (key, 1))
|
|
373
|
+
if val['n'] is not None:
|
|
374
|
+
Ublock.append(' n=%s %s' % (val['n'], val['l']))
|
|
375
|
+
else:
|
|
376
|
+
Ublock.append('%s' % (val['l']))
|
|
377
|
+
Ublock.append(' %s %s' % (val['U'], val['J']))
|
|
378
|
+
if 'rc' in val:
|
|
379
|
+
Ublock.append(' %s %s' % (val['rc'], val['Fermi_cut']))
|
|
380
|
+
Ublock.append(' %s' % val['scale_factor'])
|
|
381
|
+
|
|
382
|
+
self.update_fdf_arguments(
|
|
383
|
+
{'LDAU.Proj': Ublock, 'LDAU.ProjectorGenerationMethod': 2})
|
|
384
|
+
|
|
385
|
+
def set_Udict(self, Udict):
|
|
386
|
+
"""
|
|
387
|
+
Udict: e.g. {"Fe":{"n":3, "l":2, "U":3.0, "J":0.0}, ...}
|
|
388
|
+
or {"Fe":{[3, 2, 3, 0]}
|
|
389
|
+
|
|
390
|
+
"""
|
|
391
|
+
for specy, val in Udict.items():
|
|
392
|
+
if isinstance(val, dict):
|
|
393
|
+
self.add_Hubbard_U(specy, **val)
|
|
394
|
+
else:
|
|
395
|
+
self.add_Hubbard_U(specy, *val)
|
|
396
|
+
|
|
397
|
+
def write_Hubbard_block(self, f):
|
|
398
|
+
pass
|
|
399
|
+
|
|
400
|
+
def relax(
|
|
401
|
+
self,
|
|
402
|
+
atoms,
|
|
403
|
+
TypeOfRun='Broyden',
|
|
404
|
+
VariableCell=True,
|
|
405
|
+
ConstantVolume=False,
|
|
406
|
+
RelaxCellOnly=False,
|
|
407
|
+
MaxForceTol=0.001,
|
|
408
|
+
MaxStressTol=1,
|
|
409
|
+
NumCGSteps=40,
|
|
410
|
+
relaxed_file="relaxed.vasp"
|
|
411
|
+
):
|
|
412
|
+
pbc = atoms.get_pbc()
|
|
413
|
+
initial_magnetic_moments = atoms.get_initial_magnetic_moments()
|
|
414
|
+
self.update_fdf_arguments({
|
|
415
|
+
'MD.TypeOfRun': TypeOfRun,
|
|
416
|
+
'MD.VariableCell': VariableCell,
|
|
417
|
+
'MD.ConstantVolume': ConstantVolume,
|
|
418
|
+
'MD.RelaxCellOnly': RelaxCellOnly,
|
|
419
|
+
'MD.MaxForceTol': "%s eV/Ang" % MaxForceTol,
|
|
420
|
+
'MD.MaxStressTol': "%s GPa" % MaxStressTol,
|
|
421
|
+
'MD.NumCGSteps': NumCGSteps,
|
|
422
|
+
})
|
|
423
|
+
self.calculate(atoms)
|
|
424
|
+
#self.read(self.prefix + '.XV')
|
|
425
|
+
self.atoms=read_xv(os.path.join(self.directory, self.prefix + '.XV'))
|
|
426
|
+
self.atoms.set_pbc(pbc)
|
|
427
|
+
self.atoms.set_initial_magnetic_moments(initial_magnetic_moments)
|
|
428
|
+
atoms = self.atoms
|
|
429
|
+
self.update_fdf_arguments({
|
|
430
|
+
'MD.NumCGSteps': 0,
|
|
431
|
+
})
|
|
432
|
+
if relaxed_file is not None:
|
|
433
|
+
write(relaxed_file, atoms, vasp5=True, sort=False)
|
|
434
|
+
return self.atoms
|
|
435
|
+
|
|
436
|
+
def scf_calculation(self, atoms, dos=True, kpts=[7,7,7], **kwargs):
|
|
437
|
+
if dos:
|
|
438
|
+
k1, k2, k3 = kpts
|
|
439
|
+
self.update_fdf_arguments({'WriteEigenvalues': '.true.',
|
|
440
|
+
'ProjectedDensityOfStates': ['-70.00 30.0 0.015 3000 eV'],
|
|
441
|
+
'PDOS.kgrid_Monkhorst_Pack': [f'{k1} 0 0 0.0',
|
|
442
|
+
f'0 {k2} 0 0.0',
|
|
443
|
+
f'0 0 {k3} 0.0']})
|
|
444
|
+
self.calculate(atoms, **kwargs)
|
|
445
|
+
|
|
446
|
+
def _write_structure(self, f, atoms):
|
|
447
|
+
"""Translate the Atoms object to fdf-format.
|
|
448
|
+
|
|
449
|
+
Parameters:
|
|
450
|
+
- f: An open file object.
|
|
451
|
+
- atoms: An atoms object.
|
|
452
|
+
"""
|
|
453
|
+
cell = atoms.cell
|
|
454
|
+
f.write('\n')
|
|
455
|
+
|
|
456
|
+
if cell.rank in [1, 2]:
|
|
457
|
+
raise ValueError('Expected 3D unit cell or no unit cell. You may '
|
|
458
|
+
'wish to add vacuum along some directions.')
|
|
459
|
+
|
|
460
|
+
# Write lattice vectors
|
|
461
|
+
if np.any(cell):
|
|
462
|
+
f.write(format_fdf('LatticeConstant', '1.0 Ang'))
|
|
463
|
+
f.write('%block LatticeVectors\n')
|
|
464
|
+
for i in range(3):
|
|
465
|
+
for j in range(3):
|
|
466
|
+
s = (' %.15f' % cell[i, j]).rjust(16) + ' '
|
|
467
|
+
f.write(s)
|
|
468
|
+
f.write('\n')
|
|
469
|
+
f.write('%endblock LatticeVectors\n')
|
|
470
|
+
f.write('\n')
|
|
471
|
+
|
|
472
|
+
self._write_atomic_coordinates(f, atoms)
|
|
473
|
+
|
|
474
|
+
# Write magnetic moments.
|
|
475
|
+
magmoms = atoms.get_initial_magnetic_moments()
|
|
476
|
+
|
|
477
|
+
# The DM.InitSpin block must be written to initialize to
|
|
478
|
+
# no spin. SIESTA default is FM initialization, if the
|
|
479
|
+
# block is not written, but we must conform to the
|
|
480
|
+
# atoms object.
|
|
481
|
+
if magmoms is not None:
|
|
482
|
+
if len(magmoms) == 0:
|
|
483
|
+
f.write('#Empty block forces ASE initialization.\n')
|
|
484
|
+
|
|
485
|
+
f.write('%block DM.InitSpin\n')
|
|
486
|
+
if len(magmoms) != 0 and isinstance(magmoms[0], np.ndarray):
|
|
487
|
+
for n, Mcart in enumerate(magmoms):
|
|
488
|
+
M = cart2sph(Mcart)
|
|
489
|
+
if M[0] != 0:
|
|
490
|
+
f.write(' %d %.14f %.14f %.14f \n' %
|
|
491
|
+
(n + 1, M[0], M[1], M[2]))
|
|
492
|
+
elif len(magmoms) != 0 and isinstance(magmoms[0], float):
|
|
493
|
+
for n, M in enumerate(magmoms):
|
|
494
|
+
if M != 0:
|
|
495
|
+
f.write(' %d %.14f \n' % (n + 1, M))
|
|
496
|
+
f.write('%endblock DM.InitSpin\n')
|
|
497
|
+
f.write('\n')
|
|
498
|
+
|
|
499
|
+
def my_read_results(self):
|
|
500
|
+
"""Read the results.
|
|
501
|
+
"""
|
|
502
|
+
#self.read_number_of_grid_points()
|
|
503
|
+
self.read_energy()
|
|
504
|
+
self.read_forces_stress()
|
|
505
|
+
# self.read_eigenvalues()
|
|
506
|
+
self.read_kpoints()
|
|
507
|
+
self.read_dipole()
|
|
508
|
+
self.read_pseudo_density()
|
|
509
|
+
# self.read_hsx()
|
|
510
|
+
self.read_dim()
|
|
511
|
+
# if self.results['hsx'] is not None:
|
|
512
|
+
# self.read_pld(self.results['hsx'].norbitals,
|
|
513
|
+
# len(self.atoms))
|
|
514
|
+
# self.atoms.cell = self.results['pld'].cell * Bohr
|
|
515
|
+
# else:
|
|
516
|
+
# self.results['pld'] = None
|
|
517
|
+
|
|
518
|
+
# self.read_wfsx()
|
|
519
|
+
self.read_ion(self.atoms)
|
|
520
|
+
|
|
521
|
+
self.read_bands()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
|
|
2
|
+
withf_basis = {
|
|
3
|
+
#"La": "5\nn=5 0 1\n3.889 \n1.0 \nn=6 0 2\n9.113 6.906 \n1.0 1.0 \nn=5 1 1\n4.548 \n1.0 \nn=6 1 1\n9.113 \n1.0 \nn=5 2 2\n7.55 5.398 \n1.0 1.0 \n",
|
|
4
|
+
"Ce": "6\nn=5 0 1\n3.805 \n1.0 \nn=6 0 2\n9.041 6.837 \n1.0 1.0 \nn=5 1 1\n4.458 \n1.0 \nn=6 1 1\n9.041 \n1.0 \nn=5 2 2\n7.489 5.339 \n1.0 1.0 \nn=4 3 2\n4.114 2.494 \n1.0 1.0 \n",
|
|
5
|
+
"Pr": "6\nn=5 0 1\n3.737 \n1.0 \nn=6 0 2\n8.879 6.702 \n1.0 1.0 \nn=5 1 1\n4.387 \n1.0 \nn=6 1 1\n8.879 \n1.0 \nn=5 2 2\n7.46 5.307 \n1.0 1.0 \nn=4 3 2\n3.944 2.369 \n1.0 1.0 \n",
|
|
6
|
+
"Nd": "6\nn=5 0 1\n3.67 \n1.0 \nn=6 0 2\n8.808 6.641 \n1.0 1.0 \nn=5 1 1\n4.317 \n1.0 \nn=6 1 1\n8.808 \n1.0 \nn=5 2 2\n7.445 5.285 \n1.0 1.0 \nn=4 3 2\n3.805 2.271 \n1.0 1.0 \n",
|
|
7
|
+
"Pm": "6\nn=5 0 1\n3.611 \n1.0 \nn=6 0 2\n8.756 6.588 \n1.0 1.0 \nn=5 1 1\n4.257 \n1.0 \nn=6 1 1\n8.756 \n1.0 \nn=5 2 2\n7.43 5.269 \n1.0 1.0 \nn=4 3 2\n3.692 2.189 \n1.0 1.0 \n",
|
|
8
|
+
"Sm": "6\nn=5 0 1\n3.554 \n1.0 \nn=6 0 2\n8.668 6.516 \n1.0 1.0 \nn=5 1 1\n4.197 \n1.0 \nn=6 1 1\n8.668 \n1.0 \nn=5 2 2\n7.445 5.269 \n1.0 1.0 \nn=4 3 2\n3.59 2.115 \n1.0 1.0 \n",
|
|
9
|
+
"Eu": "6\nn=5 0 1\n3.497 \n1.0 \nn=6 0 2\n8.599 6.458 \n1.0 1.0 \nn=5 1 1\n4.139 \n1.0 \nn=6 1 1\n8.599 \n1.0 \nn=5 2 2\n7.46 5.275 \n1.0 1.0 \nn=4 3 2\n3.504 2.052 \n1.0 1.0 \n",
|
|
10
|
+
"Gd": "6\nn=5 0 1\n3.442 \n1.0 \nn=6 0 2\n8.514 6.374 \n1.0 1.0 \nn=5 1 1\n4.089 \n1.0 \nn=6 1 1\n8.514 \n1.0 \nn=5 2 2\n7.489 5.285 \n1.0 1.0 \nn=4 3 2\n3.435 1.997 \n1.0 1.0 \n",
|
|
11
|
+
"Tb": "6\nn=5 0 1\n3.394 \n1.0 \nn=6 0 2\n8.395 6.279 \n1.0 1.0 \nn=5 1 1\n4.04 \n1.0 \nn=6 1 1\n8.395 \n1.0 \nn=5 2 2\n7.52 5.301 \n1.0 1.0 \nn=4 3 2\n3.366 1.948 \n1.0 1.0 \n",
|
|
12
|
+
"Dy": "6\nn=5 0 1\n3.346 \n1.0 \nn=6 0 2\n8.295 6.186 \n1.0 1.0 \nn=5 1 1\n3.992 \n1.0 \nn=6 1 1\n8.295 \n1.0 \nn=5 2 2\n7.565 5.323 \n1.0 1.0 \nn=4 3 2\n3.306 1.901 \n1.0 1.0 \n",
|
|
13
|
+
"Ho": "6\nn=5 0 1\n3.293 \n1.0 \nn=6 0 2\n8.179 6.093 \n1.0 1.0 \nn=5 1 1\n3.944 \n1.0 \nn=6 1 1\n8.179 \n1.0 \nn=5 2 2\n7.61 5.349 \n1.0 1.0 \nn=4 3 2\n3.254 1.86 \n1.0 1.0 \n",
|
|
14
|
+
"Er": "6\nn=5 0 1\n3.247 \n1.0 \nn=6 0 2\n8.049 5.972 \n1.0 1.0 \nn=5 1 1\n3.897 \n1.0 \nn=6 1 1\n8.049 \n1.0 \nn=5 2 2\n7.656 5.387 \n1.0 1.0 \nn=4 3 2\n3.208 1.821 \n1.0 1.0 \n",
|
|
15
|
+
"Tm": "6\nn=5 0 1\n3.202 \n1.0 \nn=6 0 2\n7.921 5.872 \n1.0 1.0 \nn=5 1 1\n3.858 \n1.0 \nn=6 1 1\n7.921 \n1.0 \nn=5 2 2\n7.718 5.419 \n1.0 1.0 \nn=4 3 2\n3.163 1.785 \n1.0 1.0 \n",
|
|
16
|
+
"Yb": "6\nn=5 0 1\n3.163 \n1.0 \nn=6 0 2\n7.796 5.761 \n1.0 1.0 \nn=5 1 1\n3.812 \n1.0 \nn=6 1 1\n7.796 \n1.0 \nn=5 2 2\n7.78 5.468 \n1.0 1.0 \nn=4 3 2\n3.119 1.753 \n1.0 1.0 \n"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fincore_basis ={
|
|
20
|
+
#"La": "4\nn=5 0 1\n3.889 \n1.0 \nn=6 0 2\n9.113 6.906 \n1.0 1.0 \nn=5 1 1\n4.548 \n1.0 \nn=6 1 1\n9.113 \n1.0 \nn=5 2 2\n7.55 5.398 \n1.0 1.0 \n",
|
|
21
|
+
"Ce": "5\nn=5 0 1\n3.805 \n1.0 \nn=6 0 2\n8.968 6.776 \n1.0 1.0 \nn=5 1 1\n4.458 \n1.0 \nn=6 1 1\n8.968 \n1.0 \nn=5 2 2\n7.489 5.339 \n1.0 1.0 \n",
|
|
22
|
+
"Pr": "5\nn=5 0 1\n3.737 \n1.0 \nn=6 0 2\n8.791 6.621 \n1.0 1.0 \nn=5 1 1\n4.387 \n1.0 \nn=6 1 1\n8.791 \n1.0 \nn=5 2 2\n7.46 5.307 \n1.0 1.0 \n",
|
|
23
|
+
"Nd": "5\nn=5 0 1\n3.67 \n1.0 \nn=6 0 2\n8.634 6.49 \n1.0 1.0 \nn=5 1 1\n4.317 \n1.0 \nn=6 1 1\n8.634 \n1.0 \nn=5 2 2\n7.445 5.285 \n1.0 1.0 \n",
|
|
24
|
+
"Pm": "5\nn=5 0 1\n3.611 \n1.0 \nn=6 0 2\n8.446 6.33 \n1.0 1.0 \nn=5 1 1\n4.257 \n1.0 \nn=6 1 1\n8.446 \n1.0 \nn=5 2 2\n7.43 5.269 \n1.0 1.0 \n",
|
|
25
|
+
"Sm": "5\nn=5 0 1\n3.554 \n1.0 \nn=6 0 2\n8.328 6.223 \n1.0 1.0 \nn=5 1 1\n4.197 \n1.0 \nn=6 1 1\n8.328 \n1.0 \nn=5 2 2\n7.445 5.269 \n1.0 1.0 \n",
|
|
26
|
+
"Eu": "5\nn=5 0 1\n3.497 \n1.0 \nn=6 0 2\n8.278 6.186 \n1.0 1.0 \nn=5 1 1\n4.139 \n1.0 \nn=6 1 1\n8.278 \n1.0 \nn=5 2 2\n7.46 5.275 \n1.0 1.0 \n",
|
|
27
|
+
"Gd": "5\nn=5 0 1\n3.442 \n1.0 \nn=6 0 2\n8.278 6.179 \n1.0 1.0 \nn=5 1 1\n4.089 \n1.0 \nn=6 1 1\n8.278 \n1.0 \nn=5 2 2\n7.489 5.285 \n1.0 1.0 \n",
|
|
28
|
+
"Tb": "5\nn=5 0 1\n3.394 \n1.0 \nn=6 0 2\n8.147 6.063 \n1.0 1.0 \nn=5 1 1\n4.04 \n1.0 \nn=6 1 1\n8.147 \n1.0 \nn=5 2 2\n7.52 5.301 \n1.0 1.0 \n",
|
|
29
|
+
"Dy": "5\nn=5 0 1\n3.346 \n1.0 \nn=6 0 2\n7.969 5.919 \n1.0 1.0 \nn=5 1 1\n3.992 \n1.0 \nn=6 1 1\n7.969 \n1.0 \nn=5 2 2\n7.565 5.323 \n1.0 1.0 \n",
|
|
30
|
+
"Ho": "5\nn=5 0 1\n3.293 \n1.0 \nn=6 0 2\n7.827 5.79 \n1.0 1.0 \nn=5 1 1\n3.944 \n1.0 \nn=6 1 1\n7.827 \n1.0 \nn=5 2 2\n7.61 5.349 \n1.0 1.0 \n",
|
|
31
|
+
"Er": "5\nn=5 0 1\n3.247 \n1.0 \nn=6 0 2\n7.626 5.624 \n1.0 1.0 \nn=5 1 1\n3.897 \n1.0 \nn=6 1 1\n7.626 \n1.0 \nn=5 2 2\n7.656 5.387 \n1.0 1.0 \n",
|
|
32
|
+
"Tm": "5\nn=5 0 1\n3.202 \n1.0 \nn=6 0 2\n7.474 5.49 \n1.0 1.0 \nn=5 1 1\n3.858 \n1.0 \nn=6 1 1\n7.474 \n1.0 \nn=5 2 2\n7.718 5.419 \n1.0 1.0 \n",
|
|
33
|
+
"Yb": "5\nn=5 0 1\n3.163 \n1.0 \nn=6 0 2\n7.312 5.36 \n1.0 1.0 \nn=5 1 1\n3.812 \n1.0 \nn=6 1 1\n7.312 \n1.0 \nn=5 2 2\n7.78 5.468 \n1.0 1.0 \n"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def get_basis(element, fincore=False):
|
|
37
|
+
if not fincore:
|
|
38
|
+
return withf_basis[element]
|
|
39
|
+
elif basis == "fincore":
|
|
40
|
+
return fincore_basis[element]
|
|
41
|
+
else:
|
|
42
|
+
raise ValueError("Invalid basis set: {}".format(basis))
|
|
43
|
+
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
print(get_basis("La"))
|
|
46
|
+
print(get_basis("La", fincore=True))
|
|
47
|
+
print(get_basis("Ce"))
|
|
48
|
+
print(get_basis("Ce", fincore=True))
|
|
49
|
+
|
|
50
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: TB2Jflows
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: TB2Jflows: Workflows for automatically calculation of exchange parameters using TB2J
|
|
5
|
+
Author-email: Xu He <mailhexu@gmail.com>
|
|
6
|
+
License: BSD-2-clause
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
15
|
+
Requires-Python: >=3.6
|
|
16
|
+
Requires-Dist: ase
|
|
17
|
+
Requires-Dist: sisl
|
|
18
|
+
Requires-Dist: tb2j
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# TB2Jflows
|
|
22
|
+
Workflows for automatically calculation of exchange parameters from DFT
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
First download the package from the github page. Run the following command in the TB2Jflows directory
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
pip install . --user
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
will install TB2Jflows and the dependencies.
|
|
33
|
+
|
|
34
|
+
You need the following things to
|
|
35
|
+
|
|
36
|
+
- Siesta built with psml and netcdf.
|
|
37
|
+
- Pseudopotentials from PseudoDojo Dataset.
|
|
38
|
+
- Configure the command to run siesta and the path to the pseudopotentials, e.g.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
export ASE_IESTA_COMMAND="mpirun siesta < PREFIX.fdf > PREFIX.out 2> PREFIX.err"
|
|
42
|
+
export DOJO_PATH='$HOME/.local/pp/dojo'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
Below is an example of calculating the exchange parameters of SrMnO3:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from ase.io import read
|
|
51
|
+
from TB2Jflows import SiestaFlow
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def calculate_siesta_TB2J_SrMnO3():
|
|
55
|
+
atoms = read('SrMnO3.STRUCT_OUT')
|
|
56
|
+
atoms.set_initial_magnetic_moments([0, 3, 0, 0, 0])
|
|
57
|
+
flow = SiestaFlow(atoms,
|
|
58
|
+
spin='spin-orbit',
|
|
59
|
+
restart=True,
|
|
60
|
+
root_path='SrMnO3')
|
|
61
|
+
flow.write_metadata()
|
|
62
|
+
atoms = flow.relax(atoms)
|
|
63
|
+
flow.scf_calculation_with_rotations(atoms)
|
|
64
|
+
flow.run_TB2J(magnetic_elements='Mn',
|
|
65
|
+
nz=50,
|
|
66
|
+
kmesh=[7, 7, 7],
|
|
67
|
+
Rcut=18,
|
|
68
|
+
np=10,
|
|
69
|
+
use_cache=True)
|
|
70
|
+
flow.run_TB2J_merge()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if __name__ == '__main__':
|
|
74
|
+
calculate_siesta_TB2J_SrMnO3()
|
|
75
|
+
~
|
|
76
|
+
```
|
|
77
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
TB2Jflows/__init__.py,sha256=0aRVj9v-u64LxJl7Cyxcr4YUjpeMkBGPuv-nJbxbHOg,100
|
|
2
|
+
TB2Jflows/ase_siesta.py,sha256=1b6j0dFNnXCeLnCTWoLAJ158JQul8UcORIttGOhNydw,14366
|
|
3
|
+
TB2Jflows/auto_siesta_TB2J.py,sha256=c5dviznEbXyO3BJbh-LNBlC9efT7YbdC7ydWxyCJZ5E,3113
|
|
4
|
+
TB2Jflows/find_pp.py,sha256=iTqxLPuR88Jsuh4lc7hPEzFczhoOB0x6K5MWqYTEeiQ,2134
|
|
5
|
+
TB2Jflows/mysiesta.py,sha256=DV9dnYibrpPzegKy_MvoMOOrmoom2NPKblhVNBUZkeg,18943
|
|
6
|
+
TB2Jflows/run_abacus.py,sha256=96tZ2n02FFLl8IZf4W_4TvkCcsd6oS1FVEIqhZpY76o,2692
|
|
7
|
+
TB2Jflows/siesta_basis.py,sha256=UIO0VF_558jIK6kGctqEwHyyV_t7KEWGOtv4Obw4fyg,5408
|
|
8
|
+
tb2jflows-0.1.0.dist-info/METADATA,sha256=mnUu8VXO3Dndka3rbgqWJ0hiWxOXmWyF9AjauzpVQZk,2170
|
|
9
|
+
tb2jflows-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
+
tb2jflows-0.1.0.dist-info/licenses/LICENSE,sha256=KNu68sa-XR_2jZJKhDcSnxoNve8jtHgkw_w9PjP1YOk,1315
|
|
11
|
+
tb2jflows-0.1.0.dist-info/RECORD,,
|
tb2jflows-0.1.dist-info/METADATA
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: TB2Jflows
|
|
3
|
-
Version: 0.1
|
|
4
|
-
Summary: TB2Jflows: Workflows for automatically calculation of exchange parameters using TB2J
|
|
5
|
-
Author: Xu He
|
|
6
|
-
Author-email: mailhexu@gmail.com
|
|
7
|
-
License: BSD-2-clause
|
|
8
|
-
Classifier: Development Status :: 3 - Alpha
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Classifier: Intended Audience :: Science/Research
|
|
12
|
-
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
13
|
-
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
15
|
-
Requires-Python: >=3.6
|
|
16
|
-
License-File: LICENSE
|
|
17
|
-
Requires-Dist: TB2J
|
|
18
|
-
Requires-Dist: ase
|
|
19
|
-
Requires-Dist: sisl
|
|
20
|
-
Requires-Dist: pyDFTutils
|
|
21
|
-
Dynamic: author
|
|
22
|
-
Dynamic: author-email
|
|
23
|
-
Dynamic: classifier
|
|
24
|
-
Dynamic: description
|
|
25
|
-
Dynamic: license
|
|
26
|
-
Dynamic: license-file
|
|
27
|
-
Dynamic: requires-dist
|
|
28
|
-
Dynamic: requires-python
|
|
29
|
-
Dynamic: summary
|
|
30
|
-
|
|
31
|
-
TB2Jflows: Workflows for automatically calculation of exchange parameters using TB2J
|
tb2jflows-0.1.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
TB2Jflows/__init__.py,sha256=0aRVj9v-u64LxJl7Cyxcr4YUjpeMkBGPuv-nJbxbHOg,100
|
|
2
|
-
TB2Jflows/ase_siesta.py,sha256=zvKfKPidFvndfMQH0PHDprnFpwirk4yKdqwWDBe-_EI,14493
|
|
3
|
-
TB2Jflows/auto_siesta_TB2J.py,sha256=hrnJos-Rkx1bngFOSr4wATUr0NVyBXmSOsrvscfMLmg,3180
|
|
4
|
-
TB2Jflows/run_abacus.py,sha256=96tZ2n02FFLl8IZf4W_4TvkCcsd6oS1FVEIqhZpY76o,2692
|
|
5
|
-
tb2jflows-0.1.dist-info/licenses/LICENSE,sha256=KNu68sa-XR_2jZJKhDcSnxoNve8jtHgkw_w9PjP1YOk,1315
|
|
6
|
-
tb2jflows-0.1.dist-info/METADATA,sha256=BFLB9Ngpq9iLlEAxF245S9snQgmTFTp3FBypy5azHkY,967
|
|
7
|
-
tb2jflows-0.1.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
8
|
-
tb2jflows-0.1.dist-info/top_level.txt,sha256=iYRLHB7ZeHb59fEZLnbqJDymBKWPqfVgmvqd9S51Txw,10
|
|
9
|
-
tb2jflows-0.1.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
TB2Jflows
|
|
File without changes
|