Coverage for /builds/ase/ase/ase/io/v_sim.py : 86.67%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2This module contains functionality for reading and writing an ASE
3Atoms object in V_Sim 3.5+ ascii format.
5"""
7import numpy as np
8from ase.utils import reader, writer
11@reader
12def read_v_sim(fd):
13 """Import V_Sim input file.
15 Reads cell, atom positions, etc. from v_sim ascii file.
16 V_sim format is specified here:
17 https://l_sim.gitlab.io/v_sim/sample.html#sample_ascii
18 """
20 from ase import Atoms, units
21 from ase.geometry import cellpar_to_cell
22 import re
24 # Read comment:
25 fd.readline()
27 line = fd.readline() + ' ' + fd.readline()
28 box = line.split()
29 for i in range(len(box)):
30 box[i] = float(box[i])
32 keywords = []
33 positions = []
34 symbols = []
35 unit = 1.0
37 re_comment = re.compile(r'^\s*[#!]')
38 re_node = re.compile(r'^\s*\S+\s+\S+\s+\S+\s+\S+')
40 while True:
41 line = fd.readline()
43 if line == '':
44 break # EOF
46 p = re_comment.match(line)
47 if p is not None:
48 # remove comment character at the beginning of line
49 line = line[p.end():].replace(',', ' ').lower()
50 if line[:8] == "keyword:":
51 keywords.extend(line[8:].split())
53 elif re_node.match(line):
54 unit = 1.0
55 if not ("reduced" in keywords):
56 if (("bohr" in keywords) or ("bohrd0" in keywords) or
57 ("atomic" in keywords) or ("atomicd0" in keywords)):
58 unit = units.Bohr
60 fields = line.split()
61 positions.append([unit * float(fields[0]),
62 unit * float(fields[1]),
63 unit * float(fields[2])])
64 symbols.append(fields[3])
66 # create atoms object based on the information
67 if "angdeg" in keywords:
68 cell = cellpar_to_cell(box)
69 else:
70 unit = 1.0
71 if (("bohr" in keywords) or ("bohrd0" in keywords) or
72 ("atomic" in keywords) or ("atomicd0" in keywords)):
73 unit = units.Bohr
74 cell = np.zeros((3, 3))
75 cell.flat[[0, 3, 4, 6, 7, 8]] = box[:6]
76 cell *= unit
78 if "reduced" in keywords:
79 atoms = Atoms(cell=cell, scaled_positions=positions)
80 else:
81 atoms = Atoms(cell=cell, positions=positions)
83 if "periodic" in keywords:
84 atoms.pbc = [True, True, True]
85 elif "freebc" in keywords:
86 atoms.pbc = [False, False, False]
87 elif "surface" in keywords:
88 atoms.pbc = [True, False, True]
89 else: # default is periodic boundary conditions
90 atoms.pbc = [True, True, True]
92 atoms.set_chemical_symbols(symbols)
93 return atoms
96@writer
97def write_v_sim(fd, atoms):
98 """Write V_Sim input file.
100 Writes the atom positions and unit cell.
101 V_sim format is specified here:
102 https://l_sim.gitlab.io/v_sim/sample.html#sample_ascii
103 """
104 from ase.geometry import cellpar_to_cell, cell_to_cellpar
106 # Convert the lattice vectors to triangular matrix by converting
107 # to and from a set of lengths and angles
108 cell = cellpar_to_cell(cell_to_cellpar(atoms.cell))
109 dxx = cell[0, 0]
110 dyx, dyy = cell[1, 0:2]
111 dzx, dzy, dzz = cell[2, 0:3]
113 fd.write('===== v_sim input file created using the'
114 ' Atomic Simulation Environment (ASE) ====\n')
115 fd.write('{0} {1} {2}\n'.format(dxx, dyx, dyy))
116 fd.write('{0} {1} {2}\n'.format(dzx, dzy, dzz))
118 # Use v_sim 3.5 keywords to indicate scaled positions, etc.
119 fd.write('#keyword: reduced\n')
120 fd.write('#keyword: angstroem\n')
121 if np.alltrue(atoms.pbc):
122 fd.write('#keyword: periodic\n')
123 elif not np.any(atoms.pbc):
124 fd.write('#keyword: freeBC\n')
125 elif np.array_equiv(atoms.pbc, [True, False, True]):
126 fd.write('#keyword: surface\n')
127 else:
128 raise Exception(
129 'Only supported boundary conditions are full PBC,'
130 ' no periodic boundary, and surface which is free in y direction'
131 ' (i.e. Atoms.pbc = [True, False, True]).')
133 # Add atoms (scaled positions)
134 for position, symbol in zip(atoms.get_scaled_positions(),
135 atoms.get_chemical_symbols()):
136 fd.write('{0} {1} {2} {3}\n'.format(
137 position[0], position[1], position[2], symbol))