Source code for dpdata.plugins.gaussian

import os
import subprocess as sp
import tempfile

import dpdata.gaussian.gjf
import dpdata.gaussian.log
from dpdata.driver import Driver
from dpdata.format import Format


[docs] @Format.register("gaussian/log") class GaussianLogFormat(Format):
[docs] def from_labeled_system(self, file_name, md=False, **kwargs): try: return dpdata.gaussian.log.to_system_data(file_name, md=md) except AssertionError: return {"energies": [], "forces": [], "nopbc": True}
[docs] @Format.register("gaussian/md") class GaussianMDFormat(Format):
[docs] def from_labeled_system(self, file_name, **kwargs): return GaussianLogFormat().from_labeled_system(file_name, md=True)
[docs] @Format.register("gaussian/gjf") class GaussiaGJFFormat(Format): """Gaussian input file."""
[docs] def from_system(self, file_name: str, **kwargs): """Read Gaussian input file. Parameters ---------- file_name : str file name **kwargs : dict keyword arguments """ with open(file_name) as fp: text = fp.read() return dpdata.gaussian.gjf.read_gaussian_input(text)
[docs] def to_system(self, data: dict, file_name: str, **kwargs): """Generate Gaussian input file. Parameters ---------- data : dict system data file_name : str file name **kwargs : dict Other parameters to make input files. See :meth:`dpdata.gaussian.gjf.make_gaussian_input` """ text = dpdata.gaussian.gjf.make_gaussian_input(data, **kwargs) with open(file_name, "w") as fp: fp.write(text)
[docs] @Driver.register("gaussian") class GaussianDriver(Driver): """Gaussian driver. Note that "force" keyword must be added. If the number of atoms is large, "Geom=PrintInputOrient" should be added. Parameters ---------- gaussian_exec : str, default=g16 path to gaussian program **kwargs : dict other arguments to make input files. See :meth:`dpdata.gaussian.gjf.make_gaussian_input` Examples -------- Use B3LYP method to calculate potential energy of a methane molecule: >>> labeled_system = system.predict(keywords="force b3lyp/6-31g**", driver="gaussian") >>> labeled_system['energies'][0] -1102.714590995794 """ def __init__(self, gaussian_exec: str = "g16", **kwargs: dict) -> None: self.gaussian_exec = gaussian_exec self.kwargs = kwargs
[docs] def label(self, data: dict) -> dict: """Label a system data. Returns new data with energy, forces, and virials. Parameters ---------- data : dict data with coordinates and atom types Returns ------- dict labeled data with energies and forces """ ori_system = dpdata.System(data=data) labeled_system = dpdata.LabeledSystem() with tempfile.TemporaryDirectory() as d: for ii, ss in enumerate(ori_system): inp_fn = os.path.join(d, "%d.gjf" % ii) out_fn = os.path.join(d, "%d.log" % ii) ss.to("gaussian/gjf", inp_fn, **self.kwargs) try: sp.check_output([*self.gaussian_exec.split(), inp_fn]) except sp.CalledProcessError as e: with open(out_fn) as f: out = f.read() raise RuntimeError("Run gaussian failed! Output:\n" + out) from e labeled_system.append(dpdata.LabeledSystem(out_fn, fmt="gaussian/log")) return labeled_system.data