Skip to content

Engine Base Class

base

Abstract base classes for QM and MM engine backends.

QMEngine

Bases: ABC

Abstract base class for quantum mechanics engines.

All QM backends (Psi4, Gaussian, ORCA, etc.) must implement this interface.

name abstractmethod property

name: str

Human-readable engine name.

Returns:

Name Type Description
str str

Engine display name (e.g. "Psi4 (b3lyp/def2-svp)").

energy abstractmethod

energy(structure: Q2MMMolecule, method: str = 'b3lyp', basis: str = 'def2-svp') -> float

Calculate single-point energy in Hartrees.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
method str

QM method or functional (e.g. "b3lyp", "mp2").

'b3lyp'
basis str

Basis set name (e.g. "def2-svp", "6-31+G(d)").

'def2-svp'

Returns:

Type Description
float

Electronic energy in Hartrees.

Source code in q2mm/backends/base.py
@abstractmethod
def energy(self, structure: Q2MMMolecule, method: str = "b3lyp", basis: str = "def2-svp") -> float:
    """Calculate single-point energy in Hartrees.

    Args:
        structure: Molecular structure.
        method: QM method or functional (e.g. ``"b3lyp"``, ``"mp2"``).
        basis: Basis set name (e.g. ``"def2-svp"``, ``"6-31+G(d)"``).

    Returns:
        Electronic energy in Hartrees.
    """
    ...

hessian abstractmethod

hessian(structure: Q2MMMolecule, method: str = 'b3lyp', basis: str = 'def2-svp') -> ndarray

Calculate Hessian matrix (second derivatives of energy).

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
method str

QM method or functional.

'b3lyp'
basis str

Basis set name.

'def2-svp'

Returns:

Type Description
ndarray

Shape (3N, 3N) Hessian in Hartree/Bohr² (atomic units).

Source code in q2mm/backends/base.py
@abstractmethod
def hessian(self, structure: Q2MMMolecule, method: str = "b3lyp", basis: str = "def2-svp") -> np.ndarray:
    """Calculate Hessian matrix (second derivatives of energy).

    Args:
        structure: Molecular structure.
        method: QM method or functional.
        basis: Basis set name.

    Returns:
        Shape ``(3N, 3N)`` Hessian in **Hartree/Bohr²** (atomic units).
    """
    ...

optimize abstractmethod

optimize(structure: Q2MMMolecule, method: str = 'b3lyp', basis: str = 'def2-svp') -> tuple

Optimize geometry.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
method str

QM method or functional.

'b3lyp'
basis str

Basis set name.

'def2-svp'

Returns:

Type Description
tuple

Optimized structure as (energy, atoms, coordinates).

Source code in q2mm/backends/base.py
@abstractmethod
def optimize(self, structure: Q2MMMolecule, method: str = "b3lyp", basis: str = "def2-svp") -> tuple:
    """Optimize geometry.

    Args:
        structure: Molecular structure.
        method: QM method or functional.
        basis: Basis set name.

    Returns:
        Optimized structure as ``(energy, atoms, coordinates)``.
    """
    ...

frequencies abstractmethod

frequencies(structure: Q2MMMolecule, method: str = 'b3lyp', basis: str = 'def2-svp') -> list[float]

Calculate vibrational frequencies in cm⁻¹.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
method str

QM method or functional.

'b3lyp'
basis str

Basis set name.

'def2-svp'

Returns:

Type Description
list[float]

Vibrational frequencies in cm⁻¹.

Source code in q2mm/backends/base.py
@abstractmethod
def frequencies(self, structure: Q2MMMolecule, method: str = "b3lyp", basis: str = "def2-svp") -> list[float]:
    """Calculate vibrational frequencies in cm⁻¹.

    Args:
        structure: Molecular structure.
        method: QM method or functional.
        basis: Basis set name.

    Returns:
        Vibrational frequencies in cm⁻¹.
    """
    ...

is_available

is_available() -> bool

Check if this engine is installed and accessible.

Returns:

Name Type Description
bool bool

True if the engine binary or library can be located.

Source code in q2mm/backends/base.py
def is_available(self) -> bool:
    """Check if this engine is installed and accessible.

    Returns:
        bool: ``True`` if the engine binary or library can be located.
    """
    return False

supports_runtime_params

supports_runtime_params() -> bool

Whether parameters can be updated without rebuilding engine state.

Returns:

Name Type Description
bool bool

True if the engine supports in-place parameter updates.

Source code in q2mm/backends/base.py
def supports_runtime_params(self) -> bool:
    """Whether parameters can be updated without rebuilding engine state.

    Returns:
        bool: ``True`` if the engine supports in-place parameter updates.
    """
    return False

MMEngine

Bases: ABC

Abstract base class for molecular mechanics engines.

All MM backends (Tinker, OpenMM, MacroModel, etc.) must implement this interface.

Unit contracts (canonical units for ForceField parameters):

  • bond_k: kcal/(mol·Å²) — energy convention E = k·(r − r₀)²
  • angle_k: kcal/(mol·rad²)
  • torsion_k, vdw_epsilon: kcal/mol
  • bond_eq, vdw_radius: Å
  • angle_eq: degrees

Engines convert from canonical units to engine-native at the boundary (e.g. kcal → kJ for OpenMM, Å → nm). Output contracts:

  • energy() returns kcal/mol
  • hessian() returns Hartree/Bohr² (atomic units)
  • frequencies() returns cm⁻¹

name abstractmethod property

name: str

Human-readable engine name.

Returns:

Name Type Description
str str

Engine display name (e.g. "OpenMM", "Tinker").

energy abstractmethod

energy(structure: Q2MMMolecule, forcefield: ForceField) -> float

Calculate MM energy in kcal/mol.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure. Concrete engines may widen this to accept engine-specific handles (e.g. OpenMMHandle) per the Liskov Substitution Principle.

required
forcefield ForceField

Force field parameters.

required

Returns:

Type Description
float

Potential energy in kcal/mol.

Source code in q2mm/backends/base.py
@abstractmethod
def energy(self, structure: Q2MMMolecule, forcefield: ForceField) -> float:
    """Calculate MM energy in kcal/mol.

    Args:
        structure: Molecular structure.  Concrete engines may widen
            this to accept engine-specific handles (e.g.
            ``OpenMMHandle``) per the Liskov Substitution Principle.
        forcefield: Force field parameters.

    Returns:
        Potential energy in kcal/mol.
    """
    ...

minimize abstractmethod

minimize(structure: Q2MMMolecule, forcefield: ForceField) -> tuple

Energy-minimize structure.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
forcefield ForceField

Force field parameters.

required

Returns:

Type Description
tuple

(energy, atoms, coordinates) tuple.

Source code in q2mm/backends/base.py
@abstractmethod
def minimize(self, structure: Q2MMMolecule, forcefield: ForceField) -> tuple:
    """Energy-minimize structure.

    Args:
        structure: Molecular structure.
        forcefield: Force field parameters.

    Returns:
        ``(energy, atoms, coordinates)`` tuple.
    """
    ...

hessian abstractmethod

hessian(structure: Q2MMMolecule, forcefield: ForceField) -> ndarray

Calculate MM Hessian matrix.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
forcefield ForceField

Force field parameters.

required

Returns:

Type Description
ndarray

Shape (3N, 3N) Hessian in Hartree/Bohr² (atomic units).

Source code in q2mm/backends/base.py
@abstractmethod
def hessian(self, structure: Q2MMMolecule, forcefield: ForceField) -> np.ndarray:
    """Calculate MM Hessian matrix.

    Args:
        structure: Molecular structure.
        forcefield: Force field parameters.

    Returns:
        Shape ``(3N, 3N)`` Hessian in **Hartree/Bohr²** (atomic units).
    """
    ...

frequencies abstractmethod

frequencies(structure: Q2MMMolecule, forcefield: ForceField) -> list[float]

Calculate vibrational frequencies in cm⁻¹.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
forcefield ForceField

Force field parameters.

required

Returns:

Type Description
list[float]

Vibrational frequencies in cm⁻¹.

Source code in q2mm/backends/base.py
@abstractmethod
def frequencies(self, structure: Q2MMMolecule, forcefield: ForceField) -> list[float]:
    """Calculate vibrational frequencies in cm⁻¹.

    Args:
        structure: Molecular structure.
        forcefield: Force field parameters.

    Returns:
        Vibrational frequencies in cm⁻¹.
    """
    ...

is_available

is_available() -> bool

Check if this engine is installed and accessible.

Returns:

Name Type Description
bool bool

True if the engine binary or library can be located.

Source code in q2mm/backends/base.py
def is_available(self) -> bool:
    """Check if this engine is installed and accessible.

    Returns:
        bool: ``True`` if the engine binary or library can be located.
    """
    return False

supports_runtime_params

supports_runtime_params() -> bool

Whether parameters can be updated without rebuilding engine state.

Returns:

Name Type Description
bool bool

True if the engine supports in-place parameter updates.

Source code in q2mm/backends/base.py
def supports_runtime_params(self) -> bool:
    """Whether parameters can be updated without rebuilding engine state.

    Returns:
        bool: ``True`` if the engine supports in-place parameter updates.
    """
    return False

supports_analytical_gradients

supports_analytical_gradients() -> bool

Whether this engine provides analytical parameter gradients.

Engines returning True must implement energy_and_param_grad().

Returns:

Name Type Description
bool bool

True if the engine provides analytical parameter gradients.

Source code in q2mm/backends/base.py
def supports_analytical_gradients(self) -> bool:
    """Whether this engine provides analytical parameter gradients.

    Engines returning ``True`` must implement ``energy_and_param_grad()``.

    Returns:
        bool: ``True`` if the engine provides analytical parameter gradients.
    """
    return False

energy_and_param_grad

energy_and_param_grad(structure: Q2MMMolecule, forcefield: ForceField) -> tuple[float, ndarray]

Compute energy and analytical gradient w.r.t. MM parameters.

Must be implemented by engines for which :meth:supports_analytical_gradients returns True.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure or engine-specific context.

required
forcefield ForceField

Force field parameters.

required

Returns:

Type Description
float

(energy, grad) where energy is the MM energy in

ndarray

kcal/mol and grad is a 1-D array of dE/dp derivatives.

Raises:

Type Description
NotImplementedError

If the engine does not support analytical gradients.

Source code in q2mm/backends/base.py
def energy_and_param_grad(self, structure: Q2MMMolecule, forcefield: ForceField) -> tuple[float, np.ndarray]:
    """Compute energy and analytical gradient w.r.t. MM parameters.

    Must be implemented by engines for which
    :meth:`supports_analytical_gradients` returns ``True``.

    Args:
        structure: Molecular structure or engine-specific context.
        forcefield: Force field parameters.

    Returns:
        ``(energy, grad)`` where ``energy`` is the MM energy in
        kcal/mol and ``grad`` is a 1-D array of ``dE/dp`` derivatives.

    Raises:
        NotImplementedError: If the engine does not support analytical
            gradients.
    """
    raise NotImplementedError(
        f"{self.name} does not implement energy_and_param_grad(). "
        "Override this method when supports_analytical_gradients() returns True."
    )

create_context

create_context(structure: Q2MMMolecule, forcefield: ForceField) -> object

Create a reusable engine context/handle for a molecule.

Only needed when :meth:supports_runtime_params returns True. The returned handle can be passed as structure to other methods, allowing the engine to update parameters in-place rather than rebuilding the simulation state each evaluation.

Parameters:

Name Type Description Default
structure Q2MMMolecule

Molecular structure.

required
forcefield ForceField

Force field parameters.

required

Returns:

Type Description
object

An engine-specific handle object for reuse across evaluations.

Raises:

Type Description
NotImplementedError

If the engine does not support reusable contexts.

Source code in q2mm/backends/base.py
def create_context(self, structure: Q2MMMolecule, forcefield: ForceField) -> object:
    """Create a reusable engine context/handle for a molecule.

    Only needed when :meth:`supports_runtime_params` returns ``True``.
    The returned handle can be passed as ``structure`` to other methods,
    allowing the engine to update parameters in-place rather than
    rebuilding the simulation state each evaluation.

    Args:
        structure: Molecular structure.
        forcefield: Force field parameters.

    Returns:
        An engine-specific handle object for reuse across evaluations.

    Raises:
        NotImplementedError: If the engine does not support reusable
            contexts.
    """
    raise NotImplementedError(
        f"{self.name} does not support reusable contexts. "
        "Override create_context() if supports_runtime_params() returns True."
    )

supported_functional_forms

supported_functional_forms() -> frozenset[str]

Functional forms this engine can evaluate.

Override in subclasses; the default is all forms (no restriction).

Returns:

Type Description
frozenset[str]

frozenset[str]: Set of :class:~q2mm.models.forcefield.FunctionalForm values (as strings).

Example

.. code-block:: python

# OpenMM supports both harmonic and MM3:
return frozenset({"harmonic", "mm3"})

# A future AMOEBA-only engine:
return frozenset({"amoeba"})
Source code in q2mm/backends/base.py
def supported_functional_forms(self) -> frozenset[str]:
    """Functional forms this engine can evaluate.

    Override in subclasses; the default is all forms (no restriction).

    Returns:
        frozenset[str]: Set of
            :class:`~q2mm.models.forcefield.FunctionalForm` values
            (as strings).

    Example:
        .. code-block:: python

            # OpenMM supports both harmonic and MM3:
            return frozenset({"harmonic", "mm3"})

            # A future AMOEBA-only engine:
            return frozenset({"amoeba"})
    """
    from q2mm.models.forcefield import FunctionalForm

    return frozenset(f.value for f in FunctionalForm)