Source code for pydft_qmmm.interfaces.qmmm_pme_psi4.psi4_utils

"""Functionality for building the QM/MM/PME-hacked Psi4 interface.
"""
from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING

from .psi4_interface import PMEPsi4Interface
from pydft_qmmm.interfaces.psi4.psi4_utils import _build_context
from pydft_qmmm.interfaces.psi4.psi4_utils import Psi4Options


if TYPE_CHECKING:
    from pydft_qmmm.interfaces import QMSettings


[docs] @dataclass(frozen=True) class PMEPsi4Options(Psi4Options): """An immutable wrapper class for storing Psi4 global options. Args: pme: Whether or not to perform a Psi4 calculation with the interpolated PME potential. """ pme: str = "true"
[docs] def pme_psi4_interface_factory(settings: QMSettings) -> PMEPsi4Interface: """Build the interface to Psi4 given the settings. Args: settings: The settings used to build the Psi4 interface. Returns: The QM/MM/PME-hacked Psi4 interface. """ basis = settings.basis_set if "assign" not in settings.basis_set: basis = "assign " + settings.basis_set.strip() psi4.basis_helper(basis, name="default") options = _build_options(settings) functional = settings.functional context = _build_context(settings) wrapper = PMEPsi4Interface( settings, options, functional, context, ) # Register observer functions. settings.system.charges.register_notifier(wrapper.update_charges) settings.system.positions.register_notifier(wrapper.update_positions) settings.system.subsystems.register_notifier(wrapper.update_subsystems) return wrapper
def _build_options(settings: QMSettings) -> PMEPsi4Options: """Build the PMEPsi4Options object. Args: settings: The settings used to build the Psi4 interface. Returns: The global options used by the QM/MM/PME-hacked Psi4 in each calculation. """ options = PMEPsi4Options( "default", settings.quadrature_spherical, settings.quadrature_radial, settings.scf_type, "uks" if settings.spin > 1 else "rks", "read" if settings.read_guess else "auto", "true", ) return options