openforcefield / openff-toolkit

The Open Forcefield Toolkit provides implementations of the SMIRNOFF format, parameterization engine, and other tools. Documentation available at http://open-forcefield-toolkit.readthedocs.io
http://openforcefield.org
MIT License
318 stars 92 forks source link

Is it possible to use the same parameters in `openmm.app.Forcefield.createSystem` for openff Forcefield objects #1877

Closed WillGPoole closed 5 months ago

WillGPoole commented 5 months ago

Is your feature request related to a problem? Please describe. When you set up a system in OpenMM from a Forcefield object one can simply parse in varibles assciated with the nonbonded force.

For example, but not limited to:

system = omm_ff.createSystem(pdb.topology,
                         nonbondedMethod=PME,
                         nonbondedCutoff=12.0*angstroms,
                         switchDistance=10.0*angstroms,
                         constraints=HBonds)

Describe the solution you'd like Is it possible to expose these variables when creating a system from an openff Forcefield object using create_openmm_system() . This would make it much easier to drop into existing scripts.

Describe alternatives you've considered You can set these variables before creating the system using ff._parameter_handlers["Electrostatics"] but feels clunky and requires a deeper knowledge of the appropriate keys. Feels quite painful to set rigidWaters on/off, Hydrogen mass, EwaldTolerance etc etc. All of which you can do at the createSystem stage in openmm.

You can also make an openmm system and modify the NB force after the fact, but again is clunky.

P.s. Its entirely possible I'm completely missing something obvious.

TLDR; I am hoping for a way to use openff-toolkit as means of parametrizing molecules and then create the openmm system in the original way.

pbuslaev commented 5 months ago

I think there is a way with openmmforcefields. You can use SMIRNOFFTemplateGenerator for your molecule of interest and then create system in openMM that is using SMIRNOFF force field for a small molecule.

mattwthompson commented 5 months ago

It seems like you're mixing two questions:

  1. Can I use openmm.app.ForceField.createSystem with an OpenFF force field?
  2. How do I modify non-bonded settings in an OpenFF force field when creating an openmm.System?

To the first: no, but openmmforcefields provides some experimental avenues to make things quack in this way.

To the second: OpenMM and OpenFF both provide classes with the name ForceField but they are different models from different projects and accomplish different things. One difference is that OpenFF uses the SMIRNOFF specification, which encodes non-bonded settings in the force field itself. Therefore, it doesn't make sense to create an openmm.System with different non-bonded settings than what is specified in the force field.

ForceField objects and some of their contents can be modified directly with the API, which uses a descriptor pattern:

In [1]: from openff.toolkit import ForceField

In [2]: sage = ForceField("openff-2.2.0.offxml")

In [3]: sage['vdW'].cutoff
Out[3]: 9.0 <Unit('angstrom')>

In [4]: sage['vdW'].cutoff *= 1.23456

In [5]: sage['vdW'].cutoff
Out[5]: 11.111040000000001 <Unit('angstrom')>

though I do not generally recommend this because physical properties are likely to be best when using the settings specified in the force field, which are also likely to be what it was trained to be used with.

mattwthompson commented 5 months ago

@WillGPoole does this help? Have you been able to try any of these ideas?

WillGPoole commented 5 months ago

@WillGPoole does this help? Have you been able to try any of these ideas?

Hey @mattwthompson, sorry for not replying sooner.

I went with the openmmforcefields route - for reference:

# Create system
ff = ForceField('amber14-all.xml', "amber14/tip3p.xml")

# Create the SMIRNOFF template generator 
from openmmforcefields.generators import (
    SMIRNOFFTemplateGenerator,
)
from openff.toolkit import Molecule

lig = Molecule.from_file(args.mols)  # SDF file
smirnoff = SMIRNOFFTemplateGenerator(molecules=[lig], forcefield="openff-2.2.0")

ff.registerTemplateGenerator(smirnoff.generator)

pdb = PDBFile(args.pdb)
modeller = Modeller(pdb.topology, pdb.positions)
modeller.addSolvent(forcefield=ff, padding=1.2*nanometers, ionicStrength=0.15*molar)

# Basic System Configuration
nonbondedMethod = PME
nonbondedCutoff = 1.2*nanometers
switchDistance = 1.0*nanometers
ewaldErrorTolerance = 0.0005  # Default
constraints = HBonds
rigidWater = True  # Default
hydrogenMass = 1.0*amu

# Integration Options
dt = 0.002*picoseconds
temperature = 298*kelvin
friction = 1.0/picosecond
pressure = 1*bar

# Create a system. Define some forcefield settings such as the nonbonded method
system = ff.createSystem(modeller.topology, nonbondedMethod=nonbondedMethod,
                                 nonbondedCutoff=nonbondedCutoff,
                                 constraints=HBonds,
                                 rigidWater=rigidWater,
                                 hydrogenMass=hydrogenMass)

Thanks!