Robotics
code
Silk_LLM / cp2k.py
nlsefouh's picture
Upload 8 files
aac5fad verified
"""Functions for CP2K-specific input/output."""
__all__ = ['add_energy_cp2k_comment', 'read_frames_cp2k']
from itertools import repeat
from .utilities import Frame, merge_frames, read_frames
def add_energy_cp2k_comment(frames):
"""Parse CP2K energy and inject it into frames.
For each frame in `frames`, try to extract a CP2K-formatted potential energy
from the comment string and inject it back into the frame. Energy from CP2K is
in Hartree, so no conversion is needed.
"""
for frame in frames:
if frame.energy is not None:
raise ValueError('Energy already present.')
try:
for pair in frame.comment.split(','):
items = pair.split('=')
if items[0].strip() == 'E':
frame.energy = float(items[1])
break
except (IndexError, ValueError):
raise ValueError('No CP2K energy found in comment line.')
yield frame
def read_frames_cp2k(fn_positions, cell=None, fn_forces=None, read_energy: bool = True, force_unit=1.0):
"""Read data specifically produced by CP2K.
Arguments:
fn_positions: position trajectory file name, XYZ format
cell: a constant cell to use in all frames, optional
fn_forces: forces file name, XYZ format, optional
read_energy: whether to read energies from comments in `fn_positions`
Returns:
a `Frame` object
"""
# positions from XYZ, energies from comment if requested
# we expect units of angstrom for positions from CP2K
frames_pos = read_frames(fn_positions, fformat='xyz')
if read_energy:
frames_pos = add_energy_cp2k_comment(frames_pos)
frames = [frames_pos]
# add a constant cell if provided
if cell is not None:
frames.append(repeat(Frame(cell=cell)))
# add forces from XYZ if filename was provided
# we expect atomic units for forces from CP2K per default
if fn_forces is not None:
frames.append(read_frames(fn_forces, fformat='xyz', name_data='forces', unit=force_unit))
# iterate over merged frames
yield from merge_frames(*frames)