#!/usr/bin/env python
import random
import os
import string
import jinja2 as j
[docs]class CalculatorInterface(object):
""" All the functions that need to be implemented for a new code to be supported in APDFT. """
[docs] @staticmethod
def get_total_energy(folder):
""" Extracts the total energy of a calculation.
Args:
folder: String. Path to the QM calculation from which the energy is to be extracted.
Returns:
Total energy including nuclear-nuclear interaction [Hartree]."""
raise NotImplementedError()
[docs] def get_runfile(self, coordinates, nuclear_numbers, nuclear_charges, grid):
raise NotImplementedError()
[docs] def get_epn(folder, coordinates, includeatoms, nuclear_charges):
""" Extracts the electronic contribution to the electrostatic potential at the nuclei. """
raise NotImplementedError()
[docs]class Calculator(CalculatorInterface):
""" A concurrency-safe blocking interface for an external QM code."""
_methods = {}
def __init__(self, method, basisset, superimpose=False):
self._method = method
self._basisset = basisset
self._superimpose = superimpose
[docs] def get_methods(self):
return list(self._methods.keys())
[docs] def get_density_on_grid(self, folder, gridpoints):
raise NotImplementedError()
@staticmethod
def _get_tempname():
return "apdft-tmp-" + "".join(
random.choice(string.ascii_uppercase + string.digits) for _ in range(10)
)
[docs] @staticmethod
def get_grid(nuclear_numbers, coordinates, outputfolder):
""" Returns the integration grid used by this calculator for a given set of nuclei and geometry.
Grid weights and coordinates may be in internal units. Return value should be coords, weights. If return value is None, a default grid is used."""
return None
[docs]class MockCalculator(Calculator):
_methods = {}
[docs] @classmethod
def get_runfile(self, coordinates, nuclear_numbers, nuclear_charges, grid):
basedir = os.path.dirname(os.path.abspath(__file__))
with open("%s/templates/mock-run.sh" % basedir) as fh:
template = j.Template(fh.read())
return template.render()