import os
from ase.calculators.dftb import Dftb
from pathlib import Path
from pharmaforge.interfaces import AbstractIO
from pharmaforge.interfaces import DPDataInterface
[docs]
class DFTBInterface(AbstractIO):
""" This class is used to interface with DFTB+ for quantum chemistry calculations, and will
be used to calculate the energies and forces of the system.
.. code-block:: python
self.dftb_options = {
"Hamiltonian_SCC": "Yes",
"Hamiltonian_SccTolerance": 1e-8,
"Hamiltonian_MaxAngularMomentum_": "",
"Hamiltonian_MaxAngularMomentum_H": "s",
"Hamiltonian_MaxAngularMomentum_O": "p",
"Hamiltonian_MaxAngularMomentum_C": "p",
"Hamiltonian_MaxAngularMomentum_N": "p",
}
.. warning::
Currently, this interface does not support parallelization because it runs by creating an input file,
which is not thread safe.
Parameters
----------
skf_loc : str
The location of the DFTB+ skf files. Default is "./".
default : bool
If True, use the default options for the DFTB+ calculator. Default is False.
options : dict
A dictionary of options to pass to the DFTB+ calculator. Default is an empty dictionary.
Attributes
----------
calculator : object
The DFTB+ calculator object.
allow_parallel : bool
Whether to allow parallelization. Default is False.
level_of_theory : str
The level of theory used for the calculations. Default is "DFTB".
options_dict : dict
A dictionary of options for the DFTB+ calculator.
See Also
--------
pharmaforge.interfaces.abstractio.AbstractIO : The abstract interface class for the Psi4Interface.
ase.calculators.dftb.DFTB : The DFTB calculator object.
"""
def __init__(self, skf_loc="./", default=False, **options):
self.allow_parallel = False
self.calculator = Dftb
self.skf_loc = Path(skf_loc)
if not self.skf_loc.exists():
raise ValueError(f"skf location {self.skf_loc} does not exist.")
self.set_environment()
self.allow_parallel = True
self.level_of_theory="DFTB"
self.options_dict = {
"skf_loc": self.skf_loc,
}
if default:
print("Using default DFTB+ options.")
self.dftb_options = {
"Hamiltonian_SCC": "Yes",
"Hamiltonian_SccTolerance": 1e-8,
"Hamiltonian_MaxAngularMomentum_": "",
"Hamiltonian_MaxAngularMomentum_H": "s",
"Hamiltonian_MaxAngularMomentum_O": "p",
"Hamiltonian_MaxAngularMomentum_C": "p",
"Hamiltonian_MaxAngularMomentum_N": "p",
"Hamiltonian_MaxAngularMomentum_S": "p",
"Hamiltonian_MaxAngularMomentum_Cl": "p"
}
else:
self.dftb_options = {}
for option, value in options.items():
self.dftb_options[option] = value
for key, value in options.items():
self.options_dict[key] = value
return
[docs]
def set_environment(self):
"""Set the environment for the DFTB+ calculator."""
os.environ["DFTB_PREFIX"] = str(self.skf_loc)
def _calculate(self, structure, charge=0):
"""Calculate the system data.
Parameters
----------
structure : ase.Atoms
The ASE atoms object containing the system data.
Returns
-------
calc : ase.Atoms
The ASE atoms object with the DFTB+ calculator attached.
"""
structure.calc=self.calculator(Hamiltonian_Charge=charge,**self.dftb_options)
return structure