Example #1
0
def _write_atomtypes_buck(openff_sys: "System", top_file: IO, typemap: Dict):

    top_file.write("[ atomtypes ]\n")
    top_file.write(
        ";type, bondingtype, atomic_number, mass, charge, ptype, sigma, epsilon\n"
    )

    for atom_idx, atom_type in typemap.items():
        atom = openff_sys.topology.atom(atom_idx)  # type: ignore
        element = ele.element_from_atomic_number(atom.atomic_number)
        parameters = _get_buck_parameters(openff_sys, atom_idx)
        a = parameters["A"].to(unit.Unit("kilojoule / mol")).magnitude
        b = parameters["B"].to(1 / unit.nanometer).magnitude
        c = parameters["C"].to(unit.Unit("kilojoule / mol * nanometer ** 6")).magnitude

        top_file.write(
            "{:<11s} {:6d} {:.16g} {:.16g} {:5s} {:.16g} {:.16g} {:.16g}".format(
                atom_type,  # atom type
                # "XX",  # atom "bonding type", i.e. bond class
                atom.atomic_number,
                element.mass,
                0.0,  # charge, overriden later in [ atoms ]
                "A",  # ptype
                a,
                b,
                c,
            )
        )
        top_file.write("\n")
Example #2
0
def _process_proper_torsion_forces(openff_sys, openmm_sys):
    """Process the Propers section of an OpenFF System into corresponding
    forces within an openmm.PeriodicTorsionForce"""
    torsion_force = openmm.PeriodicTorsionForce()
    openmm_sys.addForce(torsion_force)

    proper_torsion_handler = openff_sys.handlers["ProperTorsions"]

    for top_key, pot_key in proper_torsion_handler.slot_map.items():
        indices = top_key.atom_indices
        params = proper_torsion_handler.potentials[pot_key].parameters

        k = params["k"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        periodicity = int(params["periodicity"])
        phase = params["phase"].to(off_unit.degree).magnitude
        phase = phase * unit.degree / unit.radian
        idivf = int(params["idivf"])
        torsion_force.addTorsion(
            indices[0],
            indices[1],
            indices[2],
            indices[3],
            periodicity,
            phase,
            k / idivf,
        )
Example #3
0
def _process_bond_forces(openff_sys, openmm_sys):
    """Process the Bonds section of an OpenFF System into a corresponding openmm.HarmonicBondForce"""
    harmonic_bond_force = openmm.HarmonicBondForce()
    openmm_sys.addForce(harmonic_bond_force)

    try:
        bond_handler = openff_sys.handlers["Bonds"]
    except KeyError:
        return

    try:
        constraint_handler = openff_sys.handlers["Constraints"]
        has_constraint_handler = True
    except KeyError:
        has_constraint_handler = False

    for top_key, pot_key in bond_handler.slot_map.items():
        if has_constraint_handler:
            # If this bond show up in the constraints ...
            if top_key in constraint_handler.slot_map:
                # ... don't add it as an interacting bond
                continue
        indices = top_key.atom_indices
        params = bond_handler.potentials[pot_key].parameters
        k = params["k"].to(off_unit.Unit(
            str(kcal_ang))).magnitude * kcal_ang / kj_nm
        length = params["length"].to(off_unit.nanometer).magnitude

        harmonic_bond_force.addBond(
            particle1=indices[0],
            particle2=indices[1],
            length=length,
            k=k,
        )
Example #4
0
def _from_omm_quantity(val):
    """Helper function to convert float quantities tagged with SimTK/OpenMM units to
    a Pint-compatible quantity"""
    assert type(val.value_in_unit(val.unit)) in {float, int}
    unit_ = val.unit
    quantity_ = val.value_in_unit(unit_)
    return quantity_ * unit.Unit(str(unit_))
Example #5
0
def _write_improper_coeffs(lmp_file: IO, openff_sys: System):
    lmp_file.write("\nImproper Coeffs\n\n")

    improper_handler = openff_sys.handlers["ImproperTorsions"]
    improper_type_map = dict(enumerate(improper_handler.potentials))

    for improper_type_idx, smirks in improper_type_map.items():
        params = improper_handler.potentials[smirks].parameters

        k = params["k"].to(unit.Unit("kilocalorie / mole")).magnitude
        n = int(params["periodicity"])
        phase = params["phase"].to(unit.degree).magnitude
        idivf = int(params["idivf"])
        k = k / idivf

        if (phase != 180) or (n != 2):
            raise UnsupportedExportError(
                "Improper exports to LAMMPS are funky and not well-supported "
                "at the moment, see PR #126")

        # See https://lammps.sandia.gov/doc/improper_fourier.html
        # cos(n * x - pi) == - cos(n * x)
        # k * (1 + cos(n * phi - pi / 2)) == k * (1 - cos(n * phi))
        d = -1

        lmp_file.write(
            f"{improper_type_idx+1:d} cvff {k:.16g}\t{d:d}\t{n:.16g}\n")

    lmp_file.write("\n")
Example #6
0
def _process_angle_forces(openff_sys, openmm_sys):
    """Process the Angles section of an OpenFF System into a corresponding openmm.HarmonicAngleForce"""
    harmonic_angle_force = openmm.HarmonicAngleForce()
    openmm_sys.addForce(harmonic_angle_force)

    try:
        angle_handler = openff_sys.handlers["Angles"]
    except KeyError:
        return

    for top_key, pot_key in angle_handler.slot_map.items():
        indices = top_key.atom_indices
        params = angle_handler.potentials[pot_key].parameters
        k = params["k"].to(off_unit.Unit(str(kcal_rad))).magnitude
        k = k * kcal_rad / kj_rad
        angle = params["angle"].to(off_unit.degree).magnitude
        angle = angle * unit.degree / unit.radian

        harmonic_angle_force.addAngle(
            particle1=indices[0],
            particle2=indices[1],
            particle3=indices[2],
            angle=angle,
            k=k,
        )
Example #7
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
Example #8
0
def _process_rb_torsion_forces(openff_sys, openmm_sys):
    """Process Ryckaert-Bellemans torsions"""
    rb_force = openmm.RBTorsionForce()
    openmm_sys.addForce(rb_force)

    rb_torsion_handler = openff_sys.handlers["RBTorsions"]

    for top_key, pot_key in rb_torsion_handler.slot_map.items():
        indices = top_key.atom_indices
        params = rb_torsion_handler.potentials[pot_key].parameters

        c0 = params["c0"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        c1 = params["c1"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        c2 = params["c2"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        c3 = params["c3"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        c4 = params["c4"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        c5 = params["c5"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        rb_force.addTorsion(
            indices[0],
            indices[1],
            indices[2],
            indices[3],
            c0,
            c1,
            c2,
            c3,
            c4,
            c5,
        )
Example #9
0
def _write_pair_coeffs(lmp_file: IO, openff_sys: System, atom_type_map: Dict):
    lmp_file.write("Pair Coeffs\n\n")

    vdw_handler = openff_sys["vdW"]

    for atom_type_idx, smirks in atom_type_map.items():
        params = vdw_handler.potentials[smirks].parameters

        sigma = params["sigma"].to(unit.angstrom).magnitude
        epsilon = params["epsilon"].to(
            unit.Unit("kilocalorie / mole")).magnitude

        lmp_file.write("{:d}\t{:.8g}\t{:.8g}\n".format(atom_type_idx + 1,
                                                       epsilon, sigma))

    lmp_file.write("\n")
Example #10
0
def simtk_to_pint(simtk_quantity):
    """
    Convert a SimTK Quantity (OpenMM Quantity) to a pint Quantity.

    Note: This function is adapted from evaluator.utils.openmm.openmm_quantity_to_pint,
    as part of the OpenFF Evaluator, Copyright (c) 2019 Open Force Field Consortium.
    """
    if isinstance(simtk_quantity, List):
        simtk_quantity = omm_unit.Quantity(simtk_quantity)
    openmm_unit = simtk_quantity.unit
    openmm_value = simtk_quantity.value_in_unit(openmm_unit)

    target_unit = unit_to_string(openmm_unit)
    target_unit = unit.Unit(target_unit)

    return openmm_value * target_unit
Example #11
0
def _write_bond_coeffs(lmp_file: IO, openff_sys: System):
    lmp_file.write("Bond Coeffs\n\n")

    bond_handler = openff_sys.handlers["Bonds"]
    bond_type_map = dict(enumerate(bond_handler.potentials))

    for bond_type_idx, smirks in bond_type_map.items():
        params = bond_handler.potentials[smirks].parameters

        k = params["k"].to(
            unit.Unit("kilocalorie / mole / angstrom ** 2")).magnitude
        k = k * 0.5  # Account for LAMMPS wrapping 1/2 into k
        length = params["length"].to(unit.angstrom).magnitude

        lmp_file.write(
            f"{bond_type_idx+1:d} harmonic\t{k:.16g}\t{length:.16g}\n")

    lmp_file.write("\n")
Example #12
0
def _write_angle_coeffs(lmp_file: IO, openff_sys: System):
    lmp_file.write("\nAngle Coeffs\n\n")

    angle_handler = openff_sys.handlers["Angles"]
    angle_type_map = dict(enumerate(angle_handler.potentials))

    for angle_type_idx, smirks in angle_type_map.items():
        params = angle_handler.potentials[smirks].parameters

        k = params["k"].to(
            unit.Unit("kilocalorie / mole / radian ** 2")).magnitude
        k = k * 0.5  # Account for LAMMPS wrapping 1/2 into k
        theta = params["angle"].to(unit.degree).magnitude

        lmp_file.write(
            f"{angle_type_idx+1:d} harmonic\t{k:.16g}\t{theta:.16g}\n")

    lmp_file.write("\n")
Example #13
0
def _process_bond_forces(openff_sys, openmm_sys):
    """Process the Bonds section of an OpenFF System into a corresponding openmm.HarmonicBondForce"""
    harmonic_bond_force = openmm.HarmonicBondForce()
    openmm_sys.addForce(harmonic_bond_force)

    bond_handler = openff_sys.handlers["Bonds"]
    for bond, key in bond_handler.slot_map.items():
        indices = eval(bond)
        params = bond_handler.potentials[key].parameters
        k = params["k"].to(off_unit.Unit(
            str(kcal_ang))).magnitude * kcal_ang / kj_nm
        length = params["length"].to(off_unit.nanometer).magnitude

        harmonic_bond_force.addBond(
            particle1=indices[0],
            particle2=indices[1],
            length=length,
            k=k,
        )
Example #14
0
def _write_proper_coeffs(lmp_file: IO, openff_sys: System):
    lmp_file.write("\nDihedral Coeffs\n\n")

    proper_handler = openff_sys.handlers["ProperTorsions"]
    proper_type_map = dict(enumerate(proper_handler.potentials))

    for proper_type_idx, smirks in proper_type_map.items():
        params = proper_handler.potentials[smirks].parameters

        k = params["k"].to(unit.Unit("kilocalorie / mole")).magnitude
        n = int(params["periodicity"])
        phase = params["phase"].to(unit.degree).magnitude
        idivf = int(params["idivf"])
        k = k / idivf

        lmp_file.write(
            f"{proper_type_idx+1:d} fourier 1\t{k:.16g}\t{n:d}\t{phase:.16g}\n"
        )

    lmp_file.write("\n")
Example #15
0
def _write_bonds(top_file: IO, openff_sys: "System", ref_mol: FrozenMolecule):
    if "Bonds" not in openff_sys.handlers.keys():
        return

    top_file.write("[ bonds ]\n")
    top_file.write("; ai\taj\tfunc\tr\tk\n")

    bond_handler = openff_sys.handlers["Bonds"]

    top_mol = openff_sys.topology._reference_molecule_to_topology_molecules[ref_mol][0]  # type: ignore

    offset = top_mol.atom_start_topology_index

    for bond in top_mol.bonds:
        # These are "topology indices"
        indices = tuple(sorted(a.topology_atom_index for a in bond.atoms))
        for top_key in bond_handler.slot_map:
            if top_key.atom_indices == indices:
                pot_key = bond_handler.slot_map[top_key]

        # "reference" indices
        ref_indices = [idx - offset for idx in indices]

        params = bond_handler.potentials[pot_key].parameters

        k = params["k"].to(unit.Unit("kilojoule / mole / nanometer ** 2")).magnitude
        length = params["length"].to(unit.nanometer).magnitude

        top_file.write(
            "{:7d} {:7d} {:4s} {:.16g} {:.16g}\n".format(
                ref_indices[0] + 1,  # atom i
                ref_indices[1] + 1,  # atom j
                str(1),  # bond type (functional form)
                length,
                k,
            )
        )

        del pot_key

    top_file.write("\n\n")
Example #16
0
def _process_improper_torsion_forces(openff_sys, openmm_sys):
    """Process the Impropers section of an OpenFF System into corresponding
    forces within an openmm.PeriodicTorsionForce"""
    if "ImproperTorsions" not in openff_sys.handlers.keys():
        raise Exception

    for force in openmm_sys.getForces():
        if type(force) == openmm.PeriodicTorsionForce:
            torsion_force = force
            break
    else:
        # TODO: Support case of no propers but some impropers?
        raise Exception

    improper_torsion_handler = openff_sys.handlers["ImproperTorsions"]

    for torsion_key, key in improper_torsion_handler.slot_map.items():
        torsion, idx = torsion_key.split("_")
        indices = eval(torsion)
        params = improper_torsion_handler.potentials[key].parameters

        k = params["k"].to(off_unit.Unit(
            str(kcal_mol))).magnitude * kcal_mol / kj_mol
        periodicity = int(params["periodicity"])
        phase = params["phase"].to(off_unit.degree).magnitude
        phase = phase * unit.degree / unit.radian
        idivf = int(params["idivf"])

        other_atoms = [indices[0], indices[2], indices[3]]
        for p in [(other_atoms[i], other_atoms[j], other_atoms[k])
                  for (i, j, k) in [(0, 1, 2), (1, 2, 0), (2, 0, 1)]]:
            torsion_force.addTorsion(
                indices[1],
                p[0],
                p[1],
                p[2],
                periodicity,
                phase,
                k / idivf,
            )
Example #17
0
def _write_angles(top_file: IO, openff_sys: "System", ref_mol: FrozenMolecule):
    if "Angles" not in openff_sys.handlers.keys():
        return

    top_file.write("[ angles ]\n")
    top_file.write("; ai\taj\tak\tfunc\tr\tk\n")

    top_mol = openff_sys.topology._reference_molecule_to_topology_molecules[ref_mol][0]  # type: ignore

    offset = top_mol.atom_start_topology_index

    angle_handler = openff_sys.handlers["Angles"]

    for angle in top_mol.angles:
        indices = tuple(a.topology_atom_index for a in angle)
        for top_key in angle_handler.slot_map:
            if top_key.atom_indices == indices:
                pot_key = angle_handler.slot_map[top_key]

        # "reference" indices
        ref_indices = [idx - offset for idx in indices]

        params = angle_handler.potentials[pot_key].parameters
        k = params["k"].to(unit.Unit("kilojoule / mole / radian ** 2")).magnitude
        theta = params["angle"].to(unit.degree).magnitude

        top_file.write(
            "{:7d} {:7d} {:7d} {:4s} {:.16g} {:.16g}\n".format(
                ref_indices[0] + 1,  # atom i
                ref_indices[1] + 1,  # atom j
                ref_indices[2] + 1,  # atom k
                str(1),  # angle type (functional form)
                theta,
                k,
            )
        )

    top_file.write("\n\n")
Example #18
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)
Example #19
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)
Example #20
0
from typing import TYPE_CHECKING, Dict

import numpy as np
import parmed as pmd

from openff.system import unit
from openff.system.components.potentials import Potential
from openff.system.models import PotentialKey, TopologyKey

if TYPE_CHECKING:
    from openff.system.components.system import System

kcal_mol = unit.Unit("kilocalories / mol")
kcal_mol_a2 = unit.Unit("kilocalories / mol / angstrom ** 2")
kcal_mol_rad2 = unit.Unit("kilocalories / mol / rad ** 2")


def to_parmed(off_system: "System") -> pmd.Structure:
    """Convert an OpenFF System to a ParmEd Structure"""
    structure = pmd.Structure()
    _convert_box(off_system.box, structure)

    if "Electrostatics" in off_system.handlers.keys():
        has_electrostatics = True
        electrostatics_handler = off_system.handlers["Electrostatics"]
    else:
        has_electrostatics = False

    for topology_molecule in off_system.topology.topology_molecules:  # type: ignore[union-attr]
        for atom in topology_molecule.atoms:
            atomic_number = atom.atomic_number
Example #21
0
def _write_dihedrals(top_file: IO, openff_sys: "System", ref_mol: FrozenMolecule):
    if "ProperTorsions" not in openff_sys.handlers:
        if "RBTorsions" not in openff_sys.handlers:
            if "ImproperTorsions" not in openff_sys.handlers:
                return

    top_file.write("[ dihedrals ]\n")
    top_file.write(";    i      j      k      l   func\n")

    top_mol = openff_sys.topology._reference_molecule_to_topology_molecules[ref_mol][0]  # type: ignore

    offset = top_mol.atom_start_topology_index

    rb_torsion_handler = (
        openff_sys.handlers["RBTorsions"] if "RBTorsions" in openff_sys.handlers else []
    )
    proper_torsion_handler = (
        openff_sys.handlers["ProperTorsions"]
        if "ProperTorsions" in openff_sys.handlers
        else []
    )
    improper_torsion_handler = (
        openff_sys.handlers["ImproperTorsions"]
        if "ImproperTorsions" in openff_sys.handlers
        else []
    )

    # TODO: Ensure number of torsions written matches what is expected
    for proper in top_mol.propers:
        if proper_torsion_handler:
            for top_key in proper_torsion_handler.slot_map:  # type: ignore[attr-defined]
                indices = tuple(a.topology_atom_index for a in proper)
                if top_key.atom_indices == indices:
                    pot_key = proper_torsion_handler.slot_map[top_key]  # type: ignore[attr-defined]
                    params = proper_torsion_handler.potentials[pot_key].parameters  # type: ignore[attr-defined]

                    # "reference" indices
                    ref_indices = [idx - offset for idx in indices]

                    k = params["k"].to(unit.Unit("kilojoule / mol")).magnitude
                    periodicity = int(params["periodicity"])
                    phase = params["phase"].to(unit.degree).magnitude
                    idivf = int(params["idivf"]) if "idivf" in params else 1
                    top_file.write(
                        "{:7d} {:7d} {:7d} {:7d} {:6d} {:16g} {:16g} {:7d}\n".format(
                            ref_indices[0] + 1,
                            ref_indices[1] + 1,
                            ref_indices[2] + 1,
                            ref_indices[3] + 1,
                            1,
                            phase,
                            k / idivf,
                            periodicity,
                        )
                    )
        # This should be `if` if a single quartet can be subject to both proper and RB torsions
        elif rb_torsion_handler:
            for top_key in rb_torsion_handler.slot_map:  # type: ignore[attr-defined]
                indices = tuple(a.topology_atom_index for a in proper)
                if top_key.atom_indices == indices:
                    pot_key = rb_torsion_handler.slot_map[top_key]  # type: ignore[attr-defined]
                    params = rb_torsion_handler.potentials[pot_key].parameters  # type: ignore[attr-defined]

                    # "reference" indices
                    ref_indices = [idx - offset for idx in indices]

                    c0 = params["c0"].to(unit.Unit("kilojoule / mol")).magnitude
                    c1 = params["c1"].to(unit.Unit("kilojoule / mol")).magnitude
                    c2 = params["c2"].to(unit.Unit("kilojoule / mol")).magnitude
                    c3 = params["c3"].to(unit.Unit("kilojoule / mol")).magnitude
                    c4 = params["c4"].to(unit.Unit("kilojoule / mol")).magnitude
                    c5 = params["c5"].to(unit.Unit("kilojoule / mol")).magnitude

                    top_file.write(
                        "{:7d} {:7d} {:7d} {:7d} {:6d} "
                        "{:16g} {:16g} {:16g} {:16g} {:16g} {:16g} \n".format(
                            ref_indices[0] + 1,
                            ref_indices[1] + 1,
                            ref_indices[2] + 1,
                            ref_indices[3] + 1,
                            3,
                            c0,
                            c1,
                            c2,
                            c3,
                            c4,
                            c5,
                        )
                    )

    # TODO: Ensure number of torsions written matches what is expected
    for improper in top_mol.impropers:
        if improper_torsion_handler:
            for top_key in improper_torsion_handler.slot_map:  # type: ignore[attr-defined]
                indices = tuple(a.topology_atom_index for a in improper)
                if indices == top_key.atom_indices:
                    key = improper_torsion_handler.slot_map[top_key]  # type: ignore[attr-defined]
                    params = improper_torsion_handler.potentials[key].parameters  # type: ignore[attr-defined]

                    k = params["k"].to(unit.Unit("kilojoule / mol")).magnitude
                    periodicity = int(params["periodicity"])
                    phase = params["phase"].to(unit.degree).magnitude
                    idivf = int(params["idivf"])
                    top_file.write(
                        "{:7d} {:7d} {:7d} {:7d} {:6d} {:.16g} {:.16g} {:.16g}\n".format(
                            indices[0] + 1,
                            indices[1] + 1,
                            indices[2] + 1,
                            indices[3] + 1,
                            4,
                            phase,
                            k / idivf,
                            periodicity,
                        )
                    )
Example #22
0
from openff.toolkit.topology.molecule import Molecule
from simtk import unit as omm_unit

from openff.system import unit
from openff.system.components.misc import RBTorsionHandler
from openff.system.components.potentials import Potential
from openff.system.models import PotentialKey, TopologyKey
from openff.system.stubs import ForceField
from openff.system.tests.energy_tests.gromacs import (
    get_gromacs_energies,
    get_mdp_file,
    run_gmx_energy,
)
from openff.system.tests.energy_tests.openmm import get_openmm_energies

kj_mol = unit.Unit("kilojoule / mol")


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)