root / ase / io / aims.py @ 14
Historique | Voir | Annoter | Télécharger (10,59 ko)
| 1 |
|
|---|---|
| 2 |
def read_aims(filename): |
| 3 |
"""Import FHI-aims geometry type files.
|
| 4 |
|
| 5 |
Reads unitcell, atom positions and constraints from
|
| 6 |
a geometry.in file.
|
| 7 |
"""
|
| 8 |
|
| 9 |
from ase import Atoms |
| 10 |
from ase.constraints import FixAtoms, FixCartesian |
| 11 |
import numpy as np |
| 12 |
|
| 13 |
atoms = Atoms() |
| 14 |
fd = open(filename, 'r') |
| 15 |
lines = fd.readlines() |
| 16 |
fd.close() |
| 17 |
positions = [] |
| 18 |
cell = [] |
| 19 |
symbols = [] |
| 20 |
fix = [] |
| 21 |
fix_cart = [] |
| 22 |
xyz = np.array([0, 0, 0]) |
| 23 |
i = -1
|
| 24 |
n_periodic = -1
|
| 25 |
periodic = np.array([False, False, False]) |
| 26 |
for n, line in enumerate(lines): |
| 27 |
inp = line.split() |
| 28 |
if inp == []:
|
| 29 |
continue
|
| 30 |
if inp[0] == 'atom': |
| 31 |
if xyz.all():
|
| 32 |
fix.append(i) |
| 33 |
elif xyz.any():
|
| 34 |
print 1 |
| 35 |
fix_cart.append(FixCartesian(i, xyz)) |
| 36 |
floatvect = float(inp[1]), float(inp[2]), float(inp[3]) |
| 37 |
positions.append(floatvect) |
| 38 |
symbols.append(inp[-1])
|
| 39 |
i += 1
|
| 40 |
xyz = np.array([0, 0, 0]) |
| 41 |
elif inp[0] == 'lattice_vector': |
| 42 |
floatvect = float(inp[1]), float(inp[2]), float(inp[3]) |
| 43 |
cell.append(floatvect) |
| 44 |
n_periodic = n_periodic + 1
|
| 45 |
periodic[n_periodic] = True
|
| 46 |
if inp[0] == 'constrain_relaxation': |
| 47 |
if inp[1] == '.true.': |
| 48 |
fix.append(i) |
| 49 |
elif inp[1] == 'x': |
| 50 |
xyz[0] = 1 |
| 51 |
elif inp[1] == 'y': |
| 52 |
xyz[1] = 1 |
| 53 |
elif inp[1] == 'z': |
| 54 |
xyz[2] = 1 |
| 55 |
if xyz.all():
|
| 56 |
fix.append(i) |
| 57 |
elif xyz.any():
|
| 58 |
fix_cart.append(FixCartesian(i, xyz)) |
| 59 |
atoms = Atoms(symbols, positions) |
| 60 |
if periodic.all():
|
| 61 |
atoms.set_cell(cell) |
| 62 |
atoms.set_pbc(periodic) |
| 63 |
if len(fix): |
| 64 |
atoms.set_constraint([FixAtoms(indices=fix)]+fix_cart) |
| 65 |
else:
|
| 66 |
atoms.set_constraint(fix_cart) |
| 67 |
return atoms
|
| 68 |
|
| 69 |
def write_aims(filename, atoms): |
| 70 |
"""Method to write FHI-aims geometry files.
|
| 71 |
|
| 72 |
Writes the atoms positions and constraints (only FixAtoms is
|
| 73 |
supported at the moment).
|
| 74 |
"""
|
| 75 |
|
| 76 |
from ase.constraints import FixAtoms, FixCartesian |
| 77 |
import numpy as np |
| 78 |
|
| 79 |
if isinstance(atoms, (list, tuple)): |
| 80 |
if len(atoms) > 1: |
| 81 |
raise RuntimeError("Don't know how to save more than "+ |
| 82 |
"one image to FHI-aims input")
|
| 83 |
else:
|
| 84 |
atoms = atoms[0]
|
| 85 |
|
| 86 |
fd = open(filename, 'w') |
| 87 |
fd.write('#=======================================================\n')
|
| 88 |
fd.write('#FHI-aims file: '+filename+'\n') |
| 89 |
fd.write('#Created using the Atomic Simulation Environment (ASE)\n')
|
| 90 |
fd.write('#=======================================================\n')
|
| 91 |
i = 0
|
| 92 |
if atoms.get_pbc().any():
|
| 93 |
for n, vector in enumerate(atoms.get_cell()): |
| 94 |
fd.write('lattice_vector ')
|
| 95 |
for i in range(3): |
| 96 |
fd.write('%16.16f ' % vector[i])
|
| 97 |
fd.write('\n')
|
| 98 |
fix_cart = np.zeros([len(atoms),3]) |
| 99 |
|
| 100 |
if atoms.constraints:
|
| 101 |
for constr in atoms.constraints: |
| 102 |
if isinstance(constr, FixAtoms): |
| 103 |
fix_cart[constr.index] = [1,1,1] |
| 104 |
elif isinstance(constr, FixCartesian): |
| 105 |
fix_cart[constr.a] = -constr.mask+1
|
| 106 |
|
| 107 |
for i, atom in enumerate(atoms): |
| 108 |
fd.write('atom ')
|
| 109 |
for pos in atom.get_position(): |
| 110 |
fd.write('%16.16f ' % pos)
|
| 111 |
fd.write(atom.symbol) |
| 112 |
fd.write('\n')
|
| 113 |
# (1) all coords are constrained:
|
| 114 |
if fix_cart[i].all():
|
| 115 |
fd.write('constrain_relaxation .true.\n')
|
| 116 |
# (2) some coords are constrained:
|
| 117 |
elif fix_cart[i].any():
|
| 118 |
xyz = fix_cart[i] |
| 119 |
for n in range(3): |
| 120 |
if xyz[n]:
|
| 121 |
fd.write('constrain_relaxation %s\n' % 'xyz'[n]) |
| 122 |
if atom.charge:
|
| 123 |
fd.write('initial_charge %16.6f\n' % atom.charge)
|
| 124 |
if atom.magmom:
|
| 125 |
fd.write('initial_moment %16.6f\n' % atom.magmom)
|
| 126 |
# except KeyError:
|
| 127 |
# continue
|
| 128 |
|
| 129 |
def read_energy(filename): |
| 130 |
for line in open(filename, 'r'): |
| 131 |
if line.startswith(' | Total energy corrected'): |
| 132 |
E = float(line.split()[-2]) |
| 133 |
return E
|
| 134 |
|
| 135 |
def read_aims_output(filename, index = -1): |
| 136 |
""" Import FHI-aims output files with all data available, i.e. relaxations,
|
| 137 |
MD information, force information etc etc etc. """
|
| 138 |
from ase import Atoms, Atom |
| 139 |
from ase.calculators.singlepoint import SinglePointCalculator |
| 140 |
from ase.units import Ang, fs |
| 141 |
molecular_dynamics = False
|
| 142 |
fd = open(filename, 'r') |
| 143 |
cell = [] |
| 144 |
images = [] |
| 145 |
n_periodic = -1
|
| 146 |
f = None
|
| 147 |
pbc = False
|
| 148 |
found_aims_calculator = False
|
| 149 |
v_unit = Ang/(1000.0*fs)
|
| 150 |
while True: |
| 151 |
line = fd.readline() |
| 152 |
if not line: |
| 153 |
break
|
| 154 |
if "List of parameters used to initialize the calculator:" in line: |
| 155 |
fd.readline() |
| 156 |
calc = read_aims_calculator(fd) |
| 157 |
calc.out = filename |
| 158 |
found_aims_calculator = True
|
| 159 |
if "Number of atoms" in line: |
| 160 |
inp = line.split() |
| 161 |
n_atoms = int(inp[5]) |
| 162 |
if "| Unit cell:" in line: |
| 163 |
if not pbc: |
| 164 |
pbc = True
|
| 165 |
for i in range(3): |
| 166 |
inp = fd.readline().split() |
| 167 |
cell.append([inp[1],inp[2],inp[3]]) |
| 168 |
if "Atomic structure:" in line and not molecular_dynamics: |
| 169 |
fd.readline() |
| 170 |
atoms = Atoms() |
| 171 |
for i in range(n_atoms): |
| 172 |
inp = fd.readline().split() |
| 173 |
atoms.append(Atom(inp[3],(inp[4],inp[5],inp[6]))) |
| 174 |
if "Complete information for previous time-step:" in line: |
| 175 |
molecular_dynamics = True
|
| 176 |
if "Updated atomic structure:" in line and not molecular_dynamics: |
| 177 |
fd.readline() |
| 178 |
atoms = Atoms() |
| 179 |
velocities = [] |
| 180 |
for i in range(n_atoms): |
| 181 |
inp = fd.readline().split() |
| 182 |
atoms.append(Atom(inp[4],(inp[1],inp[2],inp[3]))) |
| 183 |
if molecular_dynamics:
|
| 184 |
inp = fd.readline().split() |
| 185 |
if "Atomic structure (and velocities)" in line: |
| 186 |
fd.readline() |
| 187 |
atoms = Atoms() |
| 188 |
velocities = [] |
| 189 |
for i in range(n_atoms): |
| 190 |
inp = fd.readline().split() |
| 191 |
atoms.append(Atom(inp[4],(inp[1],inp[2],inp[3]))) |
| 192 |
inp = fd.readline().split() |
| 193 |
velocities += [[float(inp[1])*v_unit,float(inp[2])*v_unit,float(inp[3])*v_unit]] |
| 194 |
atoms.set_velocities(velocities) |
| 195 |
images.append(atoms) |
| 196 |
if "Total atomic forces" in line: |
| 197 |
f = [] |
| 198 |
for i in range(n_atoms): |
| 199 |
inp = fd.readline().split() |
| 200 |
f.append([float(inp[2]),float(inp[3]),float(inp[4])]) |
| 201 |
if not found_aims_calculator: |
| 202 |
e = images[-1].get_potential_energy()
|
| 203 |
images[-1].set_calculator(SinglePointCalculator(e,f,None,None,atoms)) |
| 204 |
e = None
|
| 205 |
f = None
|
| 206 |
if "Total energy corrected" in line: |
| 207 |
e = float(line.split()[5]) |
| 208 |
if pbc:
|
| 209 |
atoms.set_cell(cell) |
| 210 |
atoms.pbc = True
|
| 211 |
if not found_aims_calculator: |
| 212 |
atoms.set_calculator(SinglePointCalculator(e,None,None,None,atoms)) |
| 213 |
if not molecular_dynamics: |
| 214 |
images.append(atoms) |
| 215 |
e = None
|
| 216 |
if found_aims_calculator:
|
| 217 |
calc.set_results(images[-1])
|
| 218 |
images[-1].set_calculator(calc)
|
| 219 |
fd.close() |
| 220 |
if molecular_dynamics:
|
| 221 |
images = images[1:]
|
| 222 |
|
| 223 |
# return requested images, code borrowed from ase/io/trajectory.py
|
| 224 |
if isinstance(index, int): |
| 225 |
return images[index]
|
| 226 |
else:
|
| 227 |
step = index.step or 1 |
| 228 |
if step > 0: |
| 229 |
start = index.start or 0 |
| 230 |
if start < 0: |
| 231 |
start += len(images)
|
| 232 |
stop = index.stop or len(images) |
| 233 |
if stop < 0: |
| 234 |
stop += len(images)
|
| 235 |
else:
|
| 236 |
if index.start is None: |
| 237 |
start = len(images) - 1 |
| 238 |
else:
|
| 239 |
start = index.start |
| 240 |
if start < 0: |
| 241 |
start += len(images)
|
| 242 |
if index.stop is None: |
| 243 |
stop = -1
|
| 244 |
else:
|
| 245 |
stop = index.stop |
| 246 |
if stop < 0: |
| 247 |
stop += len(images)
|
| 248 |
return [images[i] for i in range(start, stop, step)] |
| 249 |
|
| 250 |
def read_aims_calculator(file): |
| 251 |
""" found instructions for building an FHI-aims calculator in the output file,
|
| 252 |
read its specifications and return it. """
|
| 253 |
from ase.calculators.aims import Aims |
| 254 |
calc = Aims() |
| 255 |
while True: |
| 256 |
line = file.readline()
|
| 257 |
if "=======================================================" in line: |
| 258 |
break
|
| 259 |
else:
|
| 260 |
args = line.split() |
| 261 |
key = args[0]
|
| 262 |
if key == '#': |
| 263 |
comment = True
|
| 264 |
elif calc.float_params.has_key(key):
|
| 265 |
calc.float_params[key] = float(args[1]) |
| 266 |
elif calc.exp_params.has_key(key):
|
| 267 |
calc.exp_params[key] = float(args[1]) |
| 268 |
elif calc.string_params.has_key(key):
|
| 269 |
calc.string_params[key] = args[1]
|
| 270 |
if len(args) > 2: |
| 271 |
for s in args[2:]: |
| 272 |
calc.string_params[key] += " "+s
|
| 273 |
elif calc.int_params.has_key(key):
|
| 274 |
calc.int_params[key] = int(args[1]) |
| 275 |
elif calc.bool_params.has_key(key):
|
| 276 |
try:
|
| 277 |
calc.bool_params[key] = bool(args[1]) |
| 278 |
except:
|
| 279 |
if key == 'vdw_correction_hirshfeld': |
| 280 |
calc.bool_params[key] = True
|
| 281 |
elif calc.list_params.has_key(key):
|
| 282 |
if key == 'output': |
| 283 |
# build output string from args:
|
| 284 |
out_option = ''
|
| 285 |
for arg in args[1:]: |
| 286 |
out_option +=str(arg)+' ' |
| 287 |
if calc.list_params['output'] is not None: |
| 288 |
calc.list_params['output'] += [out_option]
|
| 289 |
else:
|
| 290 |
calc.list_params['output'] = [out_option]
|
| 291 |
else:
|
| 292 |
calc.list_params[key] = list(args[1:]) |
| 293 |
elif '#' in key: |
| 294 |
key = key[1:]
|
| 295 |
if calc.input_parameters.has_key(key):
|
| 296 |
calc.input_parameters[key] = args[1]
|
| 297 |
if len(args) > 2: |
| 298 |
for s in args[2:]: |
| 299 |
calc.input_parameters[key] += " "+s
|
| 300 |
else:
|
| 301 |
raise TypeError('FHI-aims keyword not defined in ASE: ' + key + '. Please check.') |
| 302 |
return calc
|