Coverage for /builds/kinetik161/ase/ase/io/orca.py: 96.39%
83 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
1import os
2import re
3from io import StringIO
4from pathlib import Path
6import numpy as np
8from ase.io import read
9from ase.units import Bohr, Hartree
10from ase.utils import reader, writer
12# Made from NWChem interface
15@reader
16def read_geom_orcainp(fd):
17 """Method to read geometry from an ORCA input file."""
18 lines = fd.readlines()
20 # Find geometry region of input file.
21 stopline = 0
22 for index, line in enumerate(lines):
23 if line[1:].startswith('xyz '):
24 startline = index + 1
25 stopline = -1
26 elif (line.startswith('end') and stopline == -1):
27 stopline = index
28 elif (line.startswith('*') and stopline == -1):
29 stopline = index
30 # Format and send to read_xyz.
31 xyz_text = '%i\n' % (stopline - startline)
32 xyz_text += ' geometry\n'
33 for line in lines[startline:stopline]:
34 xyz_text += line
35 atoms = read(StringIO(xyz_text), format='xyz')
36 atoms.set_cell((0., 0., 0.)) # no unit cell defined
38 return atoms
41@writer
42def write_orca(fd, atoms, params):
43 # conventional filename: '<name>.inp'
44 fd.write(f"! {params['orcasimpleinput']} \n")
45 fd.write(f"{params['orcablocks']} \n")
47 fd.write('*xyz')
48 fd.write(" %d" % params['charge'])
49 fd.write(" %d \n" % params['mult'])
50 for atom in atoms:
51 if atom.tag == 71: # 71 is ascii G (Ghost)
52 symbol = atom.symbol + ' : '
53 else:
54 symbol = atom.symbol + ' '
55 fd.write(symbol +
56 str(atom.position[0]) + ' ' +
57 str(atom.position[1]) + ' ' +
58 str(atom.position[2]) + '\n')
59 fd.write('*\n')
62@reader
63def read_orca_energy(fd):
64 """Read Energy from ORCA output file."""
65 text = fd.read()
66 re_energy = re.compile(r"FINAL SINGLE POINT ENERGY.*\n")
67 re_not_converged = re.compile(r"Wavefunction not fully converged")
69 found_line = re_energy.finditer(text)
70 energy = float('nan')
71 for match in found_line:
72 if not re_not_converged.search(match.group()):
73 energy = float(match.group().split()[-1]) * Hartree
74 if np.isnan(energy):
75 raise RuntimeError('No energy')
76 else:
77 return energy
80@reader
81def read_orca_forces(fd):
82 """Read Forces from ORCA output file."""
83 getgrad = False
84 gradients = []
85 tempgrad = []
86 for i, line in enumerate(fd):
87 if line.find('# The current gradient') >= 0:
88 getgrad = True
89 gradients = []
90 tempgrad = []
91 continue
92 if getgrad and "#" not in line:
93 grad = line.split()[-1]
94 tempgrad.append(float(grad))
95 if len(tempgrad) == 3:
96 gradients.append(tempgrad)
97 tempgrad = []
98 if '# The at' in line:
99 getgrad = False
101 forces = -np.array(gradients) * Hartree / Bohr
102 return forces
105def read_orca_outputs(directory, stdout_path):
106 results = {}
107 energy = read_orca_energy(Path(stdout_path))
108 results['energy'] = energy
109 results['free_energy'] = energy
111 # Does engrad always exist? - No!
112 # Will there be other files -No -> We should just take engrad
113 # as a direct argument. Or maybe this function does not even need to
114 # exist.
115 engrad_path = Path(stdout_path).with_suffix('.engrad')
116 if os.path.isfile(engrad_path):
117 results['forces'] = read_orca_forces(engrad_path)
118 return results