コード例 #1
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
コード例 #2
0
def top_from_smiles(
    smiles: str,
    n_molecules: int = 1,
) -> Topology:
    """Create a gas phase OpenFF Topology from a single-molecule SMILES

    Parameters
    ----------
    smiles : str
        The SMILES of the input molecule
    n_molecules : int, optional, default = 1
        The number of copies of the SMILES molecule from which to
        compose a topology

    Returns
    -------
    top : opennff.toolkit.topology.Topology
        A single-molecule, gas phase-like topology

    """
    mol = Molecule.from_smiles(smiles)
    mol.generate_conformers(n_conformers=1)
    top = Topology.from_molecules(n_molecules * [mol])
    # Add dummy box vectors
    # TODO: Revisit if/after Topology.is_periodic
    top.box_vectors = np.eye(3) * 10 * unit.nanometer
    return top
コード例 #3
0
    def test_constraint_reassignment(self, parsley):
        """Test that constraints already existing in a parametrized system
        can be updated against new force field data"""
        # TODO: Replace with more minimal force field

        top = Topology.from_molecules(Molecule.from_smiles("CCO"))
        constrained = parsley.create_openff_system(top)

        assert len(constrained.handlers["Constraints"].slot_map.keys()) == 6

        # Update Parsley to also constrain C-O bonds
        parsley["Constraints"].add_parameter({"smirks": "[#6:1]-[#8:2]"})

        constrained.handlers["Constraints"].store_matches(
            parameter_handler=parsley["Constraints"],
            topology=top,
        )

        from openff.system.components.smirnoff import SMIRNOFFBondHandler

        bond_handler = SMIRNOFFBondHandler()
        bond_handler.store_matches(parameter_handler=parsley["Bonds"],
                                   topology=top)
        bond_handler.store_potentials(parameter_handler=parsley["Bonds"])

        constrained.handlers["Constraints"].store_constraints(
            parameter_handler=parsley["Constraints"],
            bond_handler=bond_handler,
        )

        assert len(constrained.handlers["Constraints"].slot_map.keys()) == 7
コード例 #4
0
    def test_to_openmm_assign_unique_atom_names_some_duplicates(self):
        """
        Ensure that OFF topologies where some molecules have invalid/duplicate
        atom names have unique atom names applied while the other molecules are unaffected.
        """
        # Create OpenFF topology with 1 ethanol and 2 benzenes.
        ethanol = Molecule.from_smiles("CCO")

        # Assign duplicate atom names in ethanol (two AT0s)
        ethanol_atom_names_with_duplicates = [
            f"AT{i}" for i in range(ethanol.n_atoms)
        ]
        ethanol_atom_names_with_duplicates[1] = "AT0"
        for atom, atom_name in zip(ethanol.atoms,
                                   ethanol_atom_names_with_duplicates):
            atom.name = atom_name

        # Assign unique atom names in benzene
        benzene = Molecule.from_smiles("c1ccccc1")
        benzene_atom_names = [f"AT{i}" for i in range(benzene.n_atoms)]
        for atom, atom_name in zip(benzene.atoms, benzene_atom_names):
            atom.name = atom_name

        off_topology = Topology.from_molecules(
            molecules=[ethanol, benzene, benzene])
        omm_topology = off_topology.to_openmm()
        atom_names = set()
        for atom in omm_topology.atoms():
            atom_names.add(atom.name)

        # There should be  12 "AT#"-labeled atoms (from benzene), 2 unique Cs,
        # 1 unique O, and 6 unique Hs, for a total of 21 unique atom names
        assert len(atom_names) == 21
コード例 #5
0
    def _off_handler(cls, molecule, **kwargs):
        forcefield = cls._get_forcefield(**kwargs)
        topology = Topology.from_molecules(molecule)
        openmm_system = forcefield.create_openmm_system(
            topology, charge_from_molecules=[molecule])

        # ligand_pmd.title = cls.smiles

        # for i in ligand_pmd.residues:
        #     i.name = 'LIG' #XXX no longer needed when using omm_top to create parmed structure

        tmp_dir = tempfile.mkdtemp()
        # We need all molecules as both pdb files (as packmol input)
        # and mdtraj.Trajectory for restoring bonds later.
        pdb_filename = tempfile.mktemp(suffix=".pdb", dir=tmp_dir)

        # XXX legacy code for save a pdb copy for simulation box creation
        # Chem.MolToPDBFile(mol, pdb_filename)
        # from openeye import oechem # OpenEye Python toolkits
        # oechem.OEWriteMolecule( oechem.oemolostream( pdb_filename ), mol)

        # XXX swtich to off save pdb
        # ligand_pmd.save(pdb_filename, overwrite=True)
        molecule.to_file(pdb_filename, "pdb")
        omm_top = PDBFile(pdb_filename).topology
        # ligand_pmd = parmed.openmm.topsystem.load_topology(topology.to_openmm(), openmm_system, molecule._conformers[0]) #XXX off topology does not keep atom names and resnames, use omm topology instead
        ligand_pmd = parmed.openmm.topsystem.load_topology(
            omm_top, openmm_system, molecule._conformers[0])

        return pdb_filename, ligand_pmd
コード例 #6
0
def get_assigned_torsion_param(molecule, forcefield, dihedrals):
    """
    for a molecule and specific dihedral check the assigned torsion parameter
    Parameters
    ----------
    molecule: openforcefield molecule object
    ff: ForceField offxml file
    dihedrals: list of atom indices in the dihedral

    Returns
    -------
    parameter.id: str of the torsion parameter associated with the dihedral
    """
    topology = Topology.from_molecules([molecule])
    # Run the molecule labeling
    molecule_force_list = forcefield.label_molecules(topology)

    # Print out a formatted description of the parameters applied to this molecule
    for mol_idx, mol_forces in enumerate(molecule_force_list):
        for force_tag, force_dict in mol_forces.items():
            if force_tag == "ProperTorsions":
                for (atom_indices, parameter) in force_dict.items():
                    if atom_indices == tuple(dihedrals) or tuple(
                        reversed(atom_indices)
                    ) == tuple(dihedrals):
                        return parameter.id
コード例 #7
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,
    )
コード例 #8
0
 def test_gro_file_all_zero_positions(self, parsley):
     top = Topology.from_molecules(Molecule.from_smiles("CC"))
     zero_positions = Interchange.from_smirnoff(force_field=parsley,
                                                topology=top)
     zero_positions.positions = np.zeros(
         (top.n_topology_atoms, 3)) * unit.nanometer
     with pytest.warns(UserWarning, match="seem to all be zero"):
         zero_positions.to_gro("foo.gro")
コード例 #9
0
def _create_impropers_only_system(
    smiles: str = "CC1=C(C(=O)C2=C(C1=O)N3CC4C(C3(C2COC(=O)N)OC)N4)N",
) -> mm.System:
    """Create a simulation that contains only improper torsion terms,
    by parameterizing with openff-1.2.0 and deleting  all terms but impropers
    """

    molecule = Molecule.from_smiles(smiles, allow_undefined_stereo=True)
    g = esp.Graph(molecule)

    topology = Topology.from_molecules(molecule)
    forcefield = ForceField("openff-1.2.0.offxml")
    openmm_system = forcefield.create_openmm_system(topology)

    # delete all forces except PeriodicTorsionForce
    is_torsion = (
        lambda force: "PeriodicTorsionForce" in force.__class__.__name__
    )
    for i in range(openmm_system.getNumForces())[::-1]:
        if not is_torsion(openmm_system.getForce(i)):
            openmm_system.removeForce(i)
    assert openmm_system.getNumForces() == 1
    torsion_force = openmm_system.getForce(0)
    assert is_torsion(torsion_force)

    # set k = 0 for any torsion that's not an improper
    indices = set(
        map(
            tuple,
            esp.graphs.utils.offmol_indices.improper_torsion_indices(
                molecule
            ),
        )
    )
    num_impropers_retained = 0
    for i in range(torsion_force.getNumTorsions()):
        (
            p1,
            p2,
            p3,
            p4,
            periodicity,
            phase,
            k,
        ) = torsion_force.getTorsionParameters(i)

        if (p1, p2, p3, p4) in indices:
            num_impropers_retained += 1
        else:
            torsion_force.setTorsionParameters(
                i, p1, p2, p3, p4, periodicity, phase, 0.0
            )

    assert (
        num_impropers_retained > 0
    )  # otherwise this molecule is not a useful test case!

    return openmm_system, topology, g
コード例 #10
0
    def test_force_field_no_constraints(self, parsley_unconstrained):
        """Test that a force field _without_ a Constraints tag does not add a
        Constraints handler"""
        # TODO: Replace with more minimal force field

        top = Topology.from_molecules(Molecule.from_smiles("CC"))
        sys_out = parsley_unconstrained.create_openff_system(top)

        assert "Constraints" not in sys_out.handlers.keys()
コード例 #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)
コード例 #12
0
def test_nth_degree_neighbors(n_degrees, num_pairs):
    pass
    smiles = ["c1ccccc1", "N1ONON1"]
    topology = Topology.from_molecules(
        [Molecule.from_smiles(smi) for smi in smiles])

    # See test_molecule.TestMolecule.test_nth_degree_neighbors_rings for values
    num_pairs_found = len(
        [*topology.nth_degree_neighbors(n_degrees=n_degrees)])
    assert num_pairs_found == num_pairs
コード例 #13
0
    def test_to_from_openmm(self):
        """Test a round-trip OpenFF -> OpenMM -> OpenFF Topology."""
        from simtk.openmm.app import Aromatic

        # Create OpenFF topology with 1 ethanol and 2 benzenes.
        ethanol = Molecule.from_smiles("CCO")
        benzene = Molecule.from_smiles("c1ccccc1")
        off_topology = Topology.from_molecules(
            molecules=[ethanol, benzene, benzene])

        # Convert to OpenMM Topology.
        omm_topology = off_topology.to_openmm()

        # Check that bond orders are preserved.
        n_double_bonds = sum([b.order == 2 for b in omm_topology.bonds()])
        n_aromatic_bonds = sum(
            [b.type is Aromatic for b in omm_topology.bonds()])
        assert n_double_bonds == 6
        assert n_aromatic_bonds == 12

        # Check that there is one residue for each molecule.
        assert omm_topology.getNumResidues() == 3
        assert omm_topology.getNumChains() == 3

        # Convert back to OpenFF Topology.
        off_topology_copy = Topology.from_openmm(
            omm_topology, unique_molecules=[ethanol, benzene])

        # The round-trip OpenFF Topology is identical to the original.
        # The reference molecules are the same.
        assert (off_topology.n_reference_molecules ==
                off_topology_copy.n_reference_molecules)
        reference_molecules_copy = list(off_topology_copy.reference_molecules)
        for ref_mol_idx, ref_mol in enumerate(
                off_topology.reference_molecules):
            assert ref_mol == reference_molecules_copy[ref_mol_idx]

        # The number of topology molecules is the same.
        assert (off_topology.n_topology_molecules ==
                off_topology_copy.n_topology_molecules)

        # Check atoms.
        assert off_topology.n_topology_atoms == off_topology_copy.n_topology_atoms
        for atom_idx, atom in enumerate(off_topology.topology_atoms):
            atom_copy = off_topology_copy.atom(atom_idx)
            assert atom.atomic_number == atom_copy.atomic_number

        # Check bonds.
        for bond_idx, bond in enumerate(off_topology.topology_bonds):
            bond_copy = off_topology_copy.bond(bond_idx)
            bond_atoms = [a.atomic_number for a in bond.atoms]
            bond_atoms_copy = [a.atomic_number for a in bond_copy.atoms]
            assert bond_atoms == bond_atoms_copy
            assert bond.bond_order == bond_copy.bond_order
            assert bond.bond.is_aromatic == bond_copy.bond.is_aromatic
コード例 #14
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)
コード例 #15
0
    def test_default_am1bcc_charge_assignment(self, parsley):
        top = Topology.from_molecules([
            Molecule.from_smiles("C"),
            Molecule.from_smiles("C=C"),
            Molecule.from_smiles("CCO"),
        ])

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

        compare_charges_omm_off(reference, new)
コード例 #16
0
    def test_from_parsley(self, parsley):
        top = Topology.from_molecules(
            [Molecule.from_smiles("CCO"),
             Molecule.from_smiles("CC")])

        out = parsley.create_openff_system(top)

        assert "Constraints" in out.handlers.keys()
        assert "Bonds" in out.handlers.keys()
        assert "Angles" in out.handlers.keys()
        assert "ProperTorsions" in out.handlers.keys()
        assert "vdW" in out.handlers.keys()
コード例 #17
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)
コード例 #18
0
    def test_no_matched_constraints(self, parsley):
        """Test that a force field with a Constraints tag adds an empty
        Constraints handler when the topology does not match any parameters"""
        # TODO: Replace with more minimal force field

        top = Topology.from_molecules(Molecule.from_smiles("O=C=O"))
        sys_out = parsley.create_openff_system(top)

        assert "Constraints" in sys_out.handlers.keys()

        constraints = sys_out.handlers["Constraints"]
        assert constraints.slot_map == dict()
        assert constraints.constraints == dict()
コード例 #19
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,
        },
    )
コード例 #20
0
    def test_multi_mol_topology_to_compound(self):
        """Test the basic behavior of a (multi-mol) OFFTop"""
        ethanol = Molecule.from_smiles("CCO")
        ethanol.name = "ETH"
        methane = Molecule.from_smiles("C")
        methane.name = "MET"

        top = Topology.from_molecules([ethanol, ethanol, methane, methane])

        comp = offtop_to_compound(top)

        assert comp.n_particles == 28  # 2 * (9 + 5)
        assert comp.n_bonds == 24  # 2 * (8 + 4)
        assert len(comp.children) == 4  # 4 "molecules"
コード例 #21
0
def water_box_topology() -> Topology:
    mol = Molecule.from_smiles("O")
    mol.generate_conformers()

    n_molecules = 256

    topology: Topology = Topology.from_molecules([mol] * n_molecules)

    # Create some coordinates (without the v-sites) and estimate box vectors.
    topology.box_vectors = (numpy.eye(3) *
                            math.ceil(n_molecules**(1 / 3) + 2) * 2.5 *
                            unit.angstrom)

    return topology
コード例 #22
0
def checkTorsion(molList, ff_name):
    """
    Take mollist and check if the molecules in a list match a specific torsion id

        Parameters
        ----------
        molList : List of objects
            List of oemols with datatags generated in genData function

        Returns
        -------
        molList : list of objects
            List of oemol objects that have a datatag "IDMatch" that contain the torsion id
            involved in the QCA torsion drive
    """

    matches = []
    count = 0
    mols = []
    for mol in molList:
        molecule = Molecule.from_mapped_smiles(mol.GetData("cmiles"))
        topology = Topology.from_molecules(molecule)
        # Let's label using the Parsley force field
        forcefield = ForceField(ff_name, allow_cosmetic_attributes=True)
        # Run the molecule labeling
        molecule_force_list = forcefield.label_molecules(topology)
        params = []
        # Print out a formatted description of the torsion parameters applied to this molecule
        for mol_idx, mol_forces in enumerate(molecule_force_list):
            # print(f'Forces for molecule {mol_idx}')
            for force_tag, force_dict in mol_forces.items():
                if force_tag == "ProperTorsions":
                    for (atom_indices, parameter) in force_dict.items():
                        params.append(parameter.id)
                        if atom_indices == mol.GetData("TDindices") or tuple(
                            reversed(atom_indices)
                        ) == mol.GetData("TDindices"):
                            count += 1
                            mol.SetData("IDMatch", parameter.id)
                            mols.append(mol)
    print(
        "Out of "
        + str(len(molList))
        + " molecules, "
        + str(count)
        + " were processed with checkTorsion()"
    )

    return mols
コード例 #23
0
    def test_force_field_basic_constraints(self, parsley):
        """Test that a force field Constraints tag adds a
        Constraints handler with expected data"""
        # TODO: Replace with more minimal force field

        top = Topology.from_molecules(Molecule.from_smiles("CC"))
        sys_out = parsley.create_openff_system(top)

        assert "Constraints" in sys_out.handlers.keys()
        constraints = sys_out.handlers["Constraints"]
        assert "(0, 1)" not in constraints.slot_map.keys()  # C-C bond
        assert "(0, 2)" in constraints.slot_map.keys()  # C-H bond
        assert len(constraints.slot_map.keys()) == 6  # number of C-H bonds
        assert len({constraints.slot_map.values()}) == 1  # always True
        assert constraints.constraints[constraints.slot_map["(0, 2)"]] is True
コード例 #24
0
 def test_to_openmm_assign_unique_atom_names(self):
     """
     Ensure that OFF topologies with no pre-existing atom names have unique
     atom names applied when being converted to openmm
     """
     # Create OpenFF topology with 1 ethanol and 2 benzenes.
     ethanol = Molecule.from_smiles("CCO")
     benzene = Molecule.from_smiles("c1ccccc1")
     off_topology = Topology.from_molecules(
         molecules=[ethanol, benzene, benzene])
     omm_topology = off_topology.to_openmm()
     atom_names = set()
     for atom in omm_topology.atoms():
         atom_names.add(atom.name)
     # There should be 6 unique Cs, 6 unique Hs, and 1 unique O, for a total of 13 unique atom names
     assert len(atom_names) == 13
コード例 #25
0
def test_argon_buck():
    mol = Molecule.from_smiles("[#18]")
    top = Topology.from_molecules([mol, mol])

    A = 1.69e-8 * unit.Unit("erg / mol") * Avogadro
    B = 1 / (0.273 * unit.angstrom)
    C = 102e-12 * unit.Unit("erg / mol") * unit.angstrom**6 * Avogadro

    A = A.to(unit.Unit("kilojoule/mol"))
    B = B.to(unit.Unit("1 / nanometer"))
    C = C.to(unit.Unit("kilojoule / mol * nanometer ** 6"))

    r = 0.3 * unit.nanometer

    buck = BuckinghamvdWHandler()
    coul = ElectrostaticsMetaHandler()  # Just to pass compatibility checks

    pot_key = PotentialKey(id="[#18]")
    pot = Potential(parameters={"A": A, "B": B, "C": C})

    for top_atom in top.topology_atoms:
        top_key = TopologyKey(atom_indices=(top_atom.topology_atom_index, ))
        buck.slot_map.update({top_key: pot_key})
        coul.charges.update({top_key: 0 * unit.elementary_charge})

    buck.potentials[pot_key] = pot

    from openff.system.components.system import System

    out = System()
    out.handlers["Buckingham-6"] = buck
    out.handlers["Electrostatics"] = coul
    out.topology = top
    out.box = [10, 10, 10] * unit.nanometer
    out.positions = [[0, 0, 0], [0.3, 0, 0]] * unit.nanometer
    out.to_gro("out.gro", writer="internal")
    out.to_top("out.top", writer="internal")

    gmx_energies = get_gromacs_energies(out, mdp="cutoff_buck")
    omm_energies = get_openmm_energies(out)
    by_hand = A * exp(-B * r) - C * r**-6

    gmx_energies.compare(omm_energies)

    resid = simtk_to_pint(gmx_energies.energies["Nonbonded"]) - by_hand
    assert resid < 1e-5 * unit.kilojoule / unit.mol
コード例 #26
0
    def test_pruned_impropers(self):
        """Test {smirnoff|amber}_impropers from the Topology API"""
        top = Topology.from_molecules(
            [Molecule.from_smiles(smi) for smi in ["N", "C=C"]])

        assert len([*top.smirnoff_impropers]) == 18
        assert len([*top.amber_impropers]) == 18

        # Order not guaranteed, so cannot zip and compare directly
        for smirnoff_imp in top.smirnoff_impropers:
            # Convert SMIRNOFF-style improper into AMBER-style
            mod_imp = (
                smirnoff_imp[1],
                smirnoff_imp[0],
                smirnoff_imp[2],
                smirnoff_imp[3],
            )
            assert mod_imp in top.amber_impropers
コード例 #27
0
def test_smirnoff_hack():
    """Test basic behavior of smirnoff_hack.py, in particular
    the compatibility with Molecule API"""
    from openff.toolkit.topology import Molecule, Topology
    from openff.toolkit.typing.engines.smirnoff import ForceField
    from openff.toolkit.utils.toolkits import (AmberToolsToolkitWrapper,
                                               RDKitToolkitWrapper,
                                               ToolkitRegistry)

    from forcebalance import smirnoff_hack

    top = Topology.from_molecules(Molecule.from_smiles("CCO"))
    parsley = ForceField("openff-1.0.0.offxml")

    registry = ToolkitRegistry()
    registry.register_toolkit(RDKitToolkitWrapper)
    registry.register_toolkit(AmberToolsToolkitWrapper)
    parsley.create_openmm_system(top, toolkit_registry=registry)
コード例 #28
0
def test_from_openmm_single_mols(mol, n_mols):
    """
    Test that ForceField.create_openmm_system and Interchange.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) * simtk_unit.angstrom

    top.box_vectors = np.eye(3) * np.asarray([15, 15, 15]) * simtk_unit.nanometer

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

    toolkit_system = parsley.create_openmm_system(top)

    native_system = Interchange.from_smirnoff(
        force_field=parsley, topology=top
    ).to_openmm()

    toolkit_energy = _get_openmm_energies(
        omm_sys=toolkit_system,
        box_vectors=toolkit_system.getDefaultPeriodicBoxVectors(),
        positions=positions,
    )
    native_energy = _get_openmm_energies(
        omm_sys=native_system,
        box_vectors=native_system.getDefaultPeriodicBoxVectors(),
        positions=positions,
    )

    toolkit_energy.compare(native_energy)
コード例 #29
0
ファイル: test_energies.py プロジェクト: LaYeqa/openff-system
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,
        },
    )
コード例 #30
0
 def test_to_openmm_assign_some_unique_atom_names(self):
     """
     Ensure that OFF topologies with some pre-existing atom names have unique
     atom names applied to the other atoms when being converted to openmm
     """
     # Create OpenFF topology with 1 ethanol and 2 benzenes.
     ethanol = Molecule.from_smiles("CCO")
     for atom in ethanol.atoms:
         atom.name = f"AT{atom.molecule_atom_index}"
     benzene = Molecule.from_smiles("c1ccccc1")
     off_topology = Topology.from_molecules(
         molecules=[ethanol, benzene, benzene])
     omm_topology = off_topology.to_openmm()
     atom_names = set()
     for atom in omm_topology.atoms():
         atom_names.add(atom.name)
     # There should be 9 "ATOM#"-labeled atoms, 6 unique Cs, and 6 unique Hs,
     # for a total of 21 unique atom names
     assert len(atom_names) == 21