Source code for pydft_qmmm.integrators.integrator
"""The integrator base class.
"""
from __future__ import annotations
from abc import ABC
from abc import abstractmethod
from typing import TYPE_CHECKING
import numpy as np
from numpy.typing import NDArray
if TYPE_CHECKING:
from pydft_qmmm import System
from pydft_qmmm.plugins.plugin import IntegratorPlugin
Returns = tuple[NDArray[np.float64], NDArray[np.float64]]
[docs]
class Integrator(ABC):
r"""The abstract integrator base class.
Attributes:
_plugins: (class attribute) The list of plugin names that have
been registered to the integrator.
timestep: (class attribute) The timestep (:math:`\mathrm{fs}`)
used to perform integrations.
"""
_plugins: list[str] = []
timestep: float | int
[docs]
@abstractmethod
def integrate(self, system: System) -> Returns:
r"""Integrate forces into new positions and velocities.
Args:
system: The system whose forces
(:math:`\mathrm{kJ\;mol^{-1}\;\mathring{A}^{-1}}`) and existing
positions (:math:`\mathrm{\mathring{A}}`) and velocities
(:math:`\mathrm{\mathring{A}\;fs^{-1}}`) will be used to
determine new positions and velocities.
Returns:
New positions (:math:`\mathrm{\mathring{A}}`) and velocities
(:math:`\mathrm{\mathring{A}\;fs^{-1}}`) integrated from the forces
(:math:`\mathrm{kJ\;mol^{-1}\;\mathring{A}^{-1}}`) and existing
positions and velocities of the system.
"""
[docs]
def compute_kinetic_energy(self, system: System) -> float:
r"""Calculate kinetic energy via leapfrog algorithm.
Args:
system: The system whose forces
(:math:`\mathrm{kJ\;mol^{-1}\;\mathring{A}^{-1}}`) and existing
velocities (:math:`\mathrm{\mathring{A}\;fs^{-1}}`) will be used
to calculate the kinetic energy of the system.
Returns:
The kinetic energy (:math:`\mathrm{kJ\;mol^{-1}}`) of the
system.
.. note:: Based on the implementation of the kinetic energy
kernels from OpenMM.
"""
masses = system.masses.reshape(-1, 1)
velocities = (
system.velocities
+ (
0.5*self.timestep
* system.forces*(10**-4)/masses
)
)
kinetic_energy = np.sum(0.5*masses*(velocities)**2) * (10**4)
return kinetic_energy
[docs]
def register_plugin(self, plugin: IntegratorPlugin) -> None:
"""Record plugin name and apply the plugin to the integrator.
Args:
plugin: A plugin that will modify the behavior of one or
more integrator routines.
"""
self._plugins.append(type(plugin).__name__)
plugin.modify(self)
[docs]
def active_plugins(self) -> list[str]:
"""Get the current list of active plugins.
Returns:
A list of the active plugins registered by the integrator.
"""
return self._plugins