root / ase / io / xsf.py @ 14
Historique | Voir | Annoter | Télécharger (4,27 ko)
| 1 |
import numpy as np |
|---|---|
| 2 |
|
| 3 |
from ase.atoms import Atoms |
| 4 |
from ase.units import Hartree |
| 5 |
from ase.parallel import paropen |
| 6 |
from ase.calculators.singlepoint import SinglePointCalculator |
| 7 |
|
| 8 |
|
| 9 |
def write_xsf(fileobj, images, data=None): |
| 10 |
if isinstance(fileobj, str): |
| 11 |
fileobj = paropen(fileobj, 'w')
|
| 12 |
|
| 13 |
if not isinstance(images, (list, tuple)): |
| 14 |
images = [images] |
| 15 |
|
| 16 |
fileobj.write('ANIMSTEPS %d\n' % len(images)) |
| 17 |
|
| 18 |
numbers = images[0].get_atomic_numbers()
|
| 19 |
|
| 20 |
pbc = images[0].get_pbc()
|
| 21 |
if pbc[2]: |
| 22 |
fileobj.write('CRYSTAL\n')
|
| 23 |
elif pbc[1]: |
| 24 |
fileobj.write('SLAB\n')
|
| 25 |
elif pbc[0]: |
| 26 |
fileobj.write('POLYMER\n')
|
| 27 |
else:
|
| 28 |
fileobj.write('MOLECULE\n')
|
| 29 |
|
| 30 |
for n, atoms in enumerate(images): |
| 31 |
if pbc.any():
|
| 32 |
fileobj.write('PRIMVEC %d\n' % (n + 1)) |
| 33 |
cell = atoms.get_cell() |
| 34 |
for i in range(3): |
| 35 |
fileobj.write(' %.14f %.14f %.14f\n' % tuple(cell[i])) |
| 36 |
|
| 37 |
fileobj.write('PRIMCOORD %d\n' % (n + 1)) |
| 38 |
|
| 39 |
# Get the forces if it's not too expensive:
|
| 40 |
calc = atoms.get_calculator() |
| 41 |
if (calc is not None and |
| 42 |
(hasattr(calc, 'calculation_required') and |
| 43 |
not calc.calculation_required(atoms,
|
| 44 |
['energy', 'forces', 'stress']))): |
| 45 |
forces = atoms.get_forces() |
| 46 |
else:
|
| 47 |
forces = None
|
| 48 |
|
| 49 |
pos = atoms.get_positions() |
| 50 |
|
| 51 |
fileobj.write(' %d 1\n' % len(pos)) |
| 52 |
for a in range(len(pos)): |
| 53 |
fileobj.write(' %2d' % numbers[a])
|
| 54 |
fileobj.write(' %20.14f %20.14f %20.14f' % tuple(pos[a])) |
| 55 |
if forces is None: |
| 56 |
fileobj.write('\n')
|
| 57 |
else:
|
| 58 |
fileobj.write(' %20.14f %20.14f %20.14f\n' % tuple(forces[a])) |
| 59 |
|
| 60 |
if data is None: |
| 61 |
return
|
| 62 |
|
| 63 |
fileobj.write('BEGIN_BLOCK_DATAGRID_3D\n')
|
| 64 |
fileobj.write(' data\n')
|
| 65 |
fileobj.write(' BEGIN_DATAGRID_3Dgrid#1\n')
|
| 66 |
|
| 67 |
data = np.asarray(data) |
| 68 |
if data.dtype == complex: |
| 69 |
data = np.abs(data) |
| 70 |
|
| 71 |
shape = data.shape |
| 72 |
fileobj.write(' %d %d %d\n' % shape)
|
| 73 |
|
| 74 |
cell = atoms.get_cell() |
| 75 |
origin = np.zeros(3)
|
| 76 |
for i in range(3): |
| 77 |
if not pbc[i]: |
| 78 |
origin += cell[i] / shape[i] |
| 79 |
fileobj.write(' %f %f %f\n' % tuple(origin)) |
| 80 |
|
| 81 |
for i in range(3): |
| 82 |
fileobj.write(' %f %f %f\n' %
|
| 83 |
tuple(cell[i] * (shape[i] + 1) / shape[i])) |
| 84 |
|
| 85 |
for x in range(shape[2]): |
| 86 |
for y in range(shape[1]): |
| 87 |
fileobj.write(' ')
|
| 88 |
fileobj.write(' '.join(['%f' % d for d in data[x, y]])) |
| 89 |
fileobj.write('\n')
|
| 90 |
fileobj.write('\n')
|
| 91 |
|
| 92 |
fileobj.write(' END_DATAGRID_3D\n')
|
| 93 |
fileobj.write('END_BLOCK_DATAGRID_3D\n')
|
| 94 |
|
| 95 |
|
| 96 |
def read_xsf(fileobj, index=-1): |
| 97 |
if isinstance(fileobj, str): |
| 98 |
fileobj = open(fileobj)
|
| 99 |
|
| 100 |
readline = fileobj.readline |
| 101 |
line = readline() |
| 102 |
|
| 103 |
if line.startswith('ANIMSTEPS'): |
| 104 |
nimages = int(line.split()[1]) |
| 105 |
line = readline() |
| 106 |
else:
|
| 107 |
nimages = 1
|
| 108 |
|
| 109 |
if line.startswith('CRYSTAL'): |
| 110 |
pbc = True
|
| 111 |
elif line.startswith('SLAB'): |
| 112 |
pbc = (True, True, Flase) |
| 113 |
elif line.startswith('POLYMER'): |
| 114 |
pbc = (True, False, Flase) |
| 115 |
else:
|
| 116 |
pbc = False
|
| 117 |
|
| 118 |
images = [] |
| 119 |
for n in range(nimages): |
| 120 |
cell = None
|
| 121 |
if pbc:
|
| 122 |
line = readline() |
| 123 |
assert line.startswith('PRIMVEC') |
| 124 |
cell = [] |
| 125 |
for i in range(3): |
| 126 |
cell.append([float(x) for x in readline().split()]) |
| 127 |
|
| 128 |
line = readline() |
| 129 |
assert line.startswith('PRIMCOORD') |
| 130 |
|
| 131 |
natoms = int(readline().split()[0]) |
| 132 |
numbers = [] |
| 133 |
positions = [] |
| 134 |
for a in range(natoms): |
| 135 |
line = readline().split() |
| 136 |
numbers.append(int(line[0])) |
| 137 |
positions.append([float(x) for x in line[1:]]) |
| 138 |
|
| 139 |
positions = np.array(positions) |
| 140 |
if len(positions[0]) == 3: |
| 141 |
forces = None
|
| 142 |
else:
|
| 143 |
positions = positions[:, :3]
|
| 144 |
forces = positions[:, 3:] * Hartree
|
| 145 |
|
| 146 |
image = Atoms(numbers, positions, cell=cell, pbc=pbc) |
| 147 |
|
| 148 |
if forces is not None: |
| 149 |
image.set_calculator(SinglePointCalculator(None, forces, None, |
| 150 |
None, image))
|
| 151 |
images.append(image) |
| 152 |
|
| 153 |
return images[index]
|