Ejemplo n.º 1
0
    def test_rb_torsions_vs_foyer(self, ethanol_with_rb_torsions):
        # Given that these force constants are copied from Foyer's OPLS-AA file,
        # compare to processing through the current MoSDeF pipeline
        import foyer
        import mbuild

        comp = mbuild.load("CC", smiles=True)
        comp.xyz = ethanol_with_rb_torsions.positions.m_as(unit.nanometer)
        ff = foyer.Forcefield(name="oplsaa")
        from_foyer = ff.apply(comp)
        from_foyer.box = [40, 40, 40, 90, 90, 90]
        from_foyer.save("from_foyer.top")
        from_foyer.save("from_foyer.gro")

        rb_torsion_energy_from_foyer = _run_gmx_energy(
            top_file="from_foyer.top",
            gro_file="from_foyer.gro",
            mdp_file=_get_mdp_file("default"),
        ).energies["Torsion"]

        # GROMACS vs. OpenMM was already compared, so just use one
        omm = get_gromacs_energies(ethanol_with_rb_torsions, decimal=3).energies[
            "Torsion"
        ]

        assert (omm - rb_torsion_energy_from_foyer).m_as(kj_mol) < 1e-6
Ejemplo n.º 2
0
    def test_interchange_energies(self, molecule_path, get_interchanges, oplsaa):
        if "ethanol" in molecule_path or "adamantane" in molecule_path:
            pytest.skip("Foyer/ParmEd bug with this molecule")
        openff_interchange, pmd_structure = get_interchanges(molecule_path)
        parameterized_pmd_structure = oplsaa.apply(pmd_structure)
        openff_energy = get_gromacs_energies(
            openff_interchange, decimal=3, mdp="cutoff_hbonds"
        )

        parameterized_pmd_structure.save("from_foyer.gro")
        parameterized_pmd_structure.save("from_foyer.top")

        through_foyer = _run_gmx_energy(
            top_file="from_foyer.top",
            gro_file="from_foyer.gro",
            mdp_file=_get_mdp_file("cutoff_hbonds"),
        )

        # TODO: Revisit after https://github.com/mosdef-hub/foyer/issues/431
        openff_energy.compare(
            through_foyer,
            custom_tolerances={
                "Bond": 1e-3 * unit.kilojoule / unit.mole,
                "Angle": 1e-3 * unit.kilojoule / unit.mole,
                "Nonbonded": 1e-3 * unit.kilojoule / unit.mole,
                "Torsion": 1e-3 * unit.kilojoule / unit.mole,
                "vdW": 5 * unit.kilojoule / unit.mole,
                "Electrostatics": 1 * unit.kilojoule / unit.mole,
            },
        )
Ejemplo n.º 3
0
def test_cutoff_electrostatics():
    ion_ff = ForceField(get_test_file_path("ions.offxml"))
    ions = Topology.from_molecules([
        Molecule.from_smiles("[#3]"),
        Molecule.from_smiles("[#17]"),
    ])
    out = Interchange.from_smirnoff(ion_ff, ions)
    out.box = [4, 4, 4] * unit.nanometer

    gmx = []
    lmp = []

    for d in np.linspace(0.75, 0.95, 5):
        positions = np.zeros((2, 3)) * unit.nanometer
        positions[1, 0] = d * unit.nanometer
        out.positions = positions

        out["Electrostatics"].method = "cutoff"
        gmx.append(
            get_gromacs_energies(out, mdp="auto").energies["Electrostatics"].m)
        lmp.append(
            get_lammps_energies(out).energies["Electrostatics"].m_as(
                unit.kilojoule / unit.mol))

    assert np.sum(np.sqrt(np.square(np.asarray(lmp) - np.asarray(gmx)))) < 1e-3
Ejemplo n.º 4
0
    def test_rb_torsions(self, ethanol_with_rb_torsions):
        omm = get_openmm_energies(ethanol_with_rb_torsions, round_positions=3).energies[
            "Torsion"
        ]
        gmx = get_gromacs_energies(ethanol_with_rb_torsions, decimal=3).energies[
            "Torsion"
        ]

        assert (gmx - omm).m_as(kj_mol) < 1e-6
Ejemplo n.º 5
0
    def test_parmed_roundtrip(self):
        original = pmd.load_file(get_test_file_path("ALA_GLY/ALA_GLY.top"))
        gro = pmd.load_file(get_test_file_path("ALA_GLY/ALA_GLY.gro"))
        original.box = gro.box
        original.positions = gro.positions

        openff_sys = Interchange._from_parmed(original)
        openff_sys.topology.mdtop = md.Topology.from_openmm(gro.topology)

        #  Some sanity checks, including that residues are stored ...
        assert openff_sys.topology.mdtop.n_atoms == 29
        # TODO: Assert number of topology molecules after refactor
        assert openff_sys.topology.mdtop.n_residues == 4

        # ... and written out
        openff_sys.to_gro("has_residues.gro", writer="internal")
        assert len(pmd.load_file("has_residues.gro").residues) == 4

        roundtrip = openff_sys._to_parmed()

        roundtrip.save("conv.gro", overwrite=True)
        roundtrip.save("conv.top", overwrite=True)

        original_energy = _run_gmx_energy(
            top_file=get_test_file_path("ALA_GLY/ALA_GLY.top"),
            gro_file=get_test_file_path("ALA_GLY/ALA_GLY.gro"),
            mdp_file=_get_mdp_file("cutoff_hbonds"),
        )
        internal_energy = get_gromacs_energies(openff_sys, mdp="cutoff_hbonds")

        roundtrip_energy = _run_gmx_energy(
            top_file="conv.top",
            gro_file="conv.gro",
            mdp_file=_get_mdp_file("cutoff_hbonds"),
        )

        # Differences in bond energies appear to be related to ParmEd's rounding
        # of the force constant and equilibrium bond length
        original_energy.compare(internal_energy)
        internal_energy.compare(
            roundtrip_energy,
            custom_tolerances={
                "Bond": 0.02 * omm_unit.kilojoule_per_mole,
            },
        )
        original_energy.compare(
            roundtrip_energy,
            custom_tolerances={
                "Bond": 0.02 * omm_unit.kilojoule_per_mole,
            },
        )
Ejemplo n.º 6
0
    def test_ethanol_energies(self, oplsaa_interchange_ethanol):
        from openff.interchange.tests.energy_tests.test_energies import (
            get_gromacs_energies,
        )

        gmx_energies = get_gromacs_energies(oplsaa_interchange_ethanol)
        omm_energies = get_openmm_energies(oplsaa_interchange_ethanol)

        gmx_energies.compare(
            omm_energies,
            custom_tolerances={
                "vdW": 12.0 * unit.kilojoule / unit.mole,
                "Electrostatics": 12.0 * unit.kilojoule / unit.mole,
            },
        )
Ejemplo n.º 7
0
def test_liquid_argon():
    argon = Molecule.from_smiles("[#18]")
    pdbfile = app.PDBFile(get_test_file_path("packed-argon.pdb"))

    top = Topology.from_openmm(pdbfile.topology, unique_molecules=[argon])

    argon_ff = ForceField(get_test_file_path("argon.offxml"))

    out = Interchange.from_smirnoff(argon_ff, top)
    out.positions = pdbfile.positions

    omm_energies = get_openmm_energies(out)

    gmx_energies = get_gromacs_energies(
        out,
        mdp="auto",
        writer="internal",
    )

    omm_energies.compare(
        gmx_energies,
        custom_tolerances={
            "vdW": 0.008 * simtk_unit.kilojoule_per_mole,
        },
    )

    argon_ff_no_switch = deepcopy(argon_ff)
    argon_ff_no_switch["vdW"].switch_width *= 0

    out_no_switch = Interchange.from_smirnoff(argon_ff_no_switch, top)
    out_no_switch.positions = pdbfile.positions

    lmp_energies = get_lammps_energies(out_no_switch)

    omm_energies.compare(
        lmp_energies,
        custom_tolerances={
            "vdW": 10.5 * simtk_unit.kilojoule_per_mole,
        },
    )
Ejemplo n.º 8
0
def test_water_dimer():
    tip3p = ForceField(get_test_file_path("tip3p.offxml"))
    water = Molecule.from_smiles("O")
    top = Topology.from_molecules(2 * [water])
    top.mdtop = md.Topology.from_openmm(top.to_openmm())

    pdbfile = openmm.app.PDBFile(get_test_file_path("water-dimer.pdb"))

    positions = pdbfile.positions

    openff_sys = Interchange.from_smirnoff(tip3p, top)
    openff_sys.positions = positions
    openff_sys.box = [10, 10, 10] * unit.nanometer

    omm_energies = get_openmm_energies(
        openff_sys,
        hard_cutoff=True,
        electrostatics=False,
    )

    toolkit_energies = _get_openmm_energies(
        tip3p.create_openmm_system(top),
        openff_sys.box,
        openff_sys.positions,
        hard_cutoff=True,
        electrostatics=False,
    )

    omm_energies.compare(toolkit_energies)

    # TODO: Fix GROMACS energies by handling SETTLE constraints
    # gmx_energies, _ = get_gromacs_energies(openff_sys)
    # compare_gromacs_openmm(omm_energies=omm_energies, gmx_energies=gmx_energies)

    openff_sys["Electrostatics"].method = "cutoff"
    omm_energies_cutoff = get_gromacs_energies(openff_sys)
    lmp_energies = get_lammps_energies(openff_sys)

    lmp_energies.compare(omm_energies_cutoff)
Ejemplo n.º 9
0
def test_gmx_14_energies_exist():
    # TODO: Make sure 1-4 energies are accurate, not just existent

    # Use a molecule with only one 1-4 interaction, and
    # make it between heavy atoms because H-H 1-4 are weak
    mol = Molecule.from_smiles("ClC#CCl")
    mol.name = "HPER"
    mol.generate_conformers(n_conformers=1)

    parsley = ForceField("openff-1.0.0.offxml")

    out = Interchange.from_smirnoff(parsley, mol.to_topology())
    out.positions = mol.conformers[0]

    # Put this molecule in a large box with cut-off electrostatics
    # to prevent it from interacting with images of itself
    out.box = [40, 40, 40]
    out["Electrostatics"].method = "cutoff"

    gmx_energies = get_gromacs_energies(out)

    # The only possible non-bonded interactions should be from 1-4 intramolecular interactions
    assert gmx_energies.energies["vdW"].m != 0.0
    assert gmx_energies.energies["Electrostatics"].m != 0.0
Ejemplo n.º 10
0
def test_energies_single_mol(constrained, mol_smi):
    import mbuild as mb

    mol = Molecule.from_smiles(mol_smi)
    mol.generate_conformers(n_conformers=1)
    mol.name = "FOO"
    top = mol.to_topology()
    top.box_vectors = None  # [10, 10, 10] * simtk_unit.nanometer

    if constrained:
        parsley = ForceField("openff-1.0.0.offxml")
    else:
        parsley = ForceField("openff_unconstrained-1.0.0.offxml")

    off_sys = Interchange.from_smirnoff(parsley, top)

    off_sys.handlers["Electrostatics"].method = "cutoff"

    mol.to_file("out.xyz", file_format="xyz")
    compound: mb.Compound = mb.load("out.xyz")
    packed_box: mb.Compound = mb.fill_box(compound=compound,
                                          n_compounds=1,
                                          box=mb.Box(lengths=[10, 10, 10]))

    positions = packed_box.xyz * unit.nanometer
    off_sys.positions = positions

    # Compare directly to toolkit's reference implementation
    omm_energies = get_openmm_energies(off_sys, round_positions=8)
    omm_reference = parsley.create_openmm_system(top)
    reference_energies = _get_openmm_energies(
        omm_sys=omm_reference,
        box_vectors=off_sys.box,
        positions=off_sys.positions,
        round_positions=8,
    )

    omm_energies.compare(reference_energies)

    mdp = "cutoff_hbonds" if constrained else "auto"
    # Compare GROMACS writer and OpenMM export
    gmx_energies = get_gromacs_energies(off_sys, mdp=mdp)

    custom_tolerances = {
        "Bond": 2e-5 * simtk_unit.kilojoule_per_mole,
        "Electrostatics": 2 * simtk_unit.kilojoule_per_mole,
        "vdW": 2 * simtk_unit.kilojoule_per_mole,
        "Nonbonded": 2 * simtk_unit.kilojoule_per_mole,
        "Angle": 1e-4 * simtk_unit.kilojoule_per_mole,
    }

    gmx_energies.compare(
        omm_energies,
        custom_tolerances=custom_tolerances,
    )

    if not constrained:
        other_energies = get_openmm_energies(
            off_sys,
            round_positions=8,
            hard_cutoff=True,
            electrostatics=True,
        )
        lmp_energies = get_lammps_energies(off_sys)
        custom_tolerances = {
            "vdW": 5.0 * simtk_unit.kilojoule_per_mole,
            "Electrostatics": 5.0 * simtk_unit.kilojoule_per_mole,
        }
        lmp_energies.compare(other_energies,
                             custom_tolerances=custom_tolerances)
Ejemplo n.º 11
0
def test_packmol_boxes(toolkit_file_path):
    # TODO: Isolate a set of systems here instead of using toolkit data
    # TODO: Fix nonbonded energy differences
    from openff.toolkit.utils import get_data_file_path

    pdb_file_path = get_data_file_path(toolkit_file_path)
    pdbfile = openmm.app.PDBFile(pdb_file_path)

    ethanol = Molecule.from_smiles("CCO")
    cyclohexane = Molecule.from_smiles("C1CCCCC1")
    omm_topology = pdbfile.topology
    off_topology = OFFBioTop.from_openmm(
        omm_topology, unique_molecules=[ethanol, cyclohexane])
    off_topology.mdtop = md.Topology.from_openmm(omm_topology)

    parsley = ForceField("openff_unconstrained-1.0.0.offxml")

    off_sys = Interchange.from_smirnoff(parsley, off_topology)

    off_sys.box = np.asarray(
        pdbfile.topology.getPeriodicBoxVectors().value_in_unit(
            simtk_unit.nanometer))
    off_sys.positions = pdbfile.positions

    sys_from_toolkit = parsley.create_openmm_system(off_topology)

    omm_energies = get_openmm_energies(off_sys,
                                       hard_cutoff=True,
                                       electrostatics=False)
    reference = _get_openmm_energies(
        sys_from_toolkit,
        off_sys.box,
        off_sys.positions,
        hard_cutoff=True,
        electrostatics=False,
    )

    omm_energies.compare(
        reference,
        custom_tolerances={
            "Electrostatics": 2e-2 * simtk_unit.kilojoule_per_mole,
        },
    )

    # custom_tolerances={"HarmonicBondForce": 1.0}

    # Compare GROMACS writer and OpenMM export
    gmx_energies = get_gromacs_energies(off_sys, electrostatics=False)

    omm_energies_rounded = get_openmm_energies(
        off_sys,
        round_positions=8,
        hard_cutoff=True,
        electrostatics=False,
    )

    omm_energies_rounded.compare(
        other=gmx_energies,
        custom_tolerances={
            "Angle": 1e-2 * simtk_unit.kilojoule_per_mole,
            "Torsion": 1e-2 * simtk_unit.kilojoule_per_mole,
            "Electrostatics": 3200 * simtk_unit.kilojoule_per_mole,
        },
    )