Beispiel #1
0
class TestRPMD(ForceBalanceTestCase):

    """ RPMD unit test that runs a short RPMD simulation
    and compares calculated potential energies from
    MD with postprocessed potential energies as an
    internal consistency check.
    """

    def setUp(self):
        self.logger.debug('\nBuilding OpenMM engine...\n')
        os.chdir(os.path.join('test','files','rpmd_files'))
        openmm = False
        try:
            import simtk.openmm
            openmm = True
        except: logger.warn("OpenMM cannot be imported. Make sure it's installed!")
        print os.getcwd()        

        if openmm:
            self.ommEngine = OpenMM(ffxml='qtip4pf.xml', coords='liquid.pdb', pbc=True, platname='CUDA', precision='double')
             
    def test_rpmd_simulation(self):
        self.logger.debug('\nRunning MD...\n')
        if not os.path.exists('temp'): os.mkdir('temp')
        os.chdir('temp')
        # We're in the temp directory so need to copy the force field file here.
        shutil.copy2('../qtip4pf.xml','./qtip4pf.xml')
        self.addCleanup(os.system, 'cd .. ; rm -rf temp')

        MD_data = self.ommEngine.molecular_dynamics(nsteps=1000, nsave=100, timestep=0.5, temperature=300, pressure=1.0, verbose=False, save_traj=True, rpmd_opts=['32','9'])
        # Line below performs same MD run, but using verbose option
        #MD_data = self.ommEngine.molecular_dynamics(nsteps=1000, nsave=100, timestep=0.5, temperature=300, pressure=1.0, verbose=True, save_traj=True, rpmd_opts=['32','9'])
        postprocess_potentials = self.ommEngine.evaluate_(traj=self.ommEngine.xyz_rpmd, dipole=True)
        self.assertEqual(MD_data['Dips'].all(), postprocess_potentials['Dipole'].all())
        self.assertEqual(MD_data['Potentials'].all(), postprocess_potentials['Energy'].all())
Beispiel #2
0
 def setup_class(cls):
     """
     setup any state specific to the execution of the given class (which usually contains tests).
     """
     super(TestAmber99SB, cls).setup_class()
     tinkerpath = which('testgrad')
     # try to find mdrun_d or gmx_d
     # gmx should be built with config -DGMX_DOUBLE=ON
     gmxpath = which('mdrun_d') or which('gmx_d')
     gmxsuffix = '_d'
     # Tests will FAIL if use single precision gromacs
     # gmxpath = which('mdrun') or which('gmx')
     # gmxsuffix = ''
     # self.logger.debug("\nBuilding options for target...\n")
     cls.cwd = os.path.dirname(os.path.realpath(__file__))
     os.chdir(os.path.join(cls.cwd, "files", "amber_alaglu"))
     cls.tmpfolder = os.path.join(cls.cwd, "files", "amber_alaglu", "temp")
     if not os.path.exists(cls.tmpfolder):
         os.makedirs(cls.tmpfolder)
     os.chdir(cls.tmpfolder)
     for i in [
             "topol.top", "shot.mdp", "a99sb.xml", "a99sb.prm", "all.gro",
             "all.arc", "AceGluNme.itp", "AceAlaNme.itp", "a99sb.itp"
     ]:
         os.system("ln -fs ../%s" % i)
     cls.engines = OrderedDict()
     # Set up GMX engine
     if gmxpath != '':
         cls.engines['GMX'] = GMX(coords="all.gro",
                                  gmx_top="topol.top",
                                  gmx_mdp="shot.mdp",
                                  gmxpath=gmxpath,
                                  gmxsuffix=gmxsuffix)
     else:
         logger.warn("GROMACS cannot be found, skipping GMX tests.")
     # Set up TINKER engine
     if tinkerpath != '':
         cls.engines['TINKER'] = TINKER(coords="all.arc",
                                        tinker_key="alaglu.key",
                                        tinkerpath=tinkerpath)
     else:
         logger.warn("TINKER cannot be found, skipping TINKER tests.")
     # Set up OpenMM engine
     try:
         try:
             import openmm
         except ImportError:
             import simtk.openmm
         cls.engines['OpenMM'] = OpenMM(coords="all.gro",
                                        pdb="conf.pdb",
                                        ffxml="a99sb.xml",
                                        platname="Reference",
                                        precision="double")
     except:
         logger.warn("OpenMM cannot be imported, skipping OpenMM tests.")
 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')
Beispiel #4
0
    def setUp(self):
        self.logger.debug('\nBuilding OpenMM engine...\n')
        os.chdir(os.path.join('test','files','rpmd_files'))
        openmm = False
        try:
            import simtk.openmm
            openmm = True
        except: logger.warn("OpenMM cannot be imported. Make sure it's installed!")
        print os.getcwd()        

        if openmm:
            self.ommEngine = OpenMM(ffxml='qtip4pf.xml', coords='liquid.pdb', pbc=True, platname='CUDA', precision='double')
 def setUp(self):
     tinkerpath = which('testgrad')
     gmxsuffix = '_d'
     gmxpath = which('mdrun' + gmxsuffix)
     self.logger.debug("\nBuilding options for target...\n")
     self.cwd = os.getcwd()
     os.chdir(os.path.join(os.getcwd(), "test", "files", "amber_alaglu"))
     if not os.path.exists("temp"): os.makedirs("temp")
     os.chdir("temp")
     for i in [
             "topol.top", "shot.mdp", "a99sb.xml", "a99sb.prm", "all.gro",
             "all.arc", "AceGluNme.itp", "AceAlaNme.itp", "a99sb.itp"
     ]:
         os.system("ln -fs ../%s" % i)
     self.engines = OrderedDict()
     # Set up GMX engine
     if gmxpath != '':
         self.engines['GMX'] = GMX(coords="all.gro",
                                   gmx_top="topol.top",
                                   gmx_mdp="shot.mdp",
                                   gmxpath=gmxpath,
                                   gmxsuffix=gmxsuffix)
     else:
         logger.warn("GROMACS cannot be found, skipping GMX tests.")
     # Set up TINKER engine
     if tinkerpath != '':
         self.engines['TINKER'] = TINKER(coords="all.arc",
                                         tinker_key="alaglu.key",
                                         tinkerpath=tinkerpath)
     else:
         logger.warn("TINKER cannot be found, skipping TINKER tests.")
     # Set up OpenMM engine
     openmm = False
     try:
         import simtk.openmm
         openmm = True
     except:
         logger.warn("OpenMM cannot be imported, skipping OpenMM tests.")
     if openmm:
         self.engines['OpenMM'] = OpenMM(coords="all.gro",
                                         pdb="conf.pdb",
                                         ffxml="a99sb.xml",
                                         platname="Reference",
                                         precision="double")
     self.addCleanup(os.system, 'cd .. ; rm -rf temp')
Beispiel #6
0
 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')
Beispiel #7
0
 def setup_class(cls):
     super(TestAmoebaWater6, cls).setup_class()
     #self.logger.debug("\nBuilding options for target...\n")
     cls.cwd = os.path.dirname(os.path.realpath(__file__))
     os.chdir(os.path.join(cls.cwd, "files", "amoeba_h2o6"))
     cls.tmpfolder = os.path.join(cls.cwd, "files", "amoeba_h2o6", "temp")
     if not os.path.exists(cls.tmpfolder):
         os.makedirs(cls.tmpfolder)
     os.chdir(cls.tmpfolder)
     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")
     cls.O = OpenMM(coords="hex.arc", pdb="prism.pdb", ffxml="amoebawater.xml", precision="double", \
                         mmopts={'rigidWater':False, 'mutualInducedTargetEpsilon':1e-6})
     tinkerpath = which('testgrad')
     if tinkerpath:
         cls.T = TINKER(coords="hex.arc", tinker_key="prism.key", tinkerpath=tinkerpath)
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)"
Beispiel #9
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)"