question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Parametrizing non-periodic topologies with mainline force fields changes non-bonded settings

See original GitHub issue

Describe the bug This is a long-standing mismatch between the SMIRNOFF spec and the implementation of ForceField.create_openmm_system. I’m not sure how to fix it here, nor am I sure it should be fixed here. I took a stab at something that might fix it in #920, but it blew up in complexity and won’t be implemented here. It’s also been discussed several times in scattered locations, but I don’t think there is a stub issue for it. This is similar to https://github.com/openforcefield/openff-toolkit/issues/882 in its subtlety, impact to users, and general tangled-up-ness.

To Reproduce

Using the README snippet as a starting point:

>>> import openmm
>>> from openff.toolkit.topology import Molecule
>>> from openff.toolkit.utils import get_data_file_path
>>> sdf_file_path = get_data_file_path('molecules/ethanol.sdf')
>>> molecule = Molecule.from_file(sdf_file_path)
>>>
>>> # Create an OpenFF Topology object from the molecule
>>> from openff.toolkit.topology import Topology
>>> topology = Topology.from_molecules(molecule)
>>>
>>> # Load the latest OpenFF force field definition
>>> from openff.toolkit.typing.engines.smirnoff import ForceField
>>> forcefield = ForceField('openff-1.2.0.offxml')
>>> forcefield['vdW'].method
'cutoff'
>>> forcefield['Electrostatics'].method
'PME'
>>> topology.box_vectors  # Returns nothing, since it's None
>>> openmm_system = forcefield.create_openmm_system(topology)

We have now parametrized a non-periodic topology with an electrostatics section that’s supposed to use PME, which is not valid for non-periodic topologies. This is handled by converting the entire non-bonded force (recall that out of the box, OpenMM combines vdW and electrostatics interactions into one object) into something that does not have a cutoff:

>>> for force in openmm_system.getForces():
...     if type(force) == openmm.openmm.NonbondedForce:
...         print(force.getNonbondedMethod())
...         print(force.getCutoffDistance())
...
0
0.9 nm
>>> import openmm
>>> openmm.NonbondedForce.NoCutoff
0

This is about the best that can be done with electrostatics (inherent PME errors aside), but it effectively changes the vdW cutoff method from a hard cutoff at 9 Angstroms to no cutoff at all. The energy difference of this is likely small for gas-phase systems, since the few non-bonded interactions are either 1-4 interactions that are scaled down or intramolecular. I don’t have an intuition for how much this would affect fitting, i.e. torsions.

Since this mismatch is a matter of translating details from our state to OpenMM (or any engine), Interchange sees no problem with it and will happily parametrize it, storing the methods of each handler:

>>> from openff.interchange.components.interchange import Interchange
>>> interchange = Interchange.from_smirnoff(force_field=forcefield, topology=topology)
>>> interchange['vdW'].cutoff
<Quantity(9.0, 'angstrom')>
>>> interchange['vdW'].method
'cutoff'
>>> interchange['Electrostatics'].method
'pme'

But when it comes time to convert out to an OpenMM system, it raises an error because of this mismatch:

>>> interchange.to_openmm(combine_nonbonded_forces=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mwt/miniconda3/envs/openff-dev/lib/python3.8/site-packages/openff/interchange/components/interchange.py", line 303, in to_openmm
    return to_openmm_(self, combine_nonbonded_forces=combine_nonbonded_forces)
  File "/Users/mwt/miniconda3/envs/openff-dev/lib/python3.8/site-packages/openff/interchange/interop/openmm.py", line 55, in to_openmm
    _process_nonbonded_forces(
  File "/Users/mwt/miniconda3/envs/openff-dev/lib/python3.8/site-packages/openff/interchange/interop/openmm.py", line 290, in _process_nonbonded_forces
    raise UnsupportedCutoffMethodError
openff.interchange.exceptions.UnsupportedCutoffMethodError

The error is not descriptive enough in v0.1.0 (v0.1.1 says “Combination of non-bonded cutoff methods 9.0 A (vdW) and pme (Electrostatics) not currently supported with combine_nonbonded_forces=True and .box=None”), but this is only hit because I’ve hard-coded against this invalid combination. Other engines should error out for similar reasons, but that’s out of scope here.

I’ve added a flag that will tackle cases like this by splitting out interactions into different force objects. In this case, that means electrostatics and vdW interactions will be treated separately and can have different cutoff methods. This is more consistent with what’s specified in the force field.

>>> openmm_system = interchange.to_openmm(combine_nonbonded_forces=False)
>>> for force in openmm_system.getForces():
...     if type(force) == openmm.NonbondedForce:  # vdW case, NonbondedForce.CutoffNonPeriodic
...         print(force.getNonbondedMethod(), force.getCutoffDistance())
...     elif type(force) == openmm.CustomNonbondedForce:  # Electrostatics case, NonbondedForce.PME
...         print(force.getNonbondedMethod())
...
1 0.9 nm
4

This flag is True by default now, in order to most closely match what the toolkit does right now. Flipping it handles the problem, I believe, but would result in a significant behavior change for users expecting the same behavior from Interchange.from_smirnoff(...).to_openmm(). Behavior changes include

  • Differences in which combinations of inputs run with and without error
  • The structure of the returned object, i.e. how many forces and which data is in which force
  • Likely subtle energy differences resulting from implementation details such as PME vs. non-cutoff electrostatics, cutoff vs. non-cutoff vdW interactions, etc.

A hack to force the matter now is to convert the molecule to a topology, set its periodicity to some arbitrary large value, and then continue. However, this results in unnecessary and expensive PME calculations that can slow down single-molecule calculations, which force field fitting workflows expect should be fast. It also introduces unnecessary error, both from PME approximations and potential impacts of the selection of box size.

Again, I am not sure what the solution here should be. There probably is no clean solution. The best approach may involve not fixing it here at all, which would mean that Interchange will either need to forcibly introduce this bad behavior or accept the differences in energy comparisons and other impacts to users.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
mattwthompsoncommented, Feb 3, 2022

Sorry to not be succinct at all, I think upon revisiting this I can summarize the key tension here as a response to your question

So to me the obvious thing to do is to force users to define a periodic box, unless they explicitly override and turn PME off.

This is what I would like to do, but I suspect it will be unpopular with most of our users given how often the same few lines of code

molecule = Molecule.from_x(...)
topology = molecule.to_topology()
force_field = ForceField(...)
force_field.create_openmm_system(topology)

are used. Having this raise an exception would be following the rules but I suspect cause enough grief to users that we wouldn’t want it to be the case (especially given that the proposition is adding an error case that didn’t exist before). Or at least that’s been my assumption - I assume this would break existing single-molecule/gas-phase workflows?

The only other idea I’d throw out is somehow encoding “use PME if periodic, and no cutoff if not” into the SMIRNOFF spec. I’m not saying it’s a great idea, but I think it’s how most workflows operate, how our force fields are likely to be used, and I believe how they are fitted. If this is something people want to iterate on further, I can move that discussion to the standards tracker.

0reactions
mattwthompsoncommented, May 11, 2022

This has now been resolved after OFF-EP-0005 and its implementation. There are now separate electrostatics methods for periodic and non-periodic potential, ensuring we are no longer forced to guess how charges should be treated in the gas phase when only given the instructions “use PME”

>>> import openmm
>>> from openmm import unit as openmm_unit
>>> from openff.toolkit import *
>>> from openff.toolkit.utils import get_data_file_path
>>> from openff.units import unit
>>>
>>> sdf_file_path = get_data_file_path('molecules/ethanol.sdf')
>>> molecule = Molecule.from_file(sdf_file_path)
>>> topology = Topology.from_molecules(molecule)
>>>
>>> forcefield = ForceField("openff-2.0.0.offxml")
>>> forcefield['vdW'].method
'cutoff'
>>> forcefield['Electrostatics'].periodic_potential
'Ewald3D-ConductingBoundary'
>>> forcefield['Electrostatics'].nonperiodic_potential
'Coulomb'
>>>
>>> topology.box_vectors
>>> openmm_system = forcefield.create_openmm_system(topology)
>>>
>>> for force in openmm_system.getForces():
...     if type(force) == openmm.openmm.NonbondedForce:
...         print(force.getNonbondedMethod(), force.getCutoffDistance())
...
0 0.9 nm
>>> openmm.NonbondedForce.NoCutoff
0
>>>
>>> topology.box_vectors = [4, 4, 4] * unit.nanometer
>>> topology.box_vectors
<Quantity([[4. 0. 0.]
 [0. 4. 0.]
 [0. 0. 4.]], 'nanometer')>
>>> openmm_system = forcefield.create_openmm_system(topology)
>>>
>>> for force in openmm_system.getForces():
...     if type(force) == openmm.openmm.NonbondedForce:
...         print(force.getNonbondedMethod(), force.getCutoffDistance())
...
4 0.9 nm
>>> openmm.NonbondedForce.PME
4
Read more comments on GitHub >

github_iconTop Results From Across the Web

OpenFF Toolkit Documentation - Read the Docs
capabilities require the OpenEye toolkit, but the Open Force Field developers make use of it in parameterizing new open source force fields.
Read more >
Interchange project update - Open Force Field Initiative
The topology attribute stores chemical information in a graph-like structure, without specific information about forces from the force field.
Read more >
Topologies — GROMACS 2022.4 documentation
This chapter describes the setup of the topology file, the top file and the database files: what the parameters stand for and how/where...
Read more >
NAMD User's Guide
5.2.3 Non-bonded force field parameters . ... NAMD has the ability to load GROMACS ASCII topology (.top) and coordinate (.gro) files, which.
Read more >
Scalable molecular dynamics - ResearchGate
These are simple functions describing bonded and non-bonded atomic ... from the databases with parameters for the selected force field.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found