Thank you the reply on this.
You want to calculate an interaction between two molecules by identifying the very closest distance between them, right? Given all atoms in molecule 1 and all atoms in molecule 2, you want to find the very closest pair. And then you want to compute a function of that distance.
Correct, I also attach a diagram of a contrived example of what we hope to achieve with this.
The following code attempts to match what is going on in the diagram, but currently includes all pairwise interactions, hence the energy is 49.0 kJ/mol and not 16.0 kJ/mol.
Code: Select all
import simtk.openmm.app as app
import simtk.openmm as mm
import simtk.unit as unit
import simtk.openmm.vec3 as v
import sys
# Energy rule between two points
exampleCustomNonbondedForce = mm.CustomNonbondedForce("ssip1 * ssip2")
exampleCustomNonbondedForce.addPerParticleParameter("ssip")
# Set the nature of the Cutoff and its distance
exampleCustomNonbondedForce.setNonbondedMethod(mm.CustomNonbondedForce.CutoffNonPeriodic)
exampleCustomNonbondedForce.setCutoffDistance(20 * unit.angstrom)
system = mm.System()
topology = app.Topology()
newChain = topology.addChain()
for i in range(2):
system.addParticle(15.99943*unit.amu)
system.addParticle(1.007947*unit.amu)
system.addParticle(1.007947*unit.amu)
h2o = topology.addResidue("WAT", newChain)
topology.addAtom("O" , app.element.oxygen, h2o)
topology.addAtom("H1", app.element.hydrogen, h2o)
topology.addAtom("H2", app.element.hydrogen, h2o)
# Contrived SSIP terms for the example
exampleCustomNonbondedForce.addParticle([3])
exampleCustomNonbondedForce.addParticle([2])
exampleCustomNonbondedForce.addParticle([2])
# Exclude intra molecular terms
exampleCustomNonbondedForce.addExclusion(0,1)
exampleCustomNonbondedForce.addExclusion(0,2)
exampleCustomNonbondedForce.addExclusion(1,2)
exampleCustomNonbondedForce.addExclusion(3,4)
exampleCustomNonbondedForce.addExclusion(3,5)
exampleCustomNonbondedForce.addExclusion(4,5)
system.addForce(exampleCustomNonbondedForce)
# Checking
print("system.getNumParticles() is ", system.getNumParticles())
print("system.getNumForces() is ", system.getNumForces())
# Create Integrator and simulations
integrator = mm.VerletIntegrator(1 * unit.femtosecond)
simulation = app.Simulation(topology, system, integrator)
positions = [v.Vec3(x=-0.6197, y=-0.4387, z=0.0044), v.Vec3(x=-0.5227, y=-0.45439999999999997, z=0.0061), v.Vec3(x=-0.6508, y=-0.5183, z=-0.0414),
v.Vec3(x=-0.3885, y=-0.5031, z=0.0077), v.Vec3(x=-0.2502, y=-0.5304000000000001, z=-0.05310000000000001), v.Vec3(x=-0.49829999999999997, y=-0.5980000000000001, z=0.0054)]
simulation.context.setPositions(positions)
# Obtain the "energy"
print(simulation.context.getState(getEnergy=True).getPotentialEnergy())
# Saving minimised positions
positions = simulation.context.getState(getPositions=True).getPositions()
app.PDBFile.writeFile(simulation.topology, positions, open('wat.pdb', 'w'))
I also gather that you aren't trying to do dynamics? So you only need to compute energy, not force. Is all of that correct?
This is correct as well, only energy, which is being used as a score within a docking context. No forces, no dynamics.
As a complete aside, we also discovered
this paper in which they may be doing something similar via their reference of a "custom knowledge-based force object in OpenMM".
Thanks,
Mark