-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More consistently use existing charge caching #1115
Conversation
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
|
60660a0
to
396d472
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow that's a big speedup!
Am I right in thinking that this has implications for modifying an ElectrostaticsCollection
after the charges have been cached? If so, since we demonstrate modifying collections in the examples, we should probably add some sort of invalidate_cache()
method and document this behavior both in the collection docstring and in the relevant examples. Modifying a collection according to the example and having that modification only sometimes reflected in outputs would be quite frustrating.
Might it also make sense to generalize this caching code to the Collection
class - perhaps have a parameters: dict[TopologyKey | <etc>, Potential
property there? I imagine most of the cost of _get_charges()
is the repeated dictionary lookups, though maybe having to do an attribute lookup would just reproduce that. parameters: dict[TopologyKey | <etc>, tuple[int, ...]
would be a nicer, maybe faster API, but it would mean each collection would have to somehow define an ordered set of parameters. I'm not sure if that would be worthwhile.
Other than the needed documentation and a few extremely minor nits, this looks excellent. The code seems much easier to read and with less indirection. Great work!
@@ -185,7 +181,7 @@ def _convert( | |||
_partial_charges: dict[int | VirtualSiteKey, float] = dict() | |||
|
|||
# Indexed by particle (atom or virtual site) indices | |||
for key, charge in interchange["Electrostatics"]._get_charges().items(): | |||
for key, charge in interchange["Electrostatics"].charges.items(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not leave the electrostatics_collection
assignment in place above and then use it here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't completely follow - the appeal here is to save those lookups from above and I'm not sure what the charge
variable is doing above in that scope
@@ -585,7 +581,7 @@ def _convert_virtual_sites( | |||
residue_index=molecule.atoms[0].residue_index, | |||
residue_name=molecule.atoms[0].residue_name, | |||
charge_group_number=1, | |||
charge=interchange["Electrostatics"]._get_charges()[virtual_site_key], | |||
charge=interchange["Electrostatics"].charges[virtual_site_key], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and here?
Co-authored-by: Josh A. Mitchell <yoshanuikabundi@gmail.com>
Thanks @Yoshanuikabundi! |
Description
A few code paths didn't use the improvements of #1066 / #1069, which caused some horrible performance in some number of corner cases. (Writing out GROMACS files in the protein-ligand example took 10 minutes (!) compared to a few seconds for OpenMM.)
I'm more than a little confused as to how
from_openmm
code paths might have been hit in this example - which just uses SMIRNOFF force fields andInterchange.combine
- but I could be misremembering which changes actually affected things.Checklist