Skip to content

Feature openmm torsion restraints#237

Open
fjclark wants to merge 27 commits intomainfrom
feature-openmm-torsion-restraints
Open

Feature openmm torsion restraints#237
fjclark wants to merge 27 commits intomainfrom
feature-openmm-torsion-restraints

Conversation

@fjclark
Copy link
Copy Markdown
Contributor

@fjclark fjclark commented Mar 3, 2026

This addresses #229.

I've started from #195 but removed everything to do with geomeTRIC, because this contained a bit of refactoring to reduce duplication between the standard and torsion minimisation and setup.

Changes to default behaviour from before:

  • This changes the default torsion minimisation procedure to use very strong restraints on torsions, rather than fixing the positions of all torsion atoms, which was given the thumbs up by Lily in Restrain torsions in OpenMM rather than constraining atom positions #229
  • The maximum number of iterations for torsion and non-torsion minimisation have been set to 10_000 in both cases. Previously, for non-torsion minimisation, this was set to 0. I can revert to this if preferred.
  • I've updated all restraining code to add restraint forces to a different force group, and not to include this when evaluating energies, so that the restraint energies don't contaminate the final results.

Thanks!

@fjclark fjclark requested a review from mattwthompson as a code owner March 3, 2026 16:05
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 3, 2026

Codecov Report

❌ Patch coverage is 89.41799% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.08%. Comparing base (d92a649) to head (844f070).

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pavankum
Copy link
Copy Markdown
Member

@fjclark just a curiosity question, did you check different values of tolerance for the torsion angle agreement, right now it is 5 degrees, I am guessing it is tight enough.

@fjclark
Copy link
Copy Markdown
Contributor Author

fjclark commented Mar 12, 2026

@pavankum thanks for highlighting (thought I had set this tighter, but looks like I only did this for the tests/locally). Yes, I tried locally with much tighter checks but I've now updated so that a) the tolerance is much tighter (0.1 degrees) and b) an error is raised if the deviation is greater (rather than the previous warning).

@pavankum
Copy link
Copy Markdown
Member

Thank you for the clarification @fjclark !

@fjclark
Copy link
Copy Markdown
Contributor Author

fjclark commented Mar 12, 2026

No problem! I've been playing around with this a bit today for the 3mer minimisations, and found that the very high force constant does slow down the minimisation by up to ~ 10x (up to ~ 50 ms). This is noticable for 2D scans where you avoid reparameterising/ recreating OpenMM systems and run 24 * 24 minimisations for the same system, but currently it doesn't matter much here as this is still faster than creating the systems, which is done once for every minimisation.

Copy link
Copy Markdown
Member

@mattwthompson mattwthompson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gone through everything except the most important changes - yammbs/torsion/_minimize.py and tests, which I will come back to later - with only minor suggestions for improvement. The refactors you put together look really slick

Comment on lines +70 to +72
if "Constraints" in force_field.registered_parameter_handlers:
logger.info("Deregistering Constraints handler from SMIRNOFF force field")
force_field.deregister_parameter_handler("Constraints")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document this (I forgot this was the default beavior)

Comment on lines +125 to +126
# TODO: Remove this?
context.computeVirtualSites()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to removing it as long as we're not running dynamics, but I think it's likely to be harmless most of the time

We lost a lot of time with this ~gotcha: openmm/openmm#3736 (comment)

Comment on lines +138 to +147
# Log initial positions
initial_positions = (
context.getState(getPositions=True)
.getPositions(
asNumpy=True,
)
.value_in_unit(openmm.unit.angstrom)
)
logger.debug(f"Initial positions (Angstrom): {initial_positions}")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks handy but I'm liable to forget this exists - could you add some developer/poweruser-facing docs about what is and is not logged, and at what level?

I'm thinking a new docs/logging.md file would be the best place. No need to make it comprehensive or polished - better if you don't spend much time on it, really - I just want this information to not be buried


return smirnoff_force_field.create_openmm_system(molecule.to_topology())
def _smirnoff(molecule: Molecule, force_field_path: str) -> openmm.System:
from openff.toolkit import ForceField
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: probably not worth lazy-loading here

Comment on lines +63 to +65
# The toolkit does a poor job of distinguishing between a string
# argument being a file that does not exist and a file that it should
# try to parse (polymorphic input), so just have to clobber whatever
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

For this project, I think making an effort to parse OFFXML as raw strings is a net negative. Hopefully we continue to use only files

Comment on lines +296 to +298
method : Literal["openmm_torsion_atoms_frozen", "openmm_torsion_restrained"]
Minimization method to use. OpenMM constrains the positions of all
atoms which define the torsion.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please expand this docstring with a little more detail - it's fine in the context of developing this change, but in the future this will be the entry point for users deciding which one to use and there isn't enough detail for new users to understand what each does (or me to remember in a few months when I forget)

@fjclark
Copy link
Copy Markdown
Contributor Author

fjclark commented Mar 31, 2026

Thanks Matt! I'm planning to address these comments in ~ two weeks as I'm focussing on writing up some work at the moment.

Another change I'll make in the minimisation code is avoiding creating an entire MDAnalysis universe, which is unnecessary just to get the torsion angles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants