Skip to content
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

Support for OpenMM #4

Closed
wants to merge 171 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
171 commits
Select commit Hold shift + click to select a range
29d6678
initial files for Pymatgen OpenMM IO
orionarcher Nov 10, 2021
6ed67c1
added several convenience functions for setting up OpenMM simulations
orionarcher Nov 10, 2021
052d0bb
rename files
orionarcher Nov 10, 2021
80ade99
added an equilibrate pressure and anneal simulation stages
orionarcher Nov 10, 2021
e715cfa
added code to return a simulation object from simulation generator
orionarcher Nov 10, 2021
c9350a5
improved documentation for the setup classes
orionarcher Nov 10, 2021
3c9a3b6
added testing files
orionarcher Nov 10, 2021
f1140f7
skeleton for testing setup and simulations
orionarcher Nov 10, 2021
0a1c7a7
basic type checking testing
orionarcher Nov 10, 2021
da54ceb
fixed an issue where quotation marks inside strings were causing pack…
orionarcher Nov 10, 2021
f3d33b6
fixing broken tests
orionarcher Nov 10, 2021
e6cf399
small formatting changes to setup
orionarcher Nov 10, 2021
39bdb80
bug fixes and finished basic testing for openmm setup
orionarcher Nov 11, 2021
b64d4b7
bug fixes and testing for the anneal simulation runner
orionarcher Nov 11, 2021
eb7d39a
finished bug fixes on simulation code and finished basic testing
orionarcher Nov 11, 2021
b4b233c
noted bug to be fixed later
orionarcher Nov 11, 2021
87643d5
started adapting the openmm IO to fit the new IO abstraction
orionarcher Nov 13, 2021
3998d67
corrected format of InputFiles and updated the OpenMM input set
orionarcher Nov 13, 2021
9055bc2
added get_simulation and validate methods to the OpenMMSet
orionarcher Nov 13, 2021
dff9cb7
small bug fix to setup
orionarcher Nov 13, 2021
9024ad6
update signature of OpenMMGenerator and begin migrating setup methods
orionarcher Nov 13, 2021
c0c8c68
added setup methods to OpenMMGenerator class
orionarcher Nov 13, 2021
e81713d
move from 'generate' for method names to 'get'
orionarcher Nov 13, 2021
9823bbd
finish basic system parameterization for Sage force field
orionarcher Nov 13, 2021
db46463
add a reminder to insert partial charge handling
orionarcher Nov 13, 2021
077ac74
added comments to document development plan
orionarcher Nov 14, 2021
1bc612a
fixed several typos in code
orionarcher Nov 16, 2021
8214179
add file for testing_inputs
orionarcher Nov 17, 2021
9c77d67
updated documentation and OpenMMGenerator __init__ and get_input_set
orionarcher Nov 17, 2021
ad16554
update InputFile approach to remove dynamic OpenMM objects, factor in…
orionarcher Nov 17, 2021
dd516bb
add testing skeleton and minor syntax changes
orionarcher Nov 17, 2021
9826ee2
update documentation
orionarcher Nov 17, 2021
024b8d2
add testing for OpenMMGenerator
orionarcher Nov 17, 2021
36985c3
add testing for static methods
orionarcher Nov 18, 2021
7eb2be2
add force field file
orionarcher Nov 18, 2021
359b327
adding and debugging testing
orionarcher Nov 18, 2021
7f3d3dd
fixed a bug in the packmol IO
orionarcher Nov 18, 2021
23f05e2
completed first set of testing for OpenMMGenerator
orionarcher Nov 18, 2021
dcd9c36
added abstract XmlInput class to simplify InputFile definitions
orionarcher Nov 19, 2021
ffcb529
rewrote input set to better fit new IO abstraction
orionarcher Nov 19, 2021
3b032aa
change naming conventions for InputFiles and attempt to finish get_si…
orionarcher Nov 19, 2021
4ac4fa4
added several test files and datafiles.py to organize test files
orionarcher Nov 19, 2021
ee14cd9
add corrected topology.pdg
orionarcher Nov 20, 2021
98626c2
fixed pdb file bug and removed need for coordinates by defaulting to …
orionarcher Nov 20, 2021
e067bd0
finish bug fix for TopologyInput
orionarcher Nov 20, 2021
21a5999
clean up
orionarcher Nov 20, 2021
3f5bd5c
more clean up
orionarcher Nov 20, 2021
ee8eb82
fix issue with input file syntax using XmlInput
orionarcher Nov 20, 2021
399f678
complete testing for InputFiles
orionarcher Nov 20, 2021
16344db
added InputSet testing and completed bug fixes. Testing is now complete
orionarcher Nov 20, 2021
f07f818
another packmol bugfix
orionarcher Nov 20, 2021
16caac5
improved documentation
orionarcher Nov 20, 2021
39eb02c
finished first pass documentation
orionarcher Nov 20, 2021
8be9fb8
remove unused setup.py
orionarcher Nov 20, 2021
5e85188
delete testing for setup.py
orionarcher Nov 20, 2021
64e1d3d
added files for testing partial charge assignment
orionarcher Nov 20, 2021
684af65
added skeleton for partial charge assignment and testing
orionarcher Nov 20, 2021
36f0c83
rename a directory and propagate changes
orionarcher Nov 20, 2021
0515670
restructure datafiles.py and test_inputs.py to remove all hard paths
orionarcher Nov 20, 2021
f7f37b3
finish restructuring datafiles and begin testing automated partial ch…
orionarcher Nov 20, 2021
f25e374
added several files to test chirality matching with partial charge as…
orionarcher Nov 20, 2021
90f1fba
deleted several useless files that I accidentally committed
orionarcher Nov 20, 2021
6062609
a initial implementation of partial charge matching
orionarcher Nov 20, 2021
31bcca6
rewrote get_atom_map to progressively relax stererochemistry and bond…
orionarcher Nov 21, 2021
41b06d1
added testing for infer_openff_mol and get_atom_map
orionarcher Nov 21, 2021
f34f210
add testing for _assign_charges_to_openff_mol
orionarcher Nov 21, 2021
b94cebc
finished testing for partial charge inferrer
orionarcher Nov 21, 2021
5e991ae
add add_partial_charges_to_forcefield, combining other partial charge…
orionarcher Nov 21, 2021
994634e
remove equal length assertion in get_atom_map and rename get_box
orionarcher Nov 21, 2021
e5597f3
finish all testing
orionarcher Nov 21, 2021
82af566
a couple small bug fixes
orionarcher Nov 21, 2021
a3939ea
a monstrous test that is trying to track down an enigmatic bug, will …
orionarcher Nov 21, 2021
5ac6432
reorganize imports
orionarcher Nov 21, 2021
99fe1b5
clean up imports and document imports
orionarcher Nov 21, 2021
dbb8392
finished tracking down a truly heinous bug, atom ordering was reverse…
orionarcher Nov 22, 2021
6038955
removed unused files and correct error in FEC.npy test file
orionarcher Nov 22, 2021
c070056
small syntax and formatting changes
orionarcher Nov 22, 2021
bc6d0ad
Merge branch 'htmd' into htmd_openmm
rkingsbury Nov 23, 2021
0b06b54
update testing to test from_file reconstruction
orionarcher Nov 23, 2021
cab1f6c
removed force field .xml, not currently needed
orionarcher Nov 23, 2021
74c08cf
Merge remote-tracking branch 'rkingsbury/htmd' into htmd_openmm
orionarcher Nov 23, 2021
23e33bf
Merge branch 'htmd_openmm' of github.com:orioncohen/pymatgen into htm…
orionarcher Nov 23, 2021
664fca8
changed partial charge logic to support partial charge scaling
orionarcher Nov 23, 2021
461bd63
added testing for partial charge scaling
orionarcher Nov 23, 2021
98db5b7
format all files with black and run through precommit linter
orionarcher Nov 24, 2021
aaf9e82
modified inputs to satisfy mypy static type checking
orionarcher Nov 24, 2021
587f38d
ignore type checking for pkg_resources
orionarcher Nov 24, 2021
26e1005
add docstrings to all InputFile objects
orionarcher Nov 24, 2021
9cf41d6
add docstring to init
orionarcher Nov 24, 2021
08ec3a2
update requirements-optional file with new dependencies
orionarcher Nov 24, 2021
3c876fa
updated github workflow to include openmm dependencies
orionarcher Nov 24, 2021
14f9e13
update requirements-optional again
orionarcher Nov 24, 2021
822f193
editing requirements-optional
orionarcher Nov 24, 2021
6ff2d70
more changes to test.yml
orionarcher Nov 24, 2021
d45fc77
fixed error in test.yml
orionarcher Nov 24, 2021
81f64d1
removed openff import from requirements-optional
orionarcher Nov 24, 2021
78f4411
more testing workflow changes
orionarcher Nov 24, 2021
31afad0
please pass
orionarcher Nov 24, 2021
c43804f
only conda dependencies in test.yml
orionarcher Nov 24, 2021
3fc22ae
add stricter versioning of openmm
orionarcher Nov 24, 2021
ccbbec0
change openmm version to 7.6.2
orionarcher Nov 24, 2021
d6980a9
I think I already tried this but ¯\_(ツ)_/¯
orionarcher Nov 24, 2021
42dbb1a
split InputFiles, InputSet, and InputGenerator across different files
orionarcher Nov 25, 2021
9cd2176
refactor testing into multiple files
orionarcher Nov 25, 2021
162b111
update simulation imports and testing
orionarcher Nov 25, 2021
d272547
modify packmol to fit base branch and satisfy linter
orionarcher Nov 25, 2021
49f3a2a
black simulations and add kwargs to equilibrate pressure
orionarcher Nov 25, 2021
e3adad0
added test for write_inputs
orionarcher Nov 25, 2021
a2aeb3a
fix simulations functions and add real testing
orionarcher Nov 25, 2021
02496b8
syntax change and removed randomness from testing by setting fixed pa…
orionarcher Nov 25, 2021
3c6ecbf
change header in imports
orionarcher Nov 25, 2021
1f18517
small docstring changes
orionarcher Nov 30, 2021
7a97bf0
deleted __init__.py in tests
orionarcher Nov 30, 2021
479735b
change path naming conventions to pass remote testing
orionarcher Nov 30, 2021
42948e1
add platform and platformProperties arguments to get_simulation
orionarcher Dec 9, 2021
86389a2
add new testing files for Li
orionarcher Dec 12, 2021
a67e001
bug fixes and code restructuring for generators.py
orionarcher Dec 12, 2021
0f4afc5
added test for partial charge scaling and setting on Li/PF6 system
orionarcher Dec 12, 2021
0760e38
small typo and changing args to kwargs to attempt to fix parallelizat…
orionarcher Dec 14, 2021
e6e30d8
another addition intended to help fix a pernicious multiprocessing error
orionarcher Dec 14, 2021
9946e50
fix typing error in get_simulation docs
orionarcher Dec 14, 2021
f7d7ac5
added statements for debugging and changed platform syntax
orionarcher Dec 14, 2021
50d556a
revert previous commit
orionarcher Dec 15, 2021
685ed7d
added del statement to delete context
orionarcher Dec 16, 2021
8e37b15
attempt to force garbage collection to remove Context reference
orionarcher Dec 16, 2021
6b30d6b
revert del and garbage collection changes, they did not solve the issue
orionarcher Dec 16, 2021
ae0d670
moved several static methods from OpenMMSolutionGenerator to utils.py
orionarcher Dec 16, 2021
8a32263
removed several static methods from OpenMMSolutionGen
orionarcher Dec 16, 2021
608bb4d
Merge remote-tracking branch 'orioncohen/htmd_openmm' into ae_htmd
Dec 16, 2021
003da4c
added utility functions for molarity, volume ratio, and mass ratio ca…
orionarcher Dec 16, 2021
358a794
fixed typing error
orionarcher Dec 16, 2021
3969040
Merge remote-tracking branch 'orioncohen/htmd_openmm' into ae_htmd
Jan 10, 2022
19c20e5
changed generators to allow smiles with character
orionarcher Jan 19, 2022
de1c2cf
Hasty edits to make things work
Jan 19, 2022
a068073
Merge remote-tracking branch 'orioncohen/htmd_openmm' into ae_htmd
Jan 19, 2022
480ae7c
added partial_charge_method to OpenMMSolutionGen
orionarcher Jan 20, 2022
c6f1cc2
refactor code to assign partial charges with molecules, rather than a…
orionarcher Jan 20, 2022
46fae4f
refactor testing for new partial charge method
orionarcher Jan 20, 2022
75c14c1
clean up function signatures
orionarcher Jan 20, 2022
ed2e232
add option to specify geometries of initial molecule positions, forma…
orionarcher Jan 21, 2022
10c8722
add testing for coordinate specification logic
orionarcher Jan 21, 2022
61b0ad9
Mixed ForceField Systems
Jan 21, 2022
8a1b847
Merge remote-tracking branch 'origin/ae_htmd' into ae_htmd
Jan 21, 2022
3ade32e
proofreading
Jan 21, 2022
9fadc1d
Fixing tests
Jan 22, 2022
96e6964
TODO reminder for needed test
orionarcher Jan 23, 2022
eb7ac35
fixed bug: test_get_box now fails with incorrect output
orionarcher Jan 23, 2022
9dfddf7
small formatting change
orionarcher Jan 23, 2022
8111430
Alex changes
orionarcher Jan 24, 2022
8d0620e
added new files for testing and deleted unused files
orionarcher Jan 24, 2022
a010ce8
modified datafiles to include new test files
orionarcher Jan 24, 2022
d2c5e59
added support for more file types to generators initial_geometries pr…
orionarcher Jan 24, 2022
edfaeab
added more robust testing for initial_geometries feature
orionarcher Jan 24, 2022
cbfc399
add a TODO reminder
orionarcher Jan 26, 2022
5569e82
Merge remote-tracking branch 'rkingsbury/htmd' into htmd_openmm
orionarcher Jan 26, 2022
3285239
move get_atom_map and infer_openff_mol to utils
orionarcher Jan 27, 2022
7113d8e
move order_molecule_like_smiles from generators to utils
orionarcher Jan 27, 2022
6c82b79
move get_coordinates from generators to utils
orionarcher Jan 27, 2022
298e7f8
move get_topology from generators to utils
orionarcher Jan 27, 2022
038f56b
move assign_charges_to_mols and add_mol_charges_to_forcefield from ge…
orionarcher Jan 27, 2022
32fb2c6
move parameterize_system from generators to utils
orionarcher Jan 27, 2022
29b4927
Support for multiple forcefields
Jan 28, 2022
ee3932e
pre-commit run
Jan 28, 2022
a6c9226
Addressing Comments
Feb 2, 2022
b003ff1
Separating functions
Feb 2, 2022
e4dd9fc
Adding coveralls
Feb 2, 2022
be6b48e
Trying to get linting
Feb 2, 2022
08d53ce
Unit tests + tip4p removal
Mar 14, 2022
2754454
pytest fixing
Mar 15, 2022
42d0475
black formatting
Mar 15, 2022
01efafd
Merge pull request #2 from arepstein/ae_htmd
orionarcher Apr 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .coveralls.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
repo_token: KpgnfDK8BDSSTSS4lSrCvHwHnchLgIQ0D
name: Coveralls GitHub Action
uses: coverallsapp/github-action@1.1.3
7 changes: 6 additions & 1 deletion .github/workflows/test-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:

test:
# prevent this action from running on forks
if: github.repository == 'materialsproject/pymatgen'
# if: github.repository == 'materialsproject/pymatgen'
strategy:
max-parallel: 20
matrix:
Expand Down Expand Up @@ -51,6 +51,11 @@ jobs:
sudo apt-get install csh gfortran
conda install -c conda-forge openbabel
conda install -c conda-forge packmol
- name: Install OpenMM dependencies
shell: bash -l {0}
run: |
conda install -c conda-forge openff-toolkit
conda install -c conda-forge openmm
- name: Install dependencies
shell: bash -l {0}
run: |
Expand Down
2 changes: 1 addition & 1 deletion pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ ignored-classes=optparse.Values,thread._local,_thread._local
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
ignored-modules=openmm

# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
Expand Down
3 changes: 3 additions & 0 deletions pymatgen/io/openmm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
A set of tools for setting up OpenMM simulations of battery systems.
"""
175 changes: 175 additions & 0 deletions pymatgen/io/openmm/generators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
"""
Concrete implementations of InputGenerators for the OpenMM IO.
"""

# base python
from pathlib import Path
from typing import Union, Optional, Dict, List, Tuple

# scipy
import numpy as np

# openff

# openmm
from openmm.unit import kelvin, picoseconds
from openmm import (
Context,
LangevinMiddleIntegrator,
)

# pymatgen
import pymatgen.core
from pymatgen.io.core import InputSet, InputGenerator
from pymatgen.io.openmm.inputs import (
TopologyInput,
SystemInput,
IntegratorInput,
StateInput,
)
from pymatgen.io.openmm.sets import OpenMMSet
from pymatgen.io.openmm.utils import (
get_box,
get_coordinates,
get_openmm_topology,
parameterize_system,
)

__author__ = "Orion Cohen, Ryan Kingsbury"
__version__ = "1.0"
__maintainer__ = "Orion Cohen"
__email__ = "orion@lbl.gov"
__date__ = "Nov 2021"


# noinspection PyMethodOverriding
class OpenMMSolutionGen(InputGenerator):
"""
Generator for an OpenMM InputSet.

This class is designed for generating simulations of mixed molecular systems. Starting with
only SMILEs and counts, this class can generate a valid InputSet for a wide variety of
molecular systems. Currently only the Sage force field is supported.

This class is only compatible with the Langevin Middle Integrator. To use a different
integrator, you can first generate the system with OpenMMSolutionGen and then add
a different integrator to the OpenMMInputSet.
"""

def __init__(
self,
force_field: Union[str, Dict[str, str]] = "Sage",
temperature: float = 298,
step_size: float = 0.001,
friction_coefficient: int = 1,
partial_charge_method: str = "am1bcc",
partial_charge_scaling: Optional[Dict[str, float]] = None,
partial_charges: Optional[List[Tuple[Union[pymatgen.core.Molecule, str, Path], np.ndarray]]] = None,
initial_geometries: Dict[str, Union[pymatgen.core.Molecule, str, Path]] = None,
packmol_random_seed: int = -1,
topology_file: Union[str, Path] = "topology.pdb",
system_file: Union[str, Path] = "system.xml",
integrator_file: Union[str, Path] = "integrator.xml",
state_file: Union[str, Path] = "state.xml",
):
"""
Instantiates an OpenMMSolutionGen.

Args:
force_field: force field for parameterization, currently supported Force Fields: 'Sage'.
temperature: the temperature to be added to the integrator (Kelvin).
step_size: the step size of the simulation (picoseconds).
friction_coefficient: the friction coefficient which couples the system to
the heat bath (inverse picoseconds).
partial_charge_method: Any partial charge method supported by OpenFF Molecule.assign_partial_charges.
"am1bcc" is recommended for small molecules, "mmff94" is recommended for large molecules.
partial_charge_scaling: A dictionary of partial charge scaling for particular species. Keys
are SMILEs and values are the scaling factor.
partial_charges: A list of tuples, where the first element of each tuple is a molecular
geometry and the second element is an array of charges. The geometry can be a
pymatgen.Molecule or a path to an xyz file. The geometry and charges must have the
same atom ordering.
topology_file: Location to save the Topology PDB.
system_file: Location to save the System xml.
integrator_file: Location to save the Integrator xml.
state_file: Location to save the State xml.
"""
self.force_field = force_field
self.temperature = temperature
self.step_size = step_size
self.friction_coefficient = friction_coefficient
self.partial_charge_method = partial_charge_method
self.partial_charge_scaling = partial_charge_scaling if partial_charge_scaling else {}
self.partial_charges = partial_charges if partial_charges else []
self.initial_geometries = initial_geometries if initial_geometries else {}
self.packmol_random_seed = packmol_random_seed
self.topology_file = topology_file
self.system_file = system_file
self.integrator_file = integrator_file
self.state_file = state_file

def get_input_set( # type: ignore
self,
smiles: Dict[str, int],
density: Optional[float] = None,
box: Optional[List[float]] = None,
) -> InputSet:
"""
This executes all of the logic to create the input set. It generates coordinates, instantiates
the OpenMM objects, serializes the OpenMM objects, and then returns an InputSet containing
all information needed to generate a simulaiton.

Please note that if the molecules are chiral, then the SMILEs must specify a
particular stereochemistry.

Args:
smiles: keys are smiles and values are number of that molecule to pack
density: the density of the system. density OR box must be given as an argument.
box: list of [xlo, ylo, zlo, xhi, yhi, zhi]. density OR box must be given as an argument.

Returns:
an OpenMM.InputSet
"""
assert (density is None) ^ (box is None), "Density OR box must be included, but not both."
smiles = {smile: count for smile, count in smiles.items() if count > 0}
# create dynamic openmm objects with internal methods
topology = get_openmm_topology(smiles)
if box is None:
box = get_box(smiles, density) # type: ignore
coordinates = get_coordinates(smiles, box, self.packmol_random_seed, self.initial_geometries)
smile_strings = list(smiles.keys())
system = parameterize_system(
topology,
smile_strings,
box,
self.force_field,
self.partial_charge_method,
self.partial_charge_scaling,
self.partial_charges,
)
integrator = LangevinMiddleIntegrator(
self.temperature * kelvin,
self.friction_coefficient / picoseconds,
self.step_size * picoseconds,
)
context = Context(system, integrator)
context.setPositions(coordinates)
state = context.getState(getPositions=True)
Comment on lines +155 to +157
Copy link
Author

Choose a reason for hiding this comment

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

Creating this Context caused me a truly nightmarish bug when trying to run on the Perlmutter GPUs. Somehow, instantiating a Context creates some state in the program that persists even after get_input_set has run. Later on, when I call input_set.get_simulation, the Simulation internally try's to create a Context that conflicts with the previous Context, causing an error and crashing the program. This does not occur locally when I use OpenCL or CPU as the platform, and it does not occur when I run remotely using CPU. Absolute nightmare.

Unfortunately, we can't instantiate a State without creating a Context, so these lines are integral to the current IO implementation.

There is no issue if we create the input files in one python file and then load them in another, it is only an issue if we create and load them in the same file. So thankfully, this shouldn't be too much of an issue for HTMD.

I'm tempted to just ignore this issue and make sure the error is well documented. It's enough of an edge case that I don't think it warrants restructuring the IO. Curious to hear what you think though.

This was awful to debug, so I'm thankful to have gotten to the bottom of this error.

# instantiate input files and feed to input_set
topology_input = TopologyInput(topology)
system_input = SystemInput(system)
integrator_input = IntegratorInput(integrator)
state_input = StateInput(state)
input_set = OpenMMSet(
inputs={
self.topology_file: topology_input,
self.system_file: system_input,
self.integrator_file: integrator_input,
self.state_file: state_input,
},
topology_file=self.topology_file,
system_file=self.system_file,
integrator_file=self.integrator_file,
state_file=self.state_file,
)
return input_set
Loading