Source code for ase.calculators.gaussian

import os
import copy
from import Iterable
from shutil import which
from typing import Dict, Optional

from import read, write
from ase.calculators.calculator import FileIOCalculator, EnvironmentError

class GaussianDynamics:
    calctype = 'optimizer'
    delete = ['force']
    keyword: Optional[str] = None
    special_keywords: Dict[str, str] = dict()

    def __init__(self, atoms, calc=None):
        self.atoms = atoms
        if calc is not None:
            self.calc = calc
            if self.atoms.calc is None:
                raise ValueError("{} requires a valid Gaussian calculator "

            self.calc = self.atoms.calc

    def todict(self):
        return {'type': self.calctype,
                'optimizer': self.__class__.__name__}

    def delete_keywords(self, kwargs):
        """removes list of keywords (delete) from kwargs"""
        for d in self.delete:
            kwargs.pop(d, None)

    def set_keywords(self, kwargs):
        args = kwargs.pop(self.keyword, [])
        if isinstance(args, str):
            args = [args]
        elif isinstance(args, Iterable):
            args = list(args)

        for key, template in self.special_keywords.items():
            if key in kwargs:
                val = kwargs.pop(key)

        kwargs[self.keyword] = args

    def run(self, **kwargs):
        calc_old = self.atoms.calc
        params_old = copy.deepcopy(self.calc.parameters)


        self.atoms.calc = self.calc

        except OSError:
            converged = False
            converged = True

        atoms = read(self.calc.label + '.log')
        self.atoms.cell = atoms.cell
        self.atoms.positions = atoms.positions

        self.calc.parameters = params_old
        if calc_old is not None:
            self.atoms.calc = calc_old

        return converged

class GaussianOptimizer(GaussianDynamics):
    keyword = 'opt'
    special_keywords = {
        'fmax': '{}',
        'steps': 'maxcycle={}',

class GaussianIRC(GaussianDynamics):
    keyword = 'irc'
    special_keywords = {
        'direction': '{}',
        'steps': 'maxpoints={}',

[docs]class Gaussian(FileIOCalculator): implemented_properties = ['energy', 'forces', 'dipole'] command = 'GAUSSIAN < > PREFIX.log' discard_results_on_any_change = True def __init__(self, *args, label='Gaussian', **kwargs): FileIOCalculator.__init__(self, *args, label=label, **kwargs) def calculate(self, *args, **kwargs): gaussians = ('g16', 'g09', 'g03') if 'GAUSSIAN' in self.command: for gau in gaussians: if which(gau): self.command = self.command.replace('GAUSSIAN', gau) break else: raise EnvironmentError('Missing Gaussian executable {}' .format(gaussians)) FileIOCalculator.calculate(self, *args, **kwargs) def write_input(self, atoms, properties=None, system_changes=None): FileIOCalculator.write_input(self, atoms, properties, system_changes) write(self.label + '.com', atoms, properties=properties, format='gaussian-in', parallel=False, **self.parameters) def read_results(self): output = read(self.label + '.log', format='gaussian-out') self.calc = output.calc self.results = output.calc.results # Method(s) defined in the old calculator, added here for # backwards compatibility def clean(self): for suffix in ['.com', '.chk', '.log']: try: os.remove(os.path.join(, self.label + suffix)) except OSError: pass def get_version(self): raise NotImplementedError # not sure how to do this yet