Source code for pydft_qmmm.plugins.rigid.rigid
"""Plugins for implementing stationary or rigid-body residues.
"""
from __future__ import annotations
from typing import Callable
from typing import TYPE_CHECKING
import numpy as np
from numpy.typing import NDArray
from pydft_qmmm.plugins.plugin import IntegratorPlugin
if TYPE_CHECKING:
from pydft_qmmm.integrators import Returns
from pydft_qmmm.integrators import Integrator
from pydft_qmmm import System
[docs]
class Stationary(IntegratorPlugin):
"""Keep select residues stationary during integration.
Args:
query: The VMD-like selection query which corresponds to
residues that should be kept stationary during integration.
"""
def __init__(
self,
query: str,
) -> None:
self.query = query
[docs]
def modify(
self,
integrator: Integrator,
) -> None:
"""Modify the functionality of an integrator.
Args:
integrator: The integrator whose functionality will be
modified by the plugin.
"""
self._modifieds.append(type(integrator).__name__)
self.integrator = integrator
integrator.integrate = self._modify_integrate(integrator.integrate)
integrator.compute_kinetic_energy = self._modify_compute_kinetic_energy(
integrator.compute_kinetic_energy,
)
[docs]
def constrain_velocities(self, system: System) -> NDArray[np.float64]:
"""Zero velocities for stationary residues.
Args:
system: The system with stationary residues.
Returns:
New velocities which result from zeroing the system
velocities of stationary residues.
"""
velocities = system.velocities
atoms = sorted(system.select(self.query))
velocities[atoms, :] = 0
return velocities
def _modify_integrate(
self,
integrate: Callable[[System], Returns],
) -> Callable[[System], Returns]:
"""Modify the integrate routine to stop stationary residues.
Args:
integrate: The integration routine to modify.
Returns:
The modified integration routine which keeps stationary
residues in place.
"""
def inner(system: System) -> Returns:
positions, velocities = integrate(system)
atoms = sorted(system.select(self.query))
positions[atoms, :] = system.positions[atoms, :]
velocities[atoms, :] = 0.
return positions, velocities
return inner
def _modify_compute_kinetic_energy(
self,
compute_kinetic_energy: Callable[[System], float],
) -> Callable[[System], float]:
"""Modify the kinetic energy computation for stationary residues.
Args:
compute_kinetic_energy: The kinetic energy routine to
modify.
Returns:
The modified kinetic energy routine which zeros stationary
residue velocities before the energy calculation.
"""
def inner(system: System) -> float:
masses = system.masses.reshape(-1, 1)
velocities = (
system.velocities
+ (
0.5*self.integrator.timestep
* system.forces*(10**-4)/masses
)
)
atoms = sorted(system.select(self.query))
velocities[atoms, :] = 0.
kinetic_energy = (
np.sum(0.5*masses*(velocities)**2)
* (10**4)
)
return kinetic_energy
return inner
[docs]
class RigidBody(IntegratorPlugin):
"""Apply rigid-body dynamics to select residues during integration.
Args:
query: The VMD-like selection query which corresponds to
residues that should be kept rigid during integration.
"""
def __init__(self, query: str) -> None:
raise NotImplementedError
[docs]
def modify(
self,
integrator: Integrator,
) -> None:
"""Modify the functionality of an integrator.
Args:
integrator: The integrator whose functionality will be
modified by the plugin.
"""
pass