Source code for meld.runner.transform.restraints.confinement
#
# All rights reserved
#
"""
This module implements transformers that add confinement restraints
"""
import logging
from typing import List
import openmm as mm # type: ignore
from openmm import app # type: ignore
from meld import interfaces
from meld.runner import transform
from meld.runner.transform.restraints.util import _delete_from_always_active
from meld.system import density, mapping, options, param_sampling, restraints
logger = logging.getLogger(__name__)
FORCE_GROUP = 3
[docs]class ConfinementRestraintTransformer(transform.TransformerBase):
"""
Transformer to handle confinement restraints
"""
force: mm.CustomExternalForce
[docs] def __init__(
self,
param_manager: param_sampling.ParameterManager,
mapper: mapping.PeakMapManager,
density_manager: density.DensityManager,
builder_info: dict,
options: options.RunOptions,
always_active_restraints: List[restraints.Restraint],
selectively_active_restraints: List[restraints.SelectivelyActiveCollection],
) -> None:
self.use_pbc = builder_info.get("solvation", "implicit") == "explicit"
self.restraints = [
r
for r in always_active_restraints
if isinstance(r, restraints.ConfinementRestraint)
]
_delete_from_always_active(self.restraints, always_active_restraints)
if self.restraints:
self.active = True
else:
self.active = False
[docs] def add_interactions(
self, state: interfaces.IState, system: mm.System, topology: app.Topology
) -> mm.System:
if self.active:
# create the confinement force
if self.use_pbc:
confinement_force = mm.CustomExternalForce(
"step(r - radius) * force_const * (radius - r)^2;"
"r = periodicdistance(x, y, z, 0, 0 ,0)"
)
else:
confinement_force = mm.CustomExternalForce(
"step(r - radius) * force_const * (radius - r)^2;"
"r=sqrt(x*x + y*y + z*z)"
)
confinement_force.addPerParticleParameter("radius")
confinement_force.addPerParticleParameter("force_const")
# add the atoms
for r in self.restraints:
weight = r.force_const
confinement_force.addParticle(r.atom_index, [r.radius, weight])
confinement_force.setForceGroup(FORCE_GROUP)
system.addForce(confinement_force)
self.force = confinement_force
return system
[docs] def update(
self,
state: interfaces.IState,
simulation: app.Simulation,
alpha: float,
timestep: int,
) -> None:
if self.active:
for index, r in enumerate(self.restraints):
weight = r.force_const * r.scaler(alpha) * r.ramp(timestep)
self.force.setParticleParameters(
index, r.atom_index, [r.radius, weight]
)
self.force.updateParametersInContext(simulation.context)