lambda.py
lambda.py
from Sire.IO import *
from Sire.Squire import *
from Sire.System import *
from Sire.MM import *
from Sire.Mol import *
from Sire.CAS import *
from Sire.Units import *
import os
import sys
# Get the name of the solute from the first
# command line argument (should be 'PHE' or 'TRP')
molname = sys.argv[1]
# Load the solute in a box of water, together with the
# information about the periodic box
(mols, space) = Amber().readCrdTop("%s.crd" % molname, "%s.top" % molname)
# pick out the solute from the box of molecules
mol = mols[ MolWithResID(molname) ].molecule()
# now get all of the waters (every molecule except the solute)
waters = mols.molecules()
waters.remove(mol)
# Set the cutoff distance as 10 angstroms
cutoff = HarmonicSwitchingFunction( 10 * angstrom )
# Create an MM forcefield to calculate the
# MM electrostatic energy between the solute and the waters
mmff = InterGroupCLJFF("mmff")
mmff.setSwitchingFunction(cutoff)
mmff.setSpace(space)
# Create a QM/MM forcefield to calculate the QM/MM
# electrostatic energy between the solute and the waters
qmmmff = QMMMFF("qmmmff")
qmmmff.setSwitchingFunction(cutoff)
qmmmff.setSpace(space)
qmmmff.setIntermolecularOnly(True)
# We will use the SQM program to calculate QM energies.
# Create the program and set the semi-empirical method
# from the passed string
qmprog = SQM()
qmprog.setMethod(sys.argv[2])
# Tell qmprog where to find the SQM executable
amberhome = os.getenv("AMBERHOME")
if amberhome is None:
print("Please set the AMBERHOME environment variable to point")
print("to the Amber14 installation.")
sys.exit(-1)
qmprog.setExecutable( "%s/bin/sqm" % amberhome )
# Tell the QM/MM forcefield to use this program
qmmmff.setQuantumProgram(qmprog)
# Now add the solute to group 0 of both forcefields
mmff.add( mol, MGIdx(0) )
qmmmff.add( mol, MGIdx(0) )
# Now add the waters to group 1 of both forcefields
mmff.add( waters, MGIdx(1) )
qmmmff.add( waters, MGIdx(1) )
# New stuff :-)
# we need a forcefield to hold the intermolecular
# energy between the water molecules
waterff = InterCLJFF("waterff")
waterff.setSwitchingFunction(cutoff)
waterff.setSpace(space)
waterff.add(waters)
# Now add all of the forcefields together into a single
# simulation system
system = System()
watergroup = MoleculeGroup("waters")
watergroup.add(waters)
system.add(watergroup)
system.add(mmff)
system.add(qmmmff)
system.add(waterff)
# Define the total MM energy
e_mm = Symbol("E_MM")
e_qmmm = Symbol("E_QMMM")
system.setComponent( e_mm, mmff.components().total() + \
waterff.components().total() )
system.setComponent( e_qmmm, qmmmff.components().total() + \
mmff.components().lj() + \
waterff.components().total() )
# Now define lambda - set it to 0
lam = Symbol("lambda")
system.setConstant(lam, 0)
# Now define the lambda scaled energy, such that
# it equals e_qmmm at lambda = 0, and e_mm at lambda = 1
e_lam = Symbol("E_lambda")
system.setComponent( e_lam, (1-lam)*e_qmmm + lam * e_mm )
# calculate the energy at the value of lambda supplied by the user
system.setConstant(lam, float(sys.argv[3]))
e_l = system.energy(e_lam)
print("\n%s %s" % (float(sys.argv[3]), e_l.value()))