| |
|
| | import numpy as np |
| | import openmm.unit as unit |
| | from abc import abstractmethod, ABC |
| | from scipy.constants import physical_constants |
| |
|
| |
|
| | class BaseDynamics(ABC): |
| | def __init__(self, args, state): |
| | super().__init__() |
| | self.start_file = f"./data/{args.molecule}/{state}.pdb" |
| | self.temperature = args.temperature * unit.kelvin |
| | self.friction = args.friction / unit.femtoseconds |
| | self.timestep = args.timestep * unit.femtoseconds |
| | self.pdb, self.integrator, self.simulation, self.external_force = self.setup() |
| | self.get_md_info() |
| | self.simulation.minimizeEnergy() |
| | self.position = self.report()[0] |
| |
|
| | @abstractmethod |
| | def setup(self): |
| | pass |
| |
|
| | def get_md_info(self): |
| | self.num_particles = self.simulation.system.getNumParticles() |
| | m = np.array([ |
| | self.simulation.system.getParticleMass(i).value_in_unit(unit.dalton) |
| | for i in range(self.num_particles) |
| | ]) |
| | self.heavy_atoms = m > 1.1 |
| | m = unit.Quantity(m, unit.dalton) |
| | unadjusted_variance = ( |
| | 2 * self.timestep * self.friction * unit.BOLTZMANN_CONSTANT_kB * self.temperature / m[:, None] |
| | ) |
| | std_SI_units = ( |
| | 1 / physical_constants["unified atomic mass unit"][0] * |
| | unadjusted_variance.value_in_unit(unit.joule / unit.dalton) |
| | ) |
| | self.std = unit.Quantity( |
| | np.sqrt(std_SI_units), unit.meter / unit.second |
| | ).value_in_unit(unit.nanometer / unit.femtosecond) |
| | self.m = m.value_in_unit(unit.dalton) |
| |
|
| | def step(self, forces): |
| | for i in range(forces.shape[0]): |
| | self.external_force.setParticleParameters(i, i, forces[i]) |
| | self.external_force.updateParametersInContext(self.simulation.context) |
| | self.simulation.step(1) |
| |
|
| | def report(self): |
| | state = self.simulation.context.getState(getPositions=True, getForces=True) |
| | positions = state.getPositions().value_in_unit(unit.nanometer) |
| | forces = state.getForces().value_in_unit( |
| | unit.dalton * unit.nanometer / unit.femtosecond ** 2 |
| | ) |
| | return positions, forces |
| |
|
| | def reset(self): |
| | for i in range(len(self.position)): |
| | self.external_force.setParticleParameters(i, i, [0, 0, 0]) |
| | self.external_force.updateParametersInContext(self.simulation.context) |
| | self.simulation.context.setPositions(self.position) |
| | self.simulation.context.setVelocitiesToTemperature(self.temperature) |
| |
|
| | def set_temperature(self, temperature): |
| | self.integrator.setTemperature(temperature * unit.kelvin) |
| |
|
| | def energy_function(self, positions): |
| | forces, potentials = [], [] |
| | for i in range(len(positions)): |
| | self.simulation.context.setPositions(positions[i]) |
| | state = self.simulation.context.getState(getForces=True, getEnergy=True) |
| | force = state.getForces().value_in_unit( |
| | unit.dalton * unit.nanometer / unit.femtosecond ** 2 |
| | ) |
| | potential = state.getPotentialEnergy().value_in_unit( |
| | unit.kilojoules / unit.mole |
| | ) |
| | forces.append(force) |
| | potentials.append(potential) |
| | return np.array(forces), np.array(potentials) |
| |
|