Skip to content

Commit 8351521

Browse files
author
Ryan
committed
Updated documentation, revised pycharmm engine
1 parent 65c35b9 commit 8351521

15 files changed

+697
-121
lines changed

INSTALL

+20-16
Original file line numberDiff line numberDiff line change
@@ -123,19 +123,23 @@ python -c "import alf"
123123

124124
Installing without CUDA
125125

126-
If you don't have access to CUDA GPUs, you can still run ALF, it will just be
127-
slower, and the tools aren't as streamlined for this. When setting up your
128-
environment don't include cuda. When you compile alf/wham, the lack of a cuda
129-
compiler should signal to cmake to compile the CPU code instead. This code has
130-
not been tested for a while, so please contact the developers if you have problems compiling. Next, you can probably skip compiling alf/dca unless you plan to
131-
estimate free energies with the Potts estimator. If you want to estimate free
132-
energies with the Potts estimator, you will need to modify CMakeLists.txt to
133-
omit plm. lm uses likelihood maximization which is better for most chemical
134-
spaces, and plm uses pseudolikelihood maximization which is typically only
135-
required for massive chemical spaces, e.g. more than a million species.
136-
137-
You will need to modify your CHARMM input scripts to not use GPUs (see the
138-
scripts in alf/default_scripts). Removing the BLaDE or DOMDEC options, or
139-
replacing "domdec gpu only" with "domdec gpu off" in the scripts should work.
140-
You may wish to edit the scripts and the CHARMM calls in alf/runflat.py and
141-
alf/runprod.py to use multiple CPUs in parallel to improve efficiency.
126+
If you don't have access to CUDA GPUs, you can still run ALF, it will
127+
just be slower, and the tools aren't as streamlined for this. When
128+
setting up your environment don't include cuda. When you compile
129+
alf/wham, the lack of a cuda compiler should signal to cmake to compile
130+
the CPU code instead. This code has not been tested for a while, so
131+
please contact the developers if you have problems compiling. Next, you
132+
can probably skip compiling alf/dca unless you plan to estimate free
133+
energies with the Potts estimator. If you want to estimate free energies
134+
with the Potts estimator, you will need to modify CMakeLists.txt to omit
135+
plm. lm uses likelihood maximization which is better for most chemical
136+
spaces, and plm uses pseudolikelihood maximization which is typically
137+
only required for massive chemical spaces, e.g. more than a million
138+
species.
139+
140+
You will need to modify your CHARMM input scripts to not use GPUs (see
141+
the scripts in alf/default_scripts). Removing the BLaDE or DOMDEC
142+
options, or replacing "domdec gpu only" with "domdec gpu off" in the
143+
scripts should work. You may wish to edit the scripts and the CHARMM
144+
calls in alf/runflat.py and alf/runprod.py to use multiple CPUs in
145+
parallel to improve efficiency.

README.md

+13-6
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ Molecular dynamics in the alf software is performed by an external
3636
molecular dynamics engine which must be compiled and installed
3737
independently. The currently supported engines are:
3838
* charmm : the CHARMM software package utilizing the DOMDEC GPU ONLY
39-
command
39+
command for GPU acceleration
4040
* bladelib : the CHARMM software package utilizing the BLaDE library
41+
for GPU acceleration. BLaDE is faster that DOMDEC, but has fewer
42+
features
4143
* blade : the standalone BLaDE software package
44+
* pycharmm : the python pyCHARMM package using CHARMM as a library to
45+
call BLaDE
4246
These engines may be passed to alf routines to specify the engine,
4347
because some routines have slight differences based on the engine used.
48+
Use of other molecular dynamics engines in CHARMM is possible, including
49+
engines that do not use GPUs, see instructions at the end of INSTALL.
50+
Use of other engines will require more extensive modification of alf.
4451

4552
Sampling will be optimal when the free energy landscape is flat, so
4653
flattening seeks to identify the biases that give flat free energy
@@ -168,11 +175,11 @@ higher order terms are assumed to be zero. This approximation is
168175
reasonable in many systems and significantly reduces sampling
169176
requirements, making it possible to estimate free energies for tens of
170177
thousands of sequences. To use the Potts model estimator, run
171-
alf.postprocess first, then see the examples in examples/engines with
172-
the _withPotts suffix. SubsetLM.sh uses likelihood maximization, best
173-
for systems with less than a million chemical end states, and
174-
SubsetPLM.sh uses pseudolikelihood maximization, best for systems with
175-
more than a million chemical end states. These use routines defined in
178+
alf.postprocess first, then see the examples in examples/engines/PottsLM
179+
and examples/engines/PottsPLM. PottsLM uses likelihood maximization,
180+
best for systems with less than a million chemical end states, and
181+
PottsPLM uses pseudolikelihood maximization, best for systems with more
182+
than a million chemical end states. These use routines defined in
176183
alf/dca.
177184

178185
Coupling between sites: if you have multiple sites, it is possible these

alf/GetLambdas.py

+35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,41 @@
11
#! /usr/bin/env python
22

33
def GetLambdas(alf_info,istep,ndupl=None,begres=None,endres=None):
4+
"""
5+
Reads alchemical trajectories from binary format
6+
7+
This routine reads binary alchemical flattening trajectories from
8+
run[i]/res/[name]_flat.lmd or binary alchemical production trajectories
9+
from run[i][a]/res/[name]_prod[itt].lmd where [i] is the cycle number,
10+
[a] is the duplicate letter, [name] is the system name, and [itt] is the
11+
production chunk, and copies them into human readable trajectories in
12+
analysis[i]/data/Lambda.[ia].[ir].dat where [ia] is the duplicate index
13+
and [ir] is the replica index. This routine should be called from the
14+
analysis[i] directory.
15+
16+
This routine can be called during flattening or production. Flattening
17+
versus production is detected by the absence or presence, respectively
18+
of the three optional parameters.
19+
20+
Parameters
21+
----------
22+
alf_info : dict
23+
Dictionary of variables alf needs to run
24+
istep : int
25+
The current cycle of alf being analyzed
26+
ndupl : int, optional
27+
The number of independent trials run in production. Leave empty to
28+
signal this is flattening. (defaul is None)
29+
WORKING
30+
Ff : int
31+
The final cycle of alf to include in analysis (inclusive)
32+
skipE : int, optional
33+
In longer production runs the number of lambda samples may require
34+
significant amounts of memory to store and analyze. Only alchemical
35+
frames with index modulus skipE equal to skipE-1 are analyzed.
36+
(default is 1 to analyze all frames)
37+
"""
38+
439
import sys, os
540
import numpy as np
641
# from subprocess import call

alf/GetVolumes.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def GetVolumes(alf_info,istep,ndupl=None,begres=None,endres=None):
2727
name=alf_info['name']
2828

2929
if not 'q' in alf_info:
30-
print("No charge list 'q' in alf_info")
30+
print("No charge list 'q' in alf_info - no charge changing correction will be applied")
3131
return
3232
else:
3333
q=alf_info['q']

alf/SetVars.py

+51-86
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ def SetVarsCharmm(alf_info,Step,minimize=False):
1111
nnodes=alf_info['nnodes']
1212
temp=alf_info['temp']
1313

14-
1514
fp=open('../variables'+str(Step)+'.inp','w')
1615
fp.write("* Variables from step %d of ALF\n*\n\n" % (Step,))
1716

@@ -97,7 +96,7 @@ def SetVarsCharmm(alf_info,Step,minimize=False):
9796
for i in range(0,len(nsubs)):
9897
fp.write("set nsubs"+str(i+1)+" = "+str(nsubs[i])+"\n")
9998
fp.write("set temp = "+str(temp)+"\n")
100-
fp.write("set minimize = "+str(int(minimize==True))+"\n")
99+
fp.write("set minimizeflag = "+str(int(minimize==True))+"\n")
101100
fp.write("\n")
102101
fp.close()
103102

@@ -114,7 +113,6 @@ def SetVarsBlade(alf_info,Step,minimize=False):
114113
nnodes=alf_info['nnodes']
115114
temp=alf_info['temp']
116115

117-
118116
fp=open('../variables'+str(Step)+'.inp','w')
119117

120118
b_prev=np.loadtxt('b_prev.dat')
@@ -209,44 +207,80 @@ def SetVarsPycharmm(alf_info,Step,minimize=False):
209207
import yaml
210208
import copy
211209

210+
nblocks=alf_info['nblocks']
211+
nsubs=alf_info['nsubs']
212+
nreps=alf_info['nreps']
213+
ncentral=alf_info['ncentral']
214+
name=alf_info['name']
215+
nnodes=alf_info['nnodes']
216+
temp=alf_info['temp']
217+
212218
fp=open('../variables'+str(Step)+'.py','w')
213219

214220
fp.write("import yaml\n")
215221
fp.write("import numpy as np\n")
216222

217223
bias={}
218224

225+
sub0=np.cumsum(nsubs)-nsubs
226+
219227
b_prev=np.loadtxt('b_prev.dat')
220228
b=np.loadtxt('b.dat')
221229
b_sum=b_prev+b
222230
b_sum=np.reshape(b_sum,(1,-1))
223231
np.round(b_sum,decimals=2)
224232
np.savetxt('b_sum.dat',b_sum,fmt=' %7.2f')
225233

226-
bias['b']=b_sum.tolist()
234+
for i in range(0,len(nsubs)):
235+
for j in range(0,nsubs[i]):
236+
key=f'lams{i+1}s{j+1}'
237+
bias[key]=b_sum[0,sub0[i]+j].tolist()
227238

228239
c_prev=np.loadtxt('c_prev.dat')
229240
c=np.loadtxt('c.dat')
230241
c_sum=c_prev+c
231242
np.round(c_sum,decimals=2)
232243
np.savetxt('c_sum.dat',c_sum,fmt=' %7.2f')
233244

234-
bias['c']=c_sum.tolist()
245+
for si in range(0,len(nsubs)):
246+
for sj in range(si,len(nsubs)):
247+
for i in range(0,nsubs[si]):
248+
j0=(i+1 if si==sj else 0)
249+
for j in range(j0,nsubs[sj]):
250+
key=f'cs{si+1}s{i+1}s{sj+1}s{j+1}'
251+
bias[key]=-c_sum[sub0[si]+i,sub0[sj]+j].tolist()
235252

236253
x_prev=np.loadtxt('x_prev.dat')
237254
x=np.loadtxt('x.dat')
238255
x_sum=x_prev+x
239256
np.round(x_sum,decimals=2)
240257
np.savetxt('x_sum.dat',x_sum,fmt=' %7.2f')
241258

242-
bias['x']=x_sum.tolist()
259+
for si in range(0,len(nsubs)):
260+
for sj in range(0,len(nsubs)):
261+
for i in range(0,nsubs[si]):
262+
for j in range(0,nsubs[sj]):
263+
if sub0[si]+i!=sub0[sj]+j:
264+
key=f'xs{si+1}s{i+1}s{sj+1}s{j+1}'
265+
bias[key]=-x_sum[sub0[si]+i,sub0[sj]+j].tolist()
243266

244267
s_prev=np.loadtxt('s_prev.dat')
245268
s=np.loadtxt('s.dat')
246269
s_sum=s_prev+s
247270
np.round(s_sum,decimals=2)
248271
np.savetxt('s_sum.dat',s_sum,fmt=' %7.2f')
249272

273+
for si in range(0,len(nsubs)):
274+
for sj in range(0,len(nsubs)):
275+
for i in range(0,nsubs[si]):
276+
for j in range(0,nsubs[sj]):
277+
if sub0[si]+i!=sub0[sj]+j:
278+
key=f'ss{si+1}s{i+1}s{sj+1}s{j+1}'
279+
bias[key]=-s_sum[sub0[si]+i,sub0[sj]+j].tolist()
280+
281+
bias['b']=b_sum.tolist()
282+
bias['c']=c_sum.tolist()
283+
bias['x']=x_sum.tolist()
250284
bias['s']=s_sum.tolist()
251285

252286
fp.write("bias_string=\"\"\"\n")
@@ -258,86 +292,6 @@ def SetVarsPycharmm(alf_info,Step,minimize=False):
258292
fp.write("bias['x']=np.array(bias['x'])\n")
259293
fp.write("bias['s']=np.array(bias['s'])\n")
260294

261-
nsubs=alf_info['nsubs']
262-
263-
ibuff=0
264-
lamss={}
265-
for i in range(0,len(nsubs)):
266-
lamss[i]={}
267-
for j in range(0,nsubs[i]):
268-
lamss[i][j]=b_sum[0,ibuff+j].tolist()
269-
ibuff+=nsubs[i]
270-
271-
ibuff=0
272-
cssss={}
273-
for si in range(0,len(nsubs)):
274-
jbuff=ibuff
275-
cssss[si]={}
276-
for sj in range(si,len(nsubs)):
277-
cssss[si][sj]={}
278-
for i in range(0,nsubs[si]):
279-
ii=i+ibuff
280-
cssss[si][sj][i]={}
281-
j0=0
282-
if si==sj:
283-
j0=i+1
284-
for j in range(j0,nsubs[sj]):
285-
jj=j+jbuff
286-
cssss[si][sj][i][j]=-c_sum[ii,jj].tolist()
287-
jbuff+=nsubs[sj]
288-
ibuff+=nsubs[si]
289-
290-
ibuff=0
291-
xssss={}
292-
for si in range(0,len(nsubs)):
293-
xssss[si]={}
294-
jbuff=0
295-
for sj in range(0,len(nsubs)):
296-
xssss[si][sj]={}
297-
for i in range(0,nsubs[si]):
298-
ii=i+ibuff
299-
xssss[si][sj][i]={}
300-
for j in range(0,nsubs[sj]):
301-
jj=j+jbuff
302-
if ii!=jj:
303-
xssss[si][sj][i][j]=-x_sum[ii,jj].tolist()
304-
jbuff+=nsubs[sj]
305-
ibuff+=nsubs[si]
306-
307-
ibuff=0
308-
sssss={}
309-
for si in range(0,len(nsubs)):
310-
sssss[si]={}
311-
jbuff=0
312-
for sj in range(0,len(nsubs)):
313-
sssss[si][sj]={}
314-
for i in range(0,nsubs[si]):
315-
ii=i+ibuff
316-
sssss[si][sj][i]={}
317-
for j in range(0,nsubs[sj]):
318-
jj=j+jbuff
319-
if ii!=jj:
320-
sssss[si][sj][i][j]=-s_sum[ii,jj].tolist()
321-
jbuff+=nsubs[sj]
322-
ibuff+=nsubs[si]
323-
324-
fp.write("lamss_string=\"\"\"\n")
325-
yaml.dump(lamss,fp)
326-
fp.write("\"\"\"\n")
327-
fp.write("lamss=yaml.load(lamss_string,Loader=yaml.Loader)\n")
328-
fp.write("cssss_string=\"\"\"\n")
329-
yaml.dump(cssss,fp)
330-
fp.write("\"\"\"\n")
331-
fp.write("cssss=yaml.load(cssss_string,Loader=yaml.Loader)\n")
332-
fp.write("xssss_string=\"\"\"\n")
333-
yaml.dump(xssss,fp)
334-
fp.write("\"\"\"\n")
335-
fp.write("xssss=yaml.load(xssss_string,Loader=yaml.Loader)\n")
336-
fp.write("sssss_string=\"\"\"\n")
337-
yaml.dump(sssss,fp)
338-
fp.write("\"\"\"\n")
339-
fp.write("sssss=yaml.load(sssss_string,Loader=yaml.Loader)\n")
340-
341295
alf_info_copy=copy.deepcopy(alf_info)
342296
alf_info_copy['nsubs']=alf_info_copy['nsubs'].tolist()
343297
alf_info_copy['nblocks']=alf_info_copy['nblocks'].tolist()
@@ -352,6 +306,17 @@ def SetVarsPycharmm(alf_info,Step,minimize=False):
352306
fp.write("if 'q' in alf_info:\n")
353307
fp.write(" alf_info['q']=np.array(alf_info['q'])\n")
354308

309+
fp.write("sysname='"+name+"'\n")
310+
fp.write("nnodes="+str(nnodes)+"\n")
311+
fp.write("nreps="+str(nreps)+"\n")
312+
fp.write("ncentral="+str(ncentral)+"\n")
313+
fp.write("nblocks="+str(nblocks)+"\n")
314+
fp.write("nsites="+str(len(nsubs))+"\n")
315+
fp.write("nsubs="+str(nsubs)+"\n")
316+
for i in range(0,len(nsubs)):
317+
fp.write("nsubs"+str(i+1)+"="+str(nsubs[i])+"\n")
318+
fp.write("temp="+str(temp)+"\n")
319+
355320
if minimize==True:
356321
fp.write("minimizeflag=True\n")
357322
else:

alf/default_scripts/blade_flat.inp

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
! BLaDE input file for lambda dynamics
22
!
33

4+
! This script expects esteps (equilibration steps) and nsteps
5+
! (production steps) to be set by the calling process in
6+
! arguments.inp
7+
!
8+
! Other important variables such as temp (the system temperature), and
9+
! sysname (the system name in the prep directory) are set by
10+
! variablesflat.inp. minimizeflag is unused in blade
11+
412
verbose 0
513

614
variables set restartfile null

alf/default_scripts/blade_prod.inp

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
! BLaDE input file for lambda dynamics
22
!
33

4+
! This script expects nsteps (production steps) and itt (chunk of
5+
! production) to be set by the calling process in arguments.inp
6+
!
7+
! Other important variables such as temp (the system temperature) and
8+
! sysname (the system name in the prep directory) are set by
9+
! variablesflat.inp
10+
411
verbose 0
512

613
stream arguments.inp

alf/default_scripts/bladelib_flat.inp

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
* CHARMM with BLaDE input file for lambda dynamics
22
*
33

4+
! This script expects esteps (equilibration steps), nsteps (production
5+
! steps), and seed (random number seed) to be set by the calling process
6+
!
7+
! Other important variables such as minimizeflag (whether or not to
8+
! minimize), temp (the system temperature), and sysname (the system name
9+
! in the prep directory) are set by variablesflat.inp
10+
411
set fnex = 5.5
512

613
stream "variablesflat.inp"
@@ -20,7 +27,7 @@ endif
2027

2128
faster on
2229

23-
if @minimize .eq. 1 then ! only defined in variables1.inp
30+
if @minimizeflag .eq. 1 then ! only defined in variables1.inp
2431
define uninitialized select .not. initialized end
2532
if ?nsel .eq. 0 then
2633
! domdec gpu only dlb off ndir 1 @nnodes 1

0 commit comments

Comments
 (0)