#import psi4
from ase.calculators.psi4 import Psi4
from pharmaforge.interfaces import AbstractIO
from pharmaforge.interfaces import DPDataInterface
[docs]
class Psi4Interface(AbstractIO):
""" This class is used to interface with Psi4 for quantum chemistry calculations, and will
be used to calculate the energies and forces of the system.
.. code-block:: python
self.psi4_options = {
"method": "B3LYP",
"basis": "6-31G",
"num_threads": 1,
}
Parameters
----------
basis_set : str
The basis set to use for the calculations. Default is "6-31G".
functional : str
The functional to use for the calculations. Default is "B3LYP".
num_threads : int
The number of threads to use for an individual calculation. Default is 1.
Attributes
----------
calculator : object
The Psi4 calculator object.
allow_parallel : bool
Whether to allow parallelization. Default is True.
level_of_theory : str
The level of theory used for the calculations. Default is "Psi4".
options_dict : dict
A dictionary of options for the Psi4 calculator, that can include things not sent to the calculator.
psi4_options : dict
A dictionary of options for the Psi4 calculator that are passed to the calculator.
See Also
--------
pharmaforge.interfaces.abstractio.AbstractIO : The abstract interface class for the Psi4Interface.
ase.calculators.psi4.Psi4 : The Psi4 calculator object.
Example
-------
>>> from pharmaforge.interfaces.psi4io import Psi4Interface
>>> from ase import Atoms
>>> import numpy as np
>>> h2 = Atoms('HH', positions=[(0, 0, 0), (0, 0, 1)])
>>> psi4 = Psi4Interface(default=True)
>>> calc = psi4._calculate(h2)
>>> e, f = psi4._report_data(calc)
>>> print(np.round(e,4))
-31.2467
"""
def __init__(self, default=False, **options):
"""Initialize the Psi4Interface class."""
self.calculator = Psi4
self.allow_parallel = True
self.options_dict = {}
if default:
self.psi4_options = {
"method": "B3LYP",
"basis": "6-31G",
"num_threads": 1,
}
else:
self.psi4_options = {}
for option, value in options.items():
self.psi4_options[option] = value
for key, value in options.items():
self.options_dict[key] = value
self.level_of_theory=f"{self.psi4_options['method']}/{self.psi4_options['basis']}"
return
def _calculate(self, structure, charge=0):
"""Calculate the system data.
Parameters
----------
structure : ase.Atoms
The ASE atoms object containing the system data.
Returns
-------
calc : Psi4
The Psi4 calculator object.
"""
calc=self.calculator(
atoms=structure,
charge=charge,
**self.psi4_options
)
structure.calc = calc
return structure