Coverage for /builds/ase/ase/ase/io/wien2k.py: 67.83%
143 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3import numpy as np
5from ase import Atoms
6from ase.units import Bohr, Ry
7from ase.utils import reader, writer
10def read_scf(filename):
11 try:
12 with open(filename + '.scf') as fd:
13 pip = fd.readlines()
14 ene = []
15 for line in pip:
16 if line[0:4] == ':ENE':
17 ene.append(float(line[43:59]) * Ry)
18 return ene
19 except Exception: # XXX Which kind of exception exactly?
20 return None
23@reader
24def read_struct(fd, ase=True):
25 pip = fd.readlines()
26 lattice = pip[1][0:3]
27 nat = int(pip[1][27:30])
28 cell = np.zeros(6)
29 for i in range(6):
30 cell[i] = float(pip[3][0 + i * 10:10 + i * 10])
31 cell[0:3] = cell[0:3] * Bohr
32 if lattice == 'P ':
33 lattice = 'P'
34 elif lattice == 'H ':
35 lattice = 'P'
36 cell[3:6] = [90.0, 90.0, 120.0]
37 elif lattice == 'R ':
38 lattice = 'R'
39 elif lattice == 'F ':
40 lattice = 'F'
41 elif lattice == 'B ':
42 lattice = 'I'
43 elif lattice == 'CXY':
44 lattice = 'C'
45 elif lattice == 'CXZ':
46 lattice = 'B'
47 elif lattice == 'CYZ':
48 lattice = 'A'
49 else:
50 raise RuntimeError('TEST needed')
51 pos = np.array([])
52 atomtype = []
53 rmt = []
54 neq = np.zeros(nat)
55 iline = 4
56 indif = 0
57 for iat in range(nat):
58 indifini = indif
59 if len(pos) == 0:
60 pos = np.array([[float(pip[iline][12:22]),
61 float(pip[iline][25:35]),
62 float(pip[iline][38:48])]])
63 else:
64 pos = np.append(pos, np.array([[float(pip[iline][12:22]),
65 float(pip[iline][25:35]),
66 float(pip[iline][38:48])]]),
67 axis=0)
68 indif += 1
69 iline += 1
70 neq[iat] = int(pip[iline][15:17])
71 iline += 1
72 for _ in range(1, int(neq[iat])):
73 pos = np.append(pos, np.array([[float(pip[iline][12:22]),
74 float(pip[iline][25:35]),
75 float(pip[iline][38:48])]]),
76 axis=0)
77 indif += 1
78 iline += 1
79 for _ in range(indif - indifini):
80 atomtype.append(pip[iline][0:2].replace(' ', ''))
81 rmt.append(float(pip[iline][43:48]))
82 iline += 4
83 if ase:
84 cell2 = coorsys(cell)
85 atoms = Atoms(atomtype, pos, pbc=True)
86 atoms.set_cell(cell2, scale_atoms=True)
87 cell2 = np.dot(c2p(lattice), cell2)
88 if lattice == 'R':
89 atoms.set_cell(cell2, scale_atoms=True)
90 else:
91 atoms.set_cell(cell2)
92 return atoms
93 else:
94 return cell, lattice, pos, atomtype, rmt
97@writer
98def write_struct(fd, atoms2=None, rmt=None, lattice='P', zza=None):
99 atoms = atoms2.copy()
100 atoms.wrap()
101 fd.write('ASE generated\n')
102 nat = len(atoms)
103 if rmt is None:
104 rmt = [2.0] * nat
105 fd.write(lattice +
106 ' LATTICE,NONEQUIV.ATOMS:%3i\nMODE OF CALC=RELA\n' % nat)
107 cell = atoms.get_cell()
108 metT = np.dot(cell, np.transpose(cell))
109 cell2 = cellconst(metT)
110 cell2[0:3] = cell2[0:3] / Bohr
111 fd.write(('%10.6f' * 6) % tuple(cell2) + '\n')
112 if zza is None:
113 zza = atoms.get_atomic_numbers()
114 for ii in range(nat):
115 fd.write('ATOM %3i: ' % (ii + 1))
116 pos = atoms.get_scaled_positions()[ii]
117 fd.write('X=%10.8f Y=%10.8f Z=%10.8f\n' % tuple(pos))
118 fd.write(' MULT= 1 ISPLIT= 1\n')
119 zz = zza[ii]
120 if zz > 71:
121 ro = 0.000005
122 elif zz > 36:
123 ro = 0.00001
124 elif zz > 18:
125 ro = 0.00005
126 else:
127 ro = 0.0001
128 fd.write('%-10s NPT=%5i R0=%9.8f RMT=%10.4f Z:%10.5f\n' %
129 (atoms.get_chemical_symbols()[ii], 781, ro, rmt[ii], zz))
130 fd.write(f'LOCAL ROT MATRIX: {1.0:9.7f} {0.0:9.7f} {0.0:9.7f}\n')
131 fd.write(f' {0.0:9.7f} {1.0:9.7f} {0.0:9.7f}\n')
132 fd.write(f' {0.0:9.7f} {0.0:9.7f} {1.0:9.7f}\n')
133 fd.write(' 0\n')
136def cellconst(metT):
137 """ metT=np.dot(cell,cell.T) """
138 aa = np.sqrt(metT[0, 0])
139 bb = np.sqrt(metT[1, 1])
140 cc = np.sqrt(metT[2, 2])
141 gamma = np.arccos(metT[0, 1] / (aa * bb)) / np.pi * 180.0
142 beta = np.arccos(metT[0, 2] / (aa * cc)) / np.pi * 180.0
143 alpha = np.arccos(metT[1, 2] / (bb * cc)) / np.pi * 180.0
144 return np.array([aa, bb, cc, alpha, beta, gamma])
147def coorsys(latconst):
148 a = latconst[0]
149 b = latconst[1]
150 c = latconst[2]
151 cal = np.cos(latconst[3] * np.pi / 180.0)
152 cbe = np.cos(latconst[4] * np.pi / 180.0)
153 cga = np.cos(latconst[5] * np.pi / 180.0)
154 sga = np.sin(latconst[5] * np.pi / 180.0)
155 return np.array([[a, b * cga, c * cbe],
156 [0, b * sga, c * (cal - cbe * cga) / sga],
157 [0, 0, c * np.sqrt(1 - cal**2 - cbe**2 - cga**2 +
158 2 * cal * cbe * cga) / sga]
159 ]).transpose()
162def c2p(lattice):
163 """ apply as eg. cell2 = np.dot(c2p('F'), cell)"""
164 if lattice == 'P':
165 cell = np.eye(3)
166 elif lattice == 'F':
167 cell = np.array([[0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]])
168 elif lattice == 'I':
169 cell = np.array([[-0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5]])
170 elif lattice == 'C':
171 cell = np.array([[0.5, 0.5, 0.0], [0.5, -0.5, 0.0], [0.0, 0.0, -1.0]])
172 elif lattice == 'B':
173 cell = np.array([[0.5, 0.0, 0.5], [0.0, 1.0, 0.0], [0.5, 0.0, -0.5]])
174 elif lattice == 'A':
175 cell = np.array([[-1.0, 0.0, 0.0], [0.0, -0.5, 0.5], [0.0, 0.5, 0.5]])
176 elif lattice == 'R':
177 cell = np.array([[2.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0],
178 [-1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0],
179 [-1.0 / 3.0, -2.0 / 3.0, 1.0 / 3.0]])
181 else:
182 raise ValueError('lattice is ' + lattice + '!')
183 return cell