import dataclasses
from typing import Optional
try:
from dftd4.interface import DampingParam, DispersionModel
HAS_DFTD4 = True
except ModuleNotFoundError:
HAS_DFTD4 = False
# Dummy definition, so pysisyphus does not crash if another module tries to
# import DFT4.
DFTD4 = None
from pysisyphus.calculators.Calculator import Calculator
from pysisyphus.elem_data import nuc_charges_for_atoms
@dataclasses.dataclass
class D4Params:
s6: float
s8: float
s9: float
a1: float
a2: float
OWN_METHODS = {
# ORCA 5.0.3 ... your rĀ²scan-3c bug ... why are you doing this to me? Why?
"r2scan-3c": D4Params(s6=1.0, s8=0.0, s9=2.0, a1=0.42, a2=5.65),
}
[docs]
class DFTD4(Calculator):
def __init__(
self,
method: Optional[str] = None,
damp_params: Optional[D4Params] = None,
model_params: Optional[dict] = None,
**kwargs
):
assert HAS_DFTD4, "DFTD4 python package is not installed!"
super().__init__(**kwargs)
if model_params is None:
model_params = dict()
self.model_params = model_params
if method in OWN_METHODS:
damp_params = OWN_METHODS[method]
if damp_params is not None:
self.damp_param = DampingParam(**dataclasses.asdict(damp_params))
# if method is not None:
elif method is not None:
self.method = method
self.damp_param = DampingParam(method=method)
else:
raise Exception("Please provide either 'method' or 'params'!")
[docs]
def get_model(self, atoms, coords):
atomic_numbers = nuc_charges_for_atoms(atoms)
model = DispersionModel(
atomic_numbers, coords.reshape(-1, 3), **self.model_params
)
return model
[docs]
def get_dispersion(self, atoms, coords, grad):
model = self.get_model(atoms, coords)
res = model.get_dispersion(self.damp_param, grad=grad)
results = {
"energy": float(res.get("energy")),
}
if grad:
results["forces"] = -res.get("gradient").flatten()
return results
[docs]
def get_energy(self, atoms, coords, **prepare_kwargs):
return self.get_dispersion(atoms, coords, grad=False)
[docs]
def get_forces(self, atoms, coords, **prepare_kwargs):
return self.get_dispersion(atoms, coords, grad=True)
# This calculator relies on a finite differences numerical Hessian, as provided
# by the Calculator parent class.