Example #1
0
class TestAmoebaWater6(ForceBalanceTestCase):
    """ AMOEBA unit test consisting of a water hexamer.  The test
    checks for whether the OpenMM and TINKER Engines produce
    consistent results for:

    1) Single-point energy and force
    2) Minimized energies and RMSD from the initial geometry
    3) Interaction energies between two groups of molecules
    4) Multipole moments
    5) Multipole moments after geometry optimization

    Due to careful validation of OpenMM, the results agree with TINKER
    to within very stringent criteria.  Residual errors are as follows:

    Potential energies: <0.001 kJ/mol (<1e-5 fractional error)
    Forces: <0.01 kJ/mol/nm (<1e-4 fractional error)
    Energy of optimized geometry: < 0.0001 kcal/mol
    RMSD from starting structure: < 0.001 Angstrom
    Interaction energies: < 0.0001 kcal/mol
    Multipole moments: < 0.001 Debye / Debye Angstrom
    Multipole moments (optimized): < 0.01 Debye / Debye Angstrom
    """
    def setUp(self):
        self.logger.debug("\nBuilding options for target...\n")
        self.cwd = os.getcwd()
        os.chdir(os.path.join(os.getcwd(), "test", "files", "amoeba_h2o6"))
        if not os.path.exists("temp"): os.makedirs("temp")
        os.chdir("temp")
        os.system("ln -s ../prism.pdb")
        os.system("ln -s ../prism.key")
        os.system("ln -s ../hex.arc")
        os.system("ln -s ../water.prm")
        os.system("ln -s ../amoebawater.xml")
        self.O = OpenMM(coords="hex.arc", pdb="prism.pdb", ffxml="amoebawater.xml", precision="double", \
                            mmopts={'rigidWater':False, 'mutualInducedTargetEpsilon':1e-6})
        tinkerpath = which('testgrad')
        if (which('testgrad') != ''):
            self.T = TINKER(coords="hex.arc",
                            tinker_key="prism.key",
                            tinkerpath=tinkerpath)
        os.chdir("..")
        self.addCleanup(os.system, 'rm -rf temp')

    def test_energy_force(self):
        """ Test OpenMM and TINKER energy and forces with AMOEBA force field """
        printcool("Testing OpenMM and TINKER energy and force with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        EF_O = self.O.energy_force()[0]
        EF_T = self.T.energy_force()[0]
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine',
                               self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_energy_force.dat')
            if not os.path.exists(os.path.dirname(fout)):
                os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, EF_T)
        EF_R = np.loadtxt(os.path.join(datadir, 'test_energy_force.dat'))
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct AMOEBA energy to within 0.001 kJ\n"
        )
        self.assertAlmostEqual(
            EF_O[0],
            EF_R[0],
            msg="OpenMM energy does not match the reference",
            delta=0.001)
        self.assertAlmostEqual(
            EF_T[0],
            EF_R[0],
            msg="TINKER energy does not match the reference",
            delta=0.001)
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct AMOEBA force to within 0.01 kJ/mol/nm\n"
        )
        self.assertNdArrayEqual(EF_O[1:],
                                EF_R[1:],
                                msg="OpenMM forces do not match the reference",
                                delta=0.01)
        self.assertNdArrayEqual(EF_T[1:],
                                EF_R[1:],
                                msg="TINKER forces do not match the reference",
                                delta=0.01)

    def test_energy_rmsd(self):
        """ Test OpenMM and TINKER optimized geometries with AMOEBA force field """
        self.skipTest("Need to reduce dependence on the TINKER build")
        printcool("Testing OpenMM and TINKER optimized geometry with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        EO, RO = self.O.energy_rmsd()
        ET, RT = self.T.energy_rmsd()
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine',
                               self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_energy_rmsd.dat')
            if not os.path.exists(os.path.dirname(fout)):
                os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, np.array([ET, RT]))
        RefData = os.path.join(datadir, 'test_energy_rmsd.dat')
        ERef = RefData[0]
        RRef = RefData[1]
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct minimized energy to within 0.0001 kcal\n"
        )
        self.assertAlmostEqual(
            EO,
            ERef,
            msg="OpenMM minimized energy does not match the reference",
            delta=0.0001)
        self.assertAlmostEqual(
            ET,
            ERef,
            msg="TINKER minimized energy does not match the reference",
            delta=0.0001)
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct RMSD to starting structure\n"
        )
        self.assertAlmostEqual(RO,
                               RRef,
                               msg="OpenMM RMSD does not match the reference",
                               delta=0.001)
        self.assertAlmostEqual(RT,
                               RRef,
                               msg="TINKER RMSD does not match the reference",
                               delta=0.001)

    def test_interaction_energy(self):
        """ Test OpenMM and TINKER interaction energies with AMOEBA force field """
        printcool("Testing OpenMM and TINKER interaction energy with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        IO = self.O.interaction_energy(fraga=range(9), fragb=range(9, 18))
        IT = self.T.interaction_energy(fraga=range(9), fragb=range(9, 18))
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine',
                               self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_interaction_energy.dat')
            if not os.path.exists(os.path.dirname(fout)):
                os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, np.array([IT]))
        IR = np.loadtxt(os.path.join(datadir, 'test_interaction_energy.dat'))
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct interaction energy\n"
        )
        self.assertAlmostEqual(
            IO,
            IR,
            msg="OpenMM interaction energies do not match the reference",
            delta=0.0001)
        self.assertAlmostEqual(
            IT,
            IR,
            msg="TINKER interaction energies do not match the reference",
            delta=0.0001)

    def test_multipole_moments(self):
        """ Test OpenMM and TINKER multipole moments with AMOEBA force field """
        printcool("Testing OpenMM and TINKER multipole moments with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        MO = self.O.multipole_moments(optimize=False)
        DO = np.array(MO['dipole'].values())
        QO = np.array(MO['quadrupole'].values())
        MT = self.T.multipole_moments(optimize=False)
        DT = np.array(MT['dipole'].values())
        QT = np.array(MT['quadrupole'].values())
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine',
                               self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_multipole_moments.dipole.dat')
            if not os.path.exists(os.path.dirname(fout)):
                os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, DT)
            fout = os.path.join(datadir,
                                'test_multipole_moments.quadrupole.dat')
            np.savetxt(fout, QT)
        DR = np.loadtxt(
            os.path.join(datadir, 'test_multipole_moments.dipole.dat'))
        QR = np.loadtxt(
            os.path.join(datadir, 'test_multipole_moments.quadrupole.dat'))
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct dipole\n")
        self.assertNdArrayEqual(
            DO,
            DR,
            msg="OpenMM dipoles do not match the reference",
            delta=0.001)
        self.assertNdArrayEqual(
            DT,
            DR,
            msg="TINKER dipoles do not match the reference",
            delta=0.001)
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct quadrupole\n")
        self.assertNdArrayEqual(
            QO,
            QR,
            msg="OpenMM quadrupoles do not match the reference",
            delta=0.001)
        self.assertNdArrayEqual(
            QT,
            QR,
            msg="TINKER quadrupoles do not match the reference",
            delta=0.001)

    def test_multipole_moments_optimized(self):
        """ Test OpenMM and TINKER multipole moments with AMOEBA force field """
        self.skipTest("Need to reduce dependence on the TINKER build")
        printcool("Testing OpenMM and TINKER multipole moments with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        MO1 = self.O.multipole_moments(optimize=True)
        DO1 = np.array(MO1['dipole'].values())
        QO1 = np.array(MO1['quadrupole'].values())
        MT1 = self.T.multipole_moments(optimize=True)
        DT1 = np.array(MT1['dipole'].values())
        QT1 = np.array(MT1['quadrupole'].values())
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine',
                               self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir,
                                'test_multipole_moments_optimized.dipole.dat')
            if not os.path.exists(os.path.dirname(fout)):
                os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, DT1)
            fout = os.path.join(
                datadir, 'test_multipole_moments_optimized.quadrupole.dat')
            np.savetxt(fout, QT1)
        DR1 = np.loadtxt(
            os.path.join(datadir,
                         'test_multipole_moments_optimized.dipole.dat'))
        QR1 = np.loadtxt(
            os.path.join(datadir,
                         'test_multipole_moments_optimized.quadrupole.dat'))
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct dipole when geometries are optimized\n"
        )
        self.assertNdArrayEqual(
            DO1,
            DR1,
            msg=
            "OpenMM dipoles do not match the reference when geometries are optimized",
            delta=0.001)
        self.assertNdArrayEqual(
            DT1,
            DR1,
            msg=
            "TINKER dipoles do not match the reference when geometries are optimized",
            delta=0.001)
        self.logger.debug(
            ">ASSERT OpenMM and TINKER Engines give the correct quadrupole when geometries are optimized\n"
        )
        self.assertNdArrayEqual(
            QO1,
            QR1,
            msg=
            "OpenMM quadrupoles do not match the reference when geometries are optimized",
            delta=0.01)
        self.assertNdArrayEqual(
            QT1,
            QR1,
            msg=
            "TINKER quadrupoles do not match the reference when geometries are optimized",
            delta=0.01)

    def shortDescription(self):
        """@override ForceBalanceTestCase.shortDescription()"""
        return super(TestAmoebaWater6,
                     self).shortDescription() + " (TINKER and OpenMM Engines)"
Example #2
0
class TestAmoebaWater6(ForceBalanceTestCase):

    """ AMOEBA unit test consisting of a water hexamer.  The test
    checks for whether the OpenMM and TINKER Engines produce
    consistent results for:

    1) Single-point energy and force
    2) Minimized energies and RMSD from the initial geometry
    3) Interaction energies between two groups of molecules
    4) Multipole moments
    5) Multipole moments after geometry optimization

    Due to careful validation of OpenMM, the results agree with TINKER
    to within very stringent criteria.  Residual errors are as follows:

    Potential energies: <0.001 kJ/mol (<1e-5 fractional error)
    Forces: <0.01 kJ/mol/nm (<1e-4 fractional error)
    Energy of optimized geometry: < 0.0001 kcal/mol
    RMSD from starting structure: < 0.001 Angstrom
    Interaction energies: < 0.0001 kcal/mol
    Multipole moments: < 0.001 Debye / Debye Angstrom
    Multipole moments (optimized): < 0.01 Debye / Debye Angstrom
    """

    def setUp(self):
        self.logger.debug("\nBuilding options for target...\n")
        self.cwd = os.getcwd()
        os.chdir(os.path.join(os.getcwd(), "test", "files", "amoeba_h2o6"))
        if not os.path.exists("temp"): os.makedirs("temp")
        os.chdir("temp")
        os.system("ln -s ../prism.pdb")
        os.system("ln -s ../prism.key")
        os.system("ln -s ../hex.arc")
        os.system("ln -s ../water.prm")
        os.system("ln -s ../amoebawater.xml")
        self.O = OpenMM(coords="hex.arc", pdb="prism.pdb", ffxml="amoebawater.xml", precision="double", \
                            mmopts={'rigidWater':False, 'mutualInducedTargetEpsilon':1e-6})
        tinkerpath=which('testgrad')
        if (which('testgrad') != ''):
            self.T = TINKER(coords="hex.arc", tinker_key="prism.key", tinkerpath=tinkerpath)
        os.chdir("..")
        self.addCleanup(os.system, 'rm -rf temp')

    def test_energy_force(self):
        """ Test OpenMM and TINKER energy and forces with AMOEBA force field """
        printcool("Testing OpenMM and TINKER energy and force with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        EF_O = self.O.energy_force()[0]
        EF_T = self.T.energy_force()[0]
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine', self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_energy_force.dat')
            if not os.path.exists(os.path.dirname(fout)): os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, EF_T)
        EF_R = np.loadtxt(os.path.join(datadir, 'test_energy_force.dat'))
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct AMOEBA energy to within 0.001 kJ\n")
        self.assertAlmostEqual(EF_O[0], EF_R[0], msg="OpenMM energy does not match the reference", delta=0.001)
        self.assertAlmostEqual(EF_T[0], EF_R[0], msg="TINKER energy does not match the reference", delta=0.001)
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct AMOEBA force to within 0.01 kJ/mol/nm\n")
        self.assertNdArrayEqual(EF_O[1:], EF_R[1:], msg="OpenMM forces do not match the reference", delta=0.01)
        self.assertNdArrayEqual(EF_T[1:], EF_R[1:], msg="TINKER forces do not match the reference", delta=0.01)

    def test_energy_rmsd(self):
        """ Test OpenMM and TINKER optimized geometries with AMOEBA force field """
        self.skipTest("Need to reduce dependence on the TINKER build")
        printcool("Testing OpenMM and TINKER optimized geometry with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        EO, RO = self.O.energy_rmsd()
        ET, RT = self.T.energy_rmsd()
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine', self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_energy_rmsd.dat')
            if not os.path.exists(os.path.dirname(fout)): os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, np.array([ET, RT]))
        RefData = os.path.join(datadir, 'test_energy_rmsd.dat')
        ERef = RefData[0]
        RRef = RefData[1]
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct minimized energy to within 0.0001 kcal\n")
        self.assertAlmostEqual(EO, ERef, msg="OpenMM minimized energy does not match the reference", delta=0.0001)
        self.assertAlmostEqual(ET, ERef, msg="TINKER minimized energy does not match the reference", delta=0.0001)
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct RMSD to starting structure\n")
        self.assertAlmostEqual(RO, RRef, msg="OpenMM RMSD does not match the reference", delta=0.001)
        self.assertAlmostEqual(RT, RRef, msg="TINKER RMSD does not match the reference", delta=0.001)

    def test_interaction_energy(self):
        """ Test OpenMM and TINKER interaction energies with AMOEBA force field """
        printcool("Testing OpenMM and TINKER interaction energy with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        IO = self.O.interaction_energy(fraga=range(9), fragb=range(9, 18))
        IT = self.T.interaction_energy(fraga=range(9), fragb=range(9, 18))
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine', self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_interaction_energy.dat')
            if not os.path.exists(os.path.dirname(fout)): os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, np.array([IT]))
        IR = np.loadtxt(os.path.join(datadir, 'test_interaction_energy.dat'))
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct interaction energy\n")
        self.assertAlmostEqual(IO, IR, msg="OpenMM interaction energies do not match the reference", delta=0.0001)
        self.assertAlmostEqual(IT, IR, msg="TINKER interaction energies do not match the reference", delta=0.0001)

    def test_multipole_moments(self):
        """ Test OpenMM and TINKER multipole moments with AMOEBA force field """
        printcool("Testing OpenMM and TINKER multipole moments with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        MO = self.O.multipole_moments(optimize=False)
        DO = np.array(MO['dipole'].values())
        QO = np.array(MO['quadrupole'].values())
        MT = self.T.multipole_moments(optimize=False)
        DT = np.array(MT['dipole'].values())
        QT = np.array(MT['quadrupole'].values())
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine', self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_multipole_moments.dipole.dat')
            if not os.path.exists(os.path.dirname(fout)): os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, DT)
            fout = os.path.join(datadir, 'test_multipole_moments.quadrupole.dat')
            np.savetxt(fout, QT)
        DR = np.loadtxt(os.path.join(datadir, 'test_multipole_moments.dipole.dat'))
        QR = np.loadtxt(os.path.join(datadir, 'test_multipole_moments.quadrupole.dat'))
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct dipole\n")
        self.assertNdArrayEqual(DO, DR, msg="OpenMM dipoles do not match the reference", delta=0.001)
        self.assertNdArrayEqual(DT, DR, msg="TINKER dipoles do not match the reference", delta=0.001)
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct quadrupole\n")
        self.assertNdArrayEqual(QO, QR, msg="OpenMM quadrupoles do not match the reference", delta=0.001)
        self.assertNdArrayEqual(QT, QR, msg="TINKER quadrupoles do not match the reference", delta=0.001)

    def test_multipole_moments_optimized(self):
        """ Test OpenMM and TINKER multipole moments with AMOEBA force field """
        self.skipTest("Need to reduce dependence on the TINKER build")
        printcool("Testing OpenMM and TINKER multipole moments with AMOEBA")
        os.chdir("temp")
        if not hasattr(self, 'T'):
            self.skipTest("TINKER programs are not in the PATH.")
        MO1 = self.O.multipole_moments(optimize=True)
        DO1 = np.array(MO1['dipole'].values())
        QO1 = np.array(MO1['quadrupole'].values())
        MT1 = self.T.multipole_moments(optimize=True)
        DT1 = np.array(MT1['dipole'].values())
        QT1 = np.array(MT1['quadrupole'].values())
        os.chdir("..")
        datadir = os.path.join(sys.path[0], 'files', 'test_engine', self.__class__.__name__)
        if SAVEDATA:
            fout = os.path.join(datadir, 'test_multipole_moments_optimized.dipole.dat')
            if not os.path.exists(os.path.dirname(fout)): os.makedirs(os.path.dirname(fout))
            np.savetxt(fout, DT1)
            fout = os.path.join(datadir, 'test_multipole_moments_optimized.quadrupole.dat')
            np.savetxt(fout, QT1)
        DR1 = np.loadtxt(os.path.join(datadir, 'test_multipole_moments_optimized.dipole.dat'))
        QR1 = np.loadtxt(os.path.join(datadir, 'test_multipole_moments_optimized.quadrupole.dat'))
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct dipole when geometries are optimized\n")
        self.assertNdArrayEqual(DO1, DR1, msg="OpenMM dipoles do not match the reference when geometries are optimized", delta=0.001)
        self.assertNdArrayEqual(DT1, DR1, msg="TINKER dipoles do not match the reference when geometries are optimized", delta=0.001)
        self.logger.debug(">ASSERT OpenMM and TINKER Engines give the correct quadrupole when geometries are optimized\n")
        self.assertNdArrayEqual(QO1, QR1, msg="OpenMM quadrupoles do not match the reference when geometries are optimized", delta=0.01)
        self.assertNdArrayEqual(QT1, QR1, msg="TINKER quadrupoles do not match the reference when geometries are optimized", delta=0.01)

    def shortDescription(self):
        """@override ForceBalanceTestCase.shortDescription()"""
        return super(TestAmoebaWater6,self).shortDescription() + " (TINKER and OpenMM Engines)"