/ase/io/gpaw_out.py

https://gitlab.com/jennings.p.c/ase-f-ase · Python · 239 lines · 215 code · 20 blank · 4 comment · 80 complexity · f931b39674634f21a1cc813bb3231ffe MD5 · raw file

  1. import re
  2. import numpy as np
  3. from ase.atoms import Atoms
  4. from ase.calculators.singlepoint import SinglePointDFTCalculator
  5. from ase.calculators.singlepoint import SinglePointKPoint
  6. from ase.utils import basestring
  7. def read_gpaw_out(fileobj, index):
  8. notfound = []
  9. def index_startswith(lines, string):
  10. if not isinstance(string, basestring):
  11. # assume it's a list
  12. for entry in string:
  13. try:
  14. return index_startswith(lines, entry)
  15. except ValueError:
  16. pass
  17. raise ValueError
  18. if string in notfound:
  19. raise ValueError
  20. for i, line in enumerate(lines):
  21. if line.startswith(string):
  22. return i
  23. notfound.append(string)
  24. raise ValueError
  25. def index_pattern(lines, pattern):
  26. repat = re.compile(pattern)
  27. if pattern in notfound:
  28. raise ValueError
  29. for i, line in enumerate(lines):
  30. if repat.match(line):
  31. return i
  32. notfound.append(pattern)
  33. raise ValueError
  34. def read_forces(lines, ii):
  35. f = []
  36. for i in range(ii + 1, ii + 1 + len(atoms)):
  37. try:
  38. x, y, z = lines[i].split()[-3:]
  39. f.append((float(x), float(y), float(z)))
  40. except (ValueError, IndexError) as m:
  41. raise IOError('Malformed GPAW log file: %s' % m)
  42. return f, i
  43. lines = [line.lower() for line in fileobj.readlines()]
  44. images = []
  45. while True:
  46. try:
  47. i = lines.index('unit cell:\n')
  48. except ValueError:
  49. pass
  50. else:
  51. if lines[i + 2].startswith(' -'):
  52. del lines[i + 2] # old format
  53. cell = []
  54. pbc = []
  55. for line in lines[i + 2:i + 5]:
  56. words = line.split()
  57. if len(words) == 5: # old format
  58. cell.append(float(words[2]))
  59. pbc.append(words[1] == 'yes')
  60. else: # new format with GUC
  61. cell.append([float(word) for word in words[3:6]])
  62. pbc.append(words[2] == 'yes')
  63. try:
  64. i = lines.index('positions:\n')
  65. except ValueError:
  66. break
  67. symbols = []
  68. positions = []
  69. for line in lines[i + 1:]:
  70. words = line.split()
  71. if len(words) != 5:
  72. break
  73. n, symbol, x, y, z = words
  74. symbols.append(symbol.split('.')[0].title())
  75. positions.append([float(x), float(y), float(z)])
  76. if len(symbols):
  77. atoms = Atoms(symbols=symbols, positions=positions,
  78. cell=cell, pbc=pbc)
  79. else:
  80. atoms = Atoms(cell=cell, pbc=pbc)
  81. lines = lines[i + 5:]
  82. try:
  83. ii = index_startswith(lines, 'reference energy:')
  84. Eref = float(lines[ii].split()[-1])
  85. except ValueError:
  86. Eref = None
  87. try:
  88. ii = index_pattern(lines, '\d+ k-point')
  89. word = lines[ii].split()
  90. kx = int(word[2])
  91. ky = int(word[4])
  92. kz = int(word[6])
  93. bz_kpts = (kx, ky, kz)
  94. ibz_kpts = int(lines[ii + 1].split()[0])
  95. except (ValueError, TypeError, IndexError):
  96. bz_kpts = None
  97. ibz_kpts = None
  98. try:
  99. i = index_startswith(lines, 'energy contributions relative to')
  100. except ValueError:
  101. e = energy_contributions = None
  102. else:
  103. energy_contributions = {}
  104. for line in lines[i + 2:i + 8]:
  105. fields = line.split(':')
  106. energy_contributions[fields[0]] = float(fields[1])
  107. line = lines[i + 10]
  108. assert (line.startswith('zero kelvin:') or
  109. line.startswith('extrapolated:'))
  110. e = float(line.split()[-1])
  111. try:
  112. ii = index_pattern(lines, '(fixed )?fermi level(s)?:')
  113. except ValueError:
  114. eFermi = None
  115. else:
  116. fields = lines[ii].split()
  117. try:
  118. def strip(string):
  119. for rubbish in '[],':
  120. string = string.replace(rubbish, '')
  121. return string
  122. eFermi = [float(strip(fields[-2])),
  123. float(strip(fields[-1]))]
  124. except ValueError:
  125. eFermi = float(fields[-1])
  126. # read Eigenvalues and occupations
  127. ii1 = ii2 = 1e32
  128. try:
  129. ii1 = index_startswith(lines, ' band eigenvalues occupancy')
  130. except ValueError:
  131. pass
  132. try:
  133. ii2 = index_startswith(lines, ' band eigenvalues occupancy')
  134. except ValueError:
  135. pass
  136. ii = min(ii1, ii2)
  137. if ii == 1e32:
  138. kpts = None
  139. else:
  140. ii += 1
  141. words = lines[ii].split()
  142. vals = []
  143. while(len(words) > 2):
  144. vals.append([float(w) for w in words])
  145. ii += 1
  146. words = lines[ii].split()
  147. vals = np.array(vals).transpose()
  148. kpts = [SinglePointKPoint(1, 0, 0)]
  149. kpts[0].eps_n = vals[1]
  150. kpts[0].f_n = vals[2]
  151. if vals.shape[0] > 3:
  152. kpts.append(SinglePointKPoint(1, 1, 0))
  153. kpts[1].eps_n = vals[3]
  154. kpts[1].f_n = vals[4]
  155. # read charge
  156. try:
  157. ii = index_startswith(lines, 'total charge:')
  158. except ValueError:
  159. q = None
  160. else:
  161. q = float(lines[ii].split()[2])
  162. # read dipole moment
  163. try:
  164. ii = index_startswith(lines, 'dipole moment:')
  165. except ValueError:
  166. dipole = None
  167. else:
  168. line = lines[ii]
  169. for x in '()[],':
  170. line = line.replace(x, '')
  171. dipole = np.array([float(c) for c in line.split()[2:5]])
  172. try:
  173. ii = index_startswith(lines, 'local magnetic moments')
  174. except ValueError:
  175. magmoms = None
  176. else:
  177. magmoms = []
  178. for j in range(ii + 1, ii + 1 + len(atoms)):
  179. magmom = lines[j].split()[-1]
  180. magmoms.append(float(magmom))
  181. try:
  182. ii = lines.index('forces in ev/ang:\n')
  183. except ValueError:
  184. f = None
  185. else:
  186. f, i = read_forces(lines, ii)
  187. try:
  188. ii = index_startswith(lines, 'vdw correction:')
  189. except ValueError:
  190. pass
  191. else:
  192. line = lines[ii + 1]
  193. assert line.startswith('energy:')
  194. e = float(line.split()[-1])
  195. f, i = read_forces(lines, ii + 3)
  196. if len(images) > 0 and e is None:
  197. break
  198. if q is not None and len(atoms) > 0:
  199. n = len(atoms)
  200. atoms.set_initial_charges([q / n] * n)
  201. if magmoms is not None:
  202. atoms.set_initial_magnetic_moments(magmoms)
  203. if e is not None or f is not None:
  204. calc = SinglePointDFTCalculator(atoms, energy=e, forces=f,
  205. dipole=dipole, magmoms=magmoms,
  206. efermi=eFermi,
  207. bzkpts=bz_kpts, ibzkpts=ibz_kpts)
  208. calc.eref = Eref
  209. calc.name = 'gpaw'
  210. if energy_contributions is not None:
  211. calc.energy_contributions = energy_contributions
  212. if kpts is not None:
  213. calc.kpts = kpts
  214. atoms.set_calculator(calc)
  215. images.append(atoms)
  216. lines = lines[i:]
  217. if len(images) == 0:
  218. raise IOError('Corrupted GPAW-text file!')
  219. return images[index]