Source code for pydft_qmmm.integrators.langevin_integrator
"""An integrator implementing the Langevin algorithm.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
import numpy as np
from .integrator import Integrator
from pydft_qmmm.common import KB
if TYPE_CHECKING:
from pydft_qmmm import System
from .integrator import Returns
[docs]
@dataclass
class LangevinIntegrator(Integrator):
r"""An integrator implementing the Leapfrog Verlet algorithm.
Args:
timestep: The timestep (:math:`\mathrm{fs}`) used to perform
integrations.
temperature: The temperature (:math:`\mathrm{K}`) of the bath
used to couple to the system.
friction: The friction (:math:`\mathrm{fs^{-1}}`) experienced
by particles in the system.
"""
timestep: float | int
temperature: int | float
friction: int | float
[docs]
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.
.. note:: Based on the implementation of the integrator
kernels from OpenMM.
"""
masses = system.masses.reshape((-1, 1))
vel_scale = np.exp(-self.timestep*self.friction)
frc_scale = (
self.timestep
if self.friction == 0
else (1 - vel_scale)/self.friction
)
noi_scale = (KB*self.temperature*(1 - vel_scale**2)*1000)**0.5
z = np.random.standard_normal((len(masses), 3))
momenta = system.velocities*masses
momenta = (
vel_scale*momenta
+ frc_scale*system.forces*(10**-4)
+ noi_scale*(10**-5)*z*masses**0.5
)
final_positions = (
system.positions
+ self.timestep*momenta/masses
)
final_velocities = momenta/masses
return final_positions, final_velocities