{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Note: \n", " Interchange is in the process of replacing ParmEd in many workflows, but it still in an alpha testing phase. Our internal tests indicate it is reliable for many small-molecule systems, but it is not yet reliable for complex, multi-component systems and there are likely still rough edges throughout. Feedback is welcome on the Interchange issue tracker.
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using OpenFF force fields in Amber and GROMACS\n", "\n", "The Open Forcefield Toolkit can create parametrized `openmm.System` objects that can be natively simulated with OpenMM. This example shows the Interchange project can enable parallel workflows using Amber and GROMACS." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preparing an OpenFF Topology\n", "\n", "We start by loading a PDB file containing one copy of ethanol and cyclohexane. Our goal is to create an OpenFF `Topology` object describing this system that we can parametrize with the SMIRNOFF-format \"Sage\" force field.\n", "\n", "The two `Molecule` objects created from the SMILES strings can contain information such as partial charges and stereochemistry that is not included in an OpenMM topology. In this example, partial charges are not explicitly given, and `ForceField` will assign AM1/BCC charges as specified by the \"Sage\" force field. Note that the OpenFF Toolkit produces partial charges that do not depend on the input conformation of parameterized molecules. See the [FAQ](https://open-forcefield-toolkit.readthedocs.io/en/latest/faq.html#the-partial-charges-generated-by-the-toolkit-don-t-seem-to-depend-on-the-molecule-s-conformation-is-this-a-bug) for more information." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " from openmm import app\n", "except ImportError:\n", " from simtk.openmm import app\n", "\n", "from openff.toolkit.topology import Molecule, Topology\n", "from openff.toolkit.typing.engines.smirnoff import ForceField" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ethanol = Molecule.from_smiles(\"CCO\")\n", "cyclohexane = Molecule.from_smiles(\"C1CCCCC1\")\n", "\n", "# Load the PDB file using OpenMM and save the OpenMM Topology\n", "pdbfile = app.PDBFile(\"1_cyclohexane_1_ethanol.pdb\")\n", "omm_topology = pdbfile.topology\n", "\n", "# Create the OpenFF Topology.\n", "off_topology = Topology.from_openmm(\n", " omm_topology, unique_molecules=[ethanol, cyclohexane]\n", ")\n", "off_topology" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preparing an OpenFF ForceField\n", "\n", "Once the `ForceField` class is imported, the only decision to make is which force field to use. An exhaustive list of force fields released by the Open Force Field Initiative can be found [here](from openff.toolkit.typing.engines.smirnoff import ForceField\n", ").\n", "\n", "Here we will use force field from the \"Sage\" line." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "forcefield = ForceField(\"openff-2.0.0.offxml\")\n", "forcefield" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preparing an OpenMM System\n", "\n", "Once a force field and topology have been loaded, an `openmm.System` can be generated natively with the OpenFF Toolkit." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "omm_system = forcefield.create_openmm_system(off_topology)\n", "omm_system" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preparing an Interchange object\n", "\n", "To exports to engines other than OpenMM, we will make use of the [Interchange](https://openff-interchange.readthedocs.io/) project. There is a high-level `Interchange.from_smirnoff` function that consumes OpenFF Toolkit and ForceField objects and produces an `Interchange` object which can then be exported to formats understood by other molecular simulation engines. This extra step is needed to provide a clean interface between _applied_ parameters and engines. Note also that this step does not require an OpenMM System to be generated; `ForceField.create_openmm_system` does not need to be called to use Amber and GROMACS." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from openff.interchange.components.interchange import Interchange\n", "\n", "interchange = Interchange.from_smirnoff(\n", " force_field=forcefield,\n", " topology=off_topology,\n", ")\n", "interchange.positions = pdbfile.positions\n", "interchange" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exporting to Amber and GROMACS files\n", "\n", "Once an `Interchange` object has been constructed, its API can be used to export to files understood by GROMACS, Amber, and more." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Export AMBER files.\n", "interchange.to_prmtop(\"system.prmtop\")\n", "interchange.to_inpcrd(\"system.inpcrd\")\n", "\n", "# Export GROMACS files.\n", "interchange.to_top(\"system.top\")\n", "interchange.to_gro(\"system.gro\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Validating the conversion to Amber files\n", "\n", "The Interchange project includes functions that take in an `Interchange` object and call out to simulation engines to run single-point energy calculations (with no minimization or dynamics) for the purpose of validating the export layer with each engine. Under the hood, each of these functions calls API points like those used above while converting to files understood by each engine. These rely on having each engine installed and accessible in the current `$PATH`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from openff.interchange.drivers import get_amber_energies, get_openmm_energies" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "openmm_energies = get_openmm_energies(interchange)\n", "openmm_energies.energies" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "!cat system.inpcrd\n", "!cat system.prmtop\n", "!cat system.top\n", "!cat system.gro\n", "amber_energies = get_amber_energies(interchange)\n", "amber_energies.energies" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Appendix: Validating the conversion to GROMACS and LAMMPS files\n", "\n", "If GROMACS and/or LAMMPS are installed on your machine, the same comparisons can also take place with those engines. They are available via `conda` by running a command like:\n", "\n", "```conda install gromacs lammps -c conda-forge -c bioconda```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from distutils.spawn import find_executable\n", "from pprint import pprint\n", "\n", "from openff.interchange.drivers import get_gromacs_energies, get_lammps_energies" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if find_executable(\"lmp_serial\"):\n", " pprint(get_lammps_energies(interchange).energies)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if find_executable(\"gmx\"):\n", " pprint(get_gromacs_energies(interchange).energies)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, there is a helper function `get_summary_data` that will attempt to run drivers of each engine. A summary reported is prepared as a Pandas `DataFrame`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from openff.interchange.drivers.all import get_summary_data\n", "\n", "get_summary_data(interchange)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 4 }