Skip to content

Commit b68f465

Browse files
authored
Merge pull request #27 from ddyy345/master
Add hoomd2 support, with tutorials
2 parents 4d5a557 + cb0840e commit b68f465

File tree

15 files changed

+229
-4473
lines changed

15 files changed

+229
-4473
lines changed

.gitignore

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Default files
2+
*.txt
3+
*.pyc
4+
*.dcd
5+
.DS_Store
6+
*.egg-info
7+
8+
# Byte-compiled / optimized / DLL files
9+
__pycache__/
10+
*.py[cod]
11+
*$py.class
12+
13+
# C extensions
14+
*.so
15+
16+
# Distribution / packaging
17+
.Python
18+
build/
19+
develop-eggs/
20+
dist/
21+
downloads/
22+
eggs/
23+
.eggs/
24+
lib/
25+
lib64/
26+
parts/
27+
sdist/
28+
var/
29+
wheels/
30+
*.egg-info/
31+
.installed.cfg
32+
*.egg
33+
34+
# PyInstaller
35+
# Usually these files are written by a python script from a template
36+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
37+
*.manifest
38+
*.spec
39+
40+
# Installer logs
41+
pip-log.txt
42+
pip-delete-this-directory.txt
43+
44+
# Unit test / coverage reports
45+
htmlcov/
46+
.tox/
47+
.coverage
48+
.coverage.*
49+
.cache
50+
nosetests.xml
51+
coverage.xml
52+
*.cover
53+
.hypothesis/
54+
55+
# Translations
56+
*.mo
57+
*.pot
58+
59+
# Django stuff:
60+
*.log
61+
local_settings.py
62+
63+
# Flask stuff:
64+
instance/
65+
.webassets-cache
66+
67+
# Scrapy stuff:
68+
.scrapy
69+
70+
# Sphinx documentation
71+
docs/_build/
72+
73+
# PyBuilder
74+
target/
75+
76+
# Jupyter Notebook
77+
.ipynb_checkpoints
78+
79+
# pyenv
80+
.python-version
81+
82+
# celery beat schedule file
83+
celerybeat-schedule
84+
85+
# SageMath parsed files
86+
*.sage.py
87+
88+
# Environments
89+
.env
90+
.venv
91+
env/
92+
venv/
93+
ENV/
94+
95+
# Spyder project settings
96+
.spyderproject
97+
.spyproject
98+
99+
# Rope project settings
100+
.ropeproject
101+
102+
# mkdocs documentation
103+
/site
104+
105+
# mypy
106+
.mypy_cache/

msibi/optimize.py

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import logging
44
import os
5-
65
import numpy as np
76

87
from msibi.potentials import tail_correction
@@ -52,6 +51,7 @@ class MSIBI(object):
5251

5352
def __init__(self, rdf_cutoff, n_rdf_points, pot_cutoff=None, r_switch=None,
5453
smooth_rdfs=False, max_frames=1e3):
54+
5555
self.states = []
5656
self.pairs = []
5757
self.n_iterations = 10 # Can be overridden in optimize().
@@ -62,13 +62,14 @@ def __init__(self, rdf_cutoff, n_rdf_points, pot_cutoff=None, r_switch=None,
6262
self.dr = rdf_cutoff / (n_rdf_points - 1)
6363
self.smooth_rdfs = smooth_rdfs
6464
self.rdf_r_range = np.array([0.0, self.rdf_cutoff + self.dr])
65-
self.rdf_n_bins = self.n_rdf_points + 1
65+
self.rdf_n_bins = self.n_rdf_points
6666

67-
# TODO: Description of use for pot vs rdf cutoff.
67+
# Sometimes the pot_cutoff and rdf_cutoff have different ranges,
68+
# e.g. to look at long-range correlations
6869
if not pot_cutoff:
6970
pot_cutoff = rdf_cutoff
7071
self.pot_cutoff = pot_cutoff
71-
# TODO: Describe why potential needs to be messed with to match the RDF.
72+
7273
self.pot_r = np.arange(0.0, self.pot_cutoff + self.dr, self.dr)
7374

7475
if not r_switch:
@@ -77,14 +78,54 @@ def __init__(self, rdf_cutoff, n_rdf_points, pot_cutoff=None, r_switch=None,
7778

7879
def optimize(self, states, pairs, n_iterations=10, engine='hoomd',
7980
start_iteration=0):
81+
"""Optimize the pair potentials
82+
83+
Parameters
84+
----------
85+
states : array_like, len=n_states, dtype=msibi.State
86+
List of states used to optimize pair potentials.
87+
pairs : array_like, len=n_pairs, dtype=msibi.Pair
88+
List of pairs being optimized.
89+
n_iterations : int, optional
90+
Number of iterations.
91+
engine : str, optional
92+
Engine that runs the simulations.
93+
start_iteration : int, optional
94+
Start optimization at start_iteration, useful for restarting.
95+
96+
References
97+
----------
98+
Please cite the following paper:
99+
100+
.. [1] T.C. Moore et al., "Derivation of coarse-grained potentials via
101+
multistate iterative Boltzmann inversion," Journal of Chemical
102+
Physics, vol. 140, pp. 224104, 2014.
103+
80104
"""
81-
"""
105+
106+
if engine == 'hoomd':
107+
try:
108+
import hoomd
109+
HOOMD_VERSION = 2
110+
except ImportError:
111+
try:
112+
import hoomd_script
113+
HOOMD_VERSION = 1
114+
except ImportError:
115+
raise UnsupportedEngine
116+
else: # Cannot find hoomd
117+
HOOMD_VERSION = None
118+
82119
for pair in pairs:
83120
for state, data in pair.states.items():
84121
if len(data['target_rdf']) != self.n_rdf_points:
85122
raise ValueError('Target RDF in {} of pair {} is not the '
86123
'same length as n_rdf_points.'.format(
87-
state.name, pair.name))
124+
state.name, pair.name))
125+
126+
for state in states:
127+
state.HOOMD_VERSION = HOOMD_VERSION
128+
88129
self.states = states
89130
self.pairs = pairs
90131
self.n_iterations = n_iterations
@@ -116,18 +157,23 @@ def _recompute_rdfs(self, pair, iteration):
116157
pair.states[state]['f_fit'][iteration]))
117158

118159
def initialize(self, engine='hoomd', potentials_dir=None):
119-
"""Create initial table potentials and the simulation input scripts.
160+
"""
161+
Create initial table potentials and the simulation input scripts.
120162
121163
Parameters
122164
----------
123165
engine : str, optional, default='hoomd'
166+
Engine used to run simulations
124167
potentials_dir : path, optional, default="'working_dir'/potentials"
168+
Directory to store potential files
125169
126170
"""
171+
127172
if not potentials_dir:
128173
self.potentials_dir = os.path.join(os.getcwd(), 'potentials')
129174
else:
130175
self.potentials_dir = potentials_dir
176+
131177
if not os.path.isdir(self.potentials_dir):
132178
os.mkdir(self.potentials_dir)
133179

@@ -143,9 +189,11 @@ def initialize(self, engine='hoomd', potentials_dir=None):
143189

144190
V = tail_correction(self.pot_r, pair.potential, self.r_switch)
145191
pair.potential = V
192+
146193
# This file is written for viewing of how the potential evolves.
147194
pair.save_table_potential(self.pot_r, self.dr, iteration=0,
148195
engine=engine)
196+
149197
# This file is overwritten at each iteration and actually used for
150198
# performing the query simulations.
151199
pair.save_table_potential(self.pot_r, self.dr, engine=engine)

msibi/state.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,32 @@
33
import mdtraj as md
44

55

6-
HOOMD_HEADER = """
6+
HOOMD1_HEADER = """
77
from hoomd_script import *
88
99
system = init.read_xml(filename="{0}", wrap_coordinates=True)
10+
1011
T_final = {1:.1f}
1112
1213
pot_width = {2:d}
1314
table = pair.table(width=pot_width)
15+
"""
16+
17+
HOOMD2_HEADER = """
18+
import hoomd
19+
import hoomd.md
20+
from hoomd.deprecated.init import read_xml
21+
22+
hoomd.context.initialize("")
23+
system = read_xml(filename="{0}", wrap_coordinates=True)
24+
T_final = {1:.1f}
25+
26+
pot_width = {2:d}
27+
nl = hoomd.md.nlist.cell()
28+
table = hoomd.md.pair.table(width=pot_width, nlist=nl)
1429
1530
"""
31+
1632
HOOMD_TABLE_ENTRY = """
1733
table.set_from_file('{type1}', '{type2}', filename='{potential_file}')
1834
"""
@@ -33,22 +49,23 @@ class State(object):
3349
True if each query trajectory is backed up (default=False)
3450
3551
"""
36-
def __init__(self, k, T, state_dir='', traj_file=None, top_file=None,
52+
53+
def __init__(self, kT, state_dir='', traj_file=None, top_file=None,
3754
name=None, backup_trajectory=False):
38-
self.kT = k * T
55+
self.kT = kT
3956
self.state_dir = state_dir
4057

4158
if not traj_file:
4259
self.traj_path = os.path.join(state_dir, 'query.dcd')
4360
if top_file:
4461
self.top_path = os.path.join(state_dir, top_file)
4562

46-
self.traj = None # Will be set after first iteration.
63+
self.traj = None
4764
if not name:
4865
name = 'state-{0:.3f}'.format(self.kT)
4966
self.name = name
5067

51-
self.backup_trajectory = backup_trajectory # save trajectories?
68+
self.backup_trajectory = backup_trajectory
5269

5370
def reload_query_trajectory(self):
5471
"""Reload the query trajectory. """
@@ -60,10 +77,15 @@ def reload_query_trajectory(self):
6077
def save_runscript(self, table_potentials, table_width, engine='hoomd',
6178
runscript='hoomd_run_template.py'):
6279
"""Save the input script for the MD engine. """
63-
64-
# TODO: Factor out for separate engines.
80+
6581
header = list()
66-
header.append(HOOMD_HEADER.format('start.xml', self.kT, table_width))
82+
83+
if self.HOOMD_VERSION == 1:
84+
HOOMD_HEADER = HOOMD1_HEADER
85+
elif self.HOOMD_VERSION == 2:
86+
HOOMD_HEADER = HOOMD2_HEADER
87+
88+
header.append(HOOMD_HEADER.format('start.hoomdxml', self.kT, table_width))
6789
for type1, type2, potential_file in table_potentials:
6890
header.append(HOOMD_TABLE_ENTRY.format(**locals()))
6991
header = ''.join(header)

msibi/tutorials/lj/opt.py

100644100755
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
import itertools
2-
2+
import os
33

44
import numpy as np
5-
import os
65

76
from msibi import MSIBI, State, Pair, mie
87

98

10-
# Clear out the temp files
119
os.system('rm state*/_* rdfs/pair* potentials/* f_fits.log state*/log.txt')
1210
os.system('rm state*/err.txt')
11+
os.system('rm state*/query.dcd')
1312

1413
# Set up global parameters.
1514
rdf_cutoff = 5.0
1615
opt = MSIBI(rdf_cutoff=rdf_cutoff, n_rdf_points=101, pot_cutoff=3.0,
1716
smooth_rdfs=True)
1817

1918
# Specify states.
20-
state0 = State(k=1, T=0.5, state_dir='./state0', top_file='target.pdb',
19+
state0 = State(kT=0.5, state_dir='./state0', top_file='start.hoomdxml',
2120
name='state0', backup_trajectory=True)
22-
state1 = State(k=1, T=1.5, state_dir='./state1', top_file='target.pdb',
21+
state1 = State(kT=1.5, state_dir='./state1', top_file='start.hoomdxml',
2322
name='state1', backup_trajectory=True)
24-
state2 = State(k=1, T=2.0, state_dir='./state2', top_file='target.pdb',
23+
state2 = State(kT=2.0, state_dir='./state2', top_file='start.hoomdxml',
2524
name='state2', backup_trajectory=True)
2625
states = [state0, state1, state2]
2726

msibi/tutorials/lj/state0/hoomd_run_template.py

100644100755
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
1-
all = group.all()
2-
nvt_int = integrate.bdnvt(group=all, T=T_final)
3-
integrate.mode_standard(dt=0.001)
1+
all = hoomd.group.all()
2+
nvt_int = hoomd.md.integrate.langevin(group=all, kT=T_final, seed=1)
3+
hoomd.md.integrate.mode_standard(dt=0.001)
44

5-
6-
run(1e2)
7-
output_dcd = dump.dcd(filename='query.dcd', period=100, overwrite=True)
8-
run(1e3)
9-
10-
output_xml = dump.xml()
11-
output_xml.set_params(all=True)
12-
output_xml.write(filename='final.xml')
13-
output_pdb = dump.pdb()
14-
output_pdb.write(filename='final.pdb')
5+
hoomd.run(1e2)
6+
output_dcd = hoomd.dump.dcd(filename='query.dcd', period=100, overwrite=True)
7+
hoomd.run(1e4)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<hoomd_xml version="1.4">
33
<configuration time_step="2100000" dimensions="3" natoms="1468" >
4-
<box lx="12" ly="12" lz="12"/>
4+
<box lx="13" ly="13" lz="13"/>
55
<position num="1468">
66
-4.72176265717 5.8477602005 2.7523958683
77
-3.67994141579 -5.17200660706 3.88371992111

0 commit comments

Comments
 (0)