Ejemplo n.º 1
0
    def test_from_toolkit_packmol_boxes(self, pdb_path, unique_molecules):
        """
        Test loading some pre-prepared PACKMOL-generated systems.

        These use PDB files already prepared in the toolkit because PDB files are a pain.
        """
        ff = ForceField("openff-1.0.0.offxml")

        pdb_file_path = get_data_file_path("systems/packmol_boxes/" + pdb_path)
        pdbfile = openmm.app.PDBFile(pdb_file_path)
        top = Topology.from_openmm(
            pdbfile.topology,
            unique_molecules=unique_molecules,
        )
        box = pdbfile.topology.getPeriodicBoxVectors()
        box = box.value_in_unit(nm) * unit.nanometer

        out = ff.create_openff_system(top)
        out.box = box
        out.positions = pdbfile.getPositions()

        assert np.allclose(
            out.positions.to(unit.nanometer).magnitude,
            pdbfile.getPositions().value_in_unit(nm),
        )

        get_openmm_energies(out, hard_cutoff=True).compare(
            _get_openmm_energies(
                omm_sys=ff.create_openmm_system(top),
                box_vectors=pdbfile.topology.getPeriodicBoxVectors(),
                positions=pdbfile.getPositions(),
                hard_cutoff=True,
            ))
Ejemplo n.º 2
0
def test_sanity_grompp():
    """Basic test to ensure that a topology can be processed without errors"""
    mol = Molecule.from_smiles("CC")
    mol.generate_conformers(n_conformers=1)
    top = mol.to_topology()

    parsley = ForceField("openff-1.0.0.offxml")
    off_sys = parsley.create_openff_system(top)

    off_sys.box = [4, 4, 4] * np.eye(3)
    off_sys.positions = mol.conformers[0] / omm_unit.angstrom

    off_sys.to_gro("out.gro", writer="internal")
    off_sys.to_top("out.top", writer="internal")

    # TODO: Replace with intermol.gromacs.gmx_energy call after resolving
    #  atomtype name differences that currently force -maxwarn 7
    import os

    from pkg_resources import resource_filename

    mdp_file = resource_filename("intermol", "tests/gromacs/grompp.mdp")
    exit_code = os.system(
        f"gmx grompp -f {mdp_file} -c out.gro -p out.top -maxwarn 1")

    assert exit_code == 0
Ejemplo n.º 3
0
    def test_basic_conversion_params(self, box):
        top = top_from_smiles("C")
        parsley = ForceField("openff_unconstrained-1.0.0.offxml")

        off_sys = parsley.create_openff_system(topology=top, box=box)
        # UnitArray(...)
        off_sys.positions = np.zeros(shape=(top.n_topology_atoms, 3))
        struct = off_sys.to_parmed()

        sigma0 = struct.atoms[0].atom_type.sigma
        epsilon0 = struct.atoms[0].atom_type.epsilon

        sigma1 = struct.atoms[1].atom_type.sigma
        epsilon1 = struct.atoms[1].atom_type.epsilon

        bond_k = struct.bonds[0].type.k
        req = struct.bonds[0].type.req

        angle_k = struct.angles[0].type.k
        theteq = struct.angles[0].type.theteq

        assert sigma0 == pytest.approx(3.3996695084235347)
        assert epsilon0 == pytest.approx(0.1094)

        assert sigma1 == pytest.approx(2.649532787749369)
        assert epsilon1 == pytest.approx(0.0157)

        assert bond_k == pytest.approx(379.04658864565)
        assert req == pytest.approx(1.092888378383)

        assert angle_k == pytest.approx(37.143507635885)
        assert theteq == pytest.approx(107.5991506326)

        assert np.allclose(struct.box, np.array([40, 40, 40, 90, 90, 90]))
Ejemplo n.º 4
0
def test_from_openmm_single_mols(mol, n_mols):
    """
    Test that ForceField.create_openmm_system and System.to_openmm produce
    objects with similar energies

    TODO: Tighten tolerances
    TODO: Test periodic and non-periodic
    """

    parsley = ForceField(get_test_file_path("parsley.offxml"))

    mol = Molecule.from_smiles(mol)
    mol.generate_conformers(n_conformers=1)
    top = Topology.from_molecules(n_mols * [mol])
    mol.conformers[0] -= np.min(mol.conformers) * unit.angstrom

    top.box_vectors = np.eye(3) * np.asarray([10, 10, 10]) * unit.nanometer

    if n_mols == 1:
        positions = mol.conformers[0]
    elif n_mols == 2:
        positions = np.vstack(
            [mol.conformers[0], mol.conformers[0] + 3 * unit.nanometer])
        positions = positions * unit.angstrom

    toolkit_system = parsley.create_openmm_system(top)

    native_system = parsley.create_openff_system(topology=top).to_openmm()

    compare_system_energies(
        system1=toolkit_system,
        system2=native_system,
        positions=positions,
        box_vectors=top.box_vectors,
    )
Ejemplo n.º 5
0
    def test_unsupported_handler(self):
        from openff.system.stubs import ForceField

        gbsa_ff = ForceField(
            get_data_file_path("test_forcefields/GBSA_HCT-1.0.offxml"))

        with pytest.raises(SMIRNOFFHandlersNotImplementedError,
                           match=r"SMIRNOFF parameters not.*GBSA"):
            gbsa_ff.create_openff_system(topology=None)
Ejemplo n.º 6
0
    def test_library_charge_assignment(self):
        from openff.toolkit.tests.test_forcefield import xml_ethanol_library_charges_ff

        from openff.system.stubs import ForceField

        forcefield = ForceField("openff-1.3.0.offxml")

        top = Topology.from_molecules(
            [Molecule.from_smiles(smi) for smi in ["[Na+]", "[Cl-]"]])

        forcefield.create_openff_system(top)
Ejemplo n.º 7
0
def test_to_lammps_single_mols(mol, n_mols):
    """
    Test that ForceField.create_openmm_system and System.to_openmm produce
    objects with similar energies

    TODO: Tighten tolerances
    TODO: Test periodic and non-periodic
    """

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

    mol = Molecule.from_smiles(mol)
    mol.generate_conformers(n_conformers=1)
    top = Topology.from_molecules(n_mols * [mol])
    mol.conformers[0] -= np.min(mol.conformers) * omm_unit.angstrom

    top.box_vectors = np.eye(3) * np.asarray([10, 10, 10]) * omm_unit.nanometer

    if n_mols == 1:
        positions = mol.conformers[0]
    elif n_mols == 2:
        positions = np.vstack(
            [mol.conformers[0], mol.conformers[0] + 3 * omm_unit.nanometer]
        )
        positions = positions * omm_unit.angstrom

    openff_sys = parsley.create_openff_system(topology=top)
    openff_sys.positions = positions.value_in_unit(omm_unit.nanometer)
    openff_sys.box = top.box_vectors

    reference = get_openmm_energies(
        off_sys=openff_sys, round_positions=3, electrostatics=False
    )

    lmp_energies = get_lammps_energies(
        off_sys=openff_sys, round_positions=3, electrostatics=False
    )

    _write_lammps_input(
        off_sys=openff_sys,
        file_name="tmp.in",
        electrostatics=False,
    )

    lmp_energies.compare(
        reference,
        custom_tolerances={
            "Nonbonded": 999 * omm_unit.kilojoule_per_mole,
            "Torsion": 0.005 * omm_unit.kilojoule_per_mole,
        },
    )
Ejemplo n.º 8
0
def test_internal_gromacs_writers(mol):
    mol = Molecule.from_smiles(mol)
    mol.name = "FOO"
    mol.generate_conformers(n_conformers=1)
    top = mol.to_topology()
    parsley = ForceField("openff_unconstrained-1.0.0.offxml")
    out = parsley.create_openff_system(top)

    out.box = [4, 4, 4] * np.eye(3)
    out.positions = mol.conformers[0]
    out.positions = np.round(out.positions, 2)

    openmm_sys = parsley.create_openmm_system(top)
    struct = pmd.openmm.load_topology(
        topology=top.to_openmm(),
        system=openmm_sys,
        xyz=out.positions.to(unit.angstrom),
    )
    struct.box = [40, 40, 40, 90, 90, 90]

    with tempfile.TemporaryDirectory() as off_tempdir:
        with temporary_cd(off_tempdir):

            struct.save("reference.top")
            struct.save("reference.gro")

            out.to_top("internal.top", writer="internal")
            out.to_gro("internal.gro", writer="internal", decimal=3)

            compare_gro_files("internal.gro", "reference.gro")
            # TODO: Also compare to out.to_gro("parmed.gro", writer="parmed")

            reference_energy = run_gmx_energy(
                top_file="reference.top",
                gro_file="reference.gro",
                mdp_file=get_mdp_file("default"),
            )

            internal_energy = run_gmx_energy(
                top_file="internal.top",
                gro_file="internal.gro",
                mdp_file=get_mdp_file("default"),
            )

            reference_energy.compare(
                internal_energy,
                custom_tolerances={"Bond": 2e-2 * omm_unit.kilojoule_per_mole},
            )
Ejemplo n.º 9
0
def test_nonbonded_compatibility():
    mol = Molecule.from_smiles("CCO")
    mol.name = "FOO"
    mol.generate_conformers(n_conformers=1)

    top = mol.to_topology()
    positions = mol.conformers[0].in_units_of(
        omm_unit.nanometer) / omm_unit.nanometer
    box = [4, 4, 4] * np.eye(3)

    parsley = ForceField("openff_unconstrained-1.0.0.offxml")
    off_sys = parsley.create_openff_system(top)

    off_sys.box = box
    off_sys.handlers["Electrostatics"].method = "reaction-field"

    with pytest.raises(NonbondedCompatibilityError,
                       match="reaction-field is not "):
        off_sys.to_openmm()

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

    with pytest.raises(
            MissingNonbondedCompatibilityError,
            match="Coulomb",
    ):
        off_sys.to_openmm()

    off_sys.box = None

    with pytest.raises(
            NonbondedCompatibilityError,
            match="Coulomb",
    ):
        off_sys.to_openmm()

    off_sys.box = box
    off_sys.handlers["Electrostatics"].method = "PME"

    with pytest.raises(MissingPositionsError):
        off_sys.to_gro("out.gro", writer="internal")

    off_sys.positions = positions

    # Ensure nothing obvious was mangled
    off_sys.to_top("out.top", writer="internal")
    off_sys.to_gro("out.gro", writer="internal")
def test_internal_gro_writer():
    mol = Molecule.from_smiles("C")
    mol.generate_conformers(n_conformers=1)
    top = mol.to_topology()
    parsley = ForceField("openff-1.0.0.offxml")
    out = parsley.create_openff_system(top)

    out.box = [4, 4, 4] * np.eye(3)
    out.positions = mol.conformers[0] / omm_unit.nanometer

    out.to_gro("internal.gro", writer="internal")
    out.to_gro("parmed.gro", writer="parmed")

    with open("internal.gro", "r") as file1:
        with open("parmed.gro", "r") as file2:
            # Ignore first two lines and last line
            assert file1.readlines()[2:-1] == file2.readlines()[2:-1]
Ejemplo n.º 11
0
def test_parmed_openmm(tmpdir, smiles):
    tmpdir.chdir()

    parsley = ForceField("openff_unconstrained-1.0.0.offxml")
    mol = Molecule.from_smiles(smiles)
    mol.generate_conformers(n_conformers=1)
    top = Topology.from_molecules(mol)
    box = 4 * np.eye(3) * unit.nanometer

    with tempfile.TemporaryDirectory() as omm_tempdir:
        with temporary_cd(omm_tempdir):
            openff_openmm_pmd_gmx(
                topology=top,
                forcefield=parsley,
                box=box,
                prefix="via_openmm",
            )

            ener1, ener1_file = gmx_energy(
                top="via_openmm.top",
                gro="via_openmm.gro",
                mdp=resource_filename("intermol", "tests/gromacs/grompp.mdp"),
            )

    with tempfile.TemporaryDirectory() as off_tempdir:
        with temporary_cd(off_tempdir):
            openff_pmd_gmx_indirect(
                topology=top,
                forcefield=parsley,
                box=box,
                prefix="via_conversion",
            )

            ener2, ener2_file = gmx_energy(
                top="via_conversion.top",
                gro="via_conversion.gro",
                mdp=resource_filename("intermol", "tests/gromacs/grompp.mdp"),
            )

    compare_energies(ener1, ener2)

    with tempfile.TemporaryDirectory() as off_tempdir:
        with temporary_cd(off_tempdir):
            openff_pmd_gmx_direct(
                topology=top,
                forcefield=parsley,
                box=box,
                prefix="via_call",
            )

            ener3, ener3_file = gmx_energy(
                top="via_call.top",
                gro="via_call.gro",
                mdp=resource_filename("intermol", "tests/gromacs/grompp.mdp"),
            )

    compare_energies(ener2, ener3)
Ejemplo n.º 12
0
def test_argon(n_mol):
    from openff.system.utils import get_test_file_path

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

    mol = Molecule.from_smiles("[#18]")
    mol.add_conformer(np.array([[0, 0, 0]]) * omm_unit.angstrom)
    mol.name = "FOO"
    top = Topology.from_molecules(n_mol * [mol])

    off_sys = ar_ff.create_openff_system(top)

    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=[n_mol],
        box=mb.Box([4, 4, 4]),
    )

    positions = packed_box.xyz * unit.nanometer
    positions = np.round(positions, 3)
    off_sys.positions = positions

    box = np.asarray(packed_box.box.lengths) * unit.nanometer
    off_sys.box = box

    omm_energies = get_openmm_energies(
        off_sys, round_positions=8, hard_cutoff=True, electrostatics=False
    )
    gmx_energies = get_gromacs_energies(
        off_sys, writer="internal", electrostatics=False
    )
    lmp_energies = get_lammps_energies(off_sys)

    omm_energies.compare(lmp_energies)

    omm_energies.compare(
        gmx_energies,
        custom_tolerances={
            "Nonbonded": 2e-5 * omm_unit.kilojoule_per_mole,
        },
    )
Ejemplo n.º 13
0
def test_getitem():
    """Test behavior of System.__getitem__"""
    mol = Molecule.from_smiles("CCO")
    parsley = ForceField("openff-1.0.0.offxml")
    out = parsley.create_openff_system(mol.to_topology())

    out.box = [4, 4, 4]

    assert not out.positions
    np.testing.assert_equal(out["box"].m, (4 * np.eye(3) * unit.nanometer).m)
    np.testing.assert_equal(out["box"].m, out["box_vectors"].m)

    assert out["Bonds"] == out.handlers["Bonds"]

    with pytest.raises(LookupError, match="Only str"):
        out[1]

    with pytest.raises(LookupError, match="Could not find"):
        out["CMAPs"]
Ejemplo n.º 14
0
def test_water_dimer():
    from openff.system.utils import get_test_file_path

    tip3p = ForceField(get_test_file_path("tip3p.offxml"))
    water = Molecule.from_smiles("O")
    top = Topology.from_molecules(2 * [water])

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

    positions = np.array(pdbfile.positions / omm_unit.nanometer) * unit.nanometer

    openff_sys = tip3p.create_openff_system(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)

    lmp_energies = get_lammps_energies(openff_sys, electrostatics=False)

    lmp_energies.compare(omm_energies)
Ejemplo n.º 15
0
    def test_bond_potential_handler(self):
        top = Topology.from_molecules(Molecule.from_smiles("O=O"))

        bond_handler = BondHandler(version=0.3)
        bond_parameter = BondHandler.BondType(
            smirks="[*:1]~[*:2]",
            k=1.5 * omm_unit.kilocalorie_per_mole / omm_unit.angstrom**2,
            length=1.5 * omm_unit.angstrom,
            id="b1000",
        )
        bond_handler.add_parameter(bond_parameter.to_dict())

        from openff.system.stubs import ForceField

        forcefield = ForceField()
        forcefield.register_parameter_handler(bond_handler)
        bond_potentials = forcefield["Bonds"].create_potential(top)

        pot = bond_potentials.potentials[bond_potentials.slot_map["(0, 1)"]]

        kcal_mol_a2 = unit.Unit("kilocalorie / (angstrom ** 2 * mole)")
        assert pot.parameters["k"].to(kcal_mol_a2).magnitude == pytest.approx(
            1.5)
Ejemplo n.º 16
0
def test_water_dimer():
    """Test that a water dimer can be written and the files can be grommp'd"""
    from openff.system.utils import get_test_file_path

    tip3p = ForceField(get_test_file_path("tip3p.offxml"))
    water = Molecule.from_smiles("O")
    top = Topology.from_molecules(2 * [water])

    from simtk import openmm
    from simtk import unit as omm_unit

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

    positions = np.array(
        pdbfile.positions / omm_unit.nanometer) * unit.nanometer

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

    gmx_energies = get_gromacs_energies(openff_sys, writer="internal")

    assert gmx_energies is not None
Ejemplo n.º 17
0
    def test_angle_potential_handler(self):
        top = Topology.from_molecules(Molecule.from_smiles("CCC"))

        angle_handler = AngleHandler(version=0.3)
        angle_parameter = AngleHandler.AngleType(
            smirks="[*:1]~[*:2]~[*:3]",
            k=2.5 * omm_unit.kilocalorie_per_mole / omm_unit.radian**2,
            angle=100 * omm_unit.degree,
            id="b1000",
        )
        angle_handler.add_parameter(angle_parameter.to_dict())

        from openff.system.stubs import ForceField

        forcefield = ForceField()
        forcefield.register_parameter_handler(angle_handler)
        angle_potentials = forcefield["Angles"].create_potential(top)

        top_key = TopologyKey(atom_indices=(0, 1, 2))
        pot = angle_potentials.potentials[angle_potentials.slot_map[top_key]]

        kcal_mol_rad2 = unit.Unit("kilocalorie / (mole * radian ** 2)")
        assert pot.parameters["k"].to(
            kcal_mol_rad2).magnitude == pytest.approx(2.5)
def openff_pmd_gmx_direct(
    topology: Topology,
    forcefield: ForceField,
    box: ArrayQuantity,
    prefix: str,
) -> None:
    off_sys = forcefield.create_openff_system(topology=topology)
    off_sys.box = box

    ref_mol = topology.topology_molecules[0].reference_molecule
    off_top_positions = ref_mol.conformers[0] / omm_unit.nanometer * unit.nanometer
    # TODO: Update this when better processing of OFFTop positions is supported
    off_sys.positions = off_top_positions

    off_sys.to_gro(prefix + ".gro")
    off_sys.to_top(prefix + ".top")
Ejemplo n.º 19
0
    def test_library_charge_assignment(self):
        from openff.system.stubs import ForceField

        forcefield = ForceField("openff-1.3.0.offxml")
        forcefield.deregister_parameter_handler("ToolkitAM1BCC")

        top = Topology.from_molecules(
            [Molecule.from_smiles(smi) for smi in ["[Na+]", "[Cl-]"]])

        reference = forcefield.create_openmm_system(top)
        new = forcefield.create_openff_system(top)

        compare_charges_omm_off(reference, new)
def openff_openmm_pmd_gmx(
    topology: Topology,
    forcefield: ForceField,
    box: ArrayQuantity,
    prefix: str,
) -> None:
    """Pipeline to write GROMACS files from and OpenMM system through ParmEd"""
    topology.box_vectors = box.to(unit.nanometer).magnitude * omm_unit.nanometer
    omm_sys = forcefield.create_openmm_system(topology)

    struct = pmd.openmm.load_topology(
        system=omm_sys,
        topology=topology.to_openmm(),
        xyz=topology.topology_molecules[0].reference_molecule.conformers[0],
    )

    # Assign dummy residue names, GROMACS will not accept empty strings
    # TODO: Patch upstream?
    for res in struct.residues:
        res.name = "FOO"

    struct.save(prefix + ".gro")
    struct.save(prefix + ".top")
Ejemplo n.º 21
0
 def parsley(self):
     return ForceField("openff-1.0.0.offxml")
Ejemplo n.º 22
0
def test_energies_single_mol(constrained, n_mol, mol_smi):
    mol = Molecule.from_smiles(mol_smi)
    mol.generate_conformers(n_conformers=1)
    mol.name = "FOO"
    top = Topology.from_molecules(n_mol * [mol])

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

    off_sys = parsley.create_openff_system(top)

    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=[n_mol],
        density=500,  # kg/m^3
    )

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

    box = np.asarray(packed_box.box.lengths) * unit.nanometer
    if np.any(box < 4 * unit.nanometer):
        off_sys.box = np.array([4, 4, 4]) * unit.nanometer
    else:
        off_sys.box = box

    # Compare directly to toolkit's reference implementation
    omm_energies = get_openmm_energies(
        off_sys, round_positions=8, hard_cutoff=True, electrostatics=False
    )
    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,
        hard_cutoff=True,
        electrostatics=False,
    )

    try:
        omm_energies.compare(reference_energies)
    except EnergyError as e:
        if "Nonbonded" in str(e):
            # If nonbonded energies differ, at least ensure that the nonbonded
            # parameters on each particle match
            from openff.system.tests.utils import (
                _get_charges_from_openmm_system,
                _get_lj_params_from_openmm_system,
            )
        else:
            raise e

        omm_sys = off_sys.to_openmm()
        np.testing.assert_equal(
            np.asarray([*_get_charges_from_openmm_system(omm_sys)]),
            np.asarray([*_get_charges_from_openmm_system(omm_reference)]),
        )
        np.testing.assert_equal(
            np.asarray([*_get_lj_params_from_openmm_system(omm_sys)]),
            np.asarray([*_get_lj_params_from_openmm_system(omm_reference)]),
        )

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

    custom_tolerances = {
        "Bond": 2e-5 * n_mol * omm_unit.kilojoule_per_mole,
        "Nonbonded": 1e-3 * n_mol * omm_unit.kilojoule_per_mole,
    }
    if constrained:
        # GROMACS might use the initial bond lengths, not the equilibrium bond lengths,
        # in the initial configuration, making angles differ slightly
        custom_tolerances.update(
            {
                "Angle": 5e-2 * n_mol * omm_unit.kilojoule_per_mole,
                "Nonbonded": 2.0 * n_mol * omm_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 = {
            "Nonbonded": 0.5 * n_mol * omm_unit.kilojoule_per_mole,
        }
        lmp_energies.compare(other_energies, custom_tolerances=custom_tolerances)
Ejemplo n.º 23
0
 def parsley_unconstrained(self):
     return ForceField("openff_unconstrained-1.0.0.offxml")
Ejemplo n.º 24
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 = Topology.from_openmm(
        omm_topology, unique_molecules=[ethanol, cyclohexane]
    )

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

    off_sys = parsley.create_openff_system(off_topology)

    off_sys.box = np.asarray(
        pdbfile.topology.getPeriodicBoxVectors() / omm_unit.nanometer,
    )
    off_sys.positions = np.asarray(
        pdbfile.positions / omm_unit.nanometer,
    )

    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={
            "Nonbonded": 2e-2 * omm_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 * omm_unit.kilojoule_per_mole,
            "Torsion": 1e-2 * omm_unit.kilojoule_per_mole,
            "Nonbonded": 3200 * omm_unit.kilojoule_per_mole,
        },
    )
Ejemplo n.º 25
0
 def ammonia_ff(self):
     """Fixture that loads an SMIRNOFF XML for ammonia"""
     return ForceField(get_test_file_path("ammonia.offxml"))
Ejemplo n.º 26
0
 def argon_ff(self):
     """Fixture that loads an SMIRNOFF XML for argon"""
     return ForceField(get_test_file_path("argon.offxml"))
Ejemplo n.º 27
0
def test_ethanol_opls():
    mol = Molecule.from_smiles("CC")
    mol.generate_conformers(n_conformers=1)
    top = mol.to_topology()
    parsley = ForceField("openff-1.0.0.offxml")
    out = parsley.create_openff_system(top)
    out.box = [4, 4, 4]
    out.positions = mol.conformers[0]
    out.positions = np.round(out.positions, 2)

    rb_torsions = RBTorsionHandler()
    smirks = "[#1:1]-[#6X4:2]-[#6X4:3]-[#1:4]"
    pot_key = PotentialKey(id=smirks)
    for proper in top.propers:
        top_key = TopologyKey(atom_indices=tuple(a.topology_atom_index
                                                 for a in proper))
        rb_torsions.slot_map.update({top_key: pot_key})

    # Values from HC-CT-CT-HC RB torsion
    # https://github.com/mosdef-hub/foyer/blob/7816bf53a127502520a18d76c81510f96adfdbed/foyer/forcefields/xml/oplsaa.xml#L2585
    pot = Potential(
        parameters={
            "c0": 0.6276 * kj_mol,
            "c1": 1.8828 * kj_mol,
            "c2": 0.0 * kj_mol,
            "c3": -2.5104 * kj_mol,
            "c4": 0.0 * kj_mol,
            "c5": 0.0 * kj_mol,
        })

    rb_torsions.potentials.update({pot_key: pot})

    out.handlers.update({"RBTorsions": rb_torsions})
    out.handlers.pop("ProperTorsions")

    gmx = get_openmm_energies(out, round_positions=3).energies["Torsion"]
    omm = get_gromacs_energies(out).energies["Torsion"]

    assert (gmx - omm).value_in_unit(omm_unit.kilojoule_per_mole) < 1e-3

    # Given that these force constants are copied from Foyer's OPLS-AA file,
    # compare to processing through the current MoSDeF pipeline
    try:
        import foyer
        import mbuild
    except ModuleNotFoundError:
        return

    comp = mbuild.load("CC", smiles=True)
    comp.xyz = mol.conformers[0].value_in_unit(omm_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"]

    assert (omm - rb_torsion_energy_from_foyer).value_in_unit(
        omm_unit.kilojoule_per_mole) < 1e-3